Ds1edit docs + usefull links

Post here for all aspects of map making and level design. Click here to visit the Keep's official map site, Diabolic Cartography.

Moderator: Paul Siramy

Post Reply
User avatar
Paul Siramy
Retired staff
Principality
Posts: 2828
Joined: Sat May 25, 2002 2:39 pm
Location: La Garenne Colombes (near Paris)
Contact:
France

Hand-picked

Ds1edit docs + usefull links

Post by Paul Siramy » Fri Jun 07, 2002 10:01 pm

My Ds1edit documentation IN PROGRESS
I'll try to put here all you need to know, to be able to build your maps for Diablo II.

There isn't any thanks somewhere in my ds1edit for now, so I'll put them here. I want to give Big Special Thanks for all this persons (just chronological order) :
  • DJGPP Team, I have used this compiler for years, I loved it.
  • Allegro Team, this wonderfull game library I'm using for years help me a LOT to easily make Ms-dos & Console prog for Windows. Thanks for all the person who created it, and to all the ones who are still improving it.
  • Clannad, for his original doc on the DT1 format. Despite this is my work that found how the floor tiles were implemented, without his doc in the first place, I shouldn't be able to decode the dt1 format in the begining and therefore should have give up.
  • Isilweo, for both his doc on the DS1 format, and his ds1 editor. Without his doc I shouldn't be able to decode ds1 format and again should have give up. His editor, despite I never found it usefull for wysiwyg editing (sorry :mrgreen: ), have help me a lot during my investigations of the dt1 / ds1 relations (and will surely help me again when I'll implement objetcs and paths infos)
  • Tom Amigo & AK74, for having release the sources of their command-line mpq extractor, which allowed my prog to directly read the dt1 from mpq, which is such a great help for end-users (no need to extract all the dt1 they need)
  • Myrhginoc, for his complete list of Type 2 objects (it also have the ID in objects.txt, and it'll be pretty usefull)
  • TeknoKyo, for having discovered (and explained me) that in 1.10 the Type 1 objects that have a DS1 ID not defined in MonPreset.txt for the act of the ds1 don't produce errors, as this ds1 ID will be considered as a hcIdx in Monstats.txt. So you can place almost ALL monsters this way, just with their hcIdx, without using MonPreset.txt.
Without their help in the first place, this ds1edit would not even have been possible.



Overview of the ds1 files
* a ds1 is a map, whth floors, walls, npc, paths of npc, & monsters infos, objects like fire, flags...

* it is composed of a variable amount of layers :
- up to 4 floors layers
- up to 4 walls layers

the game first draw the floors layers, then the walls ones. It's more complex than that, but we'll see this point later.


Overview of the dt1 files
* dt1 are gfx data. It contains a bunch of tiles, and in D2 the tiles are in 3d-isometric shape. A dt1 usually have tiles of a the same theme, for instance "trees.dt1" contains map tiles, each one a part of a tree.

* a floor tile is 160*80 pixels size. It is divided into 5*5 (25) sub-tiles. look in "data\global\tiles\expansion\town\townwest.ds1" (town of harrogath), there are some strange blue floors, they're invisible when you play the map, but they're still here, to block your way on some area. Such a tile is divided into 5*5 elements. What you have to know is that each one of this sub-tile can be walkable or not, this is how the game know where you can walk. These walkable infos are in the dt1 too, as long as some other infos for the tile, like the sound index the game have to play when the player walk/run over it, the effects the game can do over the tile (river / rain / nothing ...), and some other datas.

* a wall tile is like a floor tile, except that he can have walls on it, therefore an undefined height of pixels (but still 160 pixels width). Note that even the walls tiles have floor sub-tiles walkable info : this is usualy to indicate on which corner are the walls.

---> walkable infos of the sub tiles are more complex than "walk : Y/N"... there are some portions of a tile where you can't walk, but you can still see enemys / throw weapons over them.

* another think to know, VERY IMORTANT : the order of the tiles in the dt1 is unsignificant. Each one of this tile have 3 index, which I'm used to call "Orientation", "Main index" and "Sub index" in my dt1 tools. The problem is... some dt1 can use (and in fact are using) the same 3 indexs of another tile, either a tile of the same dt1, or the tile of another. These 3 index can be view easily in my ds1edit : right-click, each tile have 4 numbers, in that order : "main index", "orientation" and "sub index", the last one is the "frame", which is usually "0" or "1". Not "0" means there are in the dt1 file another tiles with the exact same 3 index number, and in this case... theses tiles are composing a set of random tiles, hence the "view same random" button that still does nothing in my ds1edit, but it'll show later a window with all the tiles of the same set because you can only see the first tile of the same random set. The game is displaying one of these tile, randomly, whereever the ds1 tell to display one. That's a way to make "different" maps with the same ds1 : each time the player will come, the area will look different, because the game will choose random tiles.



How the game (and my ds1edit) use dt1
First, there's the Data\Global\Excel\LvlTypes.txt, which is a table of dt1. Each line is for a theme of dt1 (like "act3 tombs", or "arcane sanctuary", or "act1 town", "duriel", etc...). Each one of this list can have up to 32 dt1, NO MORE. There are very few lines in this file.

Now, here's come the problem : not ALL the dt1 of a list are necessary for a ds1. In other words, the game filter this list. It use a bitfield, but in the .txt it's not a string like "010111110101", but a decimal number, like 1525, remember that ! In the Data\Global\Excel\LvlPrest.txt, changing the Dt1Mask value change the dt1 that will be take from the list. Adding a dt1 to the list is not enough, you have to change the mask too, in order to take your specific dt1.

Say each file have a value, the final dt1mask is the sum of these values. Formula : File N = 2^(N-1)
  • File 1 = 1
  • File 2 = 2
  • File 3 = 4
  • File 4 = 8
  • File 5 = 16
  • File 6 = 32
  • File 7 = 64
  • ...
  • File 30 = 536,870,912
  • File 31 = 1,073,741,824
  • File 32 = 2,147,483,648
You want to use the dt1 in columns 'File 1', 'File 3' & 'File 5' (and none of the others) then your dt1mask will be 1 + 4 + 16 = 21.

Now, if you want to add tiles in your map, many way (but it seems there's problems when trying to add act5 dt1 for now).

* if the tiles already exists in the game, you'll usually add some dt1 in the Data\Global\Excel\LvlTypes.txt, then you change the Dt1Mask value in the Data\Global\Excel\LvlPrest.txt. Now, the ds1edit will load another dt1 before displaying the map, and you'll see your tiles if you right click.

* if they're not exists, you have to make a new dt1 (and then like above, add them to the 2 .txt ), or change some existings dt1. Changing dt1 (or adding tiles to it) save you from changing the .txt files.



DT1 to DS1 relation
* hardest part. This will explain why you can't have all the tiles you want in your map. how does the game know which gfx is to be displayed in a particular cell ? It's nothing like the dt1 index and the tile index whitin it. It's the 3 indexs of the dt1 I talk previously that indicate which tile is to be display at a specific cell.



Adding a ds1 to edit
My ds1edit.exe works the same way as my ds1scene.exe, that means you have to give parameters to the prog. Copy a .bat and rename it. Let's say you want to edit the town in act 2.
  1. Extract the ds1 in the directory of ds1edit. You better have to check first in patch_d2.mpq in case there's an update of this map, else in d2exp.mpq, else d2data.mpq. In our case, it's in d2data.mpq, but there are several ds1. Let's take \Data\Global\Tiles\Act2\Town\lutN.ds1
  2. copy a .bat and rename it, for instance "act2_town_N.bat"
  3. open the "LvlTypes.txt" of the game in Excel (or D2Excel), and look for the appropriate ID. In our case the choice is easy, it's "Act 2 - Town" and therefore the Id is 12 (this is NOT the row, but the Id you take).
  4. Open the "LvlPrest.txt" of the game and choose the good DEF. In our case, it's again easy : it's the row having "Act 2 - Town", and therefore the Def is 301.
  5. Edit the "act2_town_N.bat". Change the command line to have something like
    win_ds1edit lutN.ds1 12 301 > act2_town_N.txt
  6. launch the .bat. If your parameters are ok, you'll see the town correctly. If problems appear, that's because one, or both number parameters are false, retry with another values.

Finding easily what are the ID and DEF of a DS1
I'm using DRTester, made by Sloan Roy. Get it here (from the "file center / mod making tools / animation editing" section), or from SVR website (click on "Dr. Tester" and pick 1 of the zip). Whatever the version, you should be able to use it for finding ID and DEF as follow :
  1. launch DRTest.exe
  2. in the File menu, choose the mpq you want to browse, for instance D2Data
  3. use the file selector dialog box to quickly jump to your ds1 file by typing its full path,
    for instance data\global\tiles\ACT1\Graveyard\gravey.ds1
  4. Usually, the DEF is found automaticaly, check the upper / right window (the LvlPrest.txt file datas).
    Here, the line 108 : Act 1 - Graveyard is already selected, that's the DEF value you'll give to the ds1 editor

    If DrTester don't find the DEF value, that's because you're editing a special DS1. Open LvlSub.txt in Excel, and check if your DS1 is not there. If it is, then check its Dt1Mask value, and in LvlPrest.txt search for a line that have this EXACT same Dt1Mask, and use that DEF value (it's a trick). If the DS1 is not in LvlSub either, then good luck... as it's now the common Trials and Error method in DrTester, and you're not even sure that you'll find a good value. Btw, for common map editing, you don't have to edit DS1 that are not in LvlPrest.txt, so DrTester will be usefull for you.
  5. click 2 times on the '-' button, to have a Zoom of 0.25, just to have a larger view of the map
  6. now in the bottom / right window, try several Level Type lines, until the map looks good for you.
    Here, it's the line 2 : Act 1 - Wilderness, that'll be your ID value.
  7. You can drag and move the map by clicking on the image with the left button, keep the button hold, and then move the mouse. It's the "Ctrl + Home" keys to recenter the map automaticaly if you're lost (can happen by moving far from the center and then zooming in)
  8. ---> You have found the ID and DEF values to use with the editor (here 2 and 108).

Understand the Mazes and DS1 mechanism
If you're planing to change the DS1 of a maze of the game, you'd better have to check this topic


Creating new Warp Tiles in DT1
Check this topic to know how to create new stairs. The method is to duplicate its gfx and datas (in the DT1), but editing its Main index in order to be a new Vis to use in Levels.txt. So you can have a DS1 with 8 Stairs that all looks the same, but are the 8 possible Warps in Levels.txt an area can have.


A way to randomize preset levels
Check this topic to know how to randomize preset levels. In short, you'll use the column 'Files' and 'Files1' to 'File6' in LvlPrest.txt to force the game to pick a random DS1. That is, you can have random Tristram.


Tutorial: Move NPC out of town
Check this topic to know how to move a NPC (here Gheed) from Town to a wild area. You'll be able to talk / trade as usual with this NPC.


[Any] I found out a way to link outdoor areas together
Check this topic. In short, you make 2 preset ds1 and place them side by side in the worldspace, then you add to each of the ds1 an hiden Vis that link them (these 2 hidden Vis must be placed side by side in the worldspace too).


How to : Link a new preset outdoor area to act 1 Town
Check this topic to learn a way to place your own new preset area next to the Rogue Encampment, with a trick to move the (hardcoded) blood moor area in a safe place.


Making optional maps
Check this topic to know how to make some areas available in some game session, but not always. It's using LvlPrest randomization of the ds1.


last edit : 11 jully 2013, fixed some links
last edit : 05 december 2010, added a link to the topic : Link a new preset outdoor area to act 1 Town
last edit : 24 June 2004, 02:41, moved from Tools forum to Map Editing forum
last edit : 26 May 2004, 13:17, added a link to a topic explaing how to make random maps
last edit : 16 February 2004, 22:57, added a link to a topic explaing how to make 2 working preset outdoors ds1
last edit : 10 February 2004, 11:53, updated Dr. Tester explanation and urls
last edit : 11 August 2003, 00:22, added a link to know how to move NPC out of town
last edit : 8 August 2003, 00:22, added TeknoKyo in the Credits list
last edit : 5 August 2003, 01:06, in section "Add a ds1 to edit", change the name of the .exe prog from "ds1edit" to "win_ds1edit"
last edit : 11 July 2003, 21:40, add a link for section "A way to randomize preset levels"
last edit : 7 July 2003, 21:40, add a link for section "Creating new Warp Tiles in DT1"
last edit : 23 June 2003, 11:43, add a link to "Maze & Ds1 mechanisms"
last edit : 22 June 2003, 22:36, add the section that use DrTester for searching the ID and DEF of a DS1
last edit : 12 November 2002, 01:13, add Myrhginoc in the Credits list
last edit : 3 July, 21:03, update the "How the game (and my ds1edit) use dt1" (Add a Formula for Dt1Mask)
last edit : 16 June, 11:44, update the "How the game (and my ds1edit) use dt1" (no more dt1files.txt, nor dt1mask.txt)
last edit : 15 June, 17:09, update the "Adding a ds1 to edit" (no more dt1files.txt, nor dt1mask.txt)
last edit : 8 June, 22:18, added the "Adding a ds1 to edit" section
last edit : 8 June, 14:04, gave some thanks
Last edited by Paul Siramy on Thu Jun 24, 2004 1:38 am, edited 24 times in total.

User avatar
Paul Siramy
Retired staff
Principality
Posts: 2828
Joined: Sat May 25, 2002 2:39 pm
Location: La Garenne Colombes (near Paris)
Contact:
France

Hand-picked

Post by Paul Siramy » Mon Nov 18, 2002 3:22 am

Drawing Tiles of a DS1 (notes for any developer)

First, need to know what DT1 to use. Check lvlTypes.txt, that's a list of DT1 for several theme. Which theme is the ds1 ? Hardcoded in a dll I have heard, but we can also easily guess by the path of the ds1 in the mpq, like act1\Court means that it'll take "Act 1 - Courtyard" theme (ID = 6).

This was the base DT1 list. But in fact the ds1 don't use all of them. Check lvlPrest.txt, the column DT1mask is a bitfield value. 32 bits, and curiosly 32 columns in lvlTypes.txt for a list of DT1. DT1Mask AND (1 << (NUMBER - 1)) == 1 means that the DT1 file in the "File NUMBER" column will be used. Warning, if it's not the good DT1 List or the good DT1Mask you're using, then you might end with taking a "0" DT1 file, which don't exists of course. Try with act2\tomb\duriel.ds1 : if you're using all the dt1, then you'll have problems, but not if you're only taking the ones the DT1Mask tells you.

Now that we know which DT1, which tiles from them ? Not necessary all ! There's another sweet problem to take care of : the rarity of Tiles. It's a lot better to refer to my DT1 Format doc, the very last section "Rarity of Tiles". Read that doc carefully btw, many things are important.

Now, let's draw the Tiles. First problem, in what order ? Well, you'll have no choice but to draw all layers of 1 Tile, and only after go to another Tile. The reason is because Tiles can be walls of variable height (but also because later you'll see they can be draw in any order). Now, all the layers of 1 Tile themselves, in what order ? Say that we have this 4*3 'map' for a ds1 :

Code: Select all

   1234
   5678
   9ABC
We can choose to draw these tiles in several order :
* 123456789ABC
* 15926A37B48C
* 152963A74B8C (and also 12536947A8BC too of course)

My editor use the 1st solution, as it follow the common way of reading, and also the same order as the tiles datas that are in a DS1.

Now, let's draw all layers of 1 tile... Many problems in fact. We can't simple draw them in the order FLOOR1, FLOOR2, WALL 1, WALL 2, WALL 3, WALL 4, SHADOW, as it depends of their sub-type too. Extract from my DT1 doc :
  • Floors, either static or animated, have an orientation of 0
  • Special Tiles have 10 or 11
  • Shadows have 13
  • "Walls" (better say "Objects") that have the precedent Shadows have an Orientation of 14
  • Normal walls have all the other values which are < 15
  • Roofs have 15
  • Lower walls have > 15
So for each tile, we'll have to identify each layers, and draw them accordingly (1st order key) :
  • Lower walls
  • Floors
  • Shadows
  • Upper Walls
    • that's now that are draw sprites like monsters, player & objects
but NOT THE ROOFS YET ! The roofs Tiles are draw later, so skip them for now in that process. Now, there's another order key : the layers have a priority ! (easily test in the Pandemonium Fortress). So, for each kind of these 4 layer's type, we'll have to draw the Tiles of different layers but of the same type accordingly to their priority. This priority is the prop1. The prop1 is like a Height : the less the byte, the lower it is. So at a point if we have 4 walls layers to draw, maybe we won't draw them in the WALL 1 2 3 4 order, but instead in the WALL 2 1 4 3 order for a Tile, and the next tile will be in order Wall 1 4 3 2 ! The layers in a ds1 are the logic organization (more easy to select a whole layer I suppose), while the true order to draw them is coded into the prop1 of each tiles. And what if we have 2 walls with the same height ? Let's draw them in the natural order : wall 1 then 2.

Then, after all these layers, we draw the Roof Tiles, so we process again all the tiles. In the game, these Tiles are draw even after the special effects of the Player : take a Skill shrine, then go near a house : you won't see the icon over the head, as it'll be masked by the Roof tiles.

Since Tiles don't change during the game (no moving floors, no moving walls...), maybe a good thing to do will be to rearrange the tiles in a better order right after having loading the ds1. Except if it's an editor program. But in the case of just a viewer, it sounds better to not make order checks for each tiles for each type of layers each time we have to draw them.

Now, some 'funny' things about the Tiles :

* The Tiles of Orientation 3 are the upper corner of a wall Tile, but you must draw immediatly after a Tile which have the same Main-index & sub-index but with the Orientation 4 (left corner of the same wall) . You'll never found a tile with orientation 4 in the original ds1, at least I have never found one, and I have check dozens.

* Tiles of Orientation 18 and 19 must have their orientation exchange and their sub-index set to 0 (that's the lower cliffs in the Bloody hills of act 5).

* I didn't yet found why, but the Columns in the palace of Lut Gholen are buggy in my editor, they don't show up. Certainly another special case like the 2 others.

* don't forget to draw Roofs accordingly to their height that's in their DT1 header.

* and don't forget that walls are lower than floors (and than roofs) by 80 pixels (at zoom 1:1).

* in any prop4 of a WALL tile (maybe not just only Walls ?) , there's some bits that are flags :

Code: Select all

      if ( wall[x].prop4 & 0x80) &&  // binary : 1000-0000
           (o != 10) ) // my special tiles that I always want to see, despite this flag
         continue; // don't draw this tile
I think this is some way for Blizzard to have some Special tiles (river border, warps...) in a ds1 that DO means something for the game, but that tell the game to don't draw them. Warps MUST have this bit, or else they won't work).

There's another bit that have a meaning too, maybe the 0010-0000, but I don't remember exactly where, neither what it does.

check in my ds1misc.c the functions :
  • void wprop_2_block(int i, CELL_W_S * w_ptr) // wall layers
  • void fprop_2_block(int i, CELL_F_S * f_ptr) // floor layers
  • void sprop_2_block(int i, CELL_S_S * s_ptr) // shadow layer
and in wPreview.c the functions :
  • void wpreview_draw_s(int ds1_idx, int x, int y, int mx, int my, int z, int selected)
  • void wpreview_draw_f(int ds1_idx, int x, int y, int mx, int my, int z, int selected)
  • void wpreview_draw_w(int ds1_idx, int x, int y, int mx, int my, int z, int selected, int upper)
for the case I have forget anything.

Great format that map design in Diablo 2, you like it ? And I still don't understand all (Palace's columns problem) ;)

