Merge branch 'azerothcore:master' into Playerbot

This commit is contained in:
ZhengPeiRu21
2022-04-16 21:41:45 -06:00
committed by GitHub
240 changed files with 14385 additions and 4083 deletions
+1 -1
View File
@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Define.h"
#include "LogCommon.h"
#include "Define.h"
#include "SmartEnum.h"
#include <stdexcept>
+2 -2
View File
@@ -847,8 +847,8 @@ bool AuthSession::VerifyVersion(uint8 const* a, int32 aLength, Acore::Crypto::SH
if (!sConfigMgr->GetOption<bool>("StrictVersionCheck", false))
return true;
Acore::Crypto::SHA1::Digest zeros;
Acore::Crypto::SHA1::Digest const* versionHash = nullptr;
Acore::Crypto::SHA1::Digest zeros{};
Acore::Crypto::SHA1::Digest const* versionHash{ nullptr };
if (!isReconnect)
{
+1 -1
View File
@@ -37,7 +37,7 @@ void GuardAI::Reset()
me->CastSpell(me, 18950 /*SPELL_INVISIBILITY_AND_STEALTH_DETECTION*/, true);
}
void GuardAI::EnterEvadeMode()
void GuardAI::EnterEvadeMode(EvadeReason /*why*/)
{
if (!me->IsAlive())
{
+1 -1
View File
@@ -30,7 +30,7 @@ public:
static int Permissible(Creature const* creature);
void Reset() override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/) override;
void JustDied(Unit* killer) override;
};
#endif
+4 -4
View File
@@ -26,7 +26,7 @@ NullCreatureAI::NullCreatureAI(Creature* c) : CreatureAI(c) { me->SetReactState(
void PassiveAI::UpdateAI(uint32)
{
if (me->IsInCombat() && me->getAttackers().empty())
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_NO_HOSTILES);
}
void PossessedAI::AttackStart(Unit* target)
@@ -66,11 +66,11 @@ void CritterAI::DamageTaken(Unit*, uint32&, DamageEffectType, SpellSchoolMask)
_combatTimer = 1;
}
void CritterAI::EnterEvadeMode()
void CritterAI::EnterEvadeMode(EvadeReason why)
{
if (me->HasUnitState(UNIT_STATE_FLEEING))
me->SetControlled(false, UNIT_STATE_FLEEING);
CreatureAI::EnterEvadeMode();
CreatureAI::EnterEvadeMode(why);
_combatTimer = 0;
}
@@ -80,7 +80,7 @@ void CritterAI::UpdateAI(uint32 diff)
{
_combatTimer += diff;
if (_combatTimer >= 5000)
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
}
}
+3 -3
View File
@@ -41,7 +41,7 @@ public:
void MoveInLineOfSight(Unit*) override {}
void AttackStart(Unit* target) override;
void UpdateAI(uint32) override;
void EnterEvadeMode() override {}
void EnterEvadeMode(EvadeReason /*why*/) override {}
void JustDied(Unit*) override;
void KilledUnit(Unit* victim) override;
@@ -57,7 +57,7 @@ public:
void MoveInLineOfSight(Unit*) override {}
void AttackStart(Unit*) override {}
void UpdateAI(uint32) override {}
void EnterEvadeMode() override {}
void EnterEvadeMode(EvadeReason /*why*/) override {}
void OnCharmed(bool /*apply*/) override {}
static int Permissible(Creature const*) { return PERMIT_BASE_IDLE; }
@@ -69,7 +69,7 @@ public:
explicit CritterAI(Creature* c) : PassiveAI(c) { _combatTimer = 0; }
void DamageTaken(Unit* /*done_by*/, uint32& /*damage*/, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason why) override;
void UpdateAI(uint32) override;
// Xinef: Added
+2 -1
View File
@@ -64,7 +64,8 @@ public:
//
void MoveInLineOfSight(Unit* /*who*/) override {} // CreatureAI interferes with returning pets
void MoveInLineOfSight_Safe(Unit* /*who*/) {} // CreatureAI interferes with returning pets
void EnterEvadeMode() override {} // For fleeing, pets don't use this type of Evade mechanic
void EnterEvadeMode(EvadeReason /*why*/) override {} // For fleeing, pets don't use this type of Evade mechanic
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override;
void PetStopAttack() override;
+1 -1
View File
@@ -50,7 +50,7 @@ void TotemAI::MoveInLineOfSight(Unit* /*who*/)
{
}
void TotemAI::EnterEvadeMode()
void TotemAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->CombatStop(true);
}
+3 -1
View File
@@ -31,8 +31,10 @@ public:
void MoveInLineOfSight(Unit* who) override;
void AttackStart(Unit* victim) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/) override;
void SpellHit(Unit* /*caster*/, SpellInfo const* /*spellInfo*/) override;
void DoAction(int32 param) override;
void UpdateAI(uint32 diff) override;
+43 -3
View File
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AreaBoundary.h"
#include "CreatureAI.h"
#include "Creature.h"
#include "CreatureAIImpl.h"
@@ -24,6 +25,7 @@
#include "MapReference.h"
#include "Player.h"
#include "Vehicle.h"
#include "Language.h"
class PhasedRespawn : public BasicEvent
{
@@ -196,9 +198,9 @@ void CreatureAI::TriggerAlert(Unit const* who) const
me->GetMotionMaster()->MoveDistract(5 * IN_MILLISECONDS);
}
void CreatureAI::EnterEvadeMode()
void CreatureAI::EnterEvadeMode(EvadeReason why)
{
if (!_EnterEvadeMode())
if (!_EnterEvadeMode(why))
return;
LOG_DEBUG("entities.unit", "Creature {} enters evade mode.", me->GetEntry());
@@ -290,7 +292,7 @@ bool CreatureAI::UpdateVictim()
return true;
}
bool CreatureAI::_EnterEvadeMode()
bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
{
if (!me->IsAlive())
{
@@ -357,6 +359,44 @@ void CreatureAI::MoveBackwardsChecks() {
me->GetMotionMaster()->MoveBackwards(victim, moveDist);
}
bool CreatureAI::IsInBoundary(Position const* who) const
{
if (!_boundary)
return true;
if (!who)
who = me;
return (CreatureAI::IsInBounds(*_boundary, who) != _negateBoundary);
}
bool CreatureAI::IsInBounds(CreatureBoundary const& boundary, Position const* pos)
{
for (AreaBoundary const* areaBoundary : boundary)
if (!areaBoundary->IsWithinBoundary(pos))
return false;
return true;
}
bool CreatureAI::CheckInRoom()
{
if (IsInBoundary())
return true;
else
{
EnterEvadeMode(EVADE_REASON_BOUNDARY);
return false;
}
}
void CreatureAI::SetBoundary(CreatureBoundary const* boundary, bool negateBoundaries /*= false*/)
{
_boundary = boundary;
_negateBoundary = negateBoundaries;
me->DoImmediateBoundaryCheck();
}
Creature* CreatureAI::DoSummon(uint32 entry, const Position& pos, uint32 despawnTime, TempSummonType summonType)
{
return me->SummonCreature(entry, pos, summonType, despawnTime);
+26 -4
View File
@@ -18,6 +18,7 @@
#ifndef ACORE_CREATUREAI_H
#define ACORE_CREATUREAI_H
#include "AreaBoundary.h"
#include "Common.h"
#include "Creature.h"
#include "UnitAI.h"
@@ -29,6 +30,8 @@ class Creature;
class Player;
class SpellInfo;
typedef std::vector<AreaBoundary const*> CreatureBoundary;
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
@@ -78,10 +81,19 @@ protected:
Creature* DoSummon(uint32 entry, Position const& pos, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
Creature* DoSummon(uint32 entry, WorldObject* obj, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
Creature* DoSummonFlyer(uint32 entry, WorldObject* obj, float flightZ, float radius = 5.0f, uint32 despawnTime = 30000, TempSummonType summonType = TEMPSUMMON_CORPSE_TIMED_DESPAWN);
public:
// EnumUtils: DESCRIBE THIS
enum EvadeReason
{
EVADE_REASON_NO_HOSTILES, // the creature's threat list is empty
EVADE_REASON_BOUNDARY, // the creature has moved outside its evade boundary
EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet
EVADE_REASON_OTHER
};
void Talk(uint8 id, WorldObject const* whisperTarget = nullptr);
explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), m_MoveInLineOfSight_locked(false) {}
explicit CreatureAI(Creature* creature) : UnitAI(creature), me(creature), _boundary(nullptr), _negateBoundary(false), m_MoveInLineOfSight_locked(false) { }
~CreatureAI() override {}
@@ -100,7 +112,7 @@ public:
virtual bool CanRespawn() { return true; }
// Called for reaction at stopping attack at no attackers or targets
virtual void EnterEvadeMode();
virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
// Called for reaction at enter to combat if not in combat yet (enemy can be nullptr)
virtual void EnterCombat(Unit* /*victim*/) {}
@@ -187,10 +199,20 @@ public:
virtual void PetStopAttack() { }
// boundary system methods
virtual bool CheckInRoom();
CreatureBoundary const* GetBoundary() const { return _boundary; }
void SetBoundary(CreatureBoundary const* boundary, bool negativeBoundaries = false);
static bool IsInBounds(CreatureBoundary const& boundary, Position const* who);
bool IsInBoundary(Position const* who = nullptr) const;
protected:
virtual void MoveInLineOfSight(Unit* /*who*/);
bool _EnterEvadeMode();
bool _EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
CreatureBoundary const* _boundary;
bool _negateBoundary;
private:
bool m_MoveInLineOfSight_locked;
@@ -15,6 +15,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AreaBoundary.h"
#include "ScriptedCreature.h"
#include "Cell.h"
#include "CellImpl.h"
@@ -171,7 +172,6 @@ bool SummonList::IsAnyCreatureInCombat() const
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
me(creature),
IsFleeing(false),
_evadeCheckCooldown(2500),
_isCombatMovementAllowed(true)
{
_isHeroic = me->GetMap()->IsHeroic();
@@ -489,23 +489,6 @@ enum eNPCs
NPC_FREYA = 32906,
};
bool ScriptedAI::EnterEvadeIfOutOfCombatArea()
{
if (me->IsInEvadeMode() || !me->IsInCombat())
return false;
if (_evadeCheckCooldown == GameTime::GetGameTime().count())
return false;
_evadeCheckCooldown = GameTime::GetGameTime().count();
if (!CheckEvadeIfOutOfCombatArea())
return false;
EnterEvadeMode();
return true;
}
Player* ScriptedAI::SelectTargetFromPlayerList(float maxdist, uint32 excludeAura, bool mustBeInLOS) const
{
Map::PlayerList const& pList = me->GetMap()->GetPlayers();
@@ -531,9 +514,10 @@ Player* ScriptedAI::SelectTargetFromPlayerList(float maxdist, uint32 excludeAura
BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature),
instance(creature->GetInstanceScript()),
summons(creature),
_boundary(instance ? instance->GetBossBoundary(bossId) : nullptr),
_bossId(bossId)
{
if (instance)
SetBoundary(instance->GetBossBoundary(bossId));
}
void BossAI::_Reset()
@@ -583,59 +567,10 @@ void BossAI::TeleportCheaters()
ThreatContainer::StorageType threatList = me->getThreatMgr().getThreatList();
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
if (Unit* target = (*itr)->getTarget())
if (target->GetTypeId() == TYPEID_PLAYER && !CheckBoundary(target))
if (target->GetTypeId() == TYPEID_PLAYER && !IsInBoundary(target))
target->NearTeleportTo(x, y, z, 0);
}
bool BossAI::CheckBoundary(Unit* who)
{
if (!GetBoundary() || !who)
return true;
for (BossBoundaryMap::const_iterator itr = GetBoundary()->begin(); itr != GetBoundary()->end(); ++itr)
{
switch (itr->first)
{
case BOUNDARY_N:
if (who->GetPositionX() > itr->second)
return false;
break;
case BOUNDARY_S:
if (who->GetPositionX() < itr->second)
return false;
break;
case BOUNDARY_E:
if (who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_W:
if (who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_NW:
if (who->GetPositionX() + who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SE:
if (who->GetPositionX() + who->GetPositionY() < itr->second)
return false;
break;
case BOUNDARY_NE:
if (who->GetPositionX() - who->GetPositionY() > itr->second)
return false;
break;
case BOUNDARY_SW:
if (who->GetPositionX() - who->GetPositionY() < itr->second)
return false;
break;
default:
break;
}
}
return true;
}
void BossAI::JustSummoned(Creature* summon)
{
summons.Summon(summon);
@@ -344,7 +344,6 @@ struct ScriptedAI : public CreatureAI
void SetCombatMovement(bool allowMovement);
bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; }
bool EnterEvadeIfOutOfCombatArea();
virtual bool CheckEvadeIfOutOfCombatArea() const { return false; }
// return true for heroic mode. i.e.
@@ -416,7 +415,6 @@ struct ScriptedAI : public CreatureAI
private:
Difficulty _difficulty;
uint32 _evadeCheckCooldown;
bool _isCombatMovementAllowed;
bool _isHeroic;
};
@@ -428,7 +426,6 @@ public:
~BossAI() override {}
InstanceScript* const instance;
BossBoundaryMap const* GetBoundary() const { return _boundary; }
void JustSummoned(Creature* summon) override;
void SummonedCreatureDespawn(Creature* summon) override;
@@ -453,23 +450,12 @@ protected:
void _JustDied();
void _JustReachedHome() { me->setActive(false); }
bool CheckInRoom()
{
if (CheckBoundary(me))
return true;
EnterEvadeMode();
return false;
}
bool CheckBoundary(Unit* who);
void TeleportCheaters();
EventMap events;
SummonList summons;
private:
BossBoundaryMap const* const _boundary;
uint32 const _bossId;
};
@@ -198,7 +198,7 @@ void npc_escortAI::ReturnToLastPoint()
me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, x, y, z);
}
void npc_escortAI::EnterEvadeMode()
void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->DeleteThreatList();
@@ -66,7 +66,7 @@ public:
void ReturnToLastPoint();
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
void UpdateAI(uint32 diff) override; //the "internal" update, calls UpdateEscortAI()
virtual void UpdateEscortAI(uint32 diff); //used when it's needed to add code in update (abilities, scripted events, etc)
@@ -150,7 +150,7 @@ void FollowerAI::JustRespawned()
Reset();
}
void FollowerAI::EnterEvadeMode()
void FollowerAI::EnterEvadeMode(EvadeReason /*why*/)
{
me->RemoveAllAuras();
me->DeleteThreatList();
@@ -46,7 +46,7 @@ public:
void MoveInLineOfSight(Unit*) override;
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override;
void JustDied(Unit*) override;
+1 -1
View File
@@ -618,7 +618,7 @@ void SmartAI::MovementInform(uint32 MovementType, uint32 Data)
MovepointReached(Data);
}
void SmartAI::EnterEvadeMode()
void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
{
// xinef: fixes strange jumps when charming SmartAI npc
if (!me->IsAlive() || me->IsInEvadeMode())
+1 -1
View File
@@ -80,7 +80,7 @@ public:
void EnterCombat(Unit* enemy) override;
// Called for reaction at stopping attack at no attackers or targets
void EnterEvadeMode() override;
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override;
// Called when the creature is killed
void JustDied(Unit* killer) override;
+73 -15
View File
@@ -105,7 +105,7 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3
if (eventType == SMART_EVENT_LINK)//special handling
continue;
if (eventType == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/)
if (eventType == e)
{
ConditionList conds = sConditionMgr->GetConditionsForSmartEvent((*i).entryOrGuid, (*i).event_id, (*i).source_type);
ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject(), me ? me->GetVictim() : nullptr);
@@ -1496,6 +1496,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
unitTarget->AttackStop();
}
}
delete targets;
break;
}
case SMART_ACTION_SUMMON_CREATURE:
@@ -1584,7 +1586,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
z += e.target.z;
o += e.target.o;
if (!e.action.summonGO.targetsummon)
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, x, y, z, o, 0, 0, 0, 0, e.action.summonGO.despawnTime);
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, x, y, z, o, 0, 0, 0, 0, e.action.summonGO.despawnTime, GOSummonType(e.action.summonGO.summonType));
else
(*itr)->SummonGameObject(e.action.summonGO.entry, GetBaseObject()->GetPositionX(), GetBaseObject()->GetPositionY(), GetBaseObject()->GetPositionZ(), GetBaseObject()->GetOrientation(), 0, 0, 0, 0, e.action.summonGO.despawnTime);
}
@@ -1595,7 +1597,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.GetTargetType() != SMART_TARGET_POSITION)
break;
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, e.target.x, e.target.y, e.target.z, e.target.o, 0, 0, 0, 0, e.action.summonGO.despawnTime);
GetBaseObject()->SummonGameObject(e.action.summonGO.entry, e.target.x, e.target.y, e.target.z, e.target.o, 0, 0, 0, 0, e.action.summonGO.despawnTime, GOSummonType(e.action.summonGO.summonType));
break;
}
case SMART_ACTION_KILL_UNIT:
@@ -3561,48 +3563,48 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_HOSTILE_SECOND_AGGRO:
if (me)
{
if (e.target.hostilRandom.powerType)
if (e.target.hostileRandom.powerType)
{
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly)))
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
l->push_back(u);
}
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly))
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MaxThreat, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))
l->push_back(u);
}
break;
case SMART_TARGET_HOSTILE_LAST_AGGRO:
if (me)
{
if (e.target.hostilRandom.powerType)
if (e.target.hostileRandom.powerType)
{
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly)))
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
l->push_back(u);
}
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly))
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::MinThreat, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))
l->push_back(u);
}
break;
case SMART_TARGET_HOSTILE_RANDOM:
if (me)
{
if (e.target.hostilRandom.powerType)
if (e.target.hostileRandom.powerType)
{
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly)))
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
l->push_back(u);
}
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly))
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 0, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))
l->push_back(u);
}
break;
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP:
if (me)
{
if (e.target.hostilRandom.powerType)
if (e.target.hostileRandom.powerType)
{
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly)))
if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, PowerUsersSelector(me, Powers(e.target.hostileRandom.powerType - 1), (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly)))
l->push_back(u);
}
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, (float)e.target.hostilRandom.maxDist, e.target.hostilRandom.playerOnly))
else if (Unit* u = me->AI()->SelectTarget(SelectTargetMethod::Random, 1, (float)e.target.hostileRandom.maxDist, e.target.hostileRandom.playerOnly))
l->push_back(u);
}
break;
@@ -4456,6 +4458,16 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
ProcessAction(e, unit, var0, var1);
break;
}
case SMART_EVENT_EVENT_PHASE_CHANGE:
{
if (!IsInPhase(e.event.eventPhaseChange.phasemask))
{
return;
}
ProcessAction(e, GetLastInvoker());
break;
}
case SMART_EVENT_GAME_EVENT_START:
case SMART_EVENT_GAME_EVENT_END:
{
@@ -5063,6 +5075,12 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry)
return;
}
// Do NOT allow to start a new actionlist if a previous one is already running. We need to always finish the current actionlist
if (!mTimedActionList.empty())
{
return;
}
mTimedActionList.clear();
mTimedActionList = sSmartScriptMgr->GetScript(entry, SMART_SCRIPT_TYPE_TIMED_ACTIONLIST);
if (mTimedActionList.empty())
@@ -5092,3 +5110,43 @@ Unit* SmartScript::GetLastInvoker(Unit* invoker)
return ObjectAccessor::GetUnit(*invoker, mLastInvoker);
return nullptr;
}
void SmartScript::IncPhase(uint32 p)
{
// protect phase from overflowing
SetPhase(std::min<uint32>(SMART_EVENT_PHASE_12, mEventPhase + p));
}
void SmartScript::DecPhase(uint32 p)
{
if (p >= mEventPhase)
{
SetPhase(0);
}
else
{
SetPhase(mEventPhase - p);
}
}
void SmartScript::SetPhase(uint32 p)
{
uint32 oldPhase = mEventPhase;
mEventPhase = p;
if (oldPhase != mEventPhase)
{
ProcessEventsFor(SMART_EVENT_EVENT_PHASE_CHANGE);
}
}
bool SmartScript::IsInPhase(uint32 p) const
{
if (mEventPhase == 0)
{
return false;
}
return ((1 << (mEventPhase - 1)) & p) != 0;
}
+4 -20
View File
@@ -258,26 +258,10 @@ public:
void SetPhaseReset(bool allow) { _allowPhaseReset = allow; }
private:
void IncPhase(uint32 p)
{
// Xinef: protect phase from overflowing
mEventPhase = std::min<uint32>(SMART_EVENT_PHASE_12, mEventPhase + p);
}
void DecPhase(uint32 p)
{
if (p >= mEventPhase)
mEventPhase = 0;
else
mEventPhase -= p;
}
bool IsInPhase(uint32 p) const
{
if (mEventPhase == 0)
return false;
return (1 << (mEventPhase - 1)) & p;
}
void SetPhase(uint32 p = 0) { mEventPhase = p; }
void IncPhase(uint32 p);
void DecPhase(uint32 p);
void SetPhase(uint32 p);
bool IsInPhase(uint32 p) const;
SmartAIEventList mEvents;
SmartAIEventList mInstallEvents;
@@ -410,7 +410,7 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
case SMART_TARGET_HOSTILE_LAST_AGGRO:
case SMART_TARGET_HOSTILE_RANDOM:
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.hostilRandom.playerOnly);
AC_SAI_IS_BOOLEAN_VALID(e, e.target.hostileRandom.playerOnly);
break;
case SMART_TARGET_FARTHEST:
AC_SAI_IS_BOOLEAN_VALID(e, e.target.farthest.playerOnly);
@@ -528,7 +528,7 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_JUST_CREATED: return NO_PARAMS;
case SMART_EVENT_GOSSIP_HELLO: return sizeof(SmartEvent::gossipHello);
case SMART_EVENT_FOLLOW_COMPLETED: return NO_PARAMS;
// case SMART_EVENT_EVENT_PHASE_CHANGE: return sizeof(SmartEvent::eventPhaseChange);
case SMART_EVENT_EVENT_PHASE_CHANGE: return sizeof(SmartEvent::eventPhaseChange);
case SMART_EVENT_IS_BEHIND_TARGET: return sizeof(SmartEvent::behindTarget);
case SMART_EVENT_GAME_EVENT_START: return sizeof(SmartEvent::gameEvent);
case SMART_EVENT_GAME_EVENT_END: return sizeof(SmartEvent::gameEvent);
@@ -756,10 +756,10 @@ bool SmartAIMgr::CheckUnusedTargetParams(SmartScriptHolder const& e)
case SMART_TARGET_NONE: return NO_PARAMS;
case SMART_TARGET_SELF: return NO_PARAMS;
case SMART_TARGET_VICTIM: return NO_PARAMS;
case SMART_TARGET_HOSTILE_SECOND_AGGRO: return sizeof(SmartTarget::hostilRandom);
case SMART_TARGET_HOSTILE_LAST_AGGRO: return sizeof(SmartTarget::hostilRandom);
case SMART_TARGET_HOSTILE_RANDOM: return sizeof(SmartTarget::hostilRandom);
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP: return sizeof(SmartTarget::hostilRandom);
case SMART_TARGET_HOSTILE_SECOND_AGGRO: return sizeof(SmartTarget::hostileRandom);
case SMART_TARGET_HOSTILE_LAST_AGGRO: return sizeof(SmartTarget::hostileRandom);
case SMART_TARGET_HOSTILE_RANDOM: return sizeof(SmartTarget::hostileRandom);
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP: return sizeof(SmartTarget::hostileRandom);
case SMART_TARGET_ACTION_INVOKER: return NO_PARAMS;
case SMART_TARGET_POSITION: return NO_PARAMS; //uses x,y,z,o
case SMART_TARGET_CREATURE_RANGE: return sizeof(SmartTarget::unitRange);
@@ -1076,6 +1076,27 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
}
break;
}
case SMART_EVENT_EVENT_PHASE_CHANGE:
{
if (!e.event.eventPhaseChange.phasemask)
{
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} has no param set, event won't be executed!.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
return false;
}
if (e.event.eventPhaseChange.phasemask > SMART_EVENT_PHASE_ALL)
{
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses invalid phasemask {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.eventPhaseChange.phasemask);
return false;
}
if (e.event.event_phase_mask && !(e.event.event_phase_mask & e.event.eventPhaseChange.phasemask))
{
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses event phasemask {} and incompatible event_param1 {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.event_phase_mask, e.event.eventPhaseChange.phasemask);
return false;
}
break;
}
case SMART_EVENT_IS_BEHIND_TARGET:
if (!IsMinMaxValid(e, e.event.behindTarget.cooldownMin, e.event.behindTarget.cooldownMax))
return false;
@@ -170,7 +170,7 @@ enum SMART_EVENT
SMART_EVENT_JUST_CREATED = 63, // none
SMART_EVENT_GOSSIP_HELLO = 64, // event_para_1 (only) 0 = no filter set, always execute action, 1 = GossipHello only filter set, skip action if reportUse, 2 = reportUse only filter set, skip action if GossipHello
SMART_EVENT_FOLLOW_COMPLETED = 65, // none
SMART_EVENT_UNUSED_66 = 66, // UNUSED
SMART_EVENT_EVENT_PHASE_CHANGE = 66, // event phase mask (<= SMART_EVENT_PHASE_ALL)
SMART_EVENT_IS_BEHIND_TARGET = 67, // cooldownMin, CooldownMax
SMART_EVENT_GAME_EVENT_START = 68, // game_event.Entry
SMART_EVENT_GAME_EVENT_END = 69, // game_event.Entry
@@ -376,6 +376,17 @@ struct SmartEvent
uint32 action;
} gossip;
struct
{
uint32 spell;
uint32 effIndex;
} dummy;
struct
{
uint32 phasemask;
} eventPhaseChange;
struct
{
uint32 cooldownMin;
@@ -923,6 +934,7 @@ struct SmartAction
uint32 entry;
uint32 despawnTime;
uint32 targetsummon;
uint32 summonType;
} summonGO;
struct
@@ -1410,7 +1422,7 @@ struct SmartTarget
uint32 maxDist;
SAIBool playerOnly;
uint32 powerType;
} hostilRandom;
} hostileRandom;
struct
{
@@ -1677,7 +1689,7 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] =
{SMART_EVENT_JUST_CREATED, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_GOSSIP_HELLO, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_FOLLOW_COMPLETED, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_UNUSED_66, 0},
{SMART_EVENT_EVENT_PHASE_CHANGE, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_IS_BEHIND_TARGET, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_GAME_EVENT_START, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_GAME_EVENT_END, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
@@ -16,6 +16,7 @@
*/
#include "BattlegroundAV.h"
#include "CreatureTextMgr.h"
#include "Formulas.h"
#include "GameEventMgr.h"
#include "GameGraveyard.h"
@@ -391,9 +392,13 @@ void BattlegroundAV::PostUpdateImpl(uint32 diff)
for (uint8 i = 0; i <= 1; i++) //0=alliance, 1=horde
{
if (!m_CaptainAlive[i])
{
continue;
}
if (m_CaptainBuffTimer[i] > diff)
{
m_CaptainBuffTimer[i] -= diff;
}
else
{
if (i == 0)
@@ -401,14 +406,20 @@ void BattlegroundAV::PostUpdateImpl(uint32 diff)
CastSpellOnTeam(AV_BUFF_A_CAPTAIN, TEAM_ALLIANCE);
Creature* creature = GetBGCreature(AV_CPLACE_MAX + 61);
if (creature)
YellToAll(creature, LANG_BG_AV_A_CAPTAIN_BUFF, LANG_COMMON);
{
std::string creatureText = sCreatureTextMgr->GetLocalizedChatString(creature->GetEntry(), creature->getGender(), 0, 0, DEFAULT_LOCALE);
YellToAll(creature, creatureText.c_str(), LANG_COMMON);
}
}
else
{
CastSpellOnTeam(AV_BUFF_H_CAPTAIN, TEAM_HORDE);
Creature* creature = GetBGCreature(AV_CPLACE_MAX + 59); //TODO: make the captains a dynamic creature
if (creature)
YellToAll(creature, LANG_BG_AV_H_CAPTAIN_BUFF, LANG_ORCISH);
{
std::string creatureText = sCreatureTextMgr->GetLocalizedChatString(creature->GetEntry(), creature->getGender(), 2, 0, DEFAULT_LOCALE);
YellToAll(creature, creatureText.c_str(), LANG_ORCISH);
}
}
m_CaptainBuffTimer[i] = 120000 + urand(0, 4) * 60000; //as far as i could see, the buff is randomly so i make 2minutes (thats the duration of the buff itself) + 0-4minutes TODO get the right times
}
@@ -729,7 +740,10 @@ void BattlegroundAV::ChangeMineOwner(uint8 mine, TeamId teamId, bool initial)
if (mine == AV_SOUTH_MINE) //i think this gets called all the time
{
if (Creature* creature = GetBGCreature(AV_CPLACE_MINE_S_3))
YellToAll(creature, LANG_BG_AV_S_MINE_BOSS_CLAIMS, LANG_UNIVERSAL);
{
std::string creatureText = sCreatureTextMgr->GetLocalizedChatString(creature->GetEntry(), creature->getGender(), 0, 0, DEFAULT_LOCALE);
YellToAll(creature, creatureText.c_str(), LANG_UNIVERSAL);
}
}
}
}
@@ -21,10 +21,6 @@
#include "Battleground.h"
#include "BattlegroundScore.h"
#define LANG_BG_AV_A_CAPTAIN_BUFF "Begone. Uncouth scum! The Alliance shall prevail in Alterac Valley!"
#define LANG_BG_AV_H_CAPTAIN_BUFF "Now is the time to attack! For the Horde!"
#define LANG_BG_AV_S_MINE_BOSS_CLAIMS "Snivvle is here! Snivvle claims the Coldtooth Mine!"
#define BG_AV_CAPTIME 240000 //4:00
#define BG_AV_SNOWFALL_FIRSTCAP 300000 //5:00 but i also have seen 4:05
+18 -18
View File
@@ -472,7 +472,7 @@ void ThreatMgr::modifyThreatPercent(Unit* victim, int32 percent)
//============================================================
Unit* ThreatMgr::getHostilTarget()
Unit* ThreatMgr::getHostileTarget()
{
iThreatContainer.update();
HostileReference* nextVictim = iThreatContainer.selectNextVictim(GetOwner()->ToCreature(), getCurrentVictim());
@@ -546,49 +546,49 @@ void ThreatMgr::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStatusCh
{
threatRefStatusChangeEvent->setThreatMgr(this); // now we can set the threat manager
HostileReference* hostilRef = threatRefStatusChangeEvent->getReference();
HostileReference* hostileRef = threatRefStatusChangeEvent->getReference();
switch (threatRefStatusChangeEvent->getType())
{
case UEV_THREAT_REF_THREAT_CHANGE:
if ((getCurrentVictim() == hostilRef && threatRefStatusChangeEvent->getFValue() < 0.0f) ||
(getCurrentVictim() != hostilRef && threatRefStatusChangeEvent->getFValue() > 0.0f))
if ((getCurrentVictim() == hostileRef && threatRefStatusChangeEvent->getFValue() < 0.0f) ||
(getCurrentVictim() != hostileRef && threatRefStatusChangeEvent->getFValue() > 0.0f))
setDirty(true); // the order in the threat list might have changed
break;
case UEV_THREAT_REF_ONLINE_STATUS:
if (!hostilRef->isOnline())
if (!hostileRef->isOnline())
{
if (hostilRef == getCurrentVictim())
if (hostileRef == getCurrentVictim())
{
setCurrentVictim(nullptr);
setDirty(true);
}
if (GetOwner() && GetOwner()->IsInWorld())
if (Unit* target = ObjectAccessor::GetUnit(*GetOwner(), hostilRef->getUnitGuid()))
if (Unit* target = ObjectAccessor::GetUnit(*GetOwner(), hostileRef->getUnitGuid()))
if (GetOwner()->IsInMap(target))
GetOwner()->SendRemoveFromThreatListOpcode(hostilRef);
iThreatContainer.remove(hostilRef);
iThreatOfflineContainer.addReference(hostilRef);
GetOwner()->SendRemoveFromThreatListOpcode(hostileRef);
iThreatContainer.remove(hostileRef);
iThreatOfflineContainer.addReference(hostileRef);
}
else
{
if (getCurrentVictim() && hostilRef->getThreat() > (1.1f * getCurrentVictim()->getThreat()))
if (getCurrentVictim() && hostileRef->getThreat() > (1.1f * getCurrentVictim()->getThreat()))
setDirty(true);
iThreatContainer.addReference(hostilRef);
iThreatOfflineContainer.remove(hostilRef);
iThreatContainer.addReference(hostileRef);
iThreatOfflineContainer.remove(hostileRef);
}
break;
case UEV_THREAT_REF_REMOVE_FROM_LIST:
if (hostilRef == getCurrentVictim())
if (hostileRef == getCurrentVictim())
{
setCurrentVictim(nullptr);
setDirty(true);
}
iOwner->SendRemoveFromThreatListOpcode(hostilRef);
if (hostilRef->isOnline())
iThreatContainer.remove(hostilRef);
iOwner->SendRemoveFromThreatListOpcode(hostileRef);
if (hostileRef->isOnline())
iThreatContainer.remove(hostileRef);
else
iThreatOfflineContainer.remove(hostilRef);
iThreatOfflineContainer.remove(hostileRef);
break;
}
}
+1 -1
View File
@@ -221,7 +221,7 @@ public:
[[nodiscard]] Unit* GetOwner() const { return iOwner; }
Unit* getHostilTarget();
Unit* getHostileTarget();
void tauntApply(Unit* taunter);
void tauntFadeOut(Unit* taunter);
+12 -1
View File
@@ -202,7 +202,7 @@ bool ForcedDespawnDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
}
Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(), m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipientGroup(0),
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f),
m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_wanderDistance(0.0f), m_boundaryCheckTime(2500),
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
@@ -689,6 +689,17 @@ void Creature::Update(uint32 diff)
SelectVictim();
}
// periodic check to see if the creature has passed an evade boundary
if (IsAIEnabled && !IsInEvadeMode() && IsInCombat())
{
if (diff >= m_boundaryCheckTime)
{
AI()->CheckInRoom();
m_boundaryCheckTime = 2500;
} else
m_boundaryCheckTime -= diff;
}
Unit* owner = GetCharmerOrOwner();
if (IsCharmed() && !IsWithinDistInMap(owner, GetMap()->GetVisibilityRange(), true, false))
{
@@ -285,6 +285,8 @@ public:
[[nodiscard]] float GetWanderDistance() const { return m_wanderDistance; }
void SetWanderDistance(float dist) { m_wanderDistance = dist; }
void DoImmediateBoundaryCheck() { m_boundaryCheckTime = 0; }
uint32 m_groupLootTimer; // (msecs)timer used for group loot
uint32 lootingGroupLowGUID; // used to find group which is looting corpse
@@ -401,6 +403,7 @@ protected:
uint32 m_respawnDelay; // (secs) delay between corpse disappearance and respawning
uint32 m_corpseDelay; // (secs) delay between death and corpse disappearance
float m_wanderDistance;
uint32 m_boundaryCheckTime; // (msecs) remaining time for next evade boundary check
uint16 m_transportCheckTimer;
uint32 lootPickPocketRestoreTime;
@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Define.h"
#include "Item.h"
#include "Define.h"
#include "SmartEnum.h"
#include <stdexcept>
+2 -2
View File
@@ -2304,7 +2304,7 @@ TempSummon* WorldObject::SummonCreature(uint32 entry, const Position& pos, TempS
return nullptr;
}
GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime, bool checkTransport)
GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime, bool checkTransport, GOSummonType summonType)
{
if (!IsInWorld())
return nullptr;
@@ -2330,7 +2330,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
if (respawnTime)
go->SetSpellId(1);
if (GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT) //not sure how to handle this
if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && summonType == GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)) //not sure how to handle this
ToUnit()->AddGameObject(go);
else
go->SetSpawnedByDefault(false);
+7 -1
View File
@@ -65,6 +65,12 @@ enum NotifyFlags
NOTIFY_ALL = 0xFF
};
enum GOSummonType
{
GO_SUMMON_TIMED_OR_CORPSE_DESPAWN = 0, // despawns after a specified time OR when the summoner dies
GO_SUMMON_TIMED_DESPAWN = 1 // despawns after a specified time
};
class WorldPacket;
class UpdateData;
class ByteBuffer;
@@ -516,7 +522,7 @@ public:
TempSummon* SummonCreature(uint32 id, const Position& pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0, SummonPropertiesEntry const* properties = nullptr) const;
TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, SummonPropertiesEntry const* properties = nullptr);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime, bool checkTransport = true);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime, bool checkTransport = true, GOSummonType summonType = GO_SUMMON_TIMED_OR_CORPSE_DESPAWN);
Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, bool setLevel = false, CreatureAI * (*GetAI)(Creature*) = nullptr);
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = nullptr);
+72 -18
View File
@@ -36,7 +36,9 @@
#include "PlayerSettings.h"
#include "PlayerTaxi.h"
#include "QuestDef.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "SpellInfo.h"
#include "TradeData.h"
#include "Unit.h"
#include "WorldSession.h"
@@ -2923,32 +2925,28 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& bas
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
return 0;
}
float totalmul = 1.0f;
int32 totalflat = 0;
// Drop charges for triggering spells instead of triggered ones
if (m_spellModTakingSpell)
spell = m_spellModTakingSpell;
for (auto mod : m_spellMods[op])
auto calculateSpellMod = [&](SpellModifier* mod)
{
// Charges can be set only for mods with auras
if (!mod->ownerAura)
ASSERT(mod->charges == 0);
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
continue;
// xinef: temporary pets cannot use charged mods of owner, needed for mirror image QQ they should use their own auras
if (temporaryPet && mod->charges != 0)
continue;
{
return;
}
if (mod->type == SPELLMOD_FLAT)
{
// xinef: do not allow to consume more than one 100% crit increasing spell
if (mod->op == SPELLMOD_CRITICAL_CHANCE && totalflat >= 100)
continue;
{
return;
}
totalflat += mod->value;
}
@@ -2956,32 +2954,88 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& bas
{
// skip percent mods for null basevalue (most important for spell mods with charges)
if (basevalue == T(0) || totalmul == 0.0f)
continue;
{
return;
}
// special case (skip > 10sec spell casts for instant cast setting)
if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
continue;
{
return;
}
// xinef: special exception for surge of light, dont affect crit chance if previous mods were not applied
else if (mod->op == SPELLMOD_CRITICAL_CHANCE && spell && !HasSpellMod(mod, spell))
continue;
{
return;
}
// xinef: special case for backdraft gcd reduce with backlast time reduction, dont affect gcd if cast time was not applied
else if (mod->op == SPELLMOD_GLOBAL_COOLDOWN && spell && !HasSpellMod(mod, spell))
continue;
{
return;
}
// xinef: those two mods should be multiplicative (Glyph of Renew)
if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT)
{
totalmul *= CalculatePct(1.0f, 100.0f + mod->value);
}
else
{
totalmul += CalculatePct(1.0f, mod->value);
}
}
DropModCharge(mod, spell);
};
// Drop charges for triggering spells instead of triggered ones
if (m_spellModTakingSpell)
{
spell = m_spellModTakingSpell;
}
SpellModifier* chargedMod = nullptr;
for (auto mod : m_spellMods[op])
{
// Charges can be set only for mods with auras
if (!mod->ownerAura)
{
ASSERT(!mod->charges);
}
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
{
continue;
}
if (mod->ownerAura->IsUsingCharges())
{
if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->SpellPriority < mod->ownerAura->GetSpellInfo()->SpellPriority))
{
chargedMod = mod;
}
continue;
}
calculateSpellMod(mod);
}
if (chargedMod)
{
calculateSpellMod(chargedMod);
}
float diff = 0.0f;
if (op == SPELLMOD_CASTING_TIME || op == SPELLMOD_DURATION)
{
diff = ((float)basevalue + totalflat) * (totalmul - 1.0f) + (float)totalflat;
}
else
{
diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat;
}
basevalue = T((float)basevalue + diff);
return T(diff);
}
@@ -1616,24 +1616,24 @@ QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver)
continue;
QuestStatus status = GetQuestStatus(questId);
if ((status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(questId)) || (quest->IsAutoComplete() && CanTakeQuest(quest, false)))
if (status == QUEST_STATUS_COMPLETE && !GetQuestRewardStatus(questId))
{
if (quest->IsRepeatable() || quest->IsDailyOrWeekly())
{
result2 = DIALOG_STATUS_REWARD_REP;
}
else
{
result2 = DIALOG_STATUS_REWARD;
}
result2 = DIALOG_STATUS_REWARD;
}
else if (status == QUEST_STATUS_INCOMPLETE)
{
result2 = DIALOG_STATUS_INCOMPLETE;
}
if (quest->IsAutoComplete() && CanTakeQuest(quest, false) && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
{
result2 = DIALOG_STATUS_REWARD_REP;
}
if (result2 > result)
{
result = result2;
}
}
for (QuestRelations::const_iterator i = qr.first; i != qr.second; ++i)
+38 -3
View File
@@ -14056,7 +14056,7 @@ void Unit::TauntFadeOut(Unit* taunter)
if (m_ThreatMgr.isThreatListEmpty())
{
if (creature->IsAIEnabled)
creature->AI()->EnterEvadeMode();
creature->AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES);
return;
}
@@ -14094,7 +14094,7 @@ Unit* Creature::SelectVictim()
if (CanHaveThreatList())
{
if (!target && !m_ThreatMgr.isThreatListEmpty())
target = m_ThreatMgr.getHostilTarget();
target = m_ThreatMgr.getHostileTarget();
}
else if (!HasReactState(REACT_PASSIVE))
{
@@ -14142,7 +14142,7 @@ Unit* Creature::SelectVictim()
for (Unit::AuraEffectList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr)
if ((*itr)->GetBase()->IsPermanent())
{
AI()->EnterEvadeMode();
AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_HOSTILES);
break;
}
return nullptr;
@@ -17916,6 +17916,8 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
// Set charmed
charmer->SetCharm(this, true);
StopAttackingInvalidTarget();
if (GetTypeId() == TYPEID_UNIT)
{
if (MovementGenerator* movementGenerator = GetMotionMaster()->GetMotionSlot(MOTION_SLOT_IDLE))
@@ -18080,6 +18082,8 @@ void Unit::RemoveCharmedBy(Unit* charmer)
charmer->SetCharm(this, false);
StopAttackingInvalidTarget();
Player* playerCharmer = charmer->ToPlayer();
if (playerCharmer)
{
@@ -19623,6 +19627,37 @@ void Unit::StopAttackFaction(uint32 faction_id)
(*itr)->StopAttackFaction(faction_id);
}
void Unit::StopAttackingInvalidTarget()
{
AttackerSet const& attackers = getAttackers();
for (AttackerSet::const_iterator itr = attackers.begin(); itr != attackers.end();)
{
Unit* attacker = (*itr);
if (!attacker->IsValidAttackTarget(this))
{
attacker->AttackStop();
if (attacker->GetTypeId() == TYPEID_PLAYER)
{
attacker->ToPlayer()->SendAttackSwingCancelAttack();
}
for (Unit* controled : attacker->m_Controlled)
{
if (controled->GetVictim() == this && !controled->IsValidAttackTarget(this))
{
controled->AttackStop();
}
}
itr = attackers.begin();
}
else
{
++itr;
}
}
}
void Unit::OutDebugInfo() const
{
LOG_ERROR("entities.unit", "Unit::OutDebugInfo");
+1
View File
@@ -1360,6 +1360,7 @@ public:
void CombatStop(bool includingCast = false);
void CombatStopWithPets(bool includingCast = false);
void StopAttackFaction(uint32 faction_id);
void StopAttackingInvalidTarget();
Unit* SelectNearbyTarget(Unit* exclude = nullptr, float dist = NOMINAL_MELEE_RANGE) const;
Unit* SelectNearbyNoTotemTarget(Unit* exclude = nullptr, float dist = NOMINAL_MELEE_RANGE) const;
void SendMeleeAttackStop(Unit* victim = nullptr);
@@ -15,9 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Unit.h"
#include "Define.h"
#include "SmartEnum.h"
#include "Unit.h"
#include <stdexcept>
namespace Acore::Impl::EnumUtilsImpl
+14 -23
View File
@@ -31,6 +31,12 @@
#include "Spell.h"
#include "WorldSession.h"
BossBoundaryData::~BossBoundaryData()
{
for (const_iterator it = begin(); it != end(); ++it)
delete it->boundary;
}
void InstanceScript::SaveToDB()
{
std::string data = GetSaveData();
@@ -120,6 +126,13 @@ bool InstanceScript::IsEncounterInProgress() const
return false;
}
void InstanceScript::LoadBossBoundaries(const BossBoundaryData& data)
{
for (BossBoundaryEntry const& entry : data)
if (entry.bossId < bosses.size())
bosses[entry.bossId].boundary.push_back(entry.boundary);
}
void InstanceScript::LoadMinionData(const MinionData* data)
{
while (data->entry)
@@ -137,7 +150,7 @@ void InstanceScript::LoadDoorData(const DoorData* data)
while (data->entry)
{
if (data->bossId < bosses.size())
doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type, BoundaryType(data->boundary))));
doors.insert(std::make_pair(data->entry, DoorInfo(&bosses[data->bossId], data->type)));
++data;
}
@@ -268,28 +281,6 @@ void InstanceScript::AddDoor(GameObject* door, bool add)
if (add)
{
data.bossInfo->door[data.type].insert(door);
switch (data.boundary)
{
default:
case BOUNDARY_NONE:
break;
case BOUNDARY_N:
case BOUNDARY_S:
data.bossInfo->boundary[data.boundary] = door->GetPositionX();
break;
case BOUNDARY_E:
case BOUNDARY_W:
data.bossInfo->boundary[data.boundary] = door->GetPositionY();
break;
case BOUNDARY_NW:
case BOUNDARY_SE:
data.bossInfo->boundary[data.boundary] = door->GetPositionX() + door->GetPositionY();
break;
case BOUNDARY_NE:
case BOUNDARY_SW:
data.bossInfo->boundary[data.boundary] = door->GetPositionX() - door->GetPositionY();
break;
}
}
else
data.bossInfo->door[data.type].erase(door);
+27 -25
View File
@@ -18,9 +18,11 @@
#ifndef ACORE_INSTANCE_DATA_H
#define ACORE_INSTANCE_DATA_H
#include "CreatureAI.h"
#include "ObjectMgr.h"
#include "World.h"
#include "ZoneScript.h"
#include <set>
#define OUT_SAVE_INST_DATA LOG_DEBUG("scripts.ai", "Saving Instance Data for Instance {} (Map {}, Instance Id {})", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_SAVE_INST_DATA_COMPLETE LOG_DEBUG("scripts.ai", "Saving Instance Data for Instance {} (Map {}, Instance Id {}) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
@@ -67,30 +69,30 @@ enum DoorType
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
{
uint32 entry, bossId;
DoorType type;
uint32 boundary;
};
struct BossBoundaryEntry
{
uint32 const bossId;
AreaBoundary const* const boundary;
};
struct BossBoundaryData
{
typedef std::vector<BossBoundaryEntry> StorageType;
typedef StorageType::const_iterator const_iterator;
BossBoundaryData(std::initializer_list<BossBoundaryEntry> data) : _data(data) { }
~BossBoundaryData();
const_iterator begin() const { return _data.begin(); }
const_iterator end() const { return _data.end(); }
private:
StorageType _data;
};
struct MinionData
@@ -110,16 +112,15 @@ struct BossInfo
EncounterState state;
DoorSet door[MAX_DOOR_TYPES];
MinionSet minion;
BossBoundaryMap boundary;
CreatureBoundary boundary;
};
struct DoorInfo
{
explicit DoorInfo(BossInfo* _bossInfo, DoorType _type, BoundaryType _boundary)
: bossInfo(_bossInfo), type(_type), boundary(_boundary) {}
explicit DoorInfo(BossInfo* _bossInfo, DoorType _type)
: bossInfo(_bossInfo), type(_type) { }
BossInfo* bossInfo;
DoorType type;
BoundaryType boundary;
};
struct MinionInfo
@@ -225,7 +226,7 @@ public:
virtual bool SetBossState(uint32 id, EncounterState state);
EncounterState GetBossState(uint32 id) const { return id < bosses.size() ? bosses[id].state : TO_BE_DECIDED; }
static std::string GetBossStateName(uint8 state);
BossBoundaryMap const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : nullptr; }
CreatureBoundary const* GetBossBoundary(uint32 id) const { return id < bosses.size() ? &bosses[id].boundary : nullptr; }
BossInfo const* GetBossInfo(uint32 id) const { return &bosses[id]; }
// Achievement criteria additional requirements check
@@ -255,6 +256,7 @@ public:
virtual void DoAction(int32 /*action*/) {}
protected:
void SetBossNumber(uint32 number) { bosses.resize(number); }
void LoadBossBoundaries(BossBoundaryData const& data);
void LoadDoorData(DoorData const* data);
void LoadMinionData(MinionData const* data);
void LoadObjectData(ObjectData const* creatureData, ObjectData const* gameObjectData);
+113
View File
@@ -0,0 +1,113 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) 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 Affero 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 <http://www.gnu.org/licenses/>.
*/
#include "AreaBoundary.h"
#include "Unit.h"
#include "TemporarySummon.h"
// ---== RECTANGLE ==---
RectangleBoundary::RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted) :
AreaBoundary(isInverted), _minX(southX), _maxX(northX), _minY(eastY), _maxY(westY) { }
bool RectangleBoundary::IsWithinBoundaryArea(Position const* pos) const
{
return !(
pos->GetPositionX() < _minX ||
pos->GetPositionX() > _maxX ||
pos->GetPositionY() < _minY ||
pos->GetPositionY() > _maxY
);
}
// ---== CIRCLE ==---
CircleBoundary::CircleBoundary(Position const& center, double radius, bool isInverted) :
AreaBoundary(isInverted), _center(center), _radiusSq(radius*radius) { }
CircleBoundary::CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted) :
AreaBoundary(isInverted), _center(center), _radiusSq(_center.GetDoubleExactDist2dSq(pointOnCircle)) { }
bool CircleBoundary::IsWithinBoundaryArea(Position const* pos) const
{
double offX = _center.GetDoublePositionX() - pos->GetPositionX();
double offY = _center.GetDoublePositionY() - pos->GetPositionY();
return offX * offX + offY * offY <= _radiusSq;
}
// ---== ELLIPSE ==---
EllipseBoundary::EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted) :
AreaBoundary(isInverted), _center(center), _radiusYSq(radiusY*radiusY), _scaleXSq(_radiusYSq / (radiusX*radiusX)) { }
bool EllipseBoundary::IsWithinBoundaryArea(Position const* pos) const
{
double offX = _center.GetDoublePositionX() - pos->GetPositionX();
double offY = _center.GetDoublePositionY() - pos->GetPositionY();
return (offX*offX)*_scaleXSq + (offY*offY) <= _radiusYSq;
}
// ---== TRIANGLE ==---
TriangleBoundary::TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted) :
AreaBoundary(isInverted), _a(pointA), _b(pointB), _c(pointC), _abx(_b.GetDoublePositionX()-_a.GetDoublePositionX()), _bcx(_c.GetDoublePositionX()-_b.GetDoublePositionX()), _cax(_a.GetDoublePositionX() - _c.GetDoublePositionX()), _aby(_b.GetDoublePositionY()-_a.GetDoublePositionY()), _bcy(_c.GetDoublePositionY()-_b.GetDoublePositionY()), _cay(_a.GetDoublePositionY() - _c.GetDoublePositionY()) { }
bool TriangleBoundary::IsWithinBoundaryArea(Position const* pos) const
{
// half-plane signs
bool sign1 = ((-_b.GetDoublePositionX() + pos->GetPositionX()) * _aby - (-_b.GetDoublePositionY() + pos->GetPositionY()) * _abx) < 0;
bool sign2 = ((-_c.GetDoublePositionX() + pos->GetPositionX()) * _bcy - (-_c.GetDoublePositionY() + pos->GetPositionY()) * _bcx) < 0;
bool sign3 = ((-_a.GetDoublePositionX() + pos->GetPositionX()) * _cay - (-_a.GetDoublePositionY() + pos->GetPositionY()) * _cax) < 0;
// if all signs are the same, the point is inside the triangle
return ((sign1 == sign2) && (sign2 == sign3));
}
// ---== PARALLELOGRAM ==---
ParallelogramBoundary::ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted) :
AreaBoundary(isInverted), _a(cornerA), _b(cornerB), _d(cornerD), _c(DoublePosition(_d.GetDoublePositionX() + (_b.GetDoublePositionX() - _a.GetDoublePositionX()), _d.GetDoublePositionY() + (_b.GetDoublePositionY() - _a.GetDoublePositionY()))), _abx(_b.GetDoublePositionX() - _a.GetDoublePositionX()), _dax(_a.GetDoublePositionX() - _d.GetDoublePositionX()), _aby(_b.GetDoublePositionY() - _a.GetDoublePositionY()), _day(_a.GetDoublePositionY() - _d.GetDoublePositionY()) { }
bool ParallelogramBoundary::IsWithinBoundaryArea(Position const* pos) const
{
// half-plane signs
bool sign1 = ((-_b.GetDoublePositionX() + pos->GetPositionX()) * _aby - (-_b.GetDoublePositionY() + pos->GetPositionY()) * _abx) < 0;
bool sign2 = ((-_a.GetDoublePositionX() + pos->GetPositionX()) * _day - (-_a.GetDoublePositionY() + pos->GetPositionY()) * _dax) < 0;
bool sign3 = ((-_d.GetDoublePositionY() + pos->GetPositionY()) * _abx - (-_d.GetDoublePositionX() + pos->GetPositionX()) * _aby) < 0; // AB = -CD
bool sign4 = ((-_c.GetDoublePositionY() + pos->GetPositionY()) * _dax - (-_c.GetDoublePositionX() + pos->GetPositionX()) * _day) < 0; // DA = -BC
// if all signs are equal, the point is inside
return ((sign1 == sign2) && (sign2 == sign3) && (sign3 == sign4));
}
// ---== Z RANGE ==---
ZRangeBoundary::ZRangeBoundary(float minZ, float maxZ, bool isInverted) :
AreaBoundary(isInverted), _minZ(minZ), _maxZ(maxZ) { }
bool ZRangeBoundary::IsWithinBoundaryArea(Position const* pos) const
{
return (_minZ <= pos->GetPositionZ() && pos->GetPositionZ() <= _maxZ);
}
// ---== UNION OF 2 BOUNDARIES ==---
BoundaryUnionBoundary::BoundaryUnionBoundary(AreaBoundary const* b1, AreaBoundary const* b2, bool isInverted) :
AreaBoundary(isInverted), _b1(b1), _b2(b2)
{
ASSERT(b1 && b2);
}
BoundaryUnionBoundary::~BoundaryUnionBoundary()
{
delete _b1;
delete _b2;
}
bool BoundaryUnionBoundary::IsWithinBoundaryArea(Position const* pos) const
{
return (_b1->IsWithinBoundary(pos) || _b2->IsWithinBoundary(pos));
}
+168
View File
@@ -0,0 +1,168 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) 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 Affero 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 <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_AREA_BOUNDARY_H
#define ACORE_AREA_BOUNDARY_H
#include "Position.h"
class AC_GAME_API AreaBoundary
{
public:
bool IsWithinBoundary(Position const* pos) const { return pos && (IsWithinBoundaryArea(pos) != _isInvertedBoundary); }
bool IsWithinBoundary(Position const& pos) const { return IsWithinBoundary(&pos); }
virtual ~AreaBoundary() { }
protected:
explicit AreaBoundary(bool isInverted) : _isInvertedBoundary(isInverted) { }
struct DoublePosition : Position
{
DoublePosition(double x = 0.0, double y = 0.0, double z = 0.0, float o = 0.0f)
: Position(float(x), float(y), float(z), o), DoublePosX(x), DoublePosY(y), DoublePosZ(z) { }
DoublePosition(float x, float y = 0.0f, float z = 0.0f, float o = 0.0f)
: Position(x, y, z, o), DoublePosX(x), DoublePosY(y), DoublePosZ(z) { }
DoublePosition(Position const& pos)
: Position(pos), DoublePosX(pos.m_positionX), DoublePosY(pos.m_positionY), DoublePosZ(pos.m_positionZ) { }
double GetDoublePositionX() const { return DoublePosX; }
double GetDoublePositionY() const { return DoublePosY; }
double GetDoublePositionZ() const { return DoublePosZ; }
double GetDoubleExactDist2dSq(DoublePosition const& pos) const
{
double const offX = GetDoublePositionX() - pos.GetDoublePositionX();
double const offY = GetDoublePositionY() - pos.GetDoublePositionY();
return (offX * offX) + (offY * offY);
}
Position* sync()
{
m_positionX = float(DoublePosX);
m_positionY = float(DoublePosY);
m_positionZ = float(DoublePosZ);
return this;
}
double DoublePosX;
double DoublePosY;
double DoublePosZ;
};
virtual bool IsWithinBoundaryArea(Position const* pos) const = 0;
private:
bool _isInvertedBoundary;
};
class AC_GAME_API RectangleBoundary : public AreaBoundary
{
public:
// X axis is north/south, Y axis is east/west, larger values are northwest
RectangleBoundary(float southX, float northX, float eastY, float westY, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
float const _minX, _maxX, _minY, _maxY;
};
class AC_GAME_API CircleBoundary : public AreaBoundary
{
public:
CircleBoundary(Position const& center, double radius, bool isInverted = false);
CircleBoundary(Position const& center, Position const& pointOnCircle, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
DoublePosition const _center;
double const _radiusSq;
};
class AC_GAME_API EllipseBoundary : public AreaBoundary
{
public:
EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
DoublePosition const _center;
double const _radiusYSq, _scaleXSq;
};
class AC_GAME_API TriangleBoundary : public AreaBoundary
{
public:
TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
DoublePosition const _a, _b, _c;
double const _abx, _bcx, _cax, _aby, _bcy, _cay;
};
class AC_GAME_API ParallelogramBoundary : public AreaBoundary
{
public:
// Note: AB must be orthogonal to AD
ParallelogramBoundary(Position const& cornerA, Position const& cornerB, Position const& cornerD, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
DoublePosition const _a, _b, _d, _c;
double const _abx, _dax, _aby, _day;
};
class AC_GAME_API ZRangeBoundary : public AreaBoundary
{
public:
ZRangeBoundary(float minZ, float maxZ, bool isInverted = false);
protected:
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
float const _minZ, _maxZ;
};
class AC_GAME_API BoundaryUnionBoundary : public AreaBoundary
{
public:
BoundaryUnionBoundary(AreaBoundary const* b1, AreaBoundary const* b2, bool isInverted = false);
protected:
virtual ~BoundaryUnionBoundary();
bool IsWithinBoundaryArea(Position const* pos) const override;
private:
AreaBoundary const* const _b1;
AreaBoundary const* const _b2;
};
#endif //ACORE_AREA_BOUNDARY_H
+2 -2
View File
@@ -1965,9 +1965,9 @@ inline LiquidData const GridMap::GetLiquidData(float x, float y, float z, float
if (delta > collisionHeight)
liquidData.Status = LIQUID_MAP_UNDER_WATER;
else if (delta > 0.2f)
else if (delta > 0.0f)
liquidData.Status = LIQUID_MAP_IN_WATER;
else if (delta > -0.2f)
else if (delta > -0.1f)
liquidData.Status = LIQUID_MAP_WATER_WALK;
else
liquidData.Status = LIQUID_MAP_ABOVE_WATER;
+1 -1
View File
@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Define.h"
#include "QuestDef.h"
#include "Define.h"
#include "SmartEnum.h"
#include <stdexcept>
+28 -4
View File
@@ -4495,13 +4495,25 @@ void Spell::SendSpellStart()
if (m_spellInfo->RuneCostID && m_spellInfo->PowerType == POWER_RUNE)
castFlags |= CAST_FLAG_NO_GCD; // not needed, but Blizzard sends it
PackedGuid realCasterGUID = m_caster->GetPackGUID();
if (TempSummon const* tempSummon = m_caster->ToTempSummon())
{
if (tempSummon->GetEntry() == WORLD_TRIGGER)
{
if (GameObject* casterGameobject = tempSummon->GetSummonerGameObject())
{
realCasterGUID = casterGameobject->GetPackGUID();
}
}
}
WorldPacket data(SMSG_SPELL_START, (8 + 8 + 4 + 4 + 2));
if (m_CastItem)
data << m_CastItem->GetPackGUID();
else
data << m_caster->GetPackGUID();
data << realCasterGUID;
data << m_caster->GetPackGUID();
data << realCasterGUID;
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
@@ -4581,14 +4593,26 @@ void Spell::SendSpellGo()
if (!m_spellInfo->StartRecoveryTime)
castFlags |= CAST_FLAG_NO_GCD;
PackedGuid realCasterGUID = m_caster->GetPackGUID();
if (TempSummon const* tempSummon = m_caster->ToTempSummon())
{
if (tempSummon->GetEntry() == WORLD_TRIGGER)
{
if (GameObject* casterGameobject = tempSummon->GetSummonerGameObject())
{
realCasterGUID = casterGameobject->GetPackGUID();
}
}
}
WorldPacket data(SMSG_SPELL_GO, 150); // guess size
if (m_CastItem)
data << m_CastItem->GetPackGUID();
else
data << m_caster->GetPackGUID();
data << realCasterGUID;
data << m_caster->GetPackGUID();
data << realCasterGUID;
data << uint8(m_cast_count); // pending spell cast?
data << uint32(m_spellInfo->Id); // spellId
data << uint32(castFlags); // cast flags
-19
View File
@@ -3808,25 +3808,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
m_caster->CastSpell(unitTarget, 22682, true);
return;
}
// Mirren's Drinking Hat
case 29830:
{
uint32 itemId = 23586; // Aerie Peak Pale Ale
switch (urand(0, 5))
{
case 0:
case 1:
case 2:
itemId = 23584;
break; // Loch Modan Lager
case 3:
case 4:
itemId = 23585;
break; // Stouthammer Lite
}
DoCreateItem(effIndex, itemId);
break;
}
case 20589: // Escape artist
case 30918: // Improved Sprint
{
+1
View File
@@ -831,6 +831,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
SpellVisual = spellEntry->SpellVisual;
SpellIconID = spellEntry->SpellIconID;
ActiveIconID = spellEntry->ActiveIconID;
SpellPriority = spellEntry->SpellPriority;
SpellName = spellEntry->SpellName;
Rank = spellEntry->Rank;
MaxTargetLevel = spellEntry->MaxTargetLevel;
+1
View File
@@ -377,6 +377,7 @@ public:
std::array<uint32, 2> SpellVisual;
uint32 SpellIconID;
uint32 ActiveIconID;
uint32 SpellPriority;
std::array<char const*, 16> SpellName;
std::array<char const*, 16> Rank;
uint32 MaxTargetLevel;
@@ -244,7 +244,6 @@ void SpellMgr::LoadSpellInfoCorrections()
48108, // Hot Streak
51124, // Killing Machine
54741, // Firestarter
57761, // Fireball!
64823, // Item - Druid T8 Balance 4P Bonus
34477, // Misdirection
44401, // Missile Barrage
@@ -254,6 +253,13 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->ProcCharges = 1;
});
// Fireball
ApplySpellFix({ 57761 }, [](SpellInfo* spellInfo)
{
spellInfo->ProcCharges = 1;
spellInfo->SpellPriority = 50;
});
// Tidal Wave
ApplySpellFix({ 53390 }, [](SpellInfo* spellInfo)
{
@@ -15,9 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WardenCheckMgr.h"
#include "Define.h"
#include "SmartEnum.h"
#include "WardenCheckMgr.h"
#include <stdexcept>
namespace Acore::Impl::EnumUtilsImpl
+3 -3
View File
@@ -78,7 +78,7 @@ public:
{
{ "setbit", HandleDebugSet32BitCommand, SEC_ADMINISTRATOR, Console::No },
{ "threat", HandleDebugThreatListCommand, SEC_ADMINISTRATOR, Console::No },
{ "hostil", HandleDebugHostileRefListCommand, SEC_ADMINISTRATOR, Console::No },
{ "hostile", HandleDebugHostileRefListCommand, SEC_ADMINISTRATOR, Console::No },
{ "anim", HandleDebugAnimCommand, SEC_ADMINISTRATOR, Console::No },
{ "arena", HandleDebugArenaCommand, SEC_ADMINISTRATOR, Console::No },
{ "bg", HandleDebugBattlegroundCommand, SEC_ADMINISTRATOR, Console::No },
@@ -828,7 +828,7 @@ public:
HostileReference* ref = target->getHostileRefMgr().getFirst();
uint32 count = 0;
handler->PSendSysMessage("Hostil reference list of %s (%s)", target->GetName().c_str(), target->GetGUID().ToString().c_str());
handler->PSendSysMessage("Hostile reference list of %s (%s)", target->GetName().c_str(), target->GetGUID().ToString().c_str());
while (ref)
{
@@ -845,7 +845,7 @@ public:
ref = ref->next();
}
handler->SendSysMessage("End of hostil reference list.");
handler->SendSysMessage("End of hostile reference list.");
return true;
}
@@ -130,9 +130,9 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
// Evade boss
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
@@ -199,7 +199,7 @@ public:
Position const& _homePosition = me->GetHomePosition();
if (me->GetDistance2d(_homePosition.GetPositionX(), _homePosition.GetPositionY()) > 50.0f)
{
EnterEvadeMode();
ScriptedAI::EnterEvadeMode();
return;
}
events.ScheduleEvent(EVENT_CHECK_RESET, 5000);
@@ -99,9 +99,9 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
// Evade mini bosses
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
@@ -167,7 +167,7 @@ public:
{
if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50)
{
EnterEvadeMode();
ScriptedAI::EnterEvadeMode();
Talk(YELL_EVADE);
}
ResetTimer = 5 * IN_MILLISECONDS;
@@ -88,9 +88,9 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
// Evade mini bosses
if (BattlegroundMap* bgMap = me->GetMap()->ToBattlegroundMap())
@@ -149,7 +149,7 @@ public:
{
if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 50)
{
EnterEvadeMode();
ScriptedAI::EnterEvadeMode();
Talk(YELL_EVADE);
}
ResetTimer = 5 * IN_MILLISECONDS;
@@ -225,7 +225,7 @@ public:
me->GetMotionMaster()->MoveFollow(summoner, 0.f, 0.f);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (Creature* flamelasher = ObjectAccessor::GetCreature(*me, _flamelasherGUID))
{
@@ -200,7 +200,7 @@ public:
_events.ScheduleEvent(EVENT_SPELL_SUMMON_VOIDWALKERS, 1000);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->RemoveAllAuras();
me->DeleteThreatList();
@@ -76,10 +76,10 @@ public:
events.ScheduleEvent(EVENT_KNOCK_AWAY, urand(12000, 18000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void IsSummonedBy(Unit* /*summoner*/) override
@@ -164,11 +164,11 @@ public:
events.ScheduleEvent(EVENT_MORTAL_STRIKE, urand(17000, 19000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->SetBossState(DATA_WARCHIEF_REND_BLACKHAND, FAIL);
instance->SetBossState(DATA_GYTH, FAIL);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
me->DespawnOrUnsummon();
}
@@ -63,10 +63,10 @@ MinionData const minionData[] =
DoorData const doorData[] =
{
{ GO_GYTH_EXIT_DOOR, DATA_WARCHIEF_REND_BLACKHAND, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_DRAKKISATH_DOOR_1, DATA_GENERAL_DRAKKISATH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_DRAKKISATH_DOOR_2, DATA_GENERAL_DRAKKISATH, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_GYTH_EXIT_DOOR, DATA_WARCHIEF_REND_BLACKHAND, DOOR_TYPE_PASSAGE },
{ GO_DRAKKISATH_DOOR_1, DATA_GENERAL_DRAKKISATH, DOOR_TYPE_PASSAGE },
{ GO_DRAKKISATH_DOOR_2, DATA_GENERAL_DRAKKISATH, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM, } // END
};
class instance_blackrock_spire : public InstanceMapScript
@@ -242,11 +242,10 @@ public:
// Victor Nefarius weekly mechanic drakonid spawn
// Pick 2 drakonids and keep them for the whole save duration (the drakonids can't be repeated).
std::vector<uint32> nefarianDrakonidSpawners = { NPC_BLACK_SPAWNER, NPC_BLUE_SPAWNER, NPC_BRONZE_SPAWNER, NPC_GREEN_SPAWNER, NPC_RED_SPAWNER };
_nefarianRightTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
// delete the previous picked one so we don't get any repeated.
nefarianDrakonidSpawners.erase(std::remove(nefarianDrakonidSpawners.begin(), nefarianDrakonidSpawners.end(), _nefarianRightTunnel), nefarianDrakonidSpawners.end());
// Pick another one
_nefarianLeftTunnel = Acore::Containers::SelectRandomContainerElement(nefarianDrakonidSpawners);
Acore::Containers::RandomResize(nefarianDrakonidSpawners, 2);
_nefarianRightTunnel = nefarianDrakonidSpawners[0];
_nefarianLeftTunnel = nefarianDrakonidSpawners[1];
// save it to instance
instance->SetData(DATA_NEFARIAN_LEFT_TUNNEL, _nefarianLeftTunnel);
@@ -293,6 +292,23 @@ public:
Reset();
}
void JustSummoned(Creature* summon) override
{
if (summon->GetEntry() != NPC_NEFARIAN)
{
BossAI::JustSummoned(summon);
}
}
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
{
if (summon->GetEntry() == NPC_NEFARIAN)
{
summons.DespawnAll();
Unit::Kill(me, me);
}
}
void DoAction(int32 action) override
{
if (action == ACTION_RESET)
@@ -304,12 +320,26 @@ public:
if (action == ACTION_ADD_KILLED)
{
KilledAdds++;
}
if (action == ACTION_KILLED)
{
summons.DespawnEntry(NPC_BONE_CONSTRUCT);
Unit::Kill(me, me);
if (KilledAdds == MAX_DRAKONID_KILLED)
{
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.Reset();
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
// Stop spawning adds
EntryCheckPredicate pred(_nefarianRightTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred);
EntryCheckPredicate pred2(_nefarianLeftTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred2);
}
}
}
@@ -335,14 +365,11 @@ public:
events.ScheduleEvent(EVENT_SILENCE, urand(20000, 25000));
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(30000, 35000));
events.ScheduleEvent(EVENT_SPAWN_ADDS, 10000);
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 10000);
}
void JustSummoned(Creature* summon) override { summons.Summon(summon); }
void SetData(uint32 type, uint32 data) override
{
if ( type == 1 && data == 1)
if (type == 1 && data == 1)
{
me->StopMoving();
events.ScheduleEvent(EVENT_PATH_2, 9000);
@@ -428,8 +455,7 @@ public:
events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 19000, 25000);
break;
case EVENT_FEAR:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true))
DoCast(target, SPELL_FEAR);
DoCastRandomTarget(SPELL_FEAR, 0, 40.0f);
events.ScheduleEvent(EVENT_FEAR, urand(10000, 20000));
break;
case EVENT_SILENCE:
@@ -437,8 +463,7 @@ public:
events.ScheduleEvent(EVENT_SILENCE, urand(14000, 23000));
break;
case EVENT_MIND_CONTROL:
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40, true))
DoCast(target, SPELL_SHADOW_COMMAND);
DoCastRandomTarget(SPELL_SHADOW_COMMAND, 0, 40.0f);
events.ScheduleEvent(EVENT_MIND_CONTROL, urand(24000, 30000));
break;
case EVENT_SHADOWBLINK:
@@ -450,32 +475,6 @@ public:
me->SummonCreature(_nefarianLeftTunnel, spawnerPositions[0]);
me->SummonCreature(_nefarianRightTunnel, spawnerPositions[1]);
break;
case EVENT_CHECK_PHASE_2:
if (KilledAdds >= MAX_DRAKONID_KILLED)
{
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{
nefarian->setActive(true);
nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
}
events.CancelEvent(EVENT_MIND_CONTROL);
events.CancelEvent(EVENT_FEAR);
events.CancelEvent(EVENT_SHADOW_BOLT);
events.CancelEvent(EVENT_SHADOW_BOLT_VOLLEY);
events.CancelEvent(EVENT_SILENCE);
DoCastSelf(SPELL_ROOT_SELF, true);
me->SetVisible(false);
// Stop spawning adds
EntryCheckPredicate pred(_nefarianRightTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred);
EntryCheckPredicate pred2(_nefarianLeftTunnel);
summons.DoAction(ACTION_SPAWNER_STOP, pred2);
return;
}
events.ScheduleEvent(EVENT_CHECK_PHASE_2, 1000);
break;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
@@ -500,8 +499,6 @@ public:
me->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
me->SetStandState(UNIT_STAND_STATE_STAND);
me->SetUnitFlag(UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE);
// Due to Nefarius despawning himself on Vael, we need to update the guid on instance to prevent unwanted behaviours as encounter not resetting at all.
instance->SetGuidData(DATA_LORD_VICTOR_NEFARIUS, me->GetGUID());
}
}
@@ -556,14 +553,6 @@ struct boss_nefarian : public BossAI
{
_JustDied();
Talk(SAY_DEATH);
if (Creature* victor = me->FindNearestCreature(NPC_VICTOR_NEFARIUS, 200.f, true))
{
if (victor->AI())
{
victor->AI()->DoAction(ACTION_KILLED);
}
}
}
void KilledUnit(Unit* victim) override
@@ -620,6 +609,29 @@ struct boss_nefarian : public BossAI
_introDone = true;
}
void DamageTaken(Unit* /*unit*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
{
if (me->HealthBelowPctDamaged(20, damage) && !Phase3)
{
std::list<Creature*> constructList;
me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
for (Creature* const& summon : constructList)
{
if (summon && !summon->IsAlive())
{
summon->Respawn();
summon->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_AGGRESSIVE);
summon->SetStandState(UNIT_STAND_STATE_STAND);
DoZoneInCombat(summon);
}
}
Phase3 = true;
Talk(SAY_RAISE_SKELETONS);
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -734,27 +746,6 @@ struct boss_nefarian : public BossAI
}
}
// Phase3 begins when health below 20 pct
if (!Phase3 && HealthBelowPct(20))
{
std::list<Creature*> constructList;
me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f);
for (std::list<Creature*>::const_iterator itr = constructList.begin(); itr != constructList.end(); ++itr)
{
if ((*itr) && !(*itr)->IsAlive())
{
(*itr)->Respawn();
DoZoneInCombat((*itr));
(*itr)->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
(*itr)->SetReactState(REACT_AGGRESSIVE);
(*itr)->SetStandState(UNIT_STAND_STATE_STAND);
}
}
Phase3 = true;
Talk(SAY_RAISE_SKELETONS);
}
DoMeleeAttackIfReady();
}
@@ -818,17 +809,19 @@ struct npc_corrupted_totem : public ScriptedAI
return;
}
std::vector<uint32> mobsEntries;
mobsEntries.push_back(NPC_NEFARIAN);
mobsEntries.push_back(NPC_BONE_CONSTRUCT);
mobsEntries.push_back(NPC_BRONZE_DRAKONID);
mobsEntries.push_back(NPC_BLUE_DRAKONID);
mobsEntries.push_back(NPC_RED_DRAKONID);
mobsEntries.push_back(NPC_GREEN_DRAKONID);
mobsEntries.push_back(NPC_BLACK_DRAKONID);
mobsEntries.push_back(NPC_CHROMATIC_DRAKONID);
std::vector<uint32> mobsEntries =
{
NPC_NEFARIAN,
NPC_BONE_CONSTRUCT,
NPC_BRONZE_DRAKONID,
NPC_BLUE_DRAKONID,
NPC_RED_DRAKONID,
NPC_GREEN_DRAKONID,
NPC_BLACK_DRAKONID,
NPC_CHROMATIC_DRAKONID
};
for (auto& entry : mobsEntries)
for (auto const& entry : mobsEntries)
{
std::list<Creature*> tmpMobList;
GetCreatureListWithEntryInGrid(tmpMobList, me, entry, 100.f);
@@ -938,13 +931,15 @@ struct npc_drakonid_spawner : public ScriptedAI
}
}
void IsSummonedBy(Unit* /*summoner*/) override
void IsSummonedBy(Unit* summoner) override
{
DoCastSelf(SPELL_SPAWN_DRAKONID_GEN);
_scheduler.Schedule(10s, 60s, [this](TaskContext /*context*/)
{
DoCastSelf(SPELL_SPAWN_CHROMATIC_DRAKONID);
});
_owner = summoner->GetGUID();
}
void UpdateAI(uint32 diff) override
@@ -952,8 +947,44 @@ struct npc_drakonid_spawner : public ScriptedAI
_scheduler.Update(diff);
}
void SummonedCreatureDies(Creature* summon, Unit* /*unit*/) override
{
if (summon->GetEntry() != NPC_BONE_CONSTRUCT)
{
if (Creature* victor = ObjectAccessor::GetCreature(*me, _owner))
{
victor->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
}
ObjectGuid summonGuid = summon->GetGUID();
summon->SetCorpseDelay(DAY * IN_MILLISECONDS);
summon->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
summon->SetHomePosition(summon->GetPosition());
_scheduler.Schedule(1s, [this, summonGuid](TaskContext /*context*/)
{
if (Creature* construct = ObjectAccessor::GetCreature(*me, summonGuid))
{
construct->SetVisible(false);
}
}).Schedule(2s, [this, summonGuid](TaskContext /*context*/)
{
if (Creature* construct = ObjectAccessor::GetCreature(*me, summonGuid))
{
construct->UpdateEntry(NPC_BONE_CONSTRUCT);
construct->SetReactState(REACT_PASSIVE);
construct->SetStandState(UNIT_STAND_STATE_DEAD);
construct->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
construct->SetVisible(true);
}
});
}
}
protected:
TaskScheduler _scheduler;
ObjectGuid _owner;
};
std::unordered_map<uint32, uint8> const classCallSpells =
@@ -23,48 +23,49 @@
enum Say
{
SAY_EGGS_BROKEN1 = 0,
SAY_EGGS_BROKEN2 = 1,
SAY_EGGS_BROKEN3 = 2,
SAY_DEATH = 3,
SAY_EGGS_BROKEN1 = 0,
SAY_EGGS_BROKEN2 = 1,
SAY_EGGS_BROKEN3 = 2,
SAY_DEATH = 3,
EMOTE_TROOPS_RETREAT = 0
EMOTE_TROOPS_RETREAT = 0
};
enum Spells
{
SPELL_MINDCONTROL = 19832,
SPELL_EGG_DESTROY = 19873,
SPELL_MIND_EXHAUSTION = 23958,
SPELL_MINDCONTROL = 19832,
SPELL_MINDCONTROL_VISUAL = 45537,
SPELL_EGG_DESTROY = 19873,
SPELL_MIND_EXHAUSTION = 23958,
SPELL_CLEAVE = 19632,
SPELL_WARSTOMP = 24375,
SPELL_FIREBALLVOLLEY = 22425,
SPELL_CONFLAGRATION = 23023,
SPELL_CLEAVE = 19632,
SPELL_WARSTOMP = 24375,
SPELL_FIREBALLVOLLEY = 22425,
SPELL_CONFLAGRATION = 23023,
SPELL_EXPLODE_ORB = 20037,
SPELL_EXPLOSION = 20038, // Instakill everything.
SPELL_EXPLODE_ORB = 20037,
SPELL_EXPLOSION = 20038, // Instakill everything.
SPELL_WARMING_FLAMES = 23040,
SPELL_WARMING_FLAMES = 23040,
};
enum Summons
{
NPC_ELITE_DRACHKIN = 12422,
NPC_ELITE_WARRIOR = 12458,
NPC_WARRIOR = 12416,
NPC_MAGE = 12420,
NPC_WARLOCK = 12459,
NPC_ELITE_DRACHKIN = 12422,
NPC_ELITE_WARRIOR = 12458,
NPC_WARRIOR = 12416,
NPC_MAGE = 12420,
NPC_WARLOCK = 12459,
GO_EGG = 177807
GO_EGG = 177807
};
enum EVENTS
{
EVENT_CLEAVE = 1,
EVENT_STOMP = 2,
EVENT_FIREBALL = 3,
EVENT_CONFLAGRATION = 4
EVENT_CLEAVE = 1,
EVENT_STOMP = 2,
EVENT_FIREBALL = 3,
EVENT_CONFLAGRATION = 4
};
class boss_razorgore : public CreatureScript
@@ -161,12 +162,14 @@ public:
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
{
charmer->CastSpell(charmer, SPELL_MIND_EXHAUSTION, true);
charmer->CastSpell(me, SPELL_MINDCONTROL_VISUAL, false);
}
}
else
{
if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmerGUID))
{
charmer->RemoveAurasDueToSpell(SPELL_MINDCONTROL_VISUAL);
me->TauntApply(charmer);
}
}
@@ -31,22 +31,23 @@
DoorData const doorData[] =
{
{ GO_PORTCULLIS_RAZORGORE, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 175946 || GUID 7230
{ GO_PORTCULLIS_RAZORGORE_ROOM, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_ROOM, BOUNDARY_NONE}, // ID 176964 || GUID 75158
{ GO_PORTCULLIS_VAELASTRASZ, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 175185 || GUID 7229
{ GO_PORTCULLIS_BROODLORD, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179365 || GUID 75159
{ GO_PORTCULLIS_THREEDRAGONS, DATA_FIREMAW, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_THREEDRAGONS, DATA_EBONROC, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_THREEDRAGONS, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_CHROMAGGUS, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE}, // ID 179116 || GUID 75161
{ GO_PORTCULLIS_NEFARIAN, DATA_NEFARIAN, DOOR_TYPE_ROOM, BOUNDARY_NONE}, // ID 179117 || GUID 75164
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} // END
{ GO_PORTCULLIS_RAZORGORE, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE }, // ID 175946 || GUID 7230
{ GO_PORTCULLIS_RAZORGORE_ROOM, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_ROOM, }, // ID 176964 || GUID 75158
{ GO_PORTCULLIS_VAELASTRASZ, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE }, // ID 175185 || GUID 7229
{ GO_PORTCULLIS_BROODLORD, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE }, // ID 179365 || GUID 75159
{ GO_PORTCULLIS_THREEDRAGONS, DATA_FIREMAW, DOOR_TYPE_PASSAGE }, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_THREEDRAGONS, DATA_EBONROC, DOOR_TYPE_PASSAGE }, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_THREEDRAGONS, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE }, // ID 179115 || GUID 75165
{ GO_PORTCULLIS_CHROMAGGUS, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE }, // ID 179116 || GUID 75161
{ GO_PORTCULLIS_NEFARIAN, DATA_NEFARIAN, DOOR_TYPE_ROOM }, // ID 179117 || GUID 75164
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const creatureData[] =
{
{ NPC_GRETHOK, DATA_GRETHOK },
{ NPC_NEFARIAN_TROOPS, DATA_NEFARIAN_TROOPS }
{ NPC_GRETHOK, DATA_GRETHOK },
{ NPC_NEFARIAN_TROOPS, DATA_NEFARIAN_TROOPS },
{ NPC_VICTOR_NEFARIUS, DATA_LORD_VICTOR_NEFARIUS }
};
Position const SummonPosition[8] =
@@ -90,6 +91,12 @@ public:
void OnCreatureCreate(Creature* creature) override
{
// This is required because the tempspawn at Vael overwrites his GUID.
if (creature->GetEntry() == NPC_VICTOR_NEFARIUS && creature->ToTempSummon())
{
return;
}
InstanceScript::OnCreatureCreate(creature);
switch (creature->GetEntry())
@@ -127,26 +134,19 @@ public:
case NPC_NEFARIAN:
nefarianGUID = creature->GetGUID();
break;
case NPC_VICTOR_NEFARIUS:
victorNefariusGUID = creature->GetGUID();
break;
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID:
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
{
if (CreatureAI* nefariusAI = nefarius->AI())
{
nefariusAI->JustSummoned(creature);
}
}
if (creature->AI())
{
creature->AI()->DoZoneInCombat();
}
break;
default:
break;
@@ -281,14 +281,13 @@ public:
case DATA_NEFARIAN:
switch (state)
{
case FAIL:
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15 * 60 * IN_MILLISECONDS); //15min
[[fallthrough]];
case NOT_STARTED:
if (Creature* nefarian = instance->GetCreature(nefarianGUID))
nefarian->DespawnOrUnsummon();
break;
case FAIL:
_events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15 * 60 * IN_MILLISECONDS); //15min
SetBossState(DATA_NEFARIAN, NOT_STARTED);
break;
default:
break;
}
@@ -369,8 +368,6 @@ public:
{
case DATA_RAZORGORE_THE_UNTAMED:
return razorgoreGUID;
case DATA_LORD_VICTOR_NEFARIUS:
return victorNefariusGUID;
case DATA_CHROMAGGUS:
return chromaggusGUID;
case DATA_GO_CHROMAGGUS_DOOR:
@@ -382,58 +379,10 @@ public:
return ObjectGuid::Empty;
}
void SetGuidData(uint32 type, ObjectGuid data) override
{
switch (type)
{
case DATA_LORD_VICTOR_NEFARIUS:
victorNefariusGUID = data;
break;
default:
break;
}
}
void OnUnitDeath(Unit* unit) override
{
switch (unit->GetEntry())
{
case NPC_BLACK_DRAKONID:
case NPC_BLUE_DRAKONID:
case NPC_BRONZE_DRAKONID:
case NPC_CHROMATIC_DRAKONID:
case NPC_GREEN_DRAKONID:
case NPC_RED_DRAKONID:
if (Creature* summon = unit->ToTempSummon())
{
summon->SetCorpseDelay(DAY * IN_MILLISECONDS);
summon->UpdateEntry(NPC_BONE_CONSTRUCT);
summon->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
summon->SetReactState(REACT_PASSIVE);
summon->SetStandState(UNIT_STAND_STATE_DEAD);
summon->SetHomePosition(summon->GetPosition());
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
{
if (nefarius->AI())
{
nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
}
}
else // Something happened, try another way
{
if (Creature* nefarius = summon->FindNearestCreature(NPC_VICTOR_NEFARIUS, 500.f, true))
{
victorNefariusGUID = nefarius->GetGUID();
if (nefarius->AI())
{
nefarius->AI()->DoAction(ACTION_NEFARIUS_ADD_KILLED);
}
}
}
}
break;
case NPC_BLACKWING_DRAGON:
--addsCount[0];
if (EggEvent != DONE && _events.GetTimeUntilEvent(EVENT_RAZOR_SPAWN) == Milliseconds::max())
@@ -514,7 +463,7 @@ public:
razor->AI()->DoAction(ACTION_PHASE_TWO);
break;
case EVENT_RESPAWN_NEFARIUS:
if (Creature* nefarius = instance->GetCreature(victorNefariusGUID))
if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS))
{
nefarius->SetPhaseMask(1, true);
nefarius->setActive(true);
@@ -580,7 +529,6 @@ public:
ObjectGuid chromaggusDoorGUID;
ObjectGuid nefarianGUID;
ObjectGuid nefarianDoorGUID;
ObjectGuid victorNefariusGUID;
// Razorgore
uint8 EggCount;
@@ -232,7 +232,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (!me->getThreatMgr().getThreatList().empty())
{
@@ -245,7 +245,7 @@ public:
}
else
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
}
@@ -185,7 +185,6 @@ public:
if (me->IsVisible())
DoMeleeAttackIfReady();
EnterEvadeIfOutOfCombatArea();
}
bool CheckEvadeIfOutOfCombatArea() const override
@@ -194,7 +194,7 @@ public:
case EVENT_CHECK_DIST:
if (me->GetDistance(me->GetHomePosition()) > 75.0f)
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
events.ScheduleEvent(EVENT_CHECK_DIST, 5000);
@@ -325,7 +325,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
summons.Summon(summon);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (Creature* delrissa = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_DELRISSA)))
if (!delrissa->IsAlive())
@@ -333,7 +333,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI
delrissa->Respawn();
return;
}
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void EnterCombat(Unit* who) override
@@ -240,7 +240,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DeleteThreatList();
me->CombatStop(false);
@@ -100,7 +100,7 @@ public:
instance->SetData(DATA_KIRTONOS_THE_HERALD, DONE);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
instance->SetData(DATA_KIRTONOS_THE_HERALD, FAIL);
me->DespawnOrUnsummon(1);
@@ -111,15 +111,15 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
if (Creature* alythess = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GRAND_WARLOCK_ALYTHESS)))
{
if (!alythess->IsAlive())
alythess->Respawn(true);
else if (!alythess->IsInEvadeMode())
alythess->AI()->EnterEvadeMode();
alythess->AI()->EnterEvadeMode(why);
}
}
@@ -259,15 +259,15 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
if (Creature* scorlash = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_LADY_SACROLASH)))
{
if (!scorlash->IsAlive())
scorlash->Respawn(true);
else if (!scorlash->IsInEvadeMode())
scorlash->AI()->EnterEvadeMode();
scorlash->AI()->EnterEvadeMode(why);
}
}
@@ -308,11 +308,11 @@ public:
events.Reset();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (me->GetReactState() == REACT_PASSIVE)
return;
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void AttackStart(Unit* who) override
@@ -176,12 +176,12 @@ public:
me->SetReactState(REACT_PASSIVE);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (InstanceScript* instance = me->GetInstanceScript())
if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_MURU)))
if (!muru->IsInEvadeMode())
muru->AI()->EnterEvadeMode();
muru->AI()->EnterEvadeMode(why);
me->DespawnOrUnsummon();
}
@@ -22,13 +22,13 @@
DoorData const doorData[] =
{
{ GO_FIRE_BARRIER, DATA_FELMYST_DOORS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_MURUS_GATE_1, DATA_MURU, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_MURUS_GATE_2, DATA_MURU, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_BOSS_COLLISION_1, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_BOSS_COLLISION_2, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_FORCE_FIELD, DATA_KALECGOS, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_FIRE_BARRIER, DATA_FELMYST_DOORS, DOOR_TYPE_PASSAGE },
{ GO_MURUS_GATE_1, DATA_MURU, DOOR_TYPE_ROOM },
{ GO_MURUS_GATE_2, DATA_MURU, DOOR_TYPE_PASSAGE },
{ GO_BOSS_COLLISION_1, DATA_KALECGOS, DOOR_TYPE_ROOM },
{ GO_BOSS_COLLISION_2, DATA_KALECGOS, DOOR_TYPE_ROOM },
{ GO_FORCE_FIELD, DATA_KALECGOS, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_sunwell_plateau : public InstanceMapScript
@@ -402,8 +402,6 @@ public:
else HatcherTimer -= diff;
}
EnterEvadeIfOutOfCombatArea();
DoMeleeAttackIfReady();
if (FireBreathTimer <= diff)
@@ -150,9 +150,9 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
if (GameObject* object = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(GO_GONG_OF_BETHEKK)))
object->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
me->DespawnOrUnsummon(4000);
@@ -28,8 +28,8 @@ EndScriptData */
DoorData const doorData[] =
{
{ GO_FORCEFIELD, DATA_ARLOKK, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_FORCEFIELD, DATA_ARLOKK, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_zulgurub : public InstanceMapScript
@@ -215,7 +215,7 @@ public:
{
damage = 0;
me->setActive(false);
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
}
}
@@ -243,7 +243,7 @@ public:
break;
}
me->setActive(false);
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
case EVENT_SUMMON_SOLDIERS:
for (uint8 i = 0; i < SUNWELL_DEFENDER_NUM; ++i)
@@ -393,7 +393,7 @@ public:
case EVENT_DISAPPEAR:
me->SetVisible(false);
me->setActive(false);
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
break;
case EVENT_SET_FACING:
me->SetFacingTo(2.45f);
@@ -425,11 +425,11 @@ public:
events.ScheduleEvent(EVENT_SET_FACING, 0);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (me->isActiveObject())
return;
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void SetData(uint32 type, uint32 id) override
@@ -155,7 +155,7 @@ public:
MarzonGUID.Clear();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DisappearAndDie();
@@ -317,7 +317,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DisappearAndDie();
@@ -307,13 +307,13 @@ public:
enum ParqualFintallas
{
SPELL_MARK_OF_SHAME = 6767
SPELL_MARK_OF_SHAME = 6767,
QUEST_ID_TEST_OF_LORE = 6628,
GOSSIP_MENU_ID_TEST_OF_LORE = 4764,
GOSSIP_TEXTID_PARQUAL_FINTALLAS = 5821,
GOSSIP_TEXTID_TEST_OF_LORE = 5822,
};
#define GOSSIP_HPF1 "Gul'dan"
#define GOSSIP_HPF2 "Kel'Thuzad"
#define GOSSIP_HPF3 "Ner'zhul"
class npc_parqual_fintallas : public CreatureScript
{
public:
@@ -338,17 +338,21 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (creature->IsQuestGiver())
player->PrepareQuestMenu(creature->GetGUID());
if (player->GetQuestStatus(6628) == QUEST_STATUS_INCOMPLETE && !player->HasAura(SPELL_MARK_OF_SHAME))
{
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_HPF1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_HPF2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_HPF3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, 5822, creature->GetGUID());
player->PrepareQuestMenu(creature->GetGUID());
}
if (player->GetQuestStatus(QUEST_ID_TEST_OF_LORE) == QUEST_STATUS_INCOMPLETE && !player->HasAura(SPELL_MARK_OF_SHAME))
{
AddGossipItemFor(player, GOSSIP_MENU_ID_TEST_OF_LORE, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, GOSSIP_MENU_ID_TEST_OF_LORE, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, GOSSIP_MENU_ID_TEST_OF_LORE, 3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, GOSSIP_TEXTID_TEST_OF_LORE, creature->GetGUID());
}
else
SendGossipMenuFor(player, 5821, creature->GetGUID());
{
SendGossipMenuFor(player, GOSSIP_TEXTID_PARQUAL_FINTALLAS, creature->GetGUID());
}
return true;
}
@@ -1007,7 +1011,7 @@ public:
EventMap _events;
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->DeleteThreatList();
me->CombatStop(true);
@@ -2349,7 +2353,7 @@ public:
EventMap _events;
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
me->RemoveAura(SPELL_HEROIC_VANGUARD);
me->DeleteThreatList();
+1 -1
View File
@@ -660,7 +660,7 @@ struct npc_hallows_end_soh : public ScriptedAI
me->SetDisableGravity(true);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /* why */) override
{
me->DespawnOrUnsummon(1);
}
@@ -406,7 +406,7 @@ void hyjalAI::Reset()
DoHide = true;
}
void hyjalAI::EnterEvadeMode()
void hyjalAI::EnterEvadeMode(EvadeReason /*why*/)
{
if (me->GetEntry() != JAINA)
me->RemoveAllAuras();
@@ -122,7 +122,7 @@ struct hyjalAI : public npc_escortAI
void Reset() override; // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat
void EnterEvadeMode() override; // Send creature back to spawn location and evade.
void EnterEvadeMode(EvadeReason /*why*/ = EVADE_REASON_OTHER) override; // Send creature back to spawn location and evade.
void EnterCombat(Unit* /*who*/) override; // Used to reset cooldowns for our spells and to inform the raid that we're under attack
@@ -148,13 +148,6 @@ enum Spells
SPELL_ARTHAS_CRUSADER_STRIKE = 50773,
};
#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready."
#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness."
#define GOSSIP_ITEM_ARTHAS_3 "Lead the way Prince Arthas."
#define GOSSIP_ITEM_ARTHAS_4 "I'm ready."
#define GOSSIP_ITEM_ARTHAS_5 "For Lordaeron!"
#define GOSSIP_ITEM_ARTHAS_6 "I'm ready to battle the dreadlord, sire."
enum GossipMenuArthas
{
GOSSIP_MENU_ARTHAS_1 = 13076,
@@ -303,7 +296,7 @@ public:
break;
case GOSSIP_ACTION_INFO_DEF+2:
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
AddGossipItemFor(player, 9681, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_3, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+3:
@@ -344,23 +337,23 @@ public:
switch (pInstance->GetData(DATA_ARTHAS_EVENT))
{
case COS_PROGRESS_FINISHED_INTRO:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, 9653, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_1, creature->GetGUID());
break;
case COS_PROGRESS_REACHED_TOWN_HALL:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
AddGossipItemFor(player, 9680, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_2, creature->GetGUID());
break;
case COS_PROGRESS_KILLED_EPOCH:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
AddGossipItemFor(player, 9695, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_4, creature->GetGUID());
break;
case COS_PROGRESS_LAST_CITY:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
AddGossipItemFor(player, 9696, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_5, creature->GetGUID());
break;
case COS_PROGRESS_BEFORE_MALGANIS:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
AddGossipItemFor(player, 9676, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
SendGossipMenuFor(player, GOSSIP_MENU_ARTHAS_6, creature->GetGUID());
break;
}
@@ -294,7 +294,7 @@ public:
}
}
bool CheckInRoom()
bool CheckInRoom() override
{
if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 95.0f)
{
@@ -122,10 +122,10 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
me->ClearUnitState(UNIT_STATE_ROOT);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void EnterCombat(Unit* attacker) override
@@ -70,9 +70,9 @@ public:
{
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
for (ObjectGuid const& guid : Eggs)
if (Creature* egg = me->GetMap()->GetCreature(guid))
@@ -158,11 +158,11 @@ public:
Talk(SAY_SLAY);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
Cleanup();
summons.DespawnAll();
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
@@ -68,9 +68,9 @@ public:
Talk(SAY_SLAY);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
if (me->IsSummon())
((TempSummon*)me)->UnSummon();
}
@@ -415,7 +415,7 @@ public:
void CastSpellOnBug(Creature* target) override
{
target->SetFaction(FACTION_MONSTER);
target->AI()->AttackStart(me->getThreatMgr().getHostilTarget());
target->AI()->AttackStart(me->getThreatMgr().getHostileTarget());
target->AddAura(SPELL_MUTATE_BUG, target);
target->SetFullHealth();
}
@@ -182,10 +182,10 @@ public:
events.ScheduleEvent(EVENT_POISON_SHOCK, urand(7000, 12000));
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
summons.DespawnAll();
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void JustDied(Unit* /*killer*/) override
@@ -122,11 +122,11 @@ public:
npc_escortAI::JustDied(killer);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
SummonsFollow();
ImmuneFlagSet(false, 35);
npc_escortAI::EnterEvadeMode();
npc_escortAI::EnterEvadeMode(why);
}
void CheckPlayer()
+2 -2
View File
@@ -149,9 +149,9 @@ public:
_events.ScheduleEvent(EVENT_FINAL_TALK, 5 * IN_MILLISECONDS);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
_EnterEvadeMode();
_EnterEvadeMode(why);
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{
+26 -25
View File
@@ -53,9 +53,6 @@ enum Bunthen
TAXI_PATH_ID_HORDE = 316
};
#define GOSSIP_ITEM_THUNDER "I'd like to fly to Thunder Bluff."
#define GOSSIP_ITEM_AQ_END "Do you know where I can find Half Pendant of Aquatic Endurance?"
class npc_bunthen_plainswind : public CreatureScript
{
public:
@@ -75,7 +72,7 @@ public:
SendGossipMenuFor(player, 5373, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF + 3:
SendGossipMenuFor(player, 5376, creature->GetGUID());
SendGossipMenuFor(player, 5374, creature->GetGUID());
break;
}
return true;
@@ -84,20 +81,26 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->getClass() != CLASS_DRUID)
{
SendGossipMenuFor(player, 4916, creature->GetGUID());
}
else if (player->GetTeamId() != TEAM_HORDE)
{
if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
{
AddGossipItemFor(player, 4042, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
}
SendGossipMenuFor(player, 4917, creature->GetGUID());
}
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_HORDE)
{
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_THUNDER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, 4042, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
{
AddGossipItemFor(player, 4042, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
}
SendGossipMenuFor(player, 4918, creature->GetGUID());
}
@@ -109,11 +112,6 @@ public:
## npc_great_bear_spirit
######*/
#define GOSSIP_BEAR1 "What do you represent, spirit?"
#define GOSSIP_BEAR2 "I seek to understand the importance of strength of the body."
#define GOSSIP_BEAR3 "I seek to understand the importance of strength of the heart."
#define GOSSIP_BEAR4 "I have heard your words, Great Bear Spirit, and I understand. I now seek your blessings to fully learn the way of the Claw."
class npc_great_bear_spirit : public CreatureScript
{
public:
@@ -125,15 +123,15 @@ public:
switch (action)
{
case GOSSIP_ACTION_INFO_DEF:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BEAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, 3881, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 4721, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF + 1:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BEAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
AddGossipItemFor(player, 3883, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, 4733, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF + 2:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BEAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
AddGossipItemFor(player, 3884, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
SendGossipMenuFor(player, 4734, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF + 3:
@@ -152,7 +150,7 @@ public:
//ally or horde quest
if (player->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE)
{
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_BEAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
AddGossipItemFor(player, 3882, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
SendGossipMenuFor(player, 4719, creature->GetGUID());
}
else
@@ -166,9 +164,6 @@ public:
## npc_silva_filnaveth
######*/
#define GOSSIP_ITEM_RUTHERAN "I'd like to fly to Rut'theran Village."
#define GOSSIP_ITEM_AQ_AGI "Do you know where I can find Half Pendant of Aquatic Agility?"
class npc_silva_filnaveth : public CreatureScript
{
public:
@@ -185,7 +180,7 @@ public:
player->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY);
break;
case GOSSIP_ACTION_INFO_DEF + 2:
SendGossipMenuFor(player, 5374, creature->GetGUID());
SendGossipMenuFor(player, 5376, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF + 3:
SendGossipMenuFor(player, 5375, creature->GetGUID());
@@ -197,20 +192,26 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->getClass() != CLASS_DRUID)
{
SendGossipMenuFor(player, 4913, creature->GetGUID());
}
else if (player->GetTeamId() != TEAM_ALLIANCE)
{
if (player->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
{
AddGossipItemFor(player, 4041, 2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
}
SendGossipMenuFor(player, 4915, creature->GetGUID());
}
else if (player->getClass() == CLASS_DRUID && player->GetTeamId() == TEAM_ALLIANCE)
{
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTHERAN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, 4041, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
if (player->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
{
AddGossipItemFor(player, 4041, 1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
}
SendGossipMenuFor(player, 4914, creature->GetGUID());
}
@@ -355,7 +356,7 @@ public:
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
if (player && player->IsInCombat() && player->getAttackerForHelper())
@@ -363,7 +364,7 @@ public:
AttackStart(player->getAttackerForHelper());
return;
}
npc_escortAI::EnterEvadeMode();
npc_escortAI::EnterEvadeMode(why);
}
void StartEvent(Player* player)
+15 -16
View File
@@ -284,8 +284,6 @@ public:
## npc_steward_of_time
######*/
#define GOSSIP_ITEM_FLIGHT "Please take me to the master's lair."
class npc_steward_of_time : public CreatureScript
{
public:
@@ -311,15 +309,19 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (creature->IsQuestGiver())
{
player->PrepareQuestMenu(creature->GetGUID());
}
if (player->GetQuestStatus(10279) == QUEST_STATUS_INCOMPLETE || player->GetQuestRewardStatus(10279))
{
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, 8072, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 9978, creature->GetGUID());
}
else
{
SendGossipMenuFor(player, 9977, creature->GetGUID());
}
return true;
}
@@ -329,13 +331,6 @@ public:
## npc_stone_watcher_of_norgannon
######*/
#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?"
#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?"
#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?"
#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!"
#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?"
#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum."
class npc_stone_watcher_of_norgannon : public CreatureScript
{
public:
@@ -347,23 +342,23 @@ public:
switch (action)
{
case GOSSIP_ACTION_INFO_DEF:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
AddGossipItemFor(player, 57001, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
SendGossipMenuFor(player, 1675, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+1:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
AddGossipItemFor(player, 57002, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
SendGossipMenuFor(player, 1676, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+2:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
AddGossipItemFor(player, 57003, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
SendGossipMenuFor(player, 1677, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+3:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
AddGossipItemFor(player, 57004, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
SendGossipMenuFor(player, 1678, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+4:
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
AddGossipItemFor(player, 57005, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
SendGossipMenuFor(player, 1679, creature->GetGUID());
break;
case GOSSIP_ACTION_INFO_DEF+5:
@@ -377,10 +372,14 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (creature->IsQuestGiver())
{
player->PrepareQuestMenu(creature->GetGUID());
}
if (player->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE)
AddGossipItemFor(player, GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
{
AddGossipItemFor(player, 57000, 0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
}
SendGossipMenuFor(player, 1674, creature->GetGUID());
@@ -306,10 +306,10 @@ public:
void EnterCombat(Unit* /*who*/) override { }
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
CleanUp();
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
void CleanUp()
@@ -343,7 +343,7 @@ public:
Player* pWarrior = ObjectAccessor::GetPlayer(*me, PlayerGUID);
if (!pWarrior || me->GetDistance2d(pWarrior) >= 200.0f)
{
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
@@ -351,7 +351,7 @@ public:
{
Talk(SAY_TWIGGY_FLATHEAD_DOWN);
pWarrior->FailQuest(1719);
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
@@ -435,7 +435,7 @@ public:
if (!creature || !creature->IsAlive())
{
Talk(SAY_TWIGGY_FLATHEAD_OVER);
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
else // Makes BIG WILL attackable.
@@ -83,10 +83,10 @@ class boss_anub_arak : public CreatureScript
bool intro;
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
me->DisableRotate(false);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void MoveInLineOfSight(Unit* who) override
@@ -195,7 +195,6 @@ public:
}
DoMeleeAttackIfReady();
EnterEvadeIfOutOfCombatArea();
}
bool CheckEvadeIfOutOfCombatArea() const override
@@ -21,11 +21,11 @@
DoorData const doorData[] =
{
{ GO_KRIKTHIR_DOORS, DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_ANUBARAK_DOORS1, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ANUBARAK_DOORS2, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ GO_ANUBARAK_DOORS3, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
{ GO_KRIKTHIR_DOORS, DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DOOR_TYPE_PASSAGE },
{ GO_ANUBARAK_DOORS1, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM },
{ GO_ANUBARAK_DOORS2, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM },
{ GO_ANUBARAK_DOORS3, DATA_ANUBARAK_EVENT, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM }
};
ObjectData const creatureData[] =
@@ -140,10 +140,10 @@ struct boss_amanitar : public BossAI
BossAI::SummonedCreatureDies(summon, killer);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI);
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void ExecuteEvent(uint32 eventId) override
@@ -245,7 +245,7 @@ struct npc_amanitar_mushrooms : public ScriptedAI
// Disabled events
void EnterCombat(Unit* /*who*/) override {}
void AttackStart(Unit* /*victim*/) override {}
void EnterEvadeMode() override {}
void EnterEvadeMode(EvadeReason /*why*/) override {}
void Reset() override
{
@@ -592,11 +592,11 @@ struct npc_twilight_volunteer : public ScriptedAI
}
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (!isSacraficeTarget)
{
ScriptedAI::EnterEvadeMode();
ScriptedAI::EnterEvadeMode(why);
}
}
@@ -177,7 +177,6 @@ public:
}
DoMeleeAttackIfReady();
EnterEvadeIfOutOfCombatArea();
}
bool CheckEvadeIfOutOfCombatArea() const override
@@ -218,7 +217,7 @@ public:
_events.ScheduleEvent(EVENT_LAVA_GOUT, 5000);
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
// Prevent EvadeMode
}
@@ -272,12 +272,12 @@ public:
return false;
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason why) override
{
if (IsAnyPlayerValid())
return;
BossAI::EnterEvadeMode();
BossAI::EnterEvadeMode(why);
}
void AttackStart(Unit* who) override
@@ -473,7 +473,7 @@ public:
me->SetInCombatWithZone();
}
void EnterEvadeMode() override
void EnterEvadeMode(EvadeReason /*why*/) override
{
}
@@ -22,18 +22,24 @@
#include "WorldPacket.h"
#include "ruby_sanctum.h"
BossBoundaryData const boundaries =
{
{ DATA_GENERAL_ZARITHRIAN, new EllipseBoundary(Position(3013.409f, 529.492f), 45.0, 100.0) },
{ DATA_HALION, new CircleBoundary(Position(3156.037f, 533.2656f), 48.5) }
};
DoorData const doorData[] =
{
{GO_FIRE_FIELD, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE, BOUNDARY_E },
{GO_FLAME_WALLS, DATA_SAVIANA_RAGEFIRE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_FLAME_WALLS, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_FLAME_WALLS, DATA_GENERAL_ZARITHRIAN, DOOR_TYPE_ROOM, BOUNDARY_NONE},
{GO_BURNING_TREE_4, DATA_HALION_INTRO1, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_BURNING_TREE_3, DATA_HALION_INTRO1, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_BURNING_TREE_2, DATA_HALION_INTRO2, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_BURNING_TREE_1, DATA_HALION_INTRO2, DOOR_TYPE_PASSAGE, BOUNDARY_NONE},
{GO_TWILIGHT_FLAME_RING, DATA_HALION, DOOR_TYPE_ROOM, BOUNDARY_NONE},
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE},
{GO_FIRE_FIELD, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE },
{GO_FLAME_WALLS, DATA_SAVIANA_RAGEFIRE, DOOR_TYPE_PASSAGE },
{GO_FLAME_WALLS, DATA_BALTHARUS_THE_WARBORN, DOOR_TYPE_PASSAGE },
{GO_FLAME_WALLS, DATA_GENERAL_ZARITHRIAN, DOOR_TYPE_ROOM, },
{GO_BURNING_TREE_4, DATA_HALION_INTRO1, DOOR_TYPE_PASSAGE },
{GO_BURNING_TREE_3, DATA_HALION_INTRO1, DOOR_TYPE_PASSAGE },
{GO_BURNING_TREE_2, DATA_HALION_INTRO2, DOOR_TYPE_PASSAGE },
{GO_BURNING_TREE_1, DATA_HALION_INTRO2, DOOR_TYPE_PASSAGE },
{GO_TWILIGHT_FLAME_RING, DATA_HALION, DOOR_TYPE_ROOM },
{0, 0, DOOR_TYPE_ROOM },
};
class instance_ruby_sanctum : public InstanceMapScript
@@ -46,6 +52,7 @@ public:
instance_ruby_sanctum_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetBossNumber(MAX_ENCOUNTERS);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
}

Some files were not shown because too many files have changed in this diff Show More