## Summary Removes the dated `DynamicJson` JSON helper and migrates spawner JSON (de)serialization to a polymorphic `record SpawnerDto` hierarchy. `DynamicJson` was the last remaining consumer (regions moved off it in #1400). The key correctness improvement: **System.Text.Json deserializes plain DTO records, never a live `Item`.** Previously, deserializing directly into an `Item` meant STJ constructed world-registered objects *before* the data was validated — a malformed/hand-edited spawn file could leave orphaned spawner Items in the world save. Now a parse failure is GC-only; `dto.ToSpawner()` constructs the spawner only from a fully-validated DTO and self-cleans on failure. ## What changed - **New:** `SpawnerDto` (abstract) + `SpawnerDataDto` / `RegionSpawnerDto` / `ProximitySpawnerDto`, each marked with a reusable `[JsonDiscoverableType]` opt-in attribute. Auto-discovered at the `Configure` phase — no manual registration list (avoids the regions `Register<T>()` footgun), open to custom spawner subtypes. - **Symmetric mapping:** `BaseSpawner.ToDto()` (export) ⇄ `SpawnerDto.ToSpawner()` (import). `ToSpawner()` deletes-and-rethrows on any failure, so the importer can never orphan an Item. - **`SpawnerJsonSerializer`** wires `$type` polymorphism on the `SpawnerDto` root with loud collision/constructibility validation. - **Import/export commands** rewired to the typed DTO path (reflection `FindTypeByName`/`CreateInstance` removed). - **Data migration:** the 109 `Distribution/Data/Spawns/**` files moved from `"type"`→`"$type"` and legacy `homeRange`→`spawnBounds`. The runtime still *reads* legacy `homeRange` for external files. The `homeRange→spawnBounds` formula is proven equivalent to the runtime conversion (`BoundsEquivalenceTests`, hr=0/1/3/7). - **Deleted:** `Projects/Server/Json/DynamicJson.cs`. Sparse export output matches the legacy `ToJson` (nullable DTO properties + `WhenWritingNull`). Binary world-save serialization is untouched. ## Tests - DTO round-trip per spawner type; sparse-default omission; legacy `homeRange` read; export/import file round-trip. - `Import_MalformedFile_LeaksNoWorldItems` — proves a mid-array parse failure constructs zero world Items. - `AllSpawnFilesLoadTests` — every migrated spawn file deserializes and builds. - Duplicate-discriminator validation. - UOContent.Tests 485/485, Server.Tests 710/710, build clean. ## Follow-up (not in this PR) `Rectangle3DConverter.Write` (in `Projects/Server/`) omits `z1/z2` when `Start.Z == -128`, so a future server-side export of a `homeRange`-style spawner round-trips depth 256→255. Pre-existing and out of scope here (Server change); the migrated data reads correctly. Worth a separate small converter PR.
836 lines
21 KiB
JSON
836 lines
21 KiB
JSON
[
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "0077d996-0107-433c-868d-32757f57d4ec",
|
|
"name": "Spawner (107)",
|
|
"location": [5722, 1390, 1],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 7,
|
|
"walkingRange": 7,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel3", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "017e2ed5-fb4e-4776-9c76-cff6f836f32d",
|
|
"name": "Spawner (107)",
|
|
"location": [5787, 1386, -2],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "HellCat", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "06eeaf2c-c00f-42fa-8c42-539a81928818",
|
|
"name": "Spawner (107)",
|
|
"location": [5656, 1412, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 0,
|
|
"walkingRange": 10,
|
|
"entries": [
|
|
{ "name": "EvilMageLord", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "07e0ca08-16a9-4ea3-9349-bc11d1d86995",
|
|
"name": "Spawner (107)",
|
|
"location": [5717, 1333, 6],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "LavaLizard", "maxCount": 1, "probability": 100 },
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "0eb73fc0-e467-4792-ad60-4d3102e26915",
|
|
"name": "Spawner (107)",
|
|
"location": [5693, 1415, 38],
|
|
"map": "Trammel",
|
|
"count": 4,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "Slime", "maxCount": 1, "probability": 100 },
|
|
{ "name": "GiantRat", "maxCount": 2, "probability": 100 },
|
|
{ "name": "GiantSerpent", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "193c201f-41f0-4dad-a2d7-0bcf80e30199",
|
|
"name": "Spawner (107)",
|
|
"location": [5867, 1309, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "HellCat", "maxCount": 1, "probability": 100 },
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "19c7452e-c000-43d9-97f9-7e969d89bda8",
|
|
"name": "Spawner (107)",
|
|
"location": [5638, 1439, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 0,
|
|
"walkingRange": 40,
|
|
"entries": [
|
|
{ "name": "EvilMageLord", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "1f8ce435-dfce-4ebc-ac13-34516a8067a7",
|
|
"name": "Spawner (107)",
|
|
"location": [5731, 1379, 0],
|
|
"map": "Trammel",
|
|
"count": 4,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 7,
|
|
"entries": [
|
|
{ "name": "Lich", "maxCount": 3, "probability": 100 },
|
|
{ "name": "LichLord", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "20407dd7-05e5-4af7-8771-bcf92a833e0d",
|
|
"name": "Spawner (107)",
|
|
"location": [5859, 1341, -1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "263d2d5e-da10-4537-ac29-3010728ca3b4",
|
|
"name": "Spawner (107)",
|
|
"location": [5699, 1302, 1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 15,
|
|
"walkingRange": 15,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "2a2291bc-7a04-4d90-be90-c9541aec5498",
|
|
"name": "Spawner (107)",
|
|
"location": [5678, 1340, -2],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 30,
|
|
"entries": [
|
|
{ "name": "HellHound", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellCat", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "3a2c62cd-5e59-4da4-a2ce-9a0c5c93febd",
|
|
"name": "Spawner (107)",
|
|
"location": [5643, 1403, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "3c4823a0-17b4-43bc-8033-ee7cde4874fd",
|
|
"name": "Spawner (107)",
|
|
"location": [5654, 1380, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 5,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "3dd210f5-6903-45b5-874a-1213f20378aa",
|
|
"name": "Spawner (107)",
|
|
"location": [5667, 1315, 5],
|
|
"map": "Trammel",
|
|
"count": 3,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"spawnBounds": {
|
|
"start": { "x": 5647, "y": 1295, "z": -128 },
|
|
"end": { "x": 5687, "y": 1335, "z": 20 }
|
|
},
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "Efreet", "maxCount": 2, "probability": 100 },
|
|
{ "name": "LavaLizard", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "3f1fa8e4-0461-43c5-915d-1f8d6243c984",
|
|
"name": "Spawner (107)",
|
|
"location": [5651, 1443, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "40fc9fd2-ec56-4328-ba07-79287c997be5",
|
|
"name": "Spawner (107)",
|
|
"location": [5714, 1465, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 7,
|
|
"walkingRange": 7,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel2", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "456851f3-5839-4c42-b5e2-5bebcb146b2b",
|
|
"name": "Spawner (107)",
|
|
"location": [5643, 1435, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 2,
|
|
"walkingRange": 2,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel4", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "4b7d444d-5a83-4a4a-9f9b-f268080c00c6",
|
|
"name": "Spawner (107)",
|
|
"location": [5647, 1439, 22],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 1,
|
|
"walkingRange": 15,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "56b8cca4-7325-4d9f-ae81-dfbe47bf02b5",
|
|
"name": "Spawner (107)",
|
|
"location": [5852, 1468, 1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 25,
|
|
"walkingRange": 30,
|
|
"entries": [
|
|
{ "name": "LavaSnake", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "580578d9-a4f1-4054-8d68-ca645c60d4c4",
|
|
"name": "Spawner (107)",
|
|
"location": [5650, 1419, 22],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 2,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "63aa9c1a-6933-4ee4-bbf5-fbaed82df249",
|
|
"name": "Spawner (107)",
|
|
"location": [5689, 1387, 1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 5,
|
|
"walkingRange": 10,
|
|
"entries": [
|
|
{ "name": "EvilMageLord", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "641ecc65-2a7a-4d79-8d6d-09064de015b9",
|
|
"name": "Spawner (107)",
|
|
"location": [5691, 1347, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "Daemon", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "6ac34bad-d1e3-4d92-b379-d07ad3e49439",
|
|
"name": "Spawner (107)",
|
|
"location": [5818, 1379, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "6e37e3a4-0e7e-474f-8f47-762a96993d74",
|
|
"name": "Spawner (107)",
|
|
"location": [5679, 1438, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 5,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel2", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "72406438-fb9d-4ffb-8daa-a290a93efba5",
|
|
"name": "Spawner (107)",
|
|
"location": [5835, 1304, 0],
|
|
"map": "Trammel",
|
|
"count": 6,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 15,
|
|
"walkingRange": 30,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 4, "probability": 100 },
|
|
{ "name": "Efreet", "maxCount": 1, "probability": 100 },
|
|
{ "name": "LavaSerpent", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "7e6d1ab1-e613-416e-98c1-943cfdc638ea",
|
|
"name": "Spawner (107)",
|
|
"location": [5680, 1438, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "EvilMageLord", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "82c4dd19-052a-4f08-a8d7-540d994eee6e",
|
|
"name": "Spawner (107)",
|
|
"location": [5723, 1291, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "835ef9b2-6755-46e7-bf92-e2004cd6b3f9",
|
|
"name": "Spawner (107)",
|
|
"location": [5809, 1332, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "LavaSnake", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "849224e3-2e29-427b-80eb-0a151e93e199",
|
|
"name": "Spawner (107)",
|
|
"location": [5651, 1408, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 2,
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "HellHound", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "85f5476d-1709-4dc9-b429-dadbc4f40506",
|
|
"name": "Spawner (107)",
|
|
"location": [5715, 1465, -1],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 7,
|
|
"walkingRange": 7,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel3", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "9253307c-4dbe-44bb-9e7f-7177e491daf7",
|
|
"name": "Spawner (107)",
|
|
"location": [5717, 1465, -2],
|
|
"map": "Trammel",
|
|
"count": 3,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 15,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 3, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "93d283d5-a55c-47a8-b022-cb2807cd6864",
|
|
"name": "Spawner (107)",
|
|
"location": [5790, 1451, 7],
|
|
"map": "Trammel",
|
|
"count": 4,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 5,
|
|
"walkingRange": 15,
|
|
"entries": [
|
|
{ "name": "Efreet", "maxCount": 1, "probability": 100 },
|
|
{ "name": "LavaSerpent", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellHound", "maxCount": 1, "probability": 100 },
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "a3a036ef-e0c6-4c5c-9573-2117548224e9",
|
|
"name": "Spawner (107)",
|
|
"location": [5744, 1471, 2],
|
|
"map": "Trammel",
|
|
"count": 6,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 15,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 3, "probability": 100 },
|
|
{ "name": "LavaSnake", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellCat", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellHound", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "a5f9ec55-e754-40f7-a83c-dfd7b78efc93",
|
|
"name": "Spawner (107)",
|
|
"location": [5651, 1435, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "ab04e5e0-3592-4288-b924-ac2f2b78aac7",
|
|
"name": "Spawner (107)",
|
|
"location": [5650, 1434, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 2,
|
|
"walkingRange": 2,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel3", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "c15a4f6b-9710-4def-b8d0-09c117d33575",
|
|
"name": "Spawner (107)",
|
|
"location": [5651, 1418, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 2,
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 },
|
|
{ "name": "EvilMageLord", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "c474fe51-44fd-4dc4-8a50-2a35fb00bfe8",
|
|
"name": "Spawner (107)",
|
|
"location": [5733, 1433, 22],
|
|
"map": "Trammel",
|
|
"count": 3,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "GiantRat", "maxCount": 1, "probability": 100 },
|
|
{ "name": "LavaSnake", "maxCount": 1, "probability": 100 },
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "c4aa67ce-4174-42c6-a18c-54d72771a68e",
|
|
"name": "Spawner (107)",
|
|
"location": [5643, 1435, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 3,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "c6978e2b-eb18-46b6-8809-1dba551a5efc",
|
|
"name": "Spawner (107)",
|
|
"location": [5651, 1363, 0],
|
|
"map": "Trammel",
|
|
"count": 8,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"spawnBounds": {
|
|
"start": { "x": 5648, "y": 1360, "z": 0 },
|
|
"end": { "x": 5654, "y": 1366, "z": 15 }
|
|
},
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellHound", "maxCount": 5, "probability": 100 },
|
|
{ "name": "LavaSnake", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellCat", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "c7d55c1f-b262-4f11-a264-c731516e29a4",
|
|
"name": "Spawner (107)",
|
|
"location": [5859, 1387, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "LavaLizard", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "c8ed6c9a-fa12-4cd8-8a14-e3eb1f07154a",
|
|
"name": "Spawner (107)",
|
|
"location": [5836, 1364, 1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "LavaSnake", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "cf42e1f4-a588-42f6-a9ec-f25f181ca6ae",
|
|
"name": "Spawner (107)",
|
|
"location": [5852, 1468, 1],
|
|
"map": "Trammel",
|
|
"count": 17,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 25,
|
|
"walkingRange": 30,
|
|
"entries": [
|
|
{ "name": "Lich", "maxCount": 4, "probability": 100 },
|
|
{ "name": "BoneMagi", "maxCount": 6, "probability": 100 },
|
|
{ "name": "SkeletalMage", "maxCount": 6, "probability": 100 },
|
|
{ "name": "HellCat", "maxCount": 1, "probability": 100 },
|
|
{ "name": "HellHound", "maxCount": 3, "probability": 100 },
|
|
{ "name": "FireElemental", "maxCount": 2, "probability": 100 },
|
|
{ "name": "LavaLizard", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "d402bb06-3c2f-4151-bd55-a97f1459aa8c",
|
|
"name": "Spawner (107)",
|
|
"location": [5787, 1427, 17],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "LavaLizard", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "df5837df-c256-4851-9863-5c9338442d8e",
|
|
"name": "Spawner (107)",
|
|
"location": [5732, 1297, -1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 5,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "HellHound", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "df760fe6-6df1-45ac-a3c2-0f27637dd457",
|
|
"name": "Spawner (107)",
|
|
"location": [5695, 1434, -1],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "Slime", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "e56c3640-05b4-407f-b362-11a83dfc9670",
|
|
"name": "Spawner (107)",
|
|
"location": [5651, 1402, 0],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 2,
|
|
"walkingRange": 3,
|
|
"entries": [
|
|
{ "name": "EvilMage", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "eb42506a-19bf-470c-a4b6-4e96d6ede07f",
|
|
"name": "Spawner (107)",
|
|
"location": [5747, 1320, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "FireElemental", "maxCount": 1, "probability": 100 },
|
|
{ "name": "LavaSerpent", "maxCount": 1, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "f3c05932-b64d-45a7-aaf0-98bae95935e7",
|
|
"name": "Spawner (107)",
|
|
"location": [5709, 1364, -1],
|
|
"map": "Trammel",
|
|
"count": 6,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 10,
|
|
"walkingRange": 20,
|
|
"entries": [
|
|
{ "name": "HellHound", "maxCount": 6, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "f8a27029-7a4d-4bc6-99c7-1e691e0e6c45",
|
|
"name": "Spawner (107)",
|
|
"location": [5679, 1439, 0],
|
|
"map": "Trammel",
|
|
"count": 2,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 5,
|
|
"walkingRange": 5,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel3", "maxCount": 2, "probability": 100 }
|
|
]
|
|
},
|
|
{
|
|
"$type": "Spawner",
|
|
"guid": "fc9a02b7-3d5f-4609-b586-907c4ca497ee",
|
|
"name": "Spawner (107)",
|
|
"location": [5723, 1390, 2],
|
|
"map": "Trammel",
|
|
"count": 1,
|
|
"minDelay": "00:05:00",
|
|
"maxDelay": "00:10:00",
|
|
"team": 0,
|
|
"homeRange": 7,
|
|
"walkingRange": 7,
|
|
"entries": [
|
|
{ "name": "TreasureChestLevel2", "maxCount": 1, "probability": 100 }
|
|
]
|
|
}
|
|
]
|