Skip to content
Merged
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
54 changes: 51 additions & 3 deletions code/missioneditor/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,64 @@ void ensure_valid_player_start_shipnum()
// nothing to do if the current player start is still valid
if (Player_start_shipnum >= 0 && Player_start_shipnum < MAX_SHIPS
&& Ships[Player_start_shipnum].objnum >= 0
&& Objects[Ships[Player_start_shipnum].objnum].type == OBJ_START) {
&& Objects[Ships[Player_start_shipnum].objnum].type == OBJ_START)
{
return;
}

// otherwise repoint to the first remaining player start, or -1 if there are none
Player_start_shipnum = -1;
for (auto *objp : list_range(&obj_used_list)) {
if (objp->type == OBJ_START) {
for (auto *objp : list_range(&obj_used_list))
{
if (objp->type == OBJ_START)
{
Player_start_shipnum = objp->instance;
break;
}
}
}

bool set_single_player_start(int objnum)
{
if (objnum < 0 || objnum >= MAX_OBJECTS
|| (Objects[objnum].type != OBJ_SHIP && Objects[objnum].type != OBJ_START))
{
Assertion(false, "set_single_player_start() called for object %d, which is not a ship", objnum);
return false;
}

bool changed = false;

for (auto *objp : list_range(&obj_used_list))
{
if (objp->type != OBJ_SHIP && objp->type != OBJ_START)
continue;

if (OBJ_INDEX(objp) == objnum)
{
// set as player ship
if (objp->type != OBJ_START)
{
objp->type = OBJ_START;
Player_starts++;
changed = true;
}
objp->flags.set(Object::Object_Flags::Player_ship);
}
else
{
// set as regular ship
if (objp->type == OBJ_START)
{
objp->type = OBJ_SHIP;
Player_starts--;
changed = true;
}
objp->flags.remove(Object::Object_Flags::Player_ship);
}
}

ensure_valid_player_start_shipnum();

return changed;
}
5 changes: 5 additions & 0 deletions code/missioneditor/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,8 @@ void generate_weaponry_usage_list_wing(int wing_num, int* arr);
// first remaining player start in the mission (or -1 if there are none). Call this after
// changing a ship to or from an OBJ_START via demotion, deletion, etc.
void ensure_valid_player_start_shipnum();

// Make the given object the sole player start, per single-player semantics: promote it to
// OBJ_START, demote every other player start to OBJ_SHIP, adjust Player_starts to match,
// and repoint Player_start_shipnum. Returns true if anything changed.
bool set_single_player_start(int objnum);
40 changes: 11 additions & 29 deletions fred2/shipeditordlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2431,40 +2431,22 @@ void CShipEditorDlg::OnSetAsPlayerShip()
return;
}

// since this is single player, clear all player ships and set only this one
object *objp = GET_FIRST(&obj_used_list);
while (objp != END_OF_LIST(&obj_used_list))
// find the selected ship; there should only be one
object *marked_objp = nullptr;
for (auto objp: list_range(&obj_used_list))
{
if ((objp->type == OBJ_SHIP) || (objp->type == OBJ_START))
if (((objp->type == OBJ_SHIP) || (objp->type == OBJ_START)) && objp->flags[Object::Object_Flags::Marked])
{
if (objp->flags[Object::Object_Flags::Marked]) // there should only be one selected ship
{
// set as player ship
if (objp->type != OBJ_START)
{
Player_starts++;
set_modified();
}
objp->type = OBJ_START;
objp->flags.set(Object::Object_Flags::Player_ship);
}
else
{
// set as regular ship
if (objp->type == OBJ_START)
{
Player_starts--;
set_modified();
}
objp->type = OBJ_SHIP;
objp->flags.remove(Object::Object_Flags::Player_ship);
}
marked_objp = objp;
break;
}
objp = GET_NEXT(objp);
}
if (marked_objp == nullptr)
return;

// fix up Player_start_shipnum if it became invalid
ensure_valid_player_start_shipnum();
// since this is single player, clear all player ships and set only this one
if (set_single_player_start(OBJ_INDEX(marked_objp)))
set_modified();

// finally set editor dialog
m_player_ship.SetCheck(1);
Expand Down
18 changes: 18 additions & 0 deletions qtfred/src/mission/dialogs/ShipEditor/ShipEditorDialogModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,24 @@ bool ShipEditorDialogModel::getPlayer() const
return _isPlayerShip;
}

void ShipEditorDialogModel::makeSolePlayerStart()
{
// the ship being edited, which is either a player start or a regular ship
int shipnum = (_playerShipIndex >= 0) ? _playerShipIndex : _singleShip;
if (shipnum < 0)
return;

// since this is single player, clear all player ships and set only this one
if (set_single_player_start(Ships[shipnum].objnum))
{
setModified();
_editor->missionChanged();
}

_isPlayerShip = true;
modelChanged();
}

void ShipEditorDialogModel::setRespawn(const int value)
{
if (_respawnPriority == value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class ShipEditorDialogModel : public AbstractDialogModel {

void setPlayer(bool isPlayer);
bool getPlayer() const;
void makeSolePlayerStart();

void setRespawn(int respawn);
int getRespawn() const;
Expand Down
2 changes: 1 addition & 1 deletion qtfred/src/ui/dialogs/ShipEditor/ShipEditorDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ void ShipEditorDialog::on_textureReplacementButton_clicked()

void ShipEditorDialog::on_playerShipButton_clicked()
{
_model->setPlayer(true);
_model->makeSolePlayerStart();
}
void ShipEditorDialog::on_altShipClassButton_clicked()
{
Expand Down
Loading