summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/p_setup.c')
-rw-r--r--apps/plugins/doom/p_setup.c1255
1 files changed, 1255 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_setup.c b/apps/plugins/doom/p_setup.c
new file mode 100644
index 0000000000..d40372d6da
--- /dev/null
+++ b/apps/plugins/doom/p_setup.c
@@ -0,0 +1,1255 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Do all the WAD I/O, get map description,
29 * set up initial state and misc. LUTs.
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include <math.h>
34
35#include "doomstat.h"
36#include "m_bbox.h"
37#include "m_argv.h"
38#include "g_game.h"
39#include "w_wad.h"
40#include "r_main.h"
41#include "r_things.h"
42#include "p_maputl.h"
43#include "p_map.h"
44#include "p_setup.h"
45#include "p_spec.h"
46#include "p_tick.h"
47#include "p_enemy.h"
48#include "s_sound.h"
49#include "i_system.h"
50#include "m_swap.h"
51
52#include "rockmacros.h"
53//
54// MAP related Lookup tables.
55// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
56//
57
58int numvertexes;
59vertex_t *vertexes;
60
61int numsegs;
62seg_t *segs;
63
64int numsectors;
65sector_t *sectors;
66
67int numsubsectors;
68subsector_t *subsectors;
69
70int numnodes;
71node_t *nodes;
72
73int numlines;
74line_t *lines;
75
76int numsides;
77side_t *sides;
78
79
80////////////////////////////////////////////////////////////////////////////////////////////
81// figgi 08/21/00 -- constants and globals for glBsp support
82#define gNd2 0x32644E67 // figgi -- suppport for new GL_VERT format v2.0
83#define GL_VERT_OFFSET 4
84
85int firstglvertex = 0;
86boolean usingGLNodes = false;
87boolean forceOldBsp = false;
88
89enum
90{
91 ML_GL_LABEL=0, // A separator name, GL_ExMx or GL_MAPxx
92 ML_GL_VERTS, // Extra Vertices
93 ML_GL_SEGS, // Segs, from linedefs & minisegs
94 ML_GL_SSECT, // SubSectors, list of segs
95 ML_GL_NODES // GL BSP nodes
96};
97////////////////////////////////////////////////////////////////////////////////////////////
98
99
100// BLOCKMAP
101// Created from axis aligned bounding box
102// of the map, a rectangular array of
103// blocks of size ...
104// Used to speed up collision detection
105// by spatial subdivision in 2D.
106//
107// Blockmap size.
108
109int bmapwidth, bmapheight; // size in mapblocks
110
111// killough 3/1/98: remove blockmap limit internally:
112long *blockmap; // was short -- killough
113
114// offsets in blockmap are from here
115long *blockmaplump; // was short -- killough
116
117fixed_t bmaporgx, bmaporgy; // origin of block map
118
119mobj_t **blocklinks; // for thing chains
120
121//
122// REJECT
123// For fast sight rejection.
124// Speeds up enemy AI by skipping detailed
125// LineOf Sight calculation.
126// Without the special effect, this could
127// be used as a PVS lookup as well.
128//
129
130static int rejectlump = -1;// cph - store reject lump num if cached
131const byte *rejectmatrix; // cph - const*
132
133// Maintain single and multi player starting spots.
134
135// 1/11/98 killough: Remove limit on deathmatch starts
136mapthing_t *deathmatchstarts; // killough
137size_t num_deathmatchstarts; // killough
138
139mapthing_t *deathmatch_p;
140mapthing_t playerstarts[MAXPLAYERS];
141
142//
143// P_LoadVertexes
144//
145// killough 5/3/98: reformatted, cleaned up
146//
147static void P_LoadVertexes (int lump)
148{
149 const byte *data; // cph - const
150 int i;
151
152 // Determine number of lumps:
153 // total lump length / vertex record length.
154 numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t);
155
156 // Allocate zone memory for buffer.
157 vertexes = Z_Malloc(numvertexes*sizeof(vertex_t),PU_LEVEL,0);
158
159 // Load data into cache.
160 data = W_CacheLumpNum(lump); // cph - wad handling updated
161
162 // Copy and convert vertex coordinates,
163 // internal representation as fixed.
164 for (i=0; i<numvertexes; i++)
165 {
166 vertexes[i].x = SHORT(((mapvertex_t *) data)[i].x)<<FRACBITS;
167 vertexes[i].y = SHORT(((mapvertex_t *) data)[i].y)<<FRACBITS;
168 }
169
170 // Free buffer memory.
171 W_UnlockLumpNum(lump);
172}
173
174//
175// P_LoadSegs
176//
177// killough 5/3/98: reformatted, cleaned up
178
179static void P_LoadSegs (int lump)
180{
181 int i;
182 const byte *data; // cph - const
183
184 numsegs = W_LumpLength(lump) / sizeof(mapseg_t);
185 segs = Z_Calloc(numsegs,sizeof(seg_t),PU_LEVEL,0);
186 data = W_CacheLumpNum(lump); // cph - wad lump handling updated
187
188 for (i=0; i<numsegs; i++)
189 {
190 seg_t *li = segs+i;
191 mapseg_t *ml = (mapseg_t *) data + i;
192
193 int side, linedef;
194 line_t *ldef;
195
196 li->v1 = &vertexes[SHORT(ml->v1)];
197 li->v2 = &vertexes[SHORT(ml->v2)];
198
199 li->miniseg = false; // figgi -- there are no minisegs in classic BSP nodes
200
201 li->angle = (SHORT(ml->angle))<<16;
202 li->offset =(SHORT(ml->offset))<<16;
203 linedef = SHORT(ml->linedef);
204 ldef = &lines[linedef];
205 li->linedef = ldef;
206 side = SHORT(ml->side);
207 li->sidedef = &sides[ldef->sidenum[side]];
208 li->frontsector = sides[ldef->sidenum[side]].sector;
209
210 // killough 5/3/98: ignore 2s flag if second sidedef missing:
211 if (ldef->flags & ML_TWOSIDED && ldef->sidenum[side^1]!=-1)
212 li->backsector = sides[ldef->sidenum[side^1]].sector;
213 else
214 li->backsector = 0;
215 }
216
217 W_UnlockLumpNum(lump); // cph - release the data
218}
219
220
221//
222// P_LoadSubsectors
223//
224// killough 5/3/98: reformatted, cleaned up
225
226static void P_LoadSubsectors (int lump)
227{
228 const byte *data; // cph - const*
229 int i;
230
231 numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t);
232 subsectors = Z_Calloc(numsubsectors,sizeof(subsector_t),PU_LEVEL,0);
233 data = W_CacheLumpNum(lump); // cph - wad lump handling updated
234
235 for (i=0; i<numsubsectors; i++)
236 {
237 subsectors[i].numlines = (unsigned short)SHORT(((mapsubsector_t *) data)[i].numsegs );
238 subsectors[i].firstline = (unsigned short)SHORT(((mapsubsector_t *) data)[i].firstseg);
239 }
240
241 W_UnlockLumpNum(lump); // cph - release the data
242}
243
244//
245// P_LoadSectors
246//
247// killough 5/3/98: reformatted, cleaned up
248
249static void P_LoadSectors (int lump)
250{
251 const byte *data; // cph - const*
252 int i;
253
254 numsectors = W_LumpLength (lump) / sizeof(mapsector_t);
255 sectors = Z_Calloc (numsectors,sizeof(sector_t),PU_LEVEL,0);
256 data = W_CacheLumpNum (lump); // cph - wad lump handling updated
257
258 for (i=0; i<numsectors; i++)
259 {
260 sector_t *ss = sectors + i;
261 const mapsector_t *ms = (mapsector_t *) data + i;
262
263 ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
264 ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
265 ss->floorpic = R_FlatNumForName(ms->floorpic);
266 ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
267 ss->lightlevel = SHORT(ms->lightlevel);
268 ss->special = SHORT(ms->special);
269 ss->oldspecial = SHORT(ms->special);
270 ss->tag = SHORT(ms->tag);
271 ss->thinglist = NULL;
272 ss->touching_thinglist = NULL; // phares 3/14/98
273
274 ss->nextsec = -1; //jff 2/26/98 add fields to support locking out
275 ss->prevsec = -1; // stair retriggering until build completes
276
277 // killough 3/7/98:
278 ss->floor_xoffs = 0;
279 ss->floor_yoffs = 0; // floor and ceiling flats offsets
280 ss->ceiling_xoffs = 0;
281 ss->ceiling_yoffs = 0;
282 ss->heightsec = -1; // sector used to get floor and ceiling height
283 ss->floorlightsec = -1; // sector used to get floor lighting
284 // killough 3/7/98: end changes
285
286 // killough 4/11/98 sector used to get ceiling lighting:
287 ss->ceilinglightsec = -1;
288
289 // killough 4/4/98: colormaps:
290 ss->bottommap = ss->midmap = ss->topmap = 0;
291
292 // killough 10/98: sky textures coming from sidedefs:
293 ss->sky = 0;
294 }
295
296 W_UnlockLumpNum(lump); // cph - release the data
297}
298
299
300//
301// P_LoadNodes
302//
303// killough 5/3/98: reformatted, cleaned up
304
305static void P_LoadNodes (int lump)
306{
307 const byte *data; // cph - const*
308 int i;
309
310 numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
311 nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0);
312 data = W_CacheLumpNum (lump); // cph - wad lump handling updated
313
314 for (i=0; i<numnodes; i++)
315 {
316 node_t *no = nodes + i;
317 mapnode_t *mn = (mapnode_t *) data + i;
318 int j;
319
320 no->x = SHORT(mn->x)<<FRACBITS;
321 no->y = SHORT(mn->y)<<FRACBITS;
322 no->dx = SHORT(mn->dx)<<FRACBITS;
323 no->dy = SHORT(mn->dy)<<FRACBITS;
324
325 for (j=0 ; j<2 ; j++)
326 {
327 int k;
328 no->children[j] = SHORT(mn->children[j]);
329 for (k=0 ; k<4 ; k++)
330 no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
331 }
332 }
333
334 W_UnlockLumpNum(lump); // cph - release the data
335}
336
337
338//
339// P_LoadThings
340//
341// killough 5/3/98: reformatted, cleaned up
342
343static void P_LoadThings (int lump)
344{
345 mapthing_t tempthing; // this needed to be added as the SHORT calls were overwriting eachother on reload
346 int i, numthings = W_LumpLength (lump) / sizeof(mapthing_t);
347 const byte *data = W_CacheLumpNum (lump); // cph - wad lump handling updated, const*
348
349 for (i=0; i<numthings; i++)
350 {
351 mapthing_t *mt = (mapthing_t *) data + i;
352
353 // Do not spawn cool, new monsters if !commercial
354 if (gamemode != commercial)
355 switch(mt->type)
356 {
357 case 68: // Arachnotron
358 case 64: // Archvile
359 case 88: // Boss Brain
360 case 89: // Boss Shooter
361 case 69: // Hell Knight
362 case 67: // Mancubus
363 case 71: // Pain Elemental
364 case 65: // Former Human Commando
365 case 66: // Revenant
366 case 84: // Wolf SS
367 continue;
368 }
369
370 // Do spawn all other stuff.
371 tempthing.x = SHORT(mt->x);
372 tempthing.y = SHORT(mt->y);
373 tempthing.angle = SHORT(mt->angle);
374 tempthing.type = SHORT(mt->type);
375 tempthing.options = SHORT(mt->options);
376
377 P_SpawnMapThing (&tempthing);
378 }
379
380 W_UnlockLumpNum(lump); // cph - release the data
381}
382
383//
384// P_LoadLineDefs
385// Also counts secret lines for intermissions.
386// ^^^
387// ??? killough ???
388// Does this mean secrets used to be linedef-based, rather than sector-based?
389//
390// killough 4/4/98: split into two functions, to allow sidedef overloading
391//
392// killough 5/3/98: reformatted, cleaned up
393
394static void P_LoadLineDefs (int lump)
395{
396 const byte *data; // cph - const*
397 int i;
398
399 numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
400 lines = Z_Calloc (numlines,sizeof(line_t),PU_LEVEL,0);
401 data = W_CacheLumpNum (lump); // cph - wad lump handling updated
402
403 for (i=0; i<numlines; i++)
404 {
405 maplinedef_t *mld = (maplinedef_t *) data + i;
406 line_t *ld = lines+i;
407 vertex_t *v1, *v2;
408
409 ld->flags = SHORT(mld->flags);
410 ld->special = SHORT(mld->special);
411 ld->tag = SHORT(mld->tag);
412 v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
413 v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
414 ld->dx = v2->x - v1->x;
415 ld->dy = v2->y - v1->y;
416
417 ld->tranlump = -1; // killough 4/11/98: no translucency by default
418
419 ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL :
420 FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE;
421
422 if (v1->x < v2->x)
423 {
424 ld->bbox[BOXLEFT] = v1->x;
425 ld->bbox[BOXRIGHT] = v2->x;
426 }
427 else
428 {
429 ld->bbox[BOXLEFT] = v2->x;
430 ld->bbox[BOXRIGHT] = v1->x;
431 }
432
433 if (v1->y < v2->y)
434 {
435 ld->bbox[BOXBOTTOM] = v1->y;
436 ld->bbox[BOXTOP] = v2->y;
437 }
438 else
439 {
440 ld->bbox[BOXBOTTOM] = v2->y;
441 ld->bbox[BOXTOP] = v1->y;
442 }
443
444 ld->sidenum[0] = SHORT(mld->sidenum[0]);
445 ld->sidenum[1] = SHORT(mld->sidenum[1]);
446
447 // killough 4/4/98: support special sidedef interpretation below
448 if (ld->sidenum[0] != -1 && ld->special)
449 sides[*ld->sidenum].special = ld->special;
450 }
451
452 W_UnlockLumpNum(lump); // cph - release the lump
453}
454
455// killough 4/4/98: delay using sidedefs until they are loaded
456// killough 5/3/98: reformatted, cleaned up
457
458static void P_LoadLineDefs2(int lump)
459{
460 (void)lump;
461 int i = numlines;
462 register line_t *ld = lines;
463 for (;i--;ld++)
464 {
465 { // cph 2002/07/20 - these errors are fatal if not fixed, so apply them in compatibility mode - a desync is better than a crash!
466 // killough 11/98: fix common wad errors (missing sidedefs):
467
468 if (ld->sidenum[0] == -1) {
469 ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side
470 // cph - print a warning about the bug
471 printf("P_LoadSegs: linedef %d missing first sidedef\n",numlines-i);
472 }
473
474 if ((ld->sidenum[1] == -1) && (ld->flags & ML_TWOSIDED)) {
475 ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side
476 // cph - print a warning about the bug
477 printf("P_LoadSegs: linedef %d has two-sided flag set, but no second sidedef\n",numlines-i);
478 }
479 }
480
481 ld->frontsector = ld->sidenum[0]!=-1 ? sides[ld->sidenum[0]].sector : 0;
482 ld->backsector = ld->sidenum[1]!=-1 ? sides[ld->sidenum[1]].sector : 0;
483 switch (ld->special)
484 { // killough 4/11/98: handle special types
485 int lump, j;
486
487 case 260: // killough 4/11/98: translucent 2s textures
488 lump = sides[*ld->sidenum].special; // translucency from sidedef
489 if (!ld->tag) // if tag==0,
490 ld->tranlump = lump; // affect this linedef only
491 else
492 for (j=0;j<numlines;j++) // if tag!=0,
493 if (lines[j].tag == ld->tag) // affect all matching linedefs
494 lines[j].tranlump = lump;
495 break;
496 }
497 }
498}
499
500//
501// P_LoadSideDefs
502//
503// killough 4/4/98: split into two functions
504
505static void P_LoadSideDefs (int lump)
506{
507 numsides = W_LumpLength(lump) / sizeof(mapsidedef_t);
508 sides = Z_Calloc(numsides,sizeof(side_t),PU_LEVEL,0);
509}
510
511// killough 4/4/98: delay using texture names until
512// after linedefs are loaded, to allow overloading.
513// killough 5/3/98: reformatted, cleaned up
514
515static void P_LoadSideDefs2(int lump)
516{
517 const byte *data = W_CacheLumpNum(lump); // cph - const*, wad lump handling updated
518 int i;
519
520 for (i=0; i<numsides; i++)
521 {
522 register mapsidedef_t *msd = (mapsidedef_t *) data + i;
523 register side_t *sd = sides + i;
524 register sector_t *sec;
525
526 sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
527 sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
528
529 // killough 4/4/98: allow sidedef texture names to be overloaded
530 // killough 4/11/98: refined to allow colormaps to work as wall
531 // textures if invalid as colormaps but valid as textures.
532
533 sd->sector = sec = &sectors[SHORT(msd->sector)];
534 switch (sd->special)
535 {
536 case 242: // variable colormap via 242 linedef
537 sd->bottomtexture =
538 (sec->bottommap = R_ColormapNumForName(msd->bottomtexture)) < 0 ?
539 sec->bottommap = 0, R_TextureNumForName(msd->bottomtexture): 0 ;
540 sd->midtexture =
541 (sec->midmap = R_ColormapNumForName(msd->midtexture)) < 0 ?
542 sec->midmap = 0, R_TextureNumForName(msd->midtexture) : 0 ;
543 sd->toptexture =
544 (sec->topmap = R_ColormapNumForName(msd->toptexture)) < 0 ?
545 sec->topmap = 0, R_TextureNumForName(msd->toptexture) : 0 ;
546 break;
547
548 case 260: // killough 4/11/98: apply translucency to 2s normal texture
549 sd->midtexture = strncasecmp("TRANMAP", msd->midtexture, 8) ?
550 (sd->special = W_CheckNumForName(msd->midtexture)) < 0 ||
551 W_LumpLength(sd->special) != 65536 ?
552 sd->special=0, R_TextureNumForName(msd->midtexture) :
553 (sd->special++, 0) : (sd->special=0);
554 sd->toptexture = R_TextureNumForName(msd->toptexture);
555 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
556 break;
557
558 default: // normal cases
559 sd->midtexture = R_TextureNumForName(msd->midtexture);
560 sd->toptexture = R_TextureNumForName(msd->toptexture);
561 sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
562 break;
563 }
564 }
565
566 W_UnlockLumpNum(lump); // cph - release the lump
567}
568
569//
570// jff 10/6/98
571// New code added to speed up calculation of internal blockmap
572// Algorithm is order of nlines*(ncols+nrows) not nlines*ncols*nrows
573//
574
575#define blkshift 7 /* places to shift rel position for cell num */
576#define blkmask ((1<<blkshift)-1)/* mask for rel position within cell */
577#define blkmargin 0 /* size guardband around map used */
578// jff 10/8/98 use guardband>0
579// jff 10/12/98 0 ok with + 1 in rows,cols
580
581typedef struct linelist_t // type used to list lines in each block
582{
583 long num;
584 struct linelist_t *next;
585} linelist_t;
586
587//
588// Subroutine to add a line number to a block list
589// It simply returns if the line is already in the block
590//
591
592static void AddBlockLine
593(
594 linelist_t **lists,
595 int *count,
596 int *done,
597 int blockno,
598 long lineno
599)
600{
601 linelist_t *l;
602
603 if (done[blockno])
604 return;
605
606 l = malloc(sizeof(linelist_t));
607 l->num = lineno;
608 l->next = lists[blockno];
609 lists[blockno] = l;
610 count[blockno]++;
611 done[blockno] = 1;
612}
613
614//
615// Actually construct the blockmap lump from the level data
616//
617// This finds the intersection of each linedef with the column and
618// row lines at the left and bottom of each blockmap cell. It then
619// adds the line to all block lists touching the intersection.
620//
621
622void P_CreateBlockMap()
623{
624 int xorg,yorg; // blockmap origin (lower left)
625 int nrows,ncols; // blockmap dimensions
626 linelist_t **blocklists=NULL; // array of pointers to lists of lines
627 int *blockcount=NULL; // array of counters of line lists
628 int *blockdone=NULL; // array keeping track of blocks/line
629 int NBlocks; // number of cells = nrows*ncols
630 long linetotal=0; // total length of all blocklists
631 int i,j;
632 int map_minx=INT_MAX; // init for map limits search
633 int map_miny=INT_MAX;
634 int map_maxx=INT_MIN;
635 int map_maxy=INT_MIN;
636
637 // scan for map limits, which the blockmap must enclose
638
639 for (i=0;i<numvertexes;i++)
640 {
641 fixed_t t;
642
643 if ((t=vertexes[i].x) < map_minx)
644 map_minx = t;
645 else if (t > map_maxx)
646 map_maxx = t;
647 if ((t=vertexes[i].y) < map_miny)
648 map_miny = t;
649 else if (t > map_maxy)
650 map_maxy = t;
651 }
652 map_minx >>= FRACBITS; // work in map coords, not fixed_t
653 map_maxx >>= FRACBITS;
654 map_miny >>= FRACBITS;
655 map_maxy >>= FRACBITS;
656
657 // set up blockmap area to enclose level plus margin
658
659 xorg = map_minx-blkmargin;
660 yorg = map_miny-blkmargin;
661 ncols = (map_maxx+blkmargin-xorg+1+blkmask)>>blkshift; //jff 10/12/98
662 nrows = (map_maxy+blkmargin-yorg+1+blkmask)>>blkshift; //+1 needed for
663 NBlocks = ncols*nrows; //map exactly 1 cell
664
665 // create the array of pointers on NBlocks to blocklists
666 // also create an array of linelist counts on NBlocks
667 // finally make an array in which we can mark blocks done per line
668
669 // CPhipps - calloc's
670 blocklists = calloc(NBlocks,sizeof(linelist_t *));
671 blockcount = calloc(NBlocks,sizeof(int));
672 blockdone = malloc(NBlocks*sizeof(int));
673
674 // initialize each blocklist, and enter the trailing -1 in all blocklists
675 // note the linked list of lines grows backwards
676
677 for (i=0;i<NBlocks;i++)
678 {
679 blocklists[i] = malloc(sizeof(linelist_t));
680 blocklists[i]->num = -1;
681 blocklists[i]->next = NULL;
682 blockcount[i]++;
683 }
684
685 // For each linedef in the wad, determine all blockmap blocks it touches,
686 // and add the linedef number to the blocklists for those blocks
687
688 for (i=0;i<numlines;i++)
689 {
690 int x1 = lines[i].v1->x>>FRACBITS; // lines[i] map coords
691 int y1 = lines[i].v1->y>>FRACBITS;
692 int x2 = lines[i].v2->x>>FRACBITS;
693 int y2 = lines[i].v2->y>>FRACBITS;
694 int dx = x2-x1;
695 int dy = y2-y1;
696 int vert = !dx; // lines[i] slopetype
697 int horiz = !dy;
698 int spos = (dx^dy) > 0;
699 int sneg = (dx^dy) < 0;
700 int bx,by; // block cell coords
701 int minx = x1>x2? x2 : x1; // extremal lines[i] coords
702 int maxx = x1>x2? x1 : x2;
703 int miny = y1>y2? y2 : y1;
704 int maxy = y1>y2? y1 : y2;
705
706 // no blocks done for this linedef yet
707
708 memset(blockdone,0,NBlocks*sizeof(int));
709
710 // The line always belongs to the blocks containing its endpoints
711
712 bx = (x1-xorg)>>blkshift;
713 by = (y1-yorg)>>blkshift;
714 AddBlockLine(blocklists,blockcount,blockdone,by*ncols+bx,i);
715 bx = (x2-xorg)>>blkshift;
716 by = (y2-yorg)>>blkshift;
717 AddBlockLine(blocklists,blockcount,blockdone,by*ncols+bx,i);
718
719
720 // For each column, see where the line along its left edge, which
721 // it contains, intersects the Linedef i. Add i to each corresponding
722 // blocklist.
723
724 if (!vert) // don't interesect vertical lines with columns
725 {
726 for (j=0;j<ncols;j++)
727 {
728 // intersection of Linedef with x=xorg+(j<<blkshift)
729 // (y-y1)*dx = dy*(x-x1)
730 // y = dy*(x-x1)+y1*dx;
731
732 int x = xorg+(j<<blkshift); // (x,y) is intersection
733 int y = (dy*(x-x1))/dx+y1;
734 int yb = (y-yorg)>>blkshift; // block row number
735 int yp = (y-yorg)&blkmask; // y position within block
736
737 if (yb<0 || yb>nrows-1) // outside blockmap, continue
738 continue;
739
740 if (x<minx || x>maxx) // line doesn't touch column
741 continue;
742
743 // The cell that contains the intersection point is always added
744
745 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j,i);
746
747 // if the intersection is at a corner it depends on the slope
748 // (and whether the line extends past the intersection) which
749 // blocks are hit
750
751 if (yp==0) // intersection at a corner
752 {
753 if (sneg) // \ - blocks x,y-, x-,y
754 {
755 if (yb>0 && miny<y)
756 AddBlockLine(blocklists,blockcount,blockdone,ncols*(yb-1)+j,i);
757 if (j>0 && minx<x)
758 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
759 }
760 else if (spos) // / - block x-,y-
761 {
762 if (yb>0 && j>0 && minx<x)
763 AddBlockLine(blocklists,blockcount,blockdone,ncols*(yb-1)+j-1,i);
764 }
765 else if (horiz) // - - block x-,y
766 {
767 if (j>0 && minx<x)
768 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
769 }
770 }
771 else if (j>0 && minx<x) // else not at corner: x-,y
772 AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
773 }
774 }
775
776 // For each row, see where the line along its bottom edge, which
777 // it contains, intersects the Linedef i. Add i to all the corresponding
778 // blocklists.
779
780 if (!horiz)
781 {
782 for (j=0;j<nrows;j++)
783 {
784 // intersection of Linedef with y=yorg+(j<<blkshift)
785 // (x,y) on Linedef i satisfies: (y-y1)*dx = dy*(x-x1)
786 // x = dx*(y-y1)/dy+x1;
787
788 int y = yorg+(j<<blkshift); // (x,y) is intersection
789 int x = (dx*(y-y1))/dy+x1;
790 int xb = (x-xorg)>>blkshift; // block column number
791 int xp = (x-xorg)&blkmask; // x position within block
792
793 if (xb<0 || xb>ncols-1) // outside blockmap, continue
794 continue;
795
796 if (y<miny || y>maxy) // line doesn't touch row
797 continue;
798
799 // The cell that contains the intersection point is always added
800
801 AddBlockLine(blocklists,blockcount,blockdone,ncols*j+xb,i);
802
803 // if the intersection is at a corner it depends on the slope
804 // (and whether the line extends past the intersection) which
805 // blocks are hit
806
807 if (xp==0) // intersection at a corner
808 {
809 if (sneg) // \ - blocks x,y-, x-,y
810 {
811 if (j>0 && miny<y)
812 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
813 if (xb>0 && minx<x)
814 AddBlockLine(blocklists,blockcount,blockdone,ncols*j+xb-1,i);
815 }
816 else if (vert) // | - block x,y-
817 {
818 if (j>0 && miny<y)
819 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
820 }
821 else if (spos) // / - block x-,y-
822 {
823 if (xb>0 && j>0 && miny<y)
824 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb-1,i);
825 }
826 }
827 else if (j>0 && miny<y) // else not on a corner: x,y-
828 AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
829 }
830 }
831 }
832
833 // Add initial 0 to all blocklists
834 // count the total number of lines (and 0's and -1's)
835
836 memset(blockdone,0,NBlocks*sizeof(int));
837 for (i=0,linetotal=0;i<NBlocks;i++)
838 {
839 AddBlockLine(blocklists,blockcount,blockdone,i,0);
840 linetotal += blockcount[i];
841 }
842
843 // Create the blockmap lump
844
845 blockmaplump = Z_Malloc(sizeof(*blockmaplump) * (4+NBlocks+linetotal),
846 PU_LEVEL, 0);
847 // blockmap header
848
849 blockmaplump[0] = bmaporgx = xorg << FRACBITS;
850 blockmaplump[1] = bmaporgy = yorg << FRACBITS;
851 blockmaplump[2] = bmapwidth = ncols;
852 blockmaplump[3] = bmapheight = nrows;
853
854 // offsets to lists and block lists
855
856 for (i=0;i<NBlocks;i++)
857 {
858 linelist_t *bl = blocklists[i];
859 long offs = blockmaplump[4+i] = // set offset to block's list
860 (i? blockmaplump[4+i-1] : 4+NBlocks) + (i? blockcount[i-1] : 0);
861
862 // add the lines in each block's list to the blockmaplump
863 // delete each list node as we go
864
865 while (bl)
866 {
867 linelist_t *tmp = bl->next;
868 blockmaplump[offs++] = bl->num;
869 free(bl);
870 bl = tmp;
871 }
872 }
873
874 // free all temporary storage
875
876 free (blocklists);
877 free (blockcount);
878 free (blockdone);
879}
880
881// jff 10/6/98
882// End new code added to speed up calculation of internal blockmap
883
884//
885// P_LoadBlockMap
886//
887// killough 3/1/98: substantially modified to work
888// towards removing blockmap limit (a wad limitation)
889//
890// killough 3/30/98: Rewritten to remove blockmap limit,
891// though current algorithm is brute-force and unoptimal.
892//
893
894static void P_LoadBlockMap (int lump)
895{
896 long count;
897
898 if (M_CheckParm("-blockmap") || (count = W_LumpLength(lump)/2) >= 0x10000)
899 P_CreateBlockMap();
900 else
901 {
902 long i;
903 // cph - const*, wad lump handling updated
904 const short *wadblockmaplump = W_CacheLumpNum(lump);
905 blockmaplump = Z_Malloc(sizeof(*blockmaplump) * count, PU_LEVEL, 0);
906
907 // killough 3/1/98: Expand wad blockmap into larger internal one,
908 // by treating all offsets except -1 as unsigned and zero-extending
909 // them. This potentially doubles the size of blockmaps allowed,
910 // because Doom originally considered the offsets as always signed.
911
912 blockmaplump[0] = SHORT(wadblockmaplump[0]);
913 blockmaplump[1] = SHORT(wadblockmaplump[1]);
914 blockmaplump[2] = (long)(SHORT(wadblockmaplump[2])) & 0xffff;
915 blockmaplump[3] = (long)(SHORT(wadblockmaplump[3])) & 0xffff;
916
917 for (i=4 ; i<count ; i++)
918 {
919 short t = SHORT(wadblockmaplump[i]); // killough 3/1/98
920 blockmaplump[i] = t == -1 ? -1l : (long) t & 0xffff;
921 }
922
923 W_UnlockLumpNum(lump); // cph - unlock the lump
924
925 bmaporgx = blockmaplump[0]<<FRACBITS;
926 bmaporgy = blockmaplump[1]<<FRACBITS;
927 bmapwidth = blockmaplump[2];
928 bmapheight = blockmaplump[3];
929 }
930
931 // clear out mobj chains - CPhipps - use calloc
932 blocklinks = Z_Calloc (bmapwidth*bmapheight,sizeof(*blocklinks),PU_LEVEL,0);
933 blockmap = blockmaplump+4;
934}
935
936//
937// P_GroupLines
938// Builds sector line lists and subsector sector numbers.
939// Finds block bounding boxes for sectors.
940//
941// killough 5/3/98: reformatted, cleaned up
942// cph 18/8/99: rewritten to avoid O(numlines * numsectors) section
943// It makes things more complicated, but saves seconds on big levels
944// figgi 09/18/00 -- adapted for gl-nodes
945
946// cph - convenient sub-function
947static void P_AddLineToSector(line_t* li, sector_t* sector)
948{
949 fixed_t *bbox = (void*)sector->blockbox;
950
951 sector->lines[sector->linecount++] = li;
952 M_AddToBox (bbox, li->v1->x, li->v1->y);
953 M_AddToBox (bbox, li->v2->x, li->v2->y);
954}
955
956void P_GroupLines (void)
957{
958 register line_t *li;
959 register sector_t *sector;
960 int i,j, total = numlines;
961
962 // figgi
963 for (i=0 ; i<numsubsectors ; i++)
964 {
965 seg_t *seg = &segs[subsectors[i].firstline];
966 subsectors[i].sector = NULL;
967 for(j=0; j<subsectors[i].numlines; j++)
968 {
969 if(seg->sidedef)
970 {
971 subsectors[i].sector = seg->sidedef->sector;
972 break;
973 }
974 seg++;
975 }
976 if(subsectors[i].sector == NULL)
977 I_Error("P_GroupLines: Subsector a part of no sector!\n");
978 }
979
980 // count number of lines in each sector
981 for (i=0,li=lines; i<numlines; i++, li++)
982 {
983 li->frontsector->linecount++;
984 if (li->backsector && li->backsector != li->frontsector)
985 {
986 li->backsector->linecount++;
987 total++;
988 }
989 }
990
991 { // allocate line tables for each sector
992 line_t **linebuffer = Z_Malloc(total*sizeof(line_t *), PU_LEVEL, 0);
993
994 for (i=0, sector = sectors; i<numsectors; i++, sector++)
995 {
996 sector->lines = linebuffer;
997 linebuffer += sector->linecount;
998 sector->linecount = 0;
999 M_ClearBox(sector->blockbox);
1000 }
1001 }
1002
1003 // Enter those lines
1004 for (i=0,li=lines; i<numlines; i++, li++)
1005 {
1006 P_AddLineToSector(li, li->frontsector);
1007 if (li->backsector && li->backsector != li->frontsector)
1008 P_AddLineToSector(li, li->backsector);
1009 }
1010
1011 for (i=0, sector = sectors; i<numsectors; i++, sector++)
1012 {
1013 fixed_t *bbox = (void*)sector->blockbox; // cph - For convenience, so
1014 // I can sue the old code unchanged
1015 int block;
1016
1017 // set the degenmobj_t to the middle of the bounding box
1018 sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
1019 sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
1020
1021 // adjust bounding box to map blocks
1022 block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
1023 block = block >= bmapheight ? bmapheight-1 : block;
1024 sector->blockbox[BOXTOP]=block;
1025
1026 block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
1027 block = block < 0 ? 0 : block;
1028 sector->blockbox[BOXBOTTOM]=block;
1029
1030 block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
1031 block = block >= bmapwidth ? bmapwidth-1 : block;
1032 sector->blockbox[BOXRIGHT]=block;
1033
1034 block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
1035 block = block < 0 ? 0 : block;
1036 sector->blockbox[BOXLEFT]=block;
1037 }
1038
1039}
1040
1041//
1042// killough 10/98
1043//
1044// Remove slime trails.
1045//
1046// Slime trails are inherent to Doom's coordinate system -- i.e. there is
1047// nothing that a node builder can do to prevent slime trails ALL of the time,
1048// because it's a product of the integer coodinate system, and just because
1049// two lines pass through exact integer coordinates, doesn't necessarily mean
1050// that they will intersect at integer coordinates. Thus we must allow for
1051// fractional coordinates if we are to be able to split segs with node lines,
1052// as a node builder must do when creating a BSP tree.
1053//
1054// A wad file does not allow fractional coordinates, so node builders are out
1055// of luck except that they can try to limit the number of splits (they might
1056// also be able to detect the degree of roundoff error and try to avoid splits
1057// with a high degree of roundoff error). But we can use fractional coordinates
1058// here, inside the engine. It's like the difference between square inches and
1059// square miles, in terms of granularity.
1060//
1061// For each vertex of every seg, check to see whether it's also a vertex of
1062// the linedef associated with the seg (i.e, it's an endpoint). If it's not
1063// an endpoint, and it wasn't already moved, move the vertex towards the
1064// linedef by projecting it using the law of cosines. Formula:
1065//
1066// 2 2 2 2
1067// dx x0 + dy x1 + dx dy (y0 - y1) dy y0 + dx y1 + dx dy (x0 - x1)
1068// {---------------------------------, ---------------------------------}
1069// 2 2 2 2
1070// dx + dy dx + dy
1071//
1072// (x0,y0) is the vertex being moved, and (x1,y1)-(x1+dx,y1+dy) is the
1073// reference linedef.
1074//
1075// Segs corresponding to orthogonal linedefs (exactly vertical or horizontal
1076// linedefs), which comprise at least half of all linedefs in most wads, don't
1077// need to be considered, because they almost never contribute to slime trails
1078// (because then any roundoff error is parallel to the linedef, which doesn't
1079// cause slime). Skipping simple orthogonal lines lets the code finish quicker.
1080//
1081// Please note: This section of code is not interchangable with TeamTNT's
1082// code which attempts to fix the same problem.
1083//
1084// Firelines (TM) is a Rezistered Trademark of MBF Productions
1085//
1086
1087void P_RemoveSlimeTrails(void) // killough 10/98
1088{
1089 byte *hit = calloc(1, numvertexes); // Hitlist for vertices
1090 int i;
1091 for (i=0; i<numsegs; i++) // Go through each seg
1092 {
1093 const line_t *l;
1094
1095 if (segs[i].miniseg == true) //figgi -- skip minisegs
1096 return;
1097
1098 l = segs[i].linedef; // The parent linedef
1099 if (l->dx && l->dy) // We can ignore orthogonal lines
1100 {
1101 vertex_t *v = segs[i].v1;
1102 do
1103 if (!hit[v - vertexes]) // If we haven't processed vertex
1104 {
1105 hit[v - vertexes] = 1; // Mark this vertex as processed
1106 if (v != l->v1 && v != l->v2) // Exclude endpoints of linedefs
1107 { // Project the vertex back onto the parent linedef
1108 int_64_t dx2 = (l->dx >> FRACBITS) * (l->dx >> FRACBITS);
1109 int_64_t dy2 = (l->dy >> FRACBITS) * (l->dy >> FRACBITS);
1110 int_64_t dxy = (l->dx >> FRACBITS) * (l->dy >> FRACBITS);
1111 int_64_t s = dx2 + dy2;
1112 int x0 = v->x, y0 = v->y, x1 = l->v1->x, y1 = l->v1->y;
1113 v->x = (int)((dx2 * x0 + dy2 * x1 + dxy * (y0 - y1)) / s);
1114 v->y = (int)((dy2 * y0 + dx2 * y1 + dxy * (x0 - x1)) / s);
1115 }
1116 } // Obsfucated C contest entry: :)
1117 while ((v != segs[i].v2) && (v = segs[i].v2));
1118 }
1119 }
1120 free(hit);
1121}
1122
1123//
1124// P_SetupLevel
1125//
1126// killough 5/3/98: reformatted, cleaned up
1127
1128void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
1129{
1130 (void)playermask;
1131 (void)skill;
1132 int i;
1133 char lumpname[9];
1134 int lumpnum;
1135
1136
1137 totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
1138 wminfo.partime = 180;
1139
1140 for (i=0; i<MAXPLAYERS; i++)
1141 players[i].killcount = players[i].secretcount = players[i].itemcount = 0;
1142
1143 // Initial height of PointOfView will be set by player think.
1144 players[consoleplayer].viewz = 1;
1145
1146 // Make sure all sounds are stopped before Z_FreeTags.
1147 S_Start();
1148
1149 Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1);
1150 if (rejectlump != -1) { // cph - unlock the reject table
1151 W_UnlockLumpNum(rejectlump);
1152 rejectlump = -1;
1153 }
1154
1155 P_InitThinkers();
1156
1157 // if working with a devlopment map, reload it
1158 // W_Reload (); killough 1/31/98: W_Reload obsolete
1159
1160 // find map name
1161 if (gamemode == commercial)
1162 {
1163 if (map<10)
1164 snprintf (lumpname,sizeof(lumpname),"map0%d", map);
1165 else
1166 snprintf (lumpname,sizeof(lumpname),"map%d", map);
1167 }
1168 else
1169 {
1170 snprintf(lumpname,sizeof(lumpname), "E%dM%d", episode, map); // killough 1/24/98: simplify
1171 }
1172
1173 lumpnum = W_GetNumForName(lumpname);
1174
1175 leveltime = 0;
1176
1177 // note: most of this ordering is important
1178
1179 // killough 3/1/98: P_LoadBlockMap call moved down to below
1180 // killough 4/4/98: split load of sidedefs into two parts,
1181 // to allow texture names to be used in special linedefs
1182
1183 usingGLNodes = false;
1184 P_LoadVertexes (lumpnum+ML_VERTEXES);
1185 P_LoadSectors (lumpnum+ML_SECTORS);
1186 P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
1187 P_LoadLineDefs (lumpnum+ML_LINEDEFS);
1188 P_LoadSideDefs2 (lumpnum+ML_SIDEDEFS);
1189 P_LoadLineDefs2 (lumpnum+ML_LINEDEFS);
1190 P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
1191
1192 P_LoadSubsectors(lumpnum + ML_SSECTORS);
1193 P_LoadNodes(lumpnum + ML_NODES);
1194 P_LoadSegs(lumpnum + ML_SEGS);
1195
1196 if (rejectlump != -1)
1197 W_UnlockLumpNum(rejectlump);
1198 rejectlump = lumpnum+ML_REJECT;
1199 {
1200 int rjlen = W_LumpLength(rejectlump);
1201 int rjreq = (numsectors*numsectors+7)/8;
1202 if (rjlen < rjreq) {
1203 printf("P_SetupLevel: REJECT too short (%d<%d) - padded\n",rjlen,rjreq);
1204 rejectmatrix = W_CacheLumpNumPadded(rejectlump,rjreq,0xff);
1205 } else {
1206 rejectmatrix = W_CacheLumpNum(rejectlump);
1207 }
1208 }
1209 P_GroupLines();
1210
1211 P_RemoveSlimeTrails(); // killough 10/98: remove slime trails from wad
1212
1213 // Note: you don't need to clear player queue slots --
1214 // a much simpler fix is in g_game.c -- killough 10/98
1215
1216 bodyqueslot = 0;
1217 deathmatch_p = deathmatchstarts;
1218 P_MapStart();
1219 P_LoadThings(lumpnum+ML_THINGS);
1220
1221 // if deathmatch, randomly spawn the active players
1222 if (deathmatch)
1223 for (i=0; i<MAXPLAYERS; i++)
1224 if (playeringame[i])
1225 {
1226 players[i].mo = NULL;
1227 G_DeathMatchSpawnPlayer(i);
1228 }
1229
1230 // killough 3/26/98: Spawn icon landings:
1231 if (gamemode==commercial)
1232 P_SpawnBrainTargets();
1233
1234 // clear special respawning que
1235 iquehead = iquetail = 0;
1236
1237 // set up world state
1238 P_SpawnSpecials();
1239
1240 P_MapEnd();
1241
1242 // preload graphics
1243 if (precache)
1244 R_PrecacheLevel();
1245}
1246
1247//
1248// P_Init
1249//
1250void P_Init (void)
1251{
1252 P_InitSwitchList();
1253 P_InitPicAnims();
1254 R_InitSprites(sprnames);
1255}