1 module exmap
is aliced
;
14 // ////////////////////////////////////////////////////////////////////////// //
15 import std
.stdio
: File
;
17 void exportMapScript (string modname
, string mapname
, LevelMap map
, File fo
) {
19 void writeRects (const(ubyte)[] tilemap
, string layer
) {
20 auto tiles
= tilemap
.dup
;
22 ubyte getAt (int x
, int y
) {
24 return (x
>= 0 && y
>= 0 && x
< map
.width
&& y
< map
.height ? tiles
[y
*map
.width
+x
] : 0);
27 void setAt (int x
, int y
, ubyte v
) {
29 if (x
>= 0 && y
>= 0 && x
< map
.width
&& y
< map
.height
) tiles
[y
*map
.width
+x
] = v
;
32 bool isLineFilledWith(string mode
) (int x
, int y
, int len
, ubyte tnum
) {
33 static if (mode
== "horizontal") {
36 } else if (mode
== "vertical") {
40 static assert(0, "wtf?!");
44 if (getAt(x
, y
) != tnum
) return false;
51 bool isRectFilledWith (int x
, int y
, int w
, int h
, ubyte tnum
) {
55 if (!isLineFilledWith
!"horizontal"(x
, y
, w
, tnum
)) return false;
61 void fillRectWith (int x
, int y
, int w
, int h
, ubyte tnum
) {
65 foreach (int sx
; x
..x
+w
) setAt(sx
, y
, tnum
);
70 foreach (int y
; 0..map
.height
) {
71 foreach (int x
; 0..map
.width
) {
72 ubyte tnum
= getAt(x
, y
);
73 if (tnum
== 0) continue;
74 if (tnum
>= map
.wallnames
.length
) {
75 import std
.string
: format
;
76 throw new Exception("tile type %s exceeds max texture number (%s)".format(tnum
, map
.wallnames
.length
-1));
79 int bestw
= 1, besth
= 1;
80 foreach (int ey
; y
..map
.height
) {
81 foreach (int ex
; x
..map
.width
) {
84 if (isRectFilledWith(x
, y
, w
, h
, tnum
)) {
85 if (w
*h
> bestw
*besth
) { bestw
= w
; besth
= h
; }
89 fillRectWith(x
, y
, bestw
, besth
, 0);
90 if (bestw
== 1 && besth
== 1) {
91 fo
.writeln(" mapSetTile(", map
.wallnames
[tnum
].quote
, ", ", layer
, ", ", x
, ", ", y
, ");");
93 fo
.writeln(" mapSetRect(", map
.wallnames
[tnum
].quote
, ", ", layer
, ", ", x
, ", ", y
, ", ", bestw
, ", ", besth
, ");");
99 void writeTypeRects (const(ubyte)[] tilemap
) {
100 auto tiles
= tilemap
.dup
;
102 ubyte getAt (int x
, int y
) {
103 pragma(inline
, true);
104 return (x
>= 0 && y
>= 0 && x
< map
.width
&& y
< map
.height ? tiles
[y
*map
.width
+x
] : 0);
107 void setAt (int x
, int y
, ubyte v
) {
108 pragma(inline
, true);
109 if (x
>= 0 && y
>= 0 && x
< map
.width
&& y
< map
.height
) tiles
[y
*map
.width
+x
] = v
;
112 bool isLineFilledWith(string mode
) (int x
, int y
, int len
, ubyte tnum
) {
113 static if (mode
== "horizontal") {
116 } else if (mode
== "vertical") {
120 static assert(0, "wtf?!");
124 if (getAt(x
, y
) != tnum
) return false;
131 bool isRectFilledWith (int x
, int y
, int w
, int h
, ubyte tnum
) {
135 if (!isLineFilledWith
!"horizontal"(x
, y
, w
, tnum
)) return false;
141 void fillRectWith (int x
, int y
, int w
, int h
, ubyte tnum
) {
145 foreach (int sx
; x
..x
+w
) setAt(sx
, y
, tnum
);
150 foreach (int y
; 0..map
.height
) {
151 foreach (int x
; 0..map
.width
) {
152 ubyte tnum
= getAt(x
, y
);
153 if (tnum
== 0) continue;
156 case LevelMap
.TILE_WALL
: tname
= "TILE_WALL"; break;
157 case LevelMap
.TILE_DOORC
: tname
= "TILE_DOORC"; break;
158 case LevelMap
.TILE_DOORO
: tname
= "TILE_DOORO"; break;
159 case LevelMap
.TILE_STEP
: tname
= "TILE_STEP"; break;
160 case LevelMap
.TILE_WATER
: tname
= "TILE_WATER"; break;
161 case LevelMap
.TILE_ACID1
: tname
= "TILE_ACID1"; break;
162 case LevelMap
.TILE_ACID2
: tname
= "TILE_ACID2"; break;
163 case LevelMap
.TILE_MBLOCK
: tname
= "TILE_MBLOCK"; break;
164 case LevelMap
.TILE_LIFTU
: tname
= "TILE_LIFTU"; break;
165 case LevelMap
.TILE_LIFTD
: tname
= "TILE_LIFTD"; break;
166 case LevelMap
.TILE_ACTTRAP
: tname
= "TILE_ACTTRAP"; break;
168 import std
.string
: format
;
169 throw new Exception("unknown tile type: %s".format(tnum
));
171 // stupid brute force
172 int bestw
= 1, besth
= 1;
173 foreach (int ey
; y
..map
.height
) {
174 foreach (int ex
; x
..map
.width
) {
177 if (isRectFilledWith(x
, y
, w
, h
, tnum
)) {
178 if (w
*h
> bestw
*besth
) { bestw
= w
; besth
= h
; }
182 fillRectWith(x
, y
, bestw
, besth
, 0);
183 if (bestw
== 1 && besth
== 1) {
184 fo
.writeln(" mapSetTypeTile(", tname
, ", ", x
, ", ", y
, ");");
186 fo
.writeln(" mapSetTypeRect(", tname
, ", ", x
, ", ", y
, ", ", bestw
, ", ", besth
, ");");
192 void writeThings (string ctype
) {
193 foreach (ref thing
; map
.things
) {
194 //if (thing.dmonly) continue;
195 if (auto did
= thing
.type
in d2dactordefsById
) {
196 if (did
.classtype
!= ctype
) continue;
197 if (thing
.dmonly
) fo
.write(" if (gameMode == GM_DEATHMATCH) "); else fo
.write(" ");
198 fo
.writeln("actorSpawn(", did
.classtype
.quote
, ", ", did
.classname
.quote
, ", ", cast(int)thing
.x
, ", ", cast(int)thing
.y
, ", ACTOR_DIR_", (thing
.right ?
"RIGHT" : "LEFT"), ");");
200 conwriteln("ignoring unknown D2D thing with mapid ", thing
.type
);
206 void writeSwitches () {
207 foreach (ref sw
; map
.switches
) {
208 if (sw
.type
== 0) continue; // SW_NONE
211 fo
.write(" actorSpawnVanillaSwitch(");
213 case LevelMap
.SW_NONE
: assert(0);
214 case LevelMap
.SW_EXIT
: fo
.write("exit".quote
); break;
215 case LevelMap
.SW_EXITS
: fo
.write("exitSecret".quote
); break;
216 case LevelMap
.SW_OPENDOOR
: fo
.write("doorOpen".quote
); break;
217 case LevelMap
.SW_SHUTDOOR
: fo
.write("doorClose".quote
); break;
218 case LevelMap
.SW_SHUTTRAP
: fo
.write("trapClose".quote
); break;
219 case LevelMap
.SW_DOOR
: fo
.write("door".quote
); break;
220 case LevelMap
.SW_DOOR5
: fo
.write("doorTimed90".quote
); break;
221 case LevelMap
.SW_PRESS
: fo
.write("press".quote
); break;
222 case LevelMap
.SW_TELE
: fo
.write("teleport".quote
); break;
223 case LevelMap
.SW_SECRET
: fo
.write("secret".quote
); break;
224 case LevelMap
.SW_LIFTUP
: fo
.write("liftUp".quote
); break;
225 case LevelMap
.SW_LIFTDOWN
: fo
.write("liftDown".quote
); break;
226 case LevelMap
.SW_TRAP
: fo
.write("trapClose".quote
); break;
227 case LevelMap
.SW_LIFT
: fo
.write("liftToggle".quote
); break;
228 case LevelMap
.SW_WINGAME
: fo
.write("exitWin".quote
); break;
229 default: assert(0, "invalid switch type");
231 fo
.write(", ", sw
.x
*8, ", ", sw
.y
*8, ", ");
234 if (sw
.flags
&LevelMap
.SW_PL_PRESS
) fo
.write("|SWITCH_PLAYER_PRESS");
235 if (sw
.flags
&LevelMap
.SW_MN_PRESS
) fo
.write("|SWITCH_MONSTER_PRESS");
236 if (sw
.flags
&LevelMap
.SW_PL_NEAR
) fo
.write("|SWITCH_PLAYER_PROXIMITY");
237 if (sw
.flags
&LevelMap
.SW_MN_NEAR
) fo
.write("|SWITCH_MONSTER_PROXIMITY");
238 if (sw
.flags
&LevelMap
.SW_KEY_R
) fo
.write("|SWITCH_KEY_RED");
239 if (sw
.flags
&LevelMap
.SW_KEY_G
) fo
.write("|SWITCH_KEY_GREEN");
240 if (sw
.flags
&LevelMap
.SW_KEY_B
) fo
.write("|SWITCH_KEY_BLUE");
241 fo
.writeln(", ", sw
.a
, ", ", sw
.b
, ");");
245 fo
.writeln("module ", modname
, ";");
247 fo
.writeln("import actor, mapapi, stdlib;");
250 fo
.writeln("public void buildMap () {");
251 fo
.writeln(" mapSetSize(", map
.width
, ", ", map
.height
, ");");
252 fo
.writeln(" mapSetName(", mapname
.quote
, ");");
253 fo
.writeln(" putTiles();");
254 fo
.writeln(" putItems();");
255 fo
.writeln(" putMonsters();");
256 fo
.writeln(" putSwitches();");
261 fo
.writeln("void putItems () {");
267 fo
.writeln("void putMonsters () {");
268 writeThings("monster");
273 fo
.writeln("void putSwitches () {");
279 fo
.writeln("void putTiles () {");
280 fo
.writeln(" // back");
281 writeRects(map
.tiles
[LevelMap
.Back
], "LAYER_BACK");
282 fo
.writeln(" // front");
283 writeRects(map
.tiles
[LevelMap
.Front
], "LAYER_FRONT");
284 fo
.writeln(" // types");
285 writeTypeRects(map
.tiles
[LevelMap
.Type
]);
290 // ////////////////////////////////////////////////////////////////////////// //
291 void main (string
[] args
) {
293 string mapName
= null;
295 for (usize idx
= 1; idx
< args
.length
; ++idx
) {
296 if (args
[idx
] == "--map" || args
[idx
] == "-map") {
297 import std
.algorithm
: remove
;
298 if (mapName
!is null) assert(0, "duplicate '--map'");
299 mapName
= args
[idx
+1];
300 args
= args
.remove(idx
, 2);
303 wadList
~= args
[idx
];
311 import std
.file
: thisExePath
;
312 import std
.path
: dirName
;
313 setDataPath(thisExePath
.dirName
);
315 addWad("/home/ketmar/k8prj/doom2d-tl/data/doom2d.wad");
316 foreach (string s
; wadList
) addWad(s
);
321 if (mapName
is null) mapName
= "map01";
323 conwriteln("loading '", mapName
, "'...");
324 auto map
= new LevelMap("maps/"~mapName
~".d2m");
326 conwriteln("writing '", mapName
, ".dacs'...");
327 exportMapScript(mapName
, mapName
, map
, File(mapName
~".dacs", "w"));