]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/doom/p_setup.c
merge
[plan9front.git] / sys / src / games / doom / p_setup.c
1 // Emacs style mode select   -*- C++ -*- 
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // $Log:$
18 //
19 // DESCRIPTION:
20 //      Do all the WAD I/O, get map description,
21 //      set up initial state and misc. LUTs.
22 //
23 //-----------------------------------------------------------------------------
24
25 static const char
26 rcsid[] = "$Id: p_setup.c,v 1.5 1997/02/03 22:45:12 b1 Exp $";
27
28
29 #include "z_zone.h"
30
31 #include "m_swap.h"
32 #include "m_bbox.h"
33
34 #include "g_game.h"
35
36 #include "i_system.h"
37 #include "w_wad.h"
38
39 #include "doomdef.h"
40 #include "p_local.h"
41
42 #include "s_sound.h"
43
44 #include "doomstat.h"
45
46
47 void    P_SpawnMapThing (mapthing_t*    mthing);
48
49
50 //
51 // MAP related Lookup tables.
52 // Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
53 //
54 int             numvertexes;
55 vertex_t*       vertexes;
56
57 int             numsegs;
58 seg_t*          segs;
59
60 int             numsectors;
61 sector_t*       sectors;
62
63 int             numsubsectors;
64 subsector_t*    subsectors;
65
66 int             numnodes;
67 node_t*         nodes;
68
69 int             numlines;
70 line_t*         lines;
71
72 int             numsides;
73 side_t*         sides;
74
75
76 // BLOCKMAP
77 // Created from axis aligned bounding box
78 // of the map, a rectangular array of
79 // blocks of size ...
80 // Used to speed up collision detection
81 // by spatial subdivision in 2D.
82 //
83 // Blockmap size.
84 int             bmapwidth;
85 int             bmapheight;     // size in mapblocks
86 short*          blockmap;       // int for larger maps
87 // offsets in blockmap are from here
88 short*          blockmaplump;           
89 // origin of block map
90 fixed_t         bmaporgx;
91 fixed_t         bmaporgy;
92 // for thing chains
93 mobj_t**        blocklinks;             
94
95
96 // REJECT
97 // For fast sight rejection.
98 // Speeds up enemy AI by skipping detailed
99 //  LineOf Sight calculation.
100 // Without special effect, this could be
101 //  used as a PVS lookup as well.
102 //
103 byte*           rejectmatrix;
104
105
106 // Maintain single and multi player starting spots.
107 #define MAX_DEATHMATCH_STARTS   10
108
109 mapthing_t      deathmatchstarts[MAX_DEATHMATCH_STARTS];
110 mapthing_t*     deathmatch_p;
111 mapthing_t      playerstarts[MAXPLAYERS];
112
113
114
115
116
117 //
118 // P_LoadVertexes
119 //
120 void P_LoadVertexes (int lump)
121 {
122     byte*               data;
123     int                 i;
124     mapvertex_t*        ml;
125     vertex_t*           li;
126
127     // Determine number of lumps:
128     //  total lump length / vertex record length.
129     numvertexes = W_LumpLength (lump) / sizeof(mapvertex_t);
130
131     // Allocate zone memory for buffer.
132     vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0);      
133
134     // Load data into cache.
135     data = W_CacheLumpNum (lump,PU_STATIC);
136         
137     ml = (mapvertex_t *)data;
138     li = vertexes;
139
140     // Copy and convert vertex coordinates,
141     // internal representation as fixed.
142     for (i=0 ; i<numvertexes ; i++, li++, ml++)
143     {
144         li->x = SHORT(ml->x)<<FRACBITS;
145         li->y = SHORT(ml->y)<<FRACBITS;
146     }
147
148     // Free buffer memory.
149     Z_Free (data);
150 }
151
152
153
154 //
155 // P_LoadSegs
156 //
157 void P_LoadSegs (int lump)
158 {
159     byte*               data;
160     int                 i;
161     mapseg_t*           ml;
162     seg_t*              li;
163     line_t*             ldef;
164     int                 linedef;
165     int                 side;
166         
167     numsegs = W_LumpLength (lump) / sizeof(mapseg_t);
168     segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0); 
169     memset (segs, 0, numsegs*sizeof(seg_t));
170     data = W_CacheLumpNum (lump,PU_STATIC);
171         
172     ml = (mapseg_t *)data;
173     li = segs;
174     for (i=0 ; i<numsegs ; i++, li++, ml++)
175     {
176         li->v1 = &vertexes[SHORT(ml->v1)];
177         li->v2 = &vertexes[SHORT(ml->v2)];
178                                         
179         li->angle = (SHORT(ml->angle))<<16;
180         li->offset = (SHORT(ml->offset))<<16;
181         linedef = SHORT(ml->linedef);
182         ldef = &lines[linedef];
183         li->linedef = ldef;
184         side = SHORT(ml->side);
185         li->sidedef = &sides[ldef->sidenum[side]];
186         li->frontsector = sides[ldef->sidenum[side]].sector;
187         if (ldef-> flags & ML_TWOSIDED)
188             li->backsector = sides[ldef->sidenum[side^1]].sector;
189         else
190             li->backsector = 0;
191     }
192         
193     Z_Free (data);
194 }
195
196
197 //
198 // P_LoadSubsectors
199 //
200 void P_LoadSubsectors (int lump)
201 {
202     byte*               data;
203     int                 i;
204     mapsubsector_t*     ms;
205     subsector_t*        ss;
206         
207     numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t);
208     subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0);       
209     data = W_CacheLumpNum (lump,PU_STATIC);
210         
211     ms = (mapsubsector_t *)data;
212     memset (subsectors,0, numsubsectors*sizeof(subsector_t));
213     ss = subsectors;
214     
215     for (i=0 ; i<numsubsectors ; i++, ss++, ms++)
216     {
217         ss->numlines = SHORT(ms->numsegs);
218         ss->firstline = SHORT(ms->firstseg);
219     }
220         
221     Z_Free (data);
222 }
223
224
225
226 //
227 // P_LoadSectors
228 //
229 void P_LoadSectors (int lump)
230 {
231     byte*               data;
232     int                 i;
233     mapsector_t*        ms;
234     sector_t*           ss;
235         
236     numsectors = W_LumpLength (lump) / sizeof(mapsector_t);
237     sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0);        
238     memset (sectors, 0, numsectors*sizeof(sector_t));
239     data = W_CacheLumpNum (lump,PU_STATIC);
240         
241     ms = (mapsector_t *)data;
242     ss = sectors;
243     for (i=0 ; i<numsectors ; i++, ss++, ms++)
244     {
245         ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
246         ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
247         ss->floorpic = R_FlatNumForName(ms->floorpic);
248         ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
249         ss->lightlevel = SHORT(ms->lightlevel);
250         ss->special = SHORT(ms->special);
251         ss->tag = SHORT(ms->tag);
252         ss->thinglist = NULL;
253     }
254         
255     Z_Free (data);
256 }
257
258
259 //
260 // P_LoadNodes
261 //
262 void P_LoadNodes (int lump)
263 {
264     byte*       data;
265     int         i;
266     int         j;
267     int         k;
268     mapnode_t*  mn;
269     node_t*     no;
270         
271     numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
272     nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0);      
273     data = W_CacheLumpNum (lump,PU_STATIC);
274         
275     mn = (mapnode_t *)data;
276     no = nodes;
277     
278     for (i=0 ; i<numnodes ; i++, no++, mn++)
279     {
280         no->x = SHORT(mn->x)<<FRACBITS;
281         no->y = SHORT(mn->y)<<FRACBITS;
282         no->dx = SHORT(mn->dx)<<FRACBITS;
283         no->dy = SHORT(mn->dy)<<FRACBITS;
284         for (j=0 ; j<2 ; j++)
285         {
286             no->children[j] = SHORT(mn->children[j]);
287             for (k=0 ; k<4 ; k++)
288                 no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
289         }
290     }
291         
292     Z_Free (data);
293 }
294
295
296 //
297 // P_LoadThings
298 //
299 void P_LoadThings (int lump)
300 {
301     byte*               data;
302     int                 i;
303     mapthing_t*         mt;
304     int                 numthings;
305     boolean             spawn;
306         
307     data = W_CacheLumpNum (lump,PU_STATIC);
308     numthings = W_LumpLength (lump) / sizeof(mapthing_t);
309         
310     mt = (mapthing_t *)data;
311     for (i=0 ; i<numthings ; i++, mt++)
312     {
313         spawn = true;
314
315         // Do not spawn cool, new monsters if !commercial
316         if ( gamemode != commercial)
317         {
318             switch(mt->type)
319             {
320               case 68:  // Arachnotron
321               case 64:  // Archvile
322               case 88:  // Boss Brain
323               case 89:  // Boss Shooter
324               case 69:  // Hell Knight
325               case 67:  // Mancubus
326               case 71:  // Pain Elemental
327               case 65:  // Former Human Commando
328               case 66:  // Revenant
329               case 84:  // Wolf SS
330                 spawn = false;
331                 break;
332             }
333         }
334         if (spawn == false)
335             break;
336
337         // Do spawn all other stuff. 
338         mt->x = SHORT(mt->x);
339         mt->y = SHORT(mt->y);
340         mt->angle = SHORT(mt->angle);
341         mt->type = SHORT(mt->type);
342         mt->options = SHORT(mt->options);
343         
344         P_SpawnMapThing (mt);
345     }
346         
347     Z_Free (data);
348 }
349
350
351 //
352 // P_LoadLineDefs
353 // Also counts secret lines for intermissions.
354 //
355 void P_LoadLineDefs (int lump)
356 {
357     byte*               data;
358     int                 i;
359     maplinedef_t*       mld;
360     line_t*             ld;
361     vertex_t*           v1;
362     vertex_t*           v2;
363         
364     numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
365     lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0);      
366     memset (lines, 0, numlines*sizeof(line_t));
367     data = W_CacheLumpNum (lump,PU_STATIC);
368         
369     mld = (maplinedef_t *)data;
370     ld = lines;
371     for (i=0 ; i<numlines ; i++, mld++, ld++)
372     {
373         ld->flags = SHORT(mld->flags);
374         ld->special = SHORT(mld->special);
375         ld->tag = SHORT(mld->tag);
376         v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
377         v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
378         ld->dx = v2->x - v1->x;
379         ld->dy = v2->y - v1->y;
380         
381         if (!ld->dx)
382             ld->slopetype = ST_VERTICAL;
383         else if (!ld->dy)
384             ld->slopetype = ST_HORIZONTAL;
385         else
386         {
387             if (FixedDiv (ld->dy , ld->dx) > 0)
388                 ld->slopetype = ST_POSITIVE;
389             else
390                 ld->slopetype = ST_NEGATIVE;
391         }
392                 
393         if (v1->x < v2->x)
394         {
395             ld->bbox[BOXLEFT] = v1->x;
396             ld->bbox[BOXRIGHT] = v2->x;
397         }
398         else
399         {
400             ld->bbox[BOXLEFT] = v2->x;
401             ld->bbox[BOXRIGHT] = v1->x;
402         }
403
404         if (v1->y < v2->y)
405         {
406             ld->bbox[BOXBOTTOM] = v1->y;
407             ld->bbox[BOXTOP] = v2->y;
408         }
409         else
410         {
411             ld->bbox[BOXBOTTOM] = v2->y;
412             ld->bbox[BOXTOP] = v1->y;
413         }
414
415         ld->sidenum[0] = SHORT(mld->sidenum[0]);
416         ld->sidenum[1] = SHORT(mld->sidenum[1]);
417
418         if (ld->sidenum[0] != -1)
419             ld->frontsector = sides[ld->sidenum[0]].sector;
420         else
421             ld->frontsector = 0;
422
423         if (ld->sidenum[1] != -1)
424             ld->backsector = sides[ld->sidenum[1]].sector;
425         else
426             ld->backsector = 0;
427     }
428         
429     Z_Free (data);
430 }
431
432
433 //
434 // P_LoadSideDefs
435 //
436 void P_LoadSideDefs (int lump)
437 {
438     byte*               data;
439     int                 i;
440     mapsidedef_t*       msd;
441     side_t*             sd;
442         
443     numsides = W_LumpLength (lump) / sizeof(mapsidedef_t);
444     sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0);      
445     memset (sides, 0, numsides*sizeof(side_t));
446     data = W_CacheLumpNum (lump,PU_STATIC);
447         
448     msd = (mapsidedef_t *)data;
449     sd = sides;
450     for (i=0 ; i<numsides ; i++, msd++, sd++)
451     {
452         sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
453         sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
454         sd->toptexture = R_TextureNumForName(msd->toptexture);
455         sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
456         sd->midtexture = R_TextureNumForName(msd->midtexture);
457         sd->sector = &sectors[SHORT(msd->sector)];
458     }
459         
460     Z_Free (data);
461 }
462
463
464 //
465 // P_LoadBlockMap
466 //
467 void P_LoadBlockMap (int lump)
468 {
469     int         i;
470     int         count;
471         
472     blockmaplump = W_CacheLumpNum (lump,PU_LEVEL);
473     blockmap = blockmaplump+4;
474     count = W_LumpLength (lump)/2;
475
476     for (i=0 ; i<count ; i++)
477         blockmaplump[i] = SHORT(blockmaplump[i]);
478                 
479     bmaporgx = blockmaplump[0]<<FRACBITS;
480     bmaporgy = blockmaplump[1]<<FRACBITS;
481     bmapwidth = blockmaplump[2];
482     bmapheight = blockmaplump[3];
483         
484     // clear out mobj chains
485     count = sizeof(*blocklinks)* bmapwidth*bmapheight;
486     blocklinks = Z_Malloc (count,PU_LEVEL, 0);
487     memset (blocklinks, 0, count);
488 }
489
490
491
492 //
493 // P_GroupLines
494 // Builds sector line lists and subsector sector numbers.
495 // Finds block bounding boxes for sectors.
496 //
497 void P_GroupLines (void)
498 {
499     line_t**            linebuffer;
500     int                 i;
501     int                 j;
502     int                 total;
503     line_t*             li;
504     sector_t*           sector;
505     subsector_t*        ss;
506     seg_t*              seg;
507     fixed_t             bbox[4];
508     int                 block;
509         
510     // look up sector number for each subsector
511     ss = subsectors;
512     for (i=0 ; i<numsubsectors ; i++, ss++)
513     {
514         seg = &segs[ss->firstline];
515         ss->sector = seg->sidedef->sector;
516     }
517
518     // count number of lines in each sector
519     li = lines;
520     total = 0;
521     for (i=0 ; i<numlines ; i++, li++)
522     {
523         total++;
524         li->frontsector->linecount++;
525
526         if (li->backsector && li->backsector != li->frontsector)
527         {
528             li->backsector->linecount++;
529             total++;
530         }
531     }
532         
533     // build line tables for each sector        
534     linebuffer = Z_Malloc (total*4, PU_LEVEL, 0);
535     sector = sectors;
536     for (i=0 ; i<numsectors ; i++, sector++)
537     {
538         M_ClearBox (bbox);
539         sector->lines = linebuffer;
540         li = lines;
541         for (j=0 ; j<numlines ; j++, li++)
542         {
543             if (li->frontsector == sector || li->backsector == sector)
544             {
545                 *linebuffer++ = li;
546                 M_AddToBox (bbox, li->v1->x, li->v1->y);
547                 M_AddToBox (bbox, li->v2->x, li->v2->y);
548             }
549         }
550         if (linebuffer - sector->lines != sector->linecount)
551             I_Error ("P_GroupLines: miscounted");
552                         
553         // set the degenmobj_t to the middle of the bounding box
554         sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
555         sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
556                 
557         // adjust bounding box to map blocks
558         block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
559         block = block >= bmapheight ? bmapheight-1 : block;
560         sector->blockbox[BOXTOP]=block;
561
562         block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
563         block = block < 0 ? 0 : block;
564         sector->blockbox[BOXBOTTOM]=block;
565
566         block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
567         block = block >= bmapwidth ? bmapwidth-1 : block;
568         sector->blockbox[BOXRIGHT]=block;
569
570         block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
571         block = block < 0 ? 0 : block;
572         sector->blockbox[BOXLEFT]=block;
573     }
574         
575 }
576
577
578 //
579 // P_SetupLevel
580 //
581 void
582 P_SetupLevel
583 ( int           episode,
584   int           map)
585 {
586     int         i;
587     char        lumpname[9];
588     int         lumpnum;
589         
590     totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
591     wminfo.partime = 180;
592     for (i=0 ; i<MAXPLAYERS ; i++)
593     {
594         players[i].killcount = players[i].secretcount 
595             = players[i].itemcount = 0;
596     }
597
598     // Initial height of PointOfView
599     // will be set by player think.
600     players[consoleplayer].viewz = 1; 
601
602     // Make sure all sounds are stopped before Z_FreeTags.
603     S_Start ();                 
604
605     Z_FreeTags (PU_LEVEL, PU_PURGELEVEL-1);
606
607     // UNUSED W_Profile ();
608     P_InitThinkers ();
609
610     // if working with a devlopment map, reload it
611     W_Reload ();                        
612            
613     // find map name
614     if ( gamemode == commercial)
615     {
616         if (map<10)
617             sprintf (lumpname,"map0%i", map);
618         else
619             sprintf (lumpname,"map%i", map);
620     }
621     else
622     {
623         lumpname[0] = 'E';
624         lumpname[1] = '0' + episode;
625         lumpname[2] = 'M';
626         lumpname[3] = '0' + map;
627         lumpname[4] = 0;
628     }
629
630     lumpnum = W_GetNumForName (lumpname);
631         
632     leveltime = 0;
633         
634     // note: most of this ordering is important 
635     P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
636     P_LoadVertexes (lumpnum+ML_VERTEXES);
637     P_LoadSectors (lumpnum+ML_SECTORS);
638     P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
639
640     P_LoadLineDefs (lumpnum+ML_LINEDEFS);
641     P_LoadSubsectors (lumpnum+ML_SSECTORS);
642     P_LoadNodes (lumpnum+ML_NODES);
643     P_LoadSegs (lumpnum+ML_SEGS);
644         
645     rejectmatrix = W_CacheLumpNum (lumpnum+ML_REJECT,PU_LEVEL);
646     P_GroupLines ();
647
648     bodyqueslot = 0;
649     deathmatch_p = deathmatchstarts;
650     P_LoadThings (lumpnum+ML_THINGS);
651     
652     // if deathmatch, randomly spawn the active players
653     if (deathmatch)
654     {
655         for (i=0 ; i<MAXPLAYERS ; i++)
656             if (playeringame[i])
657             {
658 printf("DBG: players[%d].mo = NULL\n", i);
659                 players[i].mo = NULL;
660                 G_DeathMatchSpawnPlayer (i);
661             }
662                         
663     }
664
665     // clear special respawning que
666     iquehead = iquetail = 0;            
667         
668     // set up world state
669     P_SpawnSpecials ();
670         
671     // preload graphics
672     if (precache)
673         R_PrecacheLevel ();
674 }
675
676
677
678 //
679 // P_Init
680 //
681 void P_Init (void)
682 {
683     P_InitSwitchList ();
684     P_InitPicAnims ();
685     R_InitSprites (sprnames);
686 }
687
688
689