*Update Naxx script. Let boss evade if they are pulled out of room.

--HG--
branch : trunk
This commit is contained in:
megamage
2009-05-17 16:37:03 -05:00
parent 424391d7c4
commit c75e3d526b
17 changed files with 176 additions and 101 deletions
+56 -19
View File
@@ -84,29 +84,13 @@ ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature), m_creature(cr
HeroicMode = m_creature->GetMap()->IsHeroic(); HeroicMode = m_creature->GetMap()->IsHeroic();
} }
void ScriptedAI::AttackStart(Unit* who, bool melee) void ScriptedAI::AttackStartNoMove(Unit* who)
{ {
if (!who) if (!who)
return; return;
if (m_creature->Attack(who, melee)) if(m_creature->Attack(who, false))
{ DoStartNoMovement(who);
if(melee)
DoStartMovement(who);
else
DoStartNoMovement(who);
}
}
void ScriptedAI::AttackStart(Unit* who)
{
if (!who)
return;
if (m_creature->Attack(who, true))
{
DoStartMovement(who);
}
} }
void ScriptedAI::UpdateAI(const uint32 diff) void ScriptedAI::UpdateAI(const uint32 diff)
@@ -650,6 +634,12 @@ void Scripted_NoMovementAI::AttackStart(Unit* who)
} }
} }
BossAI::BossAI(Creature *c, uint32 id) : ScriptedAI(c)
, bossId(id), summons(me), instance(c->GetInstanceData())
, boundary(instance ? instance->GetBossBoundary(id) : NULL)
{
}
void BossAI::_Reset() void BossAI::_Reset()
{ {
events.Reset(); events.Reset();
@@ -673,6 +663,53 @@ void BossAI::_EnterCombat()
instance->SetBossState(bossId, IN_PROGRESS); instance->SetBossState(bossId, IN_PROGRESS);
} }
bool BossAI::CheckBoundary(Unit *who)
{
if(!boundary || !who)
return true;
for(BossBoundaryMap::const_iterator itr = boundary->begin(); itr != boundary->end(); ++itr)
{
switch(itr->first)
{
case BOUNDARY_N:
if(me->GetPositionX() > itr->second)
return false;
break;
case BOUNDARY_S:
if(me->GetPositionX() < itr->second)
return false;
break;
case BOUNDARY_E:
if(me->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_W:
if(me->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_NW:
if(me->GetPositionX() + me->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SE:
if(me->GetPositionX() + me->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_NE:
if(me->GetPositionX() - me->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SW:
if(me->GetPositionX() - me->GetPositionY() < itr->second)
return false;
break;
}
}
return true;
}
void BossAI::JustSummoned(Creature *summon) void BossAI::JustSummoned(Creature *summon)
{ {
summons.Summon(summon); summons.Summon(summon);
+20 -12
View File
@@ -11,6 +11,7 @@
#include "Creature.h" #include "Creature.h"
#include "CreatureAI.h" #include "CreatureAI.h"
#include "CreatureAIImpl.h" #include "CreatureAIImpl.h"
#include "InstanceData.h"
class ScriptedInstance; class ScriptedInstance;
@@ -55,9 +56,7 @@ struct TRINITY_DLL_DECL ScriptedAI : public CreatureAI
//CreatureAI Functions //CreatureAI Functions
//************* //*************
//Called at each attack of m_creature by any victim void AttackStartNoMove(Unit *target);
void AttackStart(Unit *);
void AttackStart(Unit *, bool melee);
// Called at any Damage from any attacker (before damage apply) // Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit *done_by, uint32 &damage) {} void DamageTaken(Unit *done_by, uint32 &damage) {}
@@ -204,27 +203,36 @@ struct TRINITY_DLL_DECL Scripted_NoMovementAI : public ScriptedAI
struct TRINITY_DLL_DECL BossAI : public ScriptedAI struct TRINITY_DLL_DECL BossAI : public ScriptedAI
{ {
BossAI(Creature *c, uint32 id) : ScriptedAI(c), bossId(id) BossAI(Creature *c, uint32 id);
, summons(me), instance(c->GetInstanceData())
{}
uint32 bossId; const uint32 bossId;
EventMap events; EventMap events;
SummonList summons; SummonList summons;
InstanceData *instance; InstanceData * const instance;
const BossBoundaryMap * const boundary;
void JustSummoned(Creature *summon); void JustSummoned(Creature *summon);
void SummonedCreatureDespawn(Creature *summon); void SummonedCreatureDespawn(Creature *summon);
void UpdateAI(const uint32 diff) = 0; void UpdateAI(const uint32 diff) = 0;
void _Reset();
void _EnterCombat();
void _JustDied();
void Reset() { _Reset(); } void Reset() { _Reset(); }
void EnterCombat(Unit *who) { _EnterCombat(); } void EnterCombat(Unit *who) { _EnterCombat(); }
void JustDied(Unit *killer) { _JustDied(); } void JustDied(Unit *killer) { _JustDied(); }
protected:
void _Reset();
void _EnterCombat();
void _JustDied();
bool CheckInRoom()
{
if(CheckBoundary(me))
return true;
EnterEvadeMode();
return false;
}
bool CheckBoundary(Unit *who);
}; };
#endif #endif
@@ -441,9 +441,9 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
return; return;
if(Phase == PHASE_FLIGHT || Phase == PHASE_DEMON) if(Phase == PHASE_FLIGHT || Phase == PHASE_DEMON)
ScriptedAI::AttackStart(who, false); AttackStartNoMove(who);
else else
ScriptedAI::AttackStart(who, true); ScriptedAI::AttackStart(who);
} }
void MoveInLineOfSight(Unit *who) {} void MoveInLineOfSight(Unit *who) {}
@@ -1415,16 +1415,16 @@ struct TRINITY_DLL_DECL boss_maievAI : public ScriptedAI
return; return;
if(Phase == PHASE_TALK_SEQUENCE) if(Phase == PHASE_TALK_SEQUENCE)
ScriptedAI::AttackStart(who, false); AttackStartNoMove(who);
else if(Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE ) else if(Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE )
{ {
GETUNIT(Illidan, IllidanGUID); GETUNIT(Illidan, IllidanGUID);
if(Illidan && m_creature->IsWithinDistInMap(Illidan, 25)) if(Illidan && m_creature->IsWithinDistInMap(Illidan, 25))
BlinkToPlayer();//Do not let dread aura hurt her. BlinkToPlayer();//Do not let dread aura hurt her.
ScriptedAI::AttackStart(who, false); AttackStartNoMove(who);
} }
else else
ScriptedAI::AttackStart(who, true); ScriptedAI::AttackStart(who);
} }
void DoAction(const int32 param) void DoAction(const int32 param)
@@ -339,7 +339,7 @@ struct TRINITY_DLL_DECL boss_vazruden_the_heraldAI : public ScriptedAI
summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
summoned->SetSpeed(MOVE_FLIGHT, 2.5); summoned->SetSpeed(MOVE_FLIGHT, 2.5);
if(victim) if(victim)
((ScriptedAI*)summoned->AI())->AttackStart(victim,false); AttackStartNoMove(victim);
} }
else if(victim) else if(victim)
summoned->AI()->AttackStart(victim); summoned->AI()->AttackStart(victim);
@@ -349,7 +349,7 @@ struct TRINITY_DLL_DECL boss_vazruden_the_heraldAI : public ScriptedAI
{ {
if(sentryDown) if(sentryDown)
{ {
AttackStart(killer, false); AttackStartNoMove(killer);
sentryDown = false; sentryDown = false;
} }
else else
@@ -77,7 +77,7 @@ struct TRINITY_DLL_DECL boss_anubrekhanAI : public BossAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if(!UpdateVictim()) if(!UpdateVictim() || !CheckInRoom())
return; return;
events.Update(diff); events.Update(diff);
@@ -99,7 +99,7 @@ struct TRINITY_DLL_DECL boss_gluthAI : public BossAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if(!UpdateVictimWithGaze()) if(!UpdateVictimWithGaze() || !CheckInRoom())
return; return;
events.Update(diff); events.Update(diff);
@@ -202,7 +202,7 @@ struct TRINITY_DLL_DECL boss_gothikAI : public BossAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if(!UpdateVictimByReact()) if(!UpdateVictimByReact() || !CheckInRoom())
return; return;
events.Update(diff); events.Update(diff);
@@ -95,7 +95,7 @@ struct TRINITY_DLL_DECL boss_heiganAI : public BossAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if(!UpdateVictim()) if(!UpdateVictim() || !CheckInRoom())
return; return;
events.Update(diff); events.Update(diff);
@@ -128,19 +128,8 @@ struct TRINITY_DLL_DECL boss_nothAI : public BossAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if(me->HasReactState(REACT_AGGRESSIVE)) // ground if(!UpdateVictimByReact() || !CheckInRoom())
{ return;
if(!UpdateVictim())
return;
}
else // balcony
{
if(me->getThreatManager().isThreatListEmpty()) // if no enemy, go back at once
{
events.Reset();
events.ScheduleEvent(EVENT_GROUND, 0);
}
}
events.Update(diff); events.Update(diff);
@@ -171,13 +171,13 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public BossAI
if(!phase) if(!phase)
return; return;
if(!UpdateVictimByReact() || !CheckInRoom())
return;
events.Update(diff); events.Update(diff);
if(phase == PHASE_GROUND) if(phase == PHASE_GROUND)
{ {
if(!UpdateVictim())
return;
while(uint32 eventId = events.ExecuteEvent()) while(uint32 eventId = events.ExecuteEvent())
{ {
switch(eventId) switch(eventId)
@@ -224,12 +224,6 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public BossAI
} }
else else
{ {
/*if(me->getThreatManager().isThreatListEmpty())
{
EnterEvadeMode();
return;
}*/
if(uint32 eventId = events.ExecuteEvent()) if(uint32 eventId = events.ExecuteEvent())
{ {
switch(eventId) switch(eventId)
@@ -19,29 +19,29 @@
const DoorData doorData[] = const DoorData doorData[] =
{ {
{181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM}, {181126, BOSS_ANUBREKHAN,DOOR_TYPE_ROOM, BOUNDARY_S},
{181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE}, {181195, BOSS_ANUBREKHAN,DOOR_TYPE_PASSAGE, 0},
{194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE}, {194022, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0},
{181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE}, {181209, BOSS_FAERLINA, DOOR_TYPE_PASSAGE, 0},
{181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM}, {181209, BOSS_MAEXXNA, DOOR_TYPE_ROOM, BOUNDARY_SW},
{181200, BOSS_NOTH, DOOR_TYPE_ROOM}, {181200, BOSS_NOTH, DOOR_TYPE_ROOM, BOUNDARY_N},
{181201, BOSS_NOTH, DOOR_TYPE_PASSAGE}, {181201, BOSS_NOTH, DOOR_TYPE_PASSAGE, BOUNDARY_E},
{181202, BOSS_NOTH, DOOR_TYPE_PASSAGE}, {181202, BOSS_NOTH, DOOR_TYPE_PASSAGE, 0},
{181202, BOSS_HEIGAN, DOOR_TYPE_ROOM}, {181202, BOSS_HEIGAN, DOOR_TYPE_ROOM, BOUNDARY_N},
{181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE}, {181203, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, BOUNDARY_E},
{181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE}, {181241, BOSS_HEIGAN, DOOR_TYPE_PASSAGE, 0},
{181241, BOSS_LOATHEB, DOOR_TYPE_ROOM}, {181241, BOSS_LOATHEB, DOOR_TYPE_ROOM, BOUNDARY_W},
{181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE}, {181123, BOSS_PATCHWERK, DOOR_TYPE_PASSAGE, 0},
{181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM}, {181123, BOSS_GROBBULUS, DOOR_TYPE_ROOM, 0},
{181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE}, {181120, BOSS_GLUTH, DOOR_TYPE_PASSAGE, BOUNDARY_NW},
{181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE}, {181121, BOSS_GLUTH, DOOR_TYPE_PASSAGE, 0},
{181121, BOSS_THADDIUS, DOOR_TYPE_ROOM}, {181121, BOSS_THADDIUS, DOOR_TYPE_ROOM, 0},
{181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE}, {181124, BOSS_RAZUVIOUS, DOOR_TYPE_PASSAGE, 0},
{181124, BOSS_GOTHIK, DOOR_TYPE_ROOM}, {181124, BOSS_GOTHIK, DOOR_TYPE_ROOM, BOUNDARY_N},
{181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE}, {181125, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, BOUNDARY_S},
{181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE}, {181119, BOSS_GOTHIK, DOOR_TYPE_PASSAGE, 0},
{181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM}, {181119, BOSS_HORSEMEN, DOOR_TYPE_ROOM, BOUNDARY_NE},
{0, 0, DOOR_TYPE_ROOM}, // EOF {0, 0, DOOR_TYPE_ROOM, 0}, // EOF
}; };
const MinionData minionData[] = const MinionData minionData[] =
@@ -68,10 +68,10 @@ const float HeiganEruptionSlope[3] =
(-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]), (-3637 - HeiganPos[1]) /(2771 - HeiganPos[0]),
}; };
// 0 H O-->x // 0 H x
// 1 | // 1 ^
// 2 V // 2 |
// 3 y // 3 y<--o
inline uint32 GetEruptionSection(float x, float y) inline uint32 GetEruptionSection(float x, float y)
{ {
y -= HeiganPos[1]; y -= HeiganPos[1];
@@ -94,7 +94,7 @@ bool GossipSelect_npc_raliq_the_drunk(Player *player, Creature *_Creature, uint3
{ {
player->CLOSE_GOSSIP_MENU(); player->CLOSE_GOSSIP_MENU();
_Creature->setFaction(FACTION_HOSTILE_RD); _Creature->setFaction(FACTION_HOSTILE_RD);
((npc_raliq_the_drunkAI*)_Creature->AI())->AttackStart(player); _Creature->AI()->AttackStart(player);
} }
return true; return true;
} }
@@ -158,7 +158,7 @@ bool GossipHello_npc_salsalabim(Player *player, Creature *_Creature)
if( player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE ) if( player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE )
{ {
_Creature->setFaction(FACTION_HOSTILE_SA); _Creature->setFaction(FACTION_HOSTILE_SA);
((npc_salsalabimAI*)_Creature->AI())->AttackStart(player); _Creature->AI()->AttackStart(player);
} }
else else
{ {
@@ -150,9 +150,9 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI
void AttackStart(Unit* who) void AttackStart(Unit* who)
{ {
if(Phase1) if(Phase1)
ScriptedAI::AttackStart(who, false); AttackStartNoMove(who);
else else
ScriptedAI::AttackStart(who, true); ScriptedAI::AttackStart(who);
} }
void DamageTaken(Unit* pKiller, uint32 &damage) void DamageTaken(Unit* pKiller, uint32 &damage)
@@ -173,7 +173,7 @@ bool GossipSelect_npc_cooshcoosh(Player *player, Creature *_Creature, uint32 sen
{ {
player->CLOSE_GOSSIP_MENU(); player->CLOSE_GOSSIP_MENU();
_Creature->setFaction(FACTION_HOSTILE_CO); _Creature->setFaction(FACTION_HOSTILE_CO);
((npc_cooshcooshAI*)_Creature->AI())->AttackStart(player); _Creature->AI()->AttackStart(player);
} }
return true; return true;
} }
@@ -258,9 +258,9 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI
void AttackStart(Unit *who) void AttackStart(Unit *who)
{ {
if(Phase == 2) if(Phase == 2)
ScriptedAI::AttackStart(who, false); AttackStartNoMove(who);
else else
ScriptedAI::AttackStart(who, true); ScriptedAI::AttackStart(who);
} }
void DoMeleeAttackIfReady() void DoMeleeAttackIfReady()
+25 -1
View File
@@ -76,7 +76,7 @@ void InstanceData::LoadDoorData(const DoorData *data)
while(data->entry) while(data->entry)
{ {
if(data->bossId < bosses.size()) if(data->bossId < bosses.size())
doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type))); doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary))));
++data; ++data;
} }
@@ -143,7 +143,31 @@ void InstanceData::AddDoor(GameObject *door, bool add)
for(DoorInfoMap::iterator itr = lower; itr != upper; ++itr) for(DoorInfoMap::iterator itr = lower; itr != upper; ++itr)
{ {
if(add) if(add)
{
itr->second.bossInfo->door[itr->second.type].insert(door); itr->second.bossInfo->door[itr->second.type].insert(door);
switch(itr->second.boundary)
{
default:
case BOUNDARY_NONE:
break;
case BOUNDARY_N:
case BOUNDARY_S:
itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionX();
break;
case BOUNDARY_E:
case BOUNDARY_W:
itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionY();
break;
case BOUNDARY_NW:
case BOUNDARY_SE:
itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionX() + door->GetPositionY();
break;
case BOUNDARY_NE:
case BOUNDARY_SW:
itr->second.bossInfo->boundary[itr->second.boundary] = door->GetPositionX() - door->GetPositionY();
break;
}
}
else else
itr->second.bossInfo->door[itr->second.type].erase(door); itr->second.bossInfo->door[itr->second.type].erase(door);
} }
+25 -2
View File
@@ -51,10 +51,30 @@ enum DoorType
MAX_DOOR_TYPES, MAX_DOOR_TYPES,
}; };
enum BoundaryType
{
BOUNDARY_NONE = 0,
BOUNDARY_N,
BOUNDARY_S,
BOUNDARY_E,
BOUNDARY_W,
BOUNDARY_NE,
BOUNDARY_NW,
BOUNDARY_SE,
BOUNDARY_SW,
BOUNDARY_MAX_X = BOUNDARY_N,
BOUNDARY_MIN_X = BOUNDARY_S,
BOUNDARY_MAX_Y = BOUNDARY_W,
BOUNDARY_MIN_Y = BOUNDARY_E,
};
typedef std::map<BoundaryType, float> BossBoundaryMap;
struct DoorData struct DoorData
{ {
uint32 entry, bossId; uint32 entry, bossId;
DoorType type; DoorType type;
uint32 boundary;
}; };
struct MinionData struct MinionData
@@ -68,14 +88,16 @@ struct BossInfo
EncounterState state; EncounterState state;
DoorSet door[MAX_DOOR_TYPES]; DoorSet door[MAX_DOOR_TYPES];
MinionSet minion; MinionSet minion;
BossBoundaryMap boundary;
}; };
struct DoorInfo struct DoorInfo
{ {
explicit DoorInfo(BossInfo *_bossInfo, DoorType _type) explicit DoorInfo(BossInfo *_bossInfo, DoorType _type, BoundaryType _boundary)
: bossInfo(_bossInfo), type(_type) {} : bossInfo(_bossInfo), type(_type), boundary(_boundary) {}
BossInfo *bossInfo; BossInfo *bossInfo;
DoorType type; DoorType type;
BoundaryType boundary;
}; };
struct MinionInfo struct MinionInfo
@@ -137,6 +159,7 @@ class TRINITY_DLL_SPEC InstanceData
void HandleGameObject(uint64 GUID, bool open, GameObject *go = NULL); void HandleGameObject(uint64 GUID, bool open, GameObject *go = NULL);
virtual void SetBossState(uint32 id, EncounterState state); virtual void SetBossState(uint32 id, EncounterState state);
const BossBoundaryMap * GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : NULL; }
protected: protected:
void SetBossNumber(uint32 number) { bosses.resize(number); } void SetBossNumber(uint32 number) { bosses.resize(number); }
void LoadDoorData(const DoorData *data); void LoadDoorData(const DoorData *data);