diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 66a6dd37a..aa3d63d84 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -277,6 +277,13 @@ bool Spawn2::Process() { npcthis = npc; + if (!m_entity_variables.empty()) { + for (auto &var : m_entity_variables) { + npc->SetEntityVariable(var.first, var.second); + } + m_entity_variables = {}; + } + npc->SetResumedFromZoneSuspend(m_resumed_from_zone_suspend); m_resumed_from_zone_suspend = false; diff --git a/zone/spawn2.h b/zone/spawn2.h index 820e700d2..f021b120d 100644 --- a/zone/spawn2.h +++ b/zone/spawn2.h @@ -77,6 +77,7 @@ public: inline NPC *GetNPC() const { return npcthis; } inline bool IsResumedFromZoneSuspend() const { return m_resumed_from_zone_suspend; } inline void SetResumedFromZoneSuspend(bool resumed) { m_resumed_from_zone_suspend = resumed; } + inline void SetEntityVariables(std::map vars) { m_entity_variables = vars; } protected: friend class Zone; @@ -104,6 +105,7 @@ private: bool IsDespawned; uint32 killcount; bool m_resumed_from_zone_suspend = false; + std::map m_entity_variables = {}; }; class SpawnCondition { diff --git a/zone/zone_save_state.cpp b/zone/zone_save_state.cpp index 9f201c5b6..67676af5b 100644 --- a/zone/zone_save_state.cpp +++ b/zone/zone_save_state.cpp @@ -204,6 +204,33 @@ inline std::string GetLootSerialized(Corpse *c) return ""; } +inline std::map GetVariablesDeserialized(const std::string &entity_variables) +{ + std::map deserialized_map; + + if (entity_variables.empty()) { + return deserialized_map; + } + + if (!Strings::IsValidJson(entity_variables)) { + LogZoneState("Invalid JSON data for entity variables"); + return deserialized_map; + } + + try { + std::stringstream ss; + { + ss << entity_variables; + cereal::JSONInputArchive ar(ss); + ar(deserialized_map); + } + } catch (const std::exception &e) { + LogZoneState("Failed to load entity variables [{}]", e.what()); + } + + return deserialized_map; +} + inline void LoadNPCEntityVariables(NPC *n, const std::string &entity_variables) { if (!RuleB(Zone, StateSaveEntityVariables)) { @@ -214,25 +241,7 @@ inline void LoadNPCEntityVariables(NPC *n, const std::string &entity_variables) return; } - if (!Strings::IsValidJson(entity_variables)) { - LogZoneState("Invalid JSON data for NPC [{}]", n->GetNPCTypeID()); - return; - } - - std::map deserialized_map; - try { - std::istringstream is(entity_variables); - { - cereal::JSONInputArchive archive(is); - archive(deserialized_map); - } - } - catch (const std::exception &e) { - LogZoneState("Failed to load entity variables for NPC [{}] [{}]", n->GetNPCTypeID(), e.what()); - return; - } - - for (const auto &[key, value]: deserialized_map) { + for (const auto &[key, value]: GetVariablesDeserialized(entity_variables)) { n->SetEntityVariable(key, value); } } @@ -310,6 +319,11 @@ inline std::vector GetLootdropIds(const std::vector 0) { @@ -329,7 +343,6 @@ inline void LoadNPCState(Zone *zone, NPC *n, ZoneStateSpawnsRepository::ZoneStat n->SetResumedFromZoneSuspend(false); LoadLootStateData(zone, n, s.loot_data); n->SetResumedFromZoneSuspend(true); - LoadNPCEntityVariables(n, s.entity_variables); LoadNPCBuffs(n, s.buffs); if (s.is_corpse) { @@ -477,6 +490,7 @@ bool Zone::LoadZoneState( if (spawn_time_left == 0) { new_spawn->SetCurrentNPCID(s.npc_id); new_spawn->SetResumedFromZoneSuspend(true); + new_spawn->SetEntityVariables(GetVariablesDeserialized(s.entity_variables)); } spawn2_list.Insert(new_spawn); @@ -513,6 +527,8 @@ bool Zone::LoadZoneState( npc->SetQueuedToCorpse(); } + LoadNPCStatePreSpawn(zone, npc, s); + entity_list.AddNPC(npc, true, true); LoadNPCState(zone, npc, s); @@ -566,7 +582,7 @@ inline void SaveNPCState(NPC *n, ZoneStateSpawnsRepository::ZoneStateSpawns &s) auto buffs = n->GetBuffs(); if (buffs) { std::vector valid_buffs; - for (int index = 0; index < n->GetMaxBuffSlots(); index++) { + for (int index = 0; index < n->GetMaxBuffSlots(); index++) { if (buffs[index].spellid != 0 && buffs[index].spellid != 65535) { valid_buffs.push_back(buffs[index]); }