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