Added Creature Map tracking and improved performance on storage

This commit is contained in:
2024-09-20 23:28:58 -04:00
parent 3b7c03ce0f
commit 7b79bf0316
8 changed files with 238 additions and 102 deletions

View File

@@ -63,42 +63,35 @@ public:
void OnCreatureAddWorld(Creature* creature) override
{
uint8 level;
Map* map = creature->GetMap();
if (!sMythicPlus->IsMapEligible(map)) {
// MpLogger::debug("Map: {} is not eligible to adjust so creature was skipped: Creature {}", map->GetMapName(), creature->GetName());
return;
}
// bail if the creature is not eligible to be scaled
if (!sMythicPlus->IsCreatureEligible(creature)) {
MpLogger::debug("Creature: {} Entry: {} is not eligible to adjust so creature was skipped.", creature->GetName(), creature->GetEntry());
return;
}
sMythicPlus->AddCreatureForScaling(creature);
MpInstanceData* instanceData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId());
if(!instanceData) {
MpLogger::debug("Creature: {} Could not find instance data for Map {} and InstanceId: {}", creature->GetName(), map->GetMapName(), map->GetInstanceId());
return;
}
// MpInstanceData* instanceData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId());
// if(!instanceData) {
// MpLogger::debug("Creature: {} Could not find instance data for Map {} and InstanceId: {}", creature->GetName(), map->GetMapName(), map->GetInstanceId());
// return;
// }
if (creature->IsDungeonBoss()) {
level = instanceData->boss.avgLevel;
} else {
level = uint8(urand(instanceData->creature.avgLevel-1, instanceData->creature.avgLevel+1));
}
// if (creature->IsDungeonBoss()) {
// level = instanceData->boss.avgLevel;
// } else {
// level = uint8(urand(instanceData->creature.avgLevel-1, instanceData->creature.avgLevel+1));
// }
// Scale the creature to its new level
sMythicPlus->ScaleCreature(level, creature);
// // Scale the creature to its new level
// sMythicPlus->ScaleCreature(level, creature);
MpLogger::debug("SetLevel and Updateded Creature {} Entry {} Id {} level from {} to {}",
MpLogger::debug("SetLevel and Updateded Creature {} Entry {} Id {} level from {}",
creature->GetName(),
creature->GetEntry(),
creature->GetGUID().GetCounter(),
creature->GetLevel(),
level
creature->GetLevel()
);
@@ -110,6 +103,31 @@ public:
// }
}
void OnAllCreatureUpdate(Creature* creature, uint32 diff) override
{
if (!sMythicPlus->IsMapEligible(creature->GetMap())) {
return;
}
sMythicPlus->ScaleOnUpdate(creature, diff);
// If the config is out of date and the creature was reset, run modify against it
// if (ResetCreatureIfNeeded(creature))
// {
// LOG_DEBUG("module.MythicPlus",
// "MythicPlus_AllCreatureScript::OnAllCreatureUpdate(): Creature {} ({}) is reset to its original stats.",
// creature->GetName(),
// creature->GetLevel()
// );
// // Update the map's level if it is out of date
// sMythicPlus->UpdateMapLevelIfNeeded(creature->GetMap());
// ModifyCreatureAttributes(creature);
// }
}
// void OnCreatureRemoveWorld(Creature* creature) override
// {
// Map* map = creature->GetMap();
@@ -161,23 +179,7 @@ public:
// );
// }
// void OnAllCreatureUpdate(Creature* creature, uint32 /*diff*/) override
// {
// // If the config is out of date and the creature was reset, run modify against it
// // if (ResetCreatureIfNeeded(creature))
// // {
// // LOG_DEBUG("module.MythicPlus",
// // "MythicPlus_AllCreatureScript::OnAllCreatureUpdate(): Creature {} ({}) is reset to its original stats.",
// // creature->GetName(),
// // creature->GetLevel()
// // );
// // // Update the map's level if it is out of date
// // sMythicPlus->UpdateMapLevelIfNeeded(creature->GetMap());
// // ModifyCreatureAttributes(creature);
// // }
// }
bool UpdateCreature(Creature* creature)
{

View File

@@ -14,51 +14,21 @@ public:
{
}
void OnCreateMap(Map* map)
{
if (!sMythicPlus->IsMapEligible(map)) {
return;
}
// Attempt to cast map to InstanceMap, making sure it is not null
InstanceMap* instance = dynamic_cast<InstanceMap*>(sMapMgr->FindMap(map->GetId(), map->GetInstanceId()));
if (!instance)
{
MpLogger::error("Failed to find InstanceMap for map ID {} and instance ID {}.", map->GetId(), map->GetInstanceId());
return;
}
Map::PlayerList playerList = instance->GetPlayers();
if (!playerList.IsEmpty()) {
for (auto i = playerList.begin(); i != playerList.end(); ++i) {
if (Player* iPlayer = i->GetSource()) {
Group* group = iPlayer->GetGroup();
if (group) {
MpLogger::debug("Player {} entered map {} in groupLeader {}", iPlayer->GetName(), map->GetMapName(), group->GetLeaderName());
} else {
return;
}
}
}
} else {
MpLogger::debug("No players found in map {}", map->GetMapName());
}
}
void OnCreateMap(Map* map) { }
/**
* When a player enters the map check it needs to set up the instance data
*/
void OnPlayerEnterAll(Map* map, Player* player)
{
MpLogger::debug("AllMapScript::OnPlayerEnterAll(): {}", map->GetMapName());
if (!sMythicPlus->IsMapEligible(map)) {
return;
}
if(!sMythicPlus->IsDifficultySet(player)) {
return;
}
Group* group = player->GetGroup();
if (group) {
MpLogger::debug("Player {} entered map {} in groupLeader {}", player->GetName(), map->GetMapName(), group->GetLeaderName());
@@ -72,11 +42,23 @@ public:
return;
}
// Check if we already have mythic instance data set for this map and group
MpInstanceData* existingData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId());
if (existingData) {
if(player->GetName() == group->GetLeaderName()) {
MpLogger::debug("Instance data already set for Map: {} InstanceId: {} for GroupLeader: {} ",
map->GetMapName(),
map->GetInstanceId(),
group->GetLeaderName()
);
}
return;
}
uint8 avgLevel = 0;
MpInstanceData instanceData;
switch(groupData->difficulty) {
case MP_DIFFICULTY_MYTHIC:
MpLogger::debug("Setting up Mythic instance data for group {}", group->GetGUID().GetCounter());
instanceData.boss = sMythicPlus->mythicBossModifiers;
instanceData.creature = sMythicPlus->mythicDungeonModifiers;
instanceData.itemRewards = sMythicPlus->EnableItemRewards;
@@ -84,7 +66,6 @@ public:
instanceData.itemOffset = sMythicPlus->mythicItemOffset;
break;
case MP_DIFFICULTY_LEGENDARY:
MpLogger::debug("Setting up Legendary instance data for group {}", group->GetGUID().GetCounter());
instanceData.boss = sMythicPlus->legendaryBossModifiers;
instanceData.creature = sMythicPlus->legendaryDungeonModifiers;
instanceData.itemRewards = sMythicPlus->EnableItemRewards;
@@ -92,7 +73,6 @@ public:
instanceData.itemOffset = sMythicPlus->legendaryItemOffset;
break;
case MP_DIFFICULTY_ASCENDANT:
MpLogger::debug("Setting up Ascendant instance data for group {}", group->GetGUID().GetCounter());
instanceData.boss = sMythicPlus->ascendantBossModifiers;
instanceData.creature = sMythicPlus->ascendantDungeonModifiers;
instanceData.itemRewards = sMythicPlus->EnableItemRewards;
@@ -129,8 +109,6 @@ public:
if (!sMythicPlus->IsMapEligible(map)) {
return;
}
MpLogger::debug("AllMapScript::OnDestroyInstance(): {}", map->GetMapName());
sMpDataStore->RemoveInstanceData(map->GetId(), map->GetInstanceId());
}
};

