diff --git a/common/main/player.h b/common/main/player.h index 5b967cb8a..a416720d3 100644 --- a/common/main/player.h +++ b/common/main/player.h @@ -57,7 +57,6 @@ struct player : public prohibit_void_ptr // Game data player_flags flags; // Powerup flags, see below... fix energy; // Amount of energy remaining. - fix shields; // shields remaining (protection) ubyte lives; // Lives remaining, 0 = game over. sbyte level; // Current level player is playing. (must be signed for secret levels) stored_laser_level laser_level; // Current level of the laser. @@ -174,7 +173,7 @@ static_assert(sizeof(player_rw) == 142, "wrong size player_rw"); #define get_local_plrobj() (*vobjptr(get_local_player().objnum)) #define get_local_player_energy() (get_local_player().energy) #define get_local_player_vulcan_ammo() (get_local_player().vulcan_ammo) -#define get_local_player_shields() (get_local_player().shields) +#define get_local_player_shields() (get_local_plrobj().shields) #define get_local_player_secondary_ammo() (get_local_player().secondary_ammo) #define get_local_player_flags() (get_local_player().flags) #define get_local_player_cloak_time() (get_local_player().cloak_time) diff --git a/similar/main/collide.cpp b/similar/main/collide.cpp index 9ed690bb4..b5f4803f8 100644 --- a/similar/main/collide.cpp +++ b/similar/main/collide.cpp @@ -2078,9 +2078,6 @@ void apply_damage_to_player(const vobjptr_t playerobj, const cobjptridx_t killer Buddy_sorry_time = GameTime64; #endif } - - playerobj->shields = get_local_player_shields(); //mirror - } } diff --git a/similar/main/gameseq.cpp b/similar/main/gameseq.cpp index a8b36798c..7f3e31152 100644 --- a/similar/main/gameseq.cpp +++ b/similar/main/gameseq.cpp @@ -375,7 +375,8 @@ void init_player_stats_new_ship(ubyte pnum) { auto &plr = Players[pnum]; plr.energy = INITIAL_ENERGY; - plr.shields = StartingShields; + const auto &&plrobj = vobjptridx(plr.objnum); + plrobj->shields = StartingShields; const auto GrantedItems = (Game_mode & GM_MULTI) ? Netgame.SpawnGrantedItems : 0; const auto granted_primary_weapon_flags = map_granted_flags_to_primary_weapon_flags(GrantedItems); const auto granted_laser_level = map_granted_flags_to_laser_level(GrantedItems); @@ -461,7 +462,7 @@ void init_player_stats_new_ship(ubyte pnum) DXX_MAKE_VAR_UNDEFINED(Players[pnum].cloak_time); DXX_MAKE_VAR_UNDEFINED(Players[pnum].invulnerable_time); Players[pnum].homing_object_dist = -F1_0; // Added by RH - digi_kill_sound_linked_to_object(vcobjptridx(Players[pnum].objnum)); + digi_kill_sound_linked_to_object(plrobj); } #ifdef EDITOR diff --git a/similar/main/newdemo.cpp b/similar/main/newdemo.cpp index f962fc167..23c280e1f 100644 --- a/similar/main/newdemo.cpp +++ b/similar/main/newdemo.cpp @@ -542,8 +542,11 @@ object *prev_obj=NULL; //ptr to last object read in static void nd_read_object(const vobjptridx_t obj) { short shortsig = 0; + const auto &pl_shields = get_local_player_shields(); + const fix shields = (&pl_shields == &obj->shields) ? pl_shields : 0; *obj = {}; + obj->shields = shields; obj->next = obj->prev = object_none; obj->segnum = segment_none; diff --git a/similar/main/state.cpp b/similar/main/state.cpp index 7057e4116..15f13bd9d 100644 --- a/similar/main/state.cpp +++ b/similar/main/state.cpp @@ -462,7 +462,7 @@ static void state_object_rw_to_object(object_rw *obj_rw, const vobjptr_t obj) // Following functions convert player to player_rw and back to be written to/read from Savegames. player only differ to player_rw in terms of timer values (fix/fix64). as we reset GameTime64 for writing so it can fit into fix it's not necessary to increment savegame version. But if we once store something else into object which might be useful after restoring, it might be handy to increment Savegame version and actually store these new infos. // turn player to player_rw to be saved to Savegame. -static void state_player_to_player_rw(const player *pl, player_rw *pl_rw) +static void state_player_to_player_rw(const fix pl_shields, const player *pl, player_rw *pl_rw) { int i=0; pl_rw->callsign = pl->callsign; @@ -473,7 +473,7 @@ static void state_player_to_player_rw(const player *pl, player_rw *pl_rw) pl_rw->n_packets_sent = 0; pl_rw->flags = pl->flags.get_player_flags(); pl_rw->energy = pl->energy; - pl_rw->shields = pl->shields; + pl_rw->shields = pl_shields; pl_rw->lives = pl->lives; pl_rw->level = pl->level; pl_rw->laser_level = pl->laser_level; @@ -515,7 +515,7 @@ static void state_player_to_player_rw(const player *pl, player_rw *pl_rw) } // turn player_rw to player after reading from Savegame -static void state_player_rw_to_player(const player_rw *pl_rw, player *pl) +static void state_player_rw_to_player(const player_rw *pl_rw, player *pl, fix &pl_shields) { int i=0; pl->callsign = pl_rw->callsign; @@ -523,7 +523,7 @@ static void state_player_rw_to_player(const player_rw *pl_rw, player *pl) pl->objnum = pl_rw->objnum; pl->flags = player_flags(pl_rw->flags); pl->energy = pl_rw->energy; - pl->shields = pl_rw->shields; + pl_shields = pl_rw->shields; pl->lives = pl_rw->lives; pl->level = pl_rw->level; pl->laser_level = stored_laser_level(pl_rw->laser_level); @@ -557,19 +557,19 @@ static void state_player_rw_to_player(const player_rw *pl_rw, player *pl) pl->hours_total = pl_rw->hours_total; } -static void state_write_player(PHYSFS_file *fp, const player &pl) +static void state_write_player(PHYSFS_file *fp, const player &pl, const fix pl_shields) { player_rw pl_rw; - state_player_to_player_rw(&pl, &pl_rw); + state_player_to_player_rw(pl_shields, &pl, &pl_rw); PHYSFS_write(fp, &pl_rw, sizeof(pl_rw), 1); } -static void state_read_player(PHYSFS_file *fp, player &pl, int swap) +static void state_read_player(PHYSFS_file *fp, player &pl, int swap, fix &pl_shields) { player_rw pl_rw; PHYSFS_read(fp, &pl_rw, sizeof(pl_rw), 1); player_rw_swap(&pl_rw, swap); - state_player_rw_to_player(&pl_rw, &pl); + state_player_rw_to_player(&pl_rw, &pl, pl_shields); } namespace { @@ -987,7 +987,7 @@ int state_save_all_sub(const char *filename, const char *desc) //Save player info //PHYSFS_write(fp, &Players[Player_num], sizeof(player), 1); - state_write_player(fp, get_local_player()); + state_write_player(fp, get_local_player(), get_local_player_shields()); // Save the current weapon info PHYSFS_write(fp, &Primary_weapon, sizeof(sbyte), 1); @@ -1188,9 +1188,14 @@ int state_save_all_sub(const char *filename, const char *desc) // Save Coop Info if (Game_mode & GM_MULTI_COOP) { + /* Write local player's shields for everyone. Remote players' + * shields are ignored, and using local everywhere is cheaper + * than using it only for the one slot where it may matter. + */ + const auto shields = get_local_player_shields(); for (i = 0; i < MAX_PLAYERS; i++) // I know, I know we only allow 4 players in coop. I screwed that up. But if we ever allow 8 players in coop, who's gonna laugh then? { - state_write_player(fp, Players[i]); + state_write_player(fp, Players[i], shields); } PHYSFS_write(fp, Netgame.mission_title.data(), Netgame.mission_title.size(), 1); PHYSFS_write(fp, Netgame.mission_name.data(), Netgame.mission_name.size(), 1); @@ -1421,13 +1426,14 @@ int state_restore_all_sub(const char *filename, const secret_restore secret) //Read player info + fix pl_shields; { StartNewLevelSub(current_level, 1, secret); #if defined(DXX_BUILD_DESCENT_II) if (secret != secret_restore::none) { player dummy_player; - state_read_player(fp, dummy_player, swap); + state_read_player(fp, dummy_player, swap, pl_shields); if (secret == secret_restore::survived) { // This means he didn't die, so he keeps what he got in the secret level. get_local_player().level = dummy_player.level; get_local_player().last_score = dummy_player.last_score; @@ -1449,7 +1455,7 @@ int state_restore_all_sub(const char *filename, const secret_restore secret) } else #endif { - state_read_player(fp, get_local_player(), swap); + state_read_player(fp, get_local_player(), swap, pl_shields); } } get_local_player().callsign = org_callsign; @@ -1521,6 +1527,7 @@ int state_restore_all_sub(const char *filename, const secret_restore secret) #endif } special_reset_objects(); + get_local_player_shields() = pl_shields; // 1 = Didn't die on secret level. // 2 = Died on secret level. @@ -1773,12 +1780,14 @@ int state_restore_all_sub(const char *filename, const secret_restore secret) coop_player_got[i] = 0; // read the stored players - state_read_player(fp, restore_players[i], swap); + fix shields; + state_read_player(fp, restore_players[i], swap, shields); // make all (previous) player objects to ghosts but store them first for later remapping const auto &&obj = vobjptr(restore_players[i].objnum); if (restore_players[i].connected == CONNECT_PLAYING && obj->type == OBJ_PLAYER) { + obj->shields = shields; restore_objects[i] = *obj; obj->type = OBJ_GHOST; multi_reset_player_object(obj);