From d4c703a2e2e3fa6399a042359d0562862e277b9d Mon Sep 17 00:00:00 2001 From: sevi Date: Sun, 19 Mar 2017 01:55:40 +0100 Subject: [PATCH] Core/Instance: implement the combat resurrection limit. Cherry Pick from https://github.com/TrinityCore/TrinityCore/commit/948146f3ee890b85af50944176877c7d44c0c120 I change this a bit, so that this is works right for 4.3.3 Patch. (Here isn't add charges after a specific time. Groups have from begin 1 or 3 Charges for Resurrection.) --- src/server/game/Handlers/MiscHandler.cpp | 15 +++ src/server/game/Instances/InstanceScript.cpp | 96 ++++++++++++++++++-- src/server/game/Instances/InstanceScript.h | 11 +++ src/server/game/Maps/Map.cpp | 7 +- src/server/game/Spells/SpellInfo.cpp | 8 ++ 5 files changed, 126 insertions(+), 11 deletions(-) diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 13fffe9676..aefa711f4c 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -46,6 +46,7 @@ #include "BattlefieldMgr.h" #include "DB2Stores.h" #include "WhoListStorage.h" +#include "InstanceScript.h" void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData) { @@ -616,6 +617,20 @@ void WorldSession::HandleResurrectResponseOpcode(WorldPacket& recvData) if (!GetPlayer()->IsResurrectRequestedBy(guid)) return; + if (Player* ressPlayer = ObjectAccessor::GetPlayer(*GetPlayer(), guid)) + { + if (InstanceScript* instance = player->GetInstanceScript()) + { + if (instance->IsEncounterInProgress()) + { + if (!instance->GetCombatResurrectionCharges()) + return; + else + instance->UseCombatResurrection(); + } + } + } + GetPlayer()->ResurrectUsingRequestData(); } diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 5823897f98..4b36d0b28d 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -295,16 +295,41 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state) //TC_LOG_ERROR("misc", "Inialize boss %u state as %u.", id, (uint32)state); return false; } - else - { - if (bossInfo->state == state) - return false; + else + { + if (bossInfo->state == state) + return false; - if (state == DONE) - for (GuidSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i) - if (Creature* minion = instance->GetCreature(*i)) - if (minion->isWorldBoss() && minion->IsAlive()) - return false; + if (state == DONE) + for (GuidSet::iterator i = bossInfo->minion.begin(); i != bossInfo->minion.end(); ++i) + if (Creature* minion = instance->GetCreature(*i)) + if (minion->isWorldBoss() && minion->IsAlive()) + return false; + + switch (state) + { + case IN_PROGRESS: + { + uint32 resInterval = GetCombatResurrectionChargeInterval(); + if (instance->Is25ManRaid() || (instance->Is25ManRaid() && instance->IsHeroic())) + { + InitializeCombatResurrections(3, resInterval); + } + else + { + InitializeCombatResurrections(1, resInterval); + } + break; + } + + case FAIL: + case DONE: + ResetCombatResurrections(); + break; + + default: + break; + } bossInfo->state = state; SaveToDB(); @@ -690,3 +715,56 @@ void InstanceScript::UpdatePhasing() if (Player* player = itr->GetSource()) player->SendUpdatePhasing(); } + +void InstanceScript::UpdateCombatResurrection(uint32 diff) +{ + if (!_combatResurrectionTimerStarted) + return; + + _combatResurrectionTimer -= diff; + if (_combatResurrectionTimer <= 0) + { + AddCombatResurrectionCharge(); + _combatResurrectionTimerStarted = false; + } +} + +void InstanceScript::InitializeCombatResurrections(uint8 charges /*= 1*/, uint32 interval /*= 0*/) +{ + _combatResurrectionCharges = charges; + if (!interval) + return; + + _combatResurrectionTimer = interval; + _combatResurrectionTimerStarted = true; // true; +} + +void InstanceScript::AddCombatResurrectionCharge() +{ + // ++_combatResurrectionCharges; + _combatResurrectionTimer = GetCombatResurrectionChargeInterval(); + _combatResurrectionTimerStarted = true; +} + +void InstanceScript::UseCombatResurrection() +{ + --_combatResurrectionCharges; +} + +void InstanceScript::ResetCombatResurrections() +{ + _combatResurrectionCharges = 0; + _combatResurrectionTimer = 0; + _combatResurrectionTimerStarted = 0; +} + +uint32 InstanceScript::GetCombatResurrectionChargeInterval() const +{ + // This System here is from MoP and not Cataclysm. + // In Cataclysm have 10 Man Raids 1 Resurrection and 25 Man Raids 3 Resurrection free. + uint32 interval = 0; + if (uint32 playerCount = instance->GetPlayers().getSize()) + interval = 90 * MINUTE * IN_MILLISECONDS / playerCount; + + return interval; +} diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 9ed91fbda5..5ddd3f6c77 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -161,6 +161,7 @@ class TC_GAME_API InstanceScript : public ZoneScript void SaveToDB(); virtual void Update(uint32 /*diff*/) { } + void UpdateCombatResurrection(uint32 /*diff*/); // Used by the map's CannotEnter function. // This is to prevent players from entering during boss encounters. @@ -253,6 +254,13 @@ class TC_GAME_API InstanceScript : public ZoneScript uint32 GetEncounterCount() const { return bosses.size(); } + void InitializeCombatResurrections(uint8 charges = 1, uint32 interval = 0); + void AddCombatResurrectionCharge(); + void UseCombatResurrection(); + void ResetCombatResurrections(); + uint8 GetCombatResurrectionCharges() const { return _combatResurrectionCharges; } + uint32 GetCombatResurrectionChargeInterval() const; + protected: void SetHeaders(std::string const& dataHeaders); void SetBossNumber(uint32 number) { bosses.resize(number); } @@ -296,6 +304,9 @@ class TC_GAME_API InstanceScript : public ZoneScript ObjectInfoMap _gameObjectInfo; ObjectGuidMap _objectGuids; uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets + uint32 _combatResurrectionTimer; + uint8 _combatResurrectionCharges; // the counter for available battle resurrections + bool _combatResurrectionTimerStarted; #ifdef TRINITY_API_USE_DYNAMIC_LINKING // Strong reference to the associated script module diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 75e56f1026..bdd7b0d60c 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -3150,8 +3150,11 @@ void InstanceMap::Update(const uint32 t_diff) { Map::Update(t_diff); - if (i_data) - i_data->Update(t_diff); + if (i_data) + { + i_data->Update(t_diff); + i_data->UpdateCombatResurrection(t_diff); + } } void InstanceMap::RemovePlayerFromMap(Player* player, bool remove) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 8e62515738..5e1ae62361 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -27,6 +27,7 @@ #include "Battleground.h" #include "Vehicle.h" #include "Pet.h" +#include "InstanceScript.h" uint32 GetTargetFlagMask(SpellTargetObjectTypes objType) { @@ -1878,6 +1879,13 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta if (HasEffect(SPELL_EFFECT_SELF_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT) || HasEffect(SPELL_EFFECT_RESURRECT_NEW)) return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + if (HasAttribute(SPELL_ATTR8_BATTLE_RESURRECTION)) + if (Map* map = caster->GetMap()) + if (InstanceMap* iMap = map->ToInstance()) + if (InstanceScript* instance = iMap->GetInstanceScript()) + if (instance->GetCombatResurrectionCharges() == 0 && instance->IsEncounterInProgress()) + return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED; + return SPELL_CAST_OK; }