mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-28 16:16:27 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -2769,15 +2769,6 @@ Rate.RewardBonusMoney = 1
|
||||
|
||||
MonsterSight = 50.000000
|
||||
|
||||
#
|
||||
# ThreatRadius
|
||||
# Description: Distance for creatures to evade after being pulled away from the combat
|
||||
# starting point. If ThreatRadius is less than creature aggro radius then aggro
|
||||
# radius will be used.
|
||||
# Default: 60
|
||||
|
||||
ThreatRadius = 60
|
||||
|
||||
#
|
||||
# Rate.Creature.Aggro
|
||||
# Description: Aggro radius percentage.
|
||||
|
||||
@@ -348,7 +348,7 @@ void CreatureAI::MoveCircleChecks()
|
||||
!victim ||
|
||||
!me->IsFreeToMove() || me->HasUnitMovementFlag(MOVEMENTFLAG_ROOT) ||
|
||||
!me->IsWithinMeleeRange(victim) || me == victim->GetVictim() ||
|
||||
(victim->GetTypeId() != TYPEID_PLAYER && !victim->IsPet()) // only player & pets to save CPU
|
||||
(!victim->IsPlayer() && !victim->IsPet()) // only player & pets to save CPU
|
||||
)
|
||||
{
|
||||
return;
|
||||
@@ -357,14 +357,12 @@ void CreatureAI::MoveCircleChecks()
|
||||
me->GetMotionMaster()->MoveCircleTarget(me->GetVictim());
|
||||
}
|
||||
|
||||
void CreatureAI::MoveBackwardsChecks() {
|
||||
void CreatureAI::MoveBackwardsChecks()
|
||||
{
|
||||
Unit *victim = me->GetVictim();
|
||||
|
||||
if (
|
||||
!victim ||
|
||||
!me->IsFreeToMove() || me->HasUnitMovementFlag(MOVEMENTFLAG_ROOT) ||
|
||||
(victim->GetTypeId() != TYPEID_PLAYER && !victim->IsPet())
|
||||
)
|
||||
if (!victim || !me->IsFreeToMove() || me->HasUnitMovementFlag(MOVEMENTFLAG_ROOT) ||
|
||||
(!victim->IsPlayer() && !victim->IsPet()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -191,8 +191,7 @@ bool SummonList::IsAnyCreatureInCombat() const
|
||||
|
||||
ScriptedAI::ScriptedAI(Creature* creature) : CreatureAI(creature),
|
||||
me(creature),
|
||||
IsFleeing(false),
|
||||
_isCombatMovementAllowed(true)
|
||||
IsFleeing(false)
|
||||
{
|
||||
_isHeroic = me->GetMap()->IsHeroic();
|
||||
_difficulty = Difficulty(me->GetMap()->GetSpawnMode());
|
||||
@@ -209,7 +208,7 @@ void ScriptedAI::AttackStartNoMove(Unit* who)
|
||||
|
||||
void ScriptedAI::AttackStart(Unit* who)
|
||||
{
|
||||
if (IsCombatMovementAllowed())
|
||||
if (me->IsCombatMovementAllowed())
|
||||
CreatureAI::AttackStart(who);
|
||||
else
|
||||
AttackStartNoMove(who);
|
||||
@@ -537,11 +536,6 @@ void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, uint32(ranged));
|
||||
}
|
||||
|
||||
void ScriptedAI::SetCombatMovement(bool allowMovement)
|
||||
{
|
||||
_isCombatMovementAllowed = allowMovement;
|
||||
}
|
||||
|
||||
enum eNPCs
|
||||
{
|
||||
NPC_BROODLORD = 12017,
|
||||
|
||||
@@ -373,14 +373,6 @@ struct ScriptedAI : public CreatureAI
|
||||
|
||||
void SetEquipmentSlots(bool loadDefault, int32 mainHand = EQUIP_NO_CHANGE, int32 offHand = EQUIP_NO_CHANGE, int32 ranged = EQUIP_NO_CHANGE);
|
||||
|
||||
// Used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims
|
||||
// NOTE: If you use SetCombatMovement while the creature is in combat, it will do NOTHING - This only affects AttackStart
|
||||
// You should make the necessary to make it happen so.
|
||||
// Remember that if you modified _isCombatMovementAllowed (e.g: using SetCombatMovement) it will not be reset at Reset().
|
||||
// It will keep the last value you set.
|
||||
void SetCombatMovement(bool allowMovement);
|
||||
bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; }
|
||||
|
||||
virtual bool CheckEvadeIfOutOfCombatArea() const { return false; }
|
||||
|
||||
// return true for heroic mode. i.e.
|
||||
@@ -452,7 +444,6 @@ struct ScriptedAI : public CreatureAI
|
||||
|
||||
private:
|
||||
Difficulty _difficulty;
|
||||
bool _isCombatMovementAllowed;
|
||||
bool _isHeroic;
|
||||
std::unordered_set<uint32> _uniqueTimedEvents;
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ void npc_escortAI::AttackStart(Unit* who)
|
||||
me->StopMoving();
|
||||
}
|
||||
|
||||
if (IsCombatMovementAllowed())
|
||||
if (me->IsCombatMovementAllowed())
|
||||
me->GetMotionMaster()->MoveChase(who);
|
||||
}
|
||||
}
|
||||
@@ -178,8 +178,8 @@ void npc_escortAI::JustRespawned()
|
||||
{
|
||||
RemoveEscortState(STATE_ESCORT_ESCORTING | STATE_ESCORT_RETURNING | STATE_ESCORT_PAUSED);
|
||||
|
||||
if (!IsCombatMovementAllowed())
|
||||
SetCombatMovement(true);
|
||||
if (!me->IsCombatMovementAllowed())
|
||||
me->SetCombatMovement(true);
|
||||
|
||||
//add a small delay before going to first waypoint, normal in near all cases
|
||||
m_uiWPWaitTimer = 1000;
|
||||
|
||||
@@ -55,7 +55,7 @@ void FollowerAI::AttackStart(Unit* who)
|
||||
if (me->HasUnitState(UNIT_STATE_FOLLOW))
|
||||
me->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||
|
||||
if (IsCombatMovementAllowed())
|
||||
if (me->IsCombatMovementAllowed())
|
||||
me->GetMotionMaster()->MoveChase(who);
|
||||
}
|
||||
}
|
||||
@@ -141,8 +141,8 @@ void FollowerAI::JustRespawned()
|
||||
{
|
||||
m_uiFollowState = STATE_FOLLOW_NONE;
|
||||
|
||||
if (!IsCombatMovementAllowed())
|
||||
SetCombatMovement(true);
|
||||
if (!me->IsCombatMovementAllowed())
|
||||
me->SetCombatMovement(true);
|
||||
|
||||
if (me->GetFaction() != me->GetCreatureTemplate()->faction)
|
||||
me->SetFaction(me->GetCreatureTemplate()->faction);
|
||||
|
||||
@@ -3456,6 +3456,8 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e,
|
||||
for (WorldObject* unit : units)
|
||||
if (IsPlayer(unit) && baseObject->IsInRange(unit, float(e.target.playerRange.minDist), float(e.target.playerRange.maxDist)))
|
||||
targets.push_back(unit);
|
||||
if (e.target.playerRange.maxCount)
|
||||
Acore::Containers::RandomResize(targets, e.target.playerRange.maxCount);
|
||||
break;
|
||||
}
|
||||
case SMART_TARGET_PLAYER_DISTANCE:
|
||||
|
||||
@@ -220,7 +220,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(),
|
||||
m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_regenPower(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_detectionDistance(20.0f), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(nullptr), m_cannotReachTimer(0),
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false)
|
||||
_isMissingSwimmingFlagOutOfCombat(false), m_assistanceTimer(0), _playerDamageReq(0), _damagedByPlayer(false), _isCombatMovementAllowed(true)
|
||||
{
|
||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||
m_valuesCount = UNIT_END;
|
||||
@@ -877,7 +877,7 @@ bool Creature::IsFreeToMove()
|
||||
{
|
||||
uint32 moveFlags = m_movementInfo.GetMovementFlags();
|
||||
// Do not reposition ourself when we are not allowed to move
|
||||
if ((IsMovementPreventedByCasting() || isMoving() || !CanFreeMove()) &&
|
||||
if ((IsMovementPreventedByCasting() || isMoving() || !CanFreeMove() || !IsCombatMovementAllowed()) &&
|
||||
(GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE ||
|
||||
moveFlags & MOVEMENTFLAG_SPLINE_ENABLED))
|
||||
{
|
||||
@@ -3739,6 +3739,11 @@ bool Creature::CanCastSpell(uint32 spellID) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void Creature::SetCombatMovement(bool allowMovement)
|
||||
{
|
||||
_isCombatMovementAllowed = allowMovement;
|
||||
}
|
||||
|
||||
ObjectGuid Creature::GetSummonerGUID() const
|
||||
{
|
||||
if (TempSummon const* temp = ToTempSummon())
|
||||
|
||||
@@ -413,6 +413,14 @@ public:
|
||||
* */
|
||||
[[nodiscard]] ObjectGuid GetSummonerGUID() const;
|
||||
|
||||
// Used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims
|
||||
// NOTE: If you use SetCombatMovement while the creature is in combat, it will do NOTHING - This only affects AttackStart
|
||||
// You should make the necessary to make it happen so.
|
||||
// Remember that if you modified _isCombatMovementAllowed (e.g: using SetCombatMovement) it will not be reset at Reset().
|
||||
// It will keep the last value you set.
|
||||
void SetCombatMovement(bool allowMovement);
|
||||
bool IsCombatMovementAllowed() const { return _isCombatMovementAllowed; }
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
protected:
|
||||
@@ -501,6 +509,7 @@ private:
|
||||
|
||||
uint32 _playerDamageReq;
|
||||
bool _damagedByPlayer;
|
||||
bool _isCombatMovementAllowed;
|
||||
};
|
||||
|
||||
class AssistDelayEvent : public BasicEvent
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
#include "Timer.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
// create instance
|
||||
WorldUpdateTime sWorldUpdateTime;
|
||||
@@ -71,8 +73,34 @@ uint32 UpdateTime::GetLastUpdateTime() const
|
||||
return _updateTimeDataTable[_updateTimeTableIndex != 0 ? _updateTimeTableIndex - 1 : _updateTimeDataTable.size() - 1];
|
||||
}
|
||||
|
||||
uint32 UpdateTime::GetDatasetSize() const
|
||||
{
|
||||
return _updateTimeDataTable[_updateTimeDataTable.size() - 1] == 0 ? _updateTimeTableIndex : _orderedUpdateTimeDataTable.size();
|
||||
}
|
||||
|
||||
uint32 UpdateTime::GetPercentile(uint8 p)
|
||||
{
|
||||
if (_needsReorder)
|
||||
SortUpdateTimeDataTable();
|
||||
|
||||
// Calculate the index of the element corresponding to the percentile
|
||||
double index = (double(p) / 100.0) * (GetDatasetSize() - 1);
|
||||
|
||||
// If the index is an integer, return the value at that index
|
||||
if (index == floor(index))
|
||||
return _orderedUpdateTimeDataTable[index];
|
||||
|
||||
// Otherwise, perform linear interpolation
|
||||
int lowerIndex = floor(index);
|
||||
int upperIndex = ceil(index);
|
||||
double fraction = index - lowerIndex;
|
||||
|
||||
return _orderedUpdateTimeDataTable[lowerIndex] * (1 - fraction) + _orderedUpdateTimeDataTable[upperIndex] * fraction;
|
||||
}
|
||||
|
||||
void UpdateTime::UpdateWithDiff(uint32 diff)
|
||||
{
|
||||
_needsReorder = true;
|
||||
_totalUpdateTime = _totalUpdateTime - _updateTimeDataTable[_updateTimeTableIndex] + diff;
|
||||
_updateTimeDataTable[_updateTimeTableIndex] = diff;
|
||||
|
||||
@@ -100,6 +128,26 @@ void UpdateTime::RecordUpdateTimeReset()
|
||||
_recordedTime = GetTimeMS();
|
||||
}
|
||||
|
||||
void UpdateTime::SortUpdateTimeDataTable()
|
||||
{
|
||||
if (!_needsReorder)
|
||||
return;
|
||||
|
||||
auto endUpdateTable = _updateTimeDataTable.end();
|
||||
if (!_updateTimeDataTable[_updateTimeDataTable.size() - 1])
|
||||
endUpdateTable = std::next(_updateTimeDataTable.begin(), _updateTimeTableIndex);
|
||||
|
||||
std::copy(_updateTimeDataTable.begin(), endUpdateTable, _orderedUpdateTimeDataTable.begin());
|
||||
|
||||
auto endOrderedUpdateTable = _orderedUpdateTimeDataTable.end();
|
||||
if (!_updateTimeDataTable[_updateTimeDataTable.size() - 1])
|
||||
endOrderedUpdateTable = std::next(_orderedUpdateTimeDataTable.begin(), _updateTimeTableIndex);
|
||||
|
||||
std::sort(_orderedUpdateTimeDataTable.begin(), endOrderedUpdateTable);
|
||||
|
||||
_needsReorder = false;
|
||||
}
|
||||
|
||||
void WorldUpdateTime::LoadFromConfig()
|
||||
{
|
||||
_recordUpdateTimeInverval = Milliseconds(sConfigMgr->GetOption<uint32>("RecordUpdateTimeDiffInterval", 60000));
|
||||
@@ -117,7 +165,10 @@ void WorldUpdateTime::RecordUpdateTime(Milliseconds gameTimeMs, uint32 diff, uin
|
||||
{
|
||||
if (GetMSTimeDiff(_lastRecordTime, gameTimeMs) > _recordUpdateTimeInverval)
|
||||
{
|
||||
LOG_INFO("time.update", "Update time diff: {}. Players online: {}.", GetAverageUpdateTime(), sessionCount);
|
||||
LOG_INFO("time.update", "Last {} diffs summary with {} players online:", GetDatasetSize(), sessionCount);
|
||||
LOG_INFO("time.update", " - Mean: {};", GetAverageUpdateTime());
|
||||
LOG_INFO("time.update", " - Median: {};", GetPercentile(50));
|
||||
LOG_INFO("time.update", " - Percentiles (95, 99, max): {}, {}, {}.", GetPercentile(95), GetPercentile(99), GetPercentile(100));
|
||||
_lastRecordTime = gameTimeMs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
uint32 GetMaxUpdateTime() const;
|
||||
uint32 GetMaxUpdateTimeOfCurrentTable() const;
|
||||
uint32 GetLastUpdateTime() const;
|
||||
uint32 GetDatasetSize() const;
|
||||
uint32 GetPercentile(uint8 p);
|
||||
|
||||
void UpdateWithDiff(uint32 diff);
|
||||
|
||||
@@ -43,6 +45,8 @@ public:
|
||||
protected:
|
||||
UpdateTime();
|
||||
|
||||
void SortUpdateTimeDataTable();
|
||||
|
||||
private:
|
||||
DiffTableArray _updateTimeDataTable;
|
||||
uint32 _averageUpdateTime;
|
||||
@@ -52,6 +56,9 @@ private:
|
||||
uint32 _maxUpdateTimeOfLastTable;
|
||||
uint32 _maxUpdateTimeOfCurrentTable;
|
||||
|
||||
DiffTableArray _orderedUpdateTimeDataTable;
|
||||
bool _needsReorder;
|
||||
|
||||
Milliseconds _recordedTime;
|
||||
};
|
||||
|
||||
|
||||
@@ -282,7 +282,13 @@ public:
|
||||
|
||||
handler->PSendSysMessage("Connection peak: %u.", connPeak);
|
||||
handler->PSendSysMessage(LANG_UPTIME, secsToTimeString(GameTime::GetUptime().count()).c_str());
|
||||
handler->PSendSysMessage("Update time diff: %ums, average: %ums.", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetAverageUpdateTime());
|
||||
handler->PSendSysMessage("Update time diff: %ums. Last %d diffs summary:", sWorldUpdateTime.GetLastUpdateTime(), sWorldUpdateTime.GetDatasetSize());
|
||||
handler->PSendSysMessage("- Mean: %ums", sWorldUpdateTime.GetAverageUpdateTime());
|
||||
handler->PSendSysMessage("- Median: %ums", sWorldUpdateTime.GetPercentile(50));
|
||||
handler->PSendSysMessage("- Percentiles (95, 99, max): %ums, %ums, %ums",
|
||||
sWorldUpdateTime.GetPercentile(95),
|
||||
sWorldUpdateTime.GetPercentile(99),
|
||||
sWorldUpdateTime.GetPercentile(100));
|
||||
|
||||
//! Can't use sWorld->ShutdownMsg here in case of console command
|
||||
if (sWorld->IsShuttingDown())
|
||||
|
||||
@@ -45,7 +45,7 @@ struct boss_quartermaster_zigris : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
_hasDrunkPotion = false;
|
||||
}
|
||||
|
||||
@@ -120,11 +120,11 @@ struct boss_quartermaster_zigris : public BossAI
|
||||
{
|
||||
DoCastVictim(SPELL_SHOOT);
|
||||
me->GetMotionMaster()->Clear();
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
else if (!me->IsWithinLOSInMap(me->GetVictim()))
|
||||
{
|
||||
SetCombatMovement(true);
|
||||
me->SetCombatMovement(true);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ public:
|
||||
Talk(SAY_GAMESBEGIN_2);
|
||||
|
||||
DoCast(me, SPELL_NEFARIANS_BARRIER);
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->SetImmuneToPC(false);
|
||||
AttackStart(SelectTarget(SelectTargetMethod::Random, 0, 200.f, true));
|
||||
events.ScheduleEvent(EVENT_SHADOWBLINK, 500ms);
|
||||
|
||||
@@ -159,7 +159,7 @@ struct boss_dorothee : public ScriptedAI
|
||||
{
|
||||
boss_dorothee(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
//this is kinda a big no-no. but it will prevent her from moving to chase targets. she should just cast her spells. in this case, since there is not really something to LOS her with or get out of range this would work. but a more elegant solution would be better
|
||||
|
||||
instance = creature->GetInstanceScript();
|
||||
|
||||
@@ -123,7 +123,7 @@ struct boss_jeklik : public BossAI
|
||||
|
||||
me->SetDisableGravity(false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
BossAI::SetCombatMovement(false);
|
||||
BossAI::me->SetCombatMovement(false);
|
||||
batRidersCount = 0;
|
||||
|
||||
DoCastSelf(SPELL_GREEN_CHANNELING, true);
|
||||
@@ -148,7 +148,7 @@ struct boss_jeklik : public BossAI
|
||||
BossAI::PathEndReached(pathId);
|
||||
|
||||
me->SetDisableGravity(false);
|
||||
SetCombatMovement(true);
|
||||
me->SetCombatMovement(true);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
//
|
||||
|
||||
@@ -2168,7 +2168,7 @@ public:
|
||||
{
|
||||
boss_blight_wormAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
{
|
||||
npc_andorhal_towerAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
@@ -1411,7 +1411,7 @@ public:
|
||||
{
|
||||
alliance_riflemanAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
uint32 ExplodeTimer;
|
||||
|
||||
@@ -84,7 +84,7 @@ struct boss_ayamiss : public BossAI
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
ScheduleHealthCheckEvent(70, [&] {
|
||||
@@ -127,7 +127,7 @@ struct boss_ayamiss : public BossAI
|
||||
}
|
||||
else if (type == WAYPOINT_MOTION_TYPE && id == POINT_GROUND)
|
||||
{
|
||||
SetCombatMovement(true);
|
||||
me->SetCombatMovement(true);
|
||||
me->SetDisableGravity(false);
|
||||
|
||||
me->m_Events.AddEventAtOffset([this]()
|
||||
|
||||
@@ -188,7 +188,7 @@ struct npc_buru_egg : public ScriptedAI
|
||||
npc_buru_egg(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
_instance = me->GetInstanceScript();
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetControlled(true, UNIT_STATE_STUNNED);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ struct boss_eye_of_cthun : public BossAI
|
||||
{
|
||||
boss_eye_of_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->m_SightDistance = 90.f;
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ struct boss_cthun : public BossAI
|
||||
{
|
||||
boss_cthun(Creature* creature) : BossAI(creature, DATA_CTHUN)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
@@ -597,7 +597,7 @@ struct npc_eye_tentacle : public ScriptedAI
|
||||
}
|
||||
}
|
||||
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -651,7 +651,7 @@ struct npc_claw_tentacle : public ScriptedAI
|
||||
{
|
||||
npc_claw_tentacle(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
|
||||
if (Creature* portal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
{
|
||||
@@ -720,7 +720,7 @@ struct npc_giant_claw_tentacle : public ScriptedAI
|
||||
{
|
||||
npc_giant_claw_tentacle(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
|
||||
if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
{
|
||||
@@ -870,7 +870,7 @@ struct npc_giant_eye_tentacle : public ScriptedAI
|
||||
{
|
||||
npc_giant_eye_tentacle(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
|
||||
if (Creature* portal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
|
||||
{
|
||||
|
||||
@@ -106,7 +106,7 @@ struct boss_ouro : public BossAI
|
||||
{
|
||||
boss_ouro(Creature* creature) : BossAI(creature, DATA_OURO)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->SetControlled(true, UNIT_STATE_ROOT);
|
||||
}
|
||||
|
||||
|
||||
@@ -366,7 +366,7 @@ struct npc_toxic_slime : public ScriptedAI
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
DoCastSelf(SPELL_TOXIN);
|
||||
|
||||
InstanceScript* instance = me->GetInstanceScript();
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
{
|
||||
npc_tiger_matriarch_creditAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
events.ScheduleEvent(EVENT_CHECK_SUMMON_AURA, 2s);
|
||||
}
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ struct npc_amanitar_mushrooms : public ScriptedAI
|
||||
{
|
||||
npc_amanitar_mushrooms(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
|
||||
//TODO: this prolly needs to be done in database
|
||||
pCreature->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
@@ -295,7 +295,7 @@ struct boss_jedoga_shadowseeker : public BossAI
|
||||
{
|
||||
if (!ritualTriggered && me->HealthBelowPctDamaged(55, damage) && events.IsInPhase(PHASE_NORMAL))
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->AttackStop();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
@@ -368,7 +368,7 @@ struct boss_jedoga_shadowseeker : public BossAI
|
||||
me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL);
|
||||
me->RemoveAurasDueToSpell(SPELL_LIGHTNING_BOLTS);
|
||||
me->RemoveAurasDueToSpell(SPELL_HOVER_FALL);
|
||||
SetCombatMovement(true);
|
||||
me->SetCombatMovement(true);
|
||||
|
||||
me->SetDisableGravity(false);
|
||||
me->SetHover(false);
|
||||
|
||||
@@ -606,14 +606,14 @@ struct boss_jormungarAI : public ScriptedAI
|
||||
if( bIsStationary )
|
||||
{
|
||||
me->SetNativeDisplayId(_MODEL_MOBILE);
|
||||
SetCombatMovement(true);
|
||||
me->SetCombatMovement(true);
|
||||
if( Unit* victim = me->GetVictim() )
|
||||
me->GetMotionMaster()->MoveChase(victim);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->SetNativeDisplayId(_MODEL_STATIONARY);
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
me->RemoveAurasDueToSpell(SPELL_SUBMERGE_0);
|
||||
me->CastSpell(me, SPELL_EMERGE_0, false);
|
||||
@@ -692,7 +692,7 @@ public:
|
||||
_MODEL_STATIONARY = MODEL_ACIDMAW_STATIONARY;
|
||||
_MODEL_MOBILE = MODEL_ACIDMAW_MOBILE;
|
||||
_TYPE_OTHER = TYPE_DREADSCALE;
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1525,7 +1525,7 @@ public:
|
||||
{
|
||||
boss_yoggsaron_crusher_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->CastSpell(me, SPELL_CRUSH, true);
|
||||
me->CastSpell(me, SPELL_FOCUSED_ANGER, true);
|
||||
me->CastSpell(me, SPELL_DIMINISH_POWER, false);
|
||||
@@ -1587,7 +1587,7 @@ public:
|
||||
{
|
||||
boss_yoggsaron_corruptor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
@@ -1644,7 +1644,7 @@ public:
|
||||
{
|
||||
boss_yoggsaron_constrictor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
_checkTimer = 1;
|
||||
_playerGUID.Clear();
|
||||
}
|
||||
|
||||
@@ -1049,7 +1049,7 @@ public:
|
||||
{
|
||||
npc_warmage_coldarraAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
uint32 m_uiTimer; //Timer until recast
|
||||
|
||||
@@ -147,7 +147,7 @@ struct npc_warmage_violetstand : public ScriptedAI
|
||||
{
|
||||
npc_warmage_violetstand(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
ObjectGuid targetGUID;
|
||||
|
||||
@@ -1532,7 +1532,7 @@ public:
|
||||
{
|
||||
npc_guardian_pavilionAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
@@ -1596,7 +1596,7 @@ public:
|
||||
{
|
||||
npc_tournament_training_dummyAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
|
||||
}
|
||||
|
||||
@@ -1816,7 +1816,7 @@ public:
|
||||
PhaseCount = 0;
|
||||
Summons.DespawnAll();
|
||||
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
EventMap events;
|
||||
|
||||
@@ -57,7 +57,7 @@ struct boss_murmur : public BossAI
|
||||
{
|
||||
boss_murmur(Creature* creature) : BossAI(creature, DATA_MURMUR)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
|
||||
@@ -149,6 +149,23 @@ class spell_morogrim_tidewalker_watery_grave : public SpellScript
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
uint8 maxSize = 4;
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
targets.remove_if([caster](WorldObject const* target) -> bool
|
||||
{
|
||||
// Should not target current victim.
|
||||
return caster->GetVictim() == target;
|
||||
});
|
||||
|
||||
if (targets.size() > maxSize)
|
||||
{
|
||||
Acore::Containers::RandomResize(targets, maxSize);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
@@ -159,6 +176,7 @@ class spell_morogrim_tidewalker_watery_grave : public SpellScript
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_morogrim_tidewalker_watery_grave::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_morogrim_tidewalker_watery_grave::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ struct boss_ahune : public ScriptedAI
|
||||
{
|
||||
boss_ahune(Creature* c) : ScriptedAI(c), summons(me)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
InvokerGUID.Clear();
|
||||
|
||||
@@ -41,7 +41,7 @@ struct boss_omor_the_unscarred : public BossAI
|
||||
{
|
||||
boss_omor_the_unscarred(Creature* creature) : BossAI(creature, DATA_OMOR_THE_UNSCARRED)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
scheduler.SetValidator([this]
|
||||
{
|
||||
return !me->HasUnitState(UNIT_STATE_CASTING);
|
||||
|
||||
@@ -69,7 +69,8 @@ enum Misc
|
||||
EVENT_SPELL_BERSERK = 3,
|
||||
|
||||
EVENT_MOVE_TO_PHASE_2 = 4,
|
||||
EVENT_FINISH_DIVE = 5
|
||||
EVENT_FINISH_DIVE = 5,
|
||||
EVENT_INVISIBLE = 6
|
||||
};
|
||||
|
||||
enum GroupAlar
|
||||
@@ -89,7 +90,7 @@ struct boss_alar : public BossAI
|
||||
|
||||
boss_alar(Creature* creature) : BossAI(creature, DATA_ALAR)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
@@ -172,22 +173,25 @@ struct boss_alar : public BossAI
|
||||
if (damage >= me->GetHealth() && _platform < POINT_MIDDLE)
|
||||
{
|
||||
damage = 0;
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
scheduler.CancelAll();
|
||||
me->CastStop();
|
||||
me->SetHealth(me->GetMaxHealth());
|
||||
DoCastSelf(SPELL_EMBER_BLAST, true); //spellscript doesn't trigger
|
||||
|
||||
DoCastSelf(SPELL_EMBER_BLAST, true);
|
||||
PretendToDie(me);
|
||||
ScheduleUniqueTimedEvent(1s, [&]{
|
||||
me->SetVisible(false);
|
||||
}, EVENT_INVISIBLE);
|
||||
ScheduleUniqueTimedEvent(8s, [&]{
|
||||
me->SetPosition(alarPoints[POINT_MIDDLE]);
|
||||
}, EVENT_RELOCATE_MIDDLE);
|
||||
ScheduleUniqueTimedEvent(12s, [&]
|
||||
{
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
me->SetVisible(true);
|
||||
DoCastSelf(SPELL_CLEAR_ALL_DEBUFFS, true);
|
||||
DoCastSelf(SPELL_REBIRTH_PHASE2);
|
||||
}, EVENT_MOVE_TO_PHASE_2);
|
||||
ScheduleUniqueTimedEvent(16001ms, [&]{
|
||||
me->SetHealth(me->GetMaxHealth());
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
_platform = POINT_MIDDLE;
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
ScheduleAbilities();
|
||||
@@ -195,6 +199,18 @@ struct boss_alar : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void PretendToDie(Creature* creature)
|
||||
{
|
||||
scheduler.CancelAll();
|
||||
creature->InterruptNonMeleeSpells(true);
|
||||
creature->RemoveAllAuras();
|
||||
creature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
creature->GetMotionMaster()->MovementExpired(false);
|
||||
creature->GetMotionMaster()->MoveIdle();
|
||||
creature->SetStandState(UNIT_STAND_STATE_DEAD);
|
||||
}
|
||||
|
||||
void ScheduleAbilities()
|
||||
{
|
||||
ScheduleTimedEvent(57s, [&]
|
||||
@@ -394,37 +410,6 @@ class spell_alar_ember_blast : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class spell_alar_ember_blast_death : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_alar_ember_blast_death);
|
||||
|
||||
void OnApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
PreventDefaultAction(); // xinef: prevent default action after change that invisibility in instances is executed instantly even for creatures
|
||||
Unit* target = GetTarget();
|
||||
InvisibilityType type = InvisibilityType(aurEff->GetMiscValue());
|
||||
target->m_invisibility.AddFlag(type);
|
||||
target->m_invisibility.AddValue(type, aurEff->GetAmount());
|
||||
|
||||
GetUnitOwner()->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
GetUnitOwner()->SetStandState(UNIT_STAND_STATE_DEAD);
|
||||
GetUnitOwner()->m_last_notify_position.Relocate(0.0f, 0.0f, 0.0f);
|
||||
GetUnitOwner()->m_delayed_unit_relocation_timer = 1000;
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetUnitOwner()->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
GetUnitOwner()->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_alar_ember_blast_death::OnApply, EFFECT_2, SPELL_AURA_MOD_INVISIBILITY, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_alar_ember_blast_death::OnRemove, EFFECT_2, SPELL_AURA_MOD_INVISIBILITY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_alar_dive_bomb : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_alar_dive_bomb);
|
||||
@@ -446,7 +431,6 @@ void AddSC_boss_alar()
|
||||
RegisterTheEyeAI(boss_alar);
|
||||
RegisterSpellScript(spell_alar_flame_quills);
|
||||
RegisterSpellScript(spell_alar_ember_blast);
|
||||
RegisterSpellScript(spell_alar_ember_blast_death);
|
||||
RegisterSpellScript(spell_alar_dive_bomb);
|
||||
}
|
||||
|
||||
|
||||
@@ -145,6 +145,8 @@ enum Misc
|
||||
DATA_RESURRECT_CAST = 1,
|
||||
NPC_WORLD_TRIGGER = 19871,
|
||||
NPC_NETHER_VAPOR = 21002,
|
||||
NPC_NETHERSTRAND_LONGBOW = 21268,
|
||||
NPC_STAFF_OF_DISINTEGRATION = 21274,
|
||||
|
||||
PHASE_NONE = 0,
|
||||
PHASE_SINGLE_ADVISOR = 1,
|
||||
@@ -207,14 +209,16 @@ enum KaelActions
|
||||
ACTION_START_SANGUINAR = 0,
|
||||
ACTION_START_CAPERNIAN = 1,
|
||||
ACTION_START_TELONICUS = 2,
|
||||
ACTION_START_WEAPONS = 3
|
||||
ACTION_START_WEAPONS = 3,
|
||||
ACTION_PROGRESS_PHASE_CHECK = 4
|
||||
};
|
||||
|
||||
enum SpellGroups
|
||||
{
|
||||
GROUP_PYROBLAST = 0,
|
||||
GROUP_SHOCK_BARRIER = 1,
|
||||
GROUP_NETHER_BEAM = 2
|
||||
GROUP_PROGRESS_PHASE = 0,
|
||||
GROUP_PYROBLAST = 1,
|
||||
GROUP_SHOCK_BARRIER = 2,
|
||||
GROUP_NETHER_BEAM = 3
|
||||
};
|
||||
|
||||
const Position triggersPos[6] =
|
||||
@@ -253,9 +257,12 @@ struct boss_kaelthas : public BossAI
|
||||
summons.DoForAllSummons([&](WorldObject* summon){
|
||||
if (Creature* summonedCreature = summon->ToCreature())
|
||||
{
|
||||
summonedCreature->SetReactState(REACT_PASSIVE);
|
||||
summonedCreature->setDeathState(DeathState::JustRespawned);
|
||||
summonedCreature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (summonedCreature->GetEntry() >= NPC_LORD_SANGUINAR && summonedCreature->GetEntry() <= NPC_THALADRED)
|
||||
{
|
||||
summonedCreature->SetReactState(REACT_PASSIVE);
|
||||
summonedCreature->setDeathState(DeathState::JustRespawned);
|
||||
summonedCreature->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -382,11 +389,53 @@ struct boss_kaelthas : public BossAI
|
||||
}
|
||||
}
|
||||
});
|
||||
ScheduleUniqueTimedEvent(2min, [&]{
|
||||
scheduler.Schedule(2min, GROUP_PROGRESS_PHASE, [this](TaskContext)
|
||||
{
|
||||
PhaseAllAdvisorsExecute();
|
||||
}, EVENT_PREFIGHT_PHASE61);
|
||||
});
|
||||
}, EVENT_PREFIGHT_PHASE52);
|
||||
break;
|
||||
case ACTION_PROGRESS_PHASE_CHECK:
|
||||
if (_phase == PHASE_WEAPONS)
|
||||
{
|
||||
bool aliveWeapon = false;
|
||||
summons.DoForAllSummons([&aliveWeapon](WorldObject* summon)
|
||||
{
|
||||
if (Creature* summonedCreature = summon->ToCreature())
|
||||
{
|
||||
if (summonedCreature->IsAlive())
|
||||
{
|
||||
if (summonedCreature->GetEntry() >= NPC_NETHERSTRAND_LONGBOW && summonedCreature->GetEntry() <= NPC_STAFF_OF_DISINTEGRATION)
|
||||
{
|
||||
aliveWeapon = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!aliveWeapon)
|
||||
PhaseAllAdvisorsExecute();
|
||||
}
|
||||
else if (_phase == PHASE_ALL_ADVISORS)
|
||||
{
|
||||
bool advisorAlive = false;
|
||||
summons.DoForAllSummons([&advisorAlive](WorldObject* summon)
|
||||
{
|
||||
if (Creature* summonedCreature = summon->ToCreature())
|
||||
{
|
||||
if (summonedCreature->IsAlive())
|
||||
{
|
||||
if (summonedCreature->GetEntry() >= NPC_LORD_SANGUINAR && summonedCreature->GetEntry() <= NPC_THALADRED)
|
||||
{
|
||||
advisorAlive = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!advisorAlive)
|
||||
PhaseKaelExecute();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -629,17 +678,7 @@ struct boss_kaelthas : public BossAI
|
||||
|
||||
void PhaseAllAdvisorsExecute()
|
||||
{
|
||||
//remove all weapons so they don't get revived
|
||||
summons.DoForAllSummons([&](WorldObject* summon)
|
||||
{
|
||||
if (Creature* summonedCreature = summon->ToCreature())
|
||||
{
|
||||
if (summonedCreature->GetEntry() >= 21268 && summonedCreature->GetEntry() <= 21274)
|
||||
{
|
||||
summonedCreature->DespawnOrUnsummon();
|
||||
}
|
||||
}
|
||||
});
|
||||
scheduler.CancelGroup(GROUP_PROGRESS_PHASE);
|
||||
_phase = PHASE_ALL_ADVISORS;
|
||||
Talk(SAY_PHASE3_ADVANCE);
|
||||
ScheduleUniqueTimedEvent(6s, [&]{
|
||||
@@ -662,9 +701,10 @@ struct boss_kaelthas : public BossAI
|
||||
}
|
||||
}
|
||||
});
|
||||
ScheduleUniqueTimedEvent(3min, [&]{
|
||||
scheduler.Schedule(3min, GROUP_PROGRESS_PHASE, [this](TaskContext)
|
||||
{
|
||||
PhaseKaelExecute();
|
||||
}, EVENT_PREFIGHT_PHASE71);
|
||||
});
|
||||
}, EVENT_PREFIGHT_PHASE63);
|
||||
}
|
||||
|
||||
@@ -778,15 +818,16 @@ struct npc_lord_sanguinar : public ScriptedAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (!_hasDied)
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
{
|
||||
Talk(SAY_SANGUINAR_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
|
||||
if (!_hasDied)
|
||||
{
|
||||
Talk(SAY_SANGUINAR_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
kael->AI()->DoAction(ACTION_START_CAPERNIAN);
|
||||
_hasDied = true;
|
||||
}
|
||||
_hasDied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -830,7 +871,7 @@ struct npc_capernian : public ScriptedAI
|
||||
{
|
||||
if (me->Attack(who, false))
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(who, 45.0f, 0);
|
||||
me->GetMotionMaster()->MoveChase(who, 30.0f, 0);
|
||||
me->AddThreat(who, 0.0f);
|
||||
}
|
||||
}
|
||||
@@ -850,7 +891,7 @@ struct npc_capernian : public ScriptedAI
|
||||
}
|
||||
else
|
||||
{
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), 45.0f);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim(), 30.0f);
|
||||
DoCastVictim(SPELL_CAPERNIAN_FIREBALL);
|
||||
}
|
||||
|
||||
@@ -865,15 +906,16 @@ struct npc_capernian : public ScriptedAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (!_hasDied)
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
{
|
||||
Talk(SAY_CAPERNIAN_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
|
||||
if (!_hasDied)
|
||||
{
|
||||
Talk(SAY_CAPERNIAN_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
kael->AI()->DoAction(ACTION_START_TELONICUS);
|
||||
_hasDied = true;
|
||||
}
|
||||
_hasDied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -927,15 +969,16 @@ struct npc_telonicus : public ScriptedAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (!_hasDied)
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
{
|
||||
Talk(SAY_TELONICUS_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
|
||||
if (!_hasDied)
|
||||
{
|
||||
Talk(SAY_TELONICUS_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
kael->AI()->DoAction(ACTION_START_WEAPONS);
|
||||
_hasDied = true;
|
||||
}
|
||||
_hasDied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1011,15 +1054,16 @@ struct npc_thaladred : public ScriptedAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (!_hasDied)
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
{
|
||||
Talk(SAY_THALADRED_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
if (Creature* kael = _instance->GetCreature(DATA_KAELTHAS))
|
||||
kael->AI()->DoAction(ACTION_PROGRESS_PHASE_CHECK);
|
||||
if (!_hasDied)
|
||||
{
|
||||
Talk(SAY_THALADRED_DEATH);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
kael->AI()->DoAction(ACTION_START_SANGUINAR);
|
||||
_hasDied = true;
|
||||
}
|
||||
_hasDied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1040,200 +1084,123 @@ private:
|
||||
bool _hasDied;
|
||||
};
|
||||
|
||||
class spell_kaelthas_kael_phase_two : public SpellScriptLoader
|
||||
class spell_kaelthas_kael_phase_two : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_kael_phase_two() : SpellScriptLoader("spell_kaelthas_kael_phase_two") { }
|
||||
PrepareSpellScript(spell_kaelthas_kael_phase_two);
|
||||
|
||||
class spell_kaelthas_kael_phase_two_SpellScript : public SpellScript
|
||||
bool Load() override
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_kael_phase_two_SpellScript);
|
||||
if (GetCaster()->GetTypeId() == TYPEID_UNIT)
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
if (Creature* kael = instance->GetCreature(DATA_KAELTHAS))
|
||||
kael->AI()->SummonedCreatureDies(GetCaster()->ToCreature(), nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
if (GetCaster()->GetTypeId() == TYPEID_UNIT)
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
if (Creature* kael = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(NPC_KAELTHAS)))
|
||||
kael->AI()->SummonedCreatureDies(GetCaster()->ToCreature(), nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_kael_phase_two_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_remote_toy : public SpellScriptLoader
|
||||
class spell_kaelthas_remote_toy : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_remote_toy() : SpellScriptLoader("spell_kaelthas_remote_toy") { }
|
||||
PrepareAuraScript(spell_kaelthas_remote_toy);
|
||||
|
||||
class spell_kaelthas_remote_toy_AuraScript : public AuraScript
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PrepareAuraScript(spell_kaelthas_remote_toy_AuraScript);
|
||||
PreventDefaultAction();
|
||||
if (roll_chance_i(66))
|
||||
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_REMOTE_TOY_STUN, true);
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (roll_chance_i(66))
|
||||
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_REMOTE_TOY_STUN, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_remote_toy_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_remote_toy_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_remote_toy::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_summon_weapons : public SpellScriptLoader
|
||||
class spell_kaelthas_summon_weapons : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_summon_weapons() : SpellScriptLoader("spell_kaelthas_summon_weapons") { }
|
||||
PrepareSpellScript(spell_kaelthas_summon_weapons);
|
||||
|
||||
class spell_kaelthas_summon_weapons_SpellScript : public SpellScript
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_summon_weapons_SpellScript);
|
||||
PreventHitEffect(effIndex);
|
||||
for (uint32 i = SPELL_SUMMON_WEAPONA; i <= SPELL_SUMMON_WEAPONG; ++i)
|
||||
GetCaster()->CastSpell(GetCaster(), i, true);
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitEffect(effIndex);
|
||||
for (uint32 i = SPELL_SUMMON_WEAPONA; i <= SPELL_SUMMON_WEAPONG; ++i)
|
||||
GetCaster()->CastSpell(GetCaster(), i, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_weapons_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_summon_weapons_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_weapons::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_resurrection : public SpellScriptLoader
|
||||
class spell_kaelthas_resurrection : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_resurrection() : SpellScriptLoader("spell_kaelthas_resurrection") { }
|
||||
PrepareSpellScript(spell_kaelthas_resurrection);
|
||||
|
||||
class spell_kaelthas_resurrection_SpellScript : public SpellScript
|
||||
void HandleBeforeCast()
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_resurrection_SpellScript);
|
||||
GetCaster()->GetAI()->SetData(DATA_RESURRECT_CAST, DATA_RESURRECT_CAST);
|
||||
}
|
||||
|
||||
void HandleBeforeCast()
|
||||
{
|
||||
GetCaster()->GetAI()->SetData(DATA_RESURRECT_CAST, DATA_RESURRECT_CAST);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
BeforeCast += SpellCastFn(spell_kaelthas_resurrection_SpellScript::HandleBeforeCast);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_resurrection_SpellScript();
|
||||
BeforeCast += SpellCastFn(spell_kaelthas_resurrection::HandleBeforeCast);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_mind_control : public SpellScriptLoader
|
||||
class spell_kaelthas_mind_control : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_mind_control() : SpellScriptLoader("spell_kaelthas_mind_control") { }
|
||||
PrepareSpellScript(spell_kaelthas_mind_control);
|
||||
|
||||
class spell_kaelthas_mind_control_SpellScript : public SpellScript
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_mind_control_SpellScript);
|
||||
if (Unit* victim = GetCaster()->GetVictim())
|
||||
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
|
||||
}
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (Unit* victim = GetCaster()->GetVictim())
|
||||
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kaelthas_mind_control_SpellScript::SelectTarget, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_mind_control_SpellScript();
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kaelthas_mind_control::SelectTarget, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_burn : public SpellScriptLoader
|
||||
class spell_kaelthas_burn : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_burn() : SpellScriptLoader("spell_kaelthas_burn") { }
|
||||
PrepareAuraScript(spell_kaelthas_burn);
|
||||
|
||||
class spell_kaelthas_burn_AuraScript : public AuraScript
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PrepareAuraScript(spell_kaelthas_burn_AuraScript);
|
||||
Unit::DealDamage(GetUnitOwner(), GetUnitOwner(), GetUnitOwner()->CountPctFromMaxHealth(5) + 1);
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
Unit::DealDamage(GetUnitOwner(), GetUnitOwner(), GetUnitOwner()->CountPctFromMaxHealth(5) + 1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_burn_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_burn_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kaelthas_burn::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_flame_strike : public SpellScriptLoader
|
||||
class spell_kaelthas_flame_strike : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_flame_strike() : SpellScriptLoader("spell_kaelthas_flame_strike") { }
|
||||
PrepareAuraScript(spell_kaelthas_flame_strike);
|
||||
|
||||
class spell_kaelthas_flame_strike_AuraScript : public AuraScript
|
||||
bool Load() override
|
||||
{
|
||||
PrepareAuraScript(spell_kaelthas_flame_strike_AuraScript);
|
||||
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
|
||||
}
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
return GetUnitOwner()->GetTypeId() == TYPEID_UNIT;
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetUnitOwner()->RemoveAllAuras();
|
||||
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_FLAME_STRIKE_DAMAGE, true);
|
||||
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_kaelthas_flame_strike_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
return new spell_kaelthas_flame_strike_AuraScript();
|
||||
GetUnitOwner()->RemoveAllAuras();
|
||||
GetUnitOwner()->CastSpell(GetUnitOwner(), SPELL_FLAME_STRIKE_DAMAGE, true);
|
||||
GetUnitOwner()->ToCreature()->DespawnOrUnsummon(2000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_kaelthas_flame_strike::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1260,111 +1227,78 @@ private:
|
||||
Player* _owner;
|
||||
};
|
||||
|
||||
class spell_kaelthas_gravity_lapse : public SpellScriptLoader
|
||||
class spell_kaelthas_gravity_lapse : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_gravity_lapse() : SpellScriptLoader("spell_kaelthas_gravity_lapse") { }
|
||||
PrepareSpellScript(spell_kaelthas_gravity_lapse);
|
||||
|
||||
class spell_kaelthas_gravity_lapse_SpellScript : public SpellScript
|
||||
bool Load() override
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_gravity_lapse_SpellScript);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
_currentSpellId = SPELL_GRAVITY_LAPSE_TELEPORT1;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitEffect(effIndex);
|
||||
if (_currentSpellId < SPELL_GRAVITY_LAPSE_TELEPORT1 + 25)
|
||||
if (Player* target = GetHitPlayer())
|
||||
{
|
||||
GetCaster()->CastSpell(target, _currentSpellId++, true);
|
||||
target->m_Events.AddEvent(new lapseTeleport(target), target->m_Events.CalculateTime(1));
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_gravity_lapse_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _currentSpellId;
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_kaelthas_gravity_lapse_SpellScript();
|
||||
_currentSpellId = SPELL_GRAVITY_LAPSE_TELEPORT1;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_nether_beam : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_nether_beam() : SpellScriptLoader("spell_kaelthas_nether_beam") { }
|
||||
|
||||
class spell_kaelthas_nether_beam_SpellScript : public SpellScript
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_nether_beam_SpellScript);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitEffect(effIndex);
|
||||
|
||||
ThreatContainer::StorageType const& ThreatList = GetCaster()-> GetThreatMgr().GetThreatList();
|
||||
std::list<Unit*> targetList;
|
||||
for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr)
|
||||
PreventHitEffect(effIndex);
|
||||
if (_currentSpellId < SPELL_GRAVITY_LAPSE_TELEPORT1 + 25)
|
||||
if (Player* target = GetHitPlayer())
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*GetCaster(), (*itr)->getUnitGuid());
|
||||
if (target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targetList.push_back(target);
|
||||
GetCaster()->CastSpell(target, _currentSpellId++, true);
|
||||
target->m_Events.AddEvent(new lapseTeleport(target), target->m_Events.CalculateTime(1));
|
||||
}
|
||||
}
|
||||
|
||||
Acore::Containers::RandomResize(targetList, 5);
|
||||
for (std::list<Unit*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
GetCaster()->CastSpell(*itr, SPELL_NETHER_BEAM_DAMAGE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_nether_beam_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_nether_beam_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_gravity_lapse::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _currentSpellId;
|
||||
};
|
||||
|
||||
class spell_kaelthas_nether_beam : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_nether_beam);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitEffect(effIndex);
|
||||
|
||||
ThreatContainer::StorageType const& ThreatList = GetCaster()-> GetThreatMgr().GetThreatList();
|
||||
std::list<Unit*> targetList;
|
||||
for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr)
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*GetCaster(), (*itr)->getUnitGuid());
|
||||
if (target && target->GetTypeId() == TYPEID_PLAYER)
|
||||
targetList.push_back(target);
|
||||
}
|
||||
|
||||
Acore::Containers::RandomResize(targetList, 5);
|
||||
for (std::list<Unit*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
GetCaster()->CastSpell(*itr, SPELL_NETHER_BEAM_DAMAGE, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_nether_beam::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kaelthas_summon_nether_vapor : public SpellScriptLoader
|
||||
class spell_kaelthas_summon_nether_vapor : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kaelthas_summon_nether_vapor() : SpellScriptLoader("spell_kaelthas_summon_nether_vapor") { }
|
||||
PrepareSpellScript(spell_kaelthas_summon_nether_vapor);
|
||||
|
||||
class spell_kaelthas_summon_nether_vapor_SpellScript : public SpellScript
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_summon_nether_vapor_SpellScript);
|
||||
PreventHitEffect(effIndex);
|
||||
for (uint32 i = 0; i < 5; ++i)
|
||||
GetCaster()->SummonCreature(NPC_NETHER_VAPOR, GetCaster()->GetPositionX() + 6 * cos(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionY() + 6 * std::sin(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionZ() + 7.0f + i, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitEffect(effIndex);
|
||||
for (uint32 i = 0; i < 5; ++i)
|
||||
GetCaster()->SummonCreature(NPC_NETHER_VAPOR, GetCaster()->GetPositionX() + 6 * cos(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionY() + 6 * std::sin(i / 5.0f * 2 * M_PI), GetCaster()->GetPositionZ() + 7.0f + i, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_nether_vapor_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_kaelthas_summon_nether_vapor_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_summon_nether_vapor::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1375,15 +1309,15 @@ void AddSC_boss_kaelthas()
|
||||
RegisterTheEyeAI(npc_capernian);
|
||||
RegisterTheEyeAI(npc_telonicus);
|
||||
RegisterTheEyeAI(npc_thaladred);
|
||||
new spell_kaelthas_kael_phase_two();
|
||||
new spell_kaelthas_remote_toy();
|
||||
new spell_kaelthas_summon_weapons();
|
||||
new spell_kaelthas_resurrection();
|
||||
new spell_kaelthas_mind_control();
|
||||
new spell_kaelthas_burn();
|
||||
new spell_kaelthas_flame_strike();
|
||||
new spell_kaelthas_gravity_lapse();
|
||||
new spell_kaelthas_nether_beam();
|
||||
new spell_kaelthas_summon_nether_vapor();
|
||||
RegisterSpellScript(spell_kaelthas_kael_phase_two);
|
||||
RegisterSpellScript(spell_kaelthas_remote_toy);
|
||||
RegisterSpellScript(spell_kaelthas_summon_weapons);
|
||||
RegisterSpellScript(spell_kaelthas_resurrection);
|
||||
RegisterSpellScript(spell_kaelthas_mind_control);
|
||||
RegisterSpellScript(spell_kaelthas_burn);
|
||||
RegisterSpellScript(spell_kaelthas_flame_strike);
|
||||
RegisterSpellScript(spell_kaelthas_gravity_lapse);
|
||||
RegisterSpellScript(spell_kaelthas_nether_beam);
|
||||
RegisterSpellScript(spell_kaelthas_summon_nether_vapor);
|
||||
}
|
||||
|
||||
|
||||
@@ -768,13 +768,12 @@ class spell_gen_proc_not_self : public AuraScript
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* target = eventInfo.GetActionTarget())
|
||||
{
|
||||
ObjectGuid targetGUID = target->GetGUID();
|
||||
uint32 spellID = aurEff->GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
|
||||
caster->m_Events.AddEventAtOffset([caster, target, spellID]()
|
||||
caster->m_Events.AddEventAtOffset([caster, targetGUID, spellID]()
|
||||
{
|
||||
if (target)
|
||||
{
|
||||
if (Unit *target = ObjectAccessor::GetUnit(*caster, targetGUID))
|
||||
caster->CastSpell(target, spellID, true);
|
||||
}
|
||||
}, 100ms);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ public:
|
||||
{
|
||||
npc_training_dummyAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); //imune to knock aways like blast wave
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ public:
|
||||
{
|
||||
npc_target_dummyAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
SetCombatMovement(false);
|
||||
me->SetCombatMovement(false);
|
||||
deathTimer = 15000;
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); //imune to knock aways like blast wave
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ char* DBCDatabaseLoader::Load(uint32& records, char**& indexTable)
|
||||
std::string query = Acore::StringFormat("SELECT * FROM `%s` ORDER BY `ID` DESC", _sqlTableName);
|
||||
|
||||
// no error if empty set
|
||||
QueryResult result = WorldDatabase.Query(query.c_str());
|
||||
QueryResult result = WorldDatabase.Query(query);
|
||||
if (!result)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -21,20 +21,12 @@
|
||||
#include "Define.h"
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct DBCPosition2D
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
};
|
||||
|
||||
struct DBCPosition3D
|
||||
{
|
||||
float X;
|
||||
float Y;
|
||||
float Z;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Client expected level limitation, like as used in DBC item max levels for "until max player level"
|
||||
|
||||
@@ -27,11 +27,7 @@
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
#if BOOST_VERSION >= 106600
|
||||
#define ACORE_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_listen_connections
|
||||
#else
|
||||
#define ACORE_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_connections
|
||||
#endif
|
||||
constexpr auto ACORE_MAX_LISTEN_CONNECTIONS = boost::asio::socket_base::max_listen_connections;
|
||||
|
||||
class AsyncAcceptor
|
||||
{
|
||||
@@ -40,7 +36,7 @@ public:
|
||||
|
||||
AsyncAcceptor(Acore::Asio::IoContext& ioContext, std::string const& bindIp, uint16 port) :
|
||||
_acceptor(ioContext), _endpoint(Acore::Net::make_address(bindIp), port),
|
||||
_socket(ioContext), _closed(false), _socketFactory(std::bind(&AsyncAcceptor::DefeaultSocketFactory, this))
|
||||
_socket(ioContext), _closed(false), _socketFactory([this](){ return DefaultSocketFactory(); })
|
||||
{
|
||||
}
|
||||
|
||||
@@ -122,7 +118,7 @@ public:
|
||||
void SetSocketFactory(std::function<std::pair<tcp::socket*, uint32>()> func) { _socketFactory = func; }
|
||||
|
||||
private:
|
||||
std::pair<tcp::socket*, uint32> DefeaultSocketFactory() { return std::make_pair(&_socket, 0); }
|
||||
std::pair<tcp::socket*, uint32> DefaultSocketFactory() { return std::make_pair(&_socket, 0); }
|
||||
|
||||
tcp::acceptor _acceptor;
|
||||
tcp::endpoint _endpoint;
|
||||
@@ -155,4 +151,4 @@ void AsyncAcceptor::AsyncAccept()
|
||||
});
|
||||
}
|
||||
|
||||
#endif /* __ASYNCACCEPT_H_ */
|
||||
#endif /* __ASYNC ACCEPT_H_ */
|
||||
|
||||
@@ -73,12 +73,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::asio::ip::address GetRemoteIpAddress() const
|
||||
[[nodiscard]] boost::asio::ip::address GetRemoteIpAddress() const
|
||||
{
|
||||
return _remoteAddress;
|
||||
}
|
||||
|
||||
uint16 GetRemotePort() const
|
||||
[[nodiscard]] uint16 GetRemotePort() const
|
||||
{
|
||||
return _remotePort;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsOpen() const { return !_closed && !_closing; }
|
||||
[[nodiscard]] bool IsOpen() const { return !_closed && !_closing; }
|
||||
|
||||
void CloseSocket()
|
||||
{
|
||||
@@ -146,7 +146,7 @@ protected:
|
||||
virtual void OnClose() { }
|
||||
virtual void ReadHandler() = 0;
|
||||
|
||||
bool AsyncProcessQueue()
|
||||
[[nodiscard]] bool AsyncProcessQueue()
|
||||
{
|
||||
if (_isWritingAsync)
|
||||
return false;
|
||||
|
||||
@@ -104,9 +104,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
int32 GetNetworkThreadCount() const { return _threadCount; }
|
||||
[[nodiscard]] int32 GetNetworkThreadCount() const { return _threadCount; }
|
||||
|
||||
uint32 SelectThreadWithMinConnections() const
|
||||
[[nodiscard]] uint32 SelectThreadWithMinConnections() const
|
||||
{
|
||||
uint32 min = 0;
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ std::string ByteBuffer::ReadCString(bool requireValidUtf8 /*= true*/)
|
||||
{
|
||||
std::string value;
|
||||
|
||||
while (rpos() < size()) // prevent crash at wrong string format in packet
|
||||
while (rpos() < size()) // prevent crash the wrong string format in a packet
|
||||
{
|
||||
char c = read<char>();
|
||||
if (c == 0)
|
||||
@@ -94,7 +94,7 @@ std::string ByteBuffer::ReadCString(bool requireValidUtf8 /*= true*/)
|
||||
|
||||
uint32 ByteBuffer::ReadPackedTime()
|
||||
{
|
||||
uint32 packedDate = read<uint32>();
|
||||
auto packedDate = read<uint32>();
|
||||
tm lt = tm();
|
||||
|
||||
lt.tm_min = packedDate & 0x3F;
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
class AC_SHARED_API ByteBuffer
|
||||
{
|
||||
public:
|
||||
constexpr static size_t DEFAULT_SIZE = 0x1000;
|
||||
constexpr static std::size_t DEFAULT_SIZE = 0x1000;
|
||||
|
||||
// constructor
|
||||
ByteBuffer()
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
_storage.reserve(DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
|
||||
explicit ByteBuffer(std::size_t reserve) : _rpos(0), _wpos(0)
|
||||
{
|
||||
_storage.reserve(reserve);
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
}
|
||||
|
||||
ByteBuffer(ByteBuffer const& right) = default;
|
||||
ByteBuffer(MessageBuffer&& buffer);
|
||||
explicit ByteBuffer(MessageBuffer&& buffer);
|
||||
virtual ~ByteBuffer() = default;
|
||||
|
||||
ByteBuffer& operator=(ByteBuffer const& right)
|
||||
|
||||
@@ -24,7 +24,7 @@ boost::asio::ip::tcp_endpoint Realm::GetAddressForClient(boost::asio::ip::addres
|
||||
{
|
||||
boost::asio::ip::address realmIp;
|
||||
|
||||
// Attempt to send best address for client
|
||||
// Attempt to send best address for a client
|
||||
if (clientAddr.is_loopback())
|
||||
{
|
||||
// Try guessing if realm is also connected locally
|
||||
@@ -52,5 +52,5 @@ boost::asio::ip::tcp_endpoint Realm::GetAddressForClient(boost::asio::ip::addres
|
||||
}
|
||||
|
||||
// Return external IP
|
||||
return boost::asio::ip::tcp_endpoint(realmIp, Port);
|
||||
return { realmIp, Port };
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ void RealmList::LoadBuildInfo()
|
||||
|
||||
void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
|
||||
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population)
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 realmTimezone, AccountTypes allowedSecurityLevel, float population)
|
||||
{
|
||||
// Create new if not exist or update existed
|
||||
Realm& realm = _realms[id];
|
||||
@@ -102,7 +102,7 @@ void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string con
|
||||
realm.Name = name;
|
||||
realm.Type = icon;
|
||||
realm.Flags = flag;
|
||||
realm.Timezone = timezone;
|
||||
realm.Timezone = realmTimezone;
|
||||
realm.AllowedSecurityLevel = allowedSecurityLevel;
|
||||
realm.PopulationLevel = population;
|
||||
|
||||
@@ -192,8 +192,8 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
icon = REALM_TYPE_NORMAL;
|
||||
}
|
||||
|
||||
RealmFlags flag = RealmFlags(fields[7].Get<uint8>());
|
||||
uint8 timezone = fields[8].Get<uint8>();
|
||||
auto flag = RealmFlags(fields[7].Get<uint8>());
|
||||
uint8 realmTimezone = fields[8].Get<uint8>();
|
||||
uint8 allowedSecurityLevel = fields[9].Get<uint8>();
|
||||
float pop = fields[10].Get<float>();
|
||||
uint32 build = fields[11].Get<uint32>();
|
||||
@@ -201,7 +201,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
RealmHandle id{ realmId };
|
||||
|
||||
UpdateRealm(id, build, name, externalAddress->address(), localAddress->address(), localSubmask->address(), port, icon, flag,
|
||||
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
|
||||
realmTimezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
|
||||
|
||||
if (!existingRealms.count(id))
|
||||
{
|
||||
@@ -228,7 +228,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
if (_updateInterval)
|
||||
{
|
||||
_updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
|
||||
_updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, std::placeholders::_1));
|
||||
_updateTimer->async_wait([this](boost::system::error_code const& errorCode){ UpdateRealms(errorCode); });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ private:
|
||||
void UpdateRealms(boost::system::error_code const& error);
|
||||
void UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
|
||||
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 realmTimezone, AccountTypes allowedSecurityLevel, float population);
|
||||
|
||||
std::vector<RealmBuildInfo> _builds;
|
||||
RealmMap _realms;
|
||||
|
||||
Reference in New Issue
Block a user