Merge branch 'master' into Playerbot
This commit is contained in:
@@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC);
|
||||
PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId WHERE entry = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH);
|
||||
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id1 = ? OR id2 = ? OR id3 = ?", CONNECTION_SYNCH);
|
||||
|
||||
@@ -223,14 +223,14 @@ void CreatureAI::EnterEvadeMode(EvadeReason why)
|
||||
me->GetVehicleKit()->Reset(true);
|
||||
}
|
||||
|
||||
sScriptMgr->OnUnitEnterEvadeMode(me, why);
|
||||
|
||||
// despawn bosses at reset - only verified tbc/woltk bosses with this reset type
|
||||
CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(me->GetEntry());
|
||||
if (cInfo && cInfo->HasFlagsExtra(CREATURE_FLAG_EXTRA_HARD_RESET))
|
||||
{
|
||||
me->DespawnOnEvade();
|
||||
}
|
||||
|
||||
sScriptMgr->OnUnitEnterEvadeMode(me, why);
|
||||
}
|
||||
|
||||
/*void CreatureAI::AttackedBy(Unit* attacker)
|
||||
|
||||
@@ -650,6 +650,16 @@ void BossAI::_JustEngagedWith()
|
||||
}
|
||||
}
|
||||
|
||||
void BossAI::_EnterEvadeMode(EvadeReason why)
|
||||
{
|
||||
CreatureAI::EnterEvadeMode(why);
|
||||
if (instance)
|
||||
{
|
||||
instance->SetBossState(_bossId, NOT_STARTED);
|
||||
instance->SaveToDB();
|
||||
}
|
||||
}
|
||||
|
||||
void BossAI::TeleportCheaters()
|
||||
{
|
||||
float x, y, z;
|
||||
|
||||
@@ -488,6 +488,7 @@ public:
|
||||
|
||||
void Reset() override { _Reset(); }
|
||||
void JustEngagedWith(Unit* /*who*/) override { _JustEngagedWith(); }
|
||||
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override { _EnterEvadeMode(why); }
|
||||
void JustDied(Unit* /*killer*/) override { _JustDied(); }
|
||||
void JustReachedHome() override { _JustReachedHome(); }
|
||||
|
||||
@@ -496,6 +497,7 @@ protected:
|
||||
void _JustEngagedWith();
|
||||
void _JustDied();
|
||||
void _JustReachedHome() { me->setActive(false); }
|
||||
void _EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER);
|
||||
[[nodiscard]] bool _ProccessHealthCheckEvent(uint8 healthPct, uint32 damage, std::function<void()> exec) const;
|
||||
|
||||
void TeleportCheaters();
|
||||
|
||||
@@ -424,10 +424,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
{
|
||||
if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature))
|
||||
{
|
||||
uint32 displayId = ObjectMgr::ChooseDisplayId(ci);
|
||||
target->ToCreature()->SetDisplayId(displayId);
|
||||
CreatureModel const* model = ObjectMgr::ChooseDisplayId(ci);
|
||||
target->ToCreature()->SetDisplayId(model->CreatureDisplayID, model->DisplayScale);
|
||||
LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL: Creature entry {}, GuidLow {} set displayid to {}",
|
||||
target->GetEntry(), target->GetGUID().ToString(), displayId);
|
||||
target->GetEntry(), target->GetGUID().ToString(), model->CreatureDisplayID);
|
||||
}
|
||||
}
|
||||
//if no param1, then use value from param2 (modelId)
|
||||
@@ -1316,7 +1316,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (e.action.morphOrMount.creature > 0)
|
||||
{
|
||||
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(e.action.morphOrMount.creature))
|
||||
target->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo));
|
||||
target->ToUnit()->Mount(ObjectMgr::ChooseDisplayId(cInfo)->CreatureDisplayID);
|
||||
}
|
||||
else
|
||||
target->ToUnit()->Mount(e.action.morphOrMount.model);
|
||||
|
||||
@@ -322,8 +322,12 @@ namespace Acore::Impl::ChatCommands
|
||||
oldTail = newTail;
|
||||
}
|
||||
|
||||
if (!sScriptMgr->OnTryExecuteCommand(handler, cmdStr))
|
||||
return true;
|
||||
|
||||
/* if we matched a command at some point, invoke it */
|
||||
if (cmd)
|
||||
{ /* if we matched a command at some point, invoke it */
|
||||
{
|
||||
handler.SetSentErrorMessage(false);
|
||||
if (cmd->IsInvokerVisible(handler) && cmd->_invoker(&handler, oldTail))
|
||||
{ /* invocation succeeded, log this */
|
||||
@@ -332,11 +336,6 @@ namespace Acore::Impl::ChatCommands
|
||||
}
|
||||
else if (!handler.HasSentErrorMessage()) /* invocation failed, we should show usage */
|
||||
{
|
||||
if (!sScriptMgr->CanExecuteCommand(handler, cmdStr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
cmd->SendCommandHelp(handler);
|
||||
handler.SetSentErrorMessage(true);
|
||||
}
|
||||
@@ -344,11 +343,6 @@ namespace Acore::Impl::ChatCommands
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!sScriptMgr->CanExecuteCommand(handler, cmdStr))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,51 +116,104 @@ VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extend
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 CreatureTemplate::GetRandomValidModelId() const
|
||||
CreatureModel const CreatureModel::DefaultInvisibleModel(11686, 1.0f, 1.0f);
|
||||
CreatureModel const CreatureModel::DefaultVisibleModel(17519, 1.0f, 1.0f);
|
||||
|
||||
CreatureModel const* CreatureTemplate::GetModelByIdx(uint32 idx) const
|
||||
{
|
||||
uint8 c = 0;
|
||||
uint32 modelIDs[4];
|
||||
|
||||
if (Modelid1) modelIDs[c++] = Modelid1;
|
||||
if (Modelid2) modelIDs[c++] = Modelid2;
|
||||
if (Modelid3) modelIDs[c++] = Modelid3;
|
||||
if (Modelid4) modelIDs[c++] = Modelid4;
|
||||
|
||||
return ((c > 0) ? modelIDs[urand(0, c - 1)] : 0);
|
||||
return idx < Models.size() ? &Models[idx] : nullptr;
|
||||
}
|
||||
|
||||
uint32 CreatureTemplate::GetFirstValidModelId() const
|
||||
CreatureModel const* CreatureTemplate::GetRandomValidModel() const
|
||||
{
|
||||
if (Modelid1) return Modelid1;
|
||||
if (Modelid2) return Modelid2;
|
||||
if (Modelid3) return Modelid3;
|
||||
if (Modelid4) return Modelid4;
|
||||
return 0;
|
||||
if (!Models.size())
|
||||
return nullptr;
|
||||
|
||||
// If only one element, ignore the Probability (even if 0)
|
||||
if (Models.size() == 1)
|
||||
return &Models[0];
|
||||
|
||||
auto selectedItr = Acore::Containers::SelectRandomWeightedContainerElement(Models, [](CreatureModel const& model)
|
||||
{
|
||||
return model.Probability;
|
||||
});
|
||||
|
||||
return &(*selectedItr);
|
||||
}
|
||||
|
||||
CreatureModel const* CreatureTemplate::GetFirstValidModel() const
|
||||
{
|
||||
for (CreatureModel const& model : Models)
|
||||
if (model.CreatureDisplayID)
|
||||
return &model;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CreatureModel const* CreatureTemplate::GetModelWithDisplayId(uint32 displayId) const
|
||||
{
|
||||
for (CreatureModel const& model : Models)
|
||||
if (displayId == model.CreatureDisplayID)
|
||||
return &model;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CreatureModel const* CreatureTemplate::GetFirstInvisibleModel() const
|
||||
{
|
||||
for (CreatureModel const& model : Models)
|
||||
if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID))
|
||||
if (modelInfo && modelInfo->is_trigger)
|
||||
return &model;
|
||||
|
||||
return &CreatureModel::DefaultInvisibleModel;
|
||||
}
|
||||
|
||||
CreatureModel const* CreatureTemplate::GetFirstVisibleModel() const
|
||||
{
|
||||
for (CreatureModel const& model : Models)
|
||||
if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID))
|
||||
if (modelInfo && !modelInfo->is_trigger)
|
||||
return &model;
|
||||
|
||||
return &CreatureModel::DefaultVisibleModel;
|
||||
}
|
||||
|
||||
void CreatureTemplate::InitializeQueryData()
|
||||
{
|
||||
queryData.Initialize(SMSG_CREATURE_QUERY_RESPONSE, 1);
|
||||
|
||||
queryData << uint32(Entry); // creature entry
|
||||
queryData << uint32(Entry); // creature entry
|
||||
queryData << Name;
|
||||
queryData << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
|
||||
queryData << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
|
||||
queryData << SubName;
|
||||
queryData << IconName; // "Directions" for guard, string for Icons 2.3.0
|
||||
queryData << uint32(type_flags); // flags
|
||||
queryData << uint32(type); // CreatureType.dbc
|
||||
queryData << uint32(family); // CreatureFamily.dbc
|
||||
queryData << uint32(rank); // Creature Rank (elite, boss, etc)
|
||||
queryData << uint32(KillCredit[0]); // new in 3.1, kill credit
|
||||
queryData << uint32(KillCredit[1]); // new in 3.1, kill credit
|
||||
queryData << uint32(Modelid1); // Modelid1
|
||||
queryData << uint32(Modelid2); // Modelid2
|
||||
queryData << uint32(Modelid3); // Modelid3
|
||||
queryData << uint32(Modelid4); // Modelid4
|
||||
queryData << float(ModHealth); // dmg/hp modifier
|
||||
queryData << float(ModMana); // dmg/mana modifier
|
||||
queryData << IconName; // "Directions" for guard, string for Icons 2.3.0
|
||||
queryData << uint32(type_flags); // flags
|
||||
queryData << uint32(type); // CreatureType.dbc
|
||||
queryData << uint32(family); // CreatureFamily.dbc
|
||||
queryData << uint32(rank); // Creature Rank (elite, boss, etc)
|
||||
queryData << uint32(KillCredit[0]); // new in 3.1, kill credit
|
||||
queryData << uint32(KillCredit[1]); // new in 3.1, kill credit
|
||||
if (GetModelByIdx(0))
|
||||
queryData << uint32(GetModelByIdx(0)->CreatureDisplayID); // Modelid1
|
||||
else
|
||||
queryData << uint32(0); // Modelid1
|
||||
if (GetModelByIdx(1))
|
||||
queryData << uint32(GetModelByIdx(1)->CreatureDisplayID); // Modelid2
|
||||
else
|
||||
queryData << uint32(0); // Modelid2
|
||||
if (GetModelByIdx(2))
|
||||
queryData << uint32(GetModelByIdx(2)->CreatureDisplayID); // Modelid3
|
||||
else
|
||||
queryData << uint32(0); // Modelid3
|
||||
if (GetModelByIdx(3))
|
||||
queryData << uint32(GetModelByIdx(3)->CreatureDisplayID); // Modelid4
|
||||
else
|
||||
queryData << uint32(0); // Modelid4
|
||||
queryData << float(ModHealth); // dmg/hp modifier
|
||||
queryData << float(ModMana); // dmg/mana modifier
|
||||
queryData << uint8(RacialLeader);
|
||||
queryData << uint32(movementId); // CreatureMovementInfo.dbc
|
||||
queryData << uint32(movementId); // CreatureMovementInfo.dbc
|
||||
}
|
||||
|
||||
bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
@@ -423,21 +476,22 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData* data)
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class));
|
||||
|
||||
// Cancel load if no model defined
|
||||
if (!(cinfo->GetFirstValidModelId()))
|
||||
if (!(cinfo->GetFirstValidModel()))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template`, can't load. ", Entry);
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template_model`, can't load. ", Entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 displayID = ObjectMgr::ChooseDisplayId(GetCreatureTemplate(), data);
|
||||
if (!sObjectMgr->GetCreatureModelRandomGender(&displayID)) // Cancel load if no model defined
|
||||
CreatureModel model = *ObjectMgr::ChooseDisplayId(cinfo, data);
|
||||
CreatureModelInfo const* mInfo = sObjectMgr->GetCreatureModelRandomGender(&model, cinfo);
|
||||
if (!mInfo) // Cancel load if no model defined
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template`, can't load. ", Entry);
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model {} defined in table `creature_template_model`, can't load. ", Entry, model.CreatureDisplayID);
|
||||
return false;
|
||||
}
|
||||
|
||||
SetDisplayId(displayID);
|
||||
SetNativeDisplayId(displayID);
|
||||
SetDisplayId(model.CreatureDisplayID, model.DisplayScale);
|
||||
SetNativeDisplayId(model.CreatureDisplayID);
|
||||
|
||||
// Load creature equipment
|
||||
if (!data)
|
||||
@@ -1121,11 +1175,12 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 displayID = GetNativeDisplayId();
|
||||
if (sObjectMgr->GetCreatureModelRandomGender(&displayID) && !IsTotem()) // Cancel load if no model defined or if totem
|
||||
CreatureModel display(GetNativeDisplayId(), GetNativeObjectScale(), 1.0f);
|
||||
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, cinfo);
|
||||
if (minfo && !IsTotem()) // Cancel load if no model defined or if totem
|
||||
{
|
||||
SetDisplayId(displayID);
|
||||
SetNativeDisplayId(displayID);
|
||||
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
|
||||
SetNativeDisplayId(display.CreatureDisplayID);
|
||||
}
|
||||
|
||||
LoadCreaturesAddon();
|
||||
@@ -1361,9 +1416,9 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
|
||||
CreatureTemplate const* cinfo = GetCreatureTemplate();
|
||||
if (cinfo)
|
||||
{
|
||||
if (displayId == cinfo->Modelid1 || displayId == cinfo->Modelid2 ||
|
||||
displayId == cinfo->Modelid3 || displayId == cinfo->Modelid4)
|
||||
displayId = 0;
|
||||
for (CreatureModel model : cinfo->Models)
|
||||
if (displayId && displayId == model.CreatureDisplayID)
|
||||
displayId = 0;
|
||||
|
||||
if (npcflag == cinfo->npcflag)
|
||||
npcflag = 0;
|
||||
@@ -2032,11 +2087,12 @@ void Creature::Respawn(bool force)
|
||||
// Do not override transform auras
|
||||
if (GetAuraEffectsByType(SPELL_AURA_TRANSFORM).empty())
|
||||
{
|
||||
uint32 displayID = GetNativeDisplayId();
|
||||
if (sObjectMgr->GetCreatureModelRandomGender(&displayID)) // Cancel load if no model defined
|
||||
CreatureModel display(GetNativeDisplayId(), GetNativeObjectScale(), 1.0f);
|
||||
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, GetCreatureTemplate());
|
||||
if (minfo) // Cancel load if no model defined
|
||||
{
|
||||
SetDisplayId(displayID);
|
||||
SetNativeDisplayId(displayID);
|
||||
SetDisplayId(display.CreatureDisplayID, display.DisplayScale);
|
||||
SetNativeDisplayId(display.CreatureDisplayID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3415,9 +3471,9 @@ void Creature::SetObjectScale(float scale)
|
||||
SetFloatValue(UNIT_FIELD_COMBATREACH, combatReach * scale);
|
||||
}
|
||||
|
||||
void Creature::SetDisplayId(uint32 modelId)
|
||||
void Creature::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/)
|
||||
{
|
||||
Unit::SetDisplayId(modelId);
|
||||
Unit::SetDisplayId(modelId, displayScale);
|
||||
|
||||
float combatReach = DEFAULT_WORLD_OBJECT_SIZE;
|
||||
|
||||
@@ -3431,9 +3487,17 @@ void Creature::SetDisplayId(uint32 modelId)
|
||||
if (IsPet())
|
||||
combatReach = DEFAULT_COMBAT_REACH;
|
||||
|
||||
SetObjectScale(displayScale);
|
||||
|
||||
SetFloatValue(UNIT_FIELD_COMBATREACH, combatReach * GetObjectScale());
|
||||
}
|
||||
|
||||
void Creature::SetDisplayFromModel(uint32 modelIdx)
|
||||
{
|
||||
if (CreatureModel const* model = GetCreatureTemplate()->GetModelByIdx(modelIdx))
|
||||
SetDisplayId(model->CreatureDisplayID, model->DisplayScale);
|
||||
}
|
||||
|
||||
void Creature::SetTarget(ObjectGuid guid)
|
||||
{
|
||||
if (!_focusSpell)
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
|
||||
float GetNativeObjectScale() const override;
|
||||
void SetObjectScale(float scale) override;
|
||||
void SetDisplayId(uint32 modelId) override;
|
||||
void SetDisplayId(uint32 displayId, float displayScale = 1.f) override;
|
||||
void SetDisplayFromModel(uint32 modelIdx);
|
||||
|
||||
void DisappearAndDie();
|
||||
|
||||
|
||||
@@ -171,16 +171,29 @@ struct CreatureMovementData
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
struct CreatureModel
|
||||
{
|
||||
static CreatureModel const DefaultInvisibleModel;
|
||||
static CreatureModel const DefaultVisibleModel;
|
||||
|
||||
CreatureModel() :
|
||||
CreatureDisplayID(0), DisplayScale(0.0f), Probability(0.0f) { }
|
||||
|
||||
CreatureModel(uint32 creatureDisplayID, float displayScale, float probability) :
|
||||
CreatureDisplayID(creatureDisplayID), DisplayScale(displayScale), Probability(probability) { }
|
||||
|
||||
uint32 CreatureDisplayID;
|
||||
float DisplayScale;
|
||||
float Probability;
|
||||
};
|
||||
|
||||
// from `creature_template` table
|
||||
struct CreatureTemplate
|
||||
{
|
||||
uint32 Entry;
|
||||
uint32 DifficultyEntry[MAX_DIFFICULTY - 1];
|
||||
uint32 KillCredit[MAX_KILL_CREDIT];
|
||||
uint32 Modelid1;
|
||||
uint32 Modelid2;
|
||||
uint32 Modelid3;
|
||||
uint32 Modelid4;
|
||||
std::vector<CreatureModel> Models;
|
||||
std::string Name;
|
||||
std::string SubName;
|
||||
std::string IconName;
|
||||
@@ -239,8 +252,12 @@ struct CreatureTemplate
|
||||
uint32 flags_extra;
|
||||
uint32 ScriptID;
|
||||
WorldPacket queryData; // pussywizard
|
||||
[[nodiscard]] uint32 GetRandomValidModelId() const;
|
||||
[[nodiscard]] uint32 GetFirstValidModelId() const;
|
||||
CreatureModel const* GetModelByIdx(uint32 idx) const;
|
||||
CreatureModel const* GetRandomValidModel() const;
|
||||
CreatureModel const* GetFirstValidModel() const;
|
||||
CreatureModel const* GetModelWithDisplayId(uint32 displayId) const;
|
||||
CreatureModel const* GetFirstInvisibleModel() const;
|
||||
CreatureModel const* GetFirstVisibleModel() const;
|
||||
|
||||
// helpers
|
||||
[[nodiscard]] SkillType GetRequiredLootSkill() const
|
||||
@@ -390,6 +407,7 @@ struct CreatureModelInfo
|
||||
float combat_reach;
|
||||
uint8 gender;
|
||||
uint32 modelid_other_gender;
|
||||
float is_trigger;
|
||||
};
|
||||
|
||||
// Benchmarked: Faster than std::map (insert/find)
|
||||
|
||||
@@ -451,7 +451,6 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
|
||||
|
||||
uint32 moneyRew = 0;
|
||||
Player* player = _session->GetPlayer();
|
||||
uint8 playerLevel = player ? player->GetLevel() : 0;
|
||||
if (player && (player->getLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
|
||||
{
|
||||
moneyRew = quest->GetRewMoneyMaxLevel();
|
||||
@@ -461,7 +460,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU
|
||||
uint32 questXp;
|
||||
if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))
|
||||
{
|
||||
questXp = uint32(quest->XPValue(playerLevel) * player->GetQuestRate());
|
||||
questXp = player->CalculateQuestRewardXP(quest);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -704,7 +703,6 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
|
||||
|
||||
uint32 moneyRew = 0;
|
||||
Player* player = _session->GetPlayer();
|
||||
uint8 playerLevel = player ? player->GetLevel() : 0;
|
||||
if (player && (player->GetLevel() >= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL) || sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player)))
|
||||
{
|
||||
moneyRew = quest->GetRewMoneyMaxLevel();
|
||||
@@ -714,7 +712,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI
|
||||
uint32 questXp;
|
||||
if (player && !sScriptMgr->ShouldBeRewardedWithMoneyInsteadOfExp(player))
|
||||
{
|
||||
questXp = uint32(quest->XPValue(playerLevel) * player->GetQuestRate());
|
||||
questXp = player->CalculateQuestRewardXP(quest);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -256,6 +256,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
|
||||
|
||||
if (current && owner->IsPetNeedBeTemporaryUnsummoned())
|
||||
{
|
||||
owner->SetLastPetSpell(petInfo->CreatedBySpellId);
|
||||
owner->SetTemporaryUnsummonedPetNumber(petInfo->PetNumber);
|
||||
return false;
|
||||
}
|
||||
@@ -2417,9 +2418,9 @@ void Pet::SynchronizeLevelWithOwner()
|
||||
}
|
||||
}
|
||||
|
||||
void Pet::SetDisplayId(uint32 modelId)
|
||||
void Pet::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/)
|
||||
{
|
||||
Guardian::SetDisplayId(modelId);
|
||||
Guardian::SetDisplayId(modelId, displayScale);
|
||||
|
||||
if (!isControlled())
|
||||
return;
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
void RemoveFromWorld() override;
|
||||
|
||||
float GetNativeObjectScale() const override;
|
||||
void SetDisplayId(uint32 modelId) override;
|
||||
void SetDisplayId(uint32 modelId, float displayScale = 1.f) override;
|
||||
|
||||
PetType getPetType() const { return m_petType; }
|
||||
void setPetType(PetType type) { m_petType = type; }
|
||||
|
||||
@@ -1451,6 +1451,7 @@ public:
|
||||
bool SatisfyQuestSeasonal(Quest const* qInfo, bool msg) const;
|
||||
bool GiveQuestSourceItem(Quest const* quest);
|
||||
bool TakeQuestSourceItem(uint32 questId, bool msg);
|
||||
uint32 CalculateQuestRewardXP(Quest const* quest);
|
||||
[[nodiscard]] bool GetQuestRewardStatus(uint32 quest_id) const;
|
||||
[[nodiscard]] QuestStatus GetQuestStatus(uint32 quest_id) const;
|
||||
void SetQuestStatus(uint32 questId, QuestStatus status, bool update = true);
|
||||
|
||||
@@ -742,12 +742,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
||||
bool rewarded = IsQuestRewarded(quest_id) && !quest->IsDFQuest();
|
||||
|
||||
// Not give XP in case already completed once repeatable quest
|
||||
uint32 XP = rewarded ? 0 : uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest()));
|
||||
|
||||
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
|
||||
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
|
||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
||||
AddPct(XP, (*i)->GetAmount());
|
||||
uint32 XP = rewarded ? 0 : CalculateQuestRewardXP(quest);
|
||||
|
||||
sScriptMgr->OnQuestComputeXP(this, quest, XP);
|
||||
int32 moneyRew = 0;
|
||||
@@ -1402,6 +1397,19 @@ bool Player::TakeQuestSourceItem(uint32 questId, bool msg)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 Player::CalculateQuestRewardXP(Quest const* quest)
|
||||
{
|
||||
// apply world quest rate
|
||||
uint32 xp = uint32(quest->XPValue(GetLevel()) * GetQuestRate(quest->IsDFQuest()));
|
||||
|
||||
// handle SPELL_AURA_MOD_XP_QUEST_PCT auras
|
||||
Unit::AuraEffectList const& ModXPPctAuras = GetAuraEffectsByType(SPELL_AURA_MOD_XP_QUEST_PCT);
|
||||
for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
|
||||
AddPct(xp, (*i)->GetAmount());
|
||||
|
||||
return xp;
|
||||
}
|
||||
|
||||
bool Player::GetQuestRewardStatus(uint32 quest_id) const
|
||||
{
|
||||
Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id);
|
||||
|
||||
@@ -7833,19 +7833,17 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
|
||||
triggered_spell_id = 31803;
|
||||
|
||||
// On target with 5 stacks of Holy Vengeance direct damage is done
|
||||
if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
|
||||
{
|
||||
if (aur->GetStackAmount() == 5)
|
||||
{
|
||||
if (stacker)
|
||||
aur->RefreshDuration();
|
||||
|
||||
CastSpell(victim, 42463, true, castItem, triggeredByAura);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CastSpell(victim, 42463, true, castItem, triggeredByAura); // Seal of Vengeance
|
||||
|
||||
if (!stacker)
|
||||
return false;
|
||||
break;
|
||||
@@ -7866,19 +7864,17 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
|
||||
triggered_spell_id = 53742;
|
||||
|
||||
// On target with 5 stacks of Blood Corruption direct damage is done
|
||||
if (Aura* aur = victim->GetAura(triggered_spell_id, GetGUID()))
|
||||
{
|
||||
if (aur->GetStackAmount() == 5)
|
||||
{
|
||||
if (stacker)
|
||||
aur->RefreshDuration();
|
||||
|
||||
CastSpell(victim, 53739, true, castItem, triggeredByAura);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
CastSpell(victim, 53739, true, castItem, triggeredByAura); // Seal of Corruption
|
||||
|
||||
if (!stacker)
|
||||
return false;
|
||||
break;
|
||||
@@ -17051,13 +17047,16 @@ void Unit::RecalculateObjectScale()
|
||||
SetObjectScale(std::max(scale, scaleMin));
|
||||
}
|
||||
|
||||
void Unit::SetDisplayId(uint32 modelId)
|
||||
void Unit::SetDisplayId(uint32 modelId, float displayScale /*=1.f*/)
|
||||
{
|
||||
SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId);
|
||||
|
||||
// Set Gender by modelId
|
||||
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
|
||||
SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
|
||||
|
||||
SetObjectScale(displayScale);
|
||||
|
||||
sScriptMgr->OnDisplayIdChange(this, modelId);
|
||||
}
|
||||
|
||||
@@ -21264,17 +21263,11 @@ void Unit::PatchValuesUpdate(ByteBuffer& valuesUpdateBuf, BuildValuesCachePosPoi
|
||||
{
|
||||
if (target->IsGameMaster() && target->GetSession()->IsGMAccount())
|
||||
{
|
||||
if (cinfo->Modelid1)
|
||||
displayId = cinfo->Modelid1; // Modelid1 is a visible model for gms
|
||||
else
|
||||
displayId = 17519; // world visible trigger's model
|
||||
displayId = cinfo->GetFirstVisibleModel()->CreatureDisplayID;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cinfo->Modelid2)
|
||||
displayId = cinfo->Modelid2; // Modelid2 is an invisible model for players
|
||||
else
|
||||
displayId = 11686; // world invisible trigger's model
|
||||
displayId = cinfo->GetFirstInvisibleModel()->CreatureDisplayID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2263,10 +2263,10 @@ public:
|
||||
virtual float GetNativeObjectScale() const { return 1.0f; }
|
||||
virtual void RecalculateObjectScale();
|
||||
[[nodiscard]] uint32 GetDisplayId() const { return GetUInt32Value(UNIT_FIELD_DISPLAYID); }
|
||||
virtual void SetDisplayId(uint32 modelId);
|
||||
virtual void SetDisplayId(uint32 modelId, float displayScale = 1.f);
|
||||
[[nodiscard]] uint32 GetNativeDisplayId() const { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); }
|
||||
void RestoreDisplayId();
|
||||
void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); }
|
||||
void SetNativeDisplayId(uint32 displayId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, displayId); }
|
||||
void setTransForm(uint32 spellid) { m_transform = spellid;}
|
||||
[[nodiscard]] uint32 getTransForm() const { return m_transform;}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "LFGMgr.h"
|
||||
#include "Log.h"
|
||||
#include "MapMgr.h"
|
||||
#include <numeric>
|
||||
#include "Pet.h"
|
||||
#include "PoolMgr.h"
|
||||
#include "ReputationMgr.h"
|
||||
@@ -576,20 +577,20 @@ void ObjectMgr::LoadCreatureTemplates()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, "
|
||||
// 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, "
|
||||
// 23 24 25 26 27 28 29 30 31 32 33 34
|
||||
"detection_range, scale, `rank`, dmgschool, DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, "
|
||||
// 35 36 37 38 39 40 41
|
||||
"dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, type, "
|
||||
// 42 43 44 45 46 47 48 49 50 51
|
||||
"type_flags, lootid, pickpocketloot, skinloot, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, "
|
||||
// 52 53 54 55 56 57 58 59 60 61 62 63
|
||||
"ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, "
|
||||
// 64 65 66 67 68 69 70
|
||||
"RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName "
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, subname, IconName, "
|
||||
// 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||||
"gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, speed_swim, speed_flight, detection_range, scale, `rank`, dmgschool, "
|
||||
// 23 24 25 26 27 28 29 30 31 32 33 34
|
||||
"DamageModifier, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, "
|
||||
// 35 36 37 38 39 40 41
|
||||
"trainer_class, trainer_race, type, type_flags, lootid, pickpocketloot, skinloot, "
|
||||
// 42 43 44 45 46 47 48 49 50 51
|
||||
"PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, ctm.Ground, ctm.Swim, ctm.Flight, ctm.Rooted, "
|
||||
// 52 53 54 55 56 57 58 59 60 61 62 63
|
||||
"ctm.Chase, ctm.Random, ctm.InteractionPauseTimer, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, ExperienceModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, "
|
||||
// 64 65 66
|
||||
"spell_school_immune_mask, flags_extra, ScriptName "
|
||||
"FROM creature_template ct LEFT JOIN creature_template_movement ctm ON ct.entry = ctm.CreatureId ORDER BY entry DESC;");
|
||||
|
||||
if (!result)
|
||||
@@ -609,6 +610,9 @@ void ObjectMgr::LoadCreatureTemplates()
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
// We load the creature models after loading but before checking
|
||||
LoadCreatureTemplateModels();
|
||||
|
||||
sScriptMgr->OnAfterDatabaseLoadCreatureTemplates(_creatureTemplateStoreFast);
|
||||
|
||||
LoadCreatureTemplateResistances();
|
||||
@@ -658,47 +662,42 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook)
|
||||
{
|
||||
creatureTemplate.KillCredit[i] = fields[4 + i].Get<uint32>();
|
||||
}
|
||||
|
||||
creatureTemplate.Modelid1 = fields[6].Get<uint32>();
|
||||
creatureTemplate.Modelid2 = fields[7].Get<uint32>();
|
||||
creatureTemplate.Modelid3 = fields[8].Get<uint32>();
|
||||
creatureTemplate.Modelid4 = fields[9].Get<uint32>();
|
||||
creatureTemplate.Name = fields[10].Get<std::string>();
|
||||
creatureTemplate.SubName = fields[11].Get<std::string>();
|
||||
creatureTemplate.IconName = fields[12].Get<std::string>();
|
||||
creatureTemplate.GossipMenuId = fields[13].Get<uint32>();
|
||||
creatureTemplate.minlevel = fields[14].Get<uint8>();
|
||||
creatureTemplate.maxlevel = fields[15].Get<uint8>();
|
||||
creatureTemplate.expansion = uint32(fields[16].Get<int16>());
|
||||
creatureTemplate.faction = uint32(fields[17].Get<uint16>());
|
||||
creatureTemplate.npcflag = fields[18].Get<uint32>();
|
||||
creatureTemplate.speed_walk = fields[19].Get<float>();
|
||||
creatureTemplate.speed_run = fields[20].Get<float>();
|
||||
creatureTemplate.speed_swim = fields[21].Get<float>();
|
||||
creatureTemplate.speed_flight = fields[22].Get<float>();
|
||||
creatureTemplate.detection_range = fields[23].Get<float>();
|
||||
creatureTemplate.scale = fields[24].Get<float>();
|
||||
creatureTemplate.rank = uint32(fields[25].Get<uint8>());
|
||||
creatureTemplate.dmgschool = uint32(fields[26].Get<int8>());
|
||||
creatureTemplate.DamageModifier = fields[27].Get<float>();
|
||||
creatureTemplate.BaseAttackTime = fields[28].Get<uint32>();
|
||||
creatureTemplate.RangeAttackTime = fields[29].Get<uint32>();
|
||||
creatureTemplate.BaseVariance = fields[30].Get<float>();
|
||||
creatureTemplate.RangeVariance = fields[31].Get<float>();
|
||||
creatureTemplate.unit_class = uint32(fields[32].Get<uint8>());
|
||||
creatureTemplate.unit_flags = fields[33].Get<uint32>();
|
||||
creatureTemplate.unit_flags2 = fields[34].Get<uint32>();
|
||||
creatureTemplate.dynamicflags = fields[35].Get<uint32>();
|
||||
creatureTemplate.family = uint32(fields[36].Get<uint8>());
|
||||
creatureTemplate.trainer_type = uint32(fields[37].Get<uint8>());
|
||||
creatureTemplate.trainer_spell = fields[38].Get<uint32>();
|
||||
creatureTemplate.trainer_class = uint32(fields[39].Get<uint8>());
|
||||
creatureTemplate.trainer_race = uint32(fields[40].Get<uint8>());
|
||||
creatureTemplate.type = uint32(fields[41].Get<uint8>());
|
||||
creatureTemplate.type_flags = fields[42].Get<uint32>();
|
||||
creatureTemplate.lootid = fields[43].Get<uint32>();
|
||||
creatureTemplate.pickpocketLootId = fields[44].Get<uint32>();
|
||||
creatureTemplate.SkinLootId = fields[45].Get<uint32>();
|
||||
creatureTemplate.Name = fields[6].Get<std::string>();
|
||||
creatureTemplate.SubName = fields[7].Get<std::string>();
|
||||
creatureTemplate.IconName = fields[8].Get<std::string>();
|
||||
creatureTemplate.GossipMenuId = fields[9].Get<uint32>();
|
||||
creatureTemplate.minlevel = fields[10].Get<uint8>();
|
||||
creatureTemplate.maxlevel = fields[11].Get<uint8>();
|
||||
creatureTemplate.expansion = uint32(fields[12].Get<int16>());
|
||||
creatureTemplate.faction = uint32(fields[13].Get<uint16>());
|
||||
creatureTemplate.npcflag = fields[14].Get<uint32>();
|
||||
creatureTemplate.speed_walk = fields[15].Get<float>();
|
||||
creatureTemplate.speed_run = fields[16].Get<float>();
|
||||
creatureTemplate.speed_swim = fields[17].Get<float>();
|
||||
creatureTemplate.speed_flight = fields[18].Get<float>();
|
||||
creatureTemplate.detection_range = fields[19].Get<float>();
|
||||
creatureTemplate.scale = fields[20].Get<float>();
|
||||
creatureTemplate.rank = uint32(fields[21].Get<uint8>());
|
||||
creatureTemplate.dmgschool = uint32(fields[22].Get<int8>());
|
||||
creatureTemplate.DamageModifier = fields[23].Get<float>();
|
||||
creatureTemplate.BaseAttackTime = fields[24].Get<uint32>();
|
||||
creatureTemplate.RangeAttackTime = fields[25].Get<uint32>();
|
||||
creatureTemplate.BaseVariance = fields[26].Get<float>();
|
||||
creatureTemplate.RangeVariance = fields[27].Get<float>();
|
||||
creatureTemplate.unit_class = uint32(fields[28].Get<uint8>());
|
||||
creatureTemplate.unit_flags = fields[29].Get<uint32>();
|
||||
creatureTemplate.unit_flags2 = fields[30].Get<uint32>();
|
||||
creatureTemplate.dynamicflags = fields[31].Get<uint32>();
|
||||
creatureTemplate.family = uint32(fields[32].Get<uint8>());
|
||||
creatureTemplate.trainer_type = uint32(fields[33].Get<uint8>());
|
||||
creatureTemplate.trainer_spell = fields[34].Get<uint32>();
|
||||
creatureTemplate.trainer_class = uint32(fields[35].Get<uint8>());
|
||||
creatureTemplate.trainer_race = uint32(fields[36].Get<uint8>());
|
||||
creatureTemplate.type = uint32(fields[37].Get<uint8>());
|
||||
creatureTemplate.type_flags = fields[38].Get<uint32>();
|
||||
creatureTemplate.lootid = fields[39].Get<uint32>();
|
||||
creatureTemplate.pickpocketLootId = fields[40].Get<uint32>();
|
||||
creatureTemplate.SkinLootId = fields[41].Get<uint32>();
|
||||
|
||||
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
|
||||
{
|
||||
@@ -710,49 +709,49 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook)
|
||||
creatureTemplate.spells[i] = 0;
|
||||
}
|
||||
|
||||
creatureTemplate.PetSpellDataId = fields[46].Get<uint32>();
|
||||
creatureTemplate.VehicleId = fields[47].Get<uint32>();
|
||||
creatureTemplate.mingold = fields[48].Get<uint32>();
|
||||
creatureTemplate.maxgold = fields[49].Get<uint32>();
|
||||
creatureTemplate.AIName = fields[50].Get<std::string>();
|
||||
creatureTemplate.MovementType = uint32(fields[51].Get<uint8>());
|
||||
creatureTemplate.PetSpellDataId = fields[42].Get<uint32>();
|
||||
creatureTemplate.VehicleId = fields[43].Get<uint32>();
|
||||
creatureTemplate.mingold = fields[44].Get<uint32>();
|
||||
creatureTemplate.maxgold = fields[45].Get<uint32>();
|
||||
creatureTemplate.AIName = fields[46].Get<std::string>(); // stopped here, fix it
|
||||
creatureTemplate.MovementType = uint32(fields[47].Get<uint8>());
|
||||
if (!fields[48].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[48].Get<uint8>());
|
||||
}
|
||||
|
||||
creatureTemplate.Movement.Swim = fields[49].Get<bool>();
|
||||
if (!fields[50].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[50].Get<uint8>());
|
||||
}
|
||||
|
||||
creatureTemplate.Movement.Rooted = fields[51].Get<bool>();
|
||||
if (!fields[52].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Ground = static_cast<CreatureGroundMovementType>(fields[52].Get<uint8>());
|
||||
creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[52].Get<uint8>());
|
||||
}
|
||||
if (!fields[53].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[53].Get<uint8>());
|
||||
}
|
||||
|
||||
creatureTemplate.Movement.Swim = fields[53].Get<bool>();
|
||||
if (!fields[54].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Flight = static_cast<CreatureFlightMovementType>(fields[54].Get<uint8>());
|
||||
creatureTemplate.Movement.InteractionPauseTimer = fields[54].Get<uint32>();
|
||||
}
|
||||
|
||||
creatureTemplate.Movement.Rooted = fields[55].Get<bool>();
|
||||
if (!fields[56].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Chase = static_cast<CreatureChaseMovementType>(fields[56].Get<uint8>());
|
||||
}
|
||||
if (!fields[57].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.Random = static_cast<CreatureRandomMovementType>(fields[57].Get<uint8>());
|
||||
}
|
||||
if (!fields[58].IsNull())
|
||||
{
|
||||
creatureTemplate.Movement.InteractionPauseTimer = fields[58].Get<uint32>();
|
||||
}
|
||||
|
||||
creatureTemplate.HoverHeight = fields[59].Get<float>();
|
||||
creatureTemplate.ModHealth = fields[60].Get<float>();
|
||||
creatureTemplate.ModMana = fields[61].Get<float>();
|
||||
creatureTemplate.ModArmor = fields[62].Get<float>();
|
||||
creatureTemplate.ModExperience = fields[63].Get<float>();
|
||||
creatureTemplate.RacialLeader = fields[64].Get<bool>();
|
||||
creatureTemplate.movementId = fields[65].Get<uint32>();
|
||||
creatureTemplate.RegenHealth = fields[66].Get<bool>();
|
||||
creatureTemplate.MechanicImmuneMask = fields[67].Get<uint32>();
|
||||
creatureTemplate.SpellSchoolImmuneMask = fields[68].Get<uint8>();
|
||||
creatureTemplate.flags_extra = fields[69].Get<uint32>();
|
||||
creatureTemplate.ScriptID = GetScriptId(fields[70].Get<std::string>());
|
||||
creatureTemplate.HoverHeight = fields[55].Get<float>();
|
||||
creatureTemplate.ModHealth = fields[56].Get<float>();
|
||||
creatureTemplate.ModMana = fields[57].Get<float>();
|
||||
creatureTemplate.ModArmor = fields[58].Get<float>();
|
||||
creatureTemplate.ModExperience = fields[59].Get<float>();
|
||||
creatureTemplate.RacialLeader = fields[60].Get<bool>();
|
||||
creatureTemplate.movementId = fields[61].Get<uint32>();
|
||||
creatureTemplate.RegenHealth = fields[62].Get<bool>();
|
||||
creatureTemplate.MechanicImmuneMask = fields[63].Get<uint32>();
|
||||
creatureTemplate.SpellSchoolImmuneMask = fields[64].Get<uint8>();
|
||||
creatureTemplate.flags_extra = fields[65].Get<uint32>();
|
||||
creatureTemplate.ScriptID = GetScriptId(fields[66].Get<std::string>());
|
||||
|
||||
// useful if the creature template load is being triggered from outside this class
|
||||
if (triggerHook)
|
||||
@@ -762,6 +761,58 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields, bool triggerHook)
|
||||
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadCreatureTemplateModels()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
|
||||
// 0 1 2 3
|
||||
QueryResult result = WorldDatabase.Query("SELECT CreatureID, CreatureDisplayID, DisplayScale, Probability FROM creature_template_model ORDER BY Idx ASC");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LOG_INFO("server.loading", ">> Loaded 0 creature template model definitions. DB table `creature_template_model` is empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 creatureId = fields[0].Get<uint32>();
|
||||
uint32 creatureDisplayId = fields[1].Get<uint32>();
|
||||
float displayScale = fields[2].Get<float>();
|
||||
float probability = fields[3].Get<float>();
|
||||
|
||||
CreatureTemplate const* cInfo = GetCreatureTemplate(creatureId);
|
||||
if (!cInfo)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature template (Entry: {}) does not exist but has a record in `creature_template_model`", creatureId);
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(creatureDisplayId);
|
||||
if (!displayEntry)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing CreatureDisplayID id ({}), this can crash the client.", creatureId, creatureDisplayId);
|
||||
continue;
|
||||
}
|
||||
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(creatureDisplayId);
|
||||
if (!modelInfo)
|
||||
LOG_ERROR("sql.sql", "No model data exist for `CreatureDisplayID` = {} listed by creature (Entry: {%u}}).", creatureDisplayId, creatureId);
|
||||
|
||||
if (displayScale <= 0.0f)
|
||||
displayScale = 1.0f;
|
||||
|
||||
const_cast<CreatureTemplate*>(cInfo)->Models.emplace_back(creatureDisplayId, displayScale, probability);
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
LOG_INFO("server.loading", ">> Loaded {} creature template models in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadCreatureTemplateResistances()
|
||||
{
|
||||
uint32 oldMSTime = getMSTime();
|
||||
@@ -1112,76 +1163,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
if (!factionTemplate)
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has non-existing faction template ({}).", cInfo->Entry, cInfo->faction);
|
||||
|
||||
// used later for scale
|
||||
CreatureDisplayInfoEntry const* displayScaleEntry = nullptr;
|
||||
|
||||
if (cInfo->Modelid1)
|
||||
{
|
||||
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid1);
|
||||
if (!displayEntry)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid1 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid1);
|
||||
const_cast<CreatureTemplate*>(cInfo)->Modelid1 = 0;
|
||||
}
|
||||
else if (!displayScaleEntry)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid1);
|
||||
if (!modelInfo)
|
||||
LOG_ERROR("sql.sql", "No model data exist for `Modelid1` = {} listed by creature (Entry: {}).", cInfo->Modelid1, cInfo->Entry);
|
||||
}
|
||||
|
||||
if (cInfo->Modelid2)
|
||||
{
|
||||
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid2);
|
||||
if (!displayEntry)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid2 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid2);
|
||||
const_cast<CreatureTemplate*>(cInfo)->Modelid2 = 0;
|
||||
}
|
||||
else if (!displayScaleEntry)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid2);
|
||||
if (!modelInfo)
|
||||
LOG_ERROR("sql.sql", "No model data exist for `Modelid2` = {} listed by creature (Entry: {}).", cInfo->Modelid2, cInfo->Entry);
|
||||
}
|
||||
|
||||
if (cInfo->Modelid3)
|
||||
{
|
||||
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid3);
|
||||
if (!displayEntry)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid3 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid3);
|
||||
const_cast<CreatureTemplate*>(cInfo)->Modelid3 = 0;
|
||||
}
|
||||
else if (!displayScaleEntry)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid3);
|
||||
if (!modelInfo)
|
||||
LOG_ERROR("sql.sql", "No model data exist for `Modelid3` = {} listed by creature (Entry: {}).", cInfo->Modelid3, cInfo->Entry);
|
||||
}
|
||||
|
||||
if (cInfo->Modelid4)
|
||||
{
|
||||
CreatureDisplayInfoEntry const* displayEntry = sCreatureDisplayInfoStore.LookupEntry(cInfo->Modelid4);
|
||||
if (!displayEntry)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) lists non-existing Modelid4 id ({}), this can crash the client.", cInfo->Entry, cInfo->Modelid4);
|
||||
const_cast<CreatureTemplate*>(cInfo)->Modelid4 = 0;
|
||||
}
|
||||
else if (!displayScaleEntry)
|
||||
displayScaleEntry = displayEntry;
|
||||
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(cInfo->Modelid4);
|
||||
if (!modelInfo)
|
||||
LOG_ERROR("sql.sql", "No model data exist for `Modelid4` = {} listed by creature (Entry: {}).", cInfo->Modelid4, cInfo->Entry);
|
||||
}
|
||||
|
||||
if (!displayScaleEntry)
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo->Entry);
|
||||
|
||||
for (int k = 0; k < MAX_KILL_CREDIT; ++k)
|
||||
{
|
||||
if (cInfo->KillCredit[k])
|
||||
@@ -1194,6 +1175,11 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
}
|
||||
}
|
||||
|
||||
if (!cInfo->Models.size())
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) does not have any existing display id in creature_template_model.", cInfo->Entry);
|
||||
else if (std::accumulate(cInfo->Models.begin(), cInfo->Models.end(), 0.0f, [](float sum, CreatureModel const& model) { return sum + model.Probability; }) <= 0.0f)
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has zero total chance for all models in creature_template_model.", cInfo->Entry);
|
||||
|
||||
if (!cInfo->unit_class || ((1 << (cInfo->unit_class - 1)) & CLASSMASK_ALL_CREATURES) == 0)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Creature (Entry: {}) has invalid unit_class ({}) in creature_template. Set to 1 (UNIT_CLASS_WARRIOR).", cInfo->Entry, cInfo->unit_class);
|
||||
@@ -1280,15 +1266,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
|
||||
const_cast<CreatureTemplate*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
|
||||
}
|
||||
|
||||
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
|
||||
if (cInfo->scale <= 0.0f)
|
||||
{
|
||||
if (displayScaleEntry)
|
||||
const_cast<CreatureTemplate*>(cInfo)->scale = displayScaleEntry->scale;
|
||||
else
|
||||
const_cast<CreatureTemplate*>(cInfo)->scale = 1.0f;
|
||||
}
|
||||
|
||||
if (cInfo->expansion > (MAX_EXPANSIONS - 1))
|
||||
{
|
||||
LOG_ERROR("sql.sql", "Table `creature_template` lists creature (Entry: {}) with expansion {}. Ignored and set to 0.", cInfo->Entry, cInfo->expansion);
|
||||
@@ -1722,13 +1699,19 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelId) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/)
|
||||
CreatureModel const* ObjectMgr::ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data /*= nullptr*/)
|
||||
{
|
||||
// Load creature model (display id)
|
||||
if (data && data->displayid)
|
||||
return data->displayid;
|
||||
if (CreatureModel const* model = cinfo->GetModelWithDisplayId(data->displayid))
|
||||
return model;
|
||||
|
||||
return cinfo->GetRandomValidModelId();
|
||||
if (!(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER))
|
||||
if (CreatureModel const* model = cinfo->GetRandomValidModel())
|
||||
return model;
|
||||
|
||||
// Triggers by default receive the invisible model
|
||||
return cinfo->GetFirstInvisibleModel();
|
||||
}
|
||||
|
||||
void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, const CreatureData* data /*= nullptr*/)
|
||||
@@ -1750,9 +1733,9 @@ void ObjectMgr::ChooseCreatureFlags(const CreatureTemplate* cinfo, uint32& npcfl
|
||||
}
|
||||
}
|
||||
|
||||
CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* displayID)
|
||||
CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const
|
||||
{
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(*displayID);
|
||||
CreatureModelInfo const* modelInfo = GetCreatureModelInfo(model->CreatureDisplayID);
|
||||
if (!modelInfo)
|
||||
return nullptr;
|
||||
|
||||
@@ -1761,11 +1744,20 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* display
|
||||
{
|
||||
CreatureModelInfo const* minfo_tmp = GetCreatureModelInfo(modelInfo->modelid_other_gender);
|
||||
if (!minfo_tmp)
|
||||
LOG_ERROR("sql.sql", "Model (Entry: {}) has modelid_other_gender {} not found in table `creature_model_info`. ", *displayID, modelInfo->modelid_other_gender);
|
||||
LOG_ERROR("sql.sql", "Model (Entry: {}) has modelid_other_gender {} not found in table `creature_model_info`. ", model->CreatureDisplayID, modelInfo->modelid_other_gender);
|
||||
else
|
||||
{
|
||||
// Model ID changed
|
||||
*displayID = modelInfo->modelid_other_gender;
|
||||
model->CreatureDisplayID = modelInfo->modelid_other_gender;
|
||||
if (creatureTemplate)
|
||||
{
|
||||
auto itr = std::find_if(creatureTemplate->Models.begin(), creatureTemplate->Models.end(), [&](CreatureModel const& templateModel)
|
||||
{
|
||||
return templateModel.CreatureDisplayID == modelInfo->modelid_other_gender;
|
||||
});
|
||||
if (itr != creatureTemplate->Models.end())
|
||||
*model = *itr;
|
||||
}
|
||||
return minfo_tmp;
|
||||
}
|
||||
}
|
||||
@@ -1790,10 +1782,15 @@ void ObjectMgr::LoadCreatureModelInfo()
|
||||
_creatureModelStore.rehash(result->GetRowCount());
|
||||
uint32 count = 0;
|
||||
|
||||
// List of ModelDataIDs that use Invisible models
|
||||
uint32 triggerCreatureModelDataID[14] = { 1731, 1752, 2206, 2296, 2372, 2382, 2481, 2512, 2513, 2611, 2636, 2790, 3230, 3274 };
|
||||
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
|
||||
uint32 displayId = fields[0].Get<uint32>();
|
||||
CreatureDisplayInfoEntry const* creatureDisplay = sCreatureDisplayInfoStore.LookupEntry(displayId);
|
||||
uint32 modelId = fields[0].Get<uint32>();
|
||||
|
||||
CreatureModelInfo& modelInfo = _creatureModelStore[modelId];
|
||||
@@ -1802,6 +1799,7 @@ void ObjectMgr::LoadCreatureModelInfo()
|
||||
modelInfo.combat_reach = fields[2].Get<float>();
|
||||
modelInfo.gender = fields[3].Get<uint8>();
|
||||
modelInfo.modelid_other_gender = fields[4].Get<uint32>();
|
||||
modelInfo.is_trigger = false;
|
||||
|
||||
// Checks
|
||||
|
||||
@@ -1823,6 +1821,18 @@ void ObjectMgr::LoadCreatureModelInfo()
|
||||
if (modelInfo.combat_reach < 0.1f)
|
||||
modelInfo.combat_reach = DEFAULT_COMBAT_REACH;
|
||||
|
||||
if (CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(creatureDisplay->ModelId))
|
||||
{
|
||||
for (uint32 i = 0; i < 14; i++)
|
||||
{
|
||||
if (modelData->Id == triggerCreatureModelDataID[i])
|
||||
{
|
||||
modelInfo.is_trigger = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++count;
|
||||
} while (result->NextRow());
|
||||
|
||||
@@ -6586,7 +6596,8 @@ void ObjectMgr::GetTaxiPath(uint32 source, uint32 destination, uint32& path, uin
|
||||
|
||||
uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_alt_team /* = false */)
|
||||
{
|
||||
uint32 mount_id = 0;
|
||||
CreatureModel mountModel;
|
||||
CreatureTemplate const* mount_info = nullptr;
|
||||
|
||||
// select mount creature id
|
||||
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
|
||||
@@ -6602,22 +6613,23 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, TeamId teamId, bool allowed_a
|
||||
mount_entry = node->MountCreatureID[teamId];
|
||||
}
|
||||
|
||||
CreatureTemplate const* mount_info = GetCreatureTemplate(mount_entry);
|
||||
mount_info = GetCreatureTemplate(mount_entry);
|
||||
if (mount_info)
|
||||
{
|
||||
mount_id = mount_info->GetRandomValidModelId();
|
||||
if (!mount_id)
|
||||
CreatureModel const* model = mount_info->GetRandomValidModel();
|
||||
if (!model)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "No displayid found for the taxi mount with the entry {}! Can't load it!", mount_entry);
|
||||
return 0;
|
||||
}
|
||||
mountModel = *model;
|
||||
}
|
||||
}
|
||||
|
||||
// minfo is not actually used but the mount_id was updated
|
||||
GetCreatureModelRandomGender(&mount_id);
|
||||
GetCreatureModelRandomGender(&mountModel, mount_info);
|
||||
|
||||
return mount_id;
|
||||
return mountModel.CreatureDisplayID;
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadAreaTriggers()
|
||||
|
||||
@@ -770,8 +770,8 @@ public:
|
||||
CreatureTemplate const* GetCreatureTemplate(uint32 entry);
|
||||
[[nodiscard]] CreatureTemplateContainer const* GetCreatureTemplates() const { return &_creatureTemplateStore; }
|
||||
CreatureModelInfo const* GetCreatureModelInfo(uint32 modelId) const;
|
||||
CreatureModelInfo const* GetCreatureModelRandomGender(uint32* displayID);
|
||||
static uint32 ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr);
|
||||
CreatureModelInfo const* GetCreatureModelRandomGender(CreatureModel* model, CreatureTemplate const* creatureTemplate) const;
|
||||
static CreatureModel const* ChooseDisplayId(CreatureTemplate const* cinfo, CreatureData const* data = nullptr);
|
||||
static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = nullptr);
|
||||
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id);
|
||||
CreatureAddon const* GetCreatureAddon(ObjectGuid::LowType lowguid);
|
||||
@@ -1022,6 +1022,7 @@ public:
|
||||
void LoadCreatureLocales();
|
||||
void LoadCreatureTemplates();
|
||||
void LoadCreatureTemplate(Field* fields, bool triggerHook = false);
|
||||
void LoadCreatureTemplateModels();
|
||||
void LoadCreatureTemplateAddons();
|
||||
void LoadCreatureTemplateResistances();
|
||||
void LoadCreatureTemplateSpells();
|
||||
|
||||
@@ -116,23 +116,35 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
|
||||
}
|
||||
// guess size
|
||||
WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 100);
|
||||
data << uint32(entry); // creature entry
|
||||
data << uint32(entry); // creature entry
|
||||
data << Name;
|
||||
data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
|
||||
data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
|
||||
data << Title;
|
||||
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
|
||||
data << uint32(ci->type_flags); // flags
|
||||
data << uint32(ci->type); // CreatureType.dbc
|
||||
data << uint32(ci->family); // CreatureFamily.dbc
|
||||
data << uint32(ci->rank); // Creature Rank (elite, boss, etc)
|
||||
data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit
|
||||
data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit
|
||||
data << uint32(ci->Modelid1); // Modelid1
|
||||
data << uint32(ci->Modelid2); // Modelid2
|
||||
data << uint32(ci->Modelid3); // Modelid3
|
||||
data << uint32(ci->Modelid4); // Modelid4
|
||||
data << float(ci->ModHealth); // dmg/hp modifier
|
||||
data << float(ci->ModMana); // dmg/mana modifier
|
||||
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
|
||||
data << uint32(ci->type_flags); // flags
|
||||
data << uint32(ci->type); // CreatureType.dbc
|
||||
data << uint32(ci->family); // CreatureFamily.dbc
|
||||
data << uint32(ci->rank); // Creature Rank (elite, boss, etc)
|
||||
data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit
|
||||
data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit
|
||||
if (ci->GetModelByIdx(0))
|
||||
data << uint32(ci->GetModelByIdx(0)->CreatureDisplayID); // Modelid1
|
||||
else
|
||||
data << uint32(0); // Modelid1
|
||||
if (ci->GetModelByIdx(1))
|
||||
data << uint32(ci->GetModelByIdx(1)->CreatureDisplayID); // Modelid2
|
||||
else
|
||||
data << uint32(0); // Modelid2
|
||||
if (ci->GetModelByIdx(2))
|
||||
data << uint32(ci->GetModelByIdx(2)->CreatureDisplayID); // Modelid3
|
||||
else
|
||||
data << uint32(0); // Modelid3
|
||||
if (ci->GetModelByIdx(3))
|
||||
data << uint32(ci->GetModelByIdx(3)->CreatureDisplayID); // Modelid4
|
||||
else
|
||||
data << uint32(0); // Modelid4
|
||||
data << float(ci->ModHealth); // dmg/hp modifier
|
||||
data << float(ci->ModMana); // dmg/mana modifier
|
||||
data << uint8(ci->RacialLeader);
|
||||
|
||||
CreatureQuestItemList const* items = sObjectMgr->GetCreatureQuestItemList(entry);
|
||||
@@ -143,7 +155,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
|
||||
for (size_t i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
|
||||
data << uint32(0);
|
||||
|
||||
data << uint32(ci->movementId); // CreatureMovementInfo.dbc
|
||||
data << uint32(ci->movementId); // CreatureMovementInfo.dbc
|
||||
SendPacket(&data);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -24,9 +24,9 @@ void ScriptMgr::OnHandleDevCommand(Player* player, bool& enable)
|
||||
CALL_ENABLED_HOOKS(AllCommandScript, ALLCOMMANDHOOK_ON_HANDLE_DEV_COMMAND, script->OnHandleDevCommand(player, enable));
|
||||
}
|
||||
|
||||
bool ScriptMgr::CanExecuteCommand(ChatHandler& handler, std::string_view cmdStr)
|
||||
bool ScriptMgr::OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr)
|
||||
{
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(AllCommandScript, ALLCOMMANDHOOK_CAN_EXECUTE_COMMAND, !script->CanExecuteCommand(handler, cmdStr));
|
||||
CALL_ENABLED_BOOLEAN_HOOKS(AllCommandScript, ALLCOMMANDHOOK_ON_TRY_EXECUTE_COMMAND, !script->OnTryExecuteCommand(handler, cmdStr));
|
||||
}
|
||||
|
||||
AllCommandScript::AllCommandScript(const char* name, std::vector<uint16> enabledHooks)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
enum AllCommandHook
|
||||
{
|
||||
ALLCOMMANDHOOK_ON_HANDLE_DEV_COMMAND,
|
||||
ALLCOMMANDHOOK_CAN_EXECUTE_COMMAND,
|
||||
ALLCOMMANDHOOK_ON_TRY_EXECUTE_COMMAND,
|
||||
ALLCOMMANDHOOK_END
|
||||
};
|
||||
|
||||
@@ -39,12 +39,12 @@ public:
|
||||
virtual void OnHandleDevCommand(Player* /*player*/, bool& /*enable*/) { }
|
||||
|
||||
/**
|
||||
* @brief This hook runs execute chat command
|
||||
* @brief This hook is triggered when a command is parsed, but before it is executed
|
||||
*
|
||||
* @param handler Contains information about the ChatHandler
|
||||
* @param cmdStr Contains information about the command name
|
||||
*/
|
||||
[[nodiscard]] virtual bool CanExecuteCommand(ChatHandler& /*handler*/, std::string_view /*cmdStr*/) { return true; }
|
||||
[[nodiscard]] virtual bool OnTryExecuteCommand(ChatHandler& /*handler*/, std::string_view /*cmdStr*/) { return true; }
|
||||
};
|
||||
|
||||
// Compatibility for old scripts
|
||||
|
||||
@@ -703,7 +703,7 @@ public: /* MiscScript */
|
||||
public: /* CommandSC */
|
||||
|
||||
void OnHandleDevCommand(Player* player, bool& enable);
|
||||
bool CanExecuteCommand(ChatHandler& handler, std::string_view cmdStr);
|
||||
bool OnTryExecuteCommand(ChatHandler& handler, std::string_view cmdStr);
|
||||
|
||||
public: /* DatabaseScript */
|
||||
|
||||
|
||||
@@ -2705,7 +2705,7 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
|
||||
{
|
||||
uint32 model_id = 0;
|
||||
|
||||
if (uint32 modelid = ci->GetRandomValidModelId())
|
||||
if (uint32 modelid = ObjectMgr::ChooseDisplayId(ci)->CreatureDisplayID)
|
||||
model_id = modelid; // Will use the default model here
|
||||
|
||||
// Polymorph (sheep)
|
||||
@@ -2757,10 +2757,10 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
|
||||
uint32 cr_id = target->GetAuraEffectsByType(SPELL_AURA_MOUNTED).front()->GetMiscValue();
|
||||
if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(cr_id))
|
||||
{
|
||||
uint32 displayID = ObjectMgr::ChooseDisplayId(ci);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&displayID);
|
||||
CreatureModel model = *ObjectMgr::ChooseDisplayId(ci);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&model, ci);
|
||||
|
||||
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID);
|
||||
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3272,15 +3272,9 @@ void AuraEffect::HandleAuraMounted(AuraApplication const* aurApp, uint8 mode, bo
|
||||
|
||||
if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry))
|
||||
{
|
||||
if (GetMiscValueB() > 0) // Choose proper modelid
|
||||
{
|
||||
displayId = GetMiscValueB() == 2 && creatureInfo->Modelid2 > 0 ? creatureInfo->Modelid2 : creatureInfo->Modelid1;
|
||||
}
|
||||
else // Should we choose random modelid in this case?
|
||||
{
|
||||
displayId = ObjectMgr::ChooseDisplayId(creatureInfo);
|
||||
}
|
||||
sObjectMgr->GetCreatureModelRandomGender(&displayId);
|
||||
CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
|
||||
displayId = model.CreatureDisplayID;
|
||||
|
||||
vehicleId = creatureInfo->VehicleId;
|
||||
|
||||
@@ -4146,6 +4140,7 @@ void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8
|
||||
case 34471: // The Beast Within
|
||||
case 19574: // Bestial Wrath
|
||||
case 38484: // Bestial Wrath
|
||||
case 40081: // Free friend (Black Temple)
|
||||
mechanic = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
|
||||
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_CHARM, apply);
|
||||
target->ApplySpellImmune(GetId(), IMMUNITY_MECHANIC, MECHANIC_DISORIENTED, apply);
|
||||
@@ -5792,10 +5787,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
|
||||
|
||||
if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry))
|
||||
{
|
||||
uint32 displayID = ObjectMgr::ChooseDisplayId(creatureInfo);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&displayID);
|
||||
CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
|
||||
|
||||
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID);
|
||||
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -5822,10 +5817,10 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
|
||||
|
||||
if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creatureEntry))
|
||||
{
|
||||
uint32 displayID = ObjectMgr::ChooseDisplayId(creatureInfo);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&displayID);
|
||||
CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo);
|
||||
sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
|
||||
|
||||
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, displayID);
|
||||
target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, model.CreatureDisplayID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3710,7 +3710,6 @@ void Spell::cancel(bool bySelf)
|
||||
return;
|
||||
|
||||
uint32 oldState = m_spellState;
|
||||
bool autoRepeat = m_autoRepeat;
|
||||
m_spellState = SPELL_STATE_FINISHED;
|
||||
|
||||
m_autoRepeat = false;
|
||||
@@ -3723,12 +3722,9 @@ void Spell::cancel(bool bySelf)
|
||||
if (m_caster->ToPlayer()->NeedSendSpectatorData())
|
||||
ArenaSpectator::SendCommand_Spell(m_caster->FindMap(), m_caster->GetGUID(), "SPE", m_spellInfo->Id, bySelf ? 99998 : 99999);
|
||||
}
|
||||
[[fallthrough]]; /// @todo: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
|
||||
[[fallthrough]];
|
||||
case SPELL_STATE_DELAYED:
|
||||
SendInterrupted(0);
|
||||
// xinef: fixes bugged gcd reset in some cases
|
||||
if (!autoRepeat)
|
||||
SendCastResult(SPELL_FAILED_INTERRUPTED);
|
||||
SendInterrupted(SPELL_FAILED_INTERRUPTED);
|
||||
break;
|
||||
|
||||
case SPELL_STATE_CASTING:
|
||||
@@ -3740,8 +3736,7 @@ void Spell::cancel(bool bySelf)
|
||||
unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL);
|
||||
|
||||
SendChannelUpdate(0);
|
||||
SendInterrupted(0);
|
||||
SendCastResult(SPELL_FAILED_INTERRUPTED);
|
||||
SendInterrupted(SPELL_FAILED_INTERRUPTED);
|
||||
}
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->NeedSendSpectatorData())
|
||||
|
||||
@@ -4797,6 +4797,13 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->MaxAffectedTargets = 5;
|
||||
});
|
||||
|
||||
// Presence Of Mind
|
||||
ApplySpellFix({ 12043 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
// It should not share cooldown mods with category[1151] spells (Arcane Power [12042], Decimate [47271])
|
||||
spellInfo->AttributesEx6 |= SPELL_ATTR6_NO_CATEGORY_COOLDOWN_MODS;
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||
|
||||
@@ -63,7 +63,7 @@ struct npc_eye_of_acherus : public ScriptedAI
|
||||
{
|
||||
npc_eye_of_acherus(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
creature->SetDisplayId(creature->GetCreatureTemplate()->Modelid1);
|
||||
creature->SetDisplayFromModel(0);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
@@ -968,7 +968,7 @@ public:
|
||||
{
|
||||
me->SetImmuneToAll(true);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); // Modelid2 is a horse.
|
||||
me->SetDisplayFromModel(0); // Modelid2 is a horse.
|
||||
}
|
||||
|
||||
ObjectGuid minerGUID;
|
||||
|
||||
@@ -94,7 +94,7 @@ struct boss_jindo : public BossAI
|
||||
|
||||
void EnterEvadeMode(EvadeReason evadeReason) override
|
||||
{
|
||||
if (_EnterEvadeMode(evadeReason))
|
||||
if (CreatureAI::_EnterEvadeMode(evadeReason))
|
||||
{
|
||||
Reset();
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCE);
|
||||
|
||||
+44
-120
@@ -141,24 +141,17 @@ private:
|
||||
|
||||
struct npc_doomfire_spirit : public ScriptedAI
|
||||
{
|
||||
npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
_instance = creature->GetInstanceScript();
|
||||
}
|
||||
npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature){ }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Position randomPosition;
|
||||
|
||||
scheduler.CancelAll();
|
||||
ScheduleTimedEvent(0s, [&] {
|
||||
DoomfireMovement(randomPosition, me->GetPosition());
|
||||
|
||||
me->GetMotionMaster()->MovePoint(NEAR_POINT, randomPosition);
|
||||
me->GetMotionMaster()->MovePoint(NEAR_POINT, DoomfireMovement(me->GetPosition()));
|
||||
}, 1500ms);
|
||||
}
|
||||
|
||||
void DoomfireMovement(Position& targetPos, Position mePos)
|
||||
Position DoomfireMovement(Position mePos)
|
||||
{
|
||||
float angle = mePos.GetOrientation();
|
||||
float distance = 100.0f;
|
||||
@@ -166,8 +159,8 @@ struct npc_doomfire_spirit : public ScriptedAI
|
||||
float x = mePos.GetPositionX() + distance * cos(newAngle);
|
||||
float y = mePos.GetPositionY() + distance * sin(newAngle);
|
||||
|
||||
targetPos = Position(x, y, me->GetPositionZ());
|
||||
return;
|
||||
Position targetPos = Position(x, y, me->GetPositionZ());
|
||||
return targetPos;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -180,8 +173,6 @@ struct npc_doomfire_spirit : public ScriptedAI
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
struct boss_archimonde : public BossAI
|
||||
@@ -196,22 +187,13 @@ struct boss_archimonde : public BossAI
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
BossAI::Reset();
|
||||
_Reset();
|
||||
_wispCount = 0;
|
||||
_isChanneling = false;
|
||||
_enraged = false;
|
||||
_availableAuras.clear();
|
||||
_availableSpells.clear();
|
||||
|
||||
if (Map* map = me->GetMap())
|
||||
{
|
||||
map->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
player->ApplySpellImmune(SPELL_HAND_OF_DEATH, IMMUNITY_ID, SPELL_HAND_OF_DEATH, false);
|
||||
player->ApplySpellImmune(0, IMMUNITY_ID, SPELL_HAND_OF_DEATH, false);
|
||||
});
|
||||
}
|
||||
|
||||
if (instance->GetBossState(DATA_AZGALOR) != DONE)
|
||||
{
|
||||
me->SetVisible(false);
|
||||
@@ -225,7 +207,7 @@ struct boss_archimonde : public BossAI
|
||||
ScheduleHealthCheckEvent(10, [&]{
|
||||
scheduler.CancelAll();
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
DoCastProtection();
|
||||
DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true);
|
||||
Talk(SAY_ENRAGE);
|
||||
_enraged = true;
|
||||
me->GetMotionMaster()->Clear(false);
|
||||
@@ -234,7 +216,7 @@ struct boss_archimonde : public BossAI
|
||||
{
|
||||
if (_wispCount >= 30)
|
||||
{
|
||||
Unit::DealDamage(me, me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false);
|
||||
me->KillSelf();
|
||||
}
|
||||
Position wispPosition = { me->GetPositionX() + float(rand() % WISP_OFFSET), me->GetPositionY() + float(rand() % WISP_OFFSET), me->GetPositionZ(), 0.0f };
|
||||
if (Creature* wisp = me->SummonCreature(CREATURE_ANCIENT_WISP, wispPosition))
|
||||
@@ -262,8 +244,6 @@ struct boss_archimonde : public BossAI
|
||||
{
|
||||
if (Creature* nordrassil = me->SummonCreature(CREATURE_CHANNEL_TARGET, nordrassilPosition, TEMPSUMMON_TIMED_DESPAWN, 1200000))
|
||||
{
|
||||
nordrassil->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
nordrassil->SetDisplayId(DISPLAY_ID_TRIGGER);
|
||||
DoCast(nordrassil, SPELL_DRAIN_WORLD_TREE);
|
||||
_isChanneling = true;
|
||||
nordrassil->AI()->DoCast(me, SPELL_DRAIN_WORLD_TREE_2, true);
|
||||
@@ -273,29 +253,16 @@ struct boss_archimonde : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void DoCastProtection()
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
if (Map* map = me->GetMap())
|
||||
{
|
||||
map->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
player->AddAura(SPELL_PROTECTION_OF_ELUNE, player);
|
||||
player->ApplySpellImmune(SPELL_HAND_OF_DEATH, IMMUNITY_ID, SPELL_HAND_OF_DEATH, true);
|
||||
player->ApplySpellImmune(0, IMMUNITY_ID, SPELL_HAND_OF_DEATH, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
BossAI::JustEngagedWith(who);
|
||||
_JustEngagedWith();
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
Talk(SAY_AGGRO);
|
||||
ScheduleTimedEvent(25s, 35s, [&]
|
||||
{
|
||||
scheduler.DelayGroup(GROUP_FEAR, 5s);
|
||||
Talk(SAY_AIR_BURST);
|
||||
DoCastAOE(SPELL_AIR_BURST);
|
||||
DoCastRandomTarget(SPELL_AIR_BURST);
|
||||
}, 25s, 40s);
|
||||
ScheduleTimedEvent(25s, 35s, [&]
|
||||
{
|
||||
@@ -354,49 +321,46 @@ struct boss_archimonde : public BossAI
|
||||
instance->SetData(DATA_SPAWN_WAVES, 1);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_SLAY);
|
||||
|
||||
if (victim->IsPlayer())
|
||||
{
|
||||
GainSoulCharge(victim->ToPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
void GainSoulCharge(Player* player)
|
||||
void SetGUID(ObjectGuid guid, int32 type) override
|
||||
{
|
||||
switch (player->getClass())
|
||||
if (type == GUID_GAIN_SOUL_CHARGE_PLAYER)
|
||||
{
|
||||
case CLASS_PALADIN:
|
||||
case CLASS_PRIEST:
|
||||
case CLASS_WARLOCK:
|
||||
player->CastSpell(me, SPELL_SOUL_CHARGE_RED, true);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
case CLASS_MAGE:
|
||||
case CLASS_ROGUE:
|
||||
case CLASS_WARRIOR:
|
||||
player->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true);
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_SHAMAN:
|
||||
player->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true);
|
||||
break;
|
||||
case CLASS_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
scheduler.Schedule(2s, 10s, [this](TaskContext)
|
||||
{
|
||||
UnleashSoulCharge();
|
||||
});
|
||||
}
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, guid))
|
||||
{
|
||||
switch (player->getClass())
|
||||
{
|
||||
case CLASS_PALADIN:
|
||||
case CLASS_PRIEST:
|
||||
case CLASS_WARLOCK:
|
||||
player->CastSpell(me, SPELL_SOUL_CHARGE_RED, true);
|
||||
break;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
case CLASS_MAGE:
|
||||
case CLASS_ROGUE:
|
||||
case CLASS_WARRIOR:
|
||||
player->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true);
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_SHAMAN:
|
||||
player->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true);
|
||||
break;
|
||||
case CLASS_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
void JustDied(Unit* killer) override
|
||||
{
|
||||
BossAI::JustDied(killer);
|
||||
scheduler.Schedule(2s, 10s, [this](TaskContext)
|
||||
{
|
||||
UnleashSoulCharge();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why) override
|
||||
@@ -443,8 +407,6 @@ struct boss_archimonde : public BossAI
|
||||
{
|
||||
if (Creature* doomfire = me->SummonCreature(CREATURE_DOOMFIRE, doomfirePosition, TEMPSUMMON_TIMED_DESPAWN, 27000))
|
||||
{
|
||||
doomfireSpirit->SetVisible(false);
|
||||
doomfire->SetVisible(false);
|
||||
doomfireSpirit->SetWalk(false);
|
||||
doomfireSpirit->SetReactState(REACT_PASSIVE);
|
||||
doomfire->SetReactState(REACT_PASSIVE);
|
||||
@@ -507,42 +469,6 @@ class spell_red_sky_effect : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class spell_finger_of_death : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_finger_of_death);
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetHitUnit() && GetHitUnit()->GetAura(SPELL_PROTECTION_OF_ELUNE))
|
||||
PreventHitDamage();
|
||||
else
|
||||
GetHitUnit()->RemoveAurasByType(SPELL_AURA_EFFECT_IMMUNITY);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_finger_of_death::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_hand_of_death : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_hand_of_death);
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (GetHitUnit() && GetHitUnit()->GetAura(SPELL_PROTECTION_OF_ELUNE))
|
||||
PreventHitDamage();
|
||||
else
|
||||
GetHitUnit()->RemoveAurasByType(SPELL_AURA_EFFECT_IMMUNITY);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_hand_of_death::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_air_burst : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_air_burst);
|
||||
@@ -564,8 +490,6 @@ class spell_air_burst : public SpellScript
|
||||
void AddSC_boss_archimonde()
|
||||
{
|
||||
RegisterSpellScript(spell_red_sky_effect);
|
||||
RegisterSpellScript(spell_hand_of_death);
|
||||
RegisterSpellScript(spell_finger_of_death);
|
||||
RegisterSpellScript(spell_air_burst);
|
||||
RegisterHyjalAI(boss_archimonde);
|
||||
RegisterHyjalAI(npc_ancient_wisp);
|
||||
|
||||
@@ -27,18 +27,13 @@
|
||||
|
||||
uint32 const EncounterCount = 5;
|
||||
|
||||
enum HyjalBosses
|
||||
{
|
||||
BOSS_ARCHIMONDE = 0,
|
||||
};
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
DATA_WINTERCHILL = 1,
|
||||
DATA_ANETHERON = 2,
|
||||
DATA_KAZROGAL = 3,
|
||||
DATA_AZGALOR = 4,
|
||||
DATA_ARCHIMONDE = 5,
|
||||
DATA_WINTERCHILL = 0,
|
||||
DATA_ANETHERON = 1,
|
||||
DATA_KAZROGAL = 2,
|
||||
DATA_AZGALOR = 3,
|
||||
DATA_ARCHIMONDE = 4,
|
||||
|
||||
DATA_ALLIANCE_RETREAT = 11,
|
||||
DATA_HORDE_RETREAT = 12,
|
||||
@@ -90,6 +85,7 @@ enum HyjalCreaturesIds
|
||||
NPC_ALLIANCE_RIFLEMAN = 17921,
|
||||
NPC_ALLIANCE_PRIEST = 17928,
|
||||
NPC_ALLIANCE_SORCERESS = 17922,
|
||||
NPC_GUARDIAN_ELEMENTAL = 18001,
|
||||
|
||||
// Horde Base
|
||||
NPC_THRALL = 17852,
|
||||
@@ -102,6 +98,7 @@ enum HyjalCreaturesIds
|
||||
NPC_HORDE_PEON = 17937,
|
||||
NPC_INFERNAL_RELAY = 18242,
|
||||
NPC_INFERNAL_TARGET = 21075,
|
||||
NPC_DIRE_WOLF = 17854,
|
||||
|
||||
// Night Elf Base
|
||||
NPC_TYRANDE = 17948,
|
||||
@@ -152,7 +149,9 @@ enum HyjalMisc
|
||||
|
||||
AREA_NORDRASSIL = 3710,
|
||||
|
||||
SPELL_ETERNAL_SILENCE = 42201
|
||||
SPELL_ETERNAL_SILENCE = 42201,
|
||||
|
||||
GUID_GAIN_SOUL_CHARGE_PLAYER = 1
|
||||
};
|
||||
|
||||
enum HyjalPaths
|
||||
|
||||
@@ -51,11 +51,6 @@ ObjectData const creatureData[] =
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
ObjectData const objectData[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
Milliseconds hyjalWaveTimers[4][MAX_WAVES_STANDARD]
|
||||
{
|
||||
{ 130000ms, 130000ms, 130000ms, 130000ms, 130000ms, 130000ms, 130000ms, 190000ms, 0ms }, // Winterchill
|
||||
@@ -92,12 +87,12 @@ public:
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(EncounterCount);
|
||||
LoadDoorData(doorData);
|
||||
LoadObjectData(creatureData, objectData);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
}
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
_bossWave = 0;
|
||||
_bossWave = TO_BE_DECIDED;
|
||||
_retreat = 0;
|
||||
trash = 0;
|
||||
_currentWave = 0;
|
||||
@@ -190,12 +185,12 @@ public:
|
||||
case NPC_GARGO:
|
||||
case NPC_FROST:
|
||||
case NPC_INFER:
|
||||
if (_bossWave)
|
||||
if (_bossWave != TO_BE_DECIDED)
|
||||
creature->AI()->DoAction(_bossWave);
|
||||
else if (_retreat)
|
||||
creature->AI()->DoAction(_retreat);
|
||||
|
||||
if (creature->IsSummon() && _bossWave)
|
||||
if (creature->IsSummon() && _bossWave != TO_BE_DECIDED)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, ++trash); // Update the instance wave count on new trash spawn
|
||||
_encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe
|
||||
@@ -203,6 +198,8 @@ public:
|
||||
break;
|
||||
case NPC_TOWERING_INFERNAL:
|
||||
case NPC_LESSER_DOOMGUARD:
|
||||
case NPC_DIRE_WOLF:
|
||||
case NPC_GUARDIAN_ELEMENTAL:
|
||||
if (creature->IsSummon())
|
||||
{
|
||||
_summonedNPCs.insert(creature->GetGUID());
|
||||
@@ -231,7 +228,7 @@ public:
|
||||
case NPC_STALK:
|
||||
if (creature->IsSummon())
|
||||
{
|
||||
if (_bossWave)
|
||||
if (_bossWave != TO_BE_DECIDED)
|
||||
{
|
||||
DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, --trash); // Update the instance wave count on new trash death
|
||||
_encounterNPCs.erase(creature->GetGUID()); // Used for despawning on wipe
|
||||
@@ -243,6 +240,8 @@ public:
|
||||
break;
|
||||
case NPC_TOWERING_INFERNAL:
|
||||
case NPC_LESSER_DOOMGUARD:
|
||||
case NPC_DIRE_WOLF:
|
||||
case NPC_GUARDIAN_ELEMENTAL:
|
||||
_summonedNPCs.erase(creature->GetGUID());
|
||||
break;
|
||||
case NPC_WINTERCHILL:
|
||||
@@ -250,13 +249,18 @@ public:
|
||||
case NPC_KAZROGAL:
|
||||
case NPC_AZGALOR:
|
||||
if (Creature* jaina = GetCreature(DATA_JAINA))
|
||||
jaina->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
jaina->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
if (Creature* thrall = GetCreature(DATA_THRALL))
|
||||
thrall->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
thrall->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
SetData(DATA_RESET_WAVES, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (unit->IsPlayer() && GetBossState(DATA_ARCHIMONDE) == IN_PROGRESS)
|
||||
{
|
||||
if (Creature* archimonde = GetCreature(DATA_ARCHIMONDE))
|
||||
archimonde->AI()->SetGUID(unit->GetGUID(), GUID_GAIN_SOUL_CHARGE_PLAYER);
|
||||
}
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
@@ -264,7 +268,7 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case DATA_ALLIANCE_RETREAT:
|
||||
_bossWave = 0;
|
||||
_bossWave = TO_BE_DECIDED;
|
||||
_retreat = DATA_ALLIANCE_RETREAT;
|
||||
// Spawn Ancient Gems
|
||||
for (ObjectGuid const& guid : _ancientGemAlliance)
|
||||
@@ -290,14 +294,14 @@ public:
|
||||
}
|
||||
|
||||
// Despawn all alliance NPCs
|
||||
_scheduler.Schedule(21000ms, [this](TaskContext)
|
||||
scheduler.Schedule(21000ms, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
// Spawn Roaring Flame after a delay
|
||||
_scheduler.Schedule(30s, [this](TaskContext)
|
||||
scheduler.Schedule(30s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _roaringFlameAlliance)
|
||||
{
|
||||
@@ -313,7 +317,7 @@ public:
|
||||
SaveToDB();
|
||||
break;
|
||||
case DATA_HORDE_RETREAT:
|
||||
_bossWave = 0;
|
||||
_bossWave = TO_BE_DECIDED;
|
||||
_retreat = DATA_HORDE_RETREAT;
|
||||
for (ObjectGuid const& guid : _ancientGemHorde)
|
||||
{
|
||||
@@ -338,13 +342,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_scheduler.Schedule(21000ms, [this](TaskContext)
|
||||
scheduler.Schedule(21000ms, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
_scheduler.Schedule(30s, [this](TaskContext)
|
||||
scheduler.Schedule(30s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _roaringFlameHorde)
|
||||
if (GameObject* flame = instance->GetGameObject(guid))
|
||||
@@ -360,45 +364,49 @@ public:
|
||||
_retreat = 0;
|
||||
if (GetBossState(DATA_WINTERCHILL) != DONE)
|
||||
{
|
||||
if (!_bossWave)
|
||||
if (_bossWave == TO_BE_DECIDED)
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
_bossWave = DATA_WINTERCHILL;
|
||||
ScheduleWaves(1ms, START_WAVE_WINTERCHILL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_WINTERCHILL - 1]);
|
||||
ScheduleWaves(1ms, START_WAVE_WINTERCHILL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_WINTERCHILL]);
|
||||
}
|
||||
else if (GetBossState(DATA_ANETHERON) != DONE)
|
||||
{
|
||||
if (!_bossWave)
|
||||
if (_bossWave == TO_BE_DECIDED)
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
_bossWave = DATA_ANETHERON;
|
||||
ScheduleWaves(1ms, START_WAVE_ANETHERON, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_ANETHERON - 1]);
|
||||
ScheduleWaves(1ms, START_WAVE_ANETHERON, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_ANETHERON]);
|
||||
}
|
||||
else if (GetBossState(DATA_KAZROGAL) != DONE)
|
||||
{
|
||||
if (!_bossWave)
|
||||
if (_bossWave == TO_BE_DECIDED)
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
_bossWave = DATA_KAZROGAL;
|
||||
ScheduleWaves(1ms, START_WAVE_KAZROGAL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_KAZROGAL - 1]);
|
||||
ScheduleWaves(1ms, START_WAVE_KAZROGAL, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_KAZROGAL]);
|
||||
}
|
||||
else if (GetBossState(DATA_AZGALOR) != DONE)
|
||||
{
|
||||
if (!_bossWave)
|
||||
if (_bossWave == TO_BE_DECIDED)
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
_bossWave = DATA_AZGALOR;
|
||||
ScheduleWaves(1ms, START_WAVE_AZGALOR, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_AZGALOR - 1]);
|
||||
ScheduleWaves(1ms, START_WAVE_AZGALOR, MAX_WAVES_STANDARD, hyjalWaveTimers[DATA_AZGALOR]);
|
||||
}
|
||||
else if (GetBossState(DATA_ARCHIMONDE) != DONE)
|
||||
{
|
||||
_bossWave = DATA_ARCHIMONDE;
|
||||
ScheduleWaves(1ms, START_WAVE_NIGHT_ELF, MAX_WAVES_NIGHT_ELF, hyjalNightElfWaveTimers[0]);
|
||||
}
|
||||
|
||||
if (_bossWave != TO_BE_DECIDED)
|
||||
DoUpdateWorldState(WORLD_STATE_WAVES, 0);
|
||||
|
||||
break;
|
||||
case DATA_SPAWN_INFERNALS:
|
||||
{
|
||||
@@ -419,89 +427,51 @@ public:
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATA_RESET_ALLIANCE:
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
// also force despawn boss summons
|
||||
for (ObjectGuid const& guid : _summonedNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
if (_bossWave && (GetBossState(_bossWave) != DONE))
|
||||
SetBossState(_bossWave, NOT_STARTED);
|
||||
|
||||
_scheduler.Schedule(300s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
});
|
||||
|
||||
SetData(DATA_RESET_WAVES, 0);
|
||||
break;
|
||||
case DATA_RESET_HORDE:
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
// also force despawn boss summons
|
||||
for (ObjectGuid const& guid : _summonedNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
if (_bossWave && (GetBossState(_bossWave) != DONE))
|
||||
SetBossState(_bossWave, NOT_STARTED);
|
||||
|
||||
_scheduler.Schedule(300s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
});
|
||||
|
||||
SetData(DATA_RESET_WAVES, 0);
|
||||
break;
|
||||
case DATA_RESET_NIGHT_ELF:
|
||||
if (Creature* archimonde = GetCreature(DATA_ARCHIMONDE))
|
||||
archimonde->DespawnOrUnsummon(0s, 300s);
|
||||
[[fallthrough]];
|
||||
case DATA_RESET_ALLIANCE:
|
||||
case DATA_RESET_HORDE:
|
||||
if (GetBossState(DATA_ANETHERON) != DONE)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon(0s, 300s);
|
||||
}
|
||||
|
||||
if (GetBossState(DATA_AZGALOR) != DONE)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon(0s, 300s);
|
||||
}
|
||||
|
||||
for (ObjectGuid const& guid : _baseNightElf)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
creature->DespawnOrUnsummon(0s, 300s);
|
||||
|
||||
for (ObjectGuid const& guid : _encounterNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
if (Creature* archimonde = GetCreature(DATA_ARCHIMONDE))
|
||||
archimonde->DespawnOrUnsummon();
|
||||
// also force despawn boss summons
|
||||
for (ObjectGuid const& guid : _summonedNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
_scheduler.Schedule(300s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseNightElf)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->Respawn();
|
||||
|
||||
if (Creature* archi = GetCreature(DATA_ARCHIMONDE))
|
||||
archi->Respawn();
|
||||
});
|
||||
if (_bossWave != TO_BE_DECIDED && (GetBossState(_bossWave) != DONE))
|
||||
SetBossState(_bossWave, NOT_STARTED);
|
||||
|
||||
SetData(DATA_RESET_WAVES, 0);
|
||||
break;
|
||||
case DATA_RESET_WAVES:
|
||||
_scheduler.CancelGroup(CONTEXT_GROUP_WAVES);
|
||||
scheduler.CancelGroup(CONTEXT_GROUP_WAVES);
|
||||
_encounterNPCs.clear();
|
||||
_summonedNPCs.clear();
|
||||
_currentWave = 0;
|
||||
trash = 0;
|
||||
_bossWave = 0;
|
||||
_bossWave = TO_BE_DECIDED;
|
||||
_retreat = 0;
|
||||
DoUpdateWorldState(WORLD_STATE_WAVES, _currentWave);
|
||||
DoUpdateWorldState(WORLD_STATE_ENEMY, trash);
|
||||
@@ -533,10 +503,10 @@ public:
|
||||
void ScheduleWaves(Milliseconds /* time */, uint8 startWaves, uint8 maxWaves, Milliseconds timerptr[])
|
||||
{
|
||||
// No overlapping!
|
||||
_scheduler.CancelGroup(CONTEXT_GROUP_WAVES);
|
||||
scheduler.CancelGroup(CONTEXT_GROUP_WAVES);
|
||||
trash = 0; // Reset counter here to avoid resetting the counter from scheduled waves. Required because creatures killed for RP events counts towards the kill counter as well, confirmed in Retail.
|
||||
|
||||
_scheduler.Schedule(1ms, [this, startWaves, maxWaves, timerptr](TaskContext context)
|
||||
scheduler.Schedule(1ms, [this, startWaves, maxWaves, timerptr](TaskContext context)
|
||||
{
|
||||
// If all waves reached, cancel scheduling new ones
|
||||
if (_currentWave >= maxWaves)
|
||||
@@ -572,7 +542,7 @@ public:
|
||||
|
||||
void Update(uint32 diff) override
|
||||
{
|
||||
_scheduler.Update(diff);
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void OnPlayerInWaterStateUpdate(Player* player, bool inWater) override
|
||||
@@ -588,7 +558,6 @@ public:
|
||||
uint8 _currentWave;
|
||||
uint8 _bossWave;
|
||||
uint8 _retreat;
|
||||
TaskScheduler _scheduler;
|
||||
GuidSet _encounterNPCs;
|
||||
GuidSet _summonedNPCs;
|
||||
GuidSet _baseAlliance;
|
||||
|
||||
+101
-57
@@ -82,6 +82,7 @@ enum Spells
|
||||
SPELL_SARTHARION_FLAME_BREATH = 56908,
|
||||
SPELL_SARTHARION_TAIL_LASH = 56910,
|
||||
SPELL_CYCLONE_AURA_PERIODIC = 57598,
|
||||
SPELL_LAVA_STRIKE_DUMMY = 57578,
|
||||
SPELL_LAVA_STRIKE_DUMMY_TRIGGER = 57697,
|
||||
SPELL_LAVA_STRIKE_SUMMON = 57572,
|
||||
SPELL_SARTHARION_PYROBUFFET = 56916,
|
||||
@@ -102,6 +103,7 @@ enum Spells
|
||||
// Misc
|
||||
SPELL_FADE_ARMOR = 60708,
|
||||
SPELL_FLAME_TSUNAMI_DAMAGE_AURA = 57492,
|
||||
SPELL_FLAME_TSUNAMI_LEAP = 60241,
|
||||
SPELL_SARTHARION_PYROBUFFET_TRIGGER = 57557,
|
||||
};
|
||||
|
||||
@@ -1512,65 +1514,107 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_sartharion_lava_strike : public SpellScriptLoader
|
||||
class spell_sartharion_lava_strike : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_sartharion_lava_strike() : SpellScriptLoader("spell_sartharion_lava_strike") {}
|
||||
PrepareSpellScript(spell_sartharion_lava_strike);
|
||||
|
||||
class spell_sartharion_lava_strike_SpellScript : public SpellScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareSpellScript(spell_sartharion_lava_strike_SpellScript);
|
||||
return ValidateSpellInfo({ SPELL_LAVA_STRIKE_SUMMON, SPELL_LAVA_STRIKE_DUMMY_TRIGGER });
|
||||
}
|
||||
|
||||
bool spawned;
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
spawned = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (!GetCaster() || !GetHitUnit())
|
||||
return;
|
||||
|
||||
GetCaster()->CastSpell(GetHitUnit()->GetPositionX(), GetHitUnit()->GetPositionY(), GetHitUnit()->GetPositionZ(), SPELL_LAVA_STRIKE_DUMMY_TRIGGER, true);
|
||||
}
|
||||
|
||||
void HandleSchoolDamage(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (!GetCaster() || !GetHitUnit() || spawned)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (InstanceScript* pInstance = GetCaster()->GetInstanceScript())
|
||||
{
|
||||
if (Creature* sarth = ObjectAccessor::GetCreature(*GetHitUnit(), pInstance->GetGuidData(DATA_SARTHARION)))
|
||||
{
|
||||
sarth->AI()->SetData(DATA_VOLCANO_BLOWS, GetHitUnit()->GetGUID().GetCounter());
|
||||
sarth->CastSpell(GetHitUnit(), SPELL_LAVA_STRIKE_SUMMON, true);
|
||||
spawned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
if (m_scriptSpellId == 57578) // Dummy lava strike
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike_SpellScript::HandleSchoolDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
bool Load() override
|
||||
{
|
||||
return new spell_sartharion_lava_strike_SpellScript();
|
||||
_spawned = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (!GetCaster() || !GetHitUnit())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetCaster()->CastSpell(GetHitUnit()->GetPositionX(), GetHitUnit()->GetPositionY(), GetHitUnit()->GetPositionZ(), SPELL_LAVA_STRIKE_DUMMY_TRIGGER, true);
|
||||
}
|
||||
|
||||
void HandleSchoolDamage(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (!GetCaster() || !GetHitUnit() || _spawned)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
{
|
||||
if (Creature* sarth = ObjectAccessor::GetCreature(*GetHitUnit(), instance->GetGuidData(DATA_SARTHARION)))
|
||||
{
|
||||
sarth->AI()->SetData(DATA_VOLCANO_BLOWS, GetHitUnit()->GetGUID().GetCounter());
|
||||
sarth->CastSpell(GetHitUnit(), SPELL_LAVA_STRIKE_SUMMON, true);
|
||||
_spawned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
if (m_scriptSpellId == SPELL_LAVA_STRIKE_DUMMY)
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_sartharion_lava_strike::HandleSchoolDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool _spawned;
|
||||
};
|
||||
|
||||
// 57491 - Flame Tsunami
|
||||
class spell_obsidian_sanctum_flame_tsunami : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_obsidian_sanctum_flame_tsunami);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FLAME_TSUNAMI_LEAP });
|
||||
}
|
||||
|
||||
void HandleHit(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
if (!target->HasAura(SPELL_FLAME_TSUNAMI_LEAP))
|
||||
{
|
||||
target->CastSpell(target, SPELL_FLAME_TSUNAMI_LEAP, true);
|
||||
bool isFacingSouth = std::fabs(GetCaster()->GetOrientation() - M_PI) < M_PI / 4;
|
||||
target->KnockbackFrom(isFacingSouth ? 3283.44f : 3208.44f , target->GetPositionY(), 12.5f, 9.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_obsidian_sanctum_flame_tsunami::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// 60241 - Flame Tsunami
|
||||
class spell_obsidian_sanctum_flame_tsunami_leap : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_obsidian_sanctum_flame_tsunami_leap);
|
||||
|
||||
void HandleLeapBack(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitEffect(effIndex);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_obsidian_sanctum_flame_tsunami_leap::HandleLeapBack, EFFECT_0, SPELL_EFFECT_LEAP_BACK);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1581,7 +1625,7 @@ void AddSC_boss_sartharion()
|
||||
new boss_sartharion_tenebron();
|
||||
new boss_sartharion_vesperon();
|
||||
new npc_twilight_summon();
|
||||
|
||||
new spell_sartharion_lava_strike();
|
||||
RegisterSpellScript(spell_sartharion_lava_strike);
|
||||
RegisterSpellScript(spell_obsidian_sanctum_flame_tsunami);
|
||||
RegisterSpellScript(spell_obsidian_sanctum_flame_tsunami_leap);
|
||||
}
|
||||
|
||||
|
||||
@@ -555,6 +555,11 @@ public:
|
||||
BossAI::AttackStart(target);
|
||||
}
|
||||
|
||||
void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER) override
|
||||
{
|
||||
CreatureAI::EnterEvadeMode(why);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override {}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
|
||||
@@ -1192,68 +1192,51 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_phase_punch : public SpellScriptLoader
|
||||
class spell_algalon_phase_punch_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_algalon_phase_punch() : SpellScriptLoader("spell_algalon_phase_punch") { }
|
||||
PrepareAuraScript(spell_algalon_phase_punch_aura);
|
||||
|
||||
class spell_algalon_phase_punch_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_algalon_phase_punch_AuraScript);
|
||||
return ValidateSpellInfo(PhasePunchAlphaId);
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (GetStackAmount() != 1)
|
||||
GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]);
|
||||
GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK);
|
||||
if (GetStackAmount() == 5)
|
||||
Remove(AURA_REMOVE_BY_DEFAULT);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const*, AuraEffectHandleModes)
|
||||
{
|
||||
if (GetStackAmount() != 5)
|
||||
GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
return new spell_algalon_phase_punch_AuraScript();
|
||||
PreventDefaultAction();
|
||||
if (GetStackAmount() != 1)
|
||||
GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 2]);
|
||||
GetTarget()->CastSpell(GetTarget(), PhasePunchAlphaId[GetStackAmount() - 1], TRIGGERED_FULL_MASK);
|
||||
if (GetStackAmount() == 5)
|
||||
Remove(AURA_REMOVE_BY_DEFAULT);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const*, AuraEffectHandleModes)
|
||||
{
|
||||
if (GetStackAmount() != 5)
|
||||
GetTarget()->RemoveAurasDueToSpell(PhasePunchAlphaId[GetStackAmount() - 1]);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_phase_punch_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_algalon_phase_punch_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_collapse : public SpellScriptLoader
|
||||
class spell_algalon_collapse_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_algalon_collapse() : SpellScriptLoader("spell_algalon_collapse") { }
|
||||
PrepareAuraScript(spell_algalon_collapse_aura);
|
||||
|
||||
class spell_algalon_collapse_AuraScript : public AuraScript
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PrepareAuraScript(spell_algalon_collapse_AuraScript);
|
||||
PreventDefaultAction();
|
||||
Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE);
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
Unit::DealDamage(GetTarget(), GetTarget(), GetTarget()->CountPctFromMaxHealth(1), nullptr, NODAMAGE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_algalon_collapse_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_collapse_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1266,172 +1249,123 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_trigger_3_adds : public SpellScriptLoader
|
||||
class spell_algalon_trigger_3_adds : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_algalon_trigger_3_adds() : SpellScriptLoader("spell_algalon_trigger_3_adds") { }
|
||||
PrepareSpellScript(spell_algalon_trigger_3_adds);
|
||||
|
||||
class spell_algalon_trigger_3_adds_SpellScript : public SpellScript
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareSpellScript(spell_algalon_trigger_3_adds_SpellScript);
|
||||
targets.remove_if(ActiveConstellationFilter());
|
||||
}
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if(ActiveConstellationFilter());
|
||||
}
|
||||
|
||||
void HandleDummyEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
Creature* target = GetHitCreature();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->AI()->DoAction(ACTION_ACTIVATE_STAR);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds_SpellScript::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void HandleDummyEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
return new spell_algalon_trigger_3_adds_SpellScript();
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
Creature* target = GetHitCreature();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->AI()->DoAction(ACTION_ACTIVATE_STAR);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_trigger_3_adds::SelectTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_algalon_trigger_3_adds::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_cosmic_smash_damage : public SpellScriptLoader
|
||||
class spell_algalon_cosmic_smash_damage : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_algalon_cosmic_smash_damage() : SpellScriptLoader("spell_algalon_cosmic_smash_damage") { }
|
||||
PrepareSpellScript(spell_algalon_cosmic_smash_damage);
|
||||
|
||||
class spell_algalon_cosmic_smash_damage_SpellScript : public SpellScript
|
||||
void RecalculateDamage()
|
||||
{
|
||||
PrepareSpellScript(spell_algalon_cosmic_smash_damage_SpellScript);
|
||||
if (!GetExplTargetDest() || !GetHitUnit())
|
||||
return;
|
||||
|
||||
void RecalculateDamage()
|
||||
{
|
||||
if (!GetExplTargetDest() || !GetHitUnit())
|
||||
return;
|
||||
float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY());
|
||||
if (distance >= 10.0f)
|
||||
SetHitDamage(int32(float(GetHitDamage()) / distance));
|
||||
else if (distance > 6.0f)
|
||||
SetHitDamage(int32(float(GetHitDamage()) / distance) * 2);
|
||||
}
|
||||
|
||||
float distance = GetHitUnit()->GetDistance2d(GetExplTargetDest()->GetPositionX(), GetExplTargetDest()->GetPositionY());
|
||||
if (distance >= 10.0f)
|
||||
SetHitDamage(int32(float(GetHitDamage()) / distance));
|
||||
else if (distance > 6.0f)
|
||||
SetHitDamage(int32(float(GetHitDamage()) / distance) * 2);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage_SpellScript::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_algalon_cosmic_smash_damage_SpellScript();
|
||||
OnHit += SpellHitFn(spell_algalon_cosmic_smash_damage::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_big_bang : public SpellScriptLoader
|
||||
class spell_algalon_big_bang : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_algalon_big_bang() : SpellScriptLoader("spell_algalon_big_bang") { }
|
||||
PrepareSpellScript(spell_algalon_big_bang);
|
||||
|
||||
class spell_algalon_big_bang_SpellScript : public SpellScript
|
||||
bool Load() override
|
||||
{
|
||||
PrepareSpellScript(spell_algalon_big_bang_SpellScript);
|
||||
_targetCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
_targetCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CountTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
_targetCount = targets.size();
|
||||
}
|
||||
|
||||
void CheckTargets()
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!_targetCount && caster && caster->GetAI())
|
||||
caster->GetAI()->DoAction(ACTION_ASCEND);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang_SpellScript::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
AfterCast += SpellCastFn(spell_algalon_big_bang_SpellScript::CheckTargets);
|
||||
}
|
||||
|
||||
uint32 _targetCount;
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void CountTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
return new spell_algalon_big_bang_SpellScript();
|
||||
_targetCount = targets.size();
|
||||
}
|
||||
|
||||
void CheckTargets()
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!_targetCount && caster && caster->GetAI())
|
||||
caster->GetAI()->DoAction(ACTION_ASCEND);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_algalon_big_bang::CountTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
AfterCast += SpellCastFn(spell_algalon_big_bang::CheckTargets);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _targetCount;
|
||||
};
|
||||
|
||||
class spell_algalon_remove_phase_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_algalon_remove_phase_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_BLACK_HOLE_DAMAGE });
|
||||
}
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE);
|
||||
GetTarget()->RemoveAurasDueToSpell(SPELL_BLACK_HOLE_DAMAGE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_aura::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_remove_phase : public SpellScriptLoader
|
||||
class spell_algalon_supermassive_fail : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_algalon_remove_phase() : SpellScriptLoader("spell_algalon_remove_phase") { }
|
||||
PrepareSpellScript(spell_algalon_supermassive_fail);
|
||||
|
||||
class spell_algalon_remove_phase_AuraScript : public AuraScript
|
||||
void RecalculateDamage()
|
||||
{
|
||||
PrepareAuraScript(spell_algalon_remove_phase_AuraScript);
|
||||
if (!GetHitPlayer())
|
||||
return;
|
||||
|
||||
void HandlePeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
GetTarget()->RemoveAurasByType(SPELL_AURA_PHASE);
|
||||
GetTarget()->RemoveAurasDueToSpell(SPELL_BLACK_HOLE_DAMAGE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_algalon_remove_phase_AuraScript::HandlePeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_algalon_remove_phase_AuraScript();
|
||||
GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_algalon_supermassive_fail : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_algalon_supermassive_fail() : SpellScriptLoader("spell_algalon_supermassive_fail") { }
|
||||
|
||||
class spell_algalon_supermassive_fail_SpellScript : public SpellScript
|
||||
void Register() override
|
||||
{
|
||||
PrepareSpellScript(spell_algalon_supermassive_fail_SpellScript);
|
||||
|
||||
void RecalculateDamage()
|
||||
{
|
||||
if (!GetHitPlayer())
|
||||
return;
|
||||
|
||||
GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnHit += SpellHitFn(spell_algalon_supermassive_fail_SpellScript::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_algalon_supermassive_fail_SpellScript();
|
||||
OnHit += SpellHitFn(spell_algalon_supermassive_fail::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1470,13 +1404,13 @@ void AddSC_boss_algalon_the_observer()
|
||||
new go_celestial_planetarium_access();
|
||||
|
||||
// Spells
|
||||
new spell_algalon_phase_punch();
|
||||
new spell_algalon_collapse();
|
||||
new spell_algalon_trigger_3_adds();
|
||||
new spell_algalon_cosmic_smash_damage();
|
||||
new spell_algalon_big_bang();
|
||||
new spell_algalon_remove_phase();
|
||||
new spell_algalon_supermassive_fail();
|
||||
RegisterSpellScript(spell_algalon_phase_punch_aura);
|
||||
RegisterSpellScript(spell_algalon_collapse_aura);
|
||||
RegisterSpellScript(spell_algalon_trigger_3_adds);
|
||||
RegisterSpellScript(spell_algalon_cosmic_smash_damage);
|
||||
RegisterSpellScript(spell_algalon_big_bang);
|
||||
RegisterSpellScript(spell_algalon_remove_phase_aura);
|
||||
RegisterSpellScript(spell_algalon_supermassive_fail);
|
||||
|
||||
// Achievements
|
||||
new achievement_algalon_he_feeds_on_your_tears();
|
||||
|
||||
@@ -844,94 +844,71 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_shield_of_runes : public SpellScriptLoader
|
||||
class spell_shield_of_runes_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_shield_of_runes() : SpellScriptLoader("spell_shield_of_runes") { }
|
||||
PrepareAuraScript(spell_shield_of_runes_aura);
|
||||
|
||||
class spell_shield_of_runes_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_shield_of_runes_AuraScript);
|
||||
return ValidateSpellInfo({ SPELL_SHIELD_OF_RUNES_BUFF });
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* owner = GetUnitOwner())
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && aurEff->GetAmount() <= 0)
|
||||
owner->CastSpell(owner, SPELL_SHIELD_OF_RUNES_BUFF, false);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_shield_of_runes_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
return new spell_shield_of_runes_AuraScript();
|
||||
if (Unit* owner = GetUnitOwner())
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && aurEff->GetAmount() <= 0)
|
||||
owner->CastSpell(owner, SPELL_SHIELD_OF_RUNES_BUFF, false);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_shield_of_runes_aura::OnRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_assembly_meltdown : public SpellScriptLoader
|
||||
class spell_assembly_meltdown : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_assembly_meltdown() : SpellScriptLoader("spell_assembly_meltdown") { }
|
||||
PrepareSpellScript(spell_assembly_meltdown);
|
||||
|
||||
class spell_assembly_meltdown_SpellScript : public SpellScript
|
||||
void HandleInstaKill(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
PrepareSpellScript(spell_assembly_meltdown_SpellScript);
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_STEELBREAKER)))
|
||||
Steelbreaker->AI()->DoAction(ACTION_ADD_CHARGE);
|
||||
}
|
||||
|
||||
void HandleInstaKill(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (InstanceScript* instance = GetCaster()->GetInstanceScript())
|
||||
if (Creature* Steelbreaker = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_STEELBREAKER)))
|
||||
Steelbreaker->AI()->DoAction(ACTION_ADD_CHARGE);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_assembly_meltdown_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_assembly_meltdown_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_assembly_meltdown::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_assembly_rune_of_summoning : public SpellScriptLoader
|
||||
class spell_assembly_rune_of_summoning_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_assembly_rune_of_summoning() : SpellScriptLoader("spell_assembly_rune_of_summoning") { }
|
||||
PrepareAuraScript(spell_assembly_rune_of_summoning_aura);
|
||||
|
||||
class spell_assembly_rune_of_summoning_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_assembly_rune_of_summoning_AuraScript);
|
||||
return ValidateSpellInfo({ SPELL_RUNE_OF_SUMMONING_SUMMON });
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (aurEff->GetTickNumber() % 2 == 0)
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_RUNE_OF_SUMMONING_SUMMON, true, nullptr, aurEff, GetTarget()->IsSummon() ? GetTarget()->ToTempSummon()->GetSummonerGUID() : ObjectGuid::Empty);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (TempSummon* summ = GetTarget()->ToTempSummon())
|
||||
summ->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_assembly_rune_of_summoning_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_assembly_rune_of_summoning_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
return new spell_assembly_rune_of_summoning_AuraScript();
|
||||
PreventDefaultAction();
|
||||
if (aurEff->GetTickNumber() % 2 == 0)
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_RUNE_OF_SUMMONING_SUMMON, true, nullptr, aurEff, GetTarget()->IsSummon() ? GetTarget()->ToTempSummon()->GetSummonerGUID() : ObjectGuid::Empty);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (TempSummon* summ = GetTarget()->ToTempSummon())
|
||||
summ->DespawnOrUnsummon(1);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_assembly_rune_of_summoning_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_assembly_rune_of_summoning_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -978,9 +955,9 @@ void AddSC_boss_assembly_of_iron()
|
||||
new boss_stormcaller_brundir();
|
||||
new npc_assembly_lightning();
|
||||
|
||||
new spell_shield_of_runes();
|
||||
new spell_assembly_meltdown();
|
||||
new spell_assembly_rune_of_summoning();
|
||||
RegisterSpellScript(spell_shield_of_runes_aura);
|
||||
RegisterSpellScript(spell_assembly_meltdown);
|
||||
RegisterSpellScript(spell_assembly_rune_of_summoning_aura);
|
||||
|
||||
new achievement_assembly_of_iron("achievement_but_im_on_your_side", 0);
|
||||
new achievement_assembly_of_iron("achievement_assembly_steelbreaker", NPC_STEELBREAKER);
|
||||
|
||||
@@ -432,29 +432,18 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_auriaya_sentinel_blast : public SpellScriptLoader
|
||||
class spell_auriaya_sentinel_blast : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_auriaya_sentinel_blast() : SpellScriptLoader("spell_auriaya_sentinel_blast") { }
|
||||
PrepareSpellScript(spell_auriaya_sentinel_blast);
|
||||
|
||||
class spell_auriaya_sentinel_blast_SpellScript : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& unitList)
|
||||
{
|
||||
PrepareSpellScript(spell_auriaya_sentinel_blast_SpellScript);
|
||||
unitList.remove_if(PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& unitList)
|
||||
{
|
||||
unitList.remove_if(PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_auriaya_sentinel_blast_SpellScript();
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auriaya_sentinel_blast::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -496,7 +485,7 @@ void AddSC_boss_auriaya()
|
||||
new npc_auriaya_sanctum_sentry();
|
||||
new npc_auriaya_feral_defender();
|
||||
|
||||
new spell_auriaya_sentinel_blast();
|
||||
RegisterSpellScript(spell_auriaya_sentinel_blast);
|
||||
|
||||
new achievement_auriaya_crazy_cat_lady();
|
||||
new achievement_auriaya_nine_lives();
|
||||
|
||||
@@ -1437,151 +1437,133 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_load_into_catapult : public SpellScriptLoader
|
||||
enum LoadIntoCataPult
|
||||
{
|
||||
enum Spells
|
||||
SPELL_PASSENGER_LOADED = 62340
|
||||
};
|
||||
|
||||
class spell_load_into_catapult_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_load_into_catapult_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
SPELL_PASSENGER_LOADED = 62340,
|
||||
};
|
||||
return ValidateSpellInfo({ SPELL_PASSENGER_LOADED });
|
||||
}
|
||||
|
||||
public:
|
||||
spell_load_into_catapult() : SpellScriptLoader("spell_load_into_catapult") { }
|
||||
|
||||
class spell_load_into_catapult_AuraScript : public AuraScript
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
PrepareAuraScript(spell_load_into_catapult_AuraScript);
|
||||
Unit* owner = GetOwner()->ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* owner = GetOwner()->ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
owner->CastSpell(owner, SPELL_PASSENGER_LOADED, true);
|
||||
}
|
||||
|
||||
owner->CastSpell(owner, SPELL_PASSENGER_LOADED, true);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* owner = GetOwner()->ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
owner->RemoveAurasDueToSpell(SPELL_PASSENGER_LOADED);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_load_into_catapult_AuraScript::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_load_into_catapult_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
return new spell_load_into_catapult_AuraScript();
|
||||
Unit* owner = GetOwner()->ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
owner->RemoveAurasDueToSpell(SPELL_PASSENGER_LOADED);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_load_into_catapult_aura::OnApply, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_load_into_catapult_aura::OnRemove, EFFECT_0, SPELL_AURA_CONTROL_VEHICLE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_auto_repair : public SpellScriptLoader
|
||||
enum AutoRepair
|
||||
{
|
||||
enum Spells
|
||||
SPELL_AUTO_REPAIR = 62705,
|
||||
};
|
||||
|
||||
class spell_auto_repair : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_auto_repair);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
SPELL_AUTO_REPAIR = 62705,
|
||||
};
|
||||
return ValidateSpellInfo({ SPELL_AUTO_REPAIR });
|
||||
}
|
||||
|
||||
public:
|
||||
spell_auto_repair() : SpellScriptLoader("spell_auto_repair") {}
|
||||
|
||||
class spell_auto_repair_SpellScript : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareSpellScript(spell_auto_repair_SpellScript);
|
||||
std::list<WorldObject*> tmplist;
|
||||
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
|
||||
if (!(*itr)->ToUnit()->HasAura(SPELL_AUTO_REPAIR))
|
||||
tmplist.push_back(*itr);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
std::list<WorldObject*> tmplist;
|
||||
for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
|
||||
if (!(*itr)->ToUnit()->HasAura(SPELL_AUTO_REPAIR))
|
||||
tmplist.push_back(*itr);
|
||||
targets.clear();
|
||||
for (std::list<WorldObject*>::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr)
|
||||
targets.push_back(*itr);
|
||||
}
|
||||
|
||||
targets.clear();
|
||||
for (std::list<WorldObject*>::iterator itr = tmplist.begin(); itr != tmplist.end(); ++itr)
|
||||
targets.push_back(*itr);
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*eff*/)
|
||||
{
|
||||
Vehicle* vehicle = GetHitUnit()->GetVehicleKit();
|
||||
if (!vehicle)
|
||||
return;
|
||||
|
||||
Unit* driver = vehicle->GetPassenger(0);
|
||||
if (!driver)
|
||||
return;
|
||||
|
||||
//driver->TextEmote(VEHICLE_EMOTE_REPAIR, driver, true); // No source
|
||||
|
||||
// Actually should/could use basepoints (100) for this spell effect as percentage of health, but oh well.
|
||||
vehicle->GetBase()->SetFullHealth();
|
||||
|
||||
// Achievement
|
||||
if (InstanceScript* instance = vehicle->GetBase()->GetInstanceScript())
|
||||
instance->SetData(DATA_UNBROKEN_ACHIEVEMENT, 0);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auto_repair_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_auto_repair_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void HandleScript(SpellEffIndex /*eff*/)
|
||||
{
|
||||
return new spell_auto_repair_SpellScript();
|
||||
Vehicle* vehicle = GetHitUnit()->GetVehicleKit();
|
||||
if (!vehicle)
|
||||
return;
|
||||
|
||||
Unit* driver = vehicle->GetPassenger(0);
|
||||
if (!driver)
|
||||
return;
|
||||
|
||||
//driver->TextEmote(VEHICLE_EMOTE_REPAIR, driver, true); // No source
|
||||
|
||||
// Actually should/could use basepoints (100) for this spell effect as percentage of health, but oh well.
|
||||
vehicle->GetBase()->SetFullHealth();
|
||||
|
||||
// Achievement
|
||||
if (InstanceScript* instance = vehicle->GetBase()->GetInstanceScript())
|
||||
instance->SetData(DATA_UNBROKEN_ACHIEVEMENT, 0);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_auto_repair::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_auto_repair::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_systems_shutdown : public SpellScriptLoader
|
||||
class spell_systems_shutdown_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_systems_shutdown() : SpellScriptLoader("spell_systems_shutdown") { }
|
||||
PrepareAuraScript(spell_systems_shutdown_aura);
|
||||
|
||||
class spell_systems_shutdown_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_systems_shutdown_AuraScript);
|
||||
return ValidateSpellInfo({ SPELL_GATHERING_SPEED });
|
||||
}
|
||||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Creature* owner = GetOwner()->ToCreature();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
owner->SetControlled(true, UNIT_STATE_STUNNED);
|
||||
owner->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED);
|
||||
if (Vehicle* veh = owner->GetVehicleKit())
|
||||
if (Unit* cannon = veh->GetPassenger(SEAT_CANNON))
|
||||
cannon->GetAI()->DoAction(ACTION_DELAY_CANNON);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Creature* owner = GetOwner()->ToCreature();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
owner->SetControlled(false, UNIT_STATE_STUNNED);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_systems_shutdown_AuraScript::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_systems_shutdown_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
return new spell_systems_shutdown_AuraScript();
|
||||
Creature* owner = GetOwner()->ToCreature();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
owner->SetControlled(true, UNIT_STATE_STUNNED);
|
||||
owner->RemoveAurasDueToSpell(SPELL_GATHERING_SPEED);
|
||||
if (Vehicle* vehicle = owner->GetVehicleKit())
|
||||
if (Unit* cannon = vehicle->GetPassenger(SEAT_CANNON))
|
||||
cannon->GetAI()->DoAction(ACTION_DELAY_CANNON);
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Creature* owner = GetOwner()->ToCreature();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
owner->SetControlled(false, UNIT_STATE_STUNNED);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_systems_shutdown_aura::OnApply, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_systems_shutdown_aura::OnRemove, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1625,431 +1607,344 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_pursue : public SpellScriptLoader
|
||||
class spell_pursue : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_pursue() : SpellScriptLoader("spell_pursue") {}
|
||||
PrepareSpellScript(spell_pursue);
|
||||
|
||||
class spell_pursue_SpellScript : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareSpellScript(spell_pursue_SpellScript);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
targets.remove_if(FlameLeviathanPursuedTargetSelector());
|
||||
if (targets.empty())
|
||||
{
|
||||
targets.remove_if(FlameLeviathanPursuedTargetSelector());
|
||||
if (targets.empty())
|
||||
{
|
||||
if (Creature* caster = GetCaster()->ToCreature())
|
||||
caster->AI()->EnterEvadeMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
//! In the end, only one target should be selected
|
||||
WorldObject* _target = Acore::Containers::SelectRandomContainerElement(targets);
|
||||
targets.clear();
|
||||
if (_target)
|
||||
targets.push_back(_target);
|
||||
}
|
||||
if (Creature* caster = GetCaster()->ToCreature())
|
||||
caster->AI()->EnterEvadeMode();
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*eff*/)
|
||||
else
|
||||
{
|
||||
Creature* target = GetHitCreature();
|
||||
Unit* caster = GetCaster();
|
||||
if (!target || !caster)
|
||||
return;
|
||||
|
||||
caster->GetThreatMgr().ResetAllThreat();
|
||||
caster->GetAI()->AttackStart(target); // Chase target
|
||||
caster->AddThreat(target, 10000000.0f);
|
||||
//! In the end, only one target should be selected
|
||||
WorldObject* _target = Acore::Containers::SelectRandomContainerElement(targets);
|
||||
targets.clear();
|
||||
if (_target)
|
||||
targets.push_back(_target);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pursue_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void HandleScript(SpellEffIndex /*eff*/)
|
||||
{
|
||||
return new spell_pursue_SpellScript();
|
||||
Creature* target = GetHitCreature();
|
||||
Unit* caster = GetCaster();
|
||||
if (!target || !caster)
|
||||
return;
|
||||
|
||||
caster->GetThreatMgr().ResetAllThreat();
|
||||
caster->GetAI()->AttackStart(target); // Chase target
|
||||
caster->AddThreat(target, 10000000.0f);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_pursue::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pursue::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_vehicle_throw_passenger : public SpellScriptLoader
|
||||
class spell_vehicle_throw_passenger : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_vehicle_throw_passenger() : SpellScriptLoader("spell_vehicle_throw_passenger") {}
|
||||
PrepareSpellScript(spell_vehicle_throw_passenger);
|
||||
|
||||
class spell_vehicle_throw_passenger_SpellScript : public SpellScript
|
||||
void HandleScript()
|
||||
{
|
||||
PrepareSpellScript(spell_vehicle_throw_passenger_SpellScript);
|
||||
void HandleScript()
|
||||
{
|
||||
Spell* baseSpell = GetSpell();
|
||||
SpellCastTargets targets = baseSpell->m_targets;
|
||||
if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
|
||||
if (Unit* passenger = vehicle->GetPassenger(3))
|
||||
Spell* baseSpell = GetSpell();
|
||||
SpellCastTargets targets = baseSpell->m_targets;
|
||||
if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
|
||||
if (Unit* passenger = vehicle->GetPassenger(3))
|
||||
{
|
||||
// use 99 because it is 3d search
|
||||
std::list<WorldObject*> targetList;
|
||||
Acore::WorldObjectSpellAreaTargetCheck check(99, GetExplTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, nullptr);
|
||||
Acore::WorldObjectListSearcher<Acore::WorldObjectSpellAreaTargetCheck> searcher(GetCaster(), targetList, check);
|
||||
Cell::VisitAllObjects(GetCaster(), searcher, 99.0f);
|
||||
float minDist = 99 * 99;
|
||||
Unit* target = nullptr;
|
||||
for (std::list<WorldObject*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
{
|
||||
// use 99 because it is 3d search
|
||||
std::list<WorldObject*> targetList;
|
||||
Acore::WorldObjectSpellAreaTargetCheck check(99, GetExplTargetDest(), GetCaster(), GetCaster(), GetSpellInfo(), TARGET_CHECK_DEFAULT, nullptr);
|
||||
Acore::WorldObjectListSearcher<Acore::WorldObjectSpellAreaTargetCheck> searcher(GetCaster(), targetList, check);
|
||||
Cell::VisitAllObjects(GetCaster(), searcher, 99.0f);
|
||||
float minDist = 99 * 99;
|
||||
Unit* target = nullptr;
|
||||
for (std::list<WorldObject*>::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
{
|
||||
if (Unit* unit = (*itr)->ToUnit())
|
||||
if (unit->GetEntry() == NPC_SEAT)
|
||||
if (Vehicle* seat = unit->GetVehicleKit())
|
||||
if (!seat->GetPassenger(0))
|
||||
if (Unit* device = seat->GetPassenger(2))
|
||||
if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
if (Unit* unit = (*itr)->ToUnit())
|
||||
if (unit->GetEntry() == NPC_SEAT)
|
||||
if (Vehicle* seat = unit->GetVehicleKit())
|
||||
if (!seat->GetPassenger(0))
|
||||
if (Unit* device = seat->GetPassenger(2))
|
||||
if (!device->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
{
|
||||
float dist = unit->GetExactDistSq(targets.GetDstPos());
|
||||
if (dist < minDist)
|
||||
{
|
||||
float dist = unit->GetExactDistSq(targets.GetDstPos());
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
target = unit;
|
||||
}
|
||||
minDist = dist;
|
||||
target = unit;
|
||||
}
|
||||
}
|
||||
if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->Effects[EFFECT_0].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct
|
||||
{
|
||||
passenger->ExitVehicle();
|
||||
passenger->EnterVehicle(target, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
passenger->ExitVehicle();
|
||||
float x, y, z;
|
||||
targets.GetDstPos()->GetPosition(x, y, z);
|
||||
passenger->GetMotionMaster()->MoveJump(x, y, z, targets.GetSpeedXY(), targets.GetSpeedZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterCast += SpellCastFn(spell_vehicle_throw_passenger_SpellScript::HandleScript);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_vehicle_throw_passenger_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_tar_blaze : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_tar_blaze() : SpellScriptLoader("spell_tar_blaze") { }
|
||||
|
||||
class spell_tar_blaze_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_tar_blaze_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
GetUnitOwner()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tar_blaze_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_tar_blaze_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_vehicle_grab_pyrite : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_vehicle_grab_pyrite() : SpellScriptLoader("spell_vehicle_grab_pyrite") {}
|
||||
|
||||
class spell_vehicle_grab_pyrite_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_vehicle_grab_pyrite_SpellScript);
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* target = GetHitUnit())
|
||||
if (Unit* seat = GetCaster()->GetVehicleBase())
|
||||
if (target && target->IsWithinDist2d(targets.GetDstPos(), GetSpellInfo()->Effects[EFFECT_0].CalcRadius() * 2)) // now we use *2 because the location of the seat is not correct
|
||||
{
|
||||
if (Vehicle* vSeat = seat->GetVehicleKit())
|
||||
if (Unit* pyrite = vSeat->GetPassenger(1))
|
||||
pyrite->ExitVehicle();
|
||||
|
||||
if (Unit* parent = seat->GetVehicleBase())
|
||||
{
|
||||
GetCaster()->CastSpell(parent, 62496 /*SPELL_ADD_PYRITE*/, true);
|
||||
target->CastSpell(seat, GetEffectValue());
|
||||
|
||||
if (target->GetTypeId() == TYPEID_UNIT)
|
||||
target->ToCreature()->DespawnOrUnsummon(1300);
|
||||
}
|
||||
passenger->ExitVehicle();
|
||||
passenger->EnterVehicle(target, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vehicle_grab_pyrite_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_vehicle_grab_pyrite_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_vehicle_circuit_overload : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_vehicle_circuit_overload() : SpellScriptLoader("spell_vehicle_circuit_overload") { }
|
||||
|
||||
class spell_vehicle_circuit_overload_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_vehicle_circuit_overload_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* target = GetTarget())
|
||||
if (int(target->GetAppliedAuras().count(SPELL_OVERLOAD_CIRCUIT)) >= (target->GetMap()->Is25ManRaid() ? 4 : 2))
|
||||
else
|
||||
{
|
||||
target->CastSpell(target, SPELL_SYSTEMS_SHUTDOWN, true);
|
||||
target->RemoveAurasDueToSpell(SPELL_OVERLOAD_CIRCUIT);
|
||||
passenger->ExitVehicle();
|
||||
float x, y, z;
|
||||
targets.GetDstPos()->GetPosition(x, y, z);
|
||||
passenger->GetMotionMaster()->MoveJump(x, y, z, targets.GetSpeedXY(), targets.GetSpeedZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_vehicle_circuit_overload_AuraScript::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_vehicle_circuit_overload_AuraScript();
|
||||
AfterCast += SpellCastFn(spell_vehicle_throw_passenger::HandleScript);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_orbital_supports : public SpellScriptLoader
|
||||
class spell_tar_blaze_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_orbital_supports() : SpellScriptLoader("spell_orbital_supports") { }
|
||||
PrepareAuraScript(spell_tar_blaze_aura);
|
||||
|
||||
class spell_orbital_supports_AuraScript : public AuraScript
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PrepareAuraScript(spell_orbital_supports_AuraScript);
|
||||
GetUnitOwner()->CastSpell((Unit*)nullptr, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true);
|
||||
}
|
||||
|
||||
bool CheckAreaTarget(Unit* target)
|
||||
{
|
||||
return target->GetEntry() == NPC_LEVIATHAN;
|
||||
}
|
||||
void Register() override
|
||||
{
|
||||
DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_orbital_supports_AuraScript::CheckAreaTarget);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_orbital_supports_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_tar_blaze_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_thorims_hammer : public SpellScriptLoader
|
||||
enum VehicleGrabPyrite
|
||||
{
|
||||
public:
|
||||
spell_thorims_hammer() : SpellScriptLoader("spell_thorims_hammer") { }
|
||||
SPELL_ADD_PYRITE = 62496
|
||||
};
|
||||
|
||||
class spell_thorims_hammer_SpellScript : public SpellScript
|
||||
class spell_vehicle_grab_pyrite : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_vehicle_grab_pyrite);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareSpellScript(spell_thorims_hammer_SpellScript);
|
||||
return ValidateSpellInfo({ SPELL_ADD_PYRITE });
|
||||
}
|
||||
|
||||
void RecalculateDamage(SpellEffIndex effIndex)
|
||||
{
|
||||
if (!GetHitUnit() || effIndex == EFFECT_1)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
float dist = GetHitUnit()->GetExactDist2d(GetCaster());
|
||||
if (dist <= 7.0f)
|
||||
{
|
||||
SetHitDamage(GetSpellInfo()->Effects[EFFECT_1].CalcValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
dist -= 6.0f;
|
||||
SetHitDamage(int32(GetSpellInfo()->Effects[EFFECT_1].CalcValue() / std::max(dist, 1.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_thorims_hammer_SpellScript::RecalculateDamage, EFFECT_ALL, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
return new spell_thorims_hammer_SpellScript();
|
||||
if (Unit* target = GetHitUnit())
|
||||
if (Unit* seat = GetCaster()->GetVehicleBase())
|
||||
{
|
||||
if (Vehicle* vehicle = seat->GetVehicleKit())
|
||||
if (Unit* pyrite = vehicle->GetPassenger(1))
|
||||
pyrite->ExitVehicle();
|
||||
|
||||
if (Unit* parent = seat->GetVehicleBase())
|
||||
{
|
||||
GetCaster()->CastSpell(parent, SPELL_ADD_PYRITE, true);
|
||||
target->CastSpell(seat, GetEffectValue());
|
||||
|
||||
if (target->GetTypeId() == TYPEID_UNIT)
|
||||
target->ToCreature()->DespawnOrUnsummon(1300);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_vehicle_grab_pyrite::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_transitus_shield_beam : public SpellScriptLoader
|
||||
class spell_vehicle_circuit_overload_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_transitus_shield_beam() : SpellScriptLoader("spell_transitus_shield_beam") { }
|
||||
PrepareAuraScript(spell_vehicle_circuit_overload_aura);
|
||||
|
||||
class spell_transitus_shield_beam_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_transitus_shield_beam_AuraScript);
|
||||
return ValidateSpellInfo({ SPELL_SYSTEMS_SHUTDOWN });
|
||||
}
|
||||
|
||||
void HandleOnEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (!target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aurEff->GetEffIndex())
|
||||
{
|
||||
case EFFECT_0:
|
||||
caster->AddAura(SPELL_TRANSITUS_SHIELD_IMPACT, target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
if (!caster)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (target)
|
||||
{
|
||||
target->RemoveAurasDueToSpell(SPELL_TRANSITUS_SHIELD_IMPACT);
|
||||
}
|
||||
}
|
||||
|
||||
void Register()
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_transitus_shield_beam_AuraScript::HandleOnEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_transitus_shield_beam_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
return new spell_transitus_shield_beam_AuraScript();
|
||||
if (Unit* target = GetTarget())
|
||||
if (int(target->GetAppliedAuras().count(SPELL_OVERLOAD_CIRCUIT)) >= (target->GetMap()->Is25ManRaid() ? 4 : 2))
|
||||
{
|
||||
target->CastSpell(target, SPELL_SYSTEMS_SHUTDOWN, true);
|
||||
target->RemoveAurasDueToSpell(SPELL_OVERLOAD_CIRCUIT);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_vehicle_circuit_overload_aura::OnPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_shield_generator : public SpellScriptLoader
|
||||
class spell_orbital_supports_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_shield_generator() : SpellScriptLoader("spell_shield_generator") { }
|
||||
PrepareAuraScript(spell_orbital_supports_aura);
|
||||
|
||||
class spell_shield_generator_AuraScript : public AuraScript
|
||||
bool CheckAreaTarget(Unit* target)
|
||||
{
|
||||
PrepareAuraScript(spell_shield_generator_AuraScript);
|
||||
|
||||
uint32 absorbPct;
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster());
|
||||
return true;
|
||||
}
|
||||
|
||||
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
// Set absorbtion amount to unlimited
|
||||
amount = -1;
|
||||
}
|
||||
|
||||
void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount)
|
||||
{
|
||||
absorbAmount = CalculatePct(dmgInfo.GetDamage(), absorbPct);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_shield_generator_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
|
||||
OnEffectAbsorb += AuraEffectAbsorbFn(spell_shield_generator_AuraScript::Absorb, EFFECT_0);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
return target->GetEntry() == NPC_LEVIATHAN;
|
||||
}
|
||||
void Register() override
|
||||
{
|
||||
return new spell_shield_generator_AuraScript();
|
||||
DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_orbital_supports_aura::CheckAreaTarget);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_demolisher_ride_vehicle : public SpellScriptLoader
|
||||
class spell_thorims_hammer : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_demolisher_ride_vehicle() : SpellScriptLoader("spell_demolisher_ride_vehicle") {}
|
||||
PrepareSpellScript(spell_thorims_hammer);
|
||||
|
||||
class spell_demolisher_ride_vehicle_SpellScript : public SpellScript
|
||||
void RecalculateDamage(SpellEffIndex effIndex)
|
||||
{
|
||||
PrepareSpellScript(spell_demolisher_ride_vehicle_SpellScript);
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
if (!GetHitUnit() || effIndex == EFFECT_1)
|
||||
{
|
||||
if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
|
||||
return SPELL_CAST_OK;
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = this->GetExplTargetUnit();
|
||||
if (!target || target->GetEntry() != NPC_SALVAGED_DEMOLISHER)
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
float dist = GetHitUnit()->GetExactDist2d(GetCaster());
|
||||
if (dist <= 7.0f)
|
||||
{
|
||||
SetHitDamage(GetSpellInfo()->Effects[EFFECT_1].CalcValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
dist -= 6.0f;
|
||||
SetHitDamage(int32(GetSpellInfo()->Effects[EFFECT_1].CalcValue() / std::max(dist, 1.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
Vehicle* veh = target->GetVehicleKit();
|
||||
if (veh && veh->GetPassenger(0))
|
||||
if (Unit* target2 = veh->GetPassenger(1))
|
||||
if (Vehicle* veh2 = target2->GetVehicleKit())
|
||||
{
|
||||
if (!veh2->GetPassenger(0))
|
||||
target2->HandleSpellClick(GetCaster());
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_thorims_hammer::RecalculateDamage, EFFECT_ALL, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
}
|
||||
class spell_transitus_shield_beam_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_transitus_shield_beam_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_TRANSITUS_SHIELD_IMPACT });
|
||||
}
|
||||
|
||||
void HandleOnEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (!target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aurEff->GetEffIndex())
|
||||
{
|
||||
case EFFECT_0:
|
||||
caster->AddAura(SPELL_TRANSITUS_SHIELD_IMPACT, target);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
|
||||
if (!caster)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if (target)
|
||||
{
|
||||
target->RemoveAurasDueToSpell(SPELL_TRANSITUS_SHIELD_IMPACT);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_transitus_shield_beam_aura::HandleOnEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_transitus_shield_beam_aura::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_shield_generator_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_shield_generator_aura);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
_absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(GetCaster());
|
||||
return true;
|
||||
}
|
||||
|
||||
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
|
||||
{
|
||||
// Set absorbtion amount to unlimited
|
||||
amount = -1;
|
||||
}
|
||||
|
||||
void Absorb(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& absorbAmount)
|
||||
{
|
||||
absorbAmount = CalculatePct(dmgInfo.GetDamage(), _absorbPct);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_shield_generator_aura::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB);
|
||||
OnEffectAbsorb += AuraEffectAbsorbFn(spell_shield_generator_aura::Absorb, EFFECT_0);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _absorbPct;
|
||||
};
|
||||
|
||||
class spell_demolisher_ride_vehicle : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_demolisher_ride_vehicle);
|
||||
|
||||
SpellCastResult CheckCast()
|
||||
{
|
||||
if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnCheckCast += SpellCheckCastFn(spell_demolisher_ride_vehicle_SpellScript::CheckCast);
|
||||
}
|
||||
};
|
||||
Unit* target = this->GetExplTargetUnit();
|
||||
if (!target || target->GetEntry() != NPC_SALVAGED_DEMOLISHER)
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
Vehicle* vehicle = target->GetVehicleKit();
|
||||
if (vehicle && vehicle->GetPassenger(0))
|
||||
if (Unit* target2 = vehicle->GetPassenger(1))
|
||||
if (Vehicle* vehicle2 = target2->GetVehicleKit())
|
||||
{
|
||||
if (!vehicle2->GetPassenger(0))
|
||||
target2->HandleSpellClick(GetCaster());
|
||||
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
}
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
return new spell_demolisher_ride_vehicle_SpellScript();
|
||||
OnCheckCast += SpellCheckCastFn(spell_demolisher_ride_vehicle::CheckCast);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2143,19 +2038,19 @@ void AddSC_boss_flame_leviathan()
|
||||
new go_ulduar_tower();
|
||||
|
||||
// Spells
|
||||
new spell_load_into_catapult();
|
||||
new spell_auto_repair();
|
||||
new spell_systems_shutdown();
|
||||
new spell_pursue();
|
||||
new spell_vehicle_throw_passenger();
|
||||
new spell_tar_blaze();
|
||||
new spell_vehicle_grab_pyrite();
|
||||
new spell_vehicle_circuit_overload();
|
||||
new spell_orbital_supports();
|
||||
new spell_thorims_hammer();
|
||||
new spell_transitus_shield_beam();
|
||||
new spell_shield_generator();
|
||||
new spell_demolisher_ride_vehicle();
|
||||
RegisterSpellScript(spell_load_into_catapult_aura);
|
||||
RegisterSpellScript(spell_auto_repair);
|
||||
RegisterSpellScript(spell_systems_shutdown_aura);
|
||||
RegisterSpellScript(spell_pursue);
|
||||
RegisterSpellScript(spell_vehicle_throw_passenger);
|
||||
RegisterSpellScript(spell_tar_blaze_aura);
|
||||
RegisterSpellScript(spell_vehicle_grab_pyrite);
|
||||
RegisterSpellScript(spell_vehicle_circuit_overload_aura);
|
||||
RegisterSpellScript(spell_orbital_supports_aura);
|
||||
RegisterSpellScript(spell_thorims_hammer);
|
||||
RegisterSpellScript(spell_transitus_shield_beam_aura);
|
||||
RegisterSpellScript(spell_shield_generator_aura);
|
||||
RegisterSpellScript(spell_demolisher_ride_vehicle);
|
||||
|
||||
// Achievements
|
||||
new achievement_flame_leviathan_towers("achievement_flame_leviathan_orbital_bombardment", 1);
|
||||
|
||||
@@ -472,173 +472,138 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_aura_of_despair : public SpellScriptLoader
|
||||
class spell_aura_of_despair_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_aura_of_despair() : SpellScriptLoader("spell_aura_of_despair") { }
|
||||
PrepareAuraScript(spell_aura_of_despair_aura);
|
||||
|
||||
class spell_aura_of_despair_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_aura_of_despair_AuraScript)
|
||||
return ValidateSpellInfo({ SPELL_AURA_OF_DESPAIR_2, SPELL_CORRUPTED_RAGE, SPELL_CORRUPTED_WISDOM });
|
||||
}
|
||||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
target->CastSpell(target, SPELL_AURA_OF_DESPAIR_2, true);
|
||||
if( target->HasSpell(SPELL_SHAMANISTIC_RAGE) )
|
||||
caster->CastSpell(target, SPELL_CORRUPTED_RAGE, true);
|
||||
else if( target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 2) )
|
||||
caster->CastSpell(target, SPELL_CORRUPTED_WISDOM, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_OF_DESPAIR_2);
|
||||
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_RAGE);
|
||||
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_WISDOM);
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
target->CastSpell(target, SPELL_AURA_OF_DESPAIR_2, true);
|
||||
if (target->HasSpell(SPELL_SHAMANISTIC_RAGE))
|
||||
caster->CastSpell(target, SPELL_CORRUPTED_RAGE, true);
|
||||
else if (target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 1) || target->HasSpell(SPELL_JUDGEMENTS_OF_THE_WISDOM_RANK_1 + 2))
|
||||
caster->CastSpell(target, SPELL_CORRUPTED_WISDOM, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_aura_of_despair_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_aura_of_despair_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
return new spell_aura_of_despair_AuraScript();
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_OF_DESPAIR_2);
|
||||
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_RAGE);
|
||||
target->RemoveAurasDueToSpell(SPELL_CORRUPTED_WISDOM);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_aura_of_despair_aura::OnApply, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_aura_of_despair_aura::OnRemove, EFFECT_0, SPELL_AURA_PREVENT_REGENERATE_POWER, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mark_of_the_faceless_periodic : public SpellScriptLoader
|
||||
class spell_mark_of_the_faceless_periodic_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_mark_of_the_faceless_periodic() : SpellScriptLoader("spell_mark_of_the_faceless_periodic") { }
|
||||
PrepareAuraScript(spell_mark_of_the_faceless_periodic_aura);
|
||||
|
||||
class spell_mark_of_the_faceless_periodic_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_mark_of_the_faceless_periodic_AuraScript)
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* target = GetTarget())
|
||||
if (target->GetMapId() == 603)
|
||||
{
|
||||
int32 dmg = 5000;
|
||||
caster->CastCustomSpell(target, SPELL_MARK_OF_THE_FACELESS_EFFECT, 0, &dmg, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_periodic_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_mark_of_the_faceless_periodic_AuraScript();
|
||||
return ValidateSpellInfo({ SPELL_MARK_OF_THE_FACELESS_EFFECT });
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mark_of_the_faceless_drainhealth : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_mark_of_the_faceless_drainhealth() : SpellScriptLoader("spell_mark_of_the_faceless_drainhealth") { }
|
||||
|
||||
class spell_mark_of_the_faceless_drainhealth_SpellScript : public SpellScript
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PrepareSpellScript(spell_mark_of_the_faceless_drainhealth_SpellScript);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove(GetExplTargetUnit());
|
||||
if (targets.empty())
|
||||
Cancel();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_the_faceless_drainhealth_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_mark_of_the_faceless_drainhealth_SpellScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_saronite_vapors_dummy : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_saronite_vapors_dummy() : SpellScriptLoader("spell_saronite_vapors_dummy") { }
|
||||
|
||||
class spell_saronite_vapors_dummy_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_saronite_vapors_dummy_AuraScript)
|
||||
|
||||
void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
int32 damage = 100 * pow(2.0f, (float)GetStackAmount());
|
||||
caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DMG, &damage, nullptr, nullptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_saronite_vapors_dummy_AuraScript::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_saronite_vapors_dummy_AuraScript();
|
||||
}
|
||||
};
|
||||
|
||||
class spell_saronite_vapors_damage : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
spell_saronite_vapors_damage() : SpellScriptLoader("spell_saronite_vapors_damage") { }
|
||||
|
||||
class spell_saronite_vapors_damage_SpellScript : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_saronite_vapors_damage_SpellScript);
|
||||
|
||||
void HandleAfterHit()
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (GetHitDamage() > 2)
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* target = GetTarget())
|
||||
if (target->GetMapId() == 603)
|
||||
{
|
||||
int32 mana = GetHitDamage() / 2;
|
||||
if (Unit* t = GetHitUnit())
|
||||
caster->CastCustomSpell(t, SPELL_SARONITE_VAPORS_ENERGIZE, &mana, nullptr, nullptr, true);
|
||||
int32 dmg = 5000;
|
||||
caster->CastCustomSpell(target, SPELL_MARK_OF_THE_FACELESS_EFFECT, 0, &dmg, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_saronite_vapors_damage_SpellScript::HandleAfterHit);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_saronite_vapors_damage_SpellScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_periodic_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mark_of_the_faceless_drainhealth : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_mark_of_the_faceless_drainhealth);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove(GetExplTargetUnit());
|
||||
if (targets.empty())
|
||||
Cancel();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_the_faceless_drainhealth::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_saronite_vapors_dummy_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_saronite_vapors_dummy_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SARONITE_VAPORS_DMG });
|
||||
}
|
||||
|
||||
void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
int32 damage = 100 * pow(2.0f, (float)GetStackAmount());
|
||||
caster->CastCustomSpell(GetTarget(), SPELL_SARONITE_VAPORS_DMG, &damage, nullptr, nullptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterEffectApply += AuraEffectApplyFn(spell_saronite_vapors_dummy_aura::HandleAfterEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_saronite_vapors_damage : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_saronite_vapors_damage);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SARONITE_VAPORS_ENERGIZE });
|
||||
}
|
||||
|
||||
void HandleAfterHit()
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
if (GetHitDamage() > 2)
|
||||
{
|
||||
int32 mana = GetHitDamage() / 2;
|
||||
if (Unit* target = GetHitUnit())
|
||||
caster->CastCustomSpell(target, SPELL_SARONITE_VAPORS_ENERGIZE, &mana, nullptr, nullptr, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_saronite_vapors_damage::HandleAfterHit);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -693,11 +658,11 @@ void AddSC_boss_vezax()
|
||||
new npc_ulduar_saronite_vapors();
|
||||
new npc_ulduar_saronite_animus();
|
||||
|
||||
new spell_aura_of_despair();
|
||||
new spell_mark_of_the_faceless_periodic();
|
||||
new spell_mark_of_the_faceless_drainhealth();
|
||||
new spell_saronite_vapors_dummy();
|
||||
new spell_saronite_vapors_damage();
|
||||
RegisterSpellScript(spell_aura_of_despair_aura);
|
||||
RegisterSpellScript(spell_mark_of_the_faceless_periodic_aura);
|
||||
RegisterSpellScript(spell_mark_of_the_faceless_drainhealth);
|
||||
RegisterSpellScript(spell_saronite_vapors_dummy_aura);
|
||||
RegisterSpellScript(spell_saronite_vapors_damage);
|
||||
|
||||
new achievement_smell_saronite();
|
||||
new achievement_shadowdodger();
|
||||
|
||||
@@ -426,112 +426,112 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_ignis_scorch : public SpellScriptLoader
|
||||
class spell_ignis_scorch_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_ignis_scorch() : SpellScriptLoader("spell_ignis_scorch") { }
|
||||
PrepareAuraScript(spell_ignis_scorch_aura);
|
||||
|
||||
class spell_ignis_scorch_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_ignis_scorch_AuraScript)
|
||||
return ValidateSpellInfo( { SPELL_SCORCHED_GROUND_10, SPELL_SCORCHED_GROUND_25 });
|
||||
}
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (aurEff->GetTotalTicks() >= 0 && aurEff->GetTickNumber() == uint32(aurEff->GetTotalTicks()))
|
||||
if (Unit* c = GetCaster())
|
||||
if (Creature* s = c->SummonCreature(NPC_SCORCHED_GROUND, c->GetPositionX() + 20.0f * cos(c->GetOrientation()), c->GetPositionY() + 20.0f * std::sin(c->GetOrientation()), 361.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000))
|
||||
{
|
||||
if (!s->FindNearestCreature(NPC_WATER_TRIGGER, 25.0f, true)) // must be away from the water
|
||||
s->CastSpell(s, (aurEff->GetId() == 62546 ? SPELL_SCORCHED_GROUND_10 : SPELL_SCORCHED_GROUND_25), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_scorch_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void HandleEffectPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
return new spell_ignis_scorch_AuraScript();
|
||||
if (aurEff->GetTotalTicks() >= 0 && aurEff->GetTickNumber() == uint32(aurEff->GetTotalTicks()))
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Creature* summon = caster->SummonCreature(NPC_SCORCHED_GROUND, caster->GetPositionX() + 20.0f * cos(caster->GetOrientation()), caster->GetPositionY() + 20.0f * std::sin(caster->GetOrientation()), 361.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 30000))
|
||||
{
|
||||
if (!summon->FindNearestCreature(NPC_WATER_TRIGGER, 25.0f, true)) // must be away from the water
|
||||
summon->CastSpell(summon, (aurEff->GetId() == SPELL_SCORCH_10 ? SPELL_SCORCHED_GROUND_10 : SPELL_SCORCHED_GROUND_25), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_scorch_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ignis_grab_initial : public SpellScriptLoader
|
||||
class spell_ignis_grab_initial : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_ignis_grab_initial() : SpellScriptLoader("spell_ignis_grab_initial") { }
|
||||
PrepareSpellScript(spell_ignis_grab_initial);
|
||||
|
||||
class spell_ignis_grab_initial_SpellScript : public SpellScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareSpellScript(spell_ignis_grab_initial_SpellScript);
|
||||
return ValidateSpellInfo( { SPELL_GRAB_TRIGGERED });
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* t = GetHitUnit())
|
||||
t->CastSpell(t, SPELL_GRAB_TRIGGERED, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_ignis_grab_initial_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
return new spell_ignis_grab_initial_SpellScript();
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->CastSpell(target, SPELL_GRAB_TRIGGERED, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_ignis_grab_initial::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ignis_slag_pot : public SpellScriptLoader
|
||||
enum SlagPot
|
||||
{
|
||||
public:
|
||||
spell_ignis_slag_pot() : SpellScriptLoader("spell_ignis_slag_pot") { }
|
||||
SPELL_SLAG_POT_DAMAGE_1 = 65722,
|
||||
SPELL_SLAG_POT_DAMAGE_2 = 65723,
|
||||
SPELL_SCORCH_DAMAGE_1 = 62549,
|
||||
SPELL_SCORCH_DAMAGE_2 = 63475,
|
||||
SPELL_SLAG_IMBUED_1 = 62836,
|
||||
SPELL_SLAG_IMBUED_2 = 63536
|
||||
};
|
||||
|
||||
class spell_ignis_slag_pot_AuraScript : public AuraScript
|
||||
class spell_ignis_slag_pot_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_ignis_slag_pot_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_ignis_slag_pot_AuraScript)
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* c = GetCaster())
|
||||
if (Unit* t = GetTarget())
|
||||
c->CastSpell(t, (GetId() == 62717 ? 65722 : 65723), true);
|
||||
}
|
||||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* t = GetTarget())
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, true);
|
||||
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, true);
|
||||
}
|
||||
}
|
||||
SPELL_SLAG_POT_DAMAGE_1,
|
||||
SPELL_SLAG_POT_DAMAGE_2,
|
||||
SPELL_SCORCH_DAMAGE_1,
|
||||
SPELL_SCORCH_DAMAGE_2,
|
||||
SPELL_SLAG_IMBUED_1,
|
||||
SPELL_SLAG_IMBUED_2
|
||||
});
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* t = GetTarget())
|
||||
{
|
||||
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 62549, false);
|
||||
t->ApplySpellImmune(GetId(), IMMUNITY_ID, 63475, false);
|
||||
if (t->IsAlive())
|
||||
t->CastSpell(t, (GetId() == 62717 ? 62836 : 63536), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_slag_pot_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectApply += AuraEffectApplyFn(spell_ignis_slag_pot_AuraScript::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_ignis_slag_pot_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
return new spell_ignis_slag_pot_AuraScript();
|
||||
if (Unit* caster = GetCaster())
|
||||
if (Unit* target = GetTarget())
|
||||
caster->CastSpell(target, (GetId() == SPELL_SLAG_POT_10 ? SPELL_SLAG_POT_DAMAGE_1 : SPELL_SLAG_POT_DAMAGE_2), true);
|
||||
}
|
||||
|
||||
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_1, true);
|
||||
target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_2, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Unit* target = GetTarget())
|
||||
{
|
||||
target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_1, false);
|
||||
target->ApplySpellImmune(GetId(), IMMUNITY_ID, SPELL_SCORCH_DAMAGE_2, false);
|
||||
if (target->IsAlive())
|
||||
target->CastSpell(target, (GetId() == SPELL_SLAG_POT_10 ? SPELL_SLAG_IMBUED_1 : SPELL_SLAG_IMBUED_2), true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ignis_slag_pot_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
|
||||
OnEffectApply += AuraEffectApplyFn(spell_ignis_slag_pot_aura::OnApply, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_ignis_slag_pot_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -552,8 +552,8 @@ void AddSC_boss_ignis()
|
||||
{
|
||||
new boss_ignis();
|
||||
new npc_ulduar_iron_construct();
|
||||
new spell_ignis_scorch();
|
||||
new spell_ignis_grab_initial();
|
||||
new spell_ignis_slag_pot();
|
||||
RegisterSpellScript(spell_ignis_scorch_aura);
|
||||
RegisterSpellScript(spell_ignis_grab_initial);
|
||||
RegisterSpellScript(spell_ignis_slag_pot_aura);
|
||||
new achievement_ignis_shattered();
|
||||
}
|
||||
|
||||
@@ -718,156 +718,107 @@ private:
|
||||
Unit const* _victim;
|
||||
};
|
||||
|
||||
class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader
|
||||
class spell_ulduar_stone_grip_cast_target : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_ulduar_stone_grip_cast_target() : SpellScriptLoader("spell_ulduar_stone_grip_cast_target") { }
|
||||
PrepareSpellScript(spell_ulduar_stone_grip_cast_target);
|
||||
|
||||
class spell_ulduar_stone_grip_cast_target_SpellScript : public SpellScript
|
||||
bool Load() override
|
||||
{
|
||||
PrepareSpellScript(spell_ulduar_stone_grip_cast_target_SpellScript);
|
||||
if (GetCaster()->GetTypeId() != TYPEID_UNIT)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
if (GetCaster()->GetTypeId() != TYPEID_UNIT)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilterTargetsInitial(std::list<WorldObject*>& targets)
|
||||
{
|
||||
// Remove "main tank" and non-player targets
|
||||
targets.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim()));
|
||||
// Maximum affected targets per difficulty mode
|
||||
uint32 maxTargets = 1;
|
||||
if (GetSpellInfo()->Id == 63981)
|
||||
maxTargets = 3;
|
||||
|
||||
// Return a random amount of targets based on maxTargets
|
||||
while (maxTargets < targets.size())
|
||||
{
|
||||
std::list<WorldObject*>::iterator itr = targets.begin();
|
||||
advance(itr, urand(0, targets.size() - 1));
|
||||
targets.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target_SpellScript::FilterTargetsInitial, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void FilterTargetsInitial(std::list<WorldObject*>& targets)
|
||||
{
|
||||
return new spell_ulduar_stone_grip_cast_target_SpellScript();
|
||||
// Remove "main tank" and non-player targets
|
||||
targets.remove_if (StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim()));
|
||||
// Maximum affected targets per difficulty mode
|
||||
uint32 maxTargets = 1;
|
||||
if (GetSpellInfo()->Id == 63981)
|
||||
maxTargets = 3;
|
||||
|
||||
// Return a random amount of targets based on maxTargets
|
||||
while (maxTargets < targets.size())
|
||||
{
|
||||
std::list<WorldObject*>::iterator itr = targets.begin();
|
||||
advance(itr, urand(0, targets.size() - 1));
|
||||
targets.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_ulduar_stone_grip_cast_target::FilterTargetsInitial, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ulduar_stone_grip : public SpellScriptLoader
|
||||
class spell_ulduar_stone_grip_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_ulduar_stone_grip() : SpellScriptLoader("spell_ulduar_stone_grip") { }
|
||||
PrepareAuraScript(spell_ulduar_stone_grip_aura);
|
||||
|
||||
class spell_ulduar_stone_grip_AuraScript : public AuraScript
|
||||
void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
PrepareAuraScript(spell_ulduar_stone_grip_AuraScript);
|
||||
if (Player* owner = GetOwner()->ToPlayer())
|
||||
owner->RemoveAurasDueToSpell(aurEff->GetAmount());
|
||||
}
|
||||
|
||||
void OnRemoveStun(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* owner = GetOwner()->ToPlayer())
|
||||
owner->RemoveAurasDueToSpell(aurEff->GetAmount());
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_AuraScript::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_ulduar_stone_grip_AuraScript();
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_ulduar_stone_grip_aura::OnRemoveStun, EFFECT_2, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ulduar_squeezed_lifeless : public SpellScriptLoader
|
||||
class spell_ulduar_squeezed_lifeless : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_ulduar_squeezed_lifeless() : SpellScriptLoader("spell_ulduar_squeezed_lifeless") { }
|
||||
PrepareSpellScript(spell_ulduar_squeezed_lifeless);
|
||||
|
||||
class spell_ulduar_squeezed_lifeless_SpellScript : public SpellScript
|
||||
void HandleInstaKill(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
PrepareSpellScript(spell_ulduar_squeezed_lifeless_SpellScript);
|
||||
if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle())
|
||||
return;
|
||||
|
||||
void HandleInstaKill(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (!GetHitPlayer() || !GetHitPlayer()->GetVehicle())
|
||||
return;
|
||||
// Hack to set correct position is in _ExitVehicle()
|
||||
GetHitPlayer()->ExitVehicle();
|
||||
}
|
||||
|
||||
// Hack to set correct position is in _ExitVehicle()
|
||||
GetHitPlayer()->ExitVehicle();
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_ulduar_squeezed_lifeless_SpellScript::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_ulduar_squeezed_lifeless_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_ulduar_squeezed_lifeless::HandleInstaKill, EFFECT_1, SPELL_EFFECT_INSTAKILL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_kologarn_stone_shout : public SpellScriptLoader
|
||||
class spell_kologarn_stone_shout : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_kologarn_stone_shout() : SpellScriptLoader("spell_kologarn_stone_shout") { }
|
||||
PrepareSpellScript(spell_kologarn_stone_shout);
|
||||
|
||||
class spell_kologarn_stone_shout_AuraScript : public AuraScript
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareAuraScript(spell_kologarn_stone_shout_AuraScript);
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
uint32 triggerSpellId = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell;
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(caster, triggerSpellId, false);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
if (m_scriptSpellId == SPELL_STONE_SHOUT_10 || m_scriptSpellId == SPELL_STONE_SHOUT_25)
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kologarn_stone_shout_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_kologarn_stone_shout_AuraScript();
|
||||
targets.remove_if (PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
class spell_kologarn_stone_shout_SpellScript : public SpellScript
|
||||
void Register() override
|
||||
{
|
||||
PrepareSpellScript(spell_kologarn_stone_shout_SpellScript);
|
||||
if (m_scriptSpellId != SPELL_STONE_SHOUT_10 && m_scriptSpellId != SPELL_STONE_SHOUT_25)
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if (PlayerOrPetCheck());
|
||||
}
|
||||
class spell_kologarn_stone_shout_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_kologarn_stone_shout_aura);
|
||||
|
||||
void Register() override
|
||||
{
|
||||
if (m_scriptSpellId != SPELL_STONE_SHOUT_10 && m_scriptSpellId != SPELL_STONE_SHOUT_25)
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_kologarn_stone_shout_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
return new spell_kologarn_stone_shout_SpellScript();
|
||||
uint32 triggerSpellId = GetSpellInfo()->Effects[EFFECT_0].TriggerSpell;
|
||||
if (Unit* caster = GetCaster())
|
||||
caster->CastSpell(caster, triggerSpellId, false);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
if (m_scriptSpellId == SPELL_STONE_SHOUT_10 || m_scriptSpellId == SPELL_STONE_SHOUT_25)
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_kologarn_stone_shout_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -928,10 +879,10 @@ void AddSC_boss_kologarn()
|
||||
RegisterUlduarCreatureAI(boss_kologarn_pit_kill_bunny);
|
||||
|
||||
// Spells
|
||||
new spell_ulduar_stone_grip_cast_target();
|
||||
new spell_ulduar_stone_grip();
|
||||
new spell_ulduar_squeezed_lifeless();
|
||||
new spell_kologarn_stone_shout();
|
||||
RegisterSpellScript(spell_ulduar_stone_grip_cast_target);
|
||||
RegisterSpellScript(spell_ulduar_stone_grip_aura);
|
||||
RegisterSpellScript(spell_ulduar_squeezed_lifeless);
|
||||
RegisterSpellAndAuraScriptPair(spell_kologarn_stone_shout, spell_kologarn_stone_shout_aura);
|
||||
|
||||
// Achievements
|
||||
new achievement_kologarn_looks_could_kill();
|
||||
|
||||
@@ -2104,87 +2104,83 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_mimiron_rapid_burst : public SpellScriptLoader
|
||||
class spell_mimiron_rapid_burst_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_mimiron_rapid_burst() : SpellScriptLoader("spell_mimiron_rapid_burst") { }
|
||||
PrepareAuraScript(spell_mimiron_rapid_burst_aura);
|
||||
|
||||
class spell_mimiron_rapid_burst_AuraScript : public AuraScript
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_mimiron_rapid_burst_AuraScript)
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (Unit* c = GetCaster())
|
||||
return ValidateSpellInfo(
|
||||
{
|
||||
uint32 id = ( c->GetMap()->Is25ManRaid() ? ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_25_2 : SPELL_RAPID_BURST_DAMAGE_25_1) : ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_10_2 : SPELL_RAPID_BURST_DAMAGE_10_1) );
|
||||
c->CastSpell((Unit*)nullptr, id, true);
|
||||
}
|
||||
}
|
||||
SPELL_RAPID_BURST_DAMAGE_10_1,
|
||||
SPELL_RAPID_BURST_DAMAGE_10_2,
|
||||
SPELL_RAPID_BURST_DAMAGE_25_1,
|
||||
SPELL_RAPID_BURST_DAMAGE_25_2
|
||||
});
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_rapid_burst_AuraScript::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void HandleEffectPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
return new spell_mimiron_rapid_burst_AuraScript();
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
uint32 id = (caster->GetMap()->Is25ManRaid() ? ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_25_2 : SPELL_RAPID_BURST_DAMAGE_25_1) : ((aurEff->GetTickNumber() % 2) ? SPELL_RAPID_BURST_DAMAGE_10_2 : SPELL_RAPID_BURST_DAMAGE_10_1));
|
||||
caster->CastSpell((Unit*)nullptr, id, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_rapid_burst_aura::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mimiron_p3wx2_laser_barrage : public SpellScriptLoader
|
||||
enum p3wx2LaserBarrage
|
||||
{
|
||||
public:
|
||||
spell_mimiron_p3wx2_laser_barrage() : SpellScriptLoader("spell_mimiron_p3wx2_laser_barrage") { }
|
||||
SPELL_P3WX2_LASER_BARRAGE_1 = 63297,
|
||||
SPELL_P3WX2_LASER_BARRAGE_2 = 64042
|
||||
};
|
||||
|
||||
class spell_mimiron_p3wx2_laser_barrage_AuraScript : public AuraScript
|
||||
class spell_mimiron_p3wx2_laser_barrage_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_mimiron_p3wx2_laser_barrage_aura);
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
PrepareAuraScript(spell_mimiron_p3wx2_laser_barrage_AuraScript)
|
||||
|
||||
uint32 lastMSTime;
|
||||
float lastOrientation;
|
||||
|
||||
bool Load() override
|
||||
{
|
||||
lastMSTime = GameTime::GetGameTimeMS().count();
|
||||
lastOrientation = -1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* c = GetCaster())
|
||||
{
|
||||
if (c->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
uint32 diff = getMSTimeDiff(lastMSTime, GameTime::GetGameTimeMS().count());
|
||||
if (lastOrientation == -1.0f)
|
||||
{
|
||||
lastOrientation = (c->ToCreature()->AI()->GetData(0) * 2 * M_PI) / 100.0f;
|
||||
diff = 0;
|
||||
}
|
||||
float new_o = Position::NormalizeOrientation(lastOrientation - (M_PI / 60) * (diff / 250.0f));
|
||||
lastMSTime = GameTime::GetGameTimeMS().count();
|
||||
lastOrientation = new_o;
|
||||
c->SetFacingTo(new_o);
|
||||
|
||||
c->CastSpell((Unit*)nullptr, 63297, true);
|
||||
c->CastSpell((Unit*)nullptr, 64042, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_p3wx2_laser_barrage_AuraScript::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_mimiron_p3wx2_laser_barrage_AuraScript();
|
||||
_lastMSTime = GameTime::GetGameTimeMS().count();
|
||||
_lastOrientation = -1.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
if (caster->GetTypeId() != TYPEID_UNIT)
|
||||
return;
|
||||
uint32 diff = getMSTimeDiff(_lastMSTime, GameTime::GetGameTimeMS().count());
|
||||
if (_lastOrientation == -1.0f)
|
||||
{
|
||||
_lastOrientation = (caster->ToCreature()->AI()->GetData(0) * 2 * M_PI) / 100.0f;
|
||||
diff = 0;
|
||||
}
|
||||
float new_o = Position::NormalizeOrientation(_lastOrientation - (M_PI / 60) * (diff / 250.0f));
|
||||
_lastMSTime = GameTime::GetGameTimeMS().count();
|
||||
_lastOrientation = new_o;
|
||||
caster->SetFacingTo(new_o);
|
||||
|
||||
caster->CastSpell((Unit*)nullptr, SPELL_P3WX2_LASER_BARRAGE_1, true);
|
||||
caster->CastSpell((Unit*)nullptr, SPELL_P3WX2_LASER_BARRAGE_2, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mimiron_p3wx2_laser_barrage_aura::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 _lastMSTime;
|
||||
float _lastOrientation;
|
||||
};
|
||||
|
||||
class go_ulduar_do_not_push_this_button : public GameObjectScript
|
||||
@@ -2518,8 +2514,8 @@ void AddSC_boss_mimiron()
|
||||
new npc_ulduar_mimiron_rocket();
|
||||
new npc_ulduar_magnetic_core();
|
||||
new npc_ulduar_bot_summon_trigger();
|
||||
new spell_mimiron_rapid_burst();
|
||||
new spell_mimiron_p3wx2_laser_barrage();
|
||||
RegisterSpellScript(spell_mimiron_rapid_burst_aura);
|
||||
RegisterSpellScript(spell_mimiron_p3wx2_laser_barrage_aura);
|
||||
new go_ulduar_do_not_push_this_button();
|
||||
new npc_ulduar_flames_initial();
|
||||
new npc_ulduar_flames_spread();
|
||||
|
||||
@@ -1729,59 +1729,37 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_thorim_lightning_pillar_P2 : public SpellScriptLoader
|
||||
class spell_thorim_lightning_pillar_P2_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_thorim_lightning_pillar_P2() : SpellScriptLoader("spell_thorim_lightning_pillar_P2") { }
|
||||
PrepareAuraScript(spell_thorim_lightning_pillar_P2_aura);
|
||||
|
||||
class spell_thorim_lightning_pillar_P2_AuraScript : public AuraScript
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PrepareAuraScript(spell_thorim_lightning_pillar_P2_AuraScript);
|
||||
PreventDefaultAction();
|
||||
if (Unit* caster = GetCaster())
|
||||
GetUnitOwner()->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true);
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
PreventDefaultAction();
|
||||
if (Unit* caster = GetCaster())
|
||||
GetUnitOwner()->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_lightning_pillar_P2_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_thorim_lightning_pillar_P2_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_lightning_pillar_P2_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_thorim_trash_impale : public SpellScriptLoader
|
||||
class spell_thorim_trash_impale_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_thorim_trash_impale() : SpellScriptLoader("spell_thorim_trash_impale") { }
|
||||
PrepareAuraScript(spell_thorim_trash_impale_aura);
|
||||
|
||||
class spell_thorim_trash_impale_AuraScript : public AuraScript
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PrepareAuraScript(spell_thorim_trash_impale_AuraScript);
|
||||
// deals damage until target is healed above 90%
|
||||
if (GetUnitOwner()->HealthAbovePct(90))
|
||||
SetDuration(0);
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
// deals damage until target is healed above 90%
|
||||
if (GetUnitOwner()->HealthAbovePct(90))
|
||||
SetDuration(0);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_trash_impale_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_thorim_trash_impale_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_trash_impale_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1838,8 +1816,8 @@ void AddSC_boss_thorim()
|
||||
new go_thorim_lever();
|
||||
|
||||
// Spells
|
||||
new spell_thorim_lightning_pillar_P2();
|
||||
new spell_thorim_trash_impale();
|
||||
RegisterSpellScript(spell_thorim_lightning_pillar_P2_aura);
|
||||
RegisterSpellScript(spell_thorim_trash_impale_aura);
|
||||
|
||||
// Achievements
|
||||
new achievement_thorim_stand_in_the_lightning();
|
||||
|
||||
@@ -857,191 +857,147 @@ public:
|
||||
};
|
||||
|
||||
// 62775 - Tympanic Tantrum
|
||||
class spell_xt002_tympanic_tantrum : public SpellScriptLoader
|
||||
class spell_xt002_tympanic_tantrum : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_xt002_tympanic_tantrum() : SpellScriptLoader("spell_xt002_tympanic_tantrum") { }
|
||||
PrepareSpellScript(spell_xt002_tympanic_tantrum);
|
||||
|
||||
class spell_xt002_tympanic_tantrum_SpellScript : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareSpellScript(spell_xt002_tympanic_tantrum_SpellScript);
|
||||
targets.remove_if(PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if(PlayerOrPetCheck());
|
||||
}
|
||||
|
||||
void RecalculateDamage()
|
||||
{
|
||||
if (GetHitUnit())
|
||||
SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(GetHitDamage()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnHit += SpellHitFn(spell_xt002_tympanic_tantrum_SpellScript::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void RecalculateDamage()
|
||||
{
|
||||
return new spell_xt002_tympanic_tantrum_SpellScript();
|
||||
if (GetHitUnit())
|
||||
SetHitDamage(GetHitUnit()->CountPctFromMaxHealth(GetHitDamage()));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_tympanic_tantrum::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
OnHit += SpellHitFn(spell_xt002_tympanic_tantrum::RecalculateDamage);
|
||||
}
|
||||
};
|
||||
|
||||
// 64234, 63024 - Gravity Bomb
|
||||
class spell_xt002_gravity_bomb_aura : public SpellScriptLoader
|
||||
enum GravityBomb
|
||||
{
|
||||
public:
|
||||
spell_xt002_gravity_bomb_aura() : SpellScriptLoader("spell_xt002_gravity_bomb_aura") { }
|
||||
SPELL_GRAVTY_BOMB_10 = 63025
|
||||
};
|
||||
|
||||
class spell_xt002_gravity_bomb_aura_AuraScript : public AuraScript
|
||||
class spell_xt002_gravity_bomb : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_xt002_gravity_bomb);
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareAuraScript(spell_xt002_gravity_bomb_aura_AuraScript);
|
||||
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetOwner()->ToPlayer())
|
||||
if (Unit* xt002 = GetCaster())
|
||||
if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode
|
||||
if (Creature* cr = xt002->SummonCreature(NPC_VOID_ZONE, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000))
|
||||
{
|
||||
int32 damage = GetSpellInfo()->Id == 63025 ? 5000 : 7500;
|
||||
cr->CastCustomSpell(cr, SPELL_VOID_ZONE_DAMAGE, &damage, 0, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
Unit* xt002 = GetCaster();
|
||||
if (!xt002)
|
||||
return;
|
||||
|
||||
Unit* owner = GetOwner()->ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (aurEff->GetAmount() >= int32(owner->GetHealth()))
|
||||
if (xt002->GetAI())
|
||||
xt002->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_xt002_gravity_bomb_aura_AuraScript::OnPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_xt002_gravity_bomb_aura_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_xt002_gravity_bomb_aura_AuraScript();
|
||||
if (Unit* victim = GetCaster()->GetVictim())
|
||||
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
|
||||
}
|
||||
|
||||
class spell_xt002_gravity_bomb_aura_SpellScript : public SpellScript
|
||||
void Register() override
|
||||
{
|
||||
PrepareSpellScript(spell_xt002_gravity_bomb_aura_SpellScript);
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_gravity_bomb::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (Unit* victim = GetCaster()->GetVictim())
|
||||
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
|
||||
}
|
||||
class spell_xt002_gravity_bomb_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_xt002_gravity_bomb_aura);
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_gravity_bomb_aura_SpellScript::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return new spell_xt002_gravity_bomb_aura_SpellScript();
|
||||
return ValidateSpellInfo({ SPELL_VOID_ZONE_DAMAGE });
|
||||
}
|
||||
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetOwner()->ToPlayer())
|
||||
if (Unit* xt002 = GetCaster())
|
||||
if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode
|
||||
if (Creature* creature = xt002->SummonCreature(NPC_VOID_ZONE, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000))
|
||||
{
|
||||
int32 damage = GetSpellInfo()->Id == SPELL_GRAVTY_BOMB_10 ? 5000 : 7500;
|
||||
creature->CastCustomSpell(creature, SPELL_VOID_ZONE_DAMAGE, &damage, 0, 0, true);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
Unit* xt002 = GetCaster();
|
||||
if (!xt002)
|
||||
return;
|
||||
|
||||
Unit* owner = GetOwner()->ToUnit();
|
||||
if (!owner)
|
||||
return;
|
||||
|
||||
if (aurEff->GetAmount() >= int32(owner->GetHealth()))
|
||||
if (xt002->GetAI())
|
||||
xt002->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_xt002_gravity_bomb_aura::OnPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
AfterEffectRemove += AuraEffectRemoveFn(spell_xt002_gravity_bomb_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
// 64233, 63025 - Gravity Bomb
|
||||
class spell_xt002_gravity_bomb_damage : public SpellScriptLoader
|
||||
class spell_xt002_gravity_bomb_damage : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_xt002_gravity_bomb_damage() : SpellScriptLoader("spell_xt002_gravity_bomb_damage") { }
|
||||
PrepareSpellScript(spell_xt002_gravity_bomb_damage);
|
||||
|
||||
class spell_xt002_gravity_bomb_damage_SpellScript : public SpellScript
|
||||
void HandleScript(SpellEffIndex /*eff*/)
|
||||
{
|
||||
PrepareSpellScript(spell_xt002_gravity_bomb_damage_SpellScript);
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
void HandleScript(SpellEffIndex /*eff*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
if (GetHitDamage() >= int32(GetHitUnit()->GetHealth()))
|
||||
if (caster->GetAI())
|
||||
caster->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV);
|
||||
}
|
||||
|
||||
if (GetHitDamage() >= int32(GetHitUnit()->GetHealth()))
|
||||
if (caster->GetAI())
|
||||
caster->GetAI()->DoAction(DATA_XT002_GRAVITY_ACHIEV);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_xt002_gravity_bomb_damage_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_xt002_gravity_bomb_damage_SpellScript();
|
||||
OnEffectHitTarget += SpellEffectFn(spell_xt002_gravity_bomb_damage::HandleScript, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
// 63018, 65121 - Searing Light
|
||||
class spell_xt002_searing_light_spawn_life_spark : public SpellScriptLoader
|
||||
class spell_xt002_searing_light_spawn_life_spark : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_xt002_searing_light_spawn_life_spark() : SpellScriptLoader("spell_xt002_searing_light_spawn_life_spark") { }
|
||||
PrepareSpellScript(spell_xt002_searing_light_spawn_life_spark);
|
||||
|
||||
class spell_xt002_searing_light_spawn_life_spark_AuraScript : public AuraScript
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareAuraScript(spell_xt002_searing_light_spawn_life_spark_AuraScript);
|
||||
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (Player* player = GetOwner()->ToPlayer())
|
||||
if (Unit* xt002 = GetCaster())
|
||||
if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode
|
||||
xt002->SummonCreature(NPC_LIFE_SPARK, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_xt002_searing_light_spawn_life_spark_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_xt002_searing_light_spawn_life_spark_AuraScript();
|
||||
if (Unit* victim = GetCaster()->GetVictim())
|
||||
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
|
||||
}
|
||||
|
||||
class spell_xt002_searing_light_spawn_life_spark_SpellScript : public SpellScript
|
||||
void Register() override
|
||||
{
|
||||
PrepareSpellScript(spell_xt002_searing_light_spawn_life_spark_SpellScript);
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_searing_light_spawn_life_spark::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
void SelectTarget(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (Unit* victim = GetCaster()->GetVictim())
|
||||
targets.remove_if(Acore::ObjectGUIDCheck(victim->GetGUID(), true));
|
||||
}
|
||||
class spell_xt002_searing_light_spawn_life_spark_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_xt002_searing_light_spawn_life_spark_aura);
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_xt002_searing_light_spawn_life_spark_SpellScript::SelectTarget, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
void OnRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
return new spell_xt002_searing_light_spawn_life_spark_SpellScript();
|
||||
if (Player* player = GetOwner()->ToPlayer())
|
||||
if (Unit* xt002 = GetCaster())
|
||||
if (xt002->HasAura(aurEff->GetAmount())) // Heartbreak aura indicating hard mode
|
||||
xt002->SummonCreature(NPC_LIFE_SPARK, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_xt002_searing_light_spawn_life_spark_aura::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1088,10 +1044,10 @@ void AddSC_boss_xt002()
|
||||
new npc_xt002_life_spark();
|
||||
|
||||
// Spells
|
||||
new spell_xt002_tympanic_tantrum();
|
||||
new spell_xt002_gravity_bomb_aura();
|
||||
new spell_xt002_gravity_bomb_damage();
|
||||
new spell_xt002_searing_light_spawn_life_spark();
|
||||
RegisterSpellScript(spell_xt002_tympanic_tantrum);
|
||||
RegisterSpellAndAuraScriptPair(spell_xt002_gravity_bomb, spell_xt002_gravity_bomb_aura);
|
||||
RegisterSpellScript(spell_xt002_gravity_bomb_damage);
|
||||
RegisterSpellAndAuraScriptPair(spell_xt002_searing_light_spawn_life_spark, spell_xt002_searing_light_spawn_life_spark_aura);
|
||||
|
||||
// Achievements
|
||||
new achievement_xt002_nerf_engineering();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -79,7 +79,8 @@ enum UldSpells
|
||||
{
|
||||
SPELL_SIMPLE_TELEPORT = 12980,
|
||||
SPELL_KEEPER_TELEPORT = 62940,
|
||||
SPELL_SNOW_MOUND_PARTICLES = 64615
|
||||
SPELL_SNOW_MOUND_PARTICLES = 64615,
|
||||
SPELL_ENERGY_SAP_10 = 64740
|
||||
};
|
||||
|
||||
class npc_ulduar_keeper : public CreatureScript
|
||||
@@ -201,30 +202,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class spell_ulduar_energy_sap : public SpellScriptLoader
|
||||
enum EnergySap
|
||||
{
|
||||
public:
|
||||
spell_ulduar_energy_sap() : SpellScriptLoader("spell_ulduar_energy_sap") { }
|
||||
SPELL_ENERGY_SAP_DAMAGE_1 = 64747,
|
||||
SPELL_ENERGY_SAP_DAMAGE_2 = 64863,
|
||||
};
|
||||
|
||||
class spell_ulduar_energy_sap_AuraScript : public AuraScript
|
||||
class spell_ulduar_energy_sap_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_ulduar_energy_sap_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
PrepareAuraScript(spell_ulduar_energy_sap_AuraScript)
|
||||
return ValidateSpellInfo({ SPELL_ENERGY_SAP_DAMAGE_1, SPELL_ENERGY_SAP_DAMAGE_2 });
|
||||
}
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
if (Unit* target = GetTarget())
|
||||
target->CastSpell(target, (aurEff->GetId() == 64740) ? 64747 : 64863, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_energy_sap_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void HandleEffectPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
return new spell_ulduar_energy_sap_AuraScript();
|
||||
if (Unit* target = GetTarget())
|
||||
target->CastSpell(target, (aurEff->GetId() == SPELL_ENERGY_SAP_10) ? SPELL_ENERGY_SAP_DAMAGE_1 : SPELL_ENERGY_SAP_DAMAGE_2, true);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_energy_sap_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -500,30 +501,19 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
class spell_ulduar_arachnopod_damaged : public SpellScriptLoader
|
||||
class spell_ulduar_arachnopod_damaged_aura : public AuraScript
|
||||
{
|
||||
public:
|
||||
spell_ulduar_arachnopod_damaged() : SpellScriptLoader("spell_ulduar_arachnopod_damaged") { }
|
||||
PrepareAuraScript(spell_ulduar_arachnopod_damaged_aura);
|
||||
|
||||
class spell_ulduar_arachnopod_damaged_AuraScript : public AuraScript
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
PrepareAuraScript(spell_ulduar_arachnopod_damaged_AuraScript)
|
||||
if (Unit* caster = GetCaster())
|
||||
Unit::Kill(caster, caster, false);
|
||||
}
|
||||
|
||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||
{
|
||||
if (Unit* c = GetCaster())
|
||||
Unit::Kill(c, c, false);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_arachnopod_damaged_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_ulduar_arachnopod_damaged_AuraScript();
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_ulduar_arachnopod_damaged_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -576,11 +566,11 @@ struct npc_salvaged_siege_engine : public VehicleAI
|
||||
void AddSC_ulduar()
|
||||
{
|
||||
new npc_ulduar_keeper();
|
||||
new spell_ulduar_energy_sap();
|
||||
RegisterSpellScript(spell_ulduar_energy_sap_aura);
|
||||
RegisterUlduarCreatureAI(npc_ulduar_snow_mound);
|
||||
new npc_ulduar_storm_tempered_keeper();
|
||||
new npc_ulduar_arachnopod_destroyer();
|
||||
new spell_ulduar_arachnopod_damaged();
|
||||
RegisterSpellScript(spell_ulduar_arachnopod_damaged_aura);
|
||||
new AreaTrigger_at_celestial_planetarium_enterance();
|
||||
RegisterCreatureAI(npc_salvaged_siege_engine);
|
||||
}
|
||||
|
||||
@@ -213,6 +213,7 @@ struct npc_akama_shade : public ScriptedAI
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
DoCastSelf(SPELL_STEALTH, true);
|
||||
me->SetWalk(true);
|
||||
_sayLowHealth = false;
|
||||
scheduler.CancelAll();
|
||||
}
|
||||
|
||||
@@ -261,6 +262,15 @@ struct npc_akama_shade : public ScriptedAI
|
||||
}
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*unit*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (me->HealthBelowPctDamaged(20, damage) && !_sayLowHealth)
|
||||
{
|
||||
_sayLowHealth = true;
|
||||
Talk(SAY_LOW_HEALTH);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_AKAMA_START_OUTRO)
|
||||
@@ -284,6 +294,7 @@ struct npc_akama_shade : public ScriptedAI
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
if (Creature* shade = instance->GetCreature(DATA_SHADE_OF_AKAMA))
|
||||
{
|
||||
shade->SetHomePosition(shade->GetHomePosition());
|
||||
@@ -318,6 +329,9 @@ struct npc_akama_shade : public ScriptedAI
|
||||
scheduler.Update(diff);
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool _sayLowHealth;
|
||||
};
|
||||
|
||||
struct npc_creature_generator_akama : public ScriptedAI
|
||||
|
||||
@@ -43,14 +43,20 @@ enum Spells
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_SPELL_BERSERK = 1,
|
||||
EVENT_TALK_CHECK = 2
|
||||
EVENT_TALK_CHECK = 1,
|
||||
EVENT_ENRAGE = 2
|
||||
};
|
||||
|
||||
struct boss_najentus : public BossAI
|
||||
{
|
||||
boss_najentus(Creature* creature) : BossAI(creature, DATA_HIGH_WARLORD_NAJENTUS), _canTalk(true) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
me->m_Events.CancelEventGroup(EVENT_ENRAGE);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
_canTalk = true;
|
||||
@@ -58,11 +64,10 @@ struct boss_najentus : public BossAI
|
||||
BossAI::JustEngagedWith(who);
|
||||
Talk(SAY_AGGRO);
|
||||
|
||||
ScheduleUniqueTimedEvent(8min, [&]
|
||||
{
|
||||
me->m_Events.AddEventAtOffset([this] {
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCastSelf(SPELL_BERSERK, true);
|
||||
}, EVENT_SPELL_BERSERK);
|
||||
}, 8min, EVENT_ENRAGE);
|
||||
|
||||
ScheduleTimedEvent(25s, 100s, [&]
|
||||
{
|
||||
|
||||
@@ -253,16 +253,8 @@ public:
|
||||
void HandleScriptEffect(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
Unit* target = GetHitUnit();
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_MOD_CHARM);
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_MOD_STUN);
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_MOD_DECREASE_SPEED);
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_MOD_ROOT);
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_MOD_CONFUSE);
|
||||
target->RemoveAurasDueToSpell(SPELL_AURA_MOD_FEAR);
|
||||
if (Unit* target = GetHitUnit())
|
||||
target->RemoveAurasWithMechanic(IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ class spell_serpentshrine_cavern_serpentshrine_parasite : public AuraScript
|
||||
|
||||
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
if (GetTarget()->GetInstanceScript() && GetTarget()->GetInstanceScript()->IsEncounterInProgress())
|
||||
if (GetTarget()->GetInstanceScript())
|
||||
GetTarget()->CastSpell(GetTarget(), SPELL_SUMMON_SERPENTSHRINE_PARASITE, true);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,8 +30,18 @@
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_QUAGMIRRAN, DATA_QUAGMIRRAN },
|
||||
{ 0, 0 }
|
||||
{ NPC_QUAGMIRRAN, DATA_QUAGMIRRAN },
|
||||
{ NPC_AHUNE, DATA_AHUNE },
|
||||
{ NPC_AHUNE_LOC_BUNNY, DATA_AHUNE_BUNNY },
|
||||
{ NPC_FROZEN_CORE, DATA_FROZEN_CORE },
|
||||
{ NPC_SHAMAN_BONFIRE_BUNNY_000, DATA_BONFIRE_BUNNY_000 },
|
||||
{ NPC_SHAMAN_BONFIRE_BUNNY_001, DATA_BONFIRE_BUNNY_001 },
|
||||
{ NPC_SHAMAN_BONFIRE_BUNNY_002, DATA_BONFIRE_BUNNY_002 },
|
||||
{ NPC_SHAMAN_BEAM_BUNNY_000, DATA_BEAM_BUNNY_000 },
|
||||
{ NPC_SHAMAN_BEAM_BUNNY_001, DATA_BEAM_BUNNY_001 },
|
||||
{ NPC_SHAMAN_BEAM_BUNNY_002, DATA_BEAM_BUNNY_002 },
|
||||
{ NPC_LUMA_SKYMOTHER, DATA_LUMA_SKYMOTHER },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
class instance_the_slave_pens : public InstanceMapScript
|
||||
|
||||
@@ -114,6 +114,12 @@ private:
|
||||
bool _hasFlag;
|
||||
};
|
||||
|
||||
enum FlagOfOwnership
|
||||
{
|
||||
TEXT_FLAG_OF_OWNERSHIP = 28008,
|
||||
SPELL_TAUNT_FLAG = 52605
|
||||
};
|
||||
|
||||
// 51640 - Taunt Flag Targeting
|
||||
class spell_the_flag_of_ownership : public SpellScript
|
||||
{
|
||||
@@ -126,7 +132,7 @@ class spell_the_flag_of_ownership : public SpellScript
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
|
||||
@@ -134,10 +140,13 @@ class spell_the_flag_of_ownership : public SpellScript
|
||||
Player* target = GetHitPlayer();
|
||||
if (!target)
|
||||
return;
|
||||
caster->CastSpell(target, 52605, true);
|
||||
char buff[100];
|
||||
snprintf(buff, sizeof(buff), "%s plants the Flag of Ownership in the corpse of %s.", caster->GetName().c_str(), target->GetName().c_str());
|
||||
caster->TextEmote(buff, caster);
|
||||
caster->CastSpell(target, SPELL_TAUNT_FLAG, true);
|
||||
|
||||
LocaleConstant loc_idx = caster->ToPlayer()->GetSession()->GetSessionDbLocaleIndex();
|
||||
BroadcastText const* bct = sObjectMgr->GetBroadcastText(TEXT_FLAG_OF_OWNERSHIP);
|
||||
std::string bctMsg = Acore::StringFormat(bct->GetText(loc_idx, caster->getGender()), caster->GetName().c_str(), target->GetName().c_str());
|
||||
caster->Talk(bctMsg, CHAT_MSG_MONSTER_EMOTE, LANG_UNIVERSAL, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), target);
|
||||
|
||||
haveTarget = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,12 @@ enum PaladinSpells
|
||||
|
||||
// Crystalforge Raiment - Tier 5 Holy 2 Set
|
||||
SPELL_IMPROVED_JUDGEMENT = 37188,
|
||||
SPELL_IMPROVED_JUDGEMENT_ENERGIZE = 43838
|
||||
SPELL_IMPROVED_JUDGEMENT_ENERGIZE = 43838,
|
||||
|
||||
SPELL_PALADIN_HOLY_VENGEANCE = 31803,
|
||||
SPELL_PALADIN_BLOOD_CORRUPTION = 53742,
|
||||
SPELL_PALADIN_SEAL_OF_VENGEANCE_EFFECT = 42463,
|
||||
SPELL_PALADIN_SEAL_OF_CORRUPTION_EFFECT = 53739
|
||||
};
|
||||
|
||||
enum PaladinSpellIcons
|
||||
@@ -1105,6 +1110,45 @@ class spell_pal_seal_of_righteousness : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
// 42463 - Seal of Vengeance
|
||||
// 53739 - Seal of Corruption
|
||||
class spell_pal_seal_of_vengeance : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_pal_seal_of_vengeance);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_PALADIN_SEAL_OF_VENGEANCE_EFFECT, SPELL_PALADIN_SEAL_OF_CORRUPTION_EFFECT });
|
||||
}
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* target = GetExplTargetUnit();
|
||||
uint32 spellId = GetSpell()->GetSpellInfo()->Id;
|
||||
uint32 auraId = (spellId == SPELL_PALADIN_SEAL_OF_VENGEANCE_EFFECT)
|
||||
? SPELL_PALADIN_HOLY_VENGEANCE
|
||||
: SPELL_PALADIN_BLOOD_CORRUPTION;
|
||||
int32 damage = GetHitDamage();
|
||||
uint8 stacks = 0;
|
||||
|
||||
if (target)
|
||||
{
|
||||
Aura* aura = target->GetAura(auraId, GetCaster()->GetGUID());
|
||||
if (aura)
|
||||
stacks = aura->GetStackAmount();
|
||||
|
||||
damage = ((damage * stacks) / 5);
|
||||
|
||||
SetHitDamage(damage);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_pal_seal_of_vengeance::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_paladin_spell_scripts()
|
||||
{
|
||||
RegisterSpellAndAuraScriptPair(spell_pal_seal_of_command, spell_pal_seal_of_command_aura);
|
||||
@@ -1132,5 +1176,6 @@ void AddSC_paladin_spell_scripts()
|
||||
RegisterSpellScript(spell_pal_lay_on_hands);
|
||||
RegisterSpellScript(spell_pal_righteous_defense);
|
||||
RegisterSpellScript(spell_pal_seal_of_righteousness);
|
||||
RegisterSpellScript(spell_pal_seal_of_vengeance);
|
||||
}
|
||||
|
||||
|
||||
@@ -2602,6 +2602,17 @@ public:
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
bool CanAIAttack(Unit const* target) const override
|
||||
{
|
||||
if (Unit* summoner = me->GetCharmerOrOwner())
|
||||
{
|
||||
if (target->IsPlayer() && (!summoner->IsPvP() || !target->IsPvP()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_FLAME_BUFFET, 4s);
|
||||
@@ -2610,12 +2621,9 @@ public:
|
||||
|
||||
void IsSummonedBy(WorldObject* summoner) override
|
||||
{
|
||||
if (summoner->GetTypeId() != TYPEID_UNIT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (summoner->GetTypeId() == TYPEID_UNIT || summoner->IsPlayer())
|
||||
me->GetMotionMaster()->MoveFollow(summoner->ToUnit(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
|
||||
me->GetMotionMaster()->MoveFollow(summoner->ToUnit(), PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
|
||||
Reference in New Issue
Block a user