diff --git a/src/Scripts/AllCreatureScript.cpp b/src/Scripts/AllCreatureScript.cpp index e778af4..0c57800 100644 --- a/src/Scripts/AllCreatureScript.cpp +++ b/src/Scripts/AllCreatureScript.cpp @@ -7,6 +7,9 @@ class MythicPlus_AllCreatureScript : public AllCreatureScript { +private: + std::unordered_map m_creatureUpdateTimers; + public: MythicPlus_AllCreatureScript() : AllCreatureScript("MythicPlus_AllCreatureScript") {} @@ -14,7 +17,7 @@ public: // { // } - void OnCreatureRespawn(Creature* creature) override + void OnCreatureRespawn(Creature* creature) { Map* map = creature->GetMap(); if (!sMythicPlus->IsMapEligible(map)) { @@ -33,9 +36,70 @@ public: } } - // void OnAllCreatureUpdate(Creature* creature, uint32 diff) override - // { - // } + /** + * @brief This hook runs every update for all creatures in the world. + * We only need to concern ourselves with creatures in the scope of our mythic+ instances. + * Need to detect the following changes: + * - Creature Death State - to trigger respawn scaling. + * - Other events where a creature enters the instance that is not scaled, then should be scaled up. Some special events normal enemies will be scripted + * to show up in encounters these will not trigger the OnCreatureAddWorld, because they were not during the initial load of the instance. (Though sometimes summons do trigger this?) + * + * @param creature + * @param diff + */ + void OnAllCreatureUpdate(Creature* creature, uint32 diff) override + { + // Skip any creatures not in an instance we are scaling first to avoid unnecessary work + if (!sMythicPlus->IsMapEligible(creature->GetMap())) { + return; + } + + if (!sMythicPlus->IsCreatureEligible(creature)) { + return; + } + + // throttle this check per creature to only run if more than 20ms has passed since last check + ObjectGuid creatureGuid = creature->GetGUID(); + m_creatureUpdateTimers[creatureGuid] += diff; + if(m_creatureUpdateTimers[creatureGuid] < 20) { + return; + } + m_creatureUpdateTimers[creatureGuid] = 0; + + + auto instanceData = sMpDataStore->GetInstanceData(creature->GetMapId(), creature->GetInstanceId()); + // no instance data yet means dont scale. + if(!instanceData) { + return; + } + + MpCreatureData* creatureData = sMpDataStore->GetCreatureData(creature->GetGUID()); + + // this is a creature that was not scaled at instance load time, we need to scale it now. + if(!creatureData) { + MpLogger::debug("OnAllCreatureUpdate: Unknown Creature Add event scaling creature: {}", creature->GetName()); + sMythicPlus->AddScaledCreature(creature, sMpDataStore->GetInstanceData(creature->GetMap()->GetId(), creature->GetMap()->GetInstanceId())); + return; + } + DeathState currentState = creature->getDeathState(); + + // record the death of our scaled creature + if(currentState == DeathState::Corpse && creatureData->lastDeathState != DeathState::Corpse) { + creatureData->lastDeathState = currentState; + return; + } + + if(currentState == DeathState::Alive && creatureData->lastDeathState == DeathState::Corpse) { + MpLogger::debug("OnAllCreatureUpdate: Creature Death event scaling creature: {} level: {} guid: {} event: {}", creature->GetName(), creatureData->creature->GetLevel(), creature->GetGUID().ToString(), creature->getDeathState()); + if(creature->IsDungeonBoss() || creature->GetEntry() == 23682) { + sMythicPlus->AddScaledCreature(creature, instanceData); + } else { + sMythicPlus->AddScaledCreature(creature, instanceData); + } + } + + + } // When a new creature is added into a mythic+ map add it to the list of creatures to scale later. void OnCreatureAddWorld(Creature* creature) override @@ -51,6 +115,7 @@ public: // if we have instance data about zone then just scale the creature otherwise add to be scaled once we do. MpInstanceData* instanceData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId()); + if(instanceData) { sMythicPlus->AddScaledCreature(creature, instanceData); } else {