fix: Preserve corpse notoriety across server restart (#2426)
BaseCreatures are deleted on death (Mobile.OnDeath calls Delete for non-players), so after save/restart the corpse's _owner reference resolves to null. CorpseNotoriety gated its entire creature branch on `target.Owner is BaseCreature`, falling through to player-corpse logic once the reference vanished. That made monster corpses turn red (body.IsMonster -> Murderer) and innocent NPC corpses turn grey (null is not PlayerMobile -> CanBeAttacked) on the next restart. Snapshots the relevant owner state into CorpseFlag at corpse creation: OwnerWasBaseCreature, OwnerWasSummoned, OwnerWasAnimatedDead. Folds the standalone _murderer bool into CorpseFlag.Murderer for consistency with Criminal. CorpseNotoriety now consults the flags so the creature branch stays correct without a live mobile reference. Bumps Corpse serialization to v16 with a MigrateFrom(V15Content) that maps the old Murderer bool onto the new flag. Pre-fix corpses already on disk decay within 7 minutes; their first post-restart color may be wrong, which is acceptable. Also documents that the schema generator must be run after every version bump (`dotnet tool run ModernUOSchemaGenerator -- ModernUO.slnx`) since `dotnet build` does not emit migration JSON files.
This commit is contained in:
parent
a74c7f9d4e
commit
29e4ecdb1b
5 changed files with 251 additions and 29 deletions
|
|
@ -297,22 +297,25 @@ namespace Server.Misc
|
|||
}
|
||||
}
|
||||
|
||||
if (target.Owner is BaseCreature creature)
|
||||
// BaseCreatures are deleted on death, so target.Owner is null after a server restart.
|
||||
// The OwnerWasBaseCreature flag is the persisted snapshot that survives the live mobile.
|
||||
var creature = target.Owner as BaseCreature;
|
||||
|
||||
if (target.OwnerWasBaseCreature || creature != null)
|
||||
{
|
||||
if (srcFaction != null && trgFaction != null && srcFaction != trgFaction && source.Map == Faction.Facet)
|
||||
{
|
||||
return Notoriety.Enemy;
|
||||
}
|
||||
|
||||
if (CheckHouseFlag(source, creature, target.Location, target.Map))
|
||||
if (creature != null && CheckHouseFlag(source, creature, target.Location, target.Map))
|
||||
{
|
||||
return Notoriety.CanBeAttacked;
|
||||
}
|
||||
|
||||
var actual = Notoriety.CanBeAttacked;
|
||||
|
||||
if (target.Murderer || body.IsMonster && IsSummoned(creature) ||
|
||||
creature.IsAnimatedDead)
|
||||
if (target.Murderer || body.IsMonster && target.OwnerWasSummoned || target.OwnerWasAnimatedDead)
|
||||
{
|
||||
actual = Notoriety.Murderer;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue