Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions code/menuui/readyroom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1575,22 +1575,40 @@ void campaign_room_scroll_info_down()

void campaign_reset(const SCP_string& campaign_file)
{
Assert(Player != nullptr);

// if the caller is resetting a campaign other than the active one (only reachable via the Lua resetCampaign API),
// we can't go through mission_campaign_load(): that would swap the global Campaign struct over to the target
// campaign and overwrite Player->stats with the wrong running totals. Just delete the CSG; the next time the
// player activates this campaign, mission_campaign_load() will recreate a fresh one.
if (stricmp(campaign_file.c_str(), Campaign.filename) != 0) {
mission_campaign_savefile_delete(campaign_file.c_str());
return;
}

// note: we do not toss all-time stats from player's performance in campaign up till now
// save stats before the reset because csg_reset_data() will zero them when the deleted CSG is not found
scoring_struct saved_stats = Player->stats;

mission_campaign_savefile_delete(campaign_file.c_str());

const int load_status = mission_campaign_load(campaign_file.c_str(), nullptr, nullptr, 1);

// restore the stats that were cleared during the campaign reload
Player->stats = saved_stats;

// see if we successfully loaded this campaign
if (load_status == 0) {
// Goober5000 - reinitialize tech database if needed
if ((Campaign.flags & CF_CUSTOM_TECH_DATABASE) || !stricmp(Campaign.filename, "freespace2")) {
// reset tech database to what's in the tables
tech_reset_to_default();

// write the savefile so that we don't later load a stale techroom
Pilot.save_savefile();
}

// re-save the savefile so the CSG persists the restored stats (and the tech database reset, if applicable);
// mission_campaign_load() already wrote a fresh CSG with zeroed stats when it found no existing savefile
Pilot.save_savefile();

if (OnCampaignBeginHook->isActive()) {
OnCampaignBeginHook->run(scripting::hook_param_list(scripting::hook_param("Campaign", 's', Campaign.filename)));
}
Expand Down
2 changes: 1 addition & 1 deletion code/playerman/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class player
int objnum; // object number for this player
button_info bi; // structure that holds bit vectors for button presses
control_info ci; // control info structure for this player
scoring_struct stats; // scoring and stats info for the player (points to multi_stats or single_stats)
scoring_struct stats; // scoring and stats info for the player that are currently accumulating; loaded from multi_stats or all_time_stats

int friendly_hits; // Number of times hit a friendly ship this mission.
float friendly_damage; // Total friendly damage done in mission. Diminishes over time.
Expand Down
5 changes: 4 additions & 1 deletion code/scripting/api/objs/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,17 @@ player_h& player_h::operator=(player_h&& other) noexcept
ADE_OBJ(l_Player, player_h, "player", "Player handle");


ADE_VIRTVAR(Stats, l_Player, "scoring_stats stats", "The scoring stats of this player (read-only)", "scoring_stats", "The player stats or invalid handle") {
ADE_VIRTVAR(Stats, l_Player, "scoring_stats stats", "The scoring stats of this player that are currently accumulating, e.g. from a campaign or multiplayer session; read-only", "scoring_stats", "The player stats or invalid handle") {
player_h* plr;
if (!ade_get_args(L, "o", l_Player.GetPtr(&plr)))
return ade_set_error(L, "o", l_ScoringStats.Set(scoring_stats_h()));

if (!plr->isValid())
return ade_set_error(L, "o", l_ScoringStats.Set(scoring_stats_h()));

if (ADE_SETTING_VAR)
LuaError(L, "This property is read only.");

return ade_set_args(L, "o", l_ScoringStats.Set(scoring_stats_h(plr->get()->stats, plr->get())));
}

Expand Down
Loading