fix explosions breaking old replays

This commit is contained in:
2025-01-16 15:28:06 -06:00
parent afa79bcc5d
commit df02f79ab8
7 changed files with 31 additions and 9 deletions

View File

@@ -1599,7 +1599,8 @@ void do_combat_cast(location target) {
if(ashes_loc.x > 0){ if(ashes_loc.x > 0){
// If ashes are going to appear, there'd better be a visible blast on the spot. // If ashes are going to appear, there'd better be a visible blast on the spot.
if(!hit_ashes_loc){ 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); univ.town.set_ash(ashes_loc.x,ashes_loc.y,true);

View File

@@ -264,6 +264,9 @@ static void process_args(int argc, char* argv[]) {
cli.writeToStream(std::cout); cli.writeToStream(std::cout);
exit(0); 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(replay){
if(record_to){ if(record_to){
std::cout << "Warning: flag --record conflicts with --replay and will be ignored." << std::endl; std::cout << "Warning: flag --record conflicts with --replay and will be ignored." << std::endl;

View File

@@ -302,7 +302,9 @@ void mondo_boom(location l,short type,short snd) {
end_missile_anim(); 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) if(!boom_anim_active)
return; return;
// lose redundant explosions // 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++) for(short i = 0; i < 30; i++)
if(store_booms[i].boom_type < 0) { if(store_booms[i].boom_type < 0) {
have_boom = true; 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].dest = dest;
store_booms[i].val_to_place = val_to_place; store_booms[i].val_to_place = val_to_place;
store_booms[i].place_type = place_type; store_booms[i].place_type = place_type;

View File

@@ -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 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 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_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_missile_anim(short num_steps,location missile_origin,short sound_num) ;
void do_explosion_anim(short sound_num,short expand,short snd = -1); void do_explosion_anim(short sound_num,short expand,short snd = -1);
void click_shop_rect(rectangle area_rect); void click_shop_rect(rectangle area_rect);

View File

@@ -10,8 +10,9 @@
#include "mathutil.hpp" #include "mathutil.hpp"
std::mt19937 game_rand; 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; long unsigned int store;
short to_ret = 0; short to_ret = 0;
@@ -19,6 +20,9 @@ short get_ran (short times,short min,short max){
if(max == min) return times * min; if(max == min) return times * min;
for(short i = 1; i < times + 1; i++) { for(short i = 1; i < times + 1; i++) {
if(use_unique_ran)
store = unique_rand();
else
store = game_rand(); store = game_rand();
to_ret += min + (store % (max - min + 1)); to_ret += min + (store % (max - min + 1));
} }

View File

@@ -25,7 +25,8 @@ using std::abs;
extern std::mt19937 game_rand; 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 max(short a,short b);
short min(short a,short b); short min(short a,short b);
short minmax(short min,short max,short k); short minmax(short min,short max,short k);

View File

@@ -38,6 +38,11 @@ NSDictionary* prefsToRecord = @{
@"UIScale": @(kFloat), @"UIScale": @(kFloat),
@"UIScaleMap": @(kFloat) @"UIScaleMap": @(kFloat)
}; };
// Some legacy preferences influenced RNG and must be
// known by replays
NSDictionary* prefsToReplay = @{
@"DrawTerrainFrills": @(kBool)
};
bool prefsLoaded = false; 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); std::string key = line.substr(0, key_end + 1), val = line.substr(val_beg);
NSString* pref_key = [NSString stringWithUTF8String: key.c_str()]; NSString* pref_key = [NSString stringWithUTF8String: key.c_str()];
NSInteger type;
// Skip obsolete preferences from legacy replays // Skip obsolete preferences from legacy replays
if([prefsToRecord valueForKey: pref_key] == nil){ if([prefsToRecord valueForKey: pref_key] == nil){
if([prefsToReplay valueForKey: pref_key] == nil){
continue; continue;
}else{
type = [prefsToReplay[pref_key] integerValue];
}
}else{
type = [prefsToRecord[pref_key] integerValue];
} }
NSInteger type = [prefsToRecord[pref_key] integerValue];
switch((int)type) { switch((int)type) {
case kBool: case kBool:
if(val == "true") set_pref(key, true); if(val == "true") set_pref(key, true);