Skip to content

Commit 10f484a

Browse files
authored
Merge pull request #5649 from Goober5000/fix_ship_status
fix ShipStatus states to correctly account for exploding ships
2 parents f0c8c9a + b6c0e8b commit 10f484a

File tree

8 files changed

+58
-48
lines changed

8 files changed

+58
-48
lines changed

code/ai/aicode.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ int is_preferred_weapon(int weapon_num, object *firer_objp, object *target_objp)
386386
continue;
387387

388388
auto ship_entry = &Ship_registry[hfi->ship_registry_index];
389-
if (ship_entry->status != ShipStatus::PRESENT)
389+
if (!ship_entry->objp)
390390
continue;
391391

392392
int signature = ship_entry->objp->signature;

code/ai/aigoals.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
976976
// this goal needs some extra setup
977977
// if this doesn't work, the goal will be immediately removed
978978
auto ship_entry = ship_registry_get(aigp->target_name);
979-
if (ship_entry->status == ShipStatus::PRESENT)
979+
if (ship_entry->shipp)
980980
{
981981
auto target_aip = &Ai_info[ship_entry->shipp->ai_index];
982982
target_aip->ai_flags.set(AI::AI_Flags::Awaiting_repair);
@@ -1797,7 +1797,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
17971797
status = SHIP_STATUS_UNKNOWN;
17981798
}
17991799
// goal ship is currently in mission
1800-
else if (ship_entry->status == ShipStatus::PRESENT)
1800+
else if (ship_entry->status == ShipStatus::PRESENT || ship_entry->status == ShipStatus::DEATH_ROLL)
18011801
{
18021802
status = SHIP_STATUS_ARRIVED;
18031803
}

