/*********************************************************************//**
*	\brief BaseMonster
*	Abstraktni trida definujici zaklad vsech nepratel.
*	
*	\author Michal Jirous
*	\date 23.04.2009
*	\file ent_basemonster.h
**********************************************************************/

#ifndef __BASE_MONSTER_H__
#define __BASE_MONSTER_H__

#include "ent_creatures.h"
#include "modelslib.h"
#include "soundslib.h"


enum monsters_statuses
{
	IDLE = 0,
	REACH_ANGLE,
	REACH_TARGET,
	ATTACK,
	DYING,
	INTERRUPTLESS_ANIM,
	CUSTOM
};

const float ROTATION_ANGLE_THRESHOLD = 45.0f;	//stupnu
const float BASIC_VISIBILITY_RADIUS = 512.0f;
const float ANGLES_PER_POINT = 10.0f / 64.0f;	//10stupnu za metr
const float DEFAULT_ATTACK_RADIUS = 48.0f;

class ScriptedSequence;

#define WAIT_FOR_SEQUENCE 1
#define START_DEATH	2

const Uint32 DEFAULT_STEP_DELAY_TIME = 450;

class CBaseMonster : public Creatures
{
	void processStartDeath();
protected:
	int m_iDefaultDeathSequence, DefaultRaisingSequence;
	bool m_bStore_StartDeath;
	SoundElement m_MovementSound;
	modelLib::HLModelElement *m_pModel;
	BoundingBox m_RenderBounds;
	int m_iStatus;
	Point m_Target;
	float m_fTargetAngle;
	int m_iTargetAnimation;
	std::string m_sModelName;
	float m_fVisibilityRadius;
	float m_fAnglesPerPoint;
	float m_fAttackRadius;
	float m_fSpeed, m_fMaxSpeed;
	Vector m_vecDirection;
	int m_iCurrentAnimation;
	bool m_bDeathAnim;
	CBaseMonster *anim_finnish_monster;
	void (CBaseMonster::*anim_finnish_func)( void );

	bool playAnimation( int sequence, void (CBaseMonster::*func)(void ), CBaseMonster *monster );
	bool basic_combat( int damage, AttackInfo &target, float distance = INFINITE_DISTANCE, int damage_type = dmg::GENERIC, float dispersion = ZERO_DEGREES );
	
	virtual void onReachingAngle() = 0;	//spusteni animace akorat


	virtual void onIdle() = 0;
	
	virtual void onReachingTarget();
	virtual void onAttack() = 0;
	virtual void onDying() = 0;
	virtual void custom();

	struct callBack
	{
		Uint32 time;
		CBaseMonster *anim_finnish_monster;
		void (CBaseMonster::*anim_finnish_func)( void );
	};
	std::list<callBack> m_CallBacks;
	void insertCallBack( Uint32 delay, void (CBaseMonster::*func)(void ), CBaseMonster *monster );
	bool m_bNoticedPlayer;

	void onSequenceEnd();
	ScriptedSequence *m_pSequence;
	bool m_bStore_WaitForSequence;
	bool m_bWaitForSequence;
	virtual void passFlags( int flags );
	void calculateDistanceAndAngle( float &dist, float &angle, Point &target );
	
	Uint32 m_StepDelayTime;
	Uint32 m_StepSoundEnergy;
	Uint32 m_uiStepSoundStartTime;
public:
	CBaseMonster();
	virtual void goBackInTime();
	virtual void onAngleReachAnimEnd();
	virtual void onAttackEnd();

	void setTarget( ScriptedSequence *pSequence );//

	virtual void onAttack( const AttackInfo &attackInfo );
	virtual void prepareForCollision();//
	virtual void render( RenderData &renderData );//
	virtual void compile();////
	virtual void decompile();
	virtual bool renderCullTest( RenderData &renderData );//
	virtual void update( float seconds );
	virtual void teleport( const alg::Vector &v, bool interpolation = true );//
	virtual void restart();
	virtual void die();
	virtual void onTarget( int target_type );	//switch dead
};


#include "ent_environments.h"

#define NO_MOVEMENT	1

class ScriptedSequence : public CBaseEnvironment
{
	std::string m_sMonster;
	CBaseMonster *m_pMonster;
	virtual void passFlags( int flags );
public:
	ScriptedSequence();
	int m_iAnimation;
	bool m_bMoveHere;
	virtual void setParameters( parameters_t &parametersMap );
	virtual void onTarget( int target_type );
	virtual void compile();
	void onEnd();
};

LINK_ENTITY_TO_CLASS( scripted_sequence, ScriptedSequence );





enum
{
	CLAW_MISS1 = 0,
	CLAW_MISS2,
	CLAW_STRIKE1,
	CLAW_STRIKE2,
	CLAW_STRIKE3,
	FIGHT_SOUND_COUNT
};



class MonsterZombie : public CBaseMonster
{
	

	
	SoundElemPool<FIGHT_SOUND_COUNT> m_FightSoundsPool;
	SoundElement m_FightSound;

	virtual void onIdle();
	virtual void onReachingAngle();
	virtual void onReachingTarget();
	virtual void onAttack();
	virtual void onDying();
	virtual void custom();
	void onAttack2Finnish();
	void onAttack1Finnish();
	bool fight( int damage );
public:
	MonsterZombie();
	virtual void update( float seconds );
	virtual void compile();
};

LINK_ENTITY_TO_CLASS( monster_zombie, MonsterZombie );

#endif /*__BASE_MONSTER_H__*/

