ModernUO/Distribution/Data/Spawns/shared/trammel/Ice.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

1196 lines
21 KiB
JSON

[
{
"$type": "Spawner",
"guid": "03886f2b-1e0e-48fd-8b92-35a1a60a95c5",
"name": "Spawner (110)",
"location": [
5837,
245,
-5
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5836,
"y1": 244,
"z1": -128,
"x2": 5839,
"y2": 247,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "106c22c9-9d01-43a0-8983-bea255146fd5",
"name": "Spawner (110)",
"location": [
5833,
242,
-2
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5832,
"y1": 241,
"z1": -128,
"x2": 5835,
"y2": 244,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "308a4f85-5d3f-4f44-af64-371951608f97",
"name": "Spawner (110)",
"location": [
5785,
161,
-6
],
"map": "Trammel",
"count": 5,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5767,
"y1": 143,
"z1": -128,
"x2": 5804,
"y2": 180,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "FrostOoze",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostSpider",
"maxCount": 1,
"probability": 100
},
{
"name": "IceElemental",
"maxCount": 1,
"probability": 100
},
{
"name": "SnowElemental",
"maxCount": 1,
"probability": 100
},
{
"name": "IceSnake",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostTroll",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "3cfd9a1b-000a-430f-b44c-e64720d69237",
"name": "Spawner (110)",
"location": [
5772,
188,
-3
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5771,
"y1": 187,
"z1": -128,
"x2": 5774,
"y2": 190,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "3def478d-d193-49d2-96e0-b36023034db7",
"name": "Spawner (110)",
"location": [
5752,
144,
9
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5742,
"y1": 134,
"z1": -128,
"x2": 5763,
"y2": 155,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "WhiteWyrm",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "3ec99717-4da8-4d7c-9fb2-dd9ba4c845bc",
"name": "Spawner (110)",
"location": [
5731,
176,
-5
],
"map": "Trammel",
"count": 18,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5706,
"y1": 151,
"z1": -128,
"x2": 5757,
"y2": 202,
"z2": 128
},
"walkingRange": 35,
"entries": [
{
"name": "IceSerpent",
"maxCount": 9,
"probability": 100
},
{
"name": "SnowElemental",
"maxCount": 9,
"probability": 100
},
{
"name": "IceElemental",
"maxCount": 9,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "3f420eb7-724d-47e0-89fa-1e844feee72c",
"name": "Spawner (110)",
"location": [
5666,
331,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5665,
"y1": 330,
"z1": -128,
"x2": 5668,
"y2": 333,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "4133a659-4bcb-4b38-a3fe-097866c8aa4e",
"name": "Spawner (110)",
"location": [
5680,
306,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5670,
"y1": 296,
"z1": -128,
"x2": 5691,
"y2": 317,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "IceFiend",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "44394753-6925-4e7f-95d0-d1998f5bb036",
"name": "Spawner (110)",
"location": [
5831,
358,
-1
],
"map": "Trammel",
"count": 24,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5816,
"y1": 343,
"z1": -128,
"x2": 5847,
"y2": 374,
"z2": 128
},
"walkingRange": 25,
"entries": [
{
"name": "Ratman",
"maxCount": 12,
"probability": 100
},
{
"name": "RatmanArcher",
"maxCount": 7,
"probability": 100
},
{
"name": "RatmanMage",
"maxCount": 5,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "49c552fa-1934-405a-8d30-4fb7db89313f",
"name": "Spawner (110)",
"location": [
5839,
159,
0
],
"map": "Trammel",
"count": 5,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5824,
"y1": 144,
"z1": -128,
"x2": 5855,
"y2": 175,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "FrostOoze",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostSpider",
"maxCount": 1,
"probability": 100
},
{
"name": "IceElemental",
"maxCount": 1,
"probability": 100
},
{
"name": "SnowElemental",
"maxCount": 1,
"probability": 100
},
{
"name": "IceSnake",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostTroll",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "4df74fc7-0443-4fdc-a6ad-57d9a4d6bc7f",
"name": "Spawner (110)",
"location": [
5684,
181,
-5
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5683,
"y1": 180,
"z1": -128,
"x2": 5686,
"y2": 183,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "6502c7e1-5c7a-43b7-a0de-33f73f78e6a3",
"name": "Spawner (110)",
"location": [
5838,
355,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5837,
"y1": 354,
"z1": -128,
"x2": 5840,
"y2": 357,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel2",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "66e9c531-1fee-42e4-910a-cdf71b212b95",
"name": "Spawner (110)",
"location": [
5754,
211,
-6
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5753,
"y1": 210,
"z1": -128,
"x2": 5756,
"y2": 213,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "722d603b-dddb-4b71-88c4-9e965918d6e9",
"name": "Spawner (110)",
"location": [
5763,
187,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5762,
"y1": 186,
"z1": -128,
"x2": 5765,
"y2": 189,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "76706bc3-f4c4-4040-b206-650aa04e041d",
"name": "Spawner (110)",
"location": [
5824,
363,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5823,
"y1": 362,
"z1": -128,
"x2": 5826,
"y2": 365,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "7ebb7a60-b45f-469c-ad0b-86490c855be1",
"name": "Spawner (110)",
"location": [
5756,
203,
-2
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5755,
"y1": 202,
"z1": -128,
"x2": 5758,
"y2": 205,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "84103371-1387-4ebe-af6a-91faf5d3a5f2",
"name": "Spawner (110)",
"location": [
5850,
219,
-3
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5840,
"y1": 209,
"z1": -128,
"x2": 5861,
"y2": 230,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "RatmanMage",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "8855a9a7-aed4-4c54-94da-a94024783d51",
"name": "Spawner (110)",
"location": [
5854,
227,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5853,
"y1": 226,
"z1": -128,
"x2": 5856,
"y2": 229,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "9456469a-1f9f-43a1-9c7b-639ca4e367f3",
"name": "Spawner (110)",
"location": [
5712,
145,
-34
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5711,
"y1": 144,
"z1": -128,
"x2": 5714,
"y2": 147,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "947f998d-a84b-49c8-8619-852fff3e5295",
"name": "Spawner (110)",
"location": [
5669,
330,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5659,
"y1": 320,
"z1": -128,
"x2": 5680,
"y2": 341,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "IceFiend",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "9cbfc951-e954-4e8d-b1af-cf9457216b53",
"name": "Spawner (110)",
"location": [
5799,
188,
-6
],
"map": "Trammel",
"count": 6,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5789,
"y1": 178,
"z1": -128,
"x2": 5810,
"y2": 199,
"z2": 128
},
"walkingRange": 25,
"entries": [
{
"name": "IceSerpent",
"maxCount": 2,
"probability": 100
},
{
"name": "SnowElemental",
"maxCount": 1,
"probability": 100
},
{
"name": "Ratman",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostTroll",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostSpider",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "9f689286-dcc8-44ac-9d6b-c34c002d5ff5",
"name": "Spawner (110)",
"location": [
5682,
314,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5681,
"y1": 313,
"z1": -128,
"x2": 5684,
"y2": 316,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "a6faf1f3-65fa-47a8-a597-1bd61d7dc350",
"name": "Spawner (110)",
"location": [
5757,
213,
-7
],
"map": "Trammel",
"count": 10,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5742,
"y1": 198,
"z1": -128,
"x2": 5773,
"y2": 229,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "IceSerpent",
"maxCount": 3,
"probability": 100
},
{
"name": "Ratman",
"maxCount": 1,
"probability": 100
},
{
"name": "SnowElemental",
"maxCount": 4,
"probability": 100
},
{
"name": "IceElemental",
"maxCount": 4,
"probability": 100
},
{
"name": "FrostTroll",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "a74f4f2c-7906-46c3-bd5f-8ce30e43417c",
"name": "Spawner (110)",
"location": [
5867,
218,
-4
],
"map": "Trammel",
"count": 4,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5852,
"y1": 203,
"z1": -128,
"x2": 5883,
"y2": 234,
"z2": 128
},
"walkingRange": 25,
"entries": [
{
"name": "FrostSpider",
"maxCount": 1,
"probability": 100
},
{
"name": "FrostOoze",
"maxCount": 2,
"probability": 100
},
{
"name": "IceSnake",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "a9adcc2c-c67d-4f0d-8241-7aa8d73d0fdd",
"name": "Spawner (110)",
"location": [
5681,
191,
-6
],
"map": "Trammel",
"count": 9,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5666,
"y1": 176,
"z1": -128,
"x2": 5697,
"y2": 207,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "IceSerpent",
"maxCount": 3,
"probability": 100
},
{
"name": "SnowElemental",
"maxCount": 4,
"probability": 100
},
{
"name": "IceElemental",
"maxCount": 4,
"probability": 100
},
{
"name": "FrostTroll",
"maxCount": 1,
"probability": 100
},
{
"name": "Ratman",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "ada3263b-aece-4dee-a69b-fe3ef96a3550",
"name": "Spawner (110)",
"location": [
5814,
237,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5799,
"y1": 222,
"z1": -128,
"x2": 5830,
"y2": 253,
"z2": 128
},
"walkingRange": 15,
"entries": [
{
"name": "ArcticOgreLord",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "b4e94abe-5829-4d51-acb5-e112d8b33ce1",
"name": "Spawner (110)",
"location": [
5676,
331,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5675,
"y1": 330,
"z1": -128,
"x2": 5678,
"y2": 333,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "b5f90c32-64bd-4524-bfc6-84716f186595",
"name": "Spawner (110)",
"location": [
5683,
197,
-4
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5682,
"y1": 196,
"z1": -128,
"x2": 5685,
"y2": 199,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "b69a34f7-3ff9-4b19-b38e-817c98a7c93f",
"name": "Spawner (110)",
"location": [
5848,
226,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5847,
"y1": 225,
"z1": -128,
"x2": 5850,
"y2": 228,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel2",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "bc1b0fa0-397d-400e-a8a1-46c6980d3ed7",
"name": "Spawner (110)",
"location": [
5751,
140,
10
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5750,
"y1": 139,
"z1": -128,
"x2": 5753,
"y2": 142,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "c1a3b5ae-9c59-488f-8d7f-24d25e0c7673",
"name": "Spawner (110)",
"location": [
5758,
139,
5
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5757,
"y1": 138,
"z1": -128,
"x2": 5760,
"y2": 141,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "ca52ec08-1f4f-400a-ab1f-9e05892dbdd2",
"name": "Spawner (110)",
"location": [
5696,
303,
0
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5695,
"y1": 302,
"z1": -128,
"x2": 5698,
"y2": 305,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel4",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "dee07fb6-4dcc-43d5-bd0a-706c36801e8d",
"name": "Spawner (110)",
"location": [
5771,
224,
-2
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5761,
"y1": 214,
"z1": -128,
"x2": 5782,
"y2": 235,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "ArcticOgreLord",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "f7a22de1-cc80-4060-aa02-9728d7e241a0",
"name": "Spawner (110)",
"location": [
5721,
147,
-1
],
"map": "Trammel",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 5720,
"y1": 146,
"z1": -128,
"x2": 5723,
"y2": 149,
"z2": 128
},
"walkingRange": 1,
"entries": [
{
"name": "TreasureChestLevel3",
"maxCount": 1,
"probability": 100
}
]
}
]