//------------------------------------------------------------------------------
// 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 "Player/Anzu/AnzuState.h"
#include "Player/Anzu/Anzu.h"

#include "Stage/System/Stage.h"
#include "Player/Anzu/AnzuBigDamageState.h"
#include "Player/Anzu/AnzuSmallDamageState.h"

#include "Enemy/System/EnemySystem.h"
#include "Enemy/System/Enemy.h"

//------------------------------------------------------------------------------
// 生成、破棄
//------------------------------------------------------------------------------
// コンストラクタ
AnzuState::AnzuState(Anzu* anzu) : PlayerState(anzu), anzu_(anzu){
}
//------------------------------------------------------------------------------
// デストラクタ
AnzuState::~AnzuState(){
}
//------------------------------------------------------------------------------
// 傘の取得
SceneNode* AnzuState::getUmbrella(){
	return anzu_->getUmbrella();
}
//------------------------------------------------------------------------------
// ダメージを受けたか
bool AnzuState::isDamaged(){
	// 無敵カウンタ処理
	int matchlessCounter = getMatchlessCounter();
	if(matchlessCounter > 0){
		matchlessCounter--;
		setMatchlessCounter(matchlessCounter);
		clearDamage();
		return false;
	}
	// ダメージ
	int damageValue = getDamageValue();
	// 無敵カウンタの設定はダメージステートにて行う
	if(damageValue == 0){ return false; }

	// ダメージ処理
	if(isAerial()){ damageValue *= 2; }
	setHealth(getHealth() - damageValue);

	// 死亡か空中か大きいダメージなら吹っ飛び
	if(isDeath() || isAerial() || (damageValue > 50)){
		getPlayer()->setState(new AnzuBigDamageState(getAnzu()));
	}else{
		getPlayer()->setState(new AnzuSmallDamageState(getAnzu()));
	}
	return true;
}
//------------------------------------------------------------------------------
// 速度と位置の計算
void AnzuState::calcVelocityAndPosition(Vector3 addVelocity){
	float velocityXZAttenuation = 0.6f;
	float velocityYAttenuation = 0.95f;
	Vector3 forceField(0.f, -0.1f, 0.f);
	Vector3 position = getPosition();
	Vector3 velocity = getVelocity();

	velocity += forceField;
	velocity += addVelocity;
	velocity.x *= velocityXZAttenuation;
	velocity.y *= velocityYAttenuation;
	velocity.z *= velocityXZAttenuation;
	position += velocity;
	// 計算結果の設定
	setPosition(position);
	setVelocity(velocity);
}
//------------------------------------------------------------------------------
// 地形コリジョン
void AnzuState::landCollide(){
	// コリジョンループ、コンテンツで対応すれば最大3
	Vector3 position = getPosition();
	Vector3 velocity = getVelocity();
	CollisionNode* collisionNode = getCollisionNode();
	collisionNode->setRotationXYZ(getRotation());

	for(int i = 0; i < 3; i++){
		// コリジョンの位置設定
		collisionNode->setTranslation(position);
		collisionNode->traverse();

		// 地形とのコリジョン
		IntersectionResult result;
		getCollisionScene()->intersection(&result, getLandCollision(), 1);

		if(!result.isIntersected()){ break; }

		// 反射ベクトル補正
		Vector3 refrection = result.getMaxRefrection();
		if(Math::abs(refrection.x) < 0.09f){ refrection.x = 0.f; }
		if(Math::abs(refrection.z) < 0.09f){ refrection.z = 0.f; }
		if(refrection.isZero()){ break; }

		// 位置補正
		position += refrection;
		// 速度補正
		if(refrection.y > 0.f){
			setAerial(false);
			velocity.y = 0.f;
		}
	}
	// コリジョン位置設定
	collisionNode->setTranslation(position);
	collisionNode->traverse();

	// 計算結果の設定
	setPosition(position);
	setVelocity(velocity);
}
//------------------------------------------------------------------------------
// 攻撃コリジョン
void AnzuState::attackCollide(
	Bone* bone, const Vector3& offset, float size, int damage){
	// コリジョンの位置合わせ
	getModel()->buildBoneMatrix();
	StaticSphereCollision* collision = getAttackCollision();
	collision->setSphere(bone->getModelMatrix() * offset, size);

	// 攻撃
	collision->traverse();
	Sphere attack = collision->getWorldSphere();
	int count = getEnemySystem()->getCount();
	for(int i = 0; i < count; i++){
		Enemy* enemy = getEnemySystem()->get(i);
		Sphere target = enemy->getDamageCollision()->getWorldSphere();
		Intersection intersection;
		if(attack.intersect(&intersection, target)){
			enemy->damage(enemy->getPosition() - getPosition(), damage);
		}
	}
}
//------------------------------------------------------------------------------
// 描画セットアップ
void AnzuState::drawSetup(float animationTime){
	// 描画位置設定
	SceneNode* sceneNode = getSceneNode();
	sceneNode->setTranslation(getPosition());
	sceneNode->setRotationXYZ(getRotation());
	sceneNode->traverse();

	// アニメーション
	getAnimation()->animate(animationTime, Animation::maskPostCulling);

	// 傘の位置合わせ
	getModel()->buildBoneMatrix();
	const Matrix34& matrix = getRightHandBone()->getModelMatrix();
	getUmbrella()->setTranslation(matrix.getTranslation());
	getUmbrella()->setRotationQuaternion(matrix.getRotationQuaternion());
}
//------------------------------------------------------------------------------
