From f4314590636a863e7564acdaa4c15e806ea67bfa 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 (cherry picked from commit e1f14215d86fc9f0cd041f0e87bf0a689c086329) --- ...022_01_29_00_world_2017_02_05_00_world.sql | 13 ++++ .../game/Entities/Creature/Creature.cpp | 75 +++++++++++++------ src/server/game/Entities/Creature/Creature.h | 9 ++- src/server/game/Entities/Unit/Unit.cpp | 23 ++---- src/server/game/Entities/Unit/Unit.h | 7 -- .../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 | 2 +- .../Uldaman/instance_uldaman.cpp | 12 +-- .../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 +- .../Northrend/Ulduar/Ulduar/boss_freya.cpp | 2 +- .../boss_hydross_the_unstable.cpp | 5 +- .../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 | 8 +- src/server/scripts/Spells/spell_generic.cpp | 35 +++++++++ 28 files changed, 150 insertions(+), 115 deletions(-) create mode 100644 sql/updates/world/4.3.4/2022_01_29_00_world_2017_02_05_00_world.sql diff --git a/sql/updates/world/4.3.4/2022_01_29_00_world_2017_02_05_00_world.sql b/sql/updates/world/4.3.4/2022_01_29_00_world_2017_02_05_00_world.sql new file mode 100644 index 00000000000..bc4e3f60759 --- /dev/null +++ b/sql/updates/world/4.3.4/2022_01_29_00_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 67b5f322983..d63ee3a8c16 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -272,7 +272,7 @@ m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTi m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_regenHealth(true), m_cannotReachTarget(false), m_cannotReachTimer(0), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), _waypointPathId(0), _currentWaypointNodeInfo(0, 0), _cyclicSplinePathId(0), -m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _isMissingSwimmingFlagOutOfCombat(false), _noNpcDamageBelowPctHealth(0.f) +m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _lastDamagedTime(0), _isMissingSwimmingFlagOutOfCombat(false), _noNpcDamageBelowPctHealth(0.f) { m_valuesCount = UNIT_END; @@ -334,12 +334,7 @@ void Creature::RemoveFromWorld() void Creature::DisappearAndDie() { - DestroyForNearbyPlayers(); - //SetVisibility(VISIBILITY_OFF); - //ObjectAccessor::UpdateObjectVisibility(this); - if (IsAlive()) - setDeathState(JUST_DIED); - RemoveCorpse(false); + ForcedDespawn(0); } bool Creature::IsReturningHome() const @@ -391,7 +386,7 @@ bool Creature::IsFormationLeaderMoveAllowed() const return m_formation->CanLeaderStartMoving(); } -void Creature::RemoveCorpse(bool setSpawnTime) +void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers) { if (getDeathState() != CORPSE) return; @@ -401,12 +396,14 @@ void Creature::RemoveCorpse(bool setSpawnTime) m_corpseRemoveTime = GameTime::GetGameTime(); setDeathState(DEAD); RemoveAllAuras(); - DestroyForNearbyPlayers(); // old UpdateObjectVisibility() loot.clear(); uint32 respawnDelay = m_respawnDelay; if (CreatureAI* ai = AI()) ai->CorpseRemoved(respawnDelay); + if (destroyForNearbyPlayers) + DestroyForNearbyPlayers(); + // Should get removed later, just keep "compatibility" with scripts if (setSpawnTime) m_respawnTime = std::max(GameTime::GetGameTime() + respawnDelay, m_respawnTime); @@ -467,9 +464,9 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) return false; } - // get difficulty 1 mode entry + // get difficulty 1 mode entry, skip for pets CreatureTemplate const* cinfo = normalInfo; - for (uint8 diff = uint8(GetMap()->GetSpawnMode()); diff > 0;) + for (uint8 diff = uint8(GetMap()->GetSpawnMode()); diff > 0 && !IsPet();) { // we already have valid Map pointer for current creature! if (normalInfo->DifficultyEntry[diff - 1]) @@ -585,13 +582,16 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, else SetUInt32Value(UNIT_NPC_FLAGS, npcflag); + // if unit is in combat, keep this flag + unit_flags &= ~UNIT_FLAG_IN_COMBAT; + if (IsInCombat()) + unit_flags |= UNIT_FLAG_IN_COMBAT; + SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); SetUInt32Value(UNIT_FIELD_FLAGS_2, cInfo->unit_flags2); SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynamicflags); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - SetCanDualWield(cInfo->flags_extra & CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK); SetAttackTime(BASE_ATTACK, cInfo->BaseAttackTime); @@ -984,6 +984,10 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, Posit ProcessPositionDataChanged(data); } + // 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; @@ -2071,7 +2075,7 @@ void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer) } // Skip corpse decay time - RemoveCorpse(!overrideRespawnTime); + RemoveCorpse(!overrideRespawnTime, false); SetCorpseDelay(corpseDelay); SetRespawnDelay(respawnDelay); @@ -2384,6 +2388,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; @@ -2482,21 +2494,40 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const if (!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 (GameTime::GetGameTime() - 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() > GameTime::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 += GetCombatReach() + victim->GetCombatReach(); + + // to prevent creatures in air ignore attacks because distance is already too high... + if (GetMovementTemplate().IsFlightAllowed()) + return victim->IsInDist2d(&m_homePosition, dist); + else + return victim->IsInDist(&m_homePosition, dist); + } } CreatureAddon const* Creature::GetCreatureAddon() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 2d17adc3776..9021c09c0e2 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -83,7 +83,7 @@ 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; } @@ -244,7 +244,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 forceRespawnTime = 0s); void DespawnOrUnsummon(Milliseconds time, Seconds forceRespawnTime = 0s) { DespawnOrUnsummon(uint32(time.count()), forceRespawnTime); } @@ -351,6 +351,10 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma bool IsMovementPreventedByCasting() const override; + // 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); @@ -455,6 +459,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma // Spell Focusing CreatureSpellFocusData _spellFocusInfo; + time_t _lastDamagedTime; // Part of Evade mechanics CreatureTextRepeatGroup m_textRepeat; bool _isMissingSwimmingFlagOutOfCombat; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 20ab9e71921..e8bd9afcabb 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -304,8 +304,8 @@ Unit::Unit(bool isWorldObject) : i_motionMaster(new MotionMaster(this)), m_vehicle(nullptr), m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_isEngaged(false), m_combatManager(this), m_threatManager(this), - i_AI(nullptr), m_aiLocked(false), _lastDamagedTime(0), - m_spellHistory(new SpellHistory(this)), _isIgnoringCombat(false) + i_AI(nullptr), m_aiLocked(false), m_spellHistory(new SpellHistory(this)), + _isIgnoringCombat(false) { m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; @@ -926,13 +926,15 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam victim->ModifyHealth(-(int32)damage); if (damagetype == DIRECT_DAMAGE || damagetype == SPELL_DIRECT_DAMAGE) - { victim->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::NonPeriodicDamage, 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(SPELL_AURA_DAMAGE_SHIELD))) + victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME); victim->GetThreatManager().AddThreat(this, float(damage), spellProto); + } else // victim is a player { // random durability for items (HIT TAKEN) @@ -14829,17 +14831,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(SPELL_AURA_DAMAGE_SHIELD)) - return; - - SetLastDamagedTime(GameTime::GetGameTime()); -} - bool Unit::IsHighestExclusiveAura(Aura const* aura, bool removeOtherAuraApplications /*= false*/) { for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 44bf23d51bd..b26fa7e6a19 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1818,11 +1818,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); bool IsHighestExclusiveAuraEffect(SpellInfo const* spellInfo, AuraType auraType, int32 effectAmount, uint8 auraEffectMask, bool removeOtherAuraApplications = false); @@ -1991,8 +1986,6 @@ class TC_GAME_API Unit : public WorldObject uint32 _oldFactionId; ///< faction before charm bool _isWalkingBeforeCharm; ///< Are we walking before we were charmed? - time_t _lastDamagedTime; // Part of Evade mechanics - SpellHistory* m_spellHistory; PositionUpdateInfo _positionUpdateInfo; diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4703c8eef06..9b02887fd91 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3094,7 +3094,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m { target->Kill(caster); if (caster->GetTypeId() == TYPEID_UNIT) - caster->ToCreature()->RemoveCorpse(); + caster->ToCreature()->DespawnOrUnsummon(); } bool seatChange = (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT) // Seat change on the same direct vehicle diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 8252a1d2d99..87e4451f225 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3122,10 +3122,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 70ed2790d2c..f6937dff699 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -99,8 +99,7 @@ public: return false; } - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); + creatureTarget->DespawnOrUnsummon(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetGuidValue(UNIT_FIELD_CREATEDBY, player->GetGUID()); diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index f76495614c2..4d111421574 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -193,10 +193,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 fc47693f38c..6ee2bcf6482 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp @@ -476,8 +476,7 @@ public: } else { - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } } void JustEngagedWith(Unit* /*who*/) override { } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index 75bcdef3fe2..1c318d114df 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 9b38b457b55..eae4a4726f2 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -1178,7 +1178,7 @@ public: 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 b1648d546b6..7ad0f3309e2 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp @@ -226,8 +226,8 @@ 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 @@ -236,8 +236,8 @@ 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 @@ -246,8 +246,8 @@ 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 4f327be6b33..d4b71da0749 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -233,8 +233,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 341375d8931..85de6a6a2fa 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -239,8 +239,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 a10125d465e..765913ac406 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -571,8 +571,7 @@ public: { if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) { - me->setDeathState(DEAD); - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } } } @@ -670,8 +669,7 @@ public: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 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 fb77e41014e..c549432a2f2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -201,8 +201,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(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, 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 345025d7994..13318bf8f74 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -130,7 +130,7 @@ class boss_skeram : public CreatureScript Talk(SAY_DEATH); } else - me->RemoveCorpse(); + me->DespawnOrUnsummon(); } void JustEngagedWith(Unit* who) override diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index 98cd26fe870..177c99c810e 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -926,7 +926,7 @@ public: void npc_qiraj_war_spawn::npc_qiraj_war_spawnAI::JustDied(Unit* /*killer*/) { - me->RemoveCorpse(); + me->DespawnOrUnsummon(); if (!MobGUID) return; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 6b46b236f1c..ad96a33557c 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -246,7 +246,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 f443f7b05db..2d8db675117 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 @@ -170,10 +170,7 @@ public: for (uint8 i = 0; i < 2; ++i) { if (Creature* mob = ObjectAccessor::GetCreature(*me, beams[i])) - { - mob->setDeathState(DEAD); - mob->RemoveCorpse(); - } + mob->DespawnOrUnsummon(); } } void JustEngagedWith(Unit* /*who*/) override 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 96039a82dc0..2fdb7be3f60 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -808,9 +808,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(FACTION_FRIENDLY); + 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 70a7cafb97e..cf1976e1a5b 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 @@ -178,11 +178,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(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); - creature->RemoveCorpse(); - } + creature->DespawnOrUnsummon(); } adds.clear(); @@ -190,11 +186,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(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, 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 aa60d13de98..0af0ab63726 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -195,8 +195,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 95c0ecd9558..ff798bedabb 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 @@ -231,8 +231,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 b9dc3ad0035..64dfc91c7f3 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -121,11 +121,7 @@ public: return; if (id == 0) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - me->SetHealth(0); - } + me->DespawnOrUnsummon(1); } void SpellHit(Unit* caster, SpellInfo const* spell) override @@ -153,7 +149,8 @@ public: EnterEvadeMode(); me->SetFlag(UNIT_FIELD_FLAGS, 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 0be2e3b2b34..01ed56980f7 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -380,7 +380,6 @@ public: FlyTimer = 10000; me->SetDisableGravity(false); - me->SetVisible(true); } void SpellHit(Unit* caster, SpellInfo const* spell) override @@ -422,10 +421,7 @@ public: PlayerGUID.Clear(); } - me->SetVisible(false); - me->SetDisableGravity(false); - me->DealDamage(me, me->GetHealth(), nullptr, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, nullptr, false); - me->RemoveCorpse(); + me->DespawnOrUnsummon(1); } } @@ -1190,7 +1186,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 cf15e7ad616..f751f1453ca 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -4265,6 +4265,40 @@ 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 + { + 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.Register(&spell_gen_shroud_of_death_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + OnEffectRemove.Register(&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(); + } +}; + enum ArmorSpecializationSpells { // Warrior @@ -5524,6 +5558,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_armor_specialization(); new spell_gen_pvp_trinket(); new spell_gen_blink();