This topic is the result of some tests and discussions. It'll expose some knowledge about how the mazes of the game are made, thus allowing you to edit the corresponding ds1 in the way they're used by the game.
FIRST EXEMPLE (slightly increased Den Of Evil)
First of all, check that screenshot. This is the Den of Evil maze, after I have changed its size in LvlMaze.txt to 6. I have draw lines to show that the maze is composed of 7 'Rooms'. Each Rooms is in fact a DS1. Here's a diagram of the placment and links of these DS1 (the North in the game is the Upper/Right corner) :
Code: Select all
O <----- Start
|
O-O
|
O-O
|
O-O <--- CorpseFire
Code: Select all
caveSpre2.ds1
(3, 85)
|
|
|
caveNE2.ds1 caveSW.ds1
(3, 62) ----- (3, 57)
|
|
|
caveSE2.ds1 caveNW2.ds1
(3, 58) ----- (3, 61)
|
|
|
caveNE.ds1 caveWspec.ds1
(3, 62) ----- (3, 95)
Anyway, it's not always a straight pattern. With Rooms = 4, I had this kind of map :
Code: Select all
O <----- Start
|
O-O <--- CorpseFire
|
O
SECOND EXEMPLE (largely increased Den Of Evil)
This time in LvlMaze.txt I have set the Rooms to 20. I needed quite some time to revealed the entire map, but in the end here it is :
Large Den of Evil
The same, with a grid over it
Large Den of Evil (grid)
As you see, there's 21 DS1, and 24 nodes :
Code: Select all
O-O-O
| |
O-O O-O
| | |
O-O-O-O
| |
O-O-O-O <--- start
| |
O-O-O
|
O-O
|
O <--------- CorpseFire
Note 1 : for testing HUGE Rooms numbers someone will better have to make simple DS1 of 3*3 tiles. That way, even with that huge number of Rooms, since each rooms is very small, it won't take hours to explore it.
Note 2 : I think the maze must fit in Levels.txt. Here, we have 5 DS1 * 7 DS1, each one beeing 25*25 tiles, so the maze fit in an area of 125*175 Tiles, which are included into the 200*200 defined in levels.txt for the cave1. I haven't tried to make it larger (20 Rooms was quite long enough to explore for the purpose of just testing).
MAZE DS1 NAMING CONVENTION
I found that the elements composing a maze are 15 different ds1, all the possible combinations with at least 1 passage open. The name of the DS1 are not only easy to understand (like caveE for a cave with an open passage to the East), but they're also following a naming convention, and maybe in fact it's use deeply into the code...
Say that we use a number with 4 bits, each position for a given direction. N S E W is the order. Now, looks this :
Code: Select all
....NSEW
--------
00000000 = 0 = no opening, not used
00000001 = 1 = W
00000010 = 2 = E
00000011 = 3 = EW
00000100 = 4 = S
00000101 = 5 = SW
00000110 = 6 = SE
00000111 = 7 = SEW
00001000 = 8 = N
00001001 = 9 = NW
00001010 = 10 = NE
00001011 = 11 = NEW
00001100 = 12 = NS
00001101 = 13 = NSW
00001110 = 14 = NSE
00001111 = 15 = NSEW
Act 1 - Cave W
Act 1 - Cave E
Act 1 - Cave EW
Act 1 - Cave S
Act 1 - Cave SW
Act 1 - Cave SE
Act 1 - Cave SEW
Act 1 - Cave N
Act 1 - Cave NW
Act 1 - Cave NE
Act 1 - Cave NEW
Act 1 - Cave NS
Act 1 - Cave NSW
Act 1 - Cave NSE
Act 1 - Cave NSEW
Looks familiar ? All element in all maze (cave, crypt, barracks ...) are following this pattern.
Be aware that in LvlPrest.txt each type of DS1 of a maze is coming into several variants (the columns File1 to File6). That way, when the game wants to use a NSE type DS1 for instance, it won't always take the same, it'll take one of the available variants of the NSE DS1, thus bringing variations if the final layout of the map. I'm not sure if you can *add* new variants tough, I was told that the game is hardcoded to only take 1 DS1 between the first 2 columns...
Now, let's make a map :
ds1 placment:
Code: Select all
O
|
O-O
|
O
Code: Select all
S
|
NSE-W
|
N
Code: Select all
4
|
14-1
|
8
In summary, I think the game, when building a maze, use a table. Each element of this table (the Dungeon Room Logic Grid) should be a number between 1 and 15, telling not only the passages between the ds1 (the binary), but also in the meantime the name of the ds1 (associating a letter to each bit wich is set)... Therefore it's not so difficult to create a maze, so ... once this code is find, we might do some tricks easily (our own maze-building logic anyone ?)
Not really usefull for the end-user, but for a programmer that'll looks for a code, that may be interesting. Maybe one day we'll be able to code our own maps in the game ?
Also, be aware that the layout of the maze is dependant of the Level Type of the area. The number of Warps, the presence or not of Special DS1 (like CorpseFire in the Den of Evil)... is determined by the Level Type. Changing the Den of Evil from Act 1 Caves to Act 5 Ice Caves (there's a tutorial for that) makes the Den of Evil have 3 exits instead of 1. Also, the Arcane Sanctuary and the Nihlatak mazes for instance are always placing the entrance in the middle of the maze. That layout is something which is hardcoding, and that we can't change (yet ?).
Now, I'll let Myhrginoc speak :
I was able to climb up a couple of levels and find this code (v1.09b):
Code: Select all
6FD77190 /$ SUB ESP,438
6FD77196 |. PUSH EBX
6FD77197 |. MOV EBX,ECX
6FD77199 |. PUSH EBP
6FD7719A |. PUSH ESI
6FD7719B |. MOV EAX,DWORD PTR DS:[EBX+20]
6FD7719E |. MOV ECX,DWORD PTR DS:[EBX]
6FD771A0 |. XOR EDX,EDX
6FD771A2 |. PUSH EDI
6FD771A3 |. MOV ESI,DWORD PTR DS:[EAX+8] ; "ptGetPreset"
6FD771A6 |. MOV ECX,DWORD PTR DS:[ECX]
6FD771A8 |. MOV EAX,DWORD PTR DS:[ESI+C]
6FD771AB |. MOV DWORD PTR SS:[ESP+30],EBX
6FD771AF |. MOV EDI,DWORD PTR DS:[ECX+4]
6FD771B2 |. LEA EBP,DWORD PTR DS:[ESI+C]
6FD771B5 |. CMP EAX,EDX
6FD771B7 |. JNZ SHORT D2Common.6FD771E6
6FD771B9 |. MOV EAX,DWORD PTR DS:[ESI+4]
6FD771BC |. LEA EAX,DWORD PTR DS:[EAX+EAX*2]
6FD771BF |. LEA EDX,DWORD PTR DS:[EAX+EAX*4] ; 15 * [ESI+4]
6FD771C2 |. MOV EAX,DWORD PTR DS:[ESI+8] ; ptr to LvlPrest.bin record
6FD771C5 |. LEA EDX,DWORD PTR DS:[EAX+EDX*4+44] ; get the name string for the file
6FD771C9 |. PUSH EDX
6FD771CA |. MOV EDX,DWORD PTR DS:[ECX+8]
6FD771CD |. MOV ECX,EBP
6FD771CF |. CALL D2Common.6FD76AD0 ; ds1 loader is down in here
Code: Select all
6FD771BF |. LEA EDX,DWORD PTR DS:[EAX+EAX*4] ; 15 * [ESI+4]
15 is the width of the string in the .bin for each File columns
Here are two records of a structure I have only a dim idea about, the second one was retrieved at line 6FD771A3. I do not know how this structure is loaded.
Code: Select all
05864100 55 00 00 00 00 00 00 00 80 9F 5E 02 80 5D 86 05 U.......€Ÿ^€]†
05864110 DC 05 00 00 E8 03 00 00 18 00 00 00 18 00 00 00 Ü..è........
05864120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
05864130 00 00 00 00 00 00 00 00 C0 8B B4 02 00 00 00 00 ........À‹´....
05864140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
05864150 00 00 00 00 80 40 86 05 00 00 00 00 00 00 00 00 ....€@†........
05864160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
05864170 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
05864180 3E 00 00 00 01 00 00 00 B0 78 5E 02 00 00 00 00 >......°x^....
05864190 DC 05 00 00 00 04 00 00 18 00 00 00 18 00 00 00 Ü...........
058641A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
058641B0 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 ...............
058641C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
058641D0 00 00 00 00 00 41 86 05 00 00 00 00 00 00 00 00 .....A†........
058641E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
058641F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+00 DEF number from LvlPrest.bin
+04 File index number for fields File1 to File6 in LvlPrest.bin File# where # = (index+1)
+08 Record pointer for LvlPrest.bin
+10 OffsetX from Leveldefs.bin
+14 OffsetY from Leveldefs.bin
+18 SizeX from LvlPrest.bin
+1C SizeY from LvlPrest.bin
+54 previous record in a linked list of pGetPresets
Okay, now look at the actual LvlPrest.bin record:
Code: Select all
025E78B0 3E 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 >..............
025E78C0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 ..............
025E78D0 00 00 00 00 00 00 00 00 18 00 00 00 18 00 00 00 ..............
025E78E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E78F0 02 00 00 00 44 41 54 41 5C 47 4C 4F 42 41 4C 5C ...DATA\GLOBAL\
025E7900 54 49 4C 45 53 5C 41 63 74 31 5C 43 61 76 65 73 TILES\Act1\Caves
025E7910 5C 43 61 76 65 4E 45 2E 64 73 31 00 00 00 00 00 \CaveNE.ds1.....
025E7920 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7930 44 41 54 41 5C 47 4C 4F 42 41 4C 5C 54 49 4C 45 DATA\GLOBAL\TILE
025E7940 53 5C 41 63 74 31 5C 43 61 76 65 73 5C 43 61 76 S\Act1\Caves\Cav
025E7950 65 4E 45 32 2E 64 73 31 00 00 00 00 00 00 00 00 eNE2.ds1........
025E7960 00 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 ............0...
025E7970 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7980 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7990 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E79A0 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 ........0.......
025E79B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E79C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E79D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E79E0 00 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 ....0...........
025E79F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7A00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7A10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7A20 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0...............
025E7A30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7A40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
025E7A50 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 ...............
Code: Select all
0012ECB0 6FDC970C ASCII "Def"
0012ECB4 00000002
0012ECB8 00000000
0012ECBC 00000000
0012ECC0 00000000
0012ECC4 6FDC9704 ASCII "LevelId"
0012ECC8 00000002
0012ECCC 00000000
0012ECD0 00000004
0012ECD4 00000000
0012ECD8 6FDC96F8 ASCII "Populate"
0012ECDC 00000002
0012ECE0 00000000
0012ECE4 00000008
0012ECE8 00000000
0012ECEC 6FDC96EC ASCII "Logicals"
0012ECF0 00000002
0012ECF4 00000000
0012ECF8 0000000C
0012ECFC 00000000
0012ED00 6FDC96E0 ASCII "Outdoors"
0012ED04 00000002
0012ED08 00000000
0012ED0C 00000010
0012ED10 00000000
0012ED14 6FDC96D8 ASCII "Animate"
0012ED18 00000002
0012ED1C 00000000
0012ED20 00000014
0012ED24 00000000
0012ED28 6FDC96CC ASCII "KillEdge"
0012ED2C 00000002
0012ED30 00000000
0012ED34 00000018
0012ED38 00000000
0012ED3C 6FDC96C0 ASCII "FillBlanks"
0012ED40 00000002
0012ED44 00000000
0012ED48 0000001C
0012ED4C 00000000
0012ED50 6FDC94E4 ASCII "SizeX"
0012ED54 00000002
0012ED58 00000000
0012ED5C 00000028
0012ED60 00000000
0012ED64 6FDC94DC ASCII "SizeY"
0012ED68 00000002
0012ED6C 00000000
0012ED70 0000002C
0012ED74 00000000
0012ED78 6FDC96B8 ASCII "AutoMap"
0012ED7C 00000002
0012ED80 00000000
0012ED84 00000030
0012ED88 00000000
0012ED8C 6FDC96B0 ASCII "Scan"
0012ED90 00000002
0012ED94 00000000
0012ED98 00000034
0012ED9C 00000000
0012EDA0 6FDC96A8 ASCII "Pops"
0012EDA4 00000002
0012EDA8 00000000
0012EDAC 00000038
0012EDB0 00000000
0012EDB4 6FDC96A0 ASCII "PopPad"
0012EDB8 00000002
0012EDBC 00000000
0012EDC0 0000003C
0012EDC4 00000000
0012EDC8 6FDC9698 ASCII "Files"
0012EDCC 00000002
0012EDD0 00000000
0012EDD4 00000040
0012EDD8 00000000
0012EDDC 6FDC9684 ASCII "File1"
0012EDE0 00000001
0012EDE4 0000003B
0012EDE8 00000044 <--- offset for beginning of file names
0012EDEC 00000000
0012EDF0 6FDC967C ASCII "File2"
0012EDF4 00000001
0012EDF8 0000003B
0012EDFC 00000080
0012EE00 00000000
0012EE04 6FDC9674 ASCII "File3"
0012EE08 00000001
0012EE0C 0000003B
0012EE10 000000BC
0012EE14 00000000
0012EE18 6FDC966C ASCII "File4"
0012EE1C 00000001
0012EE20 0000003B
0012EE24 000000F8
0012EE28 00000000
0012EE2C 6FDC9664 ASCII "File5"
0012EE30 00000001
0012EE34 0000003B
0012EE38 00000134
0012EE3C 00000000
0012EE40 6FDC965C ASCII "File6"
0012EE44 00000001
0012EE48 0000003B
0012EE4C 00000170
0012EE50 00000000
0012EE54 6FDC9654 ASCII "Dt1Mask"
0012EE58 00000002
0012EE5C 00000000
0012EE60 000001AC
0012EE64 00000000
0012EE68 6FDC9508 ASCII "Expansion"
0012EE6C 00000002
0012EE70 00000000
0012EE74 00000020
0012EE78 00000000
0012EE7C 6FDC5404 ASCII "end"
0012EE80 00000000
0012EE84 00000000
0012EE88 00000000
0012EE8C 00000000
CONCLUSION
So, why this knowledge is important for you ? It'll be usefull if you're planing to completly edit the DS1 of a maze. For instance, if you want to make all the caves DS1 looks like an underground castle, you'll have to take care of these points :
- You can resize the Rooms of the maze, but if you want to, then you'll have to edit all DS1 of that maze to be the exact same size, and edit LvlMaze.txt and LvlPrest.txt accordingly.
- Follow the naming convention to know where to put the exit of each Room
- Make the exit of each Room always at the same coordinates. For instance if you're making a ds1 like this :
Then make all DS1 with East exit at the exact same coordinates, like :
Code: Select all
+---+ | | | | | [color=orange][b]X[/b][/color] +---+
And don't forget to make all the West exit of the DS1 on the same coordinates also :Code: Select all
+XX-+ | | | | | [color=orange][b]X[/b][/color] +XX-+
Code: Select all
+---+ | | | | [color=orange][b]X[/b][/color] | +---+
- The higher the number of Rooms, the bigger the maze. But the final size of the maze is also dependant of the size of each Rooms. A 'big' maze (20 Rooms) with Rooms of only 3*3 tiles each is not that big in fact, while a maze of 5 Rooms but with each Rooms beeing 100*100 Tiles is huge.