From fe63cd3dbb66f4fda743858db4284a24bc2bd400 Mon Sep 17 00:00:00 2001 From: xinef1 Date: Sun, 5 Feb 2017 15:39:22 +0100 Subject: [PATCH] Core/Creatures: Various fixes for creatures, regarding combat conditions, despawning, and few others (#18998) * Made some changes to kiting mechanics, simplified code and made taunt auras prolong combat no matter the distance from the spawn Unified some creature despawning code, removed some brutal direct calls in scripts Don't play death anim on forced despawn Removed some redundant visibility changes on creature despawn Fixed possible problem with pet initializing template info from difficulty greater than normal Properly keep UNIT_FLAG_IN_COMBAT on UpdateEntry call Moved RegenerateMana function to general Regenerate(Power) function Fixed increased health regeneration from polymorph for pets Implemented CREATURE_TYPE_FLAG_GHOST_VISIBLE, those creatures will be properly seen when player is dead also Removed hackfix from Gaeriyan and Franclorn Forgewright, fixed properly Simplified ForcedRespawnTime code in ForcedDespawn Do not allow to assist unit while evading or when enemy is evading Do not allow to attack other units when evading or when the unit is evading Corrected distance checking code before creature is allowed to evade, should fix some common problems Properly return summon position for summoned creatures as their respawn position Properly stop all moving units on gossip hello, no matter their npc flags (cherrypicked from e1f14215d86fc9f0cd041f0e87bf0a689c086329) --- ...019_07_16_03_world_2017_02_05_00_world.sql | 13 ++ .../game/Entities/Creature/Creature.cpp | 195 ++++++++++++------ src/server/game/Entities/Creature/Creature.h | 11 +- .../game/Entities/Creature/CreatureData.h | 1 + src/server/game/Entities/Pet/Pet.cpp | 36 ---- src/server/game/Entities/Pet/Pet.h | 1 - src/server/game/Entities/Unit/Unit.cpp | 22 +- src/server/game/Entities/Unit/Unit.h | 7 - src/server/game/Handlers/NPCHandler.cpp | 3 +- src/server/game/OutdoorPvP/OutdoorPvP.cpp | 2 +- .../game/Spells/Auras/SpellAuraEffects.cpp | 2 +- src/server/game/Spells/SpellEffects.cpp | 5 +- src/server/scripts/Commands/cs_pet.cpp | 3 +- .../EasternKingdoms/Gnomeregan/gnomeregan.cpp | 5 +- .../EasternKingdoms/Karazhan/karazhan.cpp | 3 +- .../SunwellPlateau/boss_felmyst.cpp | 4 +- .../SunwellPlateau/boss_kiljaeden.cpp | 3 +- .../Uldaman/instance_uldaman.cpp | 9 +- .../BattleForMountHyjal/boss_anetheron.cpp | 3 +- .../BattleForMountHyjal/boss_azgalor.cpp | 3 +- .../BattleForMountHyjal/hyjal_trash.cpp | 6 +- .../TheBlackMorass/the_black_morass.cpp | 3 +- .../Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp | 2 +- src/server/scripts/Kalimdor/zone_silithus.cpp | 2 +- .../Naxxramas/boss_four_horsemen.cpp | 2 +- .../Northrend/Ulduar/Ulduar/boss_freya.cpp | 2 +- .../boss_hydross_the_unstable.cpp | 3 +- .../SerpentShrine/boss_lady_vashj.cpp | 4 +- .../boss_warchief_kargath_bladefist.cpp | 12 +- .../Mechanar/boss_nethermancer_sepethrea.cpp | 4 +- .../boss_pathaleon_the_calculator.cpp | 4 +- .../Outland/zone_blades_edge_mountains.cpp | 9 +- .../Outland/zone_shadowmoon_valley.cpp | 9 +- src/server/scripts/Spells/spell_generic.cpp | 37 ++++ 34 files changed, 233 insertions(+), 197 deletions(-) create mode 100644 sql/updates/world/master/2019_07_16_03_world_2017_02_05_00_world.sql 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 0000000000..bc4e3f6075 --- /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 f8305dbffd..debf8f3b81 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(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); - - addvalue = uint32((27.0f / 5.0f + 17.0f) * ManaIncreaseRate); + 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); + } + 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; - // 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) + // or if enemy is in evade mode + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) + return false; + + if (!GetCharmerOrOwnerGUID().IsPlayer()) + { + if (GetMap()->IsDungeon()) 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; + // 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; + } + + // Map visibility range, but no more than 2*cell size + float dist = std::min(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 5d48cfa529..c90081536c 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, 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, 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, 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, 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, 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 01c19a2e8d..bea8ce9fb6 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 b45e1e14e3..1c28a62351 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 a618a26362..0ee1e732d6 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 92d427e083..55b3e88c34 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 441ad05493..50013a0797 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 e756f48f7a..ea9ead9812 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 959aaf123f..ff7a37c1d9 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 bf67637808..c74da19008 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 d98889232c..937578b6cc 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 37484bba40..9ae7ddd02b 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 1313340564..bfb8ede424 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 6a43171322..faf4bca902 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 0edada91c6..321a4ae429 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 b8e8bb91aa..9b58046036 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 0dfb5cfe69..ee598fff9a 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 a127321c13..744a8f974a 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 fb1f8ff102..0427de8847 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 2f1fad60e1..adff04f2e0 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 cd8ef1f253..acb5b82c1b 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 e8bedc0e8c..b44b601366 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 7b7f94a63f..9dc9dd2307 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 bf6b3cd355..6a9dac9f62 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 0d3ccc7468..0d36e85cdd 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 d40f46bbaa..5617e708b1 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 211be3d55f..4a5c82d0c7 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 c5df85fc29..51082af574 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 175caeb0de..f66c90eead 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 251954cbb7..449dc48fac 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 0c00d733bc..4f9f1f18da 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 025b0ece9e..5107eb8dac 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 1defc975ab..8e5e5e633b 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();