Merge pull request #148 from azerothcore/master

update
This commit is contained in:
bashermens
2026-01-13 00:50:29 +01:00
committed by GitHub
26 changed files with 409 additions and 181 deletions

View File

@@ -31,11 +31,14 @@ if(PLATFORM EQUAL 32)
-mfpmath=sse)
endif()
target_compile_definitions(acore-compile-option-interface
INTERFACE
-DHAVE_SSE2
-D__SSE2__)
message(STATUS "GCC: SFMT enabled, SSE2 flags forced")
if(ACORE_SYSTEM_PROCESSOR MATCHES "x86|amd64")
target_compile_definitions(acore-compile-option-interface
INTERFACE
-DHAVE_SSE2
-D__SSE2__)
message(STATUS "GCC: SFMT enabled, SSE2 flags forced")
endif()
if( WITH_WARNINGS )
target_compile_options(acore-warning-interface

View File

@@ -21,6 +21,30 @@ endif()
include("${CMAKE_SOURCE_DIR}/src/cmake/platform/settings.cmake")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64")
set(ACORE_SYSTEM_PROCESSOR "amd64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|ARM|aarch|AARCH)64$")
set(ACORE_SYSTEM_PROCESSOR "arm64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm|ARM|aarch|AARCH)$")
set(ACORE_SYSTEM_PROCESSOR "arm")
else()
set(ACORE_SYSTEM_PROCESSOR "x86")
endif()
# detect MSVC special case of using cmake -A switch (which doesn't set any cross compiling variables)
if(CMAKE_GENERATOR_PLATFORM STREQUAL "Win32")
set(ACORE_SYSTEM_PROCESSOR "x86")
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "x64")
set(ACORE_SYSTEM_PROCESSOR "amd64")
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "ARM")
set(ACORE_SYSTEM_PROCESSOR "arm")
elseif(CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64")
set(ACORE_SYSTEM_PROCESSOR "arm64")
endif()
message(STATUS "Detected ${ACORE_SYSTEM_PROCESSOR} processor architecture")
if(WIN32)
include("${CMAKE_SOURCE_DIR}/src/cmake/platform/win/settings.cmake")
elseif(UNIX)

View File

@@ -227,7 +227,7 @@ elseif (MSVC)
set(_OPENSSL_MSI_INSTALL_GUIDS "")
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
if(ACORE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(_arch "Win64-ARM")
set(_OPENSSL_MSI_INSTALL_GUIDS "99C28AFA-6419-40B1-B88D-32B810BB4234")
else()
@@ -319,7 +319,7 @@ if(WIN32 AND NOT CYGWIN)
# Since OpenSSL 1.1, lib names are like libcrypto32MTd.lib and libssl32MTd.lib
if( "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8" )
set(_OPENSSL_MSVC_ARCH_SUFFIX "64")
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ARM64")
if(ACORE_SYSTEM_PROCESSOR STREQUAL "arm64")
set(_OPENSSL_MSVC_ARCH_DIRECTORY "arm64")
else()
set(_OPENSSL_MSVC_ARCH_DIRECTORY "x64")

View File

@@ -951,6 +951,14 @@ void SmartAI::InitializeAI()
if (!(event.action.cast.castFlags & SMARTCAST_MAIN_SPELL))
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(event.action.cast.spell);
if (spellInfo && spellInfo->IsPositive())
{
LOG_WARN("scripts.ai", "SmartAI: Creature {} has SMARTCAST_MAIN_SPELL on positive spell {} - positive spells should not be used as main spell",
me->GetEntry(), event.action.cast.spell);
continue;
}
SetMainSpell(event.action.cast.spell);
break;
}
@@ -966,6 +974,11 @@ void SmartAI::InitializeAI()
if (!(event.action.cast.castFlags & SMARTCAST_COMBAT_MOVE))
continue;
// Don't use positive (healing/buff) spells to determine attack distance
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(event.action.cast.spell);
if (spellInfo && spellInfo->IsPositive())
continue;
SetMainSpell(event.action.cast.spell);
break;
}

