From cadeb5420530527cb8d2da860f67ff539fac7d33 Mon Sep 17 00:00:00 2001 From: Birk Magnussen <6238428+BMagnu@users.noreply.github.com> Date: Fri, 6 Feb 2026 08:37:12 +0900 Subject: [PATCH 1/2] Clear Decals and Recreate Model instance --- code/decals/decals.cpp | 18 ++++++++++++++++++ code/decals/decals.h | 4 ++++ code/ship/ship.cpp | 8 ++++++++ 3 files changed, 30 insertions(+) diff --git a/code/decals/decals.cpp b/code/decals/decals.cpp index 424c3807932..76c5b679dbf 100644 --- a/code/decals/decals.cpp +++ b/code/decals/decals.cpp @@ -185,6 +185,10 @@ Decal::Decal() { vm_vec_make(&scale, 1.f, 1.f, 1.f); } +void Decal::markForDeletion() { + orig_obj_type = OBJ_NONE; +} + bool Decal::isValid() const { if (!object.isValid()) { return false; @@ -193,6 +197,11 @@ bool Decal::isValid() const { return false; } + if (orig_obj_type == OBJ_NONE) { + //Decal should be cleared + return false; + } + if (orig_obj_type != object.objp()->type) { mprintf(("Decal object type for object %d has changed from %s to %s. Please let m!m know about this\n", object.objnum, Object_type_names[orig_obj_type], Object_type_names[object.objp()->type])); @@ -536,4 +545,13 @@ void addSingleFrameDecal(Decal&& info) { active_single_frame_decals.push_back(info); } +void invalidateForShip(const ship* shipp) { + int objnum = shipp->objnum; + for (Decal& decal : active_decals) { + if (decal.object.objnum == objnum) { + decal.markForDeletion(); + } + } +} + } diff --git a/code/decals/decals.h b/code/decals/decals.h index 338a4fa14e4..f7e08138a95 100644 --- a/code/decals/decals.h +++ b/code/decals/decals.h @@ -66,6 +66,8 @@ struct Decal { Decal(); + void markForDeletion(); + bool isValid() const; }; @@ -160,4 +162,6 @@ void addDecal(creation_info& info, void addSingleFrameDecal(Decal&& info); +void invalidateForShip(const ship* shipp); + } diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 94f4c735388..7fab76d7aa2 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -11766,10 +11766,16 @@ static void ship_model_change(int n, int ship_type) } model_delete_instance(sp->model_instance_num); + if (sp->cockpit_model_instance >= 0) { + model_delete_instance(sp->cockpit_model_instance); + } // create new model instance data // note: this is needed for both subsystem stuff and submodel animation stuff sp->model_instance_num = model_create_instance(OBJ_INDEX(objp), sip->model_num); + if (sip->cockpit_model_num >= 0) { + sp->cockpit_model_instance = model_create_instance(model_objnum_special::OBJNUM_COCKPIT, sip->cockpit_model_num); + } pmi = model_get_instance(sp->model_instance_num); // Goober5000 - deal with texture replacement by re-applying the same code we used during parsing @@ -12069,6 +12075,8 @@ void change_ship_type(int n, int ship_type, int by_sexp) Assertion(weapon_turret_matches.empty(), "Failed to find matches for every turret a projectile was fired from on ship %s in change_ship_type(); get a coder!\n", sp->ship_name); Assertion(last_targeted_matches.empty(), "Somehow failed to find every subsystem a player was previously targeting on ship %s in change_ship_type(); get a coder!\n", sp->ship_name); + decals::invalidateForShip(sp); + // point to new ship data ship_model_change(n, ship_type); sp->ship_info_index = ship_type; From 69b6e3b8c567f9c9521c896d25b958723261e485 Mon Sep 17 00:00:00 2001 From: Birk Magnussen <6238428+BMagnu@users.noreply.github.com> Date: Fri, 6 Feb 2026 08:39:28 +0900 Subject: [PATCH 2/2] Also reset the PMI if the new model has no cockpit --- code/ship/ship.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 7fab76d7aa2..7811fe0d070 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -11773,9 +11773,11 @@ static void ship_model_change(int n, int ship_type) // create new model instance data // note: this is needed for both subsystem stuff and submodel animation stuff sp->model_instance_num = model_create_instance(OBJ_INDEX(objp), sip->model_num); - if (sip->cockpit_model_num >= 0) { + if (sip->cockpit_model_num >= 0) sp->cockpit_model_instance = model_create_instance(model_objnum_special::OBJNUM_COCKPIT, sip->cockpit_model_num); - } + else + sp->cockpit_model_instance = -1; + pmi = model_get_instance(sp->model_instance_num); // Goober5000 - deal with texture replacement by re-applying the same code we used during parsing