diablo2-web/src/game/world-placement.ts

4908 lines
67 KiB
TypeScript

/**
* World coordinate placement and chaining for Diablo II levels.
*
* Resolves seamless adjacency along SEAMLESS_ADJACENCY and propagates coordinates
* from anchor levels (seeded from Levels.txt), aligning automap bounding boxes
* with zero gaps, zero overlaps, and zero tears.
*/
import type { WorldGraph, LevelRow, WorldEdge } from './world-graph.ts'
import { assignGateSides, buildWorldGraph } from './world-graph.ts'
export interface WorldOffset {
levelId: number
offsetX: number
offsetY: number
sizeX: number
sizeY: number
}
interface AnchorSpec {
readonly levelId: number
readonly offsetX: number
readonly offsetY: number
readonly sizeX?: number
readonly sizeY?: number
}
/**
* Anchor level coordinates seeded from Levels.txt / level definitions.
* Keyed by 0-based act index (0..4).
*/
export const ACT_ANCHORS: Readonly<Record<number, readonly AnchorSpec[]>> = {
// Act 1: Cold Plains (Level 3) at (1000, 1000)
0: [{ levelId: 3, offsetX: 1000, offsetY: 1000, sizeX: 80, sizeY: 80 }],
// Act 2: Lut Gholein (Level 40) at (1000, 1000), Canyon of Magi (Level 46) at (2500, 1000)
1: [
{ levelId: 40, offsetX: 1000, offsetY: 1000, sizeX: 56, sizeY: 56 },
{ levelId: 46, offsetX: 2500, offsetY: 1000, sizeX: 80, sizeY: 80 },
],
// Act 3: Kurast Docks (Level 75) at (1000, 1000)
2: [{ levelId: 75, offsetX: 1000, offsetY: 1000, sizeX: 64, sizeY: 48 }],
// Act 4: Pandemonium Fortress (Level 103) at (1000, 1000)
3: [{ levelId: 103, offsetX: 1000, offsetY: 1000, sizeX: 32, sizeY: 24 }],
// Act 5: Harrogath (Level 109) at (1000, 1000), Bloody Foothills (Level 110) at (760, 1000)
4: [
{ levelId: 109, offsetX: 1000, offsetY: 1000, sizeX: 40, sizeY: 40 },
{ levelId: 110, offsetX: 760, offsetY: 1000, sizeX: 240, sizeY: 48 },
],
}
/** Pre-baked canonical LevelRow records for all 136 game levels. */
export const CANONICAL_LEVEL_ROWS: readonly LevelRow[] = [
{
"id": 1,
"act": 0,
"name": "Act 1 - Town",
"drlgType": 2,
"sizeX": 56,
"sizeY": 40,
"waypoint": 0,
"position": 1,
"portal": 1,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 2,
"act": 0,
"name": "Act 1 - Wilderness 1",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
8,
8,
8,
8,
0
],
"warp": [
-1,
-1,
-1,
0,
1,
2,
3,
-1
]
},
{
"id": 3,
"act": 0,
"name": "Act 1 - Wilderness 2",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 1,
"position": 0,
"portal": 1,
"offsetX": 1000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
9,
9,
9,
9,
0
],
"warp": [
-1,
-1,
-1,
0,
1,
2,
3,
-1
]
},
{
"id": 4,
"act": 0,
"name": "Act 1 - Wilderness 3",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 2,
"position": 0,
"portal": 0,
"offsetX": 1000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
10,
10,
10,
10,
0
],
"warp": [
-1,
-1,
-1,
0,
1,
2,
3,
-1
]
},
{
"id": 5,
"act": 0,
"name": "Act 1 - Wilderness 4",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 3,
"position": 0,
"portal": 1,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
10,
10,
10,
10,
0
],
"warp": [
-1,
-1,
-1,
0,
1,
2,
3,
-1
]
},
{
"id": 6,
"act": 0,
"name": "Act 1 - Wilderness 5",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 4,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
20,
11,
11,
11,
11,
0
],
"warp": [
-1,
-1,
10,
0,
1,
2,
3,
-1
]
},
{
"id": 7,
"act": 0,
"name": "Act 1 - Wilderness 6",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 255,
"position": 0,
"portal": 1,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
12,
12,
12,
12,
0
],
"warp": [
-1,
-1,
-1,
0,
1,
2,
3,
-1
]
},
{
"id": 8,
"act": 0,
"name": "Act 1 - Cave 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1000,
"depend": 0,
"vis": [
2,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
4,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 9,
"act": 0,
"name": "Act 1 - Cave 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1300,
"depend": 0,
"vis": [
3,
0,
0,
0,
13,
0,
0,
0
],
"warp": [
4,
-1,
-1,
-1,
5,
-1,
-1,
-1
]
},
{
"id": 10,
"act": 0,
"name": "Act 1 - Cave 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1600,
"depend": 0,
"vis": [
4,
5,
0,
0,
14,
0,
0,
0
],
"warp": [
4,
4,
-1,
-1,
5,
-1,
-1,
-1
]
},
{
"id": 11,
"act": 0,
"name": "Act 1 - Cave 4",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1900,
"depend": 0,
"vis": [
6,
0,
0,
0,
15,
0,
0,
0
],
"warp": [
4,
-1,
-1,
-1,
5,
-1,
-1,
-1
]
},
{
"id": 12,
"act": 0,
"name": "Act 1 - Cave 5",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 2200,
"depend": 0,
"vis": [
7,
0,
0,
0,
16,
0,
0,
0
],
"warp": [
4,
-1,
-1,
-1,
5,
-1,
-1,
-1
]
},
{
"id": 13,
"act": 0,
"name": "Act 1 - Cave 2 Treasure",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 2500,
"depend": 0,
"vis": [
0,
9,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
4,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 14,
"act": 0,
"name": "Act 1 - Cave 3 Treasure",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 2624,
"depend": 0,
"vis": [
0,
10,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
4,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 15,
"act": 0,
"name": "Act 1 - Cave 4 Treasure",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 2748,
"depend": 0,
"vis": [
0,
11,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
4,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 16,
"act": 0,
"name": "Act 1 - Cave 5 Treasure",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 2872,
"depend": 0,
"vis": [
0,
12,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
4,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 17,
"act": 0,
"name": "Act 1 - Graveyard",
"drlgType": 3,
"sizeX": 40,
"sizeY": 48,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
18,
19,
0,
0,
0,
0,
0,
0
],
"warp": [
6,
7,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 18,
"act": 0,
"name": "Act 1 - Crypt 1 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1000,
"depend": 0,
"vis": [
17,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 19,
"act": 0,
"name": "Act 1 - Crypt 2 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1300,
"depend": 0,
"vis": [
17,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 20,
"act": 0,
"name": "Act 1 - Tower 2",
"drlgType": 2,
"sizeX": 8,
"sizeY": 8,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1600,
"depend": 0,
"vis": [
6,
21,
0,
0,
0,
0,
0,
0
],
"warp": [
11,
12,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 21,
"act": 0,
"name": "Act 1 - Crypt 3 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1000,
"depend": 0,
"vis": [
20,
22,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
9,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 22,
"act": 0,
"name": "Act 1 - Crypt 3 B",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1300,
"depend": 0,
"vis": [
21,
23,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
9,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 23,
"act": 0,
"name": "Act 1 - Crypt 3 C",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1600,
"depend": 0,
"vis": [
22,
24,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
9,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 24,
"act": 0,
"name": "Act 1 - Crypt 3 D",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1900,
"depend": 0,
"vis": [
23,
25,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
9,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 25,
"act": 0,
"name": "Act 1 - Crypt 3 E",
"drlgType": 2,
"sizeX": 30,
"sizeY": 30,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 2200,
"depend": 0,
"vis": [
24,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 26,
"act": 0,
"name": "Act 1 - Monastery",
"drlgType": 2,
"sizeX": 64,
"sizeY": 18,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
27,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 27,
"act": 0,
"name": "Act 1 - Courtyard 1",
"drlgType": 2,
"sizeX": 56,
"sizeY": 40,
"waypoint": 5,
"position": 0,
"portal": 1,
"offsetX": 0,
"offsetY": -40,
"depend": 26,
"vis": [
26,
28,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 28,
"act": 0,
"name": "Act 1 - Barracks",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
27,
29,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
14,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 29,
"act": 0,
"name": "Act 1 - Jail 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 6,
"position": 0,
"portal": 1,
"offsetX": 3500,
"offsetY": 1000,
"depend": 0,
"vis": [
28,
30,
0,
0,
0,
0,
0,
0
],
"warp": [
13,
14,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 30,
"act": 0,
"name": "Act 1 - Jail 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1300,
"depend": 0,
"vis": [
29,
31,
0,
0,
0,
0,
0,
0
],
"warp": [
13,
14,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 31,
"act": 0,
"name": "Act 1 - Jail 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1600,
"depend": 0,
"vis": [
30,
32,
0,
0,
0,
0,
0,
0
],
"warp": [
13,
13,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 32,
"act": 0,
"name": "Act 1 - Courtyard 2",
"drlgType": 2,
"sizeX": 18,
"sizeY": 20,
"waypoint": 7,
"position": 0,
"portal": 0,
"offsetX": 4000,
"offsetY": 1000,
"depend": 0,
"vis": [
31,
33,
0,
0,
0,
0,
0,
0
],
"warp": [
14,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 33,
"act": 0,
"name": "Act 1 - Cathedral",
"drlgType": 2,
"sizeX": 28,
"sizeY": 34,
"waypoint": 255,
"position": 0,
"portal": 1,
"offsetX": -4,
"offsetY": -34,
"depend": 32,
"vis": [
32,
34,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
15,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 34,
"act": 0,
"name": "Act 1 - Catacombs 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1000,
"depend": 0,
"vis": [
33,
35,
0,
0,
0,
0,
0,
0
],
"warp": [
16,
18,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 35,
"act": 0,
"name": "Act 1 - Catacombs 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 8,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1300,
"depend": 0,
"vis": [
34,
36,
0,
0,
0,
0,
0,
0
],
"warp": [
17,
18,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 36,
"act": 0,
"name": "Act 1 - Catacombs 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 1,
"offsetX": 4500,
"offsetY": 1600,
"depend": 0,
"vis": [
35,
37,
0,
0,
0,
0,
0,
0
],
"warp": [
17,
18,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 37,
"act": 0,
"name": "Act 1 - Catacombs 4",
"drlgType": 2,
"sizeX": 22,
"sizeY": 31,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1900,
"depend": 0,
"vis": [
36,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
17,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 38,
"act": 0,
"name": "Act 1 - Tristram",
"drlgType": 2,
"sizeX": 43,
"sizeY": 48,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 5000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 39,
"act": 0,
"name": "Act 1 - Moo Moo Farm",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 5000,
"offsetY": 1148,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 40,
"act": 1,
"name": "Act 2 - Town",
"drlgType": 2,
"sizeX": 56,
"sizeY": 56,
"waypoint": 9,
"position": 1,
"portal": 1,
"offsetX": 1000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
47,
47,
50,
0,
0,
0
],
"warp": [
-1,
-1,
19,
20,
24,
-1,
-1,
-1
]
},
{
"id": 41,
"act": 1,
"name": "Act 2 - Desert 1",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
55,
55,
55,
55,
0,
0,
0,
0
],
"warp": [
33,
34,
35,
36,
-1,
-1,
-1,
-1
]
},
{
"id": 42,
"act": 1,
"name": "Act 2 - Desert 2",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 11,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
56,
56,
56,
56,
0,
0,
0,
0
],
"warp": [
33,
34,
35,
36,
-1,
-1,
-1,
-1
]
},
{
"id": 43,
"act": 1,
"name": "Act 2 - Desert 3",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 13,
"position": 0,
"portal": 1,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
62,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
47,
-1,
-1,
-1
]
},
{
"id": 44,
"act": 1,
"name": "Act 2 - Desert 4",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 14,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
65,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
50,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 45,
"act": 1,
"name": "Act 2 - Desert 5",
"drlgType": 3,
"sizeX": 32,
"sizeY": 32,
"waypoint": 255,
"position": 0,
"portal": 1,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
58,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
37,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 46,
"act": 1,
"name": "Act 2 - Valley of the Kings",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 17,
"position": 1,
"portal": 1,
"offsetX": 2500,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
66,
67,
68,
69,
70,
71,
72
],
"warp": [
-1,
38,
39,
40,
41,
42,
43,
44
]
},
{
"id": 47,
"act": 1,
"name": "Act 2 - Sewer 1 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1000,
"depend": 0,
"vis": [
40,
40,
48,
0,
0,
0,
0,
0
],
"warp": [
22,
21,
23,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 48,
"act": 1,
"name": "Act 2 - Sewer 1 B",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 10,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1300,
"depend": 0,
"vis": [
47,
0,
49,
0,
0,
0,
0,
0
],
"warp": [
22,
-1,
23,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 49,
"act": 1,
"name": "Act 2 - Sewer 1 C",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1600,
"depend": 0,
"vis": [
48,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
22,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 50,
"act": 1,
"name": "Act 2 - Harem",
"drlgType": 2,
"sizeX": 16,
"sizeY": 19,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1000,
"depend": 0,
"vis": [
40,
0,
51,
51,
0,
0,
0,
0
],
"warp": [
25,
-1,
28,
29,
-1,
-1,
-1,
-1
]
},
{
"id": 51,
"act": 1,
"name": "Act 2 - Corrupt Harem 1",
"drlgType": 1,
"sizeX": 100,
"sizeY": 100,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1119,
"depend": 0,
"vis": [
50,
50,
52,
52,
0,
0,
0,
0
],
"warp": [
26,
27,
28,
29,
-1,
-1,
-1,
-1
]
},
{
"id": 52,
"act": 1,
"name": "Act 2 - Basement 1",
"drlgType": 1,
"sizeX": 100,
"sizeY": 100,
"waypoint": 15,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1319,
"depend": 0,
"vis": [
51,
51,
53,
53,
0,
0,
0,
0
],
"warp": [
26,
27,
32,
32,
-1,
-1,
-1,
-1
]
},
{
"id": 53,
"act": 1,
"name": "Act 2 - Basement 2",
"drlgType": 1,
"sizeX": 100,
"sizeY": 100,
"waypoint": 255,
"position": 0,
"portal": 1,
"offsetX": 2000,
"offsetY": 1519,
"depend": 0,
"vis": [
52,
52,
54,
54,
0,
0,
0,
0
],
"warp": [
30,
31,
32,
32,
-1,
-1,
-1,
-1
]
},
{
"id": 54,
"act": 1,
"name": "Act 2 - Basement 3",
"drlgType": 1,
"sizeX": 100,
"sizeY": 100,
"waypoint": 255,
"position": 1,
"portal": 1,
"offsetX": 2000,
"offsetY": 1719,
"depend": 0,
"vis": [
53,
53,
0,
0,
0,
0,
0,
0
],
"warp": [
30,
31,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 55,
"act": 1,
"name": "Act 2 - Tomb 1 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1000,
"depend": 0,
"vis": [
41,
0,
0,
0,
59,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
46,
-1,
-1,
-1
]
},
{
"id": 56,
"act": 1,
"name": "Act 2 - Tomb 2 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1300,
"depend": 0,
"vis": [
42,
0,
0,
0,
57,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
46,
-1,
-1,
-1
]
},
{
"id": 57,
"act": 1,
"name": "Act 2 - Tomb 2 B",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 12,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1600,
"depend": 0,
"vis": [
56,
0,
0,
0,
60,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
46,
-1,
-1,
-1
]
},
{
"id": 58,
"act": 1,
"name": "Act 2 - Tomb 3 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1900,
"depend": 0,
"vis": [
45,
0,
0,
0,
61,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
46,
-1,
-1,
-1
]
},
{
"id": 59,
"act": 1,
"name": "Act 2 - Tomb 1 Treasure",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 2200,
"depend": 0,
"vis": [
55,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 60,
"act": 1,
"name": "Act 2 - Tomb 2 Treasure",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 2500,
"depend": 0,
"vis": [
57,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 61,
"act": 1,
"name": "Act 2 - Tomb 3 Treasure",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 2800,
"depend": 0,
"vis": [
58,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 62,
"act": 1,
"name": "Act 2 - Lair 1 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1000,
"depend": 0,
"vis": [
43,
63,
0,
0,
0,
0,
0,
0
],
"warp": [
48,
49,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 63,
"act": 1,
"name": "Act 2 - Lair 1 B",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1300,
"depend": 0,
"vis": [
62,
64,
0,
0,
0,
0,
0,
0
],
"warp": [
48,
49,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 64,
"act": 1,
"name": "Act 2 - Lair 1 Treasure",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1600,
"depend": 0,
"vis": [
63,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
48,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 65,
"act": 1,
"name": "Act 2 - Sewer 2 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4000,
"offsetY": 1000,
"depend": 0,
"vis": [
44,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
22,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 66,
"act": 1,
"name": "Act 2 - Tomb Tal 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1000,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 67,
"act": 1,
"name": "Act 2 - Tomb Tal 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1300,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 68,
"act": 1,
"name": "Act 2 - Tomb Tal 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1600,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 69,
"act": 1,
"name": "Act 2 - Tomb Tal 4",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 1900,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 70,
"act": 1,
"name": "Act 2 - Tomb Tal 5",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 2200,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 71,
"act": 1,
"name": "Act 2 - Tomb Tal 6",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 2500,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 72,
"act": 1,
"name": "Act 2 - Tomb Tal 7",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4500,
"offsetY": 2800,
"depend": 0,
"vis": [
46,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
45,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 73,
"act": 1,
"name": "Act 2 - Duriel's Lair",
"drlgType": 2,
"sizeX": 32,
"sizeY": 47,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 4500,
"offsetY": 3100,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 74,
"act": 1,
"name": "Act 2 - Arcane",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 16,
"position": 1,
"portal": 1,
"offsetX": 5000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 75,
"act": 2,
"name": "Act 3 - Town",
"drlgType": 2,
"sizeX": 64,
"sizeY": 48,
"waypoint": 18,
"position": 1,
"portal": 0,
"offsetX": 1000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 76,
"act": 2,
"name": "Act 3 - Jungle 1",
"drlgType": 3,
"sizeX": 64,
"sizeY": 192,
"waypoint": 19,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
84,
85,
0,
0,
0,
0,
0,
0
],
"warp": [
51,
51,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 77,
"act": 2,
"name": "Act 3 - Jungle 2",
"drlgType": 3,
"sizeX": 64,
"sizeY": 192,
"waypoint": 20,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 78,
"act": 2,
"name": "Act 3 - Jungle 3",
"drlgType": 3,
"sizeX": 64,
"sizeY": 192,
"waypoint": 21,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
86,
88,
0,
0,
0,
0,
0,
0
],
"warp": [
53,
54,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 79,
"act": 2,
"name": "Act 3 - Kurast 1",
"drlgType": 3,
"sizeX": 80,
"sizeY": 64,
"waypoint": 22,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 80,
"act": 2,
"name": "Act 3 - Kurast 2",
"drlgType": 3,
"sizeX": 80,
"sizeY": 64,
"waypoint": 23,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
92,
92,
94,
95,
0,
0,
0,
0
],
"warp": [
57,
57,
61,
61,
-1,
-1,
-1,
-1
]
},
{
"id": 81,
"act": 2,
"name": "Act 3 - Kurast 3",
"drlgType": 3,
"sizeX": 80,
"sizeY": 64,
"waypoint": 24,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
92,
92,
96,
97,
0,
0,
0,
0
],
"warp": [
57,
57,
61,
61,
-1,
-1,
-1,
-1
]
},
{
"id": 82,
"act": 2,
"name": "Act 3 - Kurast 4",
"drlgType": 3,
"sizeX": 48,
"sizeY": 16,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
98,
99,
0,
0,
0,
0
],
"warp": [
-1,
-1,
61,
61,
-1,
-1,
-1,
-1
]
},
{
"id": 83,
"act": 2,
"name": "Act 3 - Travincal",
"drlgType": 3,
"sizeX": 64,
"sizeY": 64,
"waypoint": 25,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
100,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
64,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 84,
"act": 2,
"name": "Act 3 - Spider 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
76,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
52,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 85,
"act": 2,
"name": "Act 3 - Spider 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1300,
"depend": 0,
"vis": [
0,
76,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
52,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 86,
"act": 2,
"name": "Act 3 - Dungeon 1 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1000,
"depend": 0,
"vis": [
87,
78,
0,
0,
0,
0,
0,
0
],
"warp": [
56,
55,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 87,
"act": 2,
"name": "Act 3 - Dungeon 1 B",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1300,
"depend": 0,
"vis": [
90,
86,
0,
0,
0,
0,
0,
0
],
"warp": [
56,
55,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 88,
"act": 2,
"name": "Act 3 - Dungeon 2 A",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1600,
"depend": 0,
"vis": [
89,
78,
0,
0,
0,
0,
0,
0
],
"warp": [
56,
55,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 89,
"act": 2,
"name": "Act 3 - Dungeon 2 B",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1900,
"depend": 0,
"vis": [
91,
88,
0,
0,
0,
0,
0,
0
],
"warp": [
56,
55,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 90,
"act": 2,
"name": "Act 3 - Dungeon 1 Treasure",
"drlgType": 2,
"sizeX": 40,
"sizeY": 40,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2200,
"depend": 0,
"vis": [
0,
87,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
55,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 91,
"act": 2,
"name": "Act 3 - Dungeon 2 Treasure",
"drlgType": 2,
"sizeX": 40,
"sizeY": 40,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2340,
"depend": 0,
"vis": [
0,
89,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
55,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 92,
"act": 2,
"name": "Act 3 - Sewer 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1000,
"depend": 0,
"vis": [
80,
80,
81,
81,
93,
0,
0,
0
],
"warp": [
58,
59,
58,
59,
60,
-1,
-1,
-1
]
},
{
"id": 93,
"act": 2,
"name": "Act 3 - Sewer 2",
"drlgType": 2,
"sizeX": 18,
"sizeY": 22,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1300,
"depend": 0,
"vis": [
92,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
58,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 94,
"act": 2,
"name": "Act 3 - Temple 1",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1000,
"depend": 0,
"vis": [
80,
80,
0,
0,
0,
0,
0,
0
],
"warp": [
62,
63,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 95,
"act": 2,
"name": "Act 3 - Temple 2",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1124,
"depend": 0,
"vis": [
80,
80,
0,
0,
0,
0,
0,
0
],
"warp": [
62,
63,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 96,
"act": 2,
"name": "Act 3 - Temple 3",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1248,
"depend": 0,
"vis": [
81,
81,
0,
0,
0,
0,
0,
0
],
"warp": [
62,
63,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 97,
"act": 2,
"name": "Act 3 - Temple 4",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1372,
"depend": 0,
"vis": [
81,
81,
0,
0,
0,
0,
0,
0
],
"warp": [
62,
63,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 98,
"act": 2,
"name": "Act 3 - Temple 5",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1496,
"depend": 0,
"vis": [
82,
82,
0,
0,
0,
0,
0,
0
],
"warp": [
62,
63,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 99,
"act": 2,
"name": "Act 3 - Temple 6",
"drlgType": 2,
"sizeX": 24,
"sizeY": 24,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1620,
"depend": 0,
"vis": [
82,
82,
0,
0,
0,
0,
0,
0
],
"warp": [
62,
63,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 100,
"act": 2,
"name": "Act 3 - Mephisto 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1000,
"depend": 0,
"vis": [
101,
101,
83,
83,
0,
0,
0,
0
],
"warp": [
67,
68,
65,
66,
-1,
-1,
-1,
-1
]
},
{
"id": 101,
"act": 2,
"name": "Act 3 - Mephisto 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 26,
"position": 0,
"portal": 0,
"offsetX": 3500,
"offsetY": 1300,
"depend": 0,
"vis": [
102,
102,
100,
100,
0,
0,
0,
0
],
"warp": [
67,
68,
65,
66,
-1,
-1,
-1,
-1
]
},
{
"id": 102,
"act": 2,
"name": "Act 3 - Mephisto 3",
"drlgType": 2,
"sizeX": 41,
"sizeY": 29,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 3500,
"offsetY": 1600,
"depend": 0,
"vis": [
0,
0,
101,
101,
0,
0,
0,
0
],
"warp": [
-1,
-1,
65,
66,
-1,
-1,
-1,
-1
]
},
{
"id": 103,
"act": 3,
"name": "Act 4 - Town",
"drlgType": 2,
"sizeX": 32,
"sizeY": 24,
"waypoint": 27,
"position": 1,
"portal": 0,
"offsetX": 1000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 104,
"act": 3,
"name": "Act 4 - Mesa 1",
"drlgType": 3,
"sizeX": 80,
"sizeY": 64,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 105,
"act": 3,
"name": "Act 4 - Mesa 2",
"drlgType": 3,
"sizeX": 64,
"sizeY": 80,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 106,
"act": 3,
"name": "Act 4 - Mesa 3",
"drlgType": 3,
"sizeX": 80,
"sizeY": 64,
"waypoint": 28,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
107,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
69,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 107,
"act": 3,
"name": "Act 4 - Lava 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 29,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
106,
108,
0,
0,
0,
0,
0,
0
],
"warp": [
70,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 108,
"act": 3,
"name": "Act 4 - Diablo 1",
"drlgType": 3,
"sizeX": 120,
"sizeY": 120,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 1500,
"offsetY": 1000,
"depend": 0,
"vis": [
107,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 109,
"act": 4,
"name": "Act 5 - Town",
"drlgType": 2,
"sizeX": 40,
"sizeY": 40,
"waypoint": 30,
"position": 1,
"portal": 0,
"offsetX": 1000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 110,
"act": 4,
"name": "Act 5 - Siege 1",
"drlgType": 3,
"sizeX": 240,
"sizeY": 48,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 760,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 111,
"act": 4,
"name": "Act 5 - Barricade 1",
"drlgType": 3,
"sizeX": -1,
"sizeY": -1,
"waypoint": 31,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 112,
"act": 4,
"name": "Act 5 - Barricade 2",
"drlgType": 3,
"sizeX": -1,
"sizeY": -1,
"waypoint": 32,
"position": 0,
"portal": 0,
"offsetX": -1,
"offsetY": -1,
"depend": 0,
"vis": [
0,
0,
113,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
71,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 113,
"act": 4,
"name": "Act 5 - Ice Cave 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 33,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1000,
"depend": 0,
"vis": [
112,
115,
114,
0,
0,
0,
0,
0
],
"warp": [
73,
74,
75,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 114,
"act": 4,
"name": "Act 5 - Ice Cave 1A",
"drlgType": 1,
"sizeX": 64,
"sizeY": 64,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1300,
"depend": 0,
"vis": [
113,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
73,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 115,
"act": 4,
"name": "Act 5 - Ice Cave 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 34,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1464,
"depend": 0,
"vis": [
113,
117,
116,
0,
0,
0,
0,
0
],
"warp": [
73,
74,
75,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 116,
"act": 4,
"name": "Act 5 - Ice Cave 2A",
"drlgType": 1,
"sizeX": 32,
"sizeY": 32,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1764,
"depend": 0,
"vis": [
115,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
73,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 117,
"act": 4,
"name": "Act 5 - Barricade Snow",
"drlgType": 3,
"sizeX": 128,
"sizeY": 80,
"waypoint": 36,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 1896,
"depend": 0,
"vis": [
115,
0,
118,
0,
0,
0,
0,
0
],
"warp": [
72,
-1,
71,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 118,
"act": 4,
"name": "Act 5 - Ice Cave 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 37,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2076,
"depend": 0,
"vis": [
117,
120,
119,
0,
0,
0,
0,
0
],
"warp": [
73,
74,
75,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 119,
"act": 4,
"name": "Act 5 - Ice Cave 3A",
"drlgType": 1,
"sizeX": 32,
"sizeY": 32,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2376,
"depend": 0,
"vis": [
118,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
73,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 120,
"act": 4,
"name": "Act 5 - Mountain Top",
"drlgType": 2,
"sizeX": 20,
"sizeY": 28,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2508,
"depend": 0,
"vis": [
118,
128,
0,
0,
0,
0,
0,
0
],
"warp": [
79,
80,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 121,
"act": 4,
"name": "Act 5 - Temple Entrance",
"drlgType": 2,
"sizeX": 22,
"sizeY": 27,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 2000,
"offsetY": 2636,
"depend": 0,
"vis": [
0,
122,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
76,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 122,
"act": 4,
"name": "Act 5 - Temple 1",
"drlgType": 1,
"sizeX": 80,
"sizeY": 80,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2763,
"depend": 0,
"vis": [
121,
123,
0,
0,
0,
0,
0,
0
],
"warp": [
78,
77,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 123,
"act": 4,
"name": "Act 5 - Temple 2",
"drlgType": 1,
"sizeX": 80,
"sizeY": 80,
"waypoint": 35,
"position": 0,
"portal": 0,
"offsetX": 2000,
"offsetY": 2943,
"depend": 0,
"vis": [
122,
124,
0,
0,
0,
0,
0,
0
],
"warp": [
78,
77,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 124,
"act": 4,
"name": "Act 5 - Temple Boss",
"drlgType": 2,
"sizeX": 84,
"sizeY": 84,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 1000,
"depend": 0,
"vis": [
123,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
78,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 125,
"act": 4,
"name": "Act 5 - Hell 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 2500,
"offsetY": 1184,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 126,
"act": 4,
"name": "Act 5 - Hell 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 2500,
"offsetY": 1484,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 127,
"act": 4,
"name": "Act 5 - Hell 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 2500,
"offsetY": 1784,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 128,
"act": 4,
"name": "Act 5 - Baal Temple 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 2084,
"depend": 0,
"vis": [
120,
129,
0,
0,
0,
0,
0,
0
],
"warp": [
81,
82,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 129,
"act": 4,
"name": "Act 5 - Baal Temple 2",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 38,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 2384,
"depend": 0,
"vis": [
128,
130,
0,
0,
0,
0,
0,
0
],
"warp": [
81,
82,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 130,
"act": 4,
"name": "Act 5 - Baal Temple 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 2500,
"offsetY": 2684,
"depend": 0,
"vis": [
129,
131,
0,
0,
0,
0,
0,
0
],
"warp": [
81,
82,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 131,
"act": 4,
"name": "Act 5 - Throne Room",
"drlgType": 2,
"sizeX": 40,
"sizeY": 52,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 3000,
"offsetY": 1000,
"depend": 0,
"vis": [
130,
132,
0,
0,
0,
0,
0,
0
],
"warp": [
81,
82,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 132,
"act": 4,
"name": "Act 5 - World Stone",
"drlgType": 2,
"sizeX": 55,
"sizeY": 55,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 3000,
"offsetY": 1152,
"depend": 0,
"vis": [
131,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
81,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 133,
"act": 4,
"name": "Act 5 - Pandemonium 1",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 4000,
"offsetY": 1500,
"depend": 0,
"vis": [
17,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
8,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 134,
"act": 4,
"name": "Act 5 - Pandemonium 2",
"drlgType": 3,
"sizeX": 80,
"sizeY": 80,
"waypoint": 255,
"position": 1,
"portal": 1,
"offsetX": 4000,
"offsetY": 1700,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 135,
"act": 4,
"name": "Act 5 - Pandemonium 3",
"drlgType": 1,
"sizeX": 200,
"sizeY": 200,
"waypoint": 255,
"position": 1,
"portal": 0,
"offsetX": 4000,
"offsetY": 2884,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
},
{
"id": 136,
"act": 4,
"name": "Act 5 - Pandemonium Finale",
"drlgType": 2,
"sizeX": 43,
"sizeY": 48,
"waypoint": 255,
"position": 0,
"portal": 0,
"offsetX": 5000,
"offsetY": 1000,
"depend": 0,
"vis": [
0,
0,
0,
0,
0,
0,
0,
0
],
"warp": [
-1,
-1,
-1,
-1,
-1,
-1,
-1,
-1
]
}
]
/** Helper to derive dimensions for a level in world coordinates. */
export function getLevelDimensions(levelId: number, row?: LevelRow): { sizeX: number; sizeY: number } {
if (levelId === 111) return { sizeX: 58, sizeY: 155 }
if (levelId === 112) return { sizeX: 58, sizeY: 154 }
if (row && row.sizeX > 0 && row.sizeY > 0) {
return { sizeX: row.sizeX, sizeY: row.sizeY }
}
return { sizeX: 80, sizeY: 80 }
}
/**
* Resolve global world coordinates for all levels in an act.
*
* Chaining traverses contiguous outdoor levels along SEAMLESS_ADJACENCY from
* anchor levels (Cold Plains, Lut Gholein, Kurast Docks, Pandemonium Fortress,
* Harrogath / Bloody Foothills), propagating offsets according to seam sides
* so that adjacent levels touch with zero gaps and zero overlaps.
*
* @param act - The act number (1..5 or 0..4).
* @param seed - Act layout seed for gate side assignment.
* @param graph - Optional world graph; when omitted, builds from canonical level definitions.
* @returns Map from levelId to WorldOffset.
*/
function doRectanglesOverlap(a: WorldOffset, b: WorldOffset): boolean {
return (
a.offsetX < b.offsetX + b.sizeX &&
a.offsetX + a.sizeX > b.offsetX &&
a.offsetY < b.offsetY + b.sizeY &&
a.offsetY + a.sizeY > b.offsetY
)
}
function computeOffsetsForGraph(
activeGraph: WorldGraph,
targetAct: number,
): Map<number, WorldOffset> {
const actLevels = Array.from(activeGraph.levels.values()).filter(l => l.act === targetAct)
const levelMap = new Map(actLevels.map(l => [l.id, l]))
const result = new Map<number, WorldOffset>()
const queue: number[] = []
// 1. Seed anchor levels
const anchors = ACT_ANCHORS[targetAct] ?? []
for (const anchor of anchors) {
if (!levelMap.has(anchor.levelId)) continue
const row = levelMap.get(anchor.levelId)
const dims = getLevelDimensions(anchor.levelId, row)
const offset: WorldOffset = {
levelId: anchor.levelId,
offsetX: anchor.offsetX,
offsetY: anchor.offsetY,
sizeX: anchor.sizeX ?? dims.sizeX,
sizeY: anchor.sizeY ?? dims.sizeY,
}
result.set(anchor.levelId, offset)
queue.push(anchor.levelId)
}
// 2. BFS propagation along seamless adjacency
while (queue.length > 0) {
const currentId = queue.shift()!
const current = result.get(currentId)!
const edges = activeGraph.edges.filter(e => e.from === currentId && e.kind === 'seamless')
for (const edge of edges) {
const nextId = edge.to
if (result.has(nextId) || !levelMap.has(nextId)) continue
const nextRow = levelMap.get(nextId)
const nextDims = getLevelDimensions(nextId, nextRow)
let nextOffsetX: number
let nextOffsetY: number
// Ground-truth Act 5 barricade corridor alignment matching ka.ma0 Layer 79:
// Level 110 at (760, 1000) West gate connects to Level 111 (width 58) -> offset X = 702
// Level 111 connects North to Level 112 (width 58) -> offset X = 702
// Recorded cluster: X in [702..759], Y in [717..1026]
if (currentId === 110 && nextId === 111) {
nextOffsetX = current.offsetX - nextDims.sizeX // 760 - 58 = 702
nextOffsetY = 871
} else if (currentId === 111 && nextId === 112) {
nextOffsetX = 702
nextOffsetY = current.offsetY - nextDims.sizeY // 871 - 154 = 717
} else {
switch (edge.sideFrom) {
case 'east':
nextOffsetX = current.offsetX + current.sizeX
nextOffsetY = current.offsetY + Math.floor((current.sizeY - nextDims.sizeY) / 2)
break
case 'west':
nextOffsetX = current.offsetX - nextDims.sizeX
nextOffsetY = current.offsetY + Math.floor((current.sizeY - nextDims.sizeY) / 2)
break
case 'south':
nextOffsetX = current.offsetX + Math.floor((current.sizeX - nextDims.sizeX) / 2)
nextOffsetY = current.offsetY + current.sizeY
break
case 'north':
nextOffsetX = current.offsetX + Math.floor((current.sizeX - nextDims.sizeX) / 2)
nextOffsetY = current.offsetY - nextDims.sizeY
break
default:
nextOffsetX = current.offsetX + current.sizeX
nextOffsetY = current.offsetY
break
}
}
result.set(nextId, {
levelId: nextId,
offsetX: nextOffsetX,
offsetY: nextOffsetY,
sizeX: nextDims.sizeX,
sizeY: nextDims.sizeY,
})
queue.push(nextId)
}
}
// 3. Isolated independent levels (depend === 0): keep static offsets from Levels.txt
for (const row of actLevels) {
if (result.has(row.id) || (row.depend && row.depend > 0)) continue
const dims = getLevelDimensions(row.id, row)
const ox = row.offsetX !== -1 ? row.offsetX : 2000
const oy = row.offsetY !== -1 ? row.offsetY : 1000 + row.id * 50
result.set(row.id, {
levelId: row.id,
offsetX: ox,
offsetY: oy,
sizeX: dims.sizeX,
sizeY: dims.sizeY,
})
}
// 4. Dependent levels (row.depend > 0): resolve relative to parent origin
let resolvedAny = true
while (resolvedAny) {
resolvedAny = false
for (const row of actLevels) {
if (result.has(row.id)) continue
if (row.depend > 0 && result.has(row.depend)) {
const parent = result.get(row.depend)!
const dims = getLevelDimensions(row.id, row)
const relX = row.offsetX !== -1 ? row.offsetX : 0
const relY = row.offsetY !== -1 ? row.offsetY : 0
result.set(row.id, {
levelId: row.id,
offsetX: parent.offsetX + relX,
offsetY: parent.offsetY + relY,
sizeX: dims.sizeX,
sizeY: dims.sizeY,
})
resolvedAny = true
}
}
}
// 5. Fallback for any unplaced orphan levels (e.g. broken depend references)
for (const row of actLevels) {
if (result.has(row.id)) continue
const dims = getLevelDimensions(row.id, row)
const ox = row.offsetX !== -1 ? row.offsetX : 2000
const oy = row.offsetY !== -1 ? row.offsetY : 1000 + row.id * 50
result.set(row.id, {
levelId: row.id,
offsetX: ox,
offsetY: oy,
sizeX: dims.sizeX,
sizeY: dims.sizeY,
})
}
return result
}
function hasPlacementOverlap(offsets: Map<number, WorldOffset>): boolean {
const placed = Array.from(offsets.values())
for (let i = 0; i < placed.length; i++) {
for (let j = i + 1; j < placed.length; j++) {
if (doRectanglesOverlap(placed[i]!, placed[j]!)) return true
}
}
return false
}
/**
* Resolve global world coordinates for all levels in an act.
*
* Chaining traverses contiguous outdoor levels along SEAMLESS_ADJACENCY from
* anchor levels (Cold Plains, Lut Gholein, Kurast Docks, Pandemonium Fortress,
* Harrogath / Bloody Foothills), propagating offsets according to seam sides
* so that adjacent levels touch with zero gaps and zero overlaps.
*
* @param act - The act number (1..5 or 0..4).
* @param seed - Act layout seed for gate side assignment.
* @param graph - Optional world graph; when omitted, builds from canonical level definitions.
* @returns Map from levelId to WorldOffset.
*/
export function resolveWorldOffsets(
act: number,
seed: number,
graph?: WorldGraph,
): Map<number, WorldOffset> {
const targetAct = act >= 1 && act <= 5 ? act - 1 : (act >= 0 && act < 5 ? act : 0)
// If graph is provided and already has gate sides assigned, use it directly
if (graph && !graph.edges.some(e => e.kind === 'seamless' && e.sideFrom === null)) {
return computeOffsetsForGraph(graph, targetAct)
}
const baseGraph = graph ?? buildWorldGraph(CANONICAL_LEVEL_ROWS)
const maxAttempts = 64
let fallbackOffsets: Map<number, WorldOffset> | null = null
for (let attempt = 0; attempt < maxAttempts; attempt++) {
const attemptSeed = attempt === 0 ? seed : ((seed + attempt * 7919) >>> 0)
const activeGraph = assignGateSides(baseGraph, attemptSeed)
const offsets = computeOffsetsForGraph(activeGraph, targetAct)
if (!fallbackOffsets) {
fallbackOffsets = offsets
}
if (!hasPlacementOverlap(offsets)) {
return offsets
}
}
return fallbackOffsets!
}