View File

@@ -6002,6 +6002,19 @@ void Player::RewardReputation(Unit* victim)
}
}
FactionTemplateEntry const* GetAnyFactionTemplateForFaction(uint32 factionId)
{
for (uint32 i = 0; i < sFactionTemplateStore.GetNumRows(); ++i)
{
if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(i))
{
if (factionTemplate->faction == factionId)
return factionTemplate;
}
}
return nullptr;
}
// Calculate how many reputation points player gain with the quest
void Player::RewardReputation(Quest const* quest)
{
@@ -6055,10 +6068,24 @@ void Player::RewardReputation(Quest const* quest)
sScriptMgr->OnPlayerGiveReputation(this, quest->RewardFactionId[i], rep, REPUTATION_SOURCE_QUEST);
}
if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(quest->RewardFactionId[i]))
FactionEntry const* factionEntry = sFactionStore.LookupEntry(quest->RewardFactionId[i]);
if (!factionEntry)
continue;
FactionTemplateEntry const* templateEntry = GetAnyFactionTemplateForFaction(factionEntry->ID);
if (templateEntry)
{
GetReputationMgr().ModifyReputation(factionEntry, rep, quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER));
bool hostile = (GetTeamId() == TEAM_ALLIANCE) ? templateEntry->IsHostileToAlliancePlayers()
: templateEntry->IsHostileToHordePlayers();
if (hostile)
{
LOG_DEBUG("sql.sql", "RewardReputation: {} is hostile with player ({}), skipping!", templateEntry->ID, GetGUID().ToString());
continue;
}
}
GetReputationMgr().ModifyReputation(factionEntry, rep, quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_NO_REP_SPILLOVER));
}
}

View File

@@ -970,6 +970,9 @@ enum PlayerRestState
{
REST_STATE_RESTED = 0x01,
REST_STATE_NOT_RAF_LINKED = 0x02,
REST_STATE_TIRED = 0x03,
REST_STATE_TIRED_XP_REDUCED = 0x04, // 50% XP
REST_STATE_EXHAUSTED = 0x05, // 25% XP
REST_STATE_RAF_LINKED = 0x06
};

View File

@@ -112,13 +112,14 @@ public:
me->SetImmuneToAll(true);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetReactState(REACT_PASSIVE);
if (InstanceScript* pInstance = me->GetInstanceScript())
if (InstanceScript* instance = me->GetInstanceScript())
{
if (Creature* cr = ObjectAccessor::GetCreature(*me, pInstance->GetGuidData(DATA_ARTHAS)))
if (Creature* cr = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ARTHAS)))
cr->AI()->DoAction(ACTION_KILLED_MALGANIS);
// give credit to players
me->CastSpell(me, 58630, true);
instance->instance->SummonGameObject(DUNGEON_MODE(GO_MALGANIS_CHEST_N, GO_MALGANIS_CHEST_H), 2288.35f, 1498.73f, 128.414f, -0.994837f, 0, 0, 0, 0, 7 * DAY * IN_MILLISECONDS);
}
// quest completion

View File

@@ -1153,8 +1153,6 @@ public:
pInstance->SetData(DATA_ARTHAS_EVENT, COS_PROGRESS_FINISHED);
if (GameObject* go = pInstance->instance->GetGameObject(pInstance->GetGuidData(DATA_EXIT_GATE)))
go->SetGoState(GO_STATE_ACTIVE);
pInstance->instance->SummonGameObject(DUNGEON_MODE(GO_MALGANIS_CHEST_N, GO_MALGANIS_CHEST_H), 2288.35f, 1498.73f, 128.414f, -0.994837f, 0, 0, 0, 0, 7 * DAY * IN_MILLISECONDS);
}
ScheduleNextEvent(currentEvent, 10s);
break;

View File

