From b1bec88bd15d05fac78d29d069cf9620383027f3 Mon Sep 17 00:00:00 2001 From: killerwife Date: Fri, 8 Nov 2024 12:52:58 +0100 Subject: [PATCH] SpawnGroup: Attempt to remedy dungeon spawn group creature entry gen --- src/game/Maps/SpawnGroup.cpp | 102 ++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/src/game/Maps/SpawnGroup.cpp b/src/game/Maps/SpawnGroup.cpp index 7e0e11467a..aa7655f0e9 100644 --- a/src/game/Maps/SpawnGroup.cpp +++ b/src/game/Maps/SpawnGroup.cpp @@ -240,10 +240,9 @@ void SpawnGroup::Spawn(bool force) std::shuffle(eligibleGuids.begin(), eligibleGuids.end(), *GetRandomGenerator()); - for (auto itr = eligibleGuids.begin(); itr != eligibleGuids.end() && !eligibleGuids.empty() && m_objects.size() < m_entry.MaxCount; ++itr) + for (auto itr = eligibleGuids.begin(); itr != eligibleGuids.end() && !eligibleGuids.empty() && m_objects.size() < m_entry.MaxCount;) { uint32 dbGuid = (*itr)->DbGuid; - uint32 entry = 0; if (m_entry.HasChancedSpawns) { if ((*itr)->Chance) @@ -259,44 +258,89 @@ void SpawnGroup::Spawn(bool force) spawn = spawnItr->second; if (!spawn) + { + itr = eligibleGuids.erase(itr); continue; + } } else // filling redundant entries when a group has chanced spawns for optimization so we can stop at start m_chosenSpawns[dbGuid] = true; + + ++itr; } + } - // creatures pick random entry on first spawn in dungeons - else always pick random entry - if (GetObjectTypeId() == TYPEID_UNIT) + eligibleGuids.resize(m_entry.MaxCount - m_objects.size()); // now we have final count for processing + + auto pickCreatureEntry = [&](const SpawnGroupDbGuids* guids) -> uint32 + { + uint32 entry; + // some group members can have static entry, or selfcontained random entry + if (guids->RandomEntry) + entry = sObjectMgr.GetRandomCreatureEntry(guids->DbGuid); + else if (guids->OwnEntry) + entry = guids->OwnEntry; + else + entry = GetEligibleEntry(validEntries, minEntries); + + return entry; + }; + + auto pickGoEntry = [&](const SpawnGroupDbGuids* guids) -> uint32 + { + uint32 entry; + // some group members can have static entry, or selfcontained random entry + if (guids->RandomEntry) + entry = sObjectMgr.GetRandomGameObjectEntry(guids->DbGuid); + else if (guids->OwnEntry) + entry = guids->OwnEntry; + else + entry = GetEligibleEntry(validEntries, minEntries); + + return entry; + }; + + // pick static and random entry first in dungeons so spawn group logic can decide after + if (m_map.IsDungeon() && GetObjectTypeId() == TYPEID_UNIT) + { + for (auto data : eligibleGuids) { - if (m_map.IsDungeon()) + if (data->RandomEntry || data->OwnEntry) { - // only held in memory - implement saving to db if it becomes a major issue - if (m_chosenEntries.find(dbGuid) == m_chosenEntries.end()) - { - // some group members can have static entry, or selfcontained random entry - if ((*itr)->RandomEntry) - entry = sObjectMgr.GetRandomCreatureEntry(dbGuid); - else if ((*itr)->OwnEntry) - entry = (*itr)->OwnEntry; - else - entry = GetEligibleEntry(validEntries, minEntries); - m_chosenEntries[dbGuid] = entry; - } - else - entry = m_chosenEntries[dbGuid]; + uint32 entry = pickCreatureEntry(data); + m_chosenEntries[data->DbGuid] = entry; + if (entry && validEntries[entry]) + --validEntries[entry]; } - else - entry = GetEligibleEntry(validEntries, minEntries); } - else // GOs always pick random entry + for (auto data : eligibleGuids) { - if ((*itr)->RandomEntry) - entry = sObjectMgr.GetRandomGameObjectEntry(dbGuid); - else if ((*itr)->OwnEntry) - entry = (*itr)->OwnEntry; - else - entry = GetEligibleEntry(validEntries, minEntries); + if (!data->RandomEntry && !data->OwnEntry) + { + uint32 entry = pickCreatureEntry(data); + m_chosenEntries[data->DbGuid] = entry; + if (entry && validEntries[entry]) + --validEntries[entry]; + } } + } + + for (auto itr = eligibleGuids.begin(); itr != eligibleGuids.end(); ++itr) + { + uint32 dbGuid = (*itr)->DbGuid; + uint32 entry = 0; + // creatures pick random entry on first spawn in dungeons - else always pick random entry + if (m_map.IsDungeon() && GetObjectTypeId() == TYPEID_UNIT) + entry = m_chosenEntries[dbGuid]; // only held in memory - implement saving to db if it becomes a major issue + else + { + if (GetObjectTypeId() == TYPEID_UNIT) + entry = pickCreatureEntry(*itr); + else // GOs always pick random entry + entry = pickGoEntry(*itr); + if (entry && validEntries[entry]) + --validEntries[entry]; + } float x, y; if (GetObjectTypeId() == TYPEID_UNIT) @@ -319,8 +363,6 @@ void SpawnGroup::Spawn(bool force) else WorldObject::SpawnGameObject(dbGuid, &m_map, entry); } - if (entry && validEntries[entry]) - --validEntries[entry]; } }