doom

a minimalistic implementation of doom
git clone git://ssnf.xyz/doom
Log | Files | Refs

p_setup.c (10349B)


      1 #include <math.h>
      2 
      3 #include "m_swap.h"
      4 #include "z_zone.h"
      5 #include "m_bbox.h"
      6 #include "g_game.h"
      7 #include "i_system.h"
      8 #include "w_wad.h"
      9 #include "doomdef.h"
     10 #include "p_local.h"
     11 #include "s_sound.h"
     12 #include "doomstat.h"
     13 
     14 #define MAX_DEATHMATCH_STARTS	10
     15 
     16 vertex_t* vertexes;
     17 int       numvertexes;
     18 int		numsegs;
     19 seg_t*		segs;
     20 int		numsectors;
     21 sector_t*	sectors;
     22 int		numsubsectors;
     23 subsector_t*	subsectors;
     24 int		numnodes;
     25 node_t*		nodes;
     26 int		numlines;
     27 line_t*		lines;
     28 int		numsides;
     29 side_t*		sides;
     30 int		bmapwidth;
     31 int		bmapheight;
     32 short*		blockmap;
     33 short*		blockmaplump;
     34 fixed_t		bmaporgx;
     35 fixed_t		bmaporgy;
     36 mobj_t**	blocklinks;
     37 byte*		rejectmatrix;
     38 mapthing_t	deathmatchstarts[MAX_DEATHMATCH_STARTS];
     39 mapthing_t*	deathmatch_p;
     40 mapthing_t	playerstarts[MAXPLAYERS];
     41 
     42 void P_SpawnMapThing(mapthing_t* mthing);
     43 
     44 void
     45 P_LoadVertexes(int lump)
     46 {
     47 	mapvertex_t*	ml;
     48 	vertex_t*		li;
     49 	byte*		data;
     50 	int			i;
     51 
     52 	numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t);
     53 	vertexes = Z_Malloc(numvertexes*sizeof(vertex_t),PU_LEVEL,0);
     54 	data = W_CacheLumpNum(lump,PU_STATIC);
     55 	ml = (mapvertex_t *)data;
     56 	li = vertexes;
     57 	for (i = 0; i < numvertexes; ++i, ++li, ++ml) {
     58 		li->x = SHORT(ml->x)<<FRACBITS;
     59 		li->y = SHORT(ml->y)<<FRACBITS;
     60 	}
     61 	Z_Free(data);
     62 }
     63 
     64 void
     65 P_LoadSegs(int lump)
     66 {
     67 	byte*		data;
     68 	mapseg_t*		ml;
     69 	seg_t*		li;
     70 	line_t*		ldef;
     71 	int			i, linedef, side;
     72 
     73 	numsegs = W_LumpLength(lump) / sizeof(mapseg_t);
     74 	segs = Z_Malloc(numsegs*sizeof(seg_t),PU_LEVEL,0);
     75 	memset(segs, 0, numsegs*sizeof(seg_t));
     76 	data = W_CacheLumpNum(lump,PU_STATIC);
     77 	ml = (mapseg_t*)data;
     78 	li = segs;
     79 	for (i = 0; i < numsegs; ++i, ++li, ++ml) {
     80 		li->v1 = &vertexes[SHORT(ml->v1)];
     81 		li->v2 = &vertexes[SHORT(ml->v2)];
     82 		li->angle = (SHORT(ml->angle))<<16;
     83 		li->offset = (SHORT(ml->offset))<<16;
     84 		linedef = SHORT(ml->linedef);
     85 		ldef = &lines[linedef];
     86 		li->linedef = ldef;
     87 		side = SHORT(ml->side);
     88 		li->sidedef = &sides[ldef->sidenum[side]];
     89 		li->frontsector = sides[ldef->sidenum[side]].sector;
     90 		if(ldef-> flags & ML_TWOSIDED) li->backsector = sides[ldef->sidenum[side^1]].sector;
     91 		else li->backsector = 0;
     92 	}
     93 	Z_Free(data);
     94 }
     95 
     96 void
     97 P_LoadSubsectors(int lump)
     98 {
     99 	mapsubsector_t*	ms;
    100 	subsector_t*	ss;
    101 	byte*		data;
    102 	int			i;
    103 
    104 	numsubsectors = W_LumpLength(lump) / sizeof(mapsubsector_t);
    105 	subsectors = Z_Malloc(numsubsectors * sizeof(subsector_t), PU_LEVEL, 0);
    106 	data = W_CacheLumpNum(lump, PU_STATIC);
    107 	ms = (mapsubsector_t*)data;
    108 	memset(subsectors, 0, numsubsectors*sizeof(subsector_t));
    109 	ss = subsectors;
    110 	for (i = 0; i < numsubsectors; ++i, ++ss, ++ms) {
    111 		ss->numlines = SHORT(ms->numsegs);
    112 		ss->firstline = SHORT(ms->firstseg);
    113 	}
    114 	Z_Free(data);
    115 }
    116 
    117 void
    118 P_LoadSectors(int lump)
    119 {
    120 	mapsector_t*	ms;
    121 	sector_t*		ss;
    122 	byte*		data;
    123 	int			i;
    124 
    125 	numsectors = W_LumpLength(lump) / sizeof(mapsector_t);
    126 	sectors = Z_Malloc(numsectors * sizeof(sector_t), PU_LEVEL, 0);
    127 	memset(sectors, 0, numsectors * sizeof(sector_t));
    128 	data = W_CacheLumpNum(lump,PU_STATIC);
    129 	ms = (mapsector_t*)data;
    130 	ss = sectors;
    131 	for (i = 0; i < numsectors; ++i, ++ss, ++ms) {
    132 		ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
    133 		ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
    134 		ss->floorpic = R_FlatNumForName(ms->floorpic);
    135 		ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
    136 		ss->lightlevel = SHORT(ms->lightlevel);
    137 		ss->special = SHORT(ms->special);
    138 		ss->tag = SHORT(ms->tag);
    139 		ss->thinglist = NULL;
    140 	}
    141 	Z_Free(data);
    142 }
    143 
    144 void
    145 P_LoadNodes(int lump)
    146 {
    147 	byte*	data;
    148 	mapnode_t*	mn;
    149 	node_t*	no;
    150 	int		i, j, k;
    151 
    152 	numnodes = W_LumpLength(lump) / sizeof(mapnode_t);
    153 	nodes = Z_Malloc(numnodes*sizeof(node_t),PU_LEVEL,0);
    154 	data = W_CacheLumpNum(lump,PU_STATIC);
    155 	mn = (mapnode_t*)data;
    156 	no = nodes;
    157 	for (i = 0; i < numnodes; ++i, ++no, ++mn) {
    158 		no->x = SHORT(mn->x)<<FRACBITS;
    159 		no->y = SHORT(mn->y)<<FRACBITS;
    160 		no->dx = SHORT(mn->dx)<<FRACBITS;
    161 		no->dy = SHORT(mn->dy)<<FRACBITS;
    162 		for (j = 0; j < 2; ++j) {
    163 			no->children[j] = SHORT(mn->children[j]);
    164 			for (k = 0; k < 4; ++k) no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
    165 		}
    166 	}
    167 	Z_Free(data);
    168 }
    169 
    170 void
    171 P_LoadThings(int lump)
    172 {
    173 	mapthing_t* mt;
    174 	byte*       data;
    175 	int         i, numthings;
    176 	boolean     spawn;
    177 	data = W_CacheLumpNum(lump, PU_STATIC);
    178 
    179 	numthings = W_LumpLength(lump) / sizeof(mapthing_t);
    180 	mt = (mapthing_t *)data;
    181 	for (i = 0; i < numthings; ++i, ++mt) {
    182 		spawn = true;
    183 		if(spawn == false) break;
    184 		mt->x = SHORT(mt->x);
    185 		mt->y = SHORT(mt->y);
    186 		mt->angle = SHORT(mt->angle);
    187 		mt->type = SHORT(mt->type);
    188 		mt->options = SHORT(mt->options);
    189 		P_SpawnMapThing(mt);
    190 	}
    191 	Z_Free(data);
    192 }
    193 
    194 void
    195 P_LoadLineDefs(int lump)
    196 {
    197 	line_t*		ld;
    198 	vertex_t*		v1;
    199 	vertex_t*		v2;
    200 	byte*		data;
    201 	int			i;
    202 	maplinedef_t*	mld;
    203 
    204 	numlines = W_LumpLength(lump) / sizeof(maplinedef_t);
    205 	lines = Z_Malloc(numlines*sizeof(line_t),PU_LEVEL,0);
    206 	memset(lines, 0, numlines*sizeof(line_t));
    207 	data = W_CacheLumpNum(lump,PU_STATIC);
    208 	mld = (maplinedef_t*)data;
    209 	ld = lines;
    210 	for (i = 0; i < numlines; ++i, ++mld, ++ld) {
    211 		ld->flags = SHORT(mld->flags);
    212 		ld->special = SHORT(mld->special);
    213 		ld->tag = SHORT(mld->tag);
    214 		v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
    215 		v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
    216 		ld->dx = v2->x - v1->x;
    217 		ld->dy = v2->y - v1->y;
    218 		if(!ld->dx) ld->slopetype = ST_VERTICAL;
    219 		else if (!ld->dy) ld->slopetype = ST_HORIZONTAL;
    220 		else {
    221 			if(FixedDiv(ld->dy , ld->dx) > 0) ld->slopetype = ST_POSITIVE;
    222 			else ld->slopetype = ST_NEGATIVE;
    223 		}
    224 		if(v1->x < v2->x) {
    225 			ld->bbox[BOXLEFT] = v1->x;
    226 			ld->bbox[BOXRIGHT] = v2->x;
    227 		} else {
    228 			ld->bbox[BOXLEFT] = v2->x;
    229 			ld->bbox[BOXRIGHT] = v1->x;
    230 		}
    231 		if (v1->y < v2->y) {
    232 			ld->bbox[BOXBOTTOM] = v1->y;
    233 			ld->bbox[BOXTOP] = v2->y;
    234 		} else {
    235 			ld->bbox[BOXBOTTOM] = v2->y;
    236 			ld->bbox[BOXTOP] = v1->y;
    237 		}
    238 		ld->sidenum[0] = SHORT(mld->sidenum[0]);
    239 		ld->sidenum[1] = SHORT(mld->sidenum[1]);
    240 		if(ld->sidenum[0] != -1) ld->frontsector = sides[ld->sidenum[0]].sector;
    241 		else ld->frontsector = 0;
    242 		if(ld->sidenum[1] != -1) ld->backsector = sides[ld->sidenum[1]].sector;
    243 		else ld->backsector = 0;
    244 	}
    245 	Z_Free(data);
    246 }
    247 
    248 void
    249 P_LoadSideDefs(int lump)
    250 {
    251 	mapsidedef_t*	msd;
    252 	side_t*		sd;
    253 	byte*		data;
    254 	int			i;
    255 
    256 	numsides = W_LumpLength(lump) / sizeof(mapsidedef_t);
    257 	sides = Z_Malloc(numsides*sizeof(side_t),PU_LEVEL,0);
    258 	memset(sides, 0, numsides*sizeof(side_t));
    259 	data = W_CacheLumpNum(lump,PU_STATIC);
    260 	msd = (mapsidedef_t*)data;
    261 	sd = sides;
    262 	for (i = 0; i < numsides; ++i, ++msd, ++sd) {
    263 		sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
    264 		sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
    265 		sd->toptexture = R_TextureNumForName(msd->toptexture);
    266 		sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
    267 		sd->midtexture = R_TextureNumForName(msd->midtexture);
    268 		sd->sector = &sectors[SHORT(msd->sector)];
    269 	}
    270 	Z_Free(data);
    271 }
    272 
    273 void
    274 P_LoadBlockMap(int lump)
    275 {
    276 	int i, count;
    277 
    278 	blockmaplump = W_CacheLumpNum(lump,PU_LEVEL);
    279 	blockmap = blockmaplump+4;
    280 	count = W_LumpLength(lump)/2;
    281 	for (i = 0 ;  i < count ;  ++i) blockmaplump[i] = SHORT(blockmaplump[i]);
    282 	bmaporgx = blockmaplump[0]<<FRACBITS;
    283 	bmaporgy = blockmaplump[1]<<FRACBITS;
    284 	bmapwidth = blockmaplump[2];
    285 	bmapheight = blockmaplump[3];
    286 	count = sizeof(*blocklinks) * bmapwidth*bmapheight;
    287 	blocklinks = Z_Malloc(count,PU_LEVEL, 0);
    288 	memset(blocklinks, 0, count);
    289 }
    290 
    291 void
    292 P_GroupLines()
    293 {
    294 	line_t**     linebuffer;
    295 	line_t*      li;
    296 	sector_t*    sector;
    297 	subsector_t* ss;
    298 	seg_t*       seg;
    299 	fixed_t      bbox[4];
    300 	int          i, j , total, block;
    301 
    302 	ss = subsectors;
    303 	for (i = 0; i < numsubsectors; ++i, ++ss) {
    304 		seg = &segs[ss->firstline];
    305 		ss->sector = seg->sidedef->sector;
    306 	}
    307 	li = lines;
    308 	total = 0;
    309 	for (i = 0; i < numlines; ++i, ++li) {
    310 		++total;
    311 		++li->frontsector->linecount;
    312 		if (li->backsector && li->backsector != li->frontsector) {
    313 			++total;
    314 			++li->backsector->linecount;
    315 		}
    316 	}
    317 	linebuffer = Z_Malloc(total * 4 * 4, PU_LEVEL, 0); /* todo: figure out proper size */
    318 	sector = sectors;
    319 	for (i = 0; i < numsectors; ++i, ++sector) {
    320 		M_ClearBox(bbox);
    321 		sector->lines = linebuffer;
    322 		li = lines;
    323 		for (j = 0; j < numlines; ++j, ++li) {
    324 			if(li->frontsector == sector || li->backsector == sector) {
    325 				*linebuffer++ = li;
    326 				M_AddToBox(bbox, li->v1->x, li->v1->y);
    327 				M_AddToBox(bbox, li->v2->x, li->v2->y);
    328 			}
    329 		}
    330 		if (linebuffer - sector->lines != sector->linecount) I_Error("P_GroupLines: miscounted");
    331 		sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
    332 		sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
    333 		block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
    334 		block = block >= bmapheight ? bmapheight-1 : block;
    335 		sector->blockbox[BOXTOP]=block;
    336 		block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
    337 		block = block < 0 ? 0 : block;
    338 		sector->blockbox[BOXBOTTOM]=block;
    339 		block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
    340 		block = block >= bmapwidth ? bmapwidth-1 : block;
    341 		sector->blockbox[BOXRIGHT]=block;
    342 		block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
    343 		block = block < 0 ? 0 : block;
    344 		sector->blockbox[BOXLEFT]=block;
    345 	}
    346 }
    347 
    348 void
    349 P_SetupLevel(int episode, int map, int playermask, skill_t skill)
    350 {
    351 	char	lumpname[9];
    352 	int		i, lumpnum;
    353 
    354 	totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
    355 	wminfo.partime = 180;
    356 	for (i = 0 ; i < MAXPLAYERS ; ++i)
    357 		players[i].killcount = players[i].secretcount = players[i].itemcount = 0;
    358 	players[consoleplayer].viewz = 1;
    359 	S_Start();
    360 	Z_FreeTags(PU_LEVEL, PU_PURGELEVEL - 1);
    361 	P_InitThinkers();
    362 	lumpname[0] = 'E';
    363 	lumpname[1] = '0' + episode;
    364 	lumpname[2] = 'M';
    365 	lumpname[3] = '0' + map;
    366 	lumpname[4] = '\0';
    367 	lumpnum = W_GetNumForName(lumpname);
    368 	leveltime = 0;
    369 	P_LoadBlockMap(lumpnum+ML_BLOCKMAP);
    370 	P_LoadVertexes(lumpnum+ML_VERTEXES);
    371 	P_LoadSectors(lumpnum+ML_SECTORS);
    372 	P_LoadSideDefs(lumpnum+ML_SIDEDEFS);
    373 	P_LoadLineDefs(lumpnum+ML_LINEDEFS);
    374 	P_LoadSubsectors(lumpnum+ML_SSECTORS);
    375 	P_LoadNodes(lumpnum+ML_NODES);
    376 	P_LoadSegs(lumpnum+ML_SEGS);
    377 	rejectmatrix = W_CacheLumpNum(lumpnum+ML_REJECT,PU_LEVEL);
    378 	P_GroupLines();
    379 	bodyqueslot = 0;
    380 	deathmatch_p = deathmatchstarts;
    381 	P_LoadThings(lumpnum+ML_THINGS);
    382 	if(deathmatch) {
    383 	for (i = 0 ; i < MAXPLAYERS; ++i)
    384 		if (playeringame[i]) {
    385 			players[i].mo = NULL;
    386 			G_DeathMatchSpawnPlayer(i);
    387 		}
    388 	}
    389 	iquehead = iquetail = 0;
    390 	P_SpawnSpecials();
    391 	if(precache) R_PrecacheLevel();
    392 }
    393 
    394 void
    395 P_Init()
    396 {
    397 	P_InitSwitchList();
    398 	P_InitPicAnims();
    399 	R_InitSprites(sprnames);
    400 }