@@ -118,22 +118,41 @@ public:
void OnUnitDeath(Unit* unit) override
{
if (unit->EntryEquals(NPC_WATCHER_GASHRA, NPC_WATCHER_NARJIL, NPC_WATCHER_SILTHIK, NPC_ANUBAR_SHADOWCASTER, NPC_ANUBAR_SKIRMISHER, NPC_ANUBAR_WARRIOR))
if (!unit->EntryEquals(NPC_WATCHER_GASHRA, NPC_WATCHER_NARJIL, NPC_WATCHER_SILTHIK, NPC_ANUBAR_SHADOWCASTER, NPC_ANUBAR_SKIRMISHER, NPC_ANUBAR_WARRIOR))
return;
Creature* creature = unit->ToCreature();
if (!creature)
return;
// For trash mobs, ensure their leader is a Watcher
if (unit->EntryEquals(NPC_ANUBAR_SHADOWCASTER, NPC_ANUBAR_SKIRMISHER, NPC_ANUBAR_WARRIOR))
{
if (Creature* creature = unit->ToCreature())
{
ObjectGuid creatureGuid = creature->GetGUID();
scheduler.CancelAll();
scheduler.Schedule(1s, [this, creatureGuid](TaskContext /*context*/)
{
if (Creature* creature = instance->GetCreature(creatureGuid))
if (CreatureGroup* formation = creature->GetFormation())
if (!formation->IsAnyMemberAlive())
if (Creature* krikthir = GetCreature(DATA_KRIKTHIR))
krikthir->AI()->DoAction(ACTION_MINION_DIED);
});
}
CreatureGroup* formation = creature->GetFormation();
if (!formation)
return;
Creature* leader = formation->GetLeader();
if (!leader || !leader->EntryEquals(NPC_WATCHER_GASHRA, NPC_WATCHER_NARJIL, NPC_WATCHER_SILTHIK))
return;
}
ObjectGuid creatureGuid = creature->GetGUID();
scheduler.CancelAll();
scheduler.Schedule(1s, [this, creatureGuid](TaskContext /*context*/)
{
Creature* creature = instance->GetCreature(creatureGuid);
if (!creature)
return;
CreatureGroup* formation = creature->GetFormation();
if (!formation || formation->IsAnyMemberAlive())
return;
if (Creature* krikthir = GetCreature(DATA_KRIKTHIR))
krikthir->AI()->DoAction(ACTION_MINION_DIED);
});
}
};

View File

