//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * 敵実装
 * @author Junpee
 */

#include "Core/Utility/stdafx.h"
#include "Enemy/System/Enemy.h"
#include "Enemy/System/EnemyState.h"

//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
Enemy::Enemy(int health, u_int randomSeed) : sceneNode_(NULL), model_(NULL),
	attackBone_(NULL), bodyBone_(NULL), animation_(NULL),
	collisionNode_(NULL), landCollision_(NULL), damageCollision_(NULL),
	attackCollision_(NULL),
	state_(NULL), nextState_(NULL),
	position_(Vector3::zero), rotation_(Vector3::zero),
	direction_(Vector3::unitZ),
	velocity_(Vector3::zero), isAerial_(true),
	life_(1), health_(health),
	damageDirection_(Vector3::zero), damageValue_(0), matchlessCounter_(0),
	random_(randomSeed){
}
//------------------------------------------------------------------------------
// デストラクタ
Enemy::~Enemy(){
	if(nextState_ != NULL){ SafeDelete(nextState_); }
	if(state_ != NULL){
		state_->finalize();
		delete state_;
	}
	// コリジョンノードの破棄
	CollisionNode::recursiveDestroy(getCollisionNode());
	// シーンノードの破棄
	SceneNode::recursiveDestroy(getSceneNode());
}
//------------------------------------------------------------------------------
// 初期化
//------------------------------------------------------------------------------
// モデルの初期化
SceneNode* Enemy::initializeModel(const String& name, const String& attackBone,
	const String& bodyBone, u_int copyMask){
	// モデルデータの複製
	SceneNode* nodeSource = getScene()->getSceneNodeManager()->search(name);
	Assert(nodeSource != NULL);
	sceneNode_ = nodeSource->copy(copyMask);
	getScene()->getRootNode()->addSceneNode(sceneNode_);
	// モデル初期化
	model_ = sceneNode_->getSceneLeaf(0)->castModel()->castCharacterModel();
	Assert(model_ != NULL);
	// 攻撃ボーン取得
	attackBone_ = model_->searchBone(attackBone);
	Assert(attackBone_ != NULL);
	// 体ボーン取得
	bodyBone_ = model_->searchBone(bodyBone);
	Assert(bodyBone_ != NULL);
	return sceneNode_;
}
//------------------------------------------------------------------------------
// アニメーションの初期化
Animation* Enemy::initializeAnimation(const String& name){
	// アニメーションのコピー
	Animation* animationSource = getAnimationManager()->search(name);
	Assert(animationSource != NULL);
	animation_ = animationSource->copy();

	// バインド
	AnimationSet* animationSet = animation_->castAnimationSet();
	Assert(animationSet != NULL);
	Assert(animationSet->getAnimationCount() == 1);
	CharacterModelAnimation* modelAnimation =
		animationSet->getAnimation(0)->castCharacterModelAnimation();
	Assert(modelAnimation != NULL);
	modelAnimation->bind(model_);
	return animation_;
}
//------------------------------------------------------------------------------
// コリジョンの初期化
CollisionNode* Enemy::initializeCollision(const String& name,
	float landSize, float damageSize){
	String fixedName = getCollisionScene()->renameNode(name);
	// ノードの初期化
	collisionNode_ = getCollisionScene()->createCollisionNode(fixedName);
	getCollisionScene()->getRootNode()->addChild(collisionNode_);
	// 地形コリジョンの初期化
	landCollision_ =
		getCollisionScene()->createStaticSphereCollision(fixedName + "Land");
	landCollision_->setSphere(Vector3(0.f, landSize, 0.f), landSize);
	landCollision_->setCollisionMask(1);
	landCollision_->setUserData(this);
	collisionNode_->addChild(landCollision_);
	// ダメージコリジョンの初期化
	damageCollision_ =
		getCollisionScene()->createStaticSphereCollision(fixedName + "Damage");
	damageCollision_->setSphere(Vector3(0.f, landSize, 0.f), damageSize);
	damageCollision_->setCollisionMask(4);
	damageCollision_->setUserData(this);
	collisionNode_->addChild(damageCollision_);
	// 攻撃コリジョンの初期化
	attackCollision_ =
		getCollisionScene()->createStaticSphereCollision(fixedName + "Attack");
	attackCollision_->setCollisionMask(0);
	attackCollision_->setEnabled(false);
	attackCollision_->setUserData(this);
	collisionNode_->addChild(attackCollision_);
	return collisionNode_;
}
//------------------------------------------------------------------------------
// 状態の設定
void Enemy::setState(EnemyState* state){
	if(nextState_ != NULL){ SafeDelete(nextState_); }
	nextState_ = state;
}
//------------------------------------------------------------------------------
// 実行
void Enemy::run(){
	if(nextState_ != NULL){
		if(state_ != NULL){
			state_->finalize();
			delete state_;
		}
		state_ = nextState_;
		nextState_ = NULL;
		state_->initialize();
	}
	if(state_ != NULL){ state_->runImplement(); }
}
//------------------------------------------------------------------------------
// 向きの設定
void Enemy::setDirection(const Vector3& direction){
	if(direction.isZero()){ return; }
	direction_ = direction;
	direction_.normalize();
	rotation_ = Math3D::lookAtZ(direction_);
}
//------------------------------------------------------------------------------
