ModernUO/Distribution/Data/Spawns/post-uoml/termur/Vendors.json
Kamron Batman 2f8a7afa57 chore(spawners): migrate spawn data to $type discriminator
- Rename "type" -> "$type" (first key, required for STJ polymorphism) in
  all 109 spawn JSON files (5,612 records).
- Convert "homeRange" + "location" -> "spawnBounds" object, dropping homeRange.
  Runtime keeps reading homeRange so un-migrated/external files still load.
- Add BoundsEquivalenceTests (hr=0/1/3/7) validating that the script's toBounds
  formula produces the same Rectangle3D as the runtime homeRange path.
- Add MigratedDataLoadTests loading a real migrated file as List<SpawnerDto>
  and round-tripping each DTO through ToSpawner().
- Add tools/spawner-json-migrate/migrate.mjs (offline Node script).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:17:35 -07:00

1026 lines
18 KiB
JSON

[
{
"$type": "Spawner",
"guid": "7bd2b3c7-3c39-40c5-9c3b-98b73d060c65",
"name": "Spawner (604)",
"location": [
976,
3881,
-42
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 976,
"y1": 3881,
"z1": -42,
"x2": 977,
"y2": 3882,
"z2": -42
},
"walkingRange": 5,
"entries": [
{
"name": "Baker",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "a80c5b72-e181-4266-8109-9c7a5eaf6a10",
"name": "Spawner (604)",
"location": [
1010,
3883,
-42
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 1010,
"y1": 3883,
"z1": -42,
"x2": 1011,
"y2": 3884,
"z2": -42
},
"walkingRange": 5,
"entries": [
{
"name": "Blacksmith",
"maxCount": 1,
"probability": 100
},
{
"name": "BlacksmithGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "99c47ee2-bbb0-4d0b-9294-18104ebb0f6b",
"name": "Spawner (604)",
"location": [
1013,
3913,
-42
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 1013,
"y1": 3913,
"z1": -42,
"x2": 1014,
"y2": 3914,
"z2": -42
},
"walkingRange": 5,
"entries": [
{
"name": "Healer",
"maxCount": 1,
"probability": 100
},
{
"name": "HealerGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "6b95fe1b-1c63-479d-b481-1b4d4c929a79",
"name": "Spawner (604)",
"location": [
977,
3909,
-42
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 977,
"y1": 3909,
"z1": -42,
"x2": 978,
"y2": 3910,
"z2": -42
},
"walkingRange": 5,
"entries": [
{
"name": "Tinker",
"maxCount": 1,
"probability": 100
},
{
"name": "TinkerGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "9c632527-c639-469c-9ded-ca859e4a8859",
"name": "Spawner (604)",
"location": [
943,
3924,
-42
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 943,
"y1": 3924,
"z1": -42,
"x2": 944,
"y2": 3925,
"z2": -42
},
"walkingRange": 5,
"entries": [
{
"name": "InnKeeper",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "b317c56d-c032-4e81-aa3a-78988500a740",
"name": "Spawner (604)",
"location": [
1020,
3884,
-42
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 1020,
"y1": 3884,
"z1": -42,
"x2": 1021,
"y2": 3885,
"z2": -42
},
"walkingRange": 5,
"entries": [
{
"name": "Blacksmith",
"maxCount": 1,
"probability": 100
},
{
"name": "BlacksmithGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "556fdb4d-f7f2-4ba0-9d01-d94a76ee7a28",
"name": "Spawner (604)",
"location": [
740,
3466,
-19
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 740,
"y1": 3466,
"z1": -19,
"x2": 741,
"y2": 3467,
"z2": -19
},
"walkingRange": 5,
"entries": [
{
"name": "InnKeeper",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "65b19c79-0f40-4772-9037-1cad0769456d",
"name": "Spawner (604)",
"location": [
772,
3467,
-20
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 772,
"y1": 3467,
"z1": -20,
"x2": 773,
"y2": 3468,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Scribe",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "fd3342ae-de6c-436e-964a-e410ba1f983b",
"name": "Spawner (604)",
"location": [
773,
3478,
-20
],
"map": "TerMur",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 773,
"y1": 3478,
"z1": -20,
"x2": 774,
"y2": 3479,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Herbalist",
"maxCount": 1,
"probability": 100
},
{
"name": "Alchemist",
"maxCount": 1,
"probability": 100
},
{
"name": "CustomHairstylist",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "fcffbb1c-fb73-4c59-9257-52e1d6ebadb4",
"name": "Spawner (604)",
"location": [
772,
3490,
-20
],
"map": "TerMur",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 772,
"y1": 3490,
"z1": -20,
"x2": 773,
"y2": 3491,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Mage",
"maxCount": 1,
"probability": 100
},
{
"name": "Alchemist",
"maxCount": 1,
"probability": 100
},
{
"name": "MageGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "bb731ab1-950e-4e4b-8e55-6378eeb2c3b0",
"name": "Spawner (604)",
"location": [
783,
3491,
-20
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 783,
"y1": 3491,
"z1": -20,
"x2": 784,
"y2": 3492,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Healer",
"maxCount": 1,
"probability": 100
},
{
"name": "HealerGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "36f1b1bc-0754-4605-929a-d7c8e030a80b",
"name": "Spawner (604)",
"location": [
797,
3494,
0
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 797,
"y1": 3494,
"z1": 0,
"x2": 798,
"y2": 3495,
"z2": 0
},
"walkingRange": 5,
"entries": [
{
"name": "Provisioner",
"maxCount": 1,
"probability": 100
},
{
"name": "Cobbler",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "28cda9f4-bbd1-451d-acb0-f568361a7d6f",
"name": "Spawner (604)",
"location": [
805,
3491,
-20
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 805,
"y1": 3491,
"z1": -20,
"x2": 806,
"y2": 3492,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Baker",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "0bd1f793-51e9-4dbe-ab5c-dbd452e85d8c",
"name": "Spawner (604)",
"location": [
817,
3456,
-10
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 817,
"y1": 3456,
"z1": -10,
"x2": 818,
"y2": 3457,
"z2": -10
},
"walkingRange": 5,
"entries": [
{
"name": "Butcher",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "5f573458-bb63-4617-b2c4-c73762718dae",
"name": "Spawner (604)",
"location": [
817,
3438,
0
],
"map": "TerMur",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 817,
"y1": 3438,
"z1": 0,
"x2": 818,
"y2": 3439,
"z2": 0
},
"walkingRange": 5,
"entries": [
{
"name": "Carpenter",
"maxCount": 1,
"probability": 100
},
{
"name": "Architect",
"maxCount": 1,
"probability": 100
},
{
"name": "RealEstateBroker",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "37378f9d-5e71-46a8-8d15-0b98d48a3d04",
"name": "Spawner (604)",
"location": [
817,
3426,
0
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 817,
"y1": 3426,
"z1": 0,
"x2": 818,
"y2": 3427,
"z2": 0
},
"walkingRange": 5,
"entries": [
{
"name": "Tinker",
"maxCount": 1,
"probability": 100
},
{
"name": "TinkerGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "2088913c-0ec7-4225-8f9d-1112e817542b",
"name": "Spawner (604)",
"location": [
816,
3419,
0
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 816,
"y1": 3419,
"z1": 0,
"x2": 817,
"y2": 3420,
"z2": 0
},
"walkingRange": 5,
"entries": [
{
"name": "Blacksmith",
"maxCount": 1,
"probability": 100
},
{
"name": "BlacksmithGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "094d18b0-4b1a-491d-ae33-2463d400904b",
"name": "Spawner (604)",
"location": [
805,
3397,
0
],
"map": "TerMur",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 805,
"y1": 3397,
"z1": 0,
"x2": 806,
"y2": 3398,
"z2": 0
},
"walkingRange": 5,
"entries": [
{
"name": "Tailor",
"maxCount": 1,
"probability": 100
},
{
"name": "Weaver",
"maxCount": 1,
"probability": 100
},
{
"name": "TailorGuildmaster",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "b9c41d27-d185-41dc-aa13-7258c018abc1",
"name": "Spawner (604)",
"location": [
804,
3387,
0
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 804,
"y1": 3387,
"z1": 0,
"x2": 805,
"y2": 3388,
"z2": 0
},
"walkingRange": 5,
"entries": [
{
"name": "Tanner",
"maxCount": 1,
"probability": 100
},
{
"name": "Furtrader",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "720f9c6d-c0e6-4f66-aca9-cca448a5d02d",
"name": "Spawner (604)",
"location": [
851,
3404,
-20
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 851,
"y1": 3404,
"z1": -20,
"x2": 852,
"y2": 3405,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "AnimalTrainer",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "0197b002-1c6d-45ac-8d7d-21706a854586",
"name": "Spawner (604)",
"location": [
833,
3439,
-20
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 833,
"y1": 3439,
"z1": -20,
"x2": 834,
"y2": 3440,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Banker",
"maxCount": 1,
"probability": 100
},
{
"name": "Minter",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "3e2450a8-7aa3-434a-a144-dfc36f784d9e",
"name": "Spawner (604)",
"location": [
843,
3439,
-20
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 843,
"y1": 3439,
"z1": -20,
"x2": 844,
"y2": 3440,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Banker",
"maxCount": 1,
"probability": 100
},
{
"name": "Minter",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "f2b8fe59-6e8b-4db1-a20c-9663efe3b725",
"name": "Spawner (604)",
"location": [
702,
3435,
-20
],
"map": "TerMur",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 702,
"y1": 3435,
"z1": -20,
"x2": 703,
"y2": 3436,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Tailor",
"maxCount": 1,
"probability": 100
},
{
"name": "Weaver",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "59459615-255f-449a-b4ee-c6adf848c09a",
"name": "Spawner (604)",
"location": [
727,
3425,
-20
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 727,
"y1": 3425,
"z1": -20,
"x2": 728,
"y2": 3426,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Armorer",
"maxCount": 1,
"probability": 100
},
{
"name": "Weaponsmith",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "fa9d60df-aa99-4934-bfab-35066f170481",
"name": "Spawner (604)",
"location": [
715,
3446,
-20
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 715,
"y1": 3446,
"z1": -20,
"x2": 716,
"y2": 3447,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "Farmer",
"maxCount": 1,
"probability": 100
},
{
"name": "Farmer",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "27644d88-d3d5-458f-902d-78b7b59eaf95",
"name": "Spawner (604)",
"location": [
713,
3438,
-20
],
"map": "TerMur",
"count": 4,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 713,
"y1": 3438,
"z1": -20,
"x2": 714,
"y2": 3439,
"z2": -20
},
"walkingRange": 5,
"entries": [
{
"name": "TavernKeeper",
"maxCount": 1,
"probability": 100
},
{
"name": "Waiter",
"maxCount": 1,
"probability": 100
},
{
"name": "Barkeeper",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "2a0e5133-2658-44f4-95ca-bcc5d68ddaeb",
"name": "Spawner (604)",
"location": [
794,
3446,
-10
],
"map": "TerMur",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 794,
"y1": 3446,
"z1": -10,
"x2": 795,
"y2": 3447,
"z2": -10
},
"walkingRange": 5,
"entries": [
{
"name": "Farmer",
"maxCount": 1,
"probability": 100
},
{
"name": "Farmer",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "6d91f1ff-12e5-4d75-aa5a-033ff00b9a24",
"name": "Spawner (604)",
"location": [
779,
3431,
-10
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 779,
"y1": 3431,
"z1": -10,
"x2": 780,
"y2": 3432,
"z2": -10
},
"walkingRange": 5,
"entries": [
{
"name": "Jeweler",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "a1ba61c1-0fc5-46a4-b7de-1350606fb0fc",
"name": "Spawner (604)",
"location": [
842,
3453,
-18
],
"map": "TerMur",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 842,
"y1": 3453,
"z1": -18,
"x2": 843,
"y2": 3454,
"z2": -18
},
"walkingRange": 4,
"entries": [
{
"name": "TownCrier",
"maxCount": 1,
"probability": 100
}
]
}
]