#ifndef TASK_H
#define TASK_H
#include "bot_types.h"
// Status checks
#define CheckFly		(1<<1)
#define CheckKi			(1<<2)
#define CheckAscend		(1<<3)
#define CheckHealth		(1<<4)
#define CheckAllStats	(CheckFly | CheckKi | CheckAscend | CheckHealth)

// Sense checks
#define CheckSounds					(1<<0)
#define CheckAttacks				(1<<1)
#define CheckSurroundingPlayers		(1<<2)
#define CheckHit					(1<<3)
#define SenseAll					(CheckSounds | CheckAttacks | CheckSurroundingPlayers | CheckHit)

// Misc checks
#define CheckForEnemies				(1<<1)
#define CheckForChatMsg				(1<<2)
#define CheckDragonBall				(1<<3)
#define CheckForHunt				(1<<4)
#define CheckForKameTorps			(1<<5)
#define CheckForCookie				(1<<6)
#define CheckForSensu				(1<<7)
#define CheckAllMiscThings			(CheckForEnemies | CheckForChatMsg | CheckDragonBall | CheckForHunt | CheckForKameTorps | CheckForCookie | CheckForSensu)

class CBaseTask
{
public:
	// member variabeles
	float Delay;
	EState TaskState;
	CBot *pBot;
	// Some shortcuts...
	edict_t *pEdict; // Bots edict
	CBasePlayer *pEnemy; // Current bot enemy
	
	//added by harSens, Linux compile fix
	CBaseTask(){};

	CBaseTask(CBot *pB); // constructor
	virtual ~CBaseTask(void); // destructor

	// member functions
	float GetTaskDelay(void)		{ return Delay; };
	short GetTaskState(void)		{ return TaskState; };
	virtual int GetNesserelyChecks(void) = 0;
	virtual int GetBotStatusChecks(void) = 0;
	virtual int GetBotSenseChecks(void) = 0;
	virtual int GetBotMiscChecks(void) = 0;

	void MakeCombo(EComboType CT);
	void SetGeneralDelay(void);

	virtual void TaskThink(void) = 0;
	virtual ETaskCode TaskIdentify(void) = 0;
	virtual bool ShouldManageEnemies(void) = 0;
	virtual void ManageEnemies(void);
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return true; };
};

class CPowerUpTask: public CBaseTask
{
	short GetKiTarget(void);

public:
	CPowerUpTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CPowerUpTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskPowerup; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CTeleportTask: public CBaseTask
{
	int GetRandomTeleDir(void);

public:
	CTeleportTask(CBot *pB);
	virtual ~CTeleportTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskTeleport; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CBlockTask: public CBaseTask
{
	float BlockTime;

public:
	CBlockTask(CBot *pB) : CBaseTask(pB), BlockTime(Delay + 1.0f) {};
	virtual ~CBlockTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskBlock; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CKickEnemyTask: public CBaseTask
{
	float m_fCanKickTime;

public:

	CKickEnemyTask(CBot *pB) : CBaseTask(pB), m_fCanKickTime(Delay) {};
	virtual ~CKickEnemyTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskKickEnemy; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return (pDangerInfo->DangerValue >= DANGER_MEDIUM_MIN_VAL); };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckFly; };
	virtual int GetBotSenseChecks(void) { return (CheckSounds | CheckAttacks); };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CCounterMeleeTask: public CBaseTask
{
	int ComboChargeButton;
	float PunchKickTime;
	float NewKickPunchButtonDelay;

public:

	CCounterMeleeTask(CBot *pB) : CBaseTask(pB), PunchKickTime(Delay + RANDOM_FLOAT(1.1, 2.4)),
								  ComboChargeButton(IN_ATTACK), NewKickPunchButtonDelay(0.0f) {};
	virtual ~CCounterMeleeTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskCounterMelee; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CCombatTask: public CBaseTask  
{
public:
	CCombatTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CCombatTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskCombat; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return (pDangerInfo->DangerValue >= DANGER_MEDIUM_MIN_VAL); };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return (CheckForChatMsg | CheckDragonBall); };

	void CombatThink(void);
	float GetMinDistForAttackById(int AttackId);
	float GetMaxDistForAttackById(int AttackId);
	float GetMinDistForAttackByTableIndex(int TableInd);
	float GetMaxDistForAttackByTableIndex(int TableInd);
	void PrepareAttack(weapon_info_s *pAttackInfo, EComboUse ComboUse);
	void AttackWithMelee(void);
	short GetAttackPercent(CBasePlayer *pEnemy, weapon_info_s *pAttackInfo);
	int GetAttackIndex(int AttackId);
	bool CanUseSecondaryFire(int AttackId);
};

class CNormalMovementTask: public CBaseTask  
{
	void BotLook(void);
	void CheckFOV(void);
	void CheckSkyBox(void);
	void BotCheckUpDown(void);
	void BotTurnAtWall(Vector *vecPlaneNormal);

public:
	CNormalMovementTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CNormalMovementTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskNormalMovement; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return CheckAllMiscThings; };
};