[edit] fixed a bad link reference ~ Myhr [/edit]
Last edited by Paul Siramy on Sat Sep 15, 2007 4:00 am, edited 2 times in total.

User avatar
Kieran
Senior Moderator
Angel
Posts: 617
Joined: Mon Oct 22, 2007 9:46 am
Location: England
Contact:
Great Britain

Hand-picked

Re: Ds1edit docs + usefull links

Post by Kieran » Mon Jan 07, 2008 12:47 am

Removed
Last edited by Kieran on Mon Apr 17, 2017 2:42 pm, edited 1 time in total.

User avatar
Necrolis
Senior Admin
Throne
Posts: 9125
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
Contact:
South Africa

Hand-picked

Post by Necrolis » Mon Jan 07, 2008 6:10 am

Actuatlly thats very bad, cause the map exit won't line up with the blood moor entry all the time(have a look at some of the recent topics). Secondly i hope that by server you mean tcp/ip games, and not realms, which are banned...
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death | D2GFEx
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

User avatar
MarcoNecroX
Junior Member
Paladin
Posts: 177
Joined: Sun Apr 22, 2012 10:55 pm

Re: Ds1edit docs + usefull links

Post by MarcoNecroX » Wed Sep 10, 2014 11:40 pm

Hey Paul, sorry for bothering you again.

