From df02f79ab8548b3242f81aa02005a70bba8581b0 Mon Sep 17 00:00:00 2001 From: Nat Quayle Nelson Date: Thu, 16 Jan 2025 15:28:06 -0600 Subject: [PATCH] fix explosions breaking old replays --- src/game/boe.combat.cpp | 3 ++- src/game/boe.main.cpp | 3 +++ src/game/boe.newgraph.cpp | 6 ++++-- src/game/boe.newgraph.hpp | 2 +- src/mathutil.cpp | 8 ++++++-- src/mathutil.hpp | 3 ++- src/tools/prefs.mac.mm | 15 +++++++++++++-- 7 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/game/boe.combat.cpp b/src/game/boe.combat.cpp index e619ca57..3bd0d05d 100644 --- a/src/game/boe.combat.cpp +++ b/src/game/boe.combat.cpp @@ -1599,7 +1599,8 @@ void do_combat_cast(location target) { if(ashes_loc.x > 0){ // If ashes are going to appear, there'd better be a visible blast on the spot. if(!hit_ashes_loc){ - add_explosion(ashes_loc,0,0,get_boom_type(eDamageType::FIRE),1,0); + // the last argument is true so this doesn't break RNG of older replays: + add_explosion(ashes_loc,0,0,get_boom_type(eDamageType::FIRE),1,0,true); } univ.town.set_ash(ashes_loc.x,ashes_loc.y,true); diff --git a/src/game/boe.main.cpp b/src/game/boe.main.cpp index 1f304cbb..9796f96b 100644 --- a/src/game/boe.main.cpp +++ b/src/game/boe.main.cpp @@ -264,6 +264,9 @@ static void process_args(int argc, char* argv[]) { cli.writeToStream(std::cout); exit(0); } + // This obsolete preference should always be true unless running an old replay + // (which will set it false after this line if it needs to) + set_pref("DrawTerrainFrills", true); if(replay){ if(record_to){ std::cout << "Warning: flag --record conflicts with --replay and will be ignored." << std::endl; diff --git a/src/game/boe.newgraph.cpp b/src/game/boe.newgraph.cpp index 5ed332d4..797d71f2 100644 --- a/src/game/boe.newgraph.cpp +++ b/src/game/boe.newgraph.cpp @@ -302,7 +302,9 @@ void mondo_boom(location l,short type,short snd) { end_missile_anim(); } -void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj) { +void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj, bool use_unique_ran) { + if(!get_bool_pref("DrawTerrainFrills", true)) + return; if(!boom_anim_active) return; // lose redundant explosions @@ -316,7 +318,7 @@ void add_explosion(location dest,short val_to_place,short place_type,short boom_ for(short i = 0; i < 30; i++) if(store_booms[i].boom_type < 0) { have_boom = true; - store_booms[i].offset = (i == 0) ? 0 : -1 * get_ran(1,0,2); + store_booms[i].offset = (i == 0) ? 0 : -1 * get_ran(1,0,2,use_unique_ran); store_booms[i].dest = dest; store_booms[i].val_to_place = val_to_place; store_booms[i].place_type = place_type; diff --git a/src/game/boe.newgraph.hpp b/src/game/boe.newgraph.hpp index eabfb376..7b744659 100644 --- a/src/game/boe.newgraph.hpp +++ b/src/game/boe.newgraph.hpp @@ -56,7 +56,7 @@ void run_a_missile(location from,location fire_to,miss_num_t miss_type,short pat void run_a_boom(location boom_where,short type,short x_adj,short y_adj,short snd = -1); void mondo_boom(location l,short type,short snd = -1); void add_missile(location dest,miss_num_t missile_type,short path_type,short x_adj,short y_adj); -void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj); +void add_explosion(location dest,short val_to_place,short place_type,short boom_type,short x_adj,short y_adj, bool use_unique_ran = false); void do_missile_anim(short num_steps,location missile_origin,short sound_num) ; void do_explosion_anim(short sound_num,short expand,short snd = -1); void click_shop_rect(rectangle area_rect); diff --git a/src/mathutil.cpp b/src/mathutil.cpp index 0bba1797..faaef3f2 100644 --- a/src/mathutil.cpp +++ b/src/mathutil.cpp @@ -10,8 +10,9 @@ #include "mathutil.hpp" std::mt19937 game_rand; +std::mt19937 unique_rand; -short get_ran (short times,short min,short max){ +short get_ran (short times,short min,short max, bool use_unique_ran){ long unsigned int store; short to_ret = 0; @@ -19,7 +20,10 @@ short get_ran (short times,short min,short max){ if(max == min) return times * min; for(short i = 1; i < times + 1; i++) { - store = game_rand(); + if(use_unique_ran) + store = unique_rand(); + else + store = game_rand(); to_ret += min + (store % (max - min + 1)); } return to_ret; diff --git a/src/mathutil.hpp b/src/mathutil.hpp index f5cfea60..211b7c47 100644 --- a/src/mathutil.hpp +++ b/src/mathutil.hpp @@ -25,7 +25,8 @@ using std::abs; extern std::mt19937 game_rand; -short get_ran(short times, short min, short max); +// unique_ran: pass true for get_ran() calls that would break replay compatibility +short get_ran(short times, short min, short max, bool use_unique_ran = false); short max(short a,short b); short min(short a,short b); short minmax(short min,short max,short k); diff --git a/src/tools/prefs.mac.mm b/src/tools/prefs.mac.mm index ad1453f9..dda10c5e 100644 --- a/src/tools/prefs.mac.mm +++ b/src/tools/prefs.mac.mm @@ -38,6 +38,11 @@ NSDictionary* prefsToRecord = @{ @"UIScale": @(kFloat), @"UIScaleMap": @(kFloat) }; +// Some legacy preferences influenced RNG and must be +// known by replays +NSDictionary* prefsToReplay = @{ + @"DrawTerrainFrills": @(kBool) +}; bool prefsLoaded = false; @@ -133,11 +138,17 @@ static bool load_prefs(std::istream& istream) { std::string key = line.substr(0, key_end + 1), val = line.substr(val_beg); NSString* pref_key = [NSString stringWithUTF8String: key.c_str()]; + NSInteger type; // Skip obsolete preferences from legacy replays if([prefsToRecord valueForKey: pref_key] == nil){ - continue; + if([prefsToReplay valueForKey: pref_key] == nil){ + continue; + }else{ + type = [prefsToReplay[pref_key] integerValue]; + } + }else{ + type = [prefsToRecord[pref_key] integerValue]; } - NSInteger type = [prefsToRecord[pref_key] integerValue]; switch((int)type) { case kBool: if(val == "true") set_pref(key, true);