class CSwoopTask: public CBaseTask  
{
	bool CheckedSecondary;
	bool HoldSecondary;
	short SwoopOffsetXFactor;
	short SwoopOffsetYFactor;
	float SwoopOffsetXTarget;
	float SwoopOffsetYTarget;
	float LifeTime; // Life time for the avoid danger swoop
	float ChainSwoopCheckDelay;
	short SwoopFlags; // Swoop flags after this task is destroyed
	float TurnLessTime; // Last time the didn't had to turn much

public:

	CSwoopTask(CBot *pB);
	virtual ~CSwoopTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskSwoop; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };

	void CheckSecondaryFire(void);
	void SelectSwoopType(void);
	bool IsAvoidDangerSwoop(void) { return (pBot->m_Swoop.m_iSwoopDirection != FRONT); };
	float GetSwoopLifeTime(void);
};

class CPowerStruggleTask: public CBaseTask  
{
public:
	CPowerStruggleTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CPowerStruggleTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskPowerstruggle; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return CheckForChatMsg; };
};

class CFinishMeleeTask: public CBaseTask  
{
	int ComboChargeButton;
	float NewKickPunchButtonDelay;
	float PunchKickTime;
	float FinishMeleeTime;
	short FinishMeleeType;
	byte PrepunchAmountGoal;

	CBasePlayer *pPlayerToThrowAt;
	Vector ObstacleToThrowAt;
	bool CheckedObstacle;

public:

	CFinishMeleeTask(CBot *pB);
	virtual ~CFinishMeleeTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskFinishMelee; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };

	void CheckPlayerToThrowAt(void);
	void CheckObstacleToThrowAt(void);
	bool IsValidThrowVictim(CBasePlayer *pPlayer);
};

class CAscendTask: public CBaseTask  
{
public:
	CAscendTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CAscendTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskAscend; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return (CheckSounds | CheckAttacks | CheckHit); };
	virtual int GetBotMiscChecks(void) { return CheckForChatMsg; };
};