code/mission/missiontraining.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ void message_training_queue_check()
922922
auto ship_entry = ship_registry_get(NOX("instructor"));
923923
if (ship_entry != nullptr)
924924
{
925-
if (ship_entry->status == ShipStatus::PRESENT)
925+
if (ship_entry->shipp != nullptr)
926926
{
927927
// if the instructor is dying or departing, do nothing
928928
if (ship_entry->shipp->is_dying_or_departing())

code/parse/sexp.cpp

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6585,6 +6585,7 @@ void eval_object_ship_wing_point_team(object_ship_wing_point_team *oswpt, int no
65856585
break;
65866586

65876587
case ShipStatus::PRESENT:
6588+
case ShipStatus::DEATH_ROLL:
65886589
oswpt->type = OSWPT_TYPE_SHIP;
65896590
break;
65906591

@@ -6853,7 +6854,7 @@ int sexp_is_destroyed(int n, fix *latest_time)
68536854
if (ship_entry->status == ShipStatus::NOT_YET_PRESENT)
68546855
return SEXP_CANT_EVAL;
68556856

6856-
if (ship_entry->status == ShipStatus::EXITED)
6857+
if (ship_entry->status == ShipStatus::DEATH_ROLL || ship_entry->status == ShipStatus::EXITED)
68576858
{
68586859
// check the mission log
68596860
if (mission_log_get_time(LOG_SHIP_DESTROYED, ship_entry->name, nullptr, &time) || mission_log_get_time(LOG_SELF_DESTRUCTED, ship_entry->name, nullptr, &time))
@@ -7301,7 +7302,7 @@ int sexp_was_destroyed_by(int n, fix *latest_time)
73017302
*latest_time = time;
73027303
}
73037304
// if the ship has exited, no way to destroy it
7304-
else if (ship_entry->status == ShipStatus::EXITED)
7305+
else if (destroyed_ship_entry->status == ShipStatus::EXITED)
73057306
return SEXP_KNOWN_FALSE;
73067307
}
73077308

@@ -7526,7 +7527,14 @@ int sexp_time_exited(int n, int op_num)
75267527
if (ship)
75277528
{
75287529
auto ship_entry = eval_ship(n);
7529-
if (!ship_entry || ship_entry->status != ShipStatus::EXITED)
7530+
if (!ship_entry)
7531+
return SEXP_NAN;
7532+
if (ship_entry->status == ShipStatus::DEATH_ROLL)
7533+
{
7534+
if (!destroyed)
7535+
return SEXP_NAN;
7536+
}
7537+
else if (ship_entry->status != ShipStatus::EXITED)
75307538
return SEXP_NAN;
75317539

75327540
if (destroyed)
@@ -8784,7 +8792,8 @@ int sexp_angle_vectors(int node) {
87848792
return fl2ir(angle);
87858793
}
87868794

8787-
int sexp_angle_fvec_target(int node) {
8795+
int sexp_angle_fvec_target(int node)
8796+
{
87888797
auto* ship = eval_ship(node);
87898798

87908799
if (ship->status == ShipStatus::EXITED)
@@ -9412,7 +9421,7 @@ int sexp_last_order_time(int n)
94129421

94139422
auto ship_entry = eval_ship(n);
94149423
if (ship_entry) {
9415-
if (ship_entry->status == ShipStatus::PRESENT) {
9424+
if (ship_entry->shipp) {
94169425
aigp = Ai_info[ship_entry->shipp->ai_index].goals;
94179426
}
94189427
} else {
@@ -9785,7 +9794,7 @@ int sexp_destroyed_departed_delay(int n)
97859794
return SEXP_CANT_EVAL;
97869795
}
97879796

9788-
if (ship_entry->status == ShipStatus::EXITED) {
9797+
if (ship_entry->status == ShipStatus::DEATH_ROLL || ship_entry->status == ShipStatus::EXITED) {
97899798
if (mission_log_get_time(LOG_SHIP_DEPARTED, ship_entry->name, nullptr, &time_gone)) {
97909799
count++;
97919800
} else if (mission_log_get_time(LOG_SHIP_DESTROYED, ship_entry->name, nullptr, &time_gone)) {
@@ -11847,6 +11856,8 @@ int sexp_is_iff(int n)
1184711856
// ship is in the EXITED state but probably in the process of exploding
1184811857
else if (oswpt.ship_entry->shipp)
1184911858
{
11859+
UNREACHABLE("With the addition of the ShipStatus::DEATH_ROLL state, this shouldn't happen");
11860+
1185011861
// if the team doesn't match the team specified, return false immediately
1185111862
if (oswpt.ship_entry->shipp->team != team)
1185211863
return SEXP_KNOWN_FALSE;
@@ -12335,7 +12346,7 @@ void sexp_add_goal(int n)
1233512346
auto ship_entry = eval_ship(n);
1233612347
if (ship_entry)
1233712348
{
12338-
if (ship_entry->status != ShipStatus::PRESENT)
12349+
if (!ship_entry->shipp)
1233912350
return; // ship not around anymore???? then forget it!
1234012351

1234112352
ai_add_ship_goal_sexp(goal_node, AIG_TYPE_EVENT_SHIP, &(Ai_info[ship_entry->shipp->ai_index]));
@@ -12362,7 +12373,7 @@ void sexp_remove_goal(int n)
1236212373
auto ship_entry = eval_ship(n);
1236312374
if (ship_entry)
1236412375
{
12365-
if (ship_entry->status != ShipStatus::PRESENT)
12376+
if (!ship_entry->shipp)
1236612377
return; // ship not around anymore???? then forget it!
1236712378

1236812379
int goalindex = ai_remove_goal_sexp_sub(goal_node, Ai_info[ship_entry->shipp->ai_index].goals);
@@ -12394,7 +12405,7 @@ void sexp_clear_goals(int n)
1239412405
auto ship_entry = eval_ship(n);
1239512406
if (ship_entry)
1239612407
{
12397-
if (ship_entry->status != ShipStatus::PRESENT)
12408+
if (!ship_entry->shipp)
1239812409
continue; // ship not around anymore???? then forget it!
1239912410

1240012411
ai_clear_ship_goals(&(Ai_info[ship_entry->shipp->ai_index]));
@@ -16225,7 +16236,7 @@ void sexp_deal_with_ship_flag(int node, bool process_subsequent_nodes, Object::O
1622516236
continue;
1622616237

1622716238
// if ship is in-mission
16228-
if (ship_entry->status == ShipStatus::PRESENT)
16239+
if (ship_entry->shipp)
1622916240
{
1623016241
// save flags for state change comparisons
1623116242
auto object_flag_orig = ship_entry->objp->flags;
@@ -20181,23 +20192,20 @@ void sexp_set_alphamult(int n)
2018120192
case OSWPT_TYPE_SHIP:
2018220193
{
2018320194
auto ship_entry = oswpt.ship_entry;
20195+
ship* shipp = ship_entry->shipp;
2018420196

20185-
if (ship_entry->status == ShipStatus::PRESENT)
20186-
{
20187-
ship* shipp = ship_entry->shipp;
20188-
shipp->flags.remove(Ship::Ship_Flags::Cloaked);
20189-
if (newAlpha >= 100) {
20190-
shipp->alpha_mult = 1.0f;
20191-
shipp->flags.remove(Ship::Ship_Flags::Render_with_alpha_mult);
20192-
}
20193-
else if (newAlpha <= 0) {
20194-
shipp->alpha_mult = 0.0f;
20195-
shipp->flags.set(Ship::Ship_Flags::Cloaked);
20196-
}
20197-
else {
20198-
shipp->alpha_mult = ((float)newAlpha) / 100.f;
20199-
shipp->flags.set(Ship::Ship_Flags::Render_with_alpha_mult);
20200-
}
20197+
shipp->flags.remove(Ship::Ship_Flags::Cloaked);
20198+
if (newAlpha >= 100) {
20199+
shipp->alpha_mult = 1.0f;
20200+
shipp->flags.remove(Ship::Ship_Flags::Render_with_alpha_mult);
20201+
}
20202+
else if (newAlpha <= 0) {
20203+
shipp->alpha_mult = 0.0f;
20204+
shipp->flags.set(Ship::Ship_Flags::Cloaked);
20205+
}
20206+
else {
20207+
shipp->alpha_mult = ((float)newAlpha) / 100.f;
20208+
shipp->flags.set(Ship::Ship_Flags::Render_with_alpha_mult);
2020120209
}
2020220210
break;
2020320211
}
@@ -20307,7 +20315,7 @@ void sexp_ship_copy_damage(int node)
2030720315
continue;
2030820316

2030920317
// maybe it's present in-mission
20310-
if (target->status == ShipStatus::PRESENT)
20318+
if (target->shipp)
2031120319
{
2031220320
ship_copy_damage(target->shipp, source->shipp);
2031320321
continue;
@@ -25709,7 +25717,7 @@ int sexp_is_in_mission(int node)
2570925717
{
2571025718
// For this sexp, we do not short-circuit known-true or known-false.
2571125719
auto ship_entry = eval_ship(n);
25712-
if (!ship_entry || ship_entry->status != ShipStatus::PRESENT)
25720+
if (!ship_entry || !ship_entry->shipp)
2571325721
return SEXP_FALSE;
2571425722
}
2571525723

@@ -25718,7 +25726,6 @@ int sexp_is_in_mission(int node)
2571825726

2571925727
int sexp_has_armor_type(int node)
2572025728
{
25721-
2572225729
// get ship from sexp
2572325730
auto ship_entry = eval_ship(node);
2572425731
if (!ship_entry || ship_entry->status == ShipStatus::NOT_YET_PRESENT)
@@ -25808,7 +25815,7 @@ void sexp_manipulate_colgroup(int node, bool add_to_group)
2580825815
return;
2580925816
node = CDR(node);
2581025817

25811-
int colgroup_id = (ship_entry->status == ShipStatus::PRESENT)
25818+
int colgroup_id = (ship_entry->objp)
2581225819
? ship_entry->objp->collision_group_id
2581325820
: ship_entry->p_objp->collision_group_id;
2581425821

@@ -25830,7 +25837,7 @@ void sexp_manipulate_colgroup(int node, bool add_to_group)
2583025837
}
2583125838
}
2583225839

25833-
if (ship_entry->status == ShipStatus::PRESENT)
25840+
if (ship_entry->objp)
2583425841
ship_entry->objp->collision_group_id = colgroup_id;
2583525842
else
2583625843
ship_entry->p_objp->collision_group_id = colgroup_id;
@@ -25856,7 +25863,7 @@ void sexp_manipulate_colgroup_new(int node, bool add_to_group)
2585625863
if (!ship_entry || ship_entry->status == ShipStatus::EXITED)
2585725864
continue;
2585825865

25859-
if (ship_entry->status == ShipStatus::PRESENT)
25866+
if (ship_entry->objp)
2586025867
{
2586125868
if (add_to_group)
2586225869
ship_entry->objp->collision_group_id |= (1 << group);
@@ -25881,7 +25888,7 @@ int sexp_get_colgroup(int node)
2588125888
if (ship_entry->status == ShipStatus::EXITED)
2588225889
return SEXP_NAN_FOREVER;
2588325890

25884-
if (ship_entry->status == ShipStatus::PRESENT)
25891+
if (ship_entry->objp)
2588525892
return ship_entry->objp->collision_group_id;
2588625893
else
2588725894
return ship_entry->p_objp->collision_group_id;

code/parse/sexp/LuaSEXP.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ luacpp::LuaValue LuaSEXP::sexpToLua(int node, int argnum, int parent_node) const
176176
return LuaValue::createValue(_action.getLuaState(), ship_entry ? ship_entry->name : "");
177177
}
178178

179-
if (!ship_entry || ship_entry->status != ShipStatus::PRESENT) {
179+
if (!ship_entry || !ship_entry->objp) {
180180
// Name is invalid
181181
return LuaValue::createValue(_action.getLuaState(), l_Ship.Set(object_h()));
182182
}
@@ -256,7 +256,7 @@ luacpp::LuaValue LuaSEXP::sexpToLua(int node, int argnum, int parent_node) const
256256

257257
auto ship_entry = eval_ship(this_node);
258258

259-
if (!ship_entry || ship_entry->status != ShipStatus::PRESENT) {
259+
if (!ship_entry || !ship_entry->shipp) {
260260
// Name is invalid
261261
return LuaValue::createValue(_action.getLuaState(), l_Ship.Set(object_h()));
262262
}
@@ -284,7 +284,7 @@ luacpp::LuaValue LuaSEXP::sexpToLua(int node, int argnum, int parent_node) const
284284
}
285285

286286
auto ship_entry = eval_ship(this_node);
287-
if (!ship_entry || ship_entry->status != ShipStatus::PRESENT) {
287+
if (!ship_entry || !ship_entry->shipp) {
288288
// Name is invalid
289289
return LuaValue::createValue(_action.getLuaState(), l_Ship.Set(object_h()));
290290
}

code/playerman/playercontrol.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,7 +1768,7 @@ void player_generate_death_message(player *player_p)
17681768

17691769
// killer_parent_name is always a ship name or a callsign (or blank). If it's a ship name, get the ship and use the ship's display name
17701770
auto ship_entry = ship_registry_get(player_p->killer_parent_name);
1771-
auto killer_display_name = (ship_entry != nullptr && ship_entry->status == ShipStatus::PRESENT) ? ship_entry->shipp->get_display_name() : player_p->killer_parent_name;
1771+
auto killer_display_name = (ship_entry && ship_entry->shipp) ? ship_entry->shipp->get_display_name() : player_p->killer_parent_name;
17721772

17731773
switch (player_p->killer_objtype)
17741774
{
@@ -1785,7 +1785,7 @@ void player_generate_death_message(player *player_p)
17851785

17861786
case OBJ_WEAPON:
17871787
// is this from a friendly ship?
1788-
if ((ship_entry != nullptr) && (ship_entry->status == ShipStatus::PRESENT) && (Player_ship != nullptr) && (Player_ship->team == ship_entry->shipp->team))
1788+
if (ship_entry && ship_entry->shipp && Player_ship && (Player_ship->team == ship_entry->shipp->team))
17891789
{
17901790
sprintf(msg, XSTR( "%s was killed by friendly fire from %s", 1338), player_p->callsign, killer_display_name);
17911791
}
@@ -1827,7 +1827,7 @@ void player_generate_death_message(player *player_p)
18271827
else
18281828
{
18291829
// is this from a friendly ship?
1830-
if ((ship_entry != nullptr) && (ship_entry->status == ShipStatus::PRESENT) && (Player_ship != nullptr) && (Player_ship->team == ship_entry->shipp->team))
1830+
if (ship_entry && ship_entry->shipp && Player_ship && (Player_ship->team == ship_entry->shipp->team))
18311831
{
18321832
sprintf(msg, XSTR( "%s was destroyed by friendly beam fire from %s", 1339), player_p->callsign, killer_display_name);
18331833
}

code/ship/ship.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -909,10 +909,13 @@ enum class ShipStatus
909909
// A ship is currently in-mission, and its objp and shipp pointers are valid
910910
PRESENT,
911911

912-
// A ship is destroyed, departed, or vanished. Note however that for destroyed ships,
913-
// ship_cleanup is not called until the death roll is complete, which means there is a
914-
// period of time where the ship is "exited", but objp and shipp are still valid and
915-
// exited_index is not yet assigned.
912+
// A ship has been destroyed but is still doing its death roll (not yet "exited");
913+
// the objp and shipp pointers are still valid
914+
DEATH_ROLL,
915+
916+
// A ship is destroyed, departed, or vanished; the objp and shipp pointers are nullptr.
917+
// Note that for destroyed ships, ship_cleanup is not called until the death roll is complete,
918+
// so the ship will spend a period of time in DEATH_ROLL before moving to EXITED.
916919
EXITED
917920
};
918921

code/ship/shiphit.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1983,7 +1983,7 @@ void ship_hit_kill(object *ship_objp, object *other_obj, vec3d *hitpos, float pe
19831983

19841984
// Goober5000 - since we added a mission log entry above, immediately set the status. For destruction, ship_cleanup isn't called until a little bit later
19851985
auto entry = &Ship_registry[Ship_registry_map[sp->ship_name]];
1986-
entry->status = ShipStatus::EXITED;
1986+
entry->status = ShipStatus::DEATH_ROLL;
19871987

19881988
ship_generic_kill_stuff( ship_objp, percent_killed );
19891989

0 commit comments

Comments
 (0)