@@ -192,10 +192,10 @@ SpawnManagerClass::SpawnManagerClass(TechnoClass* owner, const AircraftTypeClass
192192
193193 if (spawnee != nullptr )
194194 {
195+ control->Status = SpawnControlStatus::Idle;
195196 control->IsSpawnedMissile = RocketTypeClass::From_AircraftType (SpawnType) != nullptr ;
196197 control->Spawnee ->Limbo ();
197198 Extension::Fetch<AircraftClassExtension>(control->Spawnee )->SpawnOwner = Owner;
198- control->Status = SpawnControlStatus::Idle;
199199 control->ReloadTimer = 0 ;
200200 SpawnControls.Add (control);
201201 }
@@ -535,9 +535,16 @@ void SpawnManagerClass::AI()
535535
536536 if (owner_coord == spawnee_coord && std::abs (spawnee->Coord .Z - Owner->Coord .Z ) < 20 )
537537 {
538- spawnee->Limbo ();
538+ /* *
539+ * WARNING: Limbo() can destroy the unit in certain situations. If that happens, we
540+ * don't want to set the status to Reloading, as that will cause a nullptr crash later
541+ * when attempting to reload a non-existing spawnee
542+ * (Detach picks up the destruction and sets the control status to Dead).
543+ * Do not touch the order of the statements here or all hell breaks loose!
544+ */
539545 control->Status = SpawnControlStatus::Reloading;
540546 control->ReloadTimer = ReloadRate;
547+ spawnee->Limbo ();
541548 }
542549 else
543550 {
@@ -583,11 +590,11 @@ void SpawnManagerClass::AI()
583590 /* *
584591 * Create a new spawn and set it to idle.
585592 */
593+ control->Status = SpawnControlStatus::Idle;
586594 control->Spawnee = static_cast <AircraftClass*>(SpawnType->Create_One_Of (Owner->Owning_House ()));
587595 control->IsSpawnedMissile = RocketTypeClass::From_AircraftType (SpawnType) != nullptr ;
588596 control->Spawnee ->Limbo ();
589597 Extension::Fetch<AircraftClassExtension>(control->Spawnee )->SpawnOwner = Owner;
590- control->Status = SpawnControlStatus::Idle;
591598 break ;
592599 }
593600 }
@@ -872,6 +879,10 @@ void SpawnManagerClass::Detach(TARGET target)
872879 const auto control = SpawnControls[i];
873880 if (control->Spawnee == target)
874881 {
882+ /* *
883+ * Only remove spawnees that are suicidal or have strength below zero.
884+ * Otherwise, it is a spawnee that landed on us and was limbo'ed for reloading.
885+ */
875886 if (control->Spawnee ->Strength <= 0 || control->Spawnee ->IsKamikaze || control->IsSpawnedMissile )
876887 {
877888 control->Spawnee = nullptr ;
0 commit comments