From 4161927c27d2d73b370f65caba0a5d8f880002e5 Mon Sep 17 00:00:00 2001 From: WarrentyExpired Date: Thu, 5 Nov 2026 14:12:04 -0500 Subject: [PATCH] #W# Fix: Fixed issue with Overworld/Citizen spawners not deleting already spawn npc. --- .../Spawners/DynamicSpawner/OverworldRef.cs | 39 +++++++++++++++++-- .../Townfolk/Citizens/Citizens/CitizensRef.cs | 36 +++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Projects/UOContent/Engines/Spawners/DynamicSpawner/OverworldRef.cs b/Projects/UOContent/Engines/Spawners/DynamicSpawner/OverworldRef.cs index 87acabd46..86029a286 100644 --- a/Projects/UOContent/Engines/Spawners/DynamicSpawner/OverworldRef.cs +++ b/Projects/UOContent/Engines/Spawners/DynamicSpawner/OverworldRef.cs @@ -27,9 +27,30 @@ namespace Server.Items public void Respawn() { - // Proxy spawners do not handle their own respawns. - // When the monster dies, the proxy deletes itself, - // and the parent Master Spawner drops a new proxy. + // Store and clear reference first to avoid deletion loop + Mobile m = _trackedMobile; + _trackedMobile = null; + + if (m != null && !m.Deleted) + { + m.Delete(); + } + + ExecuteSpawn(); + } + + public override void OnDelete() + { + // Store and clear reference first to avoid deletion loop + Mobile m = _trackedMobile; + _trackedMobile = null; + + if (m != null && !m.Deleted) + { + m.Delete(); + } + + base.OnDelete(); } public bool IsInSpawnBounds(Point3D loc) @@ -39,8 +60,12 @@ namespace Server.Items public void Remove(ISpawnable spawn) { + _trackedMobile = null; + if (!Deleted) + { Delete(); + } } public BaseProxySpawner() : base(0x6519) @@ -101,6 +126,14 @@ namespace Server.Items return; } + // Clean up existing mobile safely if one exists + Mobile existing = _trackedMobile; + _trackedMobile = null; + if (existing != null && !existing.Deleted) + { + existing.Delete(); + } + _trackedMobile = SpawnList.RandomSpawn(this, savedLocation, savedMap); if (_trackedMobile != null) diff --git a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs index 7912497a3..43939b4df 100644 --- a/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs +++ b/Projects/UOContent/Mobiles/Townfolk/Citizens/Citizens/CitizensRef.cs @@ -27,6 +27,30 @@ namespace Server.Items public void Respawn() { + // Store and clear reference first to avoid deletion loop + Mobile m = _trackedMobile; + _trackedMobile = null; + + if (m != null && !m.Deleted) + { + m.Delete(); + } + + ExecuteSpawn(); + } + + public override void OnDelete() + { + // Store and clear reference first to avoid deletion loop + Mobile m = _trackedMobile; + _trackedMobile = null; + + if (m != null && !m.Deleted) + { + m.Delete(); + } + + base.OnDelete(); } public bool IsInSpawnBounds(Point3D loc) @@ -36,8 +60,12 @@ namespace Server.Items public void Remove(ISpawnable spawn) { + _trackedMobile = null; + if (!Deleted) + { Delete(); + } } public CitizenSpawner() : base(0x6519) @@ -97,6 +125,14 @@ namespace Server.Items return; } + // Clean up existing mobile safely if one exists + Mobile existing = _trackedMobile; + _trackedMobile = null; + if (existing != null && !existing.Deleted) + { + existing.Delete(); + } + _trackedMobile = CitizenTerrainList.RandomSpawn(this, savedLocation, savedMap); if (_trackedMobile != null)