Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -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>
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -50,7 +50,7 @@ void TotemAI::MoveInLineOfSight(Unit* /*who*/)
|
||||
{
|
||||
}
|
||||
|
||||
void TotemAI::EnterEvadeMode()
|
||||
void TotemAI::EnterEvadeMode(EvadeReason /*why*/)
|
||||
{
|
||||
me->CombatStop(true);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
|
||||
[[nodiscard]] Unit* GetOwner() const { return iOwner; }
|
||||
|
||||
Unit* getHostilTarget();
|
||||
Unit* getHostileTarget();
|
||||
|
||||
void tauntApply(Unit* taunter);
|
||||
void tauntFadeOut(Unit* taunter);
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
+1
-1
@@ -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))
|
||||
{
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-2
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
+117
-86
@@ -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 =
|
||||
|
||||
+28
-25
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-76
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+6
-13
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+17
-10
@@ -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
Reference in New Issue
Block a user