class CBlindedTask: public CBaseTask  
{
public:
	CBlindedTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CBlindedTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskBlinded; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CComboTask: public CBaseTask  
{
public:
	CComboTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CComboTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskCombo; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CChargeAttackTask: public CBaseTask
{
	float EnemyMovingFastTime; // Time that the enemy is moving very fast
	float EnemyMovingSlowTime; // Time that the enemy is moving very slow

public:
	CChargeAttackTask(CBot *pB) : CBaseTask(pB), EnemyMovingFastTime(0.0f),
								  EnemyMovingSlowTime(Delay) {};
	virtual ~CChargeAttackTask(void) { pBot->m_pCurrentWeaponInfo = NULL; };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskChargeAttack; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CShootNonChargebleTask: public CBaseTask
{
	float m_fLifeTime;

public:
	CShootNonChargebleTask(CBot *pB) : CBaseTask(pB), m_fLifeTime(pBot->m_fHoldAttackTime + Delay) {};
	virtual ~CShootNonChargebleTask(void) { pBot->m_fHoldAttackTime = 0.0f; pBot->m_pCurrentWeaponInfo = NULL; };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskShootNonChargeble; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CShootScatterShotsTask: public CBaseTask
{
	float ShootTime;
	float StartTime;
	bool UseScatterCheat;

public:
	CShootScatterShotsTask(CBot *pB);
	virtual ~CShootScatterShotsTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskShootScatterShots; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };

	CBaseEntity *GetFurthestScatterShot(void);
};
	
class CControlFriezaDiscTask: public CBaseTask
{
	float EnemyMovingFastTime; // Time that the enemy is moving very fast
	float EnemyMovingSlowTime; // Time that the enemy is moving very slow
	float RealDiscTime;
	float LifeTime;

public:

	CControlFriezaDiscTask(CBot *pB) : CBaseTask(pB), EnemyMovingFastTime(0.0f),
									   EnemyMovingSlowTime(Delay),
									   RealDiscTime(RANDOM_FLOAT(10.0, 22.0)),
									   LifeTime(Delay + RealDiscTime) {};
	virtual ~CControlFriezaDiscTask(void) { pBot->SelectItem("weapon_genericbeam"); /* Make the disc go away...*/ };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskControlFriezaDisc; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return (pDangerInfo->DangerValue >= DANGER_MEDIUM_MIN_VAL); };
	virtual int GetNesserelyChecks(void) { return CheckFly; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CControlBeamTask: public CBaseTask
{
	float ControlBeamTime;
	bool BotShouldAimAtAttack;

public:
	CControlBeamTask(CBot *pB) : CBaseTask(pB), ControlBeamTime(Delay + 10.0f),
								 BotShouldAimAtAttack(false) {};
	virtual ~CControlBeamTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskControlBeam; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CLookAroundTask: public CBaseTask
{
	Vector LookAroundSpots[4];
	short Stage;
	float LookAroundDelay;

public:

	CLookAroundTask(CBot *pB) : CBaseTask(pB), Stage(0), LookAroundDelay(0.0f) {};
	virtual ~CLookAroundTask(void) { pBot->m_fPauseCheckTime = gpGlobals->time + RANDOM_FLOAT(6.0f, 12.0f); };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskLookAround; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return (CheckForEnemies | CheckForChatMsg | CheckDragonBall | CheckForHunt | CheckForCookie); };
};

// for a buu bot
class CRecoverHPTask: public CBaseTask
{
public:
	CRecoverHPTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CRecoverHPTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskRecoverHP; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return CheckForChatMsg; };
};

class CWallJumpTask: public CBaseTask
{
	float LifeTime;
	float StartChargingTime;

public:
	CWallJumpTask(CBot *pB);
	virtual ~CWallJumpTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskWallJump; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CKameTorpTask: public CBaseTask
{
	enum EKameTorpState
	{
		STATE_CHARGING,
		STATE_POWERUP,
		STATE_RELEASING,
		STATE_MOVE,
		STATE_LOOK_AROUND
	};

	float MoveAwayTime;
	int MoveAwayDir;
	float LookDelay;
	float MoveAwayDelay;
	bool PickedAnAimSpot;

	EKameTorpState KameTorpState;
	float LifeTime;
	float ShootLifeTime;
	short DesiredTorpCount;
	bool ShootingTorps;

public:

	CKameTorpTask(CBot *pB);
	virtual ~CKameTorpTask(void);

	void ChargeKameTorps(void);
	bool SetMoveAwayDir(void); // returns true when found a direction to move at
	short CountTorps(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskKameTorp; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CIdleTask: public CBaseTask
{
public:
	CIdleTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CIdleTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskIdle; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return CheckForChatMsg; };
};

class CRecoverMeleeTask: public CBaseTask
{
public:
	CRecoverMeleeTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CRecoverMeleeTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskRecoverMelee; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CBeamJumpTask: public CBaseTask
{
	float LifeTime;
	float TraceDelay;
	float CreateTime;

public:
	CBeamJumpTask(CBot *pB) : CBaseTask(pB), LifeTime(Delay + RANDOM_FLOAT(2.2, 3.2)),
		                      TraceDelay(0.0f), CreateTime(Delay) {};
	virtual ~CBeamJumpTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskBeamJump; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return ((pBot->m_fControl) && (pEdict->v.movetype == MOVETYPE_RIDEBEAM)) ? 0 : SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CNormalJumpTask: public CBaseTask
{
	float LifeTime;
	float TeleCheckDelay;

public:

	CNormalJumpTask(CBot *pB) : CBaseTask(pB), LifeTime(Delay + RANDOM_FLOAT(0.8, 1.2)),
								TeleCheckDelay(Delay + 0.2f) {};
	virtual ~CNormalJumpTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskNormalJump; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CShootCandyTask: public CBaseTask
{
	float LifeTime;
	float TeleCheckTime;
	float MoveBackTime;
	float CookieCheckDelay;
	float MoveToCookieTime;
	float EnemyIsInRangeTime;

public:

	CShootCandyTask(CBot *pB) : CBaseTask(pB), LifeTime(Delay + RANDOM_FLOAT(2.5, 5.0)),
								TeleCheckTime(0.0f), MoveBackTime(0.0f), CookieCheckDelay(0.0f),
								MoveToCookieTime(0.0f), EnemyIsInRangeTime(Delay) {};
	virtual ~CShootCandyTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskShootCandy; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return (pDangerInfo->DangerValue >= DANGER_MEDIUM_MIN_VAL); };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckFly; };
	virtual int GetBotSenseChecks(void) { return (CheckHit | CheckAttacks); };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CDBTask: public CCombatTask
{
	float m_fDBThrowDelay;
	float m_fLastTurnLessTime; // Last time the bot didn't had to turn much(to prevent circeling)
	float m_fStopMoveTime;
	float m_fMoveUpDownTime;
	int m_iMoveUpDownDir;
	bool m_bMoveAway;
	float m_fLastTeleCheck;
	float m_fLastSwoopCheck;
	bool m_bSwooped; // Did the bot swooped the previous frame?
	float m_fLastRandomMoveTime;
	float m_fRandomMoveTime;
	int m_iRandomMoveDir;
	float m_fLastRandomLookAroundTime;
	float m_fRandomLookAroundTime;
	float m_fLastLookAroundUpdate;
	Vector m_vRandomLookPos;
	float m_fChargeAttackCheckDelay; // Delay before the bot should check for charging an attack
	bool m_bCharging;
	bool m_bUseShield;
	float m_fShieldCheckDelay;

	enum EMoveAwayFromDBState
	{
		STATE_PAUSE, // pause after throw
		STATE_TURNAWAY, // turn 180 degrees
		STATE_MOVEAWAY, // Move a bit away
		STATE_NOAWAYSTATE
	} m_eMoveAwayState;

	float m_fNextAwayStateUpdate;
	float m_fStuckCheckTime;
	Vector m_vPrevLocation;

	bool HeadToNextDBWP(void);
	bool GoToDBSpot(void);
	bool GoToGatheredSpot(void);
	bool GoToDB(void);
	bool CheckThrowToDBSpot(void);
	bool DefendGatherSpot(void);
	bool GoToDefendSpot(void);
	bool CheckGatheredSpot(void);
	void HeadToGoal(Vector v_target);
	bool AttackEnemy(void);
	bool SuspectEnemy(void);
	weapon_info_s *CheckForChargeble(void);
	void AvoidPlayers(Vector v_target);
	bool UseShield(void);
	bool IsStuck(void);

public:
	CDBTask(CBot *pB) : CCombatTask(pB), m_fDBThrowDelay(0.0f), m_fLastTurnLessTime(Delay),
						m_fStopMoveTime(0.0f), m_bMoveAway(false),
						m_fNextAwayStateUpdate(0.0f), m_eMoveAwayState(STATE_NOAWAYSTATE),
						m_fLastTeleCheck(Delay + 1.0f),	m_fLastSwoopCheck(Delay + 1.0f),
						m_bSwooped(pEdict->v.movetype == MOVETYPE_PLAYERSWOOP),
						m_fLastRandomMoveTime(Delay + 1.5f), m_fRandomMoveTime(0.0f),
						m_iRandomMoveDir(0), m_fLastRandomLookAroundTime(0.0f),
						m_fRandomLookAroundTime(0.0f), m_fLastLookAroundUpdate(0.0f),
						m_vRandomLookPos(g_vecZero), m_fChargeAttackCheckDelay(0.0f),
						m_bCharging(false), m_bUseShield(false), m_fShieldCheckDelay(0.0f),
						m_vPrevLocation(pB->pev->origin), m_fStuckCheckTime(Delay + 2.0f) {};
	virtual ~CDBTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskDB; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void);
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo);
};

class CJumpOffGroundTask: public CBaseTask
{
	int MoveDir;

public:

	CJumpOffGroundTask(CBot *pB);
	virtual ~CJumpOffGroundTask(void) {};

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskJumpOffGround; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return 0; };
	virtual int GetBotSenseChecks(void) { return 0; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CHuntEnemyTask: public CBaseTask
{
	float m_fHuntPlayerUpdateTime;
	float m_fStartTime;

public:

	CHuntEnemyTask(CBot *pB) : CBaseTask(pB), m_fHuntPlayerUpdateTime(gpGlobals->time + 1.5f),
							   m_fStartTime(Delay) {};
	virtual ~CHuntEnemyTask(void) { pBot->m_pHuntPlayer = NULL; pBot->m_fHuntDelay = gpGlobals->time + 3.0f; };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskHuntEnemy; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return true; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return (CheckForEnemies | CheckForChatMsg | CheckDragonBall | CheckForCookie); };
};

class CGetSensuBeanTask: public CBaseTask
{
	float m_fLastTurnLessTime; // Last time the bot didn't had to turn much(to prevent circeling)
	float m_fStopMoveTime;

public:
	CGetSensuBeanTask(CBot *pB) : CBaseTask(pB), m_fLastTurnLessTime(Delay),
		                          m_fStopMoveTime(0.0f) {};
	virtual ~CGetSensuBeanTask(void) { pBot->m_pTargetSensuBean = NULL; };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskGetSensu; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return true; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return (CheckForEnemies | CheckForChatMsg | CheckDragonBall | CheckForCookie); };
};

class CGetCandyTask: public CBaseTask
{
	float m_fLastTurnLessTime; // Last time the bot didn't had to turn much(to prevent circeling)
	float m_fStopMoveTime;

public:
	CGetCandyTask(CBot *pB) : CBaseTask(pB), m_fLastTurnLessTime(Delay),
		                          m_fStopMoveTime(0.0f) {};
	virtual ~CGetCandyTask(void) { pBot->m_pTargetSensuBean = NULL; };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskGetCandy; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return true; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return (CheckForEnemies | CheckForChatMsg | CheckDragonBall | CheckForCookie); };
};

class CMoveToGoalTask: public CBaseTask
{
public:
	CMoveToGoalTask(CBot *pB) : CBaseTask(pB) {};
	virtual ~CMoveToGoalTask(void) { pBot->ResetWaypointVars(); };

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskHeadToGoal; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return true; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckAllStats; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return (CheckForEnemies | CheckForChatMsg | CheckDragonBall | CheckForCookie); };
};

// following tasks are for super bots

class CShootLaser1Task: public CBaseTask
{
	float ShootTime;

public:

	CShootLaser1Task(CBot *pB) : CBaseTask(pB), ShootTime(Delay + RANDOM_FLOAT(3.0, 6.0)) {};
	virtual ~CShootLaser1Task(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskShootLaser1; };
	virtual bool ShouldManageEnemies(void) { return true; };
	virtual void ManageEnemies();
	virtual bool ReactOnDanger(danger_info_s *pDangerInfo) { return (pDangerInfo->DangerValue >= DANGER_MEDIUM_MIN_VAL); }; 
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckFly; };
	virtual int GetBotSenseChecks(void) { return SenseAll; };
	virtual int GetBotMiscChecks(void) { return 0; };
};

class CDrainEntsTask: public CBaseTask
{
	float LifeTime;