I'm having a new problem with the map editor. The error is simply a crash (freeze).
The problem is after adding preset monsters via obj.txt, these are the lines:

Code: Select all

2	1	2178	void_amazon				Data\Global\Monsters	W%	NU	HTH		LIT																	0
2	1	2179	void_assassin				Data\Global\Monsters	W%	NU	HTH		HVY																	0
2	1	2180	void_barbarian				Data\Global\Monsters	W%	NU	HTH		MED																	0
2	1	2181	void_druid				Data\Global\Monsters	W%	NU	HTH		GHM																	0
2	1	2182	void_necromancer				Data\Global\Monsters	W%	NU	HTH		SKP																	0
2	1	2183	void_paladin				Data\Global\Monsters	W%	NU	HTH		MSK																	0
2	1	2184	void_sorceress				Data\Global\Monsters	W%	NU	HTH		CST																	0
What I did is create a monster token (W%). It contains a statue-version of each character (like ancients), so it consists of 7 .dcc files (each one 1 frame / 1 direction), 1 animdata line (NU), and 1 cof file. I'm using the torso layer & lit/hvy/med/ghm/skp/msk/cst classes. Needless to say, it works flawlessly ingame. And here's the .cof setup if it helps:

Code: Select all

dcc_file = W%XXYYYNUHTH.dcc
cof_token = W%
cof_mode  = NU
cof_class = HTH
nb_layers = 1
xmin = -60
xmax = 61
ymin = -100
ymax = 6
trigger_frame =0
trigger_value =0
layer_order = 01
layer_composit_01 = 01
transparency_01 = NO
layer_class_01 = hth
And here is the windows crash log:

Code: Select all

Problem signature:
  Problem Event Name:	APPCRASH
  Application Name:	win_ds1edit.exe
  Application Version:	0.0.0.0
  Application Timestamp:	4ead3c42
  Fault Module Name:	win_ds1edit.exe
  Fault Module Version:	0.0.0.0
  Fault Module Timestamp:	4ead3c42
  Exception Code:	c0000005
  Exception Offset:	00001141
  Locale ID:	11274
  Additional Information 1:	0a9e
  Additional Information 2:	0a9e372d3b4ad19135b953a78882e789
  Additional Information 3:	0a9e
  Additional Information 4:	0a9e372d3b4ad19135b953a78882e789
What called my attention is that if I use a component that is unused by this token (W%), for example LBW, MAU, etc. there is no crash (but it's obviously invisible).

Cheers :)

Post Reply

Return to “Map Editing”