Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-12-31 17:18:40 +08:00
102 changed files with 2247 additions and 409 deletions
+25 -13
View File
@@ -374,20 +374,24 @@ public:
return true;
}
static bool HandleNpcDeleteCommand(ChatHandler* handler)
static bool HandleNpcDeleteCommand(ChatHandler* handler, Optional<ObjectGuid::LowType> lowGuid)
{
Creature* unit = handler->getSelectedCreature();
Creature* creature;
if (lowGuid.has_value())
creature = handler->GetCreatureFromPlayerMapByDbGuid(*lowGuid);
else
creature = handler->getSelectedCreature();
if (!unit || unit->IsPet() || unit->IsTotem())
if (!creature || creature->IsPet() || creature->IsTotem())
{
handler->SendErrorMessage(LANG_SELECT_CREATURE);
return false;
}
// Delete the creature
unit->CombatStop();
unit->DeleteFromDB();
unit->AddObjectToRemoveList();
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
handler->SendSysMessage(LANG_COMMAND_DELCREATMESSAGE);
@@ -712,25 +716,33 @@ public:
}
//move selected creature
static bool HandleNpcMoveCommand(ChatHandler* handler)
static bool HandleNpcMoveCommand(ChatHandler* handler, Optional<ObjectGuid::LowType> guid)
{
Creature* creature = handler->getSelectedCreature();
Creature* creature;
if (guid.has_value())
creature = handler->GetCreatureFromPlayerMapByDbGuid(*guid);
else
creature = handler->getSelectedCreature();
if (!creature)
return false;
ObjectGuid::LowType lowguid = creature->GetSpawnId();
ObjectGuid::LowType lowGuid;
if (guid.has_value())
lowGuid = *guid;
else
lowGuid = creature->GetSpawnId();
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
if (!data)
{
handler->SendErrorMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SendErrorMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
return false;
}
if (handler->GetSession()->GetPlayer()->GetMapId() != data->mapid)
{
handler->SendErrorMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
handler->SendErrorMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowGuid);
return false;
}
@@ -764,7 +776,7 @@ public:
stmt->SetData(1, y);
stmt->SetData(2, z);
stmt->SetData(3, o);
stmt->SetData(4, lowguid);
stmt->SetData(4, lowGuid);
WorldDatabase.Execute(stmt);
@@ -135,6 +135,7 @@ public:
{ "npc_spellclick_spells", HandleReloadSpellClickSpellsCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "npc_trainer", HandleReloadNpcTrainerCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "npc_vendor", HandleReloadNpcVendorCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "game_event_npc_vendor", HandleReloadGameEventNPCVendorCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "page_text", HandleReloadPageTextsCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "pickpocketing_loot_template", HandleReloadLootTemplatesPickpocketingCommand, SEC_ADMINISTRATOR, Console::Yes },
{ "points_of_interest", HandleReloadPointsOfInterestCommand, SEC_ADMINISTRATOR, Console::Yes },
@@ -765,6 +766,14 @@ public:
return true;
}
static bool HandleReloadGameEventNPCVendorCommand(ChatHandler* handler)
{
LOG_INFO("server.loading", "Reloading `game_event_npc_vendor` Table!");
sGameEventMgr->LoadEventVendors();
handler->SendGlobalGMSysMessage("DB table `game_event_npc_vendor` reloaded.");
return true;
}
static bool HandleReloadPointsOfInterestCommand(ChatHandler* handler)
{
LOG_INFO("server.loading", "Reloading `points_of_interest` Table!");
@@ -188,11 +188,8 @@ public:
{
DoCast(player, afflictionSpellID, true);
if (player->HasAura(SPELL_BROODAF_BLUE) && player->HasAura(SPELL_BROODAF_BLACK) && player->HasAura(SPELL_BROODAF_RED) &&
player->HasAura(SPELL_BROODAF_BRONZE) && player->HasAura(SPELL_BROODAF_GREEN))
{
if (player->HasAllAuras(SPELL_BROODAF_BLUE, SPELL_BROODAF_BLACK, SPELL_BROODAF_RED, SPELL_BROODAF_BRONZE, SPELL_BROODAF_GREEN))
DoCast(player, SPELL_CHROMATIC_MUT_1);
}
}
}
events.ScheduleEvent(EVENT_AFFLICTION, 10s);
@@ -1424,6 +1424,7 @@ struct npc_chesspiece : public ScriptedAI
_instance = creature->GetInstanceScript();
_currentOrientation = GetDefaultOrientationForTeam();
_homePosition = creature->GetPosition();
_nextMoveTimer = urand(8 * IN_MILLISECONDS, 20 * IN_MILLISECONDS);
@@ -1457,6 +1458,8 @@ struct npc_chesspiece : public ScriptedAI
{
me->SetResistance(SpellSchools(i), 0);
}
me->NearTeleportTo(_homePosition);
}
void EnterEvadeMode(EvadeReason /*why*/) override
@@ -2044,6 +2047,7 @@ private:
KarazhanChessOrientationType _currentOrientation;
bool _teamControlledByRaid;
Position _homePosition;
};
struct npc_chess_move_trigger : public ScriptedAI
@@ -271,9 +271,6 @@ public:
piece->RemoveAllAuras();
piece->setDeathState(DeathState::JustRespawned);
piece->SetHealth(piece->GetMaxHealth());
float x, y, z, o;
piece->GetHomePosition(x, y, z, o);
piece->NearTeleportTo(x, y, z, o);
piece->AI()->DoAction(ACTION_CHESS_PIECE_RESET_ORIENTATION);
piece->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
piece->AI()->Reset();
@@ -161,13 +161,13 @@ struct boss_zuljin : public BossAI
Talk(SAY_AGGRO, 37s);
// Phase 1: Default (troll)
ScheduleTimedEvent(7s, [&] {
ScheduleTimedEvent(12s, 29s, [&] {
DoCastAOE(SPELL_WHIRLWIND);
}, 15s, 20s);
}, 12s, 29s);
ScheduleTimedEvent(8s, [&] {
ScheduleTimedEvent(7s, 23s, [&] {
DoCastRandomTarget(SPELL_GRIEVOUS_THROW, 0, 100.0f);
}, 10s);
}, 7s, 23s);
me->m_Events.AddEventAtOffset([&]() {
DoCastSelf(SPELL_BERSERK, true);
@@ -177,9 +177,9 @@ struct boss_zuljin : public BossAI
// Phase 2: Bear Form.
ScheduleHealthCheckEvent({ 80 }, [&] {
EnterPhase(PHASE_BEAR);
ScheduleTimedEvent(7s, [&] {
ScheduleTimedEvent(8s, [&] {
DoCastAOE(SPELL_CREEPING_PARALYSIS);
}, 20s);
}, 26s, 30s);
ScheduleTimedEvent(1s, [&] {
if (!me->HasSpellCooldown(SPELL_OVERPOWER) && me->GetVictim() && me->GetComboPoints())
@@ -229,17 +229,17 @@ struct boss_zuljin : public BossAI
me->m_Events.CancelEventGroup(GROUP_LYNX);
EnterPhase(PHASE_DRAGONHAWK);
ScheduleTimedEvent(5s, [&] {
ScheduleTimedEvent(12s, 26s, [&] {
DoCastSelf(SPELL_FLAME_WHIRL);
}, 12s);
}, 12s, 26s);
ScheduleTimedEvent(6s, [&] {
ScheduleTimedEvent(11s, 42s, [&] {
DoCastRandomTarget(SPELL_SUMMON_PILLAR);
}, 10s);
}, 5s, 25s);
ScheduleTimedEvent(7s, [&] {
ScheduleTimedEvent(16s, 26s, [&] {
DoCastAOE(SPELL_FLAME_BREATH);
}, 10s);
}, 6s, 25s);
});
}
@@ -49,11 +49,15 @@ Position const HarrisonJonesLoc = {120.687f, 1674.0f, 42.0217f, 1.59044f};
DoorData const doorData[] =
{
{ GO_ZULJIN_FIREWALL, DATA_ZULJIN, DOOR_TYPE_ROOM },
{ GO_DOOR_HALAZZI, DATA_HALAZZI, DOOR_TYPE_PASSAGE },
{ GO_LYNX_TEMPLE_ENTRANCE, DATA_HALAZZI, DOOR_TYPE_ROOM },
{ GO_DOOR_AKILZON, DATA_AKILZON, DOOR_TYPE_ROOM },
{ 0, 0, DOOR_TYPE_ROOM } // END
{ GO_ZULJIN_FIREWALL, DATA_ZULJIN, DOOR_TYPE_ROOM },
{ GO_DOOR_HALAZZI, DATA_HALAZZI, DOOR_TYPE_PASSAGE },
{ GO_LYNX_TEMPLE_ENTRANCE, DATA_HALAZZI, DOOR_TYPE_ROOM },
{ GO_DOOR_AKILZON, DATA_AKILZON, DOOR_TYPE_ROOM },
{ GO_ALTAR_TORCH_EAGLE_GOD, DATA_AKILZON, DOOR_TYPE_PASSAGE },
{ GO_ALTAR_TORCH_DRAGONHAWK_GOD, DATA_JANALAI, DOOR_TYPE_PASSAGE },
{ GO_ALTAR_TORCH_LYNX_GOD, DATA_HALAZZI, DOOR_TYPE_PASSAGE },
{ GO_ALTAR_TORCH_BEAR_GOD, DATA_NALORAKK, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
ObjectData const creatureData[] =
@@ -82,7 +86,12 @@ ObjectData const summonData[] =
BossBoundaryData const boundaries =
{
{ DATA_HEXLORD, new RectangleBoundary(80.50557f, 920.9858f, 155.88986f, 1015.27563f)}
{ DATA_AKILZON, new ZRangeBoundary(72.0f, 100.0f)},
{ DATA_HALAZZI, new RectangleBoundary(304.0f, 432.0f, 1052.0f, 1156.0f)},
{ DATA_HEXLORD, new RectangleBoundary(80.50557f, 920.9858f, 155.88986f, 1015.27563f)},
{ DATA_JANALAI, new ZRangeBoundary(16.0f, 46.0f)},
{ DATA_NALORAKK, new ZRangeBoundary(38.0f, 68.0f)},
{ DATA_ZULJIN, new ZRangeBoundary(43.0f, 73.0f)}
};
class instance_zulaman : public InstanceMapScript
@@ -103,6 +112,7 @@ public:
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
LoadSummonData(summonData);
_chestLooted = 0;
for (uint8 i = 0; i < RAND_VENDOR; ++i)
RandVendor[i] = NOT_STARTED;
@@ -200,6 +210,8 @@ public:
else if (data == DONE)
_akilzonGauntlet = DONE;
}
else if (type == DATA_CHEST_LOOTED)
++_chestLooted;
}
void StartAkilzonGauntlet()
@@ -226,8 +238,12 @@ public:
_akilzonGauntlet = NOT_STARTED;
for (ObjectGuid guid : AkilzonTrash)
if (Creature* creature = instance->GetCreature(guid))
{
if (!creature->IsAlive())
creature->Respawn();
else if (creature->GetEntry() == NPC_AMINISHI_TEMPEST)
creature->AI()->DoAction(ACTION_RESET_AKILZON_GAUNTLET);
}
if (Creature* creature = GetCreature(DATA_LOOKOUT))
if (creature->isMoving())
creature->Respawn(true);
@@ -320,6 +336,8 @@ public:
return RandVendor[1];
else if (type == TYPE_AKILZON_GAUNTLET)
return _akilzonGauntlet;
else if (type == DATA_CHEST_LOOTED)
return _chestLooted;
return 0;
}
@@ -330,6 +348,7 @@ public:
}
private:
uint16 _chestLooted;
uint32 RandVendor[RAND_VENDOR];
GuidSet AkilzonTrash;
EncounterState _akilzonGauntlet = NOT_STARTED;
@@ -290,13 +290,17 @@ public:
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
creature->GetInstanceScript()->SetData(DATA_CHEST_LOOTED, 0);
float x, y, z;
creature->GetPosition(x, y, z);
for (uint8 i = 0; i < 4; ++i)
{
if (HostageEntry[i] == creature->GetEntry())
{
creature->SummonGameObject(ChestEntry[i], x - 2, y, z, 0, 0, 0, 0, 0, 0);
GameObject* obj = creature->SummonGameObject(ChestEntry[i], x - 2, y, z, 0, 0, 0, 0, 0, 0);
if (obj)
obj->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
break;
}
}
@@ -586,7 +590,6 @@ private:
enum AmanishiTempest
{
ACTION_START_GAUNTLET = 1,
GROUP_AKILZON_GAUNTLET = 1,
SPELL_SUMMON_EAGLE = 43487,
SPELL_SUMMON_WARRIOR = 43486,
@@ -601,6 +604,11 @@ struct npc_amanishi_tempest : public ScriptedAI
{
_summons.DespawnAll();
scheduler.CancelAll();
}
void JustEngagedWith(Unit* /*who*/) override
{
scheduler.CancelGroup(GROUP_AKILZON_GAUNTLET);
scheduler.Schedule(9s, 11s, [this](TaskContext context)
{
DoCastVictim(SPELL_THUNDERCLAP);
@@ -623,8 +631,15 @@ struct npc_amanishi_tempest : public ScriptedAI
void DoAction(int32 action) override
{
if (action == ACTION_START_GAUNTLET)
if (action == ACTION_START_AKILZON_GAUNTLET)
ScheduleEvents();
else if (action == ACTION_RESET_AKILZON_GAUNTLET)
Reset();
}
void SummonedCreatureEvade(Creature* /*summon*/) override
{
EnterEvadeMode(EVADE_REASON_OTHER);
}
void EnterEvadeMode(EvadeReason why) override
@@ -635,7 +650,6 @@ struct npc_amanishi_tempest : public ScriptedAI
void ScheduleEvents()
{
me->SetInCombatWithZone();
scheduler.Schedule(29s, 53s, GROUP_AKILZON_GAUNTLET, [this](TaskContext context)
{
for (uint8 i = 0; i < 5; ++i)
@@ -652,11 +666,6 @@ struct npc_amanishi_tempest : public ScriptedAI
void UpdateAI(uint32 diff) override
{
scheduler.Update(diff);
if (!me->IsEngaged())
return;
Unit* victim = me->SelectVictim();
if (!victim || me->GetExactDist(victim) > me->GetAggroRange(victim))
return;
ScriptedAI::UpdateAI(diff);
}
@@ -665,26 +674,6 @@ private:
SummonList _summons;
};
struct npc_eagle_trash_aggro_trigger : public ScriptedAI
{
npc_eagle_trash_aggro_trigger(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) {}
void MoveInLineOfSight(Unit* who) override
{
if (!me->IsWithinDist(who, 10.0f, false)) // distance not confirmed
return;
Player* player = who->GetCharmerOrOwnerPlayerOrPlayerItself();
if (!player || player->IsGameMaster())
return;
if (_instance->GetData(TYPE_AKILZON_GAUNTLET) == NOT_STARTED)
_instance->SetData(TYPE_AKILZON_GAUNTLET, IN_PROGRESS);
}
private:
InstanceScript* _instance;
};
void AddSC_zulaman()
{
RegisterZulAmanCreatureAI(npc_forest_frog);
@@ -693,5 +682,4 @@ void AddSC_zulaman()
RegisterSpellScript(spell_ritual_of_power);
RegisterZulAmanCreatureAI(npc_amanishi_lookout);
RegisterZulAmanCreatureAI(npc_amanishi_tempest);
RegisterZulAmanCreatureAI(npc_eagle_trash_aggro_trigger);
}
@@ -41,7 +41,8 @@ enum DataTypes
DATA_HARRISON_JONES = 13,
TYPE_AKILZON_GAUNTLET = 14,
DATA_LOOKOUT = 15,
DATA_ZULJIN_GATE = 16
DATA_ZULJIN_GATE = 16,
DATA_CHEST_LOOTED = 17 // Used for hostage loot DB conditions
};
enum CreatureIds
@@ -79,7 +80,11 @@ enum GameobjectIds
GO_TANZARS_TRUNK = 186648,
GO_ASHLIS_BAG = 186672,
GO_KRAZS_PACKAGE = 186667,
GO_STRANGE_GONG = 187359
GO_STRANGE_GONG = 187359,
GO_ALTAR_TORCH_EAGLE_GOD = 187035,
GO_ALTAR_TORCH_DRAGONHAWK_GOD = 187036,
GO_ALTAR_TORCH_LYNX_GOD = 187037,
GO_ALTAR_TORCH_BEAR_GOD = 186860
};
enum MiscIds
@@ -87,6 +92,7 @@ enum MiscIds
DATA_TIMED_RUN = 0,
ACTION_START_TIMED_RUN = 0,
ACTION_START_AKILZON_GAUNTLET = 1,
ACTION_RESET_AKILZON_GAUNTLET = 2,
GROUP_TIMED_RUN = 1
};
@@ -190,6 +190,8 @@ public:
if (creature->IsSummon() && _bossWave != TO_BE_DECIDED)
{
if (_currentWave == 0)
creature->SetDisableReputationGain(true);
DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, ++trash); // Update the instance wave count on new trash spawn
_encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe
}
@@ -447,7 +447,7 @@ class spell_mutate_explode_bug : public SpellScript
if (target->GetEntry() != NPC_QIRAJI_SCARAB && target->GetEntry() != NPC_QIRAJI_SCORPION)
return true;
if (Creature const* creature = target->ToCreature())
if (creature->HasAura(SPELL_EXPLODE_BUG) || creature->HasAura(SPELL_MUTATE_BUG))
if (creature->HasAnyAuras(SPELL_EXPLODE_BUG, SPELL_MUTATE_BUG))
return true;
return false;
@@ -473,7 +473,7 @@ public:
{
if (spell->Id == SPELL_KODO_KOMBO_ITEM)
{
if (!(caster->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) || me->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF))
if (!caster->HasAnyAuras(SPELL_KODO_KOMBO_PLAYER_BUFF, SPELL_KODO_KOMBO_DESPAWN_BUFF)
&& (me->GetEntry() == NPC_AGED_KODO || me->GetEntry() == NPC_DYING_KODO || me->GetEntry() == NPC_ANCIENT_KODO))
{
me->UpdateEntry(NPC_TAMED_KODO, nullptr, false);
@@ -494,7 +494,7 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) && creature->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF))
if (player->HasAllAuras(SPELL_KODO_KOMBO_PLAYER_BUFF, SPELL_KODO_KOMBO_DESPAWN_BUFF))
{
player->TalkedToCreature(creature->GetEntry(), ObjectGuid::Empty);
player->RemoveAurasDueToSpell(SPELL_KODO_KOMBO_PLAYER_BUFF);
@@ -63,9 +63,9 @@ public:
{
pInstance = me->GetInstanceScript();
me->SetReactState(REACT_PASSIVE);
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_RIMEFANG_GUID)))
if (Creature* rimefang = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_RIMEFANG_GUID)))
{
c->SetCanFly(true);
rimefang->SetCanFly(true);
}
}
@@ -76,28 +76,27 @@ public:
{
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
events.Reset();
if (me->HasReactState(REACT_AGGRESSIVE)) // Reset() called by EnterEvadeMode()
{
if (!pInstance)
return;
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_MARTIN_OR_GORKUN_GUID)))
{
c->AI()->DoAction(1);
c->DespawnOrUnsummon();
pInstance->SetGuidData(DATA_MARTIN_OR_GORKUN_GUID, ObjectGuid::Empty);
}
if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_RIMEFANG_GUID)))
{
c->GetMotionMaster()->Clear();
c->GetMotionMaster()->MoveIdle();
pInstance->SetData(DATA_TYRANNUS, NOT_STARTED);
}
c->RemoveAllAuras();
c->UpdatePosition(1017.3f, 168.974f, 642.926f, 5.2709f, true);
c->StopMovingOnCurrentPos();
if (Vehicle* v = c->GetVehicleKit())
v->InstallAllAccessories(false);
}
void EnterEvadeMode(EvadeReason /*why*/) override
{
if (!pInstance)
return;
if (Creature* creature = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_MARTIN_OR_GORKUN_GUID)))
{
creature->AI()->DoAction(1);
creature->DespawnOrUnsummon();
pInstance->SetGuidData(DATA_MARTIN_OR_GORKUN_GUID, ObjectGuid::Empty);
}
// Tyrannus is temporarily spawned as Rimefang's rider. If he evades, despawn Rimefang.
// Tyrannus will be respawned once Rimefang respawns.
if (Creature* rimefang = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_RIMEFANG_GUID)))
rimefang->DespawnOnEvade();
me->DespawnOrUnsummon();
}
void DoAction(int32 param) override
@@ -140,7 +139,7 @@ public:
if (TSDistCheckPos.GetExactDist(x, y, z) > 100.0f || z > TSDistCheckPos.GetPositionZ() + 20.0f || z < TSDistCheckPos.GetPositionZ() - 20.0f)
{
me->SetHealth(me->GetMaxHealth());
EnterEvadeMode();
EnterEvadeMode(EVADE_REASON_OTHER);
return;
}
}
@@ -48,6 +48,7 @@ enum Spells
SPELL_FRENZIED_BLOODTHIRST_VISUAL = 71949,
SPELL_VAMPIRIC_BITE = 71726,
SPELL_VAMPIRIC_BITE_DUMMY = 71837,
SPELL_ESSENCE_OF_BLOOD_QUEEN = 70867,
SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR = 70879,
SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_HEAL = 70872,
SPELL_FRENZIED_BLOODTHIRST = 70877,
@@ -79,25 +80,10 @@ enum Shadowmourne
SPELL_THIRST_QUENCHED = 72154,
};
#define ESSENCE_OF_BLOOD_QUEEN RAID_MODE<uint32>(70867, 71473, 71532, 71533)
#define ESSENCE_OF_BLOOD_QUEEN_PLR RAID_MODE<uint32>(70879, 71525, 71530, 71531)
#define FRENZIED_BLOODTHIRST RAID_MODE<uint32>(70877, 71474, 70877, 71474)
#define DELIRIOUS_SLASH RAID_MODE<uint32>(71623, 71624, 71625, 71626)
#define PRESENCE_OF_THE_DARKFALLEN RAID_MODE<uint32>(70994, 71962, 71963, 71964)
uint32 const vampireAuras[3][MAX_DIFFICULTY] =
{
{70867, 71473, 71532, 71533},
{70879, 71525, 71530, 71531},
{70877, 71474, 70877, 71474},
};
bool IsVampire(Unit const* unit)
{
uint8 spawnMode = unit->GetMap()->GetSpawnMode();
for (uint8 i = 0; i < 3; ++i)
if (unit->HasAura(vampireAuras[i][spawnMode]))
return true;
if (unit->HasAnyAuras(SPELL_ESSENCE_OF_BLOOD_QUEEN, SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR, SPELL_FRENZIED_BLOODTHIRST))
return true;
return false;
}
@@ -134,6 +120,31 @@ Position const centerPos = {4595.7090f, 2769.4190f, 400.6368f, 0.000000f};
Position const airPos = {4595.7090f, 2769.4190f, 422.3893f, 0.000000f};
Position const mincharPos = {4629.3711f, 2782.6089f, 424.6390f, 0.000000f};
struct VampiricBiteTargetSelector
{
public:
VampiricBiteTargetSelector(Creature* source) : _source(source) { }
bool operator()(Unit const* target) const
{
if (!target)
return false;
if (!target->IsPlayer())
return false;
if (target->HasAura(SPELL_BLOOD_MIRROR_DAMAGE))
return false;
if (IsVampire(target))
return false;
return target != _source->GetVictim();
}
private:
Creature const* _source;
};
class boss_blood_queen_lana_thel : public CreatureScript
{
public:
@@ -327,22 +338,7 @@ public:
break;
case EVENT_VAMPIRIC_BITE:
{
Player* target = nullptr;
float maxThreat = 0.0f;
const Map::PlayerList& pl = me->GetMap()->GetPlayers();
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
if (Player* p = itr->GetSource())
if (p->IsAlive() && p != me->GetVictim() && p->GetGUID() != _offtankGUID && !p->IsGameMaster() && p->GetDistance(me) < 70.0f)
{
float th = me->GetThreatMgr().getThreatWithoutTemp(p);
if (!target || th > maxThreat)
{
target = p;
maxThreat = th;
}
}
if (target)
if (Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 0, VampiricBiteTargetSelector(me)))
{
me->CastSpell(target, SPELL_VAMPIRIC_BITE, false);
me->CastSpell((Unit*)nullptr, SPELL_VAMPIRIC_BITE_DUMMY, true);
@@ -513,17 +509,17 @@ public:
void CleanAuras()
{
instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN);
instance->DoRemoveAurasDueToSpellOnPlayers(ESSENCE_OF_BLOOD_QUEEN_PLR);
instance->DoRemoveAurasDueToSpellOnPlayers(FRENZIED_BLOODTHIRST);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ESSENCE_OF_BLOOD_QUEEN);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_ESSENCE_OF_THE_BLOOD_QUEEN_PLR);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FRENZIED_BLOODTHIRST);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_FRENZIED_BLOODTHIRST_VISUAL);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_UNCONTROLLABLE_FRENZY);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DAMAGE);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_VISUAL);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BLOOD_MIRROR_DUMMY);
instance->DoRemoveAurasDueToSpellOnPlayers(DELIRIOUS_SLASH);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_DELIRIOUS_SLASH);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PACT_OF_THE_DARKFALLEN);
instance->DoRemoveAurasDueToSpellOnPlayers(PRESENCE_OF_THE_DARKFALLEN);
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PRESENCE_OF_THE_DARKFALLEN_DUMMY);
}
bool WasVampire(ObjectGuid guid)
@@ -260,7 +260,7 @@ public:
if (target->HasAura(SPELL_FROST_IMBUED_BLADE))
return false;
if (target->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_ALL) || target->HasAura(SPELL_ICE_TOMB_UNTARGETABLE) || target->HasAura(SPELL_ICE_TOMB_DAMAGE) || target->HasAura(SPELL_TANK_MARKER_AURA) || target->HasSpiritOfRedemptionAura())
if (target->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_ALL) || target->HasAnyAuras(SPELL_ICE_TOMB_UNTARGETABLE, SPELL_ICE_TOMB_DAMAGE, SPELL_TANK_MARKER_AURA) || target->HasSpiritOfRedemptionAura())
return false;
return target != _source->GetVictim();
@@ -451,7 +451,7 @@ public:
return false;
if (_source->GetExactDist(target) > 100.0f)
return false;
if (target->HasAura(SPELL_HARVEST_SOUL_VALKYR) || target->HasAura(SPELL_VALKYR_TARGET_SEARCH))
if (target->HasAnyAuras(SPELL_HARVEST_SOUL_VALKYR, SPELL_VALKYR_TARGET_SEARCH))
return false;
if (!_source->IsWithinLOSInMap(target))
return false;
@@ -603,7 +603,7 @@ public:
{
if (!unit || !unit->IsPlayer() || unit == _sourceObj || _sourceObj->GetVictim() == unit || !unit->isTargetableForAttack())
return false;
if (unit->HasAura(SPELL_PLAGUE_AVOIDANCE) || unit->HasAura(SPELL_BOSS_HITTIN_YA_AURA) || unit->HasAura(_notAura1) || unit->HasAura(_notAura2))
if (unit->HasAnyAuras(SPELL_PLAGUE_AVOIDANCE, SPELL_BOSS_HITTIN_YA_AURA, _notAura1, _notAura2))
return false;
if (!_sourceObj->IsWithinLOSInMap(unit))
return false;
@@ -1835,7 +1835,7 @@ public:
{
if (InstanceScript* instance = creature->GetInstanceScript())
if (instance->GetBossState(DATA_ROTFACE) == DONE && instance->GetBossState(DATA_FESTERGUT) == DONE && !creature->FindCurrentSpellBySpellId(SPELL_HARVEST_BLIGHT_SPECIMEN) && !creature->FindCurrentSpellBySpellId(SPELL_HARVEST_BLIGHT_SPECIMEN25))
if (player->HasAura(SPELL_ORANGE_BLIGHT_RESIDUE) && player->HasAura(SPELL_GREEN_BLIGHT_RESIDUE))
if (player->HasAllAuras(SPELL_ORANGE_BLIGHT_RESIDUE, SPELL_GREEN_BLIGHT_RESIDUE))
creature->CastSpell(creature, SPELL_HARVEST_BLIGHT_SPECIMEN, false);
return false;
}
@@ -178,7 +178,7 @@ public:
if (!UpdateVictim())
return;
if (me->HasAura(SPELL_PLANAR_SHIFT) || me->HasAura(SPELL_DRAKE_STOP_TIME))
if (me->HasAnyAuras(SPELL_PLANAR_SHIFT, SPELL_DRAKE_STOP_TIME))
return;
events.Update(diff);
@@ -1527,7 +1527,7 @@ public:
bool OnCheck(Player* player, Unit* /*target*/, uint32 /*criteria_id*/) override
{
return player && player->HasAura(SPELL_MAGE_TOASTY_FIRE_AURA) && player->HasAura(SPELL_DRUID_STARLIGHT_AREA_AURA) && player->HasAura(SPELL_SHAMAN_STORM_POWER_10);
return player && player->HasAllAuras(SPELL_MAGE_TOASTY_FIRE_AURA, SPELL_DRUID_STARLIGHT_AREA_AURA, SPELL_SHAMAN_STORM_POWER_10);
}
};
@@ -1538,7 +1538,7 @@ public:
bool OnCheck(Player* player, Unit* /*target*/, uint32 /*criteria_id*/) override
{
return player && player->HasAura(SPELL_MAGE_TOASTY_FIRE_AURA) && player->HasAura(SPELL_DRUID_STARLIGHT_AREA_AURA) && player->HasAura(SPELL_SHAMAN_STORM_POWER_25);
return player && player->HasAllAuras(SPELL_MAGE_TOASTY_FIRE_AURA, SPELL_DRUID_STARLIGHT_AREA_AURA, SPELL_SHAMAN_STORM_POWER_25);
}
};
@@ -454,8 +454,7 @@ public:
if (!player || player->IsGameMaster() || player->IsBeingTeleported() || (player->GetPositionZ() > 670 && player->GetVehicle()) ||
// If player has Disguise aura for quest A Meeting With The Magister or An Audience With The Arcanist, do not teleport it away but let it pass
player->HasAura(SPELL_SUNREAVER_DISGUISE_FEMALE) || player->HasAura(SPELL_SUNREAVER_DISGUISE_MALE) ||
player->HasAura(SPELL_SILVER_COVENANT_DISGUISE_FEMALE) || player->HasAura(SPELL_SILVER_COVENANT_DISGUISE_MALE))
player->HasAnyAuras(SPELL_SUNREAVER_DISGUISE_FEMALE, SPELL_SUNREAVER_DISGUISE_MALE, SPELL_SILVER_COVENANT_DISGUISE_FEMALE, SPELL_SILVER_COVENANT_DISGUISE_MALE))
return;
switch (me->GetEntry())
@@ -1496,7 +1496,7 @@ public:
if (!who || !who->IsPlayer() || !me->IsHostileTo(who) || !me->isInBackInMap(who, 5.0f))
return;
if (who->HasAura(SPELL_TRESPASSER_H) || who->HasAura(SPELL_TRESPASSER_A))
if (who->HasAnyAuras(SPELL_TRESPASSER_H, SPELL_TRESPASSER_A))
return;
if (who->ToPlayer()->GetTeamId() == TEAM_ALLIANCE)
@@ -26,14 +26,6 @@
#include "SpellAuraEffects.h"
#include "SpellScript.h"
DoorData const doorData[] =
{
{ GO_LADY_VASHJ_BRIDGE_CONSOLE, DATA_BRIDGE_EMERGED, DOOR_TYPE_PASSAGE },
{ GO_COILFANG_BRIDGE1, DATA_BRIDGE_EMERGED, DOOR_TYPE_PASSAGE },
{ GO_COILFANG_BRIDGE2, DATA_BRIDGE_EMERGED, DOOR_TYPE_PASSAGE },
{ GO_COILFANG_BRIDGE3, DATA_BRIDGE_EMERGED, DOOR_TYPE_PASSAGE }
};
ObjectData const creatureData[] =
{
{ NPC_LEOTHERAS_THE_BLIND, DATA_LEOTHERAS_THE_BLIND },
@@ -45,8 +37,12 @@ ObjectData const creatureData[] =
ObjectData const gameObjectData[] =
{
{ GO_STRANGE_POOL, DATA_STRANGE_POOL },
{ 0, 0 }
{ GO_STRANGE_POOL, DATA_STRANGE_POOL },
{ GO_LADY_VASHJ_BRIDGE_CONSOLE, DATA_CONSOLE },
{ GO_COILFANG_BRIDGE1, DATA_BRIDGE_PART1 },
{ GO_COILFANG_BRIDGE2, DATA_BRIDGE_PART2 },
{ GO_COILFANG_BRIDGE3, DATA_BRIDGE_PART3 },
{ 0, 0 }
};
MinionData const minionData[] =
@@ -64,6 +60,15 @@ BossBoundaryData const boundaries =
{ DATA_LADY_VASHJ, new CircleBoundary(Position(29.99f, -922.409f), 83.65f) }
};
ObjectData const summonData[] =
{
{ NPC_ENCHANTED_ELEMENTAL, DATA_LADY_VASHJ },
{ NPC_COILFANG_ELITE, DATA_LADY_VASHJ },
{ NPC_COILFANG_STRIDER, DATA_LADY_VASHJ },
{ NPC_TAINTED_ELEMENTAL, DATA_LADY_VASHJ },
{ 0, 0 }
};
class instance_serpent_shrine : public InstanceMapScript
{
public:
@@ -77,10 +82,10 @@ public:
{
SetHeaders(DataHeader);
SetBossNumber(MAX_ENCOUNTERS);
LoadDoorData(doorData);
LoadObjectData(creatureData, gameObjectData);
LoadMinionData(minionData);
LoadBossBoundaries(boundaries);
LoadSummonData(summonData);
_aliveKeepersCount = 0;
}
@@ -108,6 +113,12 @@ public:
case GO_SHIELD_GENERATOR4:
_shieldGeneratorGUID[go->GetEntry() - GO_SHIELD_GENERATOR1] = go->GetGUID();
break;
case GO_LADY_VASHJ_BRIDGE_CONSOLE:
case GO_COILFANG_BRIDGE1:
case GO_COILFANG_BRIDGE2:
case GO_COILFANG_BRIDGE3:
go->AllowSaveToDB(true);
break;
}
InstanceScript::OnGameObjectCreate(go);
@@ -125,13 +136,6 @@ public:
case NPC_CYCLONE_KARATHRESS:
creature->GetMotionMaster()->MoveRandom(50.0f);
break;
case NPC_ENCHANTED_ELEMENTAL:
case NPC_COILFANG_ELITE:
case NPC_COILFANG_STRIDER:
case NPC_TAINTED_ELEMENTAL:
if (Creature* vashj = GetCreature(DATA_LADY_VASHJ))
vashj->AI()->JustSummoned(creature);
break;
case NPC_SEER_OLUM:
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP);
creature->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
@@ -148,19 +152,11 @@ public:
{
case DATA_PLATFORM_KEEPER_RESPAWNED:
if (_aliveKeepersCount < MAX_KEEPER_COUNT)
{
++_aliveKeepersCount;
}
break;
case DATA_PLATFORM_KEEPER_DIED:
if (_aliveKeepersCount > MIN_KEEPER_COUNT)
{
--_aliveKeepersCount;
}
break;
case DATA_BRIDGE_ACTIVATED:
SetBossState(DATA_BRIDGE_EMERGED, NOT_STARTED);
SetBossState(DATA_BRIDGE_EMERGED, DONE);
break;
case DATA_ACTIVATE_SHIELD:
if (Creature* vashj = GetCreature(DATA_LADY_VASHJ))
@@ -31,17 +31,19 @@ enum DataTypes
DATA_LEOTHERAS_THE_BLIND = 2,
DATA_FATHOM_LORD_KARATHRESS = 3,
DATA_MOROGRIM_TIDEWALKER = 4,
DATA_BRIDGE_EMERGED = 5,
DATA_LADY_VASHJ = 6,
MAX_ENCOUNTERS = 7,
DATA_LADY_VASHJ = 5,
MAX_ENCOUNTERS = 6,
DATA_PLATFORM_KEEPER_RESPAWNED = 20,
DATA_PLATFORM_KEEPER_DIED = 21,
DATA_ALIVE_KEEPERS = 22,
DATA_BRIDGE_ACTIVATED = 23,
DATA_ACTIVATE_SHIELD = 24,
DATA_STRANGE_POOL = 25,
DATA_SEER_OLUM = 26
DATA_ACTIVATE_SHIELD = 23,
DATA_STRANGE_POOL = 24,
DATA_SEER_OLUM = 25,
DATA_CONSOLE = 26, // Used by the console SAI.
DATA_BRIDGE_PART1 = 27, // Used by the console SAI.
DATA_BRIDGE_PART2 = 28, // Used by the console SAI.
DATA_BRIDGE_PART3 = 29 // Used by the console SAI.
};
enum SSNPCs
@@ -91,8 +93,8 @@ enum SSSpells
enum KeeperCount
{
MIN_KEEPER_COUNT = 0,
MAX_KEEPER_COUNT = 24
MIN_KEEPER_COUNT = 0,
MAX_KEEPER_COUNT = 24
};
template <class AI, class T>
@@ -416,7 +416,7 @@ public:
bool OnGossipHello(Player* player, GameObject* /*go*/) override
{
if (player->HasAura(SPELL_MIND_EXHAUSTION) || player->HasAura(SPELL_SHADOW_GRASP))
if (player->HasAnyAuras(SPELL_MIND_EXHAUSTION, SPELL_SHADOW_GRASP))
return true;
if (Creature* trigger = player->FindNearestCreature(NPC_HELLFIRE_RAID_TRIGGER, 10.0f))
-4
View File
@@ -303,10 +303,6 @@ public:
{
CombatAI::InitializeAI();
((Minion*)me)->SetFollowAngle(rand_norm() * 2 * M_PI);
// Heroism / Bloodlust immunity
me->ApplySpellImmune(0, IMMUNITY_ID, 32182, true);
me->ApplySpellImmune(0, IMMUNITY_ID, 2825, true);
}
};
+72 -5
View File
@@ -751,8 +751,8 @@ class spell_dk_pet_scaling : public AuraScript
// Check just if owner has Ravenous Dead since it's effect is not an aura
if (AuraEffect const* rdEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0))
{
SpellInfo const* spellInfo = rdEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value
AddPct(modifier, spellInfo->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale
SpellInfo const* spellInfo = rdEff->GetSpellInfo(); // Then get the SpellProto and add the dummy effect value
AddPct(modifier, spellInfo->Effects[EFFECT_1].CalcValue()); // Ravenous Dead edits the original scale
}
// xinef: Glyph of the Ghoul
@@ -1618,7 +1618,7 @@ class spell_dk_improved_blood_presence : public AuraScript
void HandleEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if ((target->HasAura(SPELL_DK_FROST_PRESENCE) || target->HasAura(SPELL_DK_UNHOLY_PRESENCE)) && !target->HasAura(SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED))
if (target->HasAnyAuras(SPELL_DK_FROST_PRESENCE, SPELL_DK_UNHOLY_PRESENCE) && !target->HasAura(SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED))
target->CastCustomSpell(SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED, SPELLVALUE_BASE_POINT1, aurEff->GetAmount(), target, true, nullptr, aurEff);
}
@@ -1655,7 +1655,7 @@ class spell_dk_improved_frost_presence : public AuraScript
void HandleEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if ((target->HasAura(SPELL_DK_BLOOD_PRESENCE) || target->HasAura(SPELL_DK_UNHOLY_PRESENCE)) && !target->HasAura(SPELL_DK_FROST_PRESENCE_TRIGGERED))
if (target->HasAnyAuras(SPELL_DK_BLOOD_PRESENCE, SPELL_DK_UNHOLY_PRESENCE) && !target->HasAura(SPELL_DK_FROST_PRESENCE_TRIGGERED))
target->CastCustomSpell(SPELL_DK_FROST_PRESENCE_TRIGGERED, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), target, true, nullptr, aurEff);
}
@@ -1700,7 +1700,7 @@ class spell_dk_improved_unholy_presence : public AuraScript
target->CastCustomSpell(target, SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED, &basePoints, &basePoints, &basePoints, true, nullptr, aurEff);
}
if ((target->HasAura(SPELL_DK_BLOOD_PRESENCE) || target->HasAura(SPELL_DK_FROST_PRESENCE)) && !target->HasAura(SPELL_DK_UNHOLY_PRESENCE_TRIGGERED))
if (target->HasAnyAuras(SPELL_DK_BLOOD_PRESENCE, SPELL_DK_FROST_PRESENCE) && !target->HasAura(SPELL_DK_UNHOLY_PRESENCE_TRIGGERED))
target->CastCustomSpell(SPELL_DK_UNHOLY_PRESENCE_TRIGGERED, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), target, true, nullptr, aurEff);
}
@@ -2203,6 +2203,72 @@ class spell_dk_will_of_the_necropolis : public AuraScript
}
};
// 49040 - Army of the Dead Passive
class spell_dk_army_of_the_dead_passive : public AuraScript
{
PrepareAuraScript(spell_dk_army_of_the_dead_passive);
void CalculateAPAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
// army ghoul inherits 6.5% of AP
if (Unit* owner = GetUnitOwner()->GetOwner())
amount = CalculatePct(std::max<int32>(0, owner->GetTotalAttackPowerValue(BASE_ATTACK)), 6.5f);
}
void CalculateHealthAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
// army ghoul inherits 20% of health
if (Unit* owner = GetUnitOwner()->GetOwner())
amount = owner->CountPctFromMaxHealth(20);
}
void CalculateSPAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
// army ghoul inherits 6.5% of AP
if (Unit* owner = GetUnitOwner()->GetOwner())
amount = CalculatePct(std::max<int32>(0, owner->GetTotalAttackPowerValue(BASE_ATTACK)), 6.5f);
}
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetUnitOwner()->IsPet())
return;
GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_STAT, true, SPELL_BLOCK_TYPE_POSITIVE);
GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, true, SPELL_BLOCK_TYPE_POSITIVE);
GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_ATTACK_POWER, true, SPELL_BLOCK_TYPE_POSITIVE);
GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_ATTACK_POWER_PCT, true, SPELL_BLOCK_TYPE_POSITIVE);
// Heroism / Bloodlust immunity
GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ID, 32182, true);
GetUnitOwner()->ApplySpellImmune(0, IMMUNITY_ID, 2825, true);
}
void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
{
if (!GetUnitOwner()->IsPet())
return;
isPeriodic = true;
amplitude = 2 * IN_MILLISECONDS;
}
void HandlePeriodic(AuraEffect const* aurEff)
{
PreventDefaultAction();
GetEffect(aurEff->GetEffIndex())->RecalculateAmount();
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_army_of_the_dead_passive::CalculateAPAmount, EFFECT_0, SPELL_AURA_MOD_ATTACK_POWER);
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_army_of_the_dead_passive::CalculateHealthAmount, EFFECT_1, SPELL_AURA_MOD_INCREASE_HEALTH);
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_dk_army_of_the_dead_passive::CalculateSPAmount, EFFECT_2, SPELL_AURA_MOD_DAMAGE_DONE);
OnEffectApply += AuraEffectApplyFn(spell_dk_army_of_the_dead_passive::HandleEffectApply, EFFECT_ALL, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL);
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_dk_army_of_the_dead_passive::CalcPeriodic, EFFECT_ALL, SPELL_AURA_ANY);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_dk_army_of_the_dead_passive::HandlePeriodic, EFFECT_ALL, SPELL_AURA_ANY);
}
};
void AddSC_deathknight_spell_scripts()
{
RegisterSpellScript(spell_dk_wandering_plague);
@@ -2250,4 +2316,5 @@ void AddSC_deathknight_spell_scripts()
RegisterSpellScript(spell_dk_vampiric_blood);
RegisterSpellScript(spell_dk_will_of_the_necropolis);
RegisterSpellScript(spell_dk_ghoul_thrash);
RegisterSpellScript(spell_dk_army_of_the_dead_passive);
}
@@ -5320,6 +5320,65 @@ class spell_gen_set_health : public SpellScript
}
};
// 67561 - Serverside - Pet Scaling - Master Spell 06 - Spell Hit, Expertise, Spell Penetration
class spell_pet_spellhit_expertise_spellpen_scaling : public AuraScript
{
PrepareAuraScript(spell_pet_spellhit_expertise_spellpen_scaling)
int32 CalculatePercent(float hitChance, float cap, float maxChance)
{
return (hitChance / cap) * maxChance;
}
void CalculateSpellHitAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
amount = CalculatePercent(modOwner->m_modMeleeHitChance, 8.0f, 17.0f);
}
void CalculateExpertiseAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
amount = CalculatePercent(modOwner->m_modMeleeHitChance, 8.0f, 26.0f);
}
void CalculateSpellPenAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (Player* modOwner = GetUnitOwner()->GetSpellModOwner())
amount = modOwner->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_SPELL);
}
void HandleEffectApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
GetUnitOwner()->ApplySpellImmune(GetId(), IMMUNITY_STATE, aurEff->GetAuraType(), true, SPELL_BLOCK_TYPE_POSITIVE);
}
void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
{
if (!GetUnitOwner()->IsPet())
return;
isPeriodic = true;
amplitude = 3 * IN_MILLISECONDS;
}
void HandlePeriodic(AuraEffect const* aurEff)
{
PreventDefaultAction();
GetEffect(aurEff->GetEffIndex())->RecalculateAmount();
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pet_spellhit_expertise_spellpen_scaling::CalculateSpellHitAmount, EFFECT_0, SPELL_AURA_MOD_SPELL_HIT_CHANCE);
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pet_spellhit_expertise_spellpen_scaling::CalculateExpertiseAmount, EFFECT_1, SPELL_AURA_MOD_EXPERTISE);
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pet_spellhit_expertise_spellpen_scaling::CalculateSpellPenAmount, EFFECT_2, SPELL_AURA_MOD_TARGET_RESISTANCE);
OnEffectApply += AuraEffectApplyFn(spell_pet_spellhit_expertise_spellpen_scaling::HandleEffectApply, EFFECT_ALL, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL);
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_pet_spellhit_expertise_spellpen_scaling::CalcPeriodic, EFFECT_ALL, SPELL_AURA_ANY);
OnEffectPeriodic += AuraEffectPeriodicFn(spell_pet_spellhit_expertise_spellpen_scaling::HandlePeriodic, EFFECT_ALL, SPELL_AURA_ANY);
}
};
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_silithyst);
@@ -5478,4 +5537,5 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_sober_up);
RegisterSpellScript(spell_gen_steal_weapon);
RegisterSpellScript(spell_gen_set_health);
RegisterSpellScript(spell_pet_spellhit_expertise_spellpen_scaling);
}
+1 -1
View File
@@ -969,7 +969,7 @@ class spell_pal_lay_on_hands : public SpellScript
Unit* caster = GetCaster();
if (Unit* target = GetExplTargetUnit())
if (caster == target)
if (target->HasAura(SPELL_PALADIN_FORBEARANCE) || target->HasAura(SPELL_PALADIN_AVENGING_WRATH_MARKER) || target->HasAura(SPELL_PALADIN_IMMUNE_SHIELD_MARKER))
if (target->HasAnyAuras(SPELL_PALADIN_FORBEARANCE, SPELL_PALADIN_AVENGING_WRATH_MARKER, SPELL_PALADIN_IMMUNE_SHIELD_MARKER))
return SPELL_FAILED_TARGET_AURASTATE;
// Xinef: Glyph of Divinity
@@ -267,7 +267,7 @@ class achievement_flirt_with_disaster_perf_check : public AchievementCriteriaScr
if (!player)
return false;
if (player->HasAura(AURA_PERFUME_FOREVER) || player->HasAura(AURA_PERFUME_ENCHANTRESS) || player->HasAura(AURA_PERFUME_VICTORY))
if (player->HasAnyAuras(AURA_PERFUME_FOREVER, AURA_PERFUME_ENCHANTRESS, AURA_PERFUME_VICTORY))
return true;
return false;
@@ -774,7 +774,7 @@ public:
{
// return those not tagged or already under the influence of Aura of Nature
if (Unit* unit = object->ToUnit())
return !(unit->HasAura(SPELL_MARK_OF_NATURE) && !unit->HasAura(SPELL_AURA_OF_NATURE));
return !unit->HasAllAuras(SPELL_MARK_OF_NATURE, SPELL_AURA_OF_NATURE);
return true;
}
};
@@ -999,14 +999,10 @@ public:
void SpellHit(Unit* /*Caster*/, SpellInfo const* Spell) override
{
if (InNormalForm())
{
return;
}
if (me->HasAura(NELSON_SPELL_SOUL_FLAME) && me->HasAura(NELSON_WEAKNESS_FROST_TRAP))
{
if (me->HasAllAuras(NELSON_SPELL_SOUL_FLAME, NELSON_WEAKNESS_FROST_TRAP))
me->RemoveAura(NELSON_SPELL_SOUL_FLAME);
}
if (!me->HasAura(NELSON_SPELL_CRIPPLING_CLIP) && Spell->Id == NELSON_WEAKNESS_WING_CLIP)
{