[Zone] Implement Zone State Saving on Shutdown (#4715)

* Save spawns

* Update base_zone_state_spawns_repository.h

* Zone state save work

* Code cleanup

* More cleanup

* Database migration

* Update database_update_manifest.cpp

* Revert decay at storage model

* Code cleanup

* More cleanup

* More cleanup

* More cleanup

* Entity variables

* Add entity variables to the schema

* Post rebase

* Checkpoint

* Serialize / deserialize buffs

* Current hp / mana / end save / load

* Save / load current_waypoint

* Add zone spawn protection

* Finishing touches

* Cleanup

* Update zone_save_state.cpp

* Cleanup

* Update zone_save_state.cpp

* Update npc.cpp

* Update npc.cpp

* More

* Update perl_npc.cpp

* Update zone_loot.cpp
This commit is contained in:
Chris Miles
2025-02-28 15:31:06 -06:00
committed by GitHub
parent 425d24c1f4
commit 2f7ca2cdc8
26 changed files with 1637 additions and 59 deletions
+46
View File
@@ -62,6 +62,7 @@
#else
#include <stdlib.h>
#include <pthread.h>
#endif
extern Zone* zone;
@@ -131,6 +132,9 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
),
attacked_timer(CombatEventTimer_expire),
swarm_timer(100),
m_corpse_queue_timer(1000),
m_corpse_queue_shutoff_timer(30000),
m_resumed_from_zone_suspend_shutoff_timer(30000),
classattack_timer(1000),
monkattack_timer(1000),
knightattack_timer(1000),
@@ -618,7 +622,49 @@ bool NPC::Process()
}
}
// zone state corpse creation timer
if (RuleB(Zone, StateSavingOnShutdown)) {
// creates a corpse if the NPC is queued for corpse creation
if (m_corpse_queue_timer.Check()) {
if (IsQueuedForCorpse()) {
auto decay_timer = m_corpse_decay_time;
uint16 corpse_id = GetID();
Death(this, GetHP() + 1, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand);
auto c = entity_list.GetCorpseByID(corpse_id);
if (c) {
c->UnLock();
c->SetDecayTimer(decay_timer);
}
}
m_corpse_queue_timer.Disable();
m_corpse_queue_shutoff_timer.Disable();
}
// shuts off the corpse queue timer if it is still running
if (m_corpse_queue_shutoff_timer.Check()) {
m_corpse_queue_timer.Disable();
m_corpse_queue_shutoff_timer.Disable();
}
// shuts off the temporary spawn protected state of the NPC
if (m_resumed_from_zone_suspend_shutoff_timer.Check()) {
m_resumed_from_zone_suspend_shutoff_timer.Disable();
SetResumedFromZoneSuspend(false);
}
}
if (tic_timer.Check()) {
if (RuleB(Zone, StateSavingOnShutdown) && IsQueuedForCorpse()) {
auto decay_timer = m_corpse_decay_time;
uint16 corpse_id = GetID();
Death(this, GetHP() + 1, SPELL_UNKNOWN, EQ::skills::SkillHandtoHand);
auto c = entity_list.GetCorpseByID(corpse_id);
if (c) {
c->UnLock();
c->SetDecayTimer(decay_timer);
}
}
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_TICK)) {
parse->EventNPC(EVENT_TICK, this, nullptr, "", 0);
}