From f9c0b02484084e24d524930d43c972d15444ff53 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Mon, 11 Aug 2025 13:22:41 -0500 Subject: [PATCH] town entry autosave wait for specials to run. fix #781 --- src/game/boe.specials.cpp | 6 ++++++ src/game/boe.town.cpp | 13 +++++++++---- src/game/boe.town.hpp | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/game/boe.specials.cpp b/src/game/boe.specials.cpp index 5cebc7ef..4f462956 100644 --- a/src/game/boe.specials.cpp +++ b/src/game/boe.specials.cpp @@ -2010,6 +2010,8 @@ void run_special(pending_special_type spec, short* a, short* b, bool* redraw) { univ.party.age = std::max(univ.party.age, store_time); } +extern bool need_enter_town_autosave; + // This is the big painful one, the main special engine entry point // which_mode - says when it was called // which_type - where the special is stored (town, out, scenario) @@ -2167,6 +2169,10 @@ void run_special(eSpecCtx which_mode, eSpecCtxType which_type, spec_num_t start_ erase_out_specials(); else erase_town_specials(); special_in_progress = false; + if(which_mode == eSpecCtx::ENTER_TOWN && need_enter_town_autosave){ + try_auto_save("EnterTown"); + need_enter_town_autosave = false; + } // TODO: Should find a way to do this that doesn't risk stack overflow if(ctx.next_spec == -1 && !special_queue.empty()) { diff --git a/src/game/boe.town.cpp b/src/game/boe.town.cpp index 46ecb3d2..a9b79de3 100644 --- a/src/game/boe.town.cpp +++ b/src/game/boe.town.cpp @@ -69,6 +69,8 @@ void force_town_enter(short which_town,location where_start) { town_force_loc = where_start; } +bool need_enter_town_autosave = false; + //short entry_dir; // if 9, go to forced void start_town_mode(short which_town, short entry_dir, bool debug_enter) { short town_number; @@ -334,8 +336,9 @@ void start_town_mode(short which_town, short entry_dir, bool debug_enter) { if(no_thrash.count(&monst) == 0) monst.active = eCreatureStatus::DEAD; } + bool specials_queued = false; if(!debug_enter) - handle_town_specials(town_number, (short) town_toast,(entry_dir < 9) ? univ.town->start_locs[entry_dir] : town_force_loc); + specials_queued = handle_town_specials(town_number, (short) town_toast,(entry_dir < 9) ? univ.town->start_locs[entry_dir] : town_force_loc); // Flush excess doomguards and viscous goos for(short i = 0; i < univ.town.monst.size(); i++) @@ -499,7 +502,9 @@ void start_town_mode(short which_town, short entry_dir, bool debug_enter) { // ... except it actually doesn't, because the town enter special is only queued, not run immediately. draw_terrain(1); - try_auto_save("EnterTown"); + // If special nodes still need to be called, we can't do the autosave yet. + if(specials_queued) need_enter_town_autosave = true; + else try_auto_save("EnterTown"); } @@ -626,8 +631,8 @@ location end_town_mode(bool switching_level,location destination, bool debug_lea return to_return; } -void handle_town_specials(short /*town_number*/, bool town_dead,location /*start_loc*/) { - queue_special(eSpecCtx::ENTER_TOWN, eSpecCtxType::TOWN, town_dead ? univ.town->spec_on_entry_if_dead : univ.town->spec_on_entry, univ.party.town_loc); +bool handle_town_specials(short /*town_number*/, bool town_dead,location /*start_loc*/) { + return queue_special(eSpecCtx::ENTER_TOWN, eSpecCtxType::TOWN, town_dead ? univ.town->spec_on_entry_if_dead : univ.town->spec_on_entry, univ.party.town_loc); } void handle_leave_town_specials(short /*town_number*/, short which_spec,location /*start_loc*/) { diff --git a/src/game/boe.town.hpp b/src/game/boe.town.hpp index 9467ad2c..2c866387 100644 --- a/src/game/boe.town.hpp +++ b/src/game/boe.town.hpp @@ -6,7 +6,7 @@ void force_town_enter(short which_town,location where_start); void start_town_mode(short which_town, short entry_dir, bool debug_enter = false); location end_town_mode(bool switching_level,location destination,bool debug_leave=false); // returns new party location void handle_leave_town_specials(short town_number, short which_spec,location start_loc) ; -void handle_town_specials(short town_number, bool town_dead,location start_loc) ; +bool handle_town_specials(short town_number, bool town_dead,location start_loc) ; bool abil_exists(eItemAbil abil); void start_town_combat(eDirection direction);