diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index 941595d4644..ca576748d21 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -12806,7 +12806,7 @@ int sexp_is_iff_or_species(int n, bool iff) // ship is in the EXITED state but probably in the process of exploding else if (oswpt.has_shipp()) { - UNREACHABLE("With the addition of the ShipStatus::DEATH_ROLL state, this shouldn't happen"); + Assertion(false, "With the addition of the ShipStatus::DEATH_ROLL state, this shouldn't happen"); return SEXP_KNOWN_FALSE; } // ship has vanished diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 17dff658e29..6006b8ce196 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -6914,6 +6914,25 @@ void ship_level_init() Man_thruster_reset_timestamp = timestamp(0); } +void ship_level_close() +{ + // at this point ships have all gone through ship_delete; + // clean up any ships that are still present so we don't + // leave any stray references behind (e.g. for sexps) + for (auto &ship_entry : Ship_registry) + { + if (ship_entry.status == ShipStatus::PRESENT || ship_entry.status == ShipStatus::DEATH_ROLL) + { + ship_entry.cleanup_mode = (ship_entry.status == ShipStatus::DEATH_ROLL) ? SHIP_DESTROYED : SHIP_PRESENT_AT_MISSION_END; + ship_entry.status = ShipStatus::EXITED; + ship_entry.objnum = -1; + ship_entry.shipnum = -1; + } + } + + ship_close_cockpit_displays(Player_ship); +} + /** * Add a ship onto the exited ships list. * @@ -8745,6 +8764,7 @@ void ship_close_cockpit_displays(ship* shipp) { if (shipp && shipp->cockpit_model_instance >= 0) { model_delete_instance(shipp->cockpit_model_instance); + shipp->cockpit_model_instance = -1; } for ( int i = 0; i < (int)Player_displays.size(); i++ ) { diff --git a/code/ship/ship.h b/code/ship/ship.h index e3d7e6663eb..77b7df24108 100644 --- a/code/ship/ship.h +++ b/code/ship/ship.h @@ -1688,6 +1688,7 @@ extern SCP_vector Wing_formations; extern void ship_init(); // called once at game start extern void ship_level_init(); // called before the start of each level +extern void ship_level_close(); // called after the end of each level //returns -1 if failed extern int ship_create(matrix* orient, vec3d* pos, int ship_type, const char* ship_name = nullptr, bool standalone_ship = false); @@ -1700,13 +1701,14 @@ extern void ship_delete( object * objp ); extern int ship_check_collision_fast( object * obj, object * other_obj, vec3d * hitpos ); extern int ship_get_num_ships(); -#define SHIP_VANISHED (1<<0) -#define SHIP_DESTROYED (1<<1) -#define SHIP_DEPARTED_WARP (1<<2) -#define SHIP_DEPARTED_BAY (1<<3) -#define SHIP_DEPARTED ( SHIP_DEPARTED_BAY | SHIP_DEPARTED_WARP ) -#define SHIP_DESTROYED_REDALERT (1<<4) -#define SHIP_DEPARTED_REDALERT (1<<5) +#define SHIP_VANISHED (1<<0) +#define SHIP_DESTROYED (1<<1) +#define SHIP_DEPARTED_WARP (1<<2) +#define SHIP_DEPARTED_BAY (1<<3) +#define SHIP_DEPARTED ( SHIP_DEPARTED_BAY | SHIP_DEPARTED_WARP ) +#define SHIP_DESTROYED_REDALERT (1<<4) +#define SHIP_DEPARTED_REDALERT (1<<5) +#define SHIP_PRESENT_AT_MISSION_END (1<<6) /** * @brief Deletes and de-inits a ship. diff --git a/freespace2/freespace.cpp b/freespace2/freespace.cpp index cf9d354e695..d2f2c174854 100644 --- a/freespace2/freespace.cpp +++ b/freespace2/freespace.cpp @@ -984,7 +984,7 @@ void game_level_close() particle::ParticleManager::get()->clearSources(); particle::close(); trail_level_close(); - ship_close_cockpit_displays(Player_ship); + ship_level_close(); hud_level_close(); hud_escort_clear_all(); model_instance_free_all();