	// structure containing info about absorbed attacks
	struct attack_info_s
	{
		CBaseEntity *pAttack;
		Vector OldVelocity;
		bool bFounded;

		// Constructor
		attack_info_s(CBaseEntity *p) : pAttack(p), OldVelocity(p->pev->velocity),
										bFounded(true) {};
		// Destructor
		~attack_info_s(void) { if (!IsNull(pAttack)) pAttack->pev->velocity = OldVelocity; };
	};

	TLinkedList<attack_info_s *> *pAttackInfoList;

public:

	CDrainEntsTask(CBot *pB) : CBaseTask(pB), LifeTime(Delay + RANDOM_FLOAT(3.0, 7.0)),
		                       pAttackInfoList(new TLinkedList<attack_info_s *>) {};
	virtual ~CDrainEntsTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskDrainEnts; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckFly; };
	virtual int GetBotSenseChecks(void) { return CheckHit; };
	virtual int GetBotMiscChecks(void) { return 0; };

	void DrainAttack(CBaseEntity *pAttack);
	void DrainPlayer(CBasePlayer *pPlayer);
};

class CAbsorbHealthTask: public CBaseTask
{
public:
	float LifeTime;

	CAbsorbHealthTask(CBot *pB) : CBaseTask(pB), LifeTime(Delay + RANDOM_FLOAT(3.0, 7.0)) {};
	virtual ~CAbsorbHealthTask(void);

	virtual void TaskThink(void);
	virtual ETaskCode TaskIdentify(void) { return TaskAbsorbHealth; };
	virtual bool ShouldManageEnemies(void) { return false; };
	virtual int GetNesserelyChecks(void) { return 0; };
	virtual int GetBotStatusChecks(void) { return CheckFly; };
	virtual int GetBotSenseChecks(void) { return CheckHit; };
	virtual int GetBotMiscChecks(void) { return 0; };

	bool ShootAbsorbHealthBeams(void);
};

#endif