@@ -598,7 +598,7 @@ public:
void SetData(uint32 id, uint32 value) override
{
if (!events.HasTimeUntilEvent(EVENT_CHECK_CORPOREALITY))
if (!_events.HasTimeUntilEvent(EVENT_CHECK_CORPOREALITY))
return;
if (id == DATA_MATERIAL_DAMAGE_TAKEN)

View File

@@ -37,141 +37,126 @@ enum Spells
{
SPELL_IMPALE = 28783,
SPELL_LOCUST_SWARM = 28785,
SPELL_SUMMON_CORPSE_SCRABS_5 = 29105,
SPELL_SUMMON_CORPSE_SCRABS_10 = 28864,
SPELL_SUMMON_CORPSE_SCARABS_5 = 29105,
SPELL_SUMMON_CORPSE_SCARABS_10 = 28864,
SPELL_BERSERK = 26662
};
enum Misc
{
NPC_CORPSE_SCARAB = 16698,
NPC_CRYPT_GUARD = 16573,
ACHIEV_TIMED_START_EVENT = 9891
ACHIEV_TIMED_START_EVENT = 9891,
EVENT_SPAWN_CRYPT_GUARDS_1 = 0,
EVENT_BERSERK = 1,
EVENT_SPAWN_CRYPT_GUARDS_EXTRA = 2,
};
class boss_anubrekhan : public CreatureScript
{
public:
boss_anubrekhan() : CreatureScript("boss_anubrekhan") { }
Position const cryptguardPositions[] = {
{ 3299.732f, -3502.489f, 287.077f, 2.378f },
{ 3299.086f, -3450.929f, 287.077f, 3.999f },
{ 3331.217f, -3476.607f, 287.074f, 3.269f }
};
CreatureAI* GetAI(Creature* pCreature) const override
struct boss_anubrekhan : public BossAI
{
boss_anubrekhan(Creature* creature) : BossAI(creature, BOSS_ANUB) { }
void SummonCryptGuards()
{
return GetNaxxramasAI<boss_anubrekhanAI>(pCreature);
if (Is25ManRaid())
{
me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[1], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}
}
struct boss_anubrekhanAI : public BossAI
void Reset() override
{
boss_anubrekhanAI(Creature* c) : BossAI(c, BOSS_ANUB)
{
sayGreet = false;
}
BossAI::Reset();
SummonCryptGuards();
}
void SummonCryptGuards()
{
if (Is25ManRaid())
{
me->SummonCreature(NPC_CRYPT_GUARD, 3299.732f, -3502.489f, 287.077f, 2.378f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
me->SummonCreature(NPC_CRYPT_GUARD, 3299.086f, -3450.929f, 287.077f, 3.999f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}
}
void Reset() override
{
BossAI::Reset();
SummonCryptGuards();
me->m_Events.KillAllEvents(false);
}
void JustSummoned(Creature* cr) override
{
if (me->IsInCombat())
{
cr->SetInCombatWithZone();
if (cr->GetEntry() == NPC_CRYPT_GUARD)
cr->AI()->Talk(EMOTE_SPAWN, me);
}
summons.Summon(cr);
}
void SummonedCreatureDies(Creature* cr, Unit*) override
void JustSummoned(Creature* cr) override
{
if (me->IsInCombat())
{
cr->SetInCombatWithZone();
if (cr->GetEntry() == NPC_CRYPT_GUARD)
{
cr->CastSpell(cr, SPELL_SUMMON_CORPSE_SCRABS_10, true, nullptr, nullptr, me->GetGUID());
cr->AI()->Talk(EMOTE_SCARAB);
}
cr->AI()->Talk(EMOTE_SPAWN, me);
}
summons.Summon(cr);
}
void JustDied(Unit* killer) override
void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override
{
if (summon->GetEntry() == NPC_CRYPT_GUARD)
{
BossAI::JustDied(killer);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
summon->CastSpell(summon, SPELL_SUMMON_CORPSE_SCARABS_10, true, nullptr, nullptr, me->GetGUID());
summon->AI()->Talk(EMOTE_SCARAB);
}
}
void KilledUnit(Unit* victim) override
void JustDied(Unit* killer) override
{
BossAI::JustDied(killer);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void KilledUnit(Unit* victim) override
{
if (!victim->IsPlayer())
return;
Talk(SAY_SLAY);
victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCARABS_5, true, nullptr, nullptr, me->GetGUID());
instance->StorePersistentData(PERSISTENT_DATA_IMMORTAL_FAIL, 1);
}
void JustEngagedWith(Unit* who) override
{
BossAI::JustEngagedWith(who);
me->CallForHelp(30.0f);
Talk(SAY_AGGRO);
if (!summons.HasEntry(NPC_CRYPT_GUARD))
SummonCryptGuards();
if (!Is25ManRaid())
{
if (!victim->IsPlayer())
return;
Talk(SAY_SLAY);
victim->CastSpell(victim, SPELL_SUMMON_CORPSE_SCRABS_5, true, nullptr, nullptr, me->GetGUID());
instance->StorePersistentData(PERSISTENT_DATA_IMMORTAL_FAIL, 1);
ScheduleUniqueTimedEvent(17500ms, [&] {
me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}, EVENT_SPAWN_CRYPT_GUARDS_1);
}
void JustEngagedWith(Unit* who) override
ScheduleTimedEvent(15s, [&] {
DoCastRandomTarget(SPELL_IMPALE);
}, 20s);
ScheduleTimedEvent(70s, 2min, [&] {
Talk(EMOTE_LOCUST);
DoCastSelf(SPELL_LOCUST_SWARM);
scheduler.Schedule(3s, [this](TaskContext /*context*/) {
me->SummonCreature(NPC_CRYPT_GUARD, cryptguardPositions[2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
});
}, 90s);
ScheduleEnrageTimer(SPELL_BERSERK, 10min);
}
void MoveInLineOfSight(Unit* who) override
{
if (!_sayGreet && who->IsPlayer())
{
BossAI::JustEngagedWith(who);
me->CallForHelp(30.0f);
Talk(SAY_AGGRO);
if (!summons.HasEntry(NPC_CRYPT_GUARD))
SummonCryptGuards();
if (!Is25ManRaid())
{
me->m_Events.AddEventAtOffset([&]
{
me->SummonCreature(NPC_CRYPT_GUARD, 3331.217f, -3476.607f, 287.074f, 3.269f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}, Milliseconds(urand(15000, 20000)));
}
ScheduleTimedEvent(15s, [&] {
DoCastRandomTarget(SPELL_IMPALE);
}, 20s);
ScheduleTimedEvent(70s, 2min, [&] {
Talk(EMOTE_LOCUST);
DoCastSelf(SPELL_LOCUST_SWARM);
me->m_Events.AddEventAtOffset([&]
{
me->SummonCreature(NPC_CRYPT_GUARD, 3331.217f, -3476.607f, 287.074f, 3.269f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000);
}, 3s);
}, 90s);
me->m_Events.AddEventAtOffset([&]
{
DoCastSelf(SPELL_BERSERK, true);
}, 10min);
Talk(SAY_GREET);
_sayGreet = true;
}
BossAI::MoveInLineOfSight(who);
}
void MoveInLineOfSight(Unit* who) override
{
if (!sayGreet && who->IsPlayer())
{
Talk(SAY_GREET);
sayGreet = true;
}
ScriptedAI::MoveInLineOfSight(who);
}
private:
bool sayGreet;
};
private:
bool _sayGreet{false};
};
void AddSC_boss_anubrekhan()
{
new boss_anubrekhan();
RegisterNaxxramasCreatureAI(boss_anubrekhan);
}

View File

@@ -464,6 +464,19 @@ public:
go->SetGoState(GO_STATE_ACTIVE);
gateOpened = true;
summons.DoForAllSummons([&](WorldObject* summon)
{
if (Creature* gothikMinion = summon->ToCreature())
if (gothikMinion->IsAlive())
{
if (Unit* target = SelectTarget(SelectTargetMethod::MinDistance, 0, 200.0f))
{
gothikMinion->AI()->AttackStart(target);
gothikMinion->SetReactState(REACT_AGGRESSIVE);
gothikMinion->SetInCombatWithZone();
}
}
});
Talk(EMOTE_GATE_OPENED);
}
break;

View File

@@ -146,6 +146,9 @@ enum NaxxramasGameObjectsDisplayId
enum NaxxramasCreatureId
{
// Anub'Rekhan
NPC_CRYPT_GUARD = 16573,
// Patchwerk
NPC_PATCHWERK = 16028,
NPC_PATCHWORK_GOLEM = 16017,

View File

@@ -41,6 +41,7 @@ enum Spells
SPELL_ARCANE_MAGUS_SUMMON = 47708,
SPELL_FIRE_MAGUS_DEATH = 47711,
SPELL_FROST_MAGUS_DEATH = 47712,
SPELL_ARCANE_MAGUS_DEATH = 47713,
SPELL_WEAR_CHRISTMAS_HAT = 61400
@@ -83,13 +84,11 @@ struct boss_magus_telestra : public BossAI
{
boss_magus_telestra(Creature* creature) : BossAI(creature, DATA_MAGUS_TELESTRA_EVENT) { }
uint8 copiesDied;
bool achievement;
void Reset() override
{
BossAI::Reset();
copiesDied = 0;
achievement = true;
if (IsHeroic() && sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL) && !me->HasAura(SPELL_WEAR_CHRISTMAS_HAT))
@@ -152,9 +151,8 @@ struct boss_magus_telestra : public BossAI
events.ScheduleEvent(EVENT_MAGUS_FAIL_ACHIEVEMENT, 5s);
caster->ToCreature()->DespawnOrUnsummon(1s);
if (++copiesDied >= 3)
if (me->HasAura(SPELL_FIRE_MAGUS_DEATH) && me->HasAura(SPELL_FROST_MAGUS_DEATH) && me->HasAura(SPELL_ARCANE_MAGUS_DEATH))
{
copiesDied = 0;
events.CancelEvent(EVENT_MAGUS_FAIL_ACHIEVEMENT);
events.ScheduleEvent(EVENT_MAGUS_MERGED, 5s);
me->CastSpell(me, SPELL_BURNING_WINDS, true);
@@ -168,13 +166,14 @@ struct boss_magus_telestra : public BossAI
return;
events.Update(diff);
if (me->HasUnitState(UNIT_STATE_CASTING))
if (me->HasUnitState(UNIT_STATE_CASTING) ||
(me->HasUnitState(UNIT_STATE_STUNNED) && !me->HasAura(SPELL_START_SUMMON_CLONES))) // Reflected Ice Nova can stun her as its mechanic bypasses immunities
return;
switch (events.ExecuteEvent())
{
case EVENT_MAGUS_HEALTH1:
if (me->HealthBelowPct(51))
if (me->HealthBelowPct(51) && me->HealthAbovePct(11))
{
me->CastSpell(me, SPELL_START_SUMMON_CLONES, false);
events.ScheduleEvent(EVENT_MAGUS_RELOCATE, 3500ms);

View File

@@ -32,6 +32,11 @@ ObjectData const creatureData[] =
{ 0, 0 }
};
BossBoundaryData const boundaries =
{
{ BOSS_SJONNIR, new RectangleBoundary(1206.56f, 1341.4185f, 579.9434f, 753.9599f) }
};
class instance_halls_of_stone : public InstanceMapScript
{
public:
@@ -72,6 +77,7 @@ public:
SetBossNumber(MAX_ENCOUNTER);
LoadObjectData(creatureData, nullptr);
LoadSummonData(summonData);
LoadBossBoundaries(boundaries);
memset(&Encounter, 0, sizeof(Encounter));
brannAchievement = false;

View File

@@ -2314,6 +2314,26 @@ class spell_dk_army_of_the_dead_passive : public AuraScript
}
};
// -49182 Blade Barrier
class spell_dk_blade_barrier : public AuraScript
{
PrepareAuraScript(spell_dk_blade_barrier);
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
if (Player* player = GetCaster()->ToPlayer())
if (player->getClass() == CLASS_DEATH_KNIGHT && player->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
return true;
return false;
}
void Register() override
{
DoCheckProc += AuraCheckProcFn(spell_dk_blade_barrier::CheckProc);
}
};
void AddSC_deathknight_spell_scripts()
{
RegisterSpellScript(spell_dk_wandering_plague);
@@ -2362,4 +2382,5 @@ void AddSC_deathknight_spell_scripts()
RegisterSpellScript(spell_dk_will_of_the_necropolis);
RegisterSpellScript(spell_dk_ghoul_thrash);
RegisterSpellScript(spell_dk_army_of_the_dead_passive);
RegisterSpellScript(spell_dk_blade_barrier);
}

View File

@@ -1015,6 +1015,8 @@ struct FactionTemplateEntry
return (hostileMask & entry.ourMask) != 0;
}
[[nodiscard]] bool IsHostileToPlayers() const { return (hostileMask & FACTION_MASK_PLAYER) != 0; }
[[nodiscard]] bool IsHostileToAlliancePlayers() const { return (hostileMask & FACTION_MASK_ALLIANCE) != 0; }
[[nodiscard]] bool IsHostileToHordePlayers() const { return (hostileMask & FACTION_MASK_HORDE) != 0; }
[[nodiscard]] bool IsNeutralToAll() const
{
for (unsigned int i : enemyFaction)