/* Copyright (C) 2008-2010 Trinity * * Thanks to the original authors: ScriptDev2 * * This program is free software licensed under GPL version 2 * Please see the included DOCS/LICENSE.TXT for more information */ #ifndef SC_CREATURE_H #define SC_CREATURE_H #include "Creature.h" #include "CreatureAI.h" #include "CreatureAIImpl.h" #include "InstanceData.h" #define SCRIPT_CAST_TYPE dynamic_cast //#define SCRIPT_CAST_TYPE static_cast #define CAST_PLR(a) (SCRIPT_CAST_TYPE(a)) #define CAST_CRE(a) (SCRIPT_CAST_TYPE(a)) #define CAST_SUM(a) (SCRIPT_CAST_TYPE(a)) #define CAST_PET(a) (SCRIPT_CAST_TYPE(a)) #define CAST_AI(a,b) (SCRIPT_CAST_TYPE(b)) #define GET_SPELL(a) (const_cast(GetSpellStore()->LookupEntry(a))) class ScriptedInstance; class SummonList : public std::list { public: explicit SummonList(Creature* creature) : me(creature) {} void Summon(Creature *summon) { push_back(summon->GetGUID()); } void Despawn(Creature *summon) { remove(summon->GetGUID()); } void DespawnEntry(uint32 entry); void DespawnAll(); void DoAction(uint32 entry, uint32 info); void DoZoneInCombat(uint32 entry = 0); private: Creature *me; }; struct ScriptedAI : public CreatureAI { explicit ScriptedAI(Creature* pCreature); virtual ~ScriptedAI() {} //************* //CreatureAI Functions //************* void AttackStartNoMove(Unit *pTarget); // Called at any Damage from any attacker (before damage apply) void DamageTaken(Unit* pDone_by, uint32& uiDamage) {} //Called at World update tick void UpdateAI(const uint32); //Called at creature death void JustDied(Unit* who){} //Called at creature killing another unit void KilledUnit(Unit* who){} // Called when the creature summon successfully other creature void JustSummoned(Creature*) {} // Called when a summoned creature is despawned void SummonedCreatureDespawn(Creature*) {} // Called when hit by a spell void SpellHit(Unit* caster, const SpellEntry *spell) {} // Called when spell hits a target void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) {} //Called at waypoint reached or PointMovement end void MovementInform(uint32 type, uint32 id){} // Called when AI is temporarily replaced or put back when possess is applied or removed void OnPossess(bool apply) {} //************* // Variables //************* //Pointer to creature we are manipulating Creature* me; //For fleeing bool IsFleeing; //************* //Pure virtual functions //************* //Called at creature reset either by death or evade void Reset() {} //Called at creature aggro either by MoveInLOS or Attack Start void EnterCombat(Unit* who) {} //************* //AI Helper Functions //************* //Start movement toward victim void DoStartMovement(Unit* pVictim, float fDistance = 0, float fAngle = 0); //Start no movement on victim void DoStartNoMovement(Unit* pVictim); //Stop attack of current victim void DoStopAttack(); //Cast spell by spell info void DoCastSpell(Unit* pTarget, SpellEntry const* pSpellInfo, bool bTriggered = false); //Plays a sound to all nearby players void DoPlaySoundToSet(WorldObject* pSource, uint32 sound); //Drops all threat to 0%. Does not remove players from the threat list void DoResetThreat(); float DoGetThreat(Unit* u); void DoModifyThreatPercent(Unit* pUnit, int32 pct); void DoTeleportTo(float fX, float fY, float fZ, uint32 uiTime = 0); void DoTeleportTo(const float pos[4]); void DoAction(const int32 param) {} //Teleports a player without dropping threat (only teleports to same map) void DoTeleportPlayer(Unit* pUnit, float fX, float fY, float fZ, float fO); void DoTeleportAll(float fX, float fY, float fZ, float fO); //Returns friendly unit with the most amount of hp missing from max hp Unit* DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff = 1); //Returns a list of friendly CC'd units within range std::list DoFindFriendlyCC(float fRange); //Returns a list of all friendly units missing a specific buff within range std::list DoFindFriendlyMissingBuff(float fRange, uint32 uiSpellId); //Return a player with at least minimumRange from me Player* GetPlayerAtMinimumRange(float fMinimumRange); //Spawns a creature relative to me Creature* DoSpawnCreature(uint32 uiId, float fX, float fY, float fZ, float fAngle, uint32 uiType, uint32 uiDespawntime); //Selects a unit from the creature's current aggro list Unit* SelectUnit(SelectAggroTarget pTarget, uint32 uiPosition); bool HealthBelowPct(uint32 pct) const { return me->GetHealth() * 100 < me->GetMaxHealth() * pct; } //Returns spells that meet the specified criteria from the creatures spell list SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTargetType Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect); //Checks if you can cast the specified spell bool CanCast(Unit* pTarget, SpellEntry const* pSpell, bool bTriggered = false); void SetEquipmentSlots(bool bLoadDefault, int32 uiMainHand = EQUIP_NO_CHANGE, int32 uiOffHand = EQUIP_NO_CHANGE, int32 uiRanged = EQUIP_NO_CHANGE); //Generally used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims void SetCombatMovement(bool CombatMove); bool IsCombatMovement() { return m_bCombatMovement; } bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff); // return true for heroic mode. i.e. // - for dungeon in mode 10-heroic, // - for raid in mode 10-Heroic // - for raid in mode 25-heroic // DO NOT USE to check raid in mode 25-normal. bool IsHeroic() { return m_heroicMode; } // return the dungeon or raid difficulty Difficulty getDifficulty() { return m_difficulty; } template inline const T& DUNGEON_MODE(const T& normal5, const T& heroic10) { switch(m_difficulty) { case DUNGEON_DIFFICULTY_NORMAL: return normal5; case DUNGEON_DIFFICULTY_HEROIC: return heroic10; } return heroic10; } template inline const T& RAID_MODE(const T& normal10, const T& normal25) { switch(m_difficulty) { case RAID_DIFFICULTY_10MAN_NORMAL: return normal10; case RAID_DIFFICULTY_25MAN_NORMAL: return normal25; } return normal25; } template inline const T& RAID_MODE(const T& normal10, const T& normal25, const T& heroic10, const T& heroic25) { switch(m_difficulty) { case RAID_DIFFICULTY_10MAN_NORMAL: return normal10; case RAID_DIFFICULTY_25MAN_NORMAL: return normal25; case RAID_DIFFICULTY_10MAN_HEROIC: return heroic10; case RAID_DIFFICULTY_25MAN_HEROIC: return heroic25; } return heroic25; } private: bool m_bCombatMovement; uint32 m_uiEvadeCheckCooldown; bool m_heroicMode; Difficulty m_difficulty; }; struct Scripted_NoMovementAI : public ScriptedAI { Scripted_NoMovementAI(Creature* creature) : ScriptedAI(creature) {} virtual ~Scripted_NoMovementAI() {} //Called at each attack of me by any victim void AttackStart(Unit* who); }; struct BossAI : public ScriptedAI { BossAI(Creature *c, uint32 id); virtual ~BossAI() {} const uint32 bossId; EventMap events; SummonList summons; InstanceData * const instance; const BossBoundaryMap * const boundary; void JustSummoned(Creature *summon); void SummonedCreatureDespawn(Creature *summon); void UpdateAI(const uint32 diff) = 0; void Reset() { _Reset(); } void EnterCombat(Unit *who) { _EnterCombat(); } void JustDied(Unit *killer) { _JustDied(); } void JustReachedHome() { me->setActive(false); } protected: void _Reset(); void _EnterCombat(); void _JustDied(); void _JustReachedHome() { me->setActive(false); } bool CheckInRoom() { if (CheckBoundary(me)) return true; EnterEvadeMode(); return false; } bool CheckBoundary(Unit *who); void TeleportCheaters(); }; // SD2 grid searchers. Creature *GetClosestCreatureWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange, bool bAlive = true); GameObject *GetClosestGameObjectWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange); void GetCreatureListWithEntryInGrid(std::list& lList, WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange); void GetGameObjectListWithEntryInGrid(std::list& lList, WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange); #endif