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();