DEADSOFTWARE

dfc7b7071c0a9744264c2fef70438415ae74bcf9
[flatwaifu.git] / src / map.c
1 #include "map.h"
3 #include "game.h"
4 #include "items.h"
5 #include "things.h"
6 #include "monster.h"
7 #include "switch.h"
8 #include "view.h"
10 #include "music.h"
11 #include "files.h"
12 #include "render.h"
14 #include <stdio.h>
15 #include <string.h>
16 #include "my.h"
17 #include "error.h"
19 enum {
20 MB_COMMENT = -1, MB_END = 0,
21 MB_WALLNAMES, MB_BACK, MB_WTYPE, MB_FRONT, MB_THING, MB_SWITCH,
22 MB_MUSIC, MB_SKY,
23 MB_SWITCH2,
24 MB__UNKNOWN
25 };
27 typedef struct map_header_t {
28 char id[8];
29 short ver;
30 } map_header_t;
32 typedef struct map_block_t {
33 short t;
34 short st;
35 int sz;
36 } map_block_t;
38 typedef struct old_thing_t {
39 short x, y;
40 short t;
41 unsigned short f;
42 } old_thing_t;
44 static map_block_t blk;
46 static int G_load (FILE *h) {
47 switch (blk.t) {
48 case MB_MUSIC:
49 myfread(g_music, 8, 1, h);
50 if (music_random) {
51 F_randmus(g_music);
52 }
53 F_loadmus(g_music);
54 return 1;
55 }
56 return 0;
57 }
59 static int IT_load (FILE *h) {
60 int m, i, j;
61 old_thing_t t;
62 switch (blk.t) {
63 case MB_THING:
64 for (i = 0; blk.sz > 0; ++i, blk.sz -= 8) {
65 t.x = myfread16(h);
66 t.y = myfread16(h);
67 t.t = myfread16(h);
68 t.f = myfread16(h);
69 it[i].o.x = t.x;
70 it[i].o.y = t.y;
71 it[i].t = t.t;
72 it[i].s = t.f;
73 if (it[i].t && (it[i].s & THF_DM) && !g_dm) {
74 it[i].t=0;
75 }
76 }
77 m = i;
78 for (i = 0, j = -1; i < m; ++i) {
79 if (it[i].t == TH_PLR1) {
80 j = i;
81 it[i].t = 0;
82 }
83 }
84 if (!g_dm) {
85 if (j == -1) {
86 ERR_fatal("Предмет игрок_1 не найден");
87 }
88 dm_pos[0].x = it[j].o.x;
89 dm_pos[0].y = it[j].o.y;
90 dm_pos[0].d = it[j].s & THF_DIR;
91 }
92 for (i = 0, j = -1; i < m; ++i) {
93 if (it[i].t == TH_PLR2) {
94 j = i;
95 it[i].t = 0;
96 }
97 }
98 if (!g_dm && _2pl) {
99 if (j == -1) {
100 ERR_fatal("Предмет игрок_2 не найден");
102 dm_pos[1].x = it[j].o.x;
103 dm_pos[1].y = it[j].o.y;
104 dm_pos[1].d = it[j].s & THF_DIR;
106 for (i = 0, j = 0; i < m; ++i) {
107 if (it[i].t == TH_DMSTART) {
108 if (g_dm) {
109 dm_pos[j].x = it[i].o.x;
110 dm_pos[j].y = it[i].o.y;
111 dm_pos[j].d = it[i].s & THF_DIR;
113 it[i].t = 0;
114 ++j;
117 if (g_dm && j < 2) {
118 ERR_fatal("Меньше 2-ух точек DM");
120 if (g_dm) {
121 dm_pnum = j;
122 dm_pl1p = myrand(dm_pnum);
123 do {
124 dm_pl2p = myrand(dm_pnum);
125 } while (dm_pl2p == dm_pl1p);
126 } else {
127 dm_pl1p = 0;
128 dm_pl2p = 1;
129 dm_pnum = 2;
131 PL_spawn(&pl1, dm_pos[dm_pl1p].x, dm_pos[dm_pl1p].y, dm_pos[dm_pl1p].d);
132 if (_2pl) {
133 PL_spawn(&pl2, dm_pos[dm_pl2p].x, dm_pos[dm_pl2p].y, dm_pos[dm_pl2p].d);
135 for (i = 0; i < m; ++i) {
136 if (it[i].t >= TH_CLIP && it[i].t < TH_DEMON) {
137 it[i].s = 0;
138 it[i].t = it[i].t - TH_CLIP + I_CLIP;
139 if (it[i].t >= I_KEYR && it[i].t <= I_KEYB) {
140 it[i].t |= 0x8000;
142 } else if (it[i].t >= TH_DEMON) {
143 MN_spawn(it[i].o.x, it[i].o.y, it[i].s & THF_DIR, it[i].t - TH_DEMON + MN_DEMON);
144 it[i].t = 0;
147 return 1;
149 return 0;
152 static int SW_load (FILE *h) {
153 int i;
154 switch(blk.t) {
155 case MB_SWITCH2:
156 sw_secrets = 0;
157 for (i = 0; i < MAXSW && blk.sz > 0; ++i, blk.sz -= 9) {
158 sw[i].x = myfread8(h);
159 sw[i].y = myfread8(h);
160 sw[i].t = myfread8(h);
161 sw[i].tm = myfread8(h); // unused
162 sw[i].a = myfread8(h);
163 sw[i].b = myfread8(h);
164 sw[i].c = myfread8(h);
165 sw[i].d = myfread8(h); // unused
166 sw[i].f = myfread8(h);
167 sw[i].tm = 0;
168 sw[i].d = 0;
169 sw[i].f |= 0x80;
170 if (sw[i].t == SW_SECRET) {
171 ++sw_secrets;
174 return 1;
176 return 0;
179 static void unpack (void *buf, int len, void *obuf) {
180 int i = 0;
181 int j = 0;
182 unsigned char *p = buf;
183 unsigned char *q = obuf;
184 while (i < len) {
185 int id = p[i];
186 int step = 1;
187 i += 1;
188 if (id == 0xff) {
189 step = p[i] | p[i + 1] << 8;
190 id = p[i + 2];
191 i += 3;
193 memset(&q[j], id, step);
194 j += step;
198 static int read_array (void *p, FILE *h) {
199 void *buf;
200 switch (blk.st) {
201 case 0:
202 myfread(p, FLDW * FLDH, 1, h);
203 break;
204 case 1:
205 buf = malloc(blk.sz);
206 if (buf == NULL) {
207 ERR_fatal("Не хватает памяти");
209 myfread(buf, blk.sz, 1, h);
210 unpack(buf, blk.sz, p);
211 free(buf);
212 break;
213 default:
214 return 0;
216 return 1;
219 static int W_load (FILE *h) {
220 int i;
221 char s[8];
222 switch (blk.t) {
223 case MB_WALLNAMES:
224 R_begin_load();
225 memset(walf, 0, sizeof(walf));
226 for (i = 1; i < 256 && blk.sz > 0; i++, blk.sz -= 9) {
227 myfread(s, 8, 1, h);
228 walf[i] = myfread8(h) ? 1 : 0; // ???
229 R_load(s);
230 if (strncasecmp(s, "VTRAP01", 8) == 0) {
231 walf[i] |= 2;
234 R_end_load();
235 return 1;
236 case MB_BACK:
237 return read_array(fldb, h);
238 case MB_WTYPE:
239 return read_array(fld, h);
240 case MB_FRONT:
241 return read_array(fldf, h);
242 case MB_SKY:
243 sky_type = myfread16(h);
244 R_loadsky(sky_type);
245 return 1;
247 return 0;
250 void F_loadmap (char n[8]) {
251 int r, o;
252 FILE *h;
253 map_header_t hdr;
254 W_init();
255 r = F_getresid(n);
256 h = wadh[wad[r].f];
257 fseek(h, wad[r].o, SEEK_SET);
258 myfread(hdr.id, 8, 1, h);
259 hdr.ver = myfread16(h);
260 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
261 ERR_fatal("%.8s не является уровнем", n);
263 for (;;) {
264 blk.t = myfread16(h);
265 blk.st = myfread16(h);
266 blk.sz = myfread32(h);
267 if(blk.t == MB_END) {
268 break;
270 if(blk.t == MB_COMMENT) {
271 fseek(h, blk.sz, SEEK_CUR);
272 continue;
274 o = ftell(h) + blk.sz;
275 if(!G_load(h)) {
276 if(!W_load(h)) {
277 if(!IT_load(h)) {
278 if(!SW_load(h)) {
279 ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n);
284 fseek(h, o, SEEK_SET);