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