p_setup.c 51 KB

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