View File

@@ -142,6 +142,8 @@ public:
" Group Deaths: %u\n",
groupData->difficulty,
groupData->deaths);
} else {
status += " Group Difficulty: Not Set\n";
}
}

View File

@@ -23,12 +23,7 @@ class MythicPlus_GroupScript : public GroupScript
}
void OnDisband(Group* group) override {
if (!group) {
return;
}
// MpDataStore* mpds = MpDataStore::instance();
// mpds->RemoveGroupData(group->GetGUID());
sMpDataStore->RemoveGroupData(group);
}
};

View File

@@ -4,10 +4,10 @@
#include "Player.h"
MpDataStore::MpDataStore() {
_groupData = new std::map<ObjectGuid, MpGroupData>();
_playerData = new std::map<ObjectGuid, MpPlayerData>();
_instanceData = new std::map<std::pair<uint32, uint32>, MpInstanceData>();
_instanceCreatureData = new std::map<ObjectGuid, MapCreatureData>();
_groupData = new std::unordered_map<ObjectGuid, MpGroupData>();
_playerData = new std::unordered_map<ObjectGuid, MpPlayerData>();
_instanceData = new std::unordered_map<std::pair<uint32, uint32>, MpInstanceData>();
_instanceCreatureData = new std::unordered_map<ObjectGuid, MpCreatureData>();
}
MpDataStore::~MpDataStore() {
@@ -30,7 +30,6 @@ void MpDataStore::AddGroupData(Group *group, MpGroupData groupData) {
MpLogger::error("AddGroupData called with invalid difficulty");
return;
}
// if we already have data override it
if (_groupData->contains(guid)) {
_groupData->at(guid) = groupData;
@@ -46,6 +45,13 @@ void MpDataStore::AddGroupData(Group *group, MpGroupData groupData) {
);
}
MpGroupData* MpDataStore::GetGroupData(Group* group) {
if (auto it = _groupData->find(group->GetGUID()); it != _groupData->end()) {
return &(it->second);
}
}
/**
* This keeps track of instance keys (mapId, instanceId) for a group this can be used to
* reset instance settings in the instanceData store when a difficulty is changed by the group leader.
@@ -107,12 +113,21 @@ void MpDataStore::RemoveInstanceData(uint32 mapId, uint32 instanceId) {
_instanceData->erase(GetInstanceDataKey(mapId, instanceId));
}
void MpDataStore::AddInstanceCreatureData(ObjectGuid guid, MapCreatureData mcd) {
void MpDataStore::AddCreatureData(ObjectGuid guid, MpCreatureData creatureData) {
MpLogger::debug("AddInstanceCreatureData for creature {}", guid.GetCounter());
_instanceCreatureData->insert({guid, mcd});
_instanceCreatureData->insert({guid, creatureData});
}
void MpDataStore::RemoveInstanceCreatureData(ObjectGuid guid) {
MpCreatureData* MpDataStore::GetCreatureData(ObjectGuid guid) {
if (!_instanceCreatureData->contains(guid)) {
MpLogger::debug("No instance creature data found for creature {}", guid.GetCounter());
return nullptr;
}
return &_instanceCreatureData->at(guid);
}
void MpDataStore::RemoveCreatureData(ObjectGuid guid) {
MpLogger::debug("RemoveInstanceCreatureData data for creature {}", guid.GetCounter());
_instanceCreatureData->erase(guid);
}

View File

@@ -78,10 +78,45 @@ struct MpInstanceData
};
struct MapCreatureData
/**
* Simple struct for managing information about creatures that
* are in a mythic+ instance.
*/
struct MpCreatureData
{
Creature* creature;
MapEntry* instance;
bool scaled;
// Original information about the creature that was altered.
uint8 originalLevel;
CreatureBaseStats const* originalStats;
// Custom difficulty modifiers to creatures at higher difficulties.
std::vector<uint32> auras;
std::vector<std::string> affixes;
MpCreatureData(Creature* creature)
: creature(creature), scaled(false)
{
if(creature) {
originalLevel = creature->GetLevel();
CreatureBaseStats const* originalStats = sObjectMgr->GetCreatureBaseStats(
originalLevel,
creature->GetCreatureTemplate()->unit_class
);
}
}
void SetScaled(bool scaled) {
this->scaled = scaled;
}
bool IsScaled() {
return scaled;
}
/**@todo Add Affixes and Aura Spell methods */
};
class MpDataStore {
@@ -89,10 +124,16 @@ private:
MpDataStore();
~MpDataStore();
std::map<ObjectGuid, MpGroupData>* _groupData;
std::map<ObjectGuid, MpPlayerData>* _playerData;
std::map<std::pair<uint32,uint32>,MpInstanceData>* _instanceData;
std::map<ObjectGuid, MapCreatureData>* _instanceCreatureData;
std::unordered_map<ObjectGuid, MpPlayerData>* _playerData;
// Instance Data map key is unique instance pair and values are modifiers of instance
std::unordered_map<std::pair<uint32,uint32>,MpInstanceData>* _instanceData;
// Group Data map key is group guid and values are mythic settings set by group leader
std::unordered_map<ObjectGuid, MpGroupData>* _groupData;
// Instance Creature Data map key is creature guid and values are creature itself from a mythic instance
std::unordered_map<ObjectGuid, MpCreatureData>* _instanceCreatureData;
public:
@@ -122,25 +163,30 @@ public:
};
// Set and remove difficluty settig for a group
void AddGroupData(Group *group, MpGroupData gd);
void AddGroupData(Group *group, MpGroupData groupData);
void RemoveGroupData(Group *group);
MpGroupData* GetGroupData(Group *group);
void PushGroupInstanceKey(Group *group, uint32 mapId, uint32 instanceId);
void AddPlayerData(ObjectGuid guid, MpPlayerData pd);
void RemovePlayerData(ObjectGuid guid);
// Each Map/Instance is a unique key that contains scaling information based on difficulty
void AddInstanceData(uint32 mapId, uint32 instanceId, MpInstanceData );
MpInstanceData* GetInstanceData(uint32 mapId, uint32 instanceId);
void RemoveInstanceData(uint32 mapId, uint32 instanceId);
void AddInstanceCreatureData(ObjectGuid guid, MapCreatureData mcd);
void RemoveInstanceCreatureData(ObjectGuid guid);
// Methods for interacting with the map of creatures in a mythic instances
void AddCreatureData(ObjectGuid guid, MpCreatureData creatureData);
MpCreatureData* GetCreatureData(ObjectGuid guid);
void RemoveCreatureData(ObjectGuid guid);
// creates a unique instance key into the instance data store
auto GetInstanceDataKey(uint32 mapId, uint32 instanceId) {
return std::make_pair(mapId, instanceId);
}
// accessor for this singleton
static MpDataStore* instance() {
static MpDataStore instance;
return &instance;

View File

@@ -1,4 +1,6 @@
#include "MythicPlus.h"
#include "MpDataStore.h"
#include "MpLogger.h"
#include "ObjectMgr.h"
#include "MapMgr.h"
@@ -15,6 +17,22 @@ bool MythicPlus::IsMapEligible(Map* map)
return false;
}
bool MythicPlus::IsDifficultySet(Player* player)
{
Group* group = player->GetGroup();
if (!group) {
return false;
}
MpGroupData const* groupData = sMpDataStore->GetGroupData(group->GetGUID());
if (!groupData) {
return false;
}
return true;
}
bool MythicPlus::IsDifficultyEnabled(std::string difficulty)
{
return std::find(enabledDifficulties.begin(), enabledDifficulties.end(), difficulty) != enabledDifficulties.end();
@@ -63,6 +81,76 @@ bool MythicPlus::IsCreatureEligible(Creature* creature)
return true;
}
void MythicPlus::AddCreatureForScaling(Creature* creature)
{
if (!IsCreatureEligible(creature)) {
return;
}
sMpDataStore->AddCreatureData(creature->GetGUID(), MpCreatureData(creature));
MpLogger::debug("Added creature {} to instance data for instance {}",
creature->GetName(),
creature->GetMap()->GetMapName()
);
}
void MythicPlus::ScaleOnUpdate(Creature* creature, uint32 diff)
{
// Check to see if the creature is in our list to be scaled to mythic+ levels
MpCreatureData* creatureData = sMpDataStore->GetCreatureData(creature->GetGUID());
if (!creatureData) {
return;
}
// if it has already been scaled then do nothing.
if (creatureData->IsScaled()) {
MpLogger::debug("Creature {} Entry {} Id {} already scaled in ScaleOnUpdate()",
creature->GetName(),
creature->GetEntry(),
creature->GetGUID().GetCounter()
);
return;
}
// Otherwise we handle scaling the stats of the creature based on map difficulty set
Map* map = creature->GetMap();
if(!map) {
MpLogger::warn("Map is null for creature {} Entry {} Id {} could not scale in ScaleOnUpdate()",
creature->GetName(),
creature->GetEntry(),
creature->GetGUID().GetCounter()
);
return;
}
// The instance data for this map determines how to scale the creature by difficulty set
MpInstanceData* instanceData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId());
if (!instanceData) {
MpLogger::warn("Instance data is null for creature {} Entry {} Id {} could not scale in ScaleOnUpdate()",
creature->GetName(),
creature->GetEntry(),
creature->GetGUID().GetCounter()
);
return;
}
// allow small variance in level for non-boss creatures
uint8 level = uint8(urand(instanceData->creature.avgLevel - 1, instanceData->creature.avgLevel + 1));
if(creature->IsDungeonBoss()) {
level = instanceData->boss.avgLevel;
}
ScaleCreature(level, creature);
creatureData->SetScaled(true); // Since updates happen frequently set the flag so we do not re-scale
MpLogger::debug("Sca Creature {} Entry {} Id {} level from {} to {}",
creature->GetName(),
creature->GetEntry(),
creature->GetGUID().GetCounter(),
creature->GetLevel(),
level
);
}
void MythicPlus::ScaleCreature(uint8 level, Creature* creature)
{
creature->SetLevel(level);
@@ -118,7 +206,7 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature)
*/
float GetHealthModifier(int32 Rank)
{
switch (Rank) // define rates for each elite rank
switch (Rank)
{
case CREATURE_ELITE_NORMAL:
return sWorld->getRate(RATE_CREATURE_NORMAL_HP);

View File

@@ -52,6 +52,9 @@ public:
// Map is eligible for mythic+ scaling
bool IsMapEligible(Map* map);
// If a player difficulty is set that is eligible for mythic+ scaling
bool IsDifficultySet(Player* player);
// Check is difficulty is enabled in the configuration
bool IsDifficultyEnabled(std::string difficulty);
@@ -61,6 +64,13 @@ public:
// The creature should be given Mythic+ scaling and powers check for pets, npcs, etc
bool IsCreatureEligible(Creature* creature);
// Adds the creature if eligible to be scaled
void AddCreatureForScaling(Creature* creature);
// Will make determination on if this creature needs to be scaled and will do so
// the diff time is used to determine the last time the creature was modified.
void ScaleOnUpdate(Creature* creature, uint32 diff);
// Scales the creature based on the level and the creature base stats
void ScaleCreature(uint8 level, Creature* creature);