ModernUO/Distribution/Data/Spawns/shared/ilshenar/Wisp.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

723 lines
13 KiB
JSON

[
{
"$type": "Spawner",
"guid": "0d68da82-d86a-4c40-8085-174a01c65f55",
"name": "Spawner (313)",
"location": [
775,
1479,
-28
],
"map": "Ilshenar",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 760,
"y1": 1464,
"z1": -128,
"x2": 791,
"y2": 1495,
"z2": 128
},
"walkingRange": 15,
"entries": [
{
"name": "Balron",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "0fe99fe0-a203-4563-994b-5e02d70f1b3f",
"name": "Spawner (313)",
"location": [
888,
1568,
-28
],
"map": "Ilshenar",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 878,
"y1": 1558,
"z1": -128,
"x2": 899,
"y2": 1579,
"z2": 128
},
"walkingRange": 15,
"entries": [
{
"name": "EvilMage",
"maxCount": 1,
"probability": 100
},
{
"name": "EvilMageLord",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "14b1989d-ec45-42db-af1b-92f49023b981",
"name": "Spawner (313)",
"location": [
891,
1537,
-28
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 885,
"y1": 1531,
"z1": -128,
"x2": 898,
"y2": 1544,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "RottingCorpse",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "2ef49b9b-97d6-431a-946d-ffd2f1615697",
"name": "Spawner (313)",
"location": [
855,
1566,
-28
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 849,
"y1": 1560,
"z1": -128,
"x2": 862,
"y2": 1573,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "Shade",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "33185d9f-afa2-43d7-a7aa-7d221c1a309a",
"name": "Spawner (313)",
"location": [
964,
1554,
-28
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 957,
"y1": 1547,
"z1": -128,
"x2": 972,
"y2": 1562,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "LichLord",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "4b9e3103-e83e-48a4-88b3-c72acbe5e173",
"name": "Spawner (313)",
"location": [
936,
1559,
-22
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 926,
"y1": 1549,
"z1": -128,
"x2": 947,
"y2": 1570,
"z2": 128
},
"walkingRange": 25,
"entries": [
{
"name": "Balron",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "516473d8-b5d1-4924-ad74-556649f98470",
"name": "Spawner (313)",
"location": [
939,
1492,
-28
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 934,
"y1": 1487,
"z1": -128,
"x2": 945,
"y2": 1498,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "Imp",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "530dcd87-a132-4cdb-a9c9-0f78758e4ad0",
"name": "Spawner (313)",
"location": [
962,
1480,
-28
],
"map": "Ilshenar",
"count": 4,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 952,
"y1": 1470,
"z1": -128,
"x2": 973,
"y2": 1491,
"z2": 128
},
"walkingRange": 15,
"entries": [
{
"name": "Wraith",
"maxCount": 4,
"probability": 100
},
{
"name": "Spectre",
"maxCount": 4,
"probability": 100
},
{
"name": "Shade",
"maxCount": 4,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "5ce9d857-549d-4bf0-8e70-2dd6902c4ccf",
"name": "Spawner (313)",
"location": [
775,
1480,
-28
],
"map": "Ilshenar",
"count": 5,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 735,
"y1": 1440,
"z1": -128,
"x2": 816,
"y2": 1521,
"z2": 128
},
"walkingRange": 40,
"entries": [
{
"name": "Imp",
"maxCount": 5,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "649b7645-25f8-4c0c-ac2d-896e558b2767",
"name": "Spawner (313)",
"location": [
776,
1480,
-28
],
"map": "Ilshenar",
"count": 15,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 773,
"y1": 1477,
"z1": -128,
"x2": 780,
"y2": 1484,
"z2": 128
},
"walkingRange": 3,
"entries": [
{
"name": "TreasureChestLevel1",
"maxCount": 9,
"probability": 100
},
{
"name": "TreasureChestLevel2",
"maxCount": 9,
"probability": 100
},
{
"name": "TreasureChestLevel3",
"maxCount": 6,
"probability": 100
},
{
"name": "TreasureChestLevel4",
"maxCount": 6,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "67d46705-d56a-4098-bafb-ede2658118a8",
"name": "Spawner (313)",
"location": [
855,
1567,
-28
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 849,
"y1": 1561,
"z1": -128,
"x2": 862,
"y2": 1574,
"z2": 128
},
"walkingRange": 6,
"entries": [
{
"name": "SkeletalMage",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "6cf2cd79-9f0f-4f25-af2b-333a9317171f",
"name": "Spawner (313)",
"location": [
827,
1479,
-28
],
"map": "Ilshenar",
"count": 6,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 817,
"y1": 1469,
"z1": -128,
"x2": 838,
"y2": 1490,
"z2": 128
},
"walkingRange": 15,
"entries": [
{
"name": "Shade",
"maxCount": 2,
"probability": 100
},
{
"name": "BoneKnight",
"maxCount": 2,
"probability": 100
},
{
"name": "BoneMagi",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "74498688-9c91-4ea3-8abd-adcd2beb3b8d",
"name": "Spawner (313)",
"location": [
959,
1530,
-28
],
"map": "Ilshenar",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 952,
"y1": 1523,
"z1": -128,
"x2": 967,
"y2": 1538,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "Lich",
"maxCount": 1,
"probability": 100
},
{
"name": "Wraith",
"maxCount": 0,
"probability": 100
},
{
"name": "Spectre",
"maxCount": 0,
"probability": 100
},
{
"name": "Shade",
"maxCount": 0,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "79272788-c6c6-4216-84e0-985b942af71b",
"name": "Spawner (313)",
"location": [
871,
1531,
-28
],
"map": "Ilshenar",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 865,
"y1": 1525,
"z1": -128,
"x2": 878,
"y2": 1538,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "EvilMage",
"maxCount": 3,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "a90852cd-b672-4c4f-83bb-99dcc861ead0",
"name": "Spawner (313)",
"location": [
851,
1498,
-28
],
"map": "Ilshenar",
"count": 1,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 846,
"y1": 1493,
"z1": -128,
"x2": 857,
"y2": 1504,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "RottingCorpse",
"maxCount": 1,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "add779de-8361-4edb-b214-900500ca81f0",
"name": "Spawner (313)",
"location": [
888,
1471,
-28
],
"map": "Ilshenar",
"count": 8,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 876,
"y1": 1459,
"z1": -128,
"x2": 901,
"y2": 1484,
"z2": 128
},
"walkingRange": 20,
"entries": [
{
"name": "Shade",
"maxCount": 3,
"probability": 100
},
{
"name": "BoneKnight",
"maxCount": 3,
"probability": 100
},
{
"name": "BoneMagi",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "ae956108-5118-4793-94d7-ac885617030f",
"name": "Spawner (313)",
"location": [
681,
1535,
-28
],
"map": "Ilshenar",
"count": 20,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 641,
"y1": 1495,
"z1": -128,
"x2": 722,
"y2": 1576,
"z2": 128
},
"walkingRange": 60,
"entries": [
{
"name": "Wisp",
"maxCount": 20,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "b19163ea-9376-48e7-9bf7-b0a6a2e75d38",
"name": "Spawner (313)",
"location": [
1000,
1512,
0
],
"map": "Ilshenar",
"count": 5,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 985,
"y1": 1497,
"z1": -128,
"x2": 1016,
"y2": 1528,
"z2": 128
},
"walkingRange": 15,
"entries": [
{
"name": "Titan",
"maxCount": 2,
"probability": 100
},
{
"name": "Cyclops",
"maxCount": 3,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "be42e727-e04f-47a2-b07c-49046fdafcb9",
"name": "Spawner (313)",
"location": [
939,
1531,
-28
],
"map": "Ilshenar",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 934,
"y1": 1526,
"z1": -128,
"x2": 945,
"y2": 1537,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "Imp",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "f4f8aa84-982a-4bd5-a708-9724d8598dd7",
"name": "Spawner (313)",
"location": [
901,
1507,
2
],
"map": "Ilshenar",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 891,
"y1": 1497,
"z1": -128,
"x2": 912,
"y2": 1518,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "EvilMageLord",
"maxCount": 2,
"probability": 100
}
]
},
{
"$type": "Spawner",
"guid": "fc4fedc9-9489-4385-bf85-9ec569081f4a",
"name": "Spawner (313)",
"location": [
961,
1502,
-28
],
"map": "Ilshenar",
"count": 2,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"team": 0,
"spawnBounds": {
"x1": 955,
"y1": 1496,
"z1": -128,
"x2": 968,
"y2": 1509,
"z2": 128
},
"walkingRange": 10,
"entries": [
{
"name": "Ettin",
"maxCount": 2,
"probability": 100
}
]
}
]