#ifndef __STANCE_H__ #define __STANCE_H__ #include "ps/Vector2D.h" class CEntity; class CPlayer; /** * A combat stance. This object is given various events by an entity and can choose what the * entity will do when it does not have any player orders. **/ class CStance { protected: CEntity* m_Entity; public: CStance(CEntity* ent): m_Entity(ent) {} virtual ~CStance() {} // Called each tick if the unit is idle. virtual void onIdle() = 0; // Called when the unit is damaged. Source might be NULL for damage from "acts of Gaia" // (but we get notified anyway in case we want to run around in fear). Most stances will // probably want to retaliate here. virtual void onDamaged(CEntity* source) = 0; // Does this stance allow movement at all during AI control? virtual bool allowsMovement() = 0; // Called when the unit is under AI control and wishes to move to the given position; // the stance may choose to cancel if it is too far. virtual bool checkMovement(CVector2D proposedPos) = 0; }; /** * Hold Fire stance: Unit never attacks, not even to fight back. **/ class CHoldStance : public CStance { public: CHoldStance(CEntity* ent): CStance(ent) {}; virtual ~CHoldStance() {}; virtual void onIdle() {}; virtual void onDamaged(CEntity* UNUSED(source)) {}; virtual bool allowsMovement() { return false; }; virtual bool checkMovement(CVector2D UNUSED(proposedPos)) { return false; } }; /** * Aggressive stance: The unit will attack any enemy it sees and pursue it indefinitely. **/ class CAggressStance : public CStance { public: CAggressStance(CEntity* ent): CStance(ent) {}; virtual ~CAggressStance() {}; virtual void onIdle(); virtual void onDamaged(CEntity* source); virtual bool allowsMovement() { return true; }; virtual bool checkMovement(CVector2D UNUSED(proposedPos)) { return true; } }; /** * Stand Ground stance: The unit will attack enemies in LOS but never move. **/ class CStandStance : public CStance { public: CStandStance(CEntity* ent): CStance(ent) {}; virtual ~CStandStance() {}; virtual void onIdle(); virtual void onDamaged(CEntity* source); virtual bool allowsMovement() { return false; }; virtual bool checkMovement(CVector2D UNUSED(proposedPos)) { return false; } }; /** * Defensive stance: The unit will attack enemies but will never pursue them further * than its LOS away from its original position (the point where it last became idle). **/ class CDefendStance : public CStance { CVector2D idlePos; public: CDefendStance(CEntity* ent): CStance(ent) {}; virtual ~CDefendStance() {}; virtual void onIdle(); virtual void onDamaged(CEntity* source); virtual bool allowsMovement() { return true; }; virtual bool checkMovement(CVector2D proposedPos); }; /** * Utility functions used by the various stances. **/ class CStanceUtils { private: CStanceUtils() {}; public: // Attacks the given target using the appropriate attack action (obtained from JavaScript). static void attack(CEntity* entity, CEntity* target); // Picks a visible entity to attack. static CEntity* chooseTarget(CEntity* entity); // Picks a visible entity within the given circle to attack static CEntity* chooseTarget(float x, float y, float radius, CPlayer* player); }; #endif