/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#ifndef WOWSERVER_AIINTERFACE_H
#define WOWSERVER_AIINTERFACE_H
/* platforms that already define M_PI in math.h */
#ifdef M_PI
#undef M_PI
#endif
#define M_PI 3.14159265358979323846
#define UNIT_MOVEMENT_INTERPOLATE_INTERVAL 400/*750*/ // ms smoother server/client side moving vs less cpu/ less b/w
#define TARGET_UPDATE_INTERVAL 600 // ms
#define oocr 50.0f // out of combat range
#define PLAYER_SIZE 1.5f
#define ENABLE_CREATURE_DAZE
#ifdef ENABLE_CREATURE_DAZE
#define CREATURE_SPELL_TO_DAZE 1604
#define CREATURE_CHANCE_TO_DAZE 20
#define CREATURE_DAZE_TRIGGER_ANGLE M_PI/2 //for the beginners this means 45 degrees
#endif
class Object;
class Creature;
class Unit;
class Player;
class WorldSession;
class SpellCastTargets;
enum AIType
{
AITYPE_LONER,
AITYPE_AGRO,
AITYPE_SOCIAL,
AITYPE_PET,
AITYPE_TOTEM,
AITYPE_GUARDIAN, //we got a master but he cannot control us, we follow and battle oposite factions
};
enum MovementType
{
MOVEMENTTYPE_NONE,
MOVEMENTTYPE_RANDOMWP,
MOVEMENTTYPE_CIRCLEWP,
MOVEMENTTYPE_WANTEDWP,
MOVEMENTTYPE_DONTMOVEWP,
MOVEMENTTYPE_QUEST = 10,
MOVEMENTTYPE_FORWARDTHANSTOP = 11,
};
/*struct AI_Target
{
Unit* target;
int32 threat;
};*/
enum AI_Agent
{
AGENT_NULL,
AGENT_MELEE,
AGENT_RANGED,
AGENT_FLEE,
AGENT_SPELL,
AGENT_CALLFORHELP
};
enum AI_SpellType
{
STYPE_NULL,
STYPE_ROOT,
STYPE_HEAL,
STYPE_STUN,
STYPE_FEAR,
STYPE_SILENCE,
STYPE_CURSE,
STYPE_AOEDAMAGE,
STYPE_DAMAGE,
STYPE_SUMMON,
STYPE_BUFF,
STYPE_DEBUFF
};
enum AI_SpellTargetType
{
TTYPE_NULL,
TTYPE_SINGLETARGET,
TTYPE_DESTINATION,
TTYPE_SOURCE,
TTYPE_CASTER,
};
enum AI_State
{
STATE_IDLE,
STATE_ATTACKING,
STATE_CASTING,
STATE_FLEEING,
STATE_FOLLOWING,
STATE_EVADE,
STATE_MOVEWP,
STATE_FEAR,
STATE_WANDER,
STATE_STOPPED,
STATE_SCRIPTMOVE,
STATE_SCRIPTIDLE
};
enum MovementState
{
MOVEMENTSTATE_MOVE,
MOVEMENTSTATE_FOLLOW,
MOVEMENTSTATE_STOP,
MOVEMENTSTATE_FOLLOW_OWNER
};
enum CreatureState
{
STOPPED,
MOVING,
ATTACKING
};
enum AiEvents
{
EVENT_ENTERCOMBAT,
EVENT_LEAVECOMBAT,
EVENT_DAMAGETAKEN,
EVENT_FEAR,
EVENT_UNFEAR,
EVENT_FOLLOWOWNER,
EVENT_WANDER,
EVENT_UNWANDER,
EVENT_UNITDIED,
};
struct SpellEntry;
//enum MOD_TYPES;
struct AI_Spell
{
uint32 entryId;
uint16 agent;
uint32 procChance;
//int32 procCount;
//uint32 procCountDB;
SpellEntry * spell;
uint8 spellType;
uint8 spelltargetType;
float cooldown;
float floatMisc1;
uint32 Misc2;
float minrange;
float maxrange;
};
bool isGuard(uint32 id);
uint32 getGuardId(uint32 id);
typedef HM_NAMESPACE::hash_map TargetMap;
typedef std::set AssistTargetSet;
typedef std::map SpellMap;
class SERVER_DECL AIInterface
{
public:
AIInterface();
~AIInterface();
// Misc
void Init(Unit *un, AIType at, MovementType mt);
void Init(Unit *un, AIType at, MovementType mt, Unit *owner); // used for pets
Unit *GetUnit() { return m_Unit; }
Unit *GetPetOwner() { return m_PetOwner; }
void DismissPet();
void SetUnitToFollow(Unit* un) { UnitToFollow = un; };
void SetUnitToFear(Unit* un) { UnitToFear = un; };
void SetFollowDistance(float dist) { FollowDistance = dist; };
void SetUnitToFollowAngle(float angle) { m_fallowAngle = angle; }
bool setInFront(Unit* target);
inline Unit* getUnitToFollow() { return UnitToFollow; }
void setCreatureState(CreatureState state){ m_creatureState = state; }
inline uint8 getAIState() { return m_AIState; }
inline uint8 getAIType() { return m_AIType; }
inline uint8 getCurrentAgent() { return m_aiCurrentAgent; }
void setCurrentAgent(AI_Agent agent) { m_aiCurrentAgent = agent; }
uint32 getThreatByGUID(uint64 guid);
uint32 getThreatByPtr(Unit* obj);
Unit *GetMostHated();
bool modThreatByGUID(uint64 guid, int32 mod);
bool modThreatByPtr(Unit* obj, int32 mod);
void RemoveThreatByPtr(Unit* obj);
inline AssistTargetSet GetAssistTargets() { return m_assistTargets; }
inline TargetMap *GetAITargets() { return &m_aiTargets; }
void addAssistTargets(Unit* Friends);
void WipeHateList();
void WipeTargetList();
bool taunt(Unit* caster, bool apply = true);
Unit* getTauntedBy();
bool GetIsTaunted();
inline uint32 getAITargetsCount() { return m_aiTargets.size(); }
inline uint32 getOutOfCombatRange() { return m_outOfCombatRange; }
void setOutOfCombatRange(uint32 val) { m_outOfCombatRange = val; }
// Spell
void CastSpell(Unit* caster, SpellEntry *spellInfo, SpellCastTargets targets);
SpellEntry *getSpellEntry(uint32 spellId);
SpellCastTargets setSpellTargets(SpellEntry *spellInfo, Unit* target);
AI_Spell *getSpell();
void addSpellToList(AI_Spell *sp);
// Event Handler
void HandleEvent(uint32 event, Unit* pUnit, uint32 misc1);
void OnDeath(Object* pKiller);
void AttackReaction(Unit *pUnit, uint32 damage_dealt, uint32 spellId = 0);
bool HealReaction(Unit* caster, Unit* victim, uint32 amount);
void Event_Summon_EE_totem(uint32 summon_duration);
void Event_Summon_FE_totem(uint32 summon_duration);
// Update
void Update(uint32 p_time);
// Movement
void SendMoveToPacket(float toX, float toY, float toZ, float toO, uint32 time, uint32 MoveFlags);
//void SendMoveToSplinesPacket(std::list wp, bool run);
void MoveTo(float x, float y, float z, float o);
uint32 getMoveFlags();
void UpdateMove();
void SendCurrentMove(Player* plyr/*uint64 guid*/);
bool StopMovement(uint32 time);
uint32 getCurrentWaypoint() { return m_currentWaypoint; }
void changeWayPointID(uint32 oldwpid, uint32 newwpid);
bool addWayPoint(WayPoint* wp);
bool saveWayPoints(uint32 wpid);
bool showWayPoints(uint32 wpid, Player* pPlayer, bool Backwards);
bool hideWayPoints(uint32 wpid, Player* pPlayer);
WayPoint* getWayPoint(uint32 wpid);
void deleteWayPoint(uint32 wpid, bool save = true);
inline bool hasWaypoints() { return m_waypoints!=NULL; }
inline void setMoveType(uint32 movetype) { m_moveType = movetype; }
inline uint32 getMoveType() { return m_moveType; }
inline void setMoveRunFlag(bool f) { m_moveRun = f; }
inline bool getMoveRunFlag() { return m_moveRun; }
void setWaypointToMove(uint32 id) { m_currentWaypoint = id; }
bool IsFlying();
// Calculation
float _CalcAggroRange(Unit* target);
void _CalcDestinationAndMove(Unit *target, float dist);
float _CalcCombatRange(Unit* target, bool ranged);
float _CalcDistanceFromHome();
uint32 _CalcThreat(uint32 damage, uint32 spellId, Unit* Attacker);
void SetAllowedToEnterCombat(bool val) { m_AllowedToEnterCombat = val; }
inline bool GetAllowedToEnterCombat(void) { return m_AllowedToEnterCombat; }
void CheckTarget(Unit* target);
inline void SetAIState(AI_State newstate) { m_AIState = newstate; }
// Movement
bool m_canMove;
bool m_WayPointsShowing;
bool m_WayPointsShowBackwards;
uint32 m_currentWaypoint;
bool m_moveBackward;
uint32 m_moveType;
bool m_moveRun;
bool m_moveFly;
bool m_moveSprint;
CreatureState m_creatureState;
uint32 GetWayPointsCount()
{
if(m_waypoints)
return m_waypoints->size();
else
return 0;
}
bool m_canFlee;
bool m_canCallForHelp;
bool m_canRangedAttack;
float m_FleeHealth;
uint32 m_FleeDuration;
float m_CallForHelpHealth;
uint32 m_totemspelltimer;
uint32 m_totemspelltime;
SpellEntry * totemspell;
float m_sourceX, m_sourceY, m_sourceZ;
uint32 m_totalMoveTime;
inline void AddStopTime(uint32 Time) { m_moveTimer += Time; }
inline void SetNextSpell(AI_Spell * sp) { m_nextSpell = sp; }
inline Unit* GetNextTarget() { return m_nextTarget; }
inline void SetNextTarget (Unit *nextTarget)
{
m_nextTarget = nextTarget;
if(nextTarget)
m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, m_nextTarget->GetGUID());
else m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, 0);
}
/*inline void ResetProcCounts()
{
AI_Spell * sp;
for(list::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
{
sp = *itr;
sp->procCount =sp->procCountDB;
}
}*/
Creature * m_formationLinkTarget;
float m_formationFollowDistance;
float m_formationFollowAngle;
uint32 m_formationLinkSqlId;
void WipeReferences();
WayPointMap *m_waypoints;
inline void SetPetOwner(Unit * owner) { m_PetOwner = owner; }
map m_spellCooldown;
list m_spells;
uint32 __fastcall GetSpellCooldown(uint32 SpellId);
void __fastcall AddSpellCooldown(SpellEntry * pSpell, AI_Spell * sp);
bool disable_melee;
bool waiting_for_cooldown;
uint32 next_spell_time;
void CheckNextSpell(AI_Spell * sp)
{
if(m_nextSpell == sp)
m_nextSpell = 0;
}
inline void SetWaypointMap(WayPointMap * m) { m_waypoints = m; }
bool m_hasWaypointEvents;
bool m_isGuard;
bool m_fastMove;
void setGuardTimer(uint32 timer) { m_guardTimer = timer; }
private:
bool m_AllowedToEnterCombat;
// Update
void _UpdateTargets();
void _UpdateMovement(uint32 p_time);
void _UpdateCombat(uint32 p_time);
void _UpdateTimer(uint32 p_time);
int m_updateAssist;
int m_updateTargets;
uint32 m_updateAssistTimer;
uint32 m_updateTargetsTimer;
// Misc
bool firstLeaveCombat;
Unit* FindTarget();
Unit* FindTargetForSpell(AI_Spell *sp);
bool FindFriends(float dist);
AI_Spell *m_nextSpell;
Unit* m_nextTarget;
uint32 m_fleeTimer;
bool m_hasFleed;
bool m_hasCalledForHelp;
uint32 m_outOfCombatRange;
Unit *m_Unit;
Unit *m_PetOwner;
float FollowDistance;
float FollowDistance_backup;
float m_fallowAngle;
//std::set m_aiTargets;
TargetMap m_aiTargets;
AssistTargetSet m_assistTargets;
AIType m_AIType;
AI_State m_AIState;
AI_State m_AIState_backup;
AI_Agent m_aiCurrentAgent;
Unit* tauntedBy;
bool isTaunted;
// Movement
float m_moveSpeed;
float m_destinationX;
float m_destinationY;
float m_destinationZ;
float m_nextPosX;
float m_nextPosY;
float m_nextPosZ;
//Return position after attacking a mob
float m_returnX;
float m_returnY;
float m_returnZ;
float m_lastFollowX;
float m_lastFollowY;
//typedef std::map WayPointMap;
Unit *UnitToFollow;
Unit *UnitToFollow_backup;//used unly when forcing creature to wander (blind spell) so when effect wears off we can follow our master again (guardian)
Unit *UnitToFear;
uint32 m_timeToMove;
uint32 m_timeMoved;
uint32 m_moveTimer;
uint32 m_FearTimer;
uint32 m_WanderTimer;
MovementType m_MovementType;
MovementState m_MovementState;
uint32 m_guardTimer;
int32 m_currentHighestThreat;
};
#endif