diff options
34 files changed, 232 insertions, 196 deletions
diff --git a/sql/updates/world/master/2019_07_16_03_world_2017_02_05_00_world.sql b/sql/updates/world/master/2019_07_16_03_world_2017_02_05_00_world.sql new file mode 100644 index 00000000000..bc4e3f60759 --- /dev/null +++ b/sql/updates/world/master/2019_07_16_03_world_2017_02_05_00_world.sql @@ -0,0 +1,13 @@ + +-- Franclorn Forgewright +SET @ENTRY := 8888; +UPDATE `creature_template` SET `npcflag`=`npcflag`&~0x8000 WHERE `entry`=@ENTRY; + +-- Gaeriyan +SET @ENTRY := 9299; +UPDATE `creature_template` SET `npcflag`=`npcflag`&~0x8000 WHERE `entry`=@ENTRY; +UPDATE `creature_template_addon` SET `auras`='10848' WHERE `entry`=@ENTRY; + +-- Shroud of Death Spell +DELETE FROM `spell_script_names` WHERE spell_id=10848; +INSERT INTO `spell_script_names` VALUES(10848, 'spell_gen_shroud_of_death'); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index f8305dbffdf..debf8f3b817 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -178,7 +178,8 @@ _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_cannotReachTarget(false), m_cannotReachTimer(0), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), -m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0), m_shouldReacquireTarget(false), m_suppressedOrientation(0.0f) +m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0), m_shouldReacquireTarget(false), m_suppressedOrientation(0.0f), +_lastDamagedTime(0) { m_regenTimer = CREATURE_REGEN_INTERVAL; @@ -244,12 +245,7 @@ void Creature::RemoveFromWorld() void Creature::DisappearAndDie() { - DestroyForNearbyPlayers(); - //SetVisibility(VISIBILITY_OFF); - //ObjectAccessor::UpdateObjectVisibility(this); - if (IsAlive()) - setDeathState(JUST_DIED); - RemoveCorpse(false); + ForcedDespawn(0); } void Creature::SearchFormation() @@ -266,7 +262,7 @@ void Creature::SearchFormation() sFormationMgr->AddCreatureToGroup(frmdata->second->leaderGUID, this); } -void Creature::RemoveCorpse(bool setSpawnTime) +void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers) { if (getDeathState() != CORPSE) return; @@ -280,6 +276,9 @@ void Creature::RemoveCorpse(bool setSpawnTime) if (IsAIEnabled) AI()->CorpseRemoved(respawnDelay); + if (destroyForNearbyPlayers) + DestroyForNearbyPlayers(); + // Should get removed later, just keep "compatibility" with scripts if (setSpawnTime) m_respawnTime = std::max<time_t>(time(NULL) + respawnDelay, m_respawnTime); @@ -290,6 +289,20 @@ void Creature::RemoveCorpse(bool setSpawnTime) float x, y, z, o; GetRespawnPosition(x, y, z, &o); + + // We were spawned on transport, calculate real position + if (IsSpawnedOnTransport()) + { + Position& pos = m_movementInfo.transport.pos; + pos.m_positionX = x; + pos.m_positionY = y; + pos.m_positionZ = z; + pos.SetOrientation(o); + + if (TransportBase* transport = GetDirectTransport()) + transport->CalculatePassengerPosition(x, y, z, &o); + } + SetHomePosition(x, y, z, o); GetMap()->CreatureRelocation(this, x, y, z, o); } @@ -426,6 +439,11 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, SetNpcFlags(NPCFlags(npcFlags & 0xFFFFFFFF)); SetNpcFlags2(NPCFlags2(npcFlags >> 32)); + // if unit is in combat, keep this flag + unitFlags &= ~UNIT_FLAG_IN_COMBAT; + if (IsInCombat()) + unitFlags |= UNIT_FLAG_IN_COMBAT; + SetUnitFlags(UnitFlags(unitFlags)); SetUnitFlags2(UnitFlags2(unitFlags2)); SetUnitFlags3(UnitFlags3(unitFlags3)); @@ -434,8 +452,6 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::StateAnimID), sAnimationDataStore.GetNumRows()); - RemoveUnitFlag(UNIT_FLAG_IN_COMBAT); - SetBaseAttackTime(BASE_ATTACK, cInfo->BaseAttackTime); SetBaseAttackTime(OFF_ATTACK, cInfo->BaseAttackTime); SetBaseAttackTime(RANGED_ATTACK, cInfo->RangeAttackTime); @@ -680,13 +696,11 @@ void Creature::Update(uint32 diff) if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed RegenerateHealth(); - if (HasUnitFlag2(UNIT_FLAG2_REGENERATE_POWER)) - { - if (GetPowerType() == POWER_ENERGY) - Regenerate(POWER_ENERGY); - else - RegenerateMana(); - } + if (GetPowerType() == POWER_ENERGY) + Regenerate(POWER_ENERGY); + else + Regenerate(POWER_MANA); + m_regenTimer = CREATURE_REGEN_INTERVAL; } @@ -706,32 +720,57 @@ void Creature::Update(uint32 diff) sScriptMgr->OnCreatureUpdate(this, diff); } -void Creature::RegenerateMana() +void Creature::Regenerate(Powers power) { - uint32 curValue = GetPower(POWER_MANA); - uint32 maxValue = GetMaxPower(POWER_MANA); + uint32 curValue = GetPower(power); + uint32 maxValue = GetMaxPower(power); + + if (!HasUnitFlag2(UNIT_FLAG2_REGENERATE_POWER)) + return; if (curValue >= maxValue) return; - uint32 addvalue = 0; + float addvalue = 0.0f; - // Combat and any controlled creature - if (IsInCombat() || !GetCharmerOrOwnerGUID().IsEmpty()) + switch (power) { - float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA); + case POWER_FOCUS: + { + // For hunter pets. + addvalue = 24 * sWorld->getRate(RATE_POWER_FOCUS); + break; + } + case POWER_ENERGY: + { + // For deathknight's ghoul. + addvalue = 20; + break; + } + case POWER_MANA: + { + // Combat and any controlled creature + if (IsInCombat() || GetCharmerOrOwnerGUID().IsEmpty()) + { + float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA); - addvalue = uint32((27.0f / 5.0f + 17.0f) * ManaIncreaseRate); + addvalue = uint32((27.0f / 5.0f + 17.0f) * ManaIncreaseRate); + } + else + addvalue = maxValue / 3; + + break; + } + default: + return; } - else - addvalue = maxValue / 3; // Apply modifiers (if any). - addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); + addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power); - addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) * CREATURE_REGEN_INTERVAL / (5 * IN_MILLISECONDS); + addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * (IsHunterPet() ? PET_FOCUS_REGEN_INTERVAL : CREATURE_REGEN_INTERVAL) / (5 * IN_MILLISECONDS); - ModifyPower(POWER_MANA, addvalue); + ModifyPower(power, int32(addvalue)); } void Creature::RegenerateHealth() @@ -747,8 +786,8 @@ void Creature::RegenerateHealth() uint32 addvalue = 0; - // Not only pet, but any controlled creature - if (!GetCharmerOrOwnerGUID().IsEmpty()) + // Not only pet, but any controlled creature (and not polymorphed) + if (!GetCharmerOrOwnerGUID().IsEmpty() && !IsPolymorphed()) { float HealthIncreaseRate = sWorld->getRate(RATE_HEALTH); @@ -891,6 +930,10 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float return false; } + // Allow players to see those units while dead, do it here (mayby altered by addon auras) + if (cinfo->type_flags & CREATURE_TYPE_FLAG_GHOST_VISIBLE) + m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST); + if (!CreateFromProto(guidlow, entry, data, vehId)) return false; @@ -1833,7 +1876,7 @@ void Creature::Respawn(bool force) setDeathState(CORPSE); } - RemoveCorpse(false); + RemoveCorpse(false, false); if (getDeathState() == DEAD) { @@ -1891,29 +1934,21 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds const& forceRespawn return; } + // do it before killing creature + DestroyForNearbyPlayers(); + + if (IsAlive()) + setDeathState(JUST_DIED); + + bool overrideRespawnTime = true; if (forceRespawnTimer > Seconds::zero()) { - if (IsAlive()) - { - uint32 respawnDelay = m_respawnDelay; - uint32 corpseDelay = m_corpseDelay; - m_respawnDelay = forceRespawnTimer.count(); - m_corpseDelay = 0; - setDeathState(JUST_DIED); - m_respawnDelay = respawnDelay; - m_corpseDelay = corpseDelay; - } - else - { - m_corpseRemoveTime = time(NULL); - m_respawnTime = time(NULL) + forceRespawnTimer.count(); - } + SetRespawnTime(forceRespawnTimer.count()); + overrideRespawnTime = false; } - else - if (IsAlive()) - setDeathState(JUST_DIED); - RemoveCorpse(false); + // Skip corpse decay time + RemoveCorpse(overrideRespawnTime, false); } void Creature::DespawnOrUnsummon(uint32 msTimeToDespawn /*= 0*/, Seconds const& forceRespawnTimer /*= 0*/) @@ -2198,6 +2233,14 @@ bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction / if (!IsAlive()) return false; + // we cannot assist in evade mode + if (IsInEvadeMode()) + return false; + + // or if enemy is in evade mode + if (enemy->GetTypeId() == TYPEID_UNIT && enemy->ToCreature()->IsInEvadeMode()) + return false; + // we don't need help from non-combatant ;) if (IsCivilian()) return false; @@ -2291,21 +2334,40 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const if (IsAIEnabled && !AI()->CanAIAttack(victim)) return false; - if (GetMap()->IsDungeon()) - return true; + // we cannot attack in evade mode + if (IsInEvadeMode()) + return false; + + // or if enemy is in evade mode + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) + return false; - // if the mob is actively being damaged, do not reset due to distance unless it's a world boss - if (!isWorldBoss()) - if (time(NULL) - GetLastDamagedTime() <= MAX_AGGRO_RESET_TIME) + if (!GetCharmerOrOwnerGUID().IsPlayer()) + { + if (GetMap()->IsDungeon()) + return true; + + // don't check distance to home position if recently damaged, this should include taunt auras + if (!isWorldBoss() && (GetLastDamagedTime() > sWorld->GetGameTime() || HasAuraType(SPELL_AURA_MOD_TAUNT))) return true; + } - //Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick. - float dist = std::max(GetAttackDistance(victim), sWorld->getFloatConfig(CONFIG_THREAT_RADIUS)) + m_CombatDistance; + // Map visibility range, but no more than 2*cell size + float dist = std::min<float>(GetMap()->GetVisibilityRange(), SIZE_OF_GRID_CELL * 2); if (Unit* unit = GetCharmerOrOwner()) return victim->IsWithinDist(unit, dist); else - return victim->IsInDist(&m_homePosition, dist); + { + // include sizes for huge npcs + dist += GetObjectSize() + victim->GetObjectSize(); + + // to prevent creatures in air ignore attacks because distance is already too high... + if (GetCreatureTemplate()->InhabitType & INHABIT_AIR) + return victim->IsInDist2d(&m_homePosition, dist); + else + return victim->IsInDist(&m_homePosition, dist); + } } CreatureAddon const* Creature::GetCreatureAddon() const @@ -2468,6 +2530,7 @@ time_t Creature::GetRespawnTimeEx() const void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, float* dist) const { + // for npcs on transport, this will return transport offset if (m_spawnId) { if (CreatureData const* data = sObjectMgr->GetCreatureData(GetSpawnId())) @@ -2484,11 +2547,13 @@ void Creature::GetRespawnPosition(float &x, float &y, float &z, float* ori, floa } } - x = GetPositionX(); - y = GetPositionY(); - z = GetPositionZ(); + // changed this from current position to home position, fixes world summons with infinite duration (wg npcs for example) + Position homePos = GetHomePosition(); + x = homePos.GetPositionX(); + y = homePos.GetPositionY(); + z = homePos.GetPositionZ(); if (ori) - *ori = GetOrientation(); + *ori = homePos.GetOrientation(); if (dist) *dist = 0; } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 5d48cfa529b..c90081536c0 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -88,7 +88,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma ObjectGuid::LowType GetSpawnId() const { return m_spawnId; } void Update(uint32 time) override; // overwrited Unit::Update - void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist =nullptr) const; + void GetRespawnPosition(float &x, float &y, float &z, float* ori = nullptr, float* dist = nullptr) const; + bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->mapid != GetMapId(); } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } uint32 GetCorpseDelay() const { return m_corpseDelay; } @@ -240,7 +241,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; } void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; } - void RemoveCorpse(bool setSpawnTime = true); + void RemoveCorpse(bool setSpawnTime = true, bool destroyForNearbyPlayers = true); void DespawnOrUnsummon(uint32 msTimeToDespawn = 0, Seconds const& forceRespawnTime = Seconds(0)); void DespawnOrUnsummon(Milliseconds const& time, Seconds const& forceRespawnTime = Seconds(0)) { DespawnOrUnsummon(uint32(time.count()), forceRespawnTime); } @@ -334,6 +335,10 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool IsFocusing(Spell const* focusSpell = nullptr, bool withDelay = false); void ReleaseFocus(Spell const* focusSpell = nullptr, bool withDelay = true); + // Part of Evade mechanics + time_t GetLastDamagedTime() const { return _lastDamagedTime; } + void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; } + CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup); void SetTextRepeatId(uint8 textGroup, uint8 id); void ClearTextRepeatGroup(uint8 textGroup); @@ -365,7 +370,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma uint32 m_combatPulseDelay; // (secs) how often the creature puts the entire zone in combat (only works in dungeons) ReactStates m_reactState; // for AI, not charmInfo - void RegenerateMana(); void RegenerateHealth(); void Regenerate(Powers power); MovementGeneratorType m_defaultMovementType; @@ -415,6 +419,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma ObjectGuid m_suppressedTarget; // Stores the creature's "real" target while casting float m_suppressedOrientation; // Stores the creature's "real" orientation while casting + time_t _lastDamagedTime; // Part of Evade mechanics CreatureTextRepeatGroup m_textRepeat; }; diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 01c19a2e8d1..bea8ce9fb62 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -286,6 +286,7 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_GUARD | CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING | CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ | CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK) const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS; +const uint32 PET_FOCUS_REGEN_INTERVAL = 4 * IN_MILLISECONDS; const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS; const uint8 MAX_KILL_CREDIT = 2; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index b45e1e14e34..1c28a62351c 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -633,42 +633,6 @@ void Pet::Update(uint32 diff) Creature::Update(diff); } -void Creature::Regenerate(Powers power) -{ - uint32 curValue = GetPower(power); - uint32 maxValue = GetMaxPower(power); - - if (curValue >= maxValue) - return; - - float addvalue = 0.0f; - - switch (power) - { - case POWER_FOCUS: - { - // For hunter pets. - addvalue = 24 * sWorld->getRate(RATE_POWER_FOCUS); - break; - } - case POWER_ENERGY: - { - // For deathknight's ghoul. - addvalue = 20; - break; - } - default: - return; - } - - // Apply modifiers (if any). - addvalue *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, power); - - addvalue += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, power) * (IsHunterPet() ? PET_FOCUS_REGEN_INTERVAL : CREATURE_REGEN_INTERVAL) / (5 * IN_MILLISECONDS); - - ModifyPower(power, int32(addvalue)); -} - void Pet::Remove(PetSaveMode mode, bool returnreagent) { GetOwner()->RemovePet(this, mode, returnreagent); diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index a618a26362c..0ee1e732d6b 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -22,7 +22,6 @@ #include "PetDefines.h" #include "TemporarySummon.h" -#define PET_FOCUS_REGEN_INTERVAL 4 * IN_MILLISECONDS #define HAPPINESS_LEVEL_SIZE 333000 struct PetSpell diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 92d427e083a..55b3e88c34f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -291,7 +291,7 @@ Unit::Unit(bool isWorldObject) : m_removedAurasCount(0), i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_ThreatManager(this), m_vehicle(NULL), m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this), _aiAnimKitId(0), _movementAnimKitId(0), _meleeAnimKitId(0), - _lastDamagedTime(0), _spellHistory(new SpellHistory(this)) + _spellHistory(new SpellHistory(this)) { m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; @@ -877,13 +877,16 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam victim->ModifyHealth(-(int32)damage); if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE) - { victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0); - victim->UpdateLastDamagedTime(spellProto); - } if (victim->GetTypeId() != TYPEID_PLAYER) + { + // Part of Evade mechanics. DoT's and Thorns / Retribution Aura do not contribute to this + if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(GetMap()->GetDifficultyID(), SPELL_AURA_DAMAGE_SHIELD))) + victim->ToCreature()->SetLastDamagedTime(sWorld->GetGameTime() + MAX_AGGRO_RESET_TIME); + victim->AddThreat(this, float(damage), damageSchoolMask, spellProto); + } else // victim is a player { // random durability for items (HIT TAKEN) @@ -13914,17 +13917,6 @@ int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEf return val; } -void Unit::UpdateLastDamagedTime(SpellInfo const* spellProto) -{ - if (GetTypeId() != TYPEID_UNIT || IsPet()) - return; - - if (spellProto && spellProto->HasAura(DIFFICULTY_NONE, SPELL_AURA_DAMAGE_SHIELD)) - return; - - SetLastDamagedTime(time(NULL)); -} - bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/) { for (AuraEffect* aurEff : aura->GetAuraEffects()) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 441ad05493a..50013a0797d 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1991,11 +1991,6 @@ class TC_GAME_API Unit : public WorldObject // Movement info Movement::MoveSpline * movespline; - // Part of Evade mechanics - time_t GetLastDamagedTime() const { return _lastDamagedTime; } - void UpdateLastDamagedTime(SpellInfo const* spellProto); - void SetLastDamagedTime(time_t val) { _lastDamagedTime = val; } - int32 GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool checkMiscValue = false, int32 miscValue = 0) const; bool IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications = false); @@ -2146,8 +2141,6 @@ class TC_GAME_API Unit : public WorldObject uint16 _movementAnimKitId; uint16 _meleeAnimKitId; - time_t _lastDamagedTime; // Part of Evade mechanics - SpellHistory* _spellHistory; }; diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index e756f48f7ac..ea9ead98121 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -168,7 +168,8 @@ void WorldSession::HandleGossipHelloOpcode(WorldPackets::NPC::Hello& packet) //if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard()) + // and if he has pure gossip or is banker and moves or is tabard designer? + //if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard()) unit->StopMoving(); // If spiritguide, no need for gossip menu, just put player into resurrect queue diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp index 959aaf123f7..ff7a37c1d97 100644 --- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp +++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp @@ -172,7 +172,7 @@ bool OPvPCapturePoint::DelCreature(uint32 type) ++itr; // Don't save respawn time c->SetRespawnTime(0); - c->RemoveCorpse(); + c->DespawnOrUnsummon(); c->AddObjectToRemoveList(); } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index bf676378083..c74da190086 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -2943,7 +2943,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m { target->Kill(caster); if (caster->GetTypeId() == TYPEID_UNIT) - caster->ToCreature()->RemoveCorpse(); + caster->ToCreature()->DespawnOrUnsummon(); } if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT)) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index d98889232c4..937578b6ccd 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3188,10 +3188,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) { caster->RewardPlayerAndGroupAtEvent(18388, unitTarget); if (Creature* target = unitTarget->ToCreature()) - { - target->setDeathState(CORPSE); - target->RemoveCorpse(); - } + target->DespawnOrUnsummon(); } break; // Mug Transformation diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index 37484bba405..9ae7ddd02b1 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -98,8 +98,7 @@ public: return false; } - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); + creatureTarget->DespawnOrUnsummon(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetCreatorGUID(player->GetGUID()); diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index 13133405643..bfb8ede424c 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -196,10 +196,7 @@ public: { if (Creature* summon = ObjectAccessor::GetCreature(*me, *itr)) { - if (summon->IsAlive()) - summon->DisappearAndDie(); - else - summon->RemoveCorpse(); + summon->DespawnOrUnsummon(); } } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp index 6a431713222..faf4bca902c 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -480,8 +480,7 @@ public: } else { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } } void EnterCombat(Unit* /*who*/) override { } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index 0edada91c6b..321a4ae4299 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -499,9 +499,7 @@ public: me->SummonCreature(NPC_DEAD, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); } (*i)->SetVisible(false); - (*i)->setDeathState(JUST_DIED); - if ((*i)->getDeathState() == CORPSE) - (*i)->RemoveCorpse(); + (*i)->DespawnOrUnsummon(); } } }; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index b8e8bb91aae..9b58046036f 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -1174,8 +1174,7 @@ public: uiTimer = 5000; break; case 3: - me->KillSelf(); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); break; } } else uiTimer -=diff; diff --git a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp index 0dfb5cfe69d..ee598fff9a5 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp @@ -228,8 +228,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || target->isDead() || target->getFaction() != 14) continue; - target->setDeathState(JUST_DIED); - target->RemoveCorpse(); + target->DespawnOrUnsummon(); } // Vault Walkers @@ -238,8 +237,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || target->isDead() || target->getFaction() != 14) continue; - target->setDeathState(JUST_DIED); - target->RemoveCorpse(); + target->DespawnOrUnsummon(); } // Earthen Guardians @@ -248,8 +246,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || target->isDead() || target->getFaction() != 14) continue; - target->setDeathState(JUST_DIED); - target->RemoveCorpse(); + target->DespawnOrUnsummon(); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp index a127321c138..744a8f974ac 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -240,8 +240,7 @@ public: Creature* boss = ObjectAccessor::GetCreature(*me, AnetheronGUID); if (!boss || boss->isDead()) { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); return; } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp index fb1f8ff102b..0427de88471 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -249,8 +249,7 @@ public: Creature* boss = ObjectAccessor::GetCreature(*me, AzgalorGUID); if (!boss || boss->isDead()) { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); return; } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index 2f1fad60e10..adff04f2e0c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -577,8 +577,7 @@ public: { if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) { - me->setDeathState(DEAD); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } } } @@ -677,8 +676,7 @@ public: me->SetEmoteState(EMOTE_ONESHOT_ATTACK_UNARMED); if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) { - me->setDeathState(DEAD); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp index cd8ef1f253a..acb5b82c1b1 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -207,8 +207,7 @@ public: //if we reach this it means event was running but at some point reset. if (instance->GetData(TYPE_MEDIVH) == NOT_STARTED) { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); me->Respawn(); return; } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index e8bedc0e8c3..b44b6013666 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -128,7 +128,7 @@ class boss_skeram : public CreatureScript if (!me->IsSummon()) Talk(SAY_DEATH); else - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index 7b7f94a63f3..9dc9dd23070 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -936,7 +936,7 @@ public: void npc_qiraj_war_spawn::npc_qiraj_war_spawnAI::JustDied(Unit* /*slayer*/) { - me->RemoveCorpse(); + me->DespawnOrUnsummon(); if (!MobGUID) return; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index bf6b3cd3558..6a9dac9f620 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -276,7 +276,7 @@ struct boss_four_horsemen_baseAI : public BossAI { if (Creature* cBoss = getHorsemanHandle(boss)) { - cBoss->DespawnOrUnsummon(0); + cBoss->DespawnOrUnsummon(); cBoss->SetRespawnTime(15); } else diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 0d3ccc74685..0d36e85cdd4 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -248,7 +248,7 @@ class npc_iron_roots : public CreatureScript target->RemoveAurasDueToSpell(SPELL_ROOTS_FREYA); } - me->RemoveCorpse(false); + me->DespawnOrUnsummon(); } private: diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp index d40f46bbaaa..5617e708b10 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp @@ -172,8 +172,7 @@ public: { if (Creature* mob = ObjectAccessor::GetCreature(*me, beams[i])) { - mob->setDeathState(DEAD); - mob->RemoveCorpse(); + mob->DespawnOrUnsummon(); } } } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index 211be3d55f2..4a5c82d0c75 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -805,9 +805,9 @@ public: if (!Vashj || !Vashj->IsAlive() || ENSURE_AI(boss_lady_vashj::boss_lady_vashjAI, Vashj->ToCreature()->AI())->Phase != 3) { // remove - me->setDeathState(DEAD); - me->RemoveCorpse(); me->setFaction(35); + me->DespawnOrUnsummon(); + return; } CheckTimer = 1000; diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index c5df85fc291..51082af5744 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -179,11 +179,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript { Creature* creature = ObjectAccessor::GetCreature(*me, *itr); if (creature && creature->IsAlive()) - { - creature->GetMotionMaster()->Clear(true); - me->DealDamage(creature, creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - creature->RemoveCorpse(); - } + creature->DespawnOrUnsummon(); } adds.clear(); @@ -191,11 +187,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript { Creature* creature = ObjectAccessor::GetCreature(*me, *itr); if (creature && creature->IsAlive()) - { - creature->GetMotionMaster()->Clear(true); - me->DealDamage(creature, creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - creature->RemoveCorpse(); - } + creature->DespawnOrUnsummon(); } assassins.clear(); } diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp index 175caeb0dea..f66c90eead0 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -196,8 +196,8 @@ class npc_ragin_flames : public CreatureScript if (instance->GetData(DATA_NETHERMANCER_SEPRETHREA) != IN_PROGRESS) { //remove - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); + return; } Check_Timer = 1000; } else Check_Timer -= diff; diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp index 251954cbb73..449dc48fac4 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp @@ -232,8 +232,8 @@ class npc_nether_wraith : public CreatureScript { if (Die_Timer <= diff) { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); + return; } else Die_Timer -= diff; diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp index 0c00d733bcb..4f9f1f18da9 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -123,11 +123,7 @@ public: return; if (id == 0) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - me->SetHealth(0); - } + me->DespawnOrUnsummon(1); } void SpellHit(Unit* caster, const SpellInfo* spell) override @@ -155,7 +151,8 @@ public: EnterEvadeMode(); me->AddUnitFlag(UNIT_FLAG_NON_ATTACKABLE); IsNihil = true; - }else + } + else AttackStart(caster); } } diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 025b0ece9e4..5107eb8dac1 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -384,7 +384,6 @@ public: FlyTimer = 10000; me->SetDisableGravity(false); - me->SetVisible(true); } void SpellHit(Unit* caster, const SpellInfo* spell) override @@ -428,10 +427,8 @@ public: PlayerGUID.Clear(); } - me->SetVisible(false); - me->SetDisableGravity(false); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); + + me->DespawnOrUnsummon(1); } } @@ -1197,7 +1194,7 @@ public: void JustDied(Unit* /*killer*/) override { - me->RemoveCorpse(); + me->DespawnOrUnsummon(); if (Creature* LordIllidan = (ObjectAccessor::GetCreature(*me, LordIllidanGUID))) ENSURE_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, LordIllidan->AI())->LiveCounter(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 1defc975ab5..8e5e5e633b1 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4426,6 +4426,42 @@ class spell_gen_pony_mount_check : public SpellScriptLoader } }; +class spell_gen_shroud_of_death : public SpellScriptLoader +{ +public: + spell_gen_shroud_of_death() : SpellScriptLoader("spell_gen_shroud_of_death") { } + + class spell_gen_shroud_of_death_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_shroud_of_death_AuraScript); + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + PreventDefaultAction(); + GetUnitOwner()->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); + GetUnitOwner()->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + PreventDefaultAction(); + GetUnitOwner()->m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); + GetUnitOwner()->m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); + } + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_gen_shroud_of_death_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove += AuraEffectRemoveFn(spell_gen_shroud_of_death_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gen_shroud_of_death_AuraScript(); + } +}; + // 169869 - Transformation Sickness class spell_gen_decimatus_transformation_sickness : public SpellScriptLoader { @@ -4752,6 +4788,7 @@ void AddSC_generic_spell_scripts() new spell_gen_landmine_knockback_achievement(); new spell_gen_clear_debuffs(); new spell_gen_pony_mount_check(); + new spell_gen_shroud_of_death(); new spell_gen_decimatus_transformation_sickness(); new spell_gen_anetheron_summon_towering_infernal(); new spell_gen_mark_of_kazrogal_hellfire(); |