## Summary `BaseCreature` stored the pet owner (`ControlMaster`) and the summoner (`SummonMaster`) in two fields. Every flow that manages pets kept them in step by hand: summon, transfer, stable, claim, ball of summoning and GM obey. They now share one `_master` field, and the two properties read it through the Controlled and Summoned flags: ```csharp ControlMaster => Controlled ? master : null SummonMaster => Controlled && !Summoned ? null : master ``` Every existing reader keeps its meaning: - `ControlMaster` is still "the owner". - `SummonMaster` is still "the summoner, controlled or not". Blade spirits, energy vortexes, clones, undead minions and enraged creatures (a summon master without `Summoned`) never become visible through `ControlMaster`, so the ungated readers (ML notoriety, aggressor entries and similar) behave as before. - Setting `SummonMaster` on a plain pet does nothing, instead of quietly replacing the owner. - `SetControlMaster` now keeps both masters in step, so the hand-written `SummonMaster` copies are removed from ball of summoning, GM obey, pet transfer, auto-stable and claim, the animal trainer's stable and claim, and jail stabling. ## Serialization BaseCreature moves to v24 with one serialized master (slot 15); the old `SummonMaster` slot is dropped. - `MigrateFrom(V23Content)` resolves absent fields through the same default-value methods the live reader uses. - A save that carried both masters (a summon traded before ownership followed transfers) resolves to the owner. Legacy pre-codegen streams follow the same rule. Requires `ModernUO.Serialization.Generator` 4.2.0 (#2671). `UOContent.Tests` was still on 4.1.0 and is bumped to match. ## Test plan - [x] `MasterShapes_RoundTrip`: controlled pet, controlled summon, energy vortex, enraged creature - [x] `SummonMaster_OnPlainPet_KeepsTheOwner`: owner and follower counts unchanged - [x] `LegacyV22Stream_DifferingMasters_OwnerWins` - [x] `V23Stream_MigratesToOneMaster_AndDefaultsAbsentFields`: both master slots -> owner; flags past bit 32; absent fields take class defaults - [x] UOContent.Tests (1168 passed, 2 skipped) and Server.Tests (907) green
465 lines
No EOL
9.7 KiB
JSON
Generated
465 lines
No EOL
9.7 KiB
JSON
Generated
{
|
|
"version": 24,
|
|
"type": "Server.Mobiles.BaseCreature",
|
|
"properties": [
|
|
{
|
|
"name": "DefaultAI",
|
|
"type": "Server.Mobiles.AIType",
|
|
"rule": "EnumMigrationRule"
|
|
},
|
|
{
|
|
"name": "CurrentAI",
|
|
"type": "Server.Mobiles.AIType",
|
|
"usesSaveFlag": true,
|
|
"rule": "EnumMigrationRule"
|
|
},
|
|
{
|
|
"name": "RangePerception",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "RangeFight",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "RangeHome",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "Team",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "FightMode",
|
|
"type": "Server.Mobiles.FightMode",
|
|
"usesSaveFlag": true,
|
|
"rule": "EnumMigrationRule"
|
|
},
|
|
{
|
|
"name": "ActiveSpeed",
|
|
"type": "double",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "PassiveSpeed",
|
|
"type": "double",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "CurrentSpeed",
|
|
"type": "double",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "ActiveMoveSpeed",
|
|
"type": "double",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "PassiveMoveSpeed",
|
|
"type": "double",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "Home",
|
|
"type": "Server.Point3D",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveUOTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"Point3D"
|
|
]
|
|
},
|
|
{
|
|
"name": "HomeMap",
|
|
"type": "Server.Map",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveUOTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"Map"
|
|
]
|
|
},
|
|
{
|
|
"name": "Controlled",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "Master",
|
|
"type": "Server.Mobile",
|
|
"usesSaveFlag": true,
|
|
"rule": "SerializableInterfaceMigrationRule"
|
|
},
|
|
{
|
|
"name": "ControlTarget",
|
|
"type": "Server.Mobile",
|
|
"usesSaveFlag": true,
|
|
"rule": "SerializableInterfaceMigrationRule"
|
|
},
|
|
{
|
|
"name": "ControlDest",
|
|
"type": "Server.Point3D",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveUOTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"Point3D"
|
|
]
|
|
},
|
|
{
|
|
"name": "ControlOrder",
|
|
"type": "Server.Mobiles.OrderType",
|
|
"usesSaveFlag": true,
|
|
"rule": "EnumMigrationRule"
|
|
},
|
|
{
|
|
"name": "MinTameSkill",
|
|
"type": "double",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "Tamable",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "Summoned",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "SummonEnd",
|
|
"type": "System.DateTime",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"AnchoredTime"
|
|
]
|
|
},
|
|
{
|
|
"name": "ControlSlots",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "Loyalty",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "CurrentWayPoint",
|
|
"type": "Server.Items.WayPoint",
|
|
"usesSaveFlag": true,
|
|
"rule": "SerializableInterfaceMigrationRule"
|
|
},
|
|
{
|
|
"name": "HitsMaxSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "StamMaxSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "ManaMaxSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "DamageMin",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "DamageMax",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "PhysicalResistanceSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "FireResistSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "ColdResistSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "PoisonResistSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "EnergyResistSeed",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "PhysicalDamage",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "FireDamage",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "ColdDamage",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "PoisonDamage",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "EnergyDamage",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "Owners",
|
|
"type": "System.Collections.Generic.List\u003CServer.Mobile\u003E",
|
|
"usesSaveFlag": true,
|
|
"rule": "ListMigrationRule",
|
|
"ruleArguments": [
|
|
"@Tidy",
|
|
"Server.Mobile",
|
|
"SerializableInterfaceMigrationRule"
|
|
]
|
|
},
|
|
{
|
|
"name": "IsDeadPet",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "IsBonded",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "BondingBegin",
|
|
"type": "System.DateTime",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "OwnerAbandonTime",
|
|
"type": "System.DateTime",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "HasGeneratedLoot",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "IsParagon",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "Friends",
|
|
"type": "System.Collections.Generic.List\u003CServer.Mobile\u003E",
|
|
"usesSaveFlag": true,
|
|
"rule": "ListMigrationRule",
|
|
"ruleArguments": [
|
|
"@Tidy",
|
|
"Server.Mobile",
|
|
"SerializableInterfaceMigrationRule"
|
|
]
|
|
},
|
|
{
|
|
"name": "RemoveIfUntamed",
|
|
"type": "bool",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"name": "RemoveStep",
|
|
"type": "int",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
"EncodedInt"
|
|
]
|
|
},
|
|
{
|
|
"name": "PendingDeleteTimer",
|
|
"type": "Server.Timer",
|
|
"usesSaveFlag": true,
|
|
"rule": "TimerMigrationRule",
|
|
"ruleArguments": [
|
|
"@AnchoredTimer"
|
|
]
|
|
},
|
|
{
|
|
"name": "CorpseNameOverride",
|
|
"type": "string",
|
|
"usesSaveFlag": true,
|
|
"rule": "PrimitiveTypeMigrationRule",
|
|
"ruleArguments": [
|
|
""
|
|
]
|
|
}
|
|
]
|
|
} |