DEADSOFTWARE

update copyrights
[flatwaifu.git] / src / map.c
1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
18 #include "map.h"
20 #include "game.h"
21 #include "items.h"
22 #include "things.h"
23 #include "monster.h"
24 #include "switch.h"
25 #include "view.h"
27 #include "music.h"
28 #include "files.h"
29 #include "render.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include "my.h"
34 #include "error.h"
36 enum {
37 MB_COMMENT = -1, MB_END = 0,
38 MB_WALLNAMES, MB_BACK, MB_WTYPE, MB_FRONT, MB_THING, MB_SWITCH,
39 MB_MUSIC, MB_SKY,
40 MB_SWITCH2,
41 MB__UNKNOWN
42 };
44 typedef struct map_header_t {
45 char id[8];
46 short ver;
47 } map_header_t;
49 typedef struct map_block_t {
50 short t;
51 short st;
52 int sz;
53 } map_block_t;
55 typedef struct old_thing_t {
56 short x, y;
57 short t;
58 unsigned short f;
59 } old_thing_t;
61 static map_block_t blk;
63 static int G_load (FILE *h) {
64 switch (blk.t) {
65 case MB_MUSIC:
66 myfread(g_music, 8, 1, h);
67 //if (music_random) {
68 // F_randmus(g_music);
69 //}
70 MUS_load(g_music);
71 return 1;
72 }
73 return 0;
74 }
76 static int IT_load (FILE *h) {
77 int m, i, j;
78 old_thing_t t;
79 switch (blk.t) {
80 case MB_THING:
81 for (i = 0; blk.sz > 0; ++i, blk.sz -= 8) {
82 t.x = myfread16(h);
83 t.y = myfread16(h);
84 t.t = myfread16(h);
85 t.f = myfread16(h);
86 it[i].o.x = t.x;
87 it[i].o.y = t.y;
88 it[i].t = t.t;
89 it[i].s = t.f;
90 if (it[i].t && (it[i].s & THF_DM) && !g_dm) {
91 it[i].t=0;
92 }
93 }
94 m = i;
95 for (i = 0, j = -1; i < m; ++i) {
96 if (it[i].t == TH_PLR1) {
97 j = i;
98 it[i].t = 0;
99 }
101 if (!g_dm) {
102 if (j == -1) {
103 ERR_fatal("Предмет игрок_1 не найден");
105 dm_pos[0].x = it[j].o.x;
106 dm_pos[0].y = it[j].o.y;
107 dm_pos[0].d = it[j].s & THF_DIR;
109 for (i = 0, j = -1; i < m; ++i) {
110 if (it[i].t == TH_PLR2) {
111 j = i;
112 it[i].t = 0;
115 if (!g_dm && _2pl) {
116 if (j == -1) {
117 ERR_fatal("Предмет игрок_2 не найден");
119 dm_pos[1].x = it[j].o.x;
120 dm_pos[1].y = it[j].o.y;
121 dm_pos[1].d = it[j].s & THF_DIR;
123 for (i = 0, j = 0; i < m; ++i) {
124 if (it[i].t == TH_DMSTART) {
125 if (g_dm) {
126 dm_pos[j].x = it[i].o.x;
127 dm_pos[j].y = it[i].o.y;
128 dm_pos[j].d = it[i].s & THF_DIR;
130 it[i].t = 0;
131 ++j;
134 if (g_dm && j < 2) {
135 ERR_fatal("Меньше 2-ух точек DM");
137 if (g_dm) {
138 dm_pnum = j;
139 dm_pl1p = myrand(dm_pnum);
140 do {
141 dm_pl2p = myrand(dm_pnum);
142 } while (dm_pl2p == dm_pl1p);
143 } else {
144 dm_pl1p = 0;
145 dm_pl2p = 1;
146 dm_pnum = 2;
148 PL_spawn(&pl1, dm_pos[dm_pl1p].x, dm_pos[dm_pl1p].y, dm_pos[dm_pl1p].d);
149 if (_2pl) {
150 PL_spawn(&pl2, dm_pos[dm_pl2p].x, dm_pos[dm_pl2p].y, dm_pos[dm_pl2p].d);
152 for (i = 0; i < m; ++i) {
153 if (it[i].t >= TH_CLIP && it[i].t < TH_DEMON) {
154 it[i].s = 0;
155 it[i].t = it[i].t - TH_CLIP + I_CLIP;
156 if (it[i].t >= I_KEYR && it[i].t <= I_KEYB) {
157 it[i].t |= 0x8000;
159 } else if (it[i].t >= TH_DEMON) {
160 MN_spawn(it[i].o.x, it[i].o.y, it[i].s & THF_DIR, it[i].t - TH_DEMON + MN_DEMON);
161 it[i].t = 0;
164 return 1;
166 return 0;
169 static int SW_load (FILE *h) {
170 int i;
171 switch(blk.t) {
172 case MB_SWITCH2:
173 sw_secrets = 0;
174 for (i = 0; i < MAXSW && blk.sz > 0; ++i, blk.sz -= 9) {
175 sw[i].x = myfread8(h);
176 sw[i].y = myfread8(h);
177 sw[i].t = myfread8(h);
178 sw[i].tm = myfread8(h); // unused
179 sw[i].a = myfread8(h);
180 sw[i].b = myfread8(h);
181 sw[i].c = myfread8(h);
182 sw[i].d = myfread8(h); // unused
183 sw[i].f = myfread8(h);
184 sw[i].tm = 0;
185 sw[i].d = 0;
186 sw[i].f |= 0x80;
187 if (sw[i].t == SW_SECRET) {
188 ++sw_secrets;
191 return 1;
193 return 0;
196 static void unpack (void *buf, int len, void *obuf) {
197 int i = 0;
198 int j = 0;
199 unsigned char *p = buf;
200 unsigned char *q = obuf;
201 while (i < len) {
202 int id = p[i];
203 int step = 1;
204 i += 1;
205 if (id == 0xff) {
206 step = p[i] | p[i + 1] << 8;
207 id = p[i + 2];
208 i += 3;
210 memset(&q[j], id, step);
211 j += step;
215 static int read_array (void *p, FILE *h) {
216 void *buf;
217 switch (blk.st) {
218 case 0:
219 myfread(p, FLDW * FLDH, 1, h);
220 break;
221 case 1:
222 buf = malloc(blk.sz);
223 if (buf == NULL) {
224 ERR_fatal("Не хватает памяти");
226 myfread(buf, blk.sz, 1, h);
227 unpack(buf, blk.sz, p);
228 free(buf);
229 break;
230 default:
231 return 0;
233 return 1;
236 static int W_load (FILE *h) {
237 int i;
238 char s[8];
239 switch (blk.t) {
240 case MB_WALLNAMES:
241 R_begin_load();
242 memset(walf, 0, sizeof(walf));
243 for (i = 1; i < 256 && blk.sz > 0; i++, blk.sz -= 9) {
244 myfread(s, 8, 1, h);
245 walf[i] = myfread8(h) ? 1 : 0; // ???
246 R_load(s);
247 if (strncasecmp(s, "VTRAP01", 8) == 0) {
248 walf[i] |= 2;
251 R_end_load();
252 return 1;
253 case MB_BACK:
254 return read_array(fldb, h);
255 case MB_WTYPE:
256 return read_array(fld, h);
257 case MB_FRONT:
258 return read_array(fldf, h);
259 case MB_SKY:
260 sky_type = myfread16(h);
261 R_loadsky(sky_type);
262 return 1;
264 return 0;
267 void F_loadmap (char n[8]) {
268 int r, o;
269 FILE *h;
270 map_header_t hdr;
271 W_init();
272 r = F_getresid(n);
273 h = wadh[wad[r].f];
274 fseek(h, wad[r].o, SEEK_SET);
275 myfread(hdr.id, 8, 1, h);
276 hdr.ver = myfread16(h);
277 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
278 ERR_fatal("%.8s не является уровнем", n);
280 for (;;) {
281 blk.t = myfread16(h);
282 blk.st = myfread16(h);
283 blk.sz = myfread32(h);
284 if(blk.t == MB_END) {
285 break;
287 if(blk.t == MB_COMMENT) {
288 fseek(h, blk.sz, SEEK_CUR);
289 continue;
291 o = ftell(h) + blk.sz;
292 if(!G_load(h)) {
293 if(!W_load(h)) {
294 if(!IT_load(h)) {
295 if(!SW_load(h)) {
296 ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n);
301 fseek(h, o, SEEK_SET);