#include "map.h" #include "game.h" #include "items.h" #include "things.h" #include "monster.h" #include "switch.h" #include "view.h" #include "music.h" #include "files.h" #include "render.h" #include #include #include "my.h" #include "error.h" enum { MB_COMMENT = -1, MB_END = 0, MB_WALLNAMES, MB_BACK, MB_WTYPE, MB_FRONT, MB_THING, MB_SWITCH, MB_MUSIC, MB_SKY, MB_SWITCH2, MB__UNKNOWN }; typedef struct map_header_t { char id[8]; short ver; } map_header_t; typedef struct map_block_t { short t; short st; int sz; } map_block_t; typedef struct old_thing_t { short x, y; short t; unsigned short f; } old_thing_t; static map_block_t blk; static int G_load (FILE *h) { switch (blk.t) { case MB_MUSIC: myfread(g_music, 8, 1, h); //if (music_random) { // F_randmus(g_music); //} MUS_load(g_music); return 1; } return 0; } static int IT_load (FILE *h) { int m, i, j; old_thing_t t; switch (blk.t) { case MB_THING: for (i = 0; blk.sz > 0; ++i, blk.sz -= 8) { t.x = myfread16(h); t.y = myfread16(h); t.t = myfread16(h); t.f = myfread16(h); it[i].o.x = t.x; it[i].o.y = t.y; it[i].t = t.t; it[i].s = t.f; if (it[i].t && (it[i].s & THF_DM) && !g_dm) { it[i].t=0; } } m = i; for (i = 0, j = -1; i < m; ++i) { if (it[i].t == TH_PLR1) { j = i; it[i].t = 0; } } if (!g_dm) { if (j == -1) { ERR_fatal("Предмет игрок_1 не найден"); } dm_pos[0].x = it[j].o.x; dm_pos[0].y = it[j].o.y; dm_pos[0].d = it[j].s & THF_DIR; } for (i = 0, j = -1; i < m; ++i) { if (it[i].t == TH_PLR2) { j = i; it[i].t = 0; } } if (!g_dm && _2pl) { if (j == -1) { ERR_fatal("Предмет игрок_2 не найден"); } dm_pos[1].x = it[j].o.x; dm_pos[1].y = it[j].o.y; dm_pos[1].d = it[j].s & THF_DIR; } for (i = 0, j = 0; i < m; ++i) { if (it[i].t == TH_DMSTART) { if (g_dm) { dm_pos[j].x = it[i].o.x; dm_pos[j].y = it[i].o.y; dm_pos[j].d = it[i].s & THF_DIR; } it[i].t = 0; ++j; } } if (g_dm && j < 2) { ERR_fatal("Меньше 2-ух точек DM"); } if (g_dm) { dm_pnum = j; dm_pl1p = myrand(dm_pnum); do { dm_pl2p = myrand(dm_pnum); } while (dm_pl2p == dm_pl1p); } else { dm_pl1p = 0; dm_pl2p = 1; dm_pnum = 2; } PL_spawn(&pl1, dm_pos[dm_pl1p].x, dm_pos[dm_pl1p].y, dm_pos[dm_pl1p].d); if (_2pl) { PL_spawn(&pl2, dm_pos[dm_pl2p].x, dm_pos[dm_pl2p].y, dm_pos[dm_pl2p].d); } for (i = 0; i < m; ++i) { if (it[i].t >= TH_CLIP && it[i].t < TH_DEMON) { it[i].s = 0; it[i].t = it[i].t - TH_CLIP + I_CLIP; if (it[i].t >= I_KEYR && it[i].t <= I_KEYB) { it[i].t |= 0x8000; } } else if (it[i].t >= TH_DEMON) { MN_spawn(it[i].o.x, it[i].o.y, it[i].s & THF_DIR, it[i].t - TH_DEMON + MN_DEMON); it[i].t = 0; } } return 1; } return 0; } static int SW_load (FILE *h) { int i; switch(blk.t) { case MB_SWITCH2: sw_secrets = 0; for (i = 0; i < MAXSW && blk.sz > 0; ++i, blk.sz -= 9) { sw[i].x = myfread8(h); sw[i].y = myfread8(h); sw[i].t = myfread8(h); sw[i].tm = myfread8(h); // unused sw[i].a = myfread8(h); sw[i].b = myfread8(h); sw[i].c = myfread8(h); sw[i].d = myfread8(h); // unused sw[i].f = myfread8(h); sw[i].tm = 0; sw[i].d = 0; sw[i].f |= 0x80; if (sw[i].t == SW_SECRET) { ++sw_secrets; } } return 1; } return 0; } static void unpack (void *buf, int len, void *obuf) { int i = 0; int j = 0; unsigned char *p = buf; unsigned char *q = obuf; while (i < len) { int id = p[i]; int step = 1; i += 1; if (id == 0xff) { step = p[i] | p[i + 1] << 8; id = p[i + 2]; i += 3; } memset(&q[j], id, step); j += step; } } static int read_array (void *p, FILE *h) { void *buf; switch (blk.st) { case 0: myfread(p, FLDW * FLDH, 1, h); break; case 1: buf = malloc(blk.sz); if (buf == NULL) { ERR_fatal("Не хватает памяти"); } myfread(buf, blk.sz, 1, h); unpack(buf, blk.sz, p); free(buf); break; default: return 0; } return 1; } static int W_load (FILE *h) { int i; char s[8]; switch (blk.t) { case MB_WALLNAMES: R_begin_load(); memset(walf, 0, sizeof(walf)); for (i = 1; i < 256 && blk.sz > 0; i++, blk.sz -= 9) { myfread(s, 8, 1, h); walf[i] = myfread8(h) ? 1 : 0; // ??? R_load(s); if (strncasecmp(s, "VTRAP01", 8) == 0) { walf[i] |= 2; } } R_end_load(); return 1; case MB_BACK: return read_array(fldb, h); case MB_WTYPE: return read_array(fld, h); case MB_FRONT: return read_array(fldf, h); case MB_SKY: sky_type = myfread16(h); R_loadsky(sky_type); return 1; } return 0; } void F_loadmap (char n[8]) { int r, o; FILE *h; map_header_t hdr; W_init(); r = F_getresid(n); h = wadh[wad[r].f]; fseek(h, wad[r].o, SEEK_SET); myfread(hdr.id, 8, 1, h); hdr.ver = myfread16(h); if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) { ERR_fatal("%.8s не является уровнем", n); } for (;;) { blk.t = myfread16(h); blk.st = myfread16(h); blk.sz = myfread32(h); if(blk.t == MB_END) { break; } if(blk.t == MB_COMMENT) { fseek(h, blk.sz, SEEK_CUR); continue; } o = ftell(h) + blk.sz; if(!G_load(h)) { if(!W_load(h)) { if(!IT_load(h)) { if(!SW_load(h)) { ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n); } } } } fseek(h, o, SEEK_SET); } }