Skip to content

Commit dab690e

Browse files
authored
Merge pull request scp-fs2open#7600 from Goober5000/fix/ship_demotion
fix a bug with player ships being demoted to common ships
2 parents 5c17ab6 + 7d5bab2 commit dab690e

11 files changed

Lines changed: 61 additions & 50 deletions

File tree

code/missioneditor/common.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// methods and members common to any mission editor FSO may have
22
#include "common.h"
3+
#include "globalincs/linklist.h"
34
#include "mission/missionparse.h"
45
#include "iff_defs/iff_defs.h"
6+
#include "object/object.h"
57
#include "ship/ship.h"
68

79
// to keep track of data
@@ -145,3 +147,22 @@ void generate_weaponry_usage_list_wing(int wing_num, int* arr)
145147
}
146148
}
147149
}
150+
151+
void ensure_valid_player_start_shipnum()
152+
{
153+
// nothing to do if the current player start is still valid
154+
if (Player_start_shipnum >= 0 && Player_start_shipnum < MAX_SHIPS
155+
&& Ships[Player_start_shipnum].objnum >= 0
156+
&& Objects[Ships[Player_start_shipnum].objnum].type == OBJ_START) {
157+
return;
158+
}
159+
160+
// otherwise repoint to the first remaining player start, or -1 if there are none
161+
Player_start_shipnum = -1;
162+
for (auto *objp : list_range(&obj_used_list)) {
163+
if (objp->type == OBJ_START) {
164+
Player_start_shipnum = objp->instance;
165+
break;
166+
}
167+
}
168+
}

code/missioneditor/common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,8 @@ anchor_t target_to_anchor(int target);
4848
void generate_weaponry_usage_list_team(int team, int* arr);
4949

5050
void generate_weaponry_usage_list_wing(int wing_num, int* arr);
51+
52+
// If Player_start_shipnum no longer refers to a valid player start ship, repoint it to the
53+
// first remaining player start in the mission (or -1 if there are none). Call this after
54+
// changing a ship to or from an OBJ_START via demotion, deletion, etc.
55+
void ensure_valid_player_start_shipnum();

code/missioneditor/missionsave.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4393,8 +4393,7 @@ int Fred_mission_save::save_players()
43934393
for (i = 0; i < Num_teams; i++) {
43944394
required_string_fred("$Starting Shipname:");
43954395
parse_comments();
4396-
Assert(Player_start_shipnum >= 0);
4397-
fout(" %s", Ships[Player_start_shipnum].ship_name);
4396+
fout(" %s", (Player_start_shipnum >= 0) ? Ships[Player_start_shipnum].ship_name : "<none>");
43984397

43994398
if (save_config.save_format != MissionFormat::RETAIL) {
44004399
if (Team_data[i].do_not_validate) {

fred2/fredview.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "ai/aigoals.h"
3333
#include "ship/ship.h" // for ship names
3434
#include "prop/prop.h" // for prop names
35+
#include "missioneditor/common.h"
3536
#include "MissionGoalsDlg.h"
3637
#include "MissionCutscenesDlg.h"
3738
#include "wing.h"
@@ -2641,6 +2642,9 @@ int CFREDView::global_error_check()
26412642
ptr->type = OBJ_SHIP;
26422643
Player_starts--;
26432644
t--;
2645+
2646+
ensure_valid_player_start_shipnum();
2647+
26442648
if (error("Invalid ship type for a player. Ship has been reset to non-player ship.")){
26452649
return 1;
26462650
}
@@ -3130,7 +3134,9 @@ int CFREDView::global_error_check()
31303134
return -1;
31313135
}*/
31323136

3133-
Assert((Player_start_shipnum >= 0) && (Player_start_shipnum < MAX_SHIPS) && (Ships[Player_start_shipnum].objnum >= 0));
3137+
if ((Player_start_shipnum < 0) || (Player_start_shipnum >= MAX_SHIPS) || (Ships[Player_start_shipnum].objnum < 0)){
3138+
return internal_error("Mission has no valid player start ship");
3139+
}
31343140
i = global_error_check_player_wings(multi);
31353141
if (i){
31363142
return i;

fred2/management.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,6 @@ int common_object_delete(int obj)
12351235
char msg[255];
12361236
const char *name;
12371237
int i, z, r, type;
1238-
object *objp;
12391238
SCP_list<CJumpNode>::iterator jnp;
12401239

12411240
type = Objects[obj].type;
@@ -1271,17 +1270,7 @@ int common_object_delete(int obj)
12711270
ai_do_objects_undocked_stuff(&Objects[obj], dock_get_first_docked_object(&Objects[obj]));
12721271
}
12731272

1274-
if (Player_start_shipnum == i) { // need a new single player start.
1275-
objp = GET_FIRST(&obj_used_list);
1276-
while (objp != END_OF_LIST(&obj_used_list)) {
1277-
if (objp->type == OBJ_START) {
1278-
Player_start_shipnum = objp->instance;
1279-
break;
1280-
}
1281-
1282-
objp = GET_NEXT(objp);
1283-
}
1284-
}
1273+
ensure_valid_player_start_shipnum(); // may need a new single player start
12851274

12861275
Player_starts--;
12871276

fred2/shipeditordlg.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,17 +1258,7 @@ int CShipEditorDlg::update_data(int redraw)
12581258
}
12591259
}
12601260

1261-
if (Player_start_shipnum < 0 || Objects[Ships[Player_start_shipnum].objnum].type != OBJ_START) { // need a new single player start.
1262-
ptr = GET_FIRST(&obj_used_list);
1263-
while (ptr != END_OF_LIST(&obj_used_list)) {
1264-
if (ptr->type == OBJ_START) {
1265-
Player_start_shipnum = ptr->instance;
1266-
break;
1267-
}
1268-
1269-
ptr = GET_NEXT(ptr);
1270-
}
1271-
}
1261+
ensure_valid_player_start_shipnum(); // may need a new single player start
12721262

12731263
if (modified)
12741264
set_modified();
@@ -1518,7 +1508,9 @@ int CShipEditorDlg::update_ship(int ship)
15181508

15191509
Objects[Ships[ship].objnum].type = OBJ_SHIP;
15201510
break;
1521-
}
1511+
}
1512+
1513+
ensure_valid_player_start_shipnum();
15221514

15231515
Update_ship = 1;
15241516
return 0;
@@ -2448,19 +2440,32 @@ void CShipEditorDlg::OnSetAsPlayerShip()
24482440
if (objp->flags[Object::Object_Flags::Marked]) // there should only be one selected ship
24492441
{
24502442
// set as player ship
2443+
if (objp->type != OBJ_START)
2444+
{
2445+
Player_starts++;
2446+
set_modified();
2447+
}
24512448
objp->type = OBJ_START;
24522449
objp->flags.set(Object::Object_Flags::Player_ship);
24532450
}
24542451
else
24552452
{
24562453
// set as regular ship
2454+
if (objp->type == OBJ_START)
2455+
{
2456+
Player_starts--;
2457+
set_modified();
2458+
}
24572459
objp->type = OBJ_SHIP;
24582460
objp->flags.remove(Object::Object_Flags::Player_ship);
24592461
}
24602462
}
24612463
objp = GET_NEXT(objp);
24622464
}
24632465

2466+
// fix up Player_start_shipnum if it became invalid
2467+
ensure_valid_player_start_shipnum();
2468+
24642469
// finally set editor dialog
24652470
m_player_ship.SetCheck(1);
24662471
update_map_window();

fred2/wing.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ int create_wing() {
227227
}
228228

229229
count = 0;
230-
if (Objects[Ships[Player_start_shipnum].objnum].flags[Object::Object_Flags::Marked])
230+
if ((Player_start_shipnum >= 0) && (Player_start_shipnum < MAX_SHIPS) && (Ships[Player_start_shipnum].objnum >= 0)
231+
&& Objects[Ships[Player_start_shipnum].objnum].flags[Object::Object_Flags::Marked])
231232
count = 1;
232233

233234
ptr = GET_FIRST(&obj_used_list);

qtfred/src/mission/Editor.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,6 @@ int Editor::common_object_delete(int obj) {
974974
char msg[255];
975975
const char *name;
976976
int i, z, r, type;
977-
object* objp;
978977
SCP_list<CJumpNode>::iterator jnp;
979978

980979
type = Objects[obj].type;
@@ -1013,17 +1012,7 @@ int Editor::common_object_delete(int obj) {
10131012
ai_do_objects_undocked_stuff(&Objects[obj], dock_get_first_docked_object(&Objects[obj]));
10141013
}
10151014

1016-
if (Player_start_shipnum == i) { // need a new single player start.
1017-
objp = GET_FIRST(&obj_used_list);
1018-
while (objp != END_OF_LIST(&obj_used_list)) {
1019-
if (objp->type == OBJ_START) {
1020-
Player_start_shipnum = objp->instance;
1021-
break;
1022-
}
1023-
1024-
objp = GET_NEXT(objp);
1025-
}
1026-
}
1015+
ensure_valid_player_start_shipnum(); // may need a new single player start
10271016

10281017
Player_starts--;
10291018

qtfred/src/mission/EditorWing.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ int Editor::create_wing()
240240
}
241241

242242
count = 0;
243-
if (Objects[Ships[Player_start_shipnum].objnum].flags[Object::Object_Flags::Marked]) {
243+
if ((Player_start_shipnum >= 0) && (Player_start_shipnum < MAX_SHIPS) && (Ships[Player_start_shipnum].objnum >= 0)
244+
&& Objects[Ships[Player_start_shipnum].objnum].flags[Object::Object_Flags::Marked]) {
244245
count = 1;
245246
}
246247

qtfred/src/mission/dialogs/ShipEditor/ShipEditorDialogModel.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,15 +1150,8 @@ void ShipEditorDialogModel::setPlayer(const bool m_player)
11501150
}
11511151
}
11521152
}
1153-
// Fix up Player_start_shipnum if it became invalid
1154-
if (Player_start_shipnum < 0 || Objects[Ships[Player_start_shipnum].objnum].type != OBJ_START) {
1155-
for (auto* p = GET_FIRST(&obj_used_list); p != END_OF_LIST(&obj_used_list); p = GET_NEXT(p)) {
1156-
if (p->type == OBJ_START) {
1157-
Player_start_shipnum = p->instance;
1158-
break;
1159-
}
1160-
}
1161-
}
1153+
// fix up Player_start_shipnum if it became invalid
1154+
ensure_valid_player_start_shipnum();
11621155
setModified();
11631156
_editor->missionChanged();
11641157
modelChanged();

0 commit comments

Comments
 (0)