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.
123 lines
No EOL
2.9 KiB
JSON
Generated
123 lines
No EOL
2.9 KiB
JSON
Generated
{
|
|
"version": 16,
|
|
"type": "Server.Items.Corpse",
|
|
"properties": [
|
|
{
|
|
"name": "RestoreEquip",
|
|
"type": "System.Collections.Generic.List\u003CServer.Item\u003E",
|
|
"rule": "ListMigrationRule",
|
|
"ruleArguments": [
|
|
"Server.Item",
|
|
"SerializableInterfaceMigrationRule"
|
|
]
|
|
},
|
|
{
|
|
"name": "Flags",
|
|
"type": "Server.Items.CorpseFlag",
|
|
"rule": "EnumMigrationRule"
|
|
},
|
|
{
|
|
"name": "TimeOfDeath",
|
|
"type": "System.DateTime",
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"DeltaTime"
|
|
]
|
|
},
|
|
{
|
|
"name": "RestoreTable",
|
|
"type": "System.Collections.Generic.Dictionary\u003CServer.Item, Server.Point3D\u003E",
|
|
"rule": "DictionaryMigrationRule",
|
|
"ruleArguments": [
|
|
"Server.Item",
|
|
"SerializableInterfaceMigrationRule",
|
|
"0",
|
|
"Server.Point3D",
|
|
"PrimitiveUOTypeMigrationRule",
|
|
"1",
|
|
"Point3D"
|
|
]
|
|
},
|
|
{
|
|
"name": "DecayTimer",
|
|
"type": "Server.Timer",
|
|
"rule": "TimerMigrationRule",
|
|
"ruleArguments": [
|
|
"@TimerDrift"
|
|
]
|
|
},
|
|
{
|
|
"name": "Looters",
|
|
"type": "System.Collections.Generic.HashSet\u003CServer.Mobile\u003E",
|
|
"rule": "HashSetMigrationRule",
|
|
"ruleArguments": [
|
|
"Server.Mobile",
|
|
"SerializableInterfaceMigrationRule"
|
|
]
|
|
},
|
|
{
|
|
"name": "Killer",
|
|
"type": "Server.Mobile",
|
|
"rule": "SerializableInterfaceMigrationRule"
|
|
},
|
|
{
|
|
"name": "Aggressors",
|
|
"type": "System.Collections.Generic.List\u003CServer.Mobile\u003E",
|
|
"rule": "ListMigrationRule",
|
|
"ruleArguments": [
|
|
"Server.Mobile",
|
|
"SerializableInterfaceMigrationRule"
|
|
]
|
|
},
|
|
{
|
|
"name": "Owner",
|
|
"type": "Server.Mobile",
|
|
"rule": "SerializableInterfaceMigrationRule"
|
|
},
|
|
{
|
|
"name": "CorpseName",
|
|
"type": "string",
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "AccessLevel",
|
|
"type": "Server.AccessLevel",
|
|
"rule": "EnumMigrationRule"
|
|
},
|
|
{
|
|
"name": "Guild",
|
|
"type": "Server.Guilds.Guild",
|
|
"rule": "SerializableInterfaceMigrationRule"
|
|
},
|
|
{
|
|
"name": "EquipItems",
|
|
"type": "System.Collections.Generic.List\u003CServer.Item\u003E",
|
|
"rule": "ListMigrationRule",
|
|
"ruleArguments": [
|
|
"Server.Item",
|
|
"SerializableInterfaceMigrationRule"
|
|
]
|
|
},
|
|
{
|
|
"name": "Hair",
|
|
"type": "Server.VirtualHairInfo",
|
|
"rule": "RawSerializableMigrationRule",
|
|
"ruleArguments": [
|
|
"",
|
|
"@CanBeNull"
|
|
]
|
|
},
|
|
{
|
|
"name": "FacialHair",
|
|
"type": "Server.VirtualHairInfo",
|
|
"rule": "RawSerializableMigrationRule",
|
|
"ruleArguments": [
|
|
"",
|
|
"@CanBeNull"
|
|
]
|
|
}
|
|
]
|
|
} |