[Fix] Zone State Spawn2 Location Restore (#4844)

* [Fix] Zone State Spawn2 Location Restore

* Update zone_save_state.cpp

* Update zone_save_state.cpp

* Update zone_save_state.cpp

* Update zone_save_state.cpp
This commit is contained in:
Chris Miles 2025-04-09 21:43:18 -05:00 committed by GitHub
parent 216b3a039f
commit 16e341906d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 8 deletions

View File

@ -277,7 +277,13 @@ bool Spawn2::Process() {
}
}
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Water);
// zone state restore
if (m_stored_location != glm::vec4(0, 0, -1000, 0)) {
loc = m_stored_location;
m_stored_location = glm::vec4(0, 0, -1000, 0);
}
NPC *npc = new NPC(tmp, this, loc, GravityBehavior::Water);
npcthis = npc;

View File

@ -79,6 +79,7 @@ public:
inline void SetResumedFromZoneSuspend(bool resumed) { m_resumed_from_zone_suspend = resumed; }
inline void SetEntityVariables(std::map<std::string, std::string> vars) { m_entity_variables = vars; }
inline void SetResumedNPCID(uint32 npc_id) { m_resumed_npc_id = npc_id; }
inline void SetStoredLocation(const glm::vec4& loc) { m_stored_location = loc; }
protected:
friend class Zone;
@ -108,6 +109,7 @@ private:
bool m_resumed_from_zone_suspend = false;
uint32 m_resumed_npc_id = 0;
std::map<std::string, std::string> m_entity_variables = {};
glm::vec4 m_stored_location = {0, 0, -1000, 0}; // use -1000 to indicate unset/zero-state
};
class SpawnCondition {

View File

@ -5,6 +5,7 @@
#include "corpse.h"
#include "zone.h"
#include "zone_save_state.h"
#include "../common/repositories/spawn2_repository.h"
// IsZoneStateValid checks if the zone state is valid
// if these fields are all empty or zero value for an entire zone state, it's considered invalid
@ -440,8 +441,28 @@ bool Zone::LoadZoneState(
zone->initgrids_timer.Trigger();
zone->Process();
// load base spawn2 data for spawn locations
std::vector<std::string> spawn2_ids;
for (auto &s: spawn_states) {
if (s.spawn2_id > 0) {
spawn2_ids.push_back(std::to_string(s.spawn2_id));
}
}
std::vector<Spawn2Repository::Spawn2> spawn2s;
if (!spawn2_ids.empty()) {
spawn2s = Spawn2Repository::GetWhere(
content_db,
fmt::format(
"id IN ({})",
Strings::Join(spawn2_ids, ",")
)
);
LogZoneState("Loaded [{}] spawn2s", spawn2s.size());
}
// spawn2
int count = 0;
for (auto &s: spawn_states) {
if (s.spawngroup_id == 0 || s.is_corpse || s.is_zone) {
continue;
@ -463,13 +484,26 @@ bool Zone::LoadZoneState(
}
}
// find spawn 2 by id
Spawn2Repository::Spawn2 spawn2;
for (auto &sp: spawn2s) {
if (sp.id == s.spawn2_id) {
spawn2 = sp;
break;
}
}
if (!spawn2.id) {
LogZoneState("Failed to load spawn2 data for spawn2_id [{}]", s.spawn2_id);
}
auto new_spawn = new Spawn2(
s.spawn2_id,
s.spawngroup_id,
s.x,
s.y,
s.z,
s.heading,
spawn2.id > 0 ? spawn2.x : s.x,
spawn2.id > 0 ? spawn2.y : s.y,
spawn2.id > 0 ? spawn2.z : s.z,
spawn2.id > 0 ? spawn2.heading : s.heading,
s.respawn_time,
s.variance,
spawn_time_left,
@ -481,14 +515,14 @@ bool Zone::LoadZoneState(
(EmuAppearance) s.anim
);
new_spawn->SetStoredLocation(glm::vec4(s.x, s.y, s.z, s.heading));
if (spawn_time_left == 0) {
new_spawn->SetResumedNPCID(s.npc_id);
new_spawn->SetResumedFromZoneSuspend(true);
new_spawn->SetEntityVariables(GetVariablesDeserialized(s.entity_variables));
}
count++;
spawn2_list.Insert(new_spawn);
new_spawn->Process();
auto n = new_spawn->GetNPC();