diff options
Diffstat (limited to 'src/p_spec.c')
-rw-r--r-- | src/p_spec.c | 3353 |
1 files changed, 3353 insertions, 0 deletions
diff --git a/src/p_spec.c b/src/p_spec.c new file mode 100644 index 0000000..738eec2 --- /dev/null +++ b/src/p_spec.c | |||
@@ -0,0 +1,3353 @@ | |||
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 | * -Loads and initializes texture and flat animation sequences | ||
31 | * -Implements utility functions for all linedef/sector special handlers | ||
32 | * -Dispatches walkover and gun line triggers | ||
33 | * -Initializes and implements special sector types | ||
34 | * -Implements donut linedef triggers | ||
35 | * -Initializes and implements BOOM linedef triggers for | ||
36 | * Scrollers/Conveyors | ||
37 | * Friction | ||
38 | * Wind/Current | ||
39 | * | ||
40 | *-----------------------------------------------------------------------------*/ | ||
41 | |||
42 | #include "doomstat.h" | ||
43 | #include "p_spec.h" | ||
44 | #include "p_tick.h" | ||
45 | #include "p_setup.h" | ||
46 | #include "m_random.h" | ||
47 | #include "d_englsh.h" | ||
48 | #include "m_argv.h" | ||
49 | #include "w_wad.h" | ||
50 | #include "r_main.h" | ||
51 | #include "p_maputl.h" | ||
52 | #include "p_map.h" | ||
53 | #include "g_game.h" | ||
54 | #include "p_inter.h" | ||
55 | #include "s_sound.h" | ||
56 | #include "sounds.h" | ||
57 | #include "m_bbox.h" // phares 3/20/98 | ||
58 | #include "d_deh.h" | ||
59 | #include "r_plane.h" | ||
60 | #include "lprintf.h" | ||
61 | |||
62 | // | ||
63 | // Animating textures and planes | ||
64 | // There is another anim_t used in wi_stuff, unrelated. | ||
65 | // | ||
66 | typedef struct | ||
67 | { | ||
68 | boolean istexture; | ||
69 | int picnum; | ||
70 | int basepic; | ||
71 | int numpics; | ||
72 | int speed; | ||
73 | |||
74 | } anim_t; | ||
75 | |||
76 | // | ||
77 | // source animation definition | ||
78 | // | ||
79 | // | ||
80 | #ifdef _MSC_VER // proff: This is the same as __attribute__ ((packed)) in GNUC | ||
81 | #pragma pack(push) | ||
82 | #pragma pack(1) | ||
83 | #endif //_MSC_VER | ||
84 | |||
85 | #if defined(__MWERKS__) | ||
86 | #pragma options align=packed | ||
87 | #endif | ||
88 | |||
89 | typedef struct | ||
90 | { | ||
91 | signed char istexture; //jff 3/23/98 make char for comparison // cph - make signed | ||
92 | char endname[9]; // if false, it is a flat | ||
93 | char startname[9]; | ||
94 | int speed; | ||
95 | } PACKEDATTR animdef_t; //jff 3/23/98 pack to read from memory | ||
96 | |||
97 | #if defined(__MWERKS__) | ||
98 | #pragma options align=reset | ||
99 | #endif | ||
100 | |||
101 | #ifdef _MSC_VER | ||
102 | #pragma pack(pop) | ||
103 | #endif //_MSC_VER | ||
104 | |||
105 | #define MAXANIMS 32 // no longer a strict limit -- killough | ||
106 | |||
107 | static anim_t* lastanim; | ||
108 | static anim_t* anims; // new structure w/o limits -- killough | ||
109 | static size_t maxanims; | ||
110 | |||
111 | // killough 3/7/98: Initialize generalized scrolling | ||
112 | static void P_SpawnScrollers(void); | ||
113 | |||
114 | static void P_SpawnFriction(void); // phares 3/16/98 | ||
115 | static void P_SpawnPushers(void); // phares 3/20/98 | ||
116 | |||
117 | // | ||
118 | // P_InitPicAnims | ||
119 | // | ||
120 | // Load the table of animation definitions, checking for existence of | ||
121 | // the start and end of each frame. If the start doesn't exist the sequence | ||
122 | // is skipped, if the last doesn't exist, BOOM exits. | ||
123 | // | ||
124 | // Wall/Flat animation sequences, defined by name of first and last frame, | ||
125 | // The full animation sequence is given using all lumps between the start | ||
126 | // and end entry, in the order found in the WAD file. | ||
127 | // | ||
128 | // This routine modified to read its data from a predefined lump or | ||
129 | // PWAD lump called ANIMATED rather than a static table in this module to | ||
130 | // allow wad designers to insert or modify animation sequences. | ||
131 | // | ||
132 | // Lump format is an array of byte packed animdef_t structures, terminated | ||
133 | // by a structure with istexture == -1. The lump can be generated from a | ||
134 | // text source file using SWANTBLS.EXE, distributed with the BOOM utils. | ||
135 | // The standard list of switches and animations is contained in the example | ||
136 | // source text file DEFSWANI.DAT also in the BOOM util distribution. | ||
137 | // | ||
138 | // | ||
139 | void P_InitPicAnims (void) | ||
140 | { | ||
141 | int i; | ||
142 | const animdef_t *animdefs; //jff 3/23/98 pointer to animation lump | ||
143 | int lump = W_GetNumForName("ANIMATED"); // cph - new wad lump handling | ||
144 | // Init animation | ||
145 | |||
146 | //jff 3/23/98 read from predefined or wad lump instead of table | ||
147 | animdefs = (const animdef_t *)W_CacheLumpNum(lump); | ||
148 | |||
149 | lastanim = anims; | ||
150 | for (i=0 ; animdefs[i].istexture != -1 ; i++) | ||
151 | { | ||
152 | // 1/11/98 killough -- removed limit by array-doubling | ||
153 | if (lastanim >= anims + maxanims) | ||
154 | { | ||
155 | size_t newmax = maxanims ? maxanims*2 : MAXANIMS; | ||
156 | anims = realloc(anims, newmax*sizeof(*anims)); // killough | ||
157 | lastanim = anims + maxanims; | ||
158 | maxanims = newmax; | ||
159 | } | ||
160 | |||
161 | if (animdefs[i].istexture) | ||
162 | { | ||
163 | // different episode ? | ||
164 | if (R_CheckTextureNumForName(animdefs[i].startname) == -1) | ||
165 | continue; | ||
166 | |||
167 | lastanim->picnum = R_TextureNumForName (animdefs[i].endname); | ||
168 | lastanim->basepic = R_TextureNumForName (animdefs[i].startname); | ||
169 | } | ||
170 | else | ||
171 | { | ||
172 | if ((W_CheckNumForName)(animdefs[i].startname, ns_flats) == -1) // killough 4/17/98 | ||
173 | continue; | ||
174 | |||
175 | lastanim->picnum = R_FlatNumForName (animdefs[i].endname); | ||
176 | lastanim->basepic = R_FlatNumForName (animdefs[i].startname); | ||
177 | } | ||
178 | |||
179 | lastanim->istexture = animdefs[i].istexture; | ||
180 | lastanim->numpics = lastanim->picnum - lastanim->basepic + 1; | ||
181 | |||
182 | if (lastanim->numpics < 2) | ||
183 | I_Error ("P_InitPicAnims: bad cycle from %s to %s", | ||
184 | animdefs[i].startname, | ||
185 | animdefs[i].endname); | ||
186 | |||
187 | lastanim->speed = LONG(animdefs[i].speed); // killough 5/5/98: add LONG() | ||
188 | lastanim++; | ||
189 | } | ||
190 | W_UnlockLumpNum(lump); | ||
191 | } | ||
192 | |||
193 | /////////////////////////////////////////////////////////////// | ||
194 | // | ||
195 | // Linedef and Sector Special Implementation Utility Functions | ||
196 | // | ||
197 | /////////////////////////////////////////////////////////////// | ||
198 | |||
199 | // | ||
200 | // getSide() | ||
201 | // | ||
202 | // Will return a side_t* | ||
203 | // given the number of the current sector, | ||
204 | // the line number, and the side (0/1) that you want. | ||
205 | // | ||
206 | // Note: if side=1 is specified, it must exist or results undefined | ||
207 | // | ||
208 | side_t* getSide | ||
209 | ( int currentSector, | ||
210 | int line, | ||
211 | int side ) | ||
212 | { | ||
213 | return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; | ||
214 | } | ||
215 | |||
216 | |||
217 | // | ||
218 | // getSector() | ||
219 | // | ||
220 | // Will return a sector_t* | ||
221 | // given the number of the current sector, | ||
222 | // the line number and the side (0/1) that you want. | ||
223 | // | ||
224 | // Note: if side=1 is specified, it must exist or results undefined | ||
225 | // | ||
226 | sector_t* getSector | ||
227 | ( int currentSector, | ||
228 | int line, | ||
229 | int side ) | ||
230 | { | ||
231 | return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; | ||
232 | } | ||
233 | |||
234 | |||
235 | // | ||
236 | // twoSided() | ||
237 | // | ||
238 | // Given the sector number and the line number, | ||
239 | // it will tell you whether the line is two-sided or not. | ||
240 | // | ||
241 | // modified to return actual two-sidedness rather than presence | ||
242 | // of 2S flag unless compatibility optioned | ||
243 | // | ||
244 | int twoSided | ||
245 | ( int sector, | ||
246 | int line ) | ||
247 | { | ||
248 | //jff 1/26/98 return what is actually needed, whether the line | ||
249 | //has two sidedefs, rather than whether the 2S flag is set | ||
250 | |||
251 | return comp[comp_model] ? | ||
252 | (sectors[sector].lines[line])->flags & ML_TWOSIDED | ||
253 | : | ||
254 | (sectors[sector].lines[line])->sidenum[1] != NO_INDEX; | ||
255 | } | ||
256 | |||
257 | |||
258 | // | ||
259 | // getNextSector() | ||
260 | // | ||
261 | // Return sector_t * of sector next to current across line. | ||
262 | // | ||
263 | // Note: returns NULL if not two-sided line, or both sides refer to sector | ||
264 | // | ||
265 | sector_t* getNextSector | ||
266 | ( line_t* line, | ||
267 | sector_t* sec ) | ||
268 | { | ||
269 | //jff 1/26/98 check unneeded since line->backsector already | ||
270 | //returns NULL if the line is not two sided, and does so from | ||
271 | //the actual two-sidedness of the line, rather than its 2S flag | ||
272 | |||
273 | if (comp[comp_model]) | ||
274 | { | ||
275 | if (!(line->flags & ML_TWOSIDED)) | ||
276 | return NULL; | ||
277 | } | ||
278 | |||
279 | if (line->frontsector == sec) { | ||
280 | if (comp[comp_model] || line->backsector!=sec) | ||
281 | return line->backsector; //jff 5/3/98 don't retn sec unless compatibility | ||
282 | else // fixes an intra-sector line breaking functions | ||
283 | return NULL; // like floor->highest floor | ||
284 | } | ||
285 | return line->frontsector; | ||
286 | } | ||
287 | |||
288 | |||
289 | // | ||
290 | // P_FindLowestFloorSurrounding() | ||
291 | // | ||
292 | // Returns the fixed point value of the lowest floor height | ||
293 | // in the sector passed or its surrounding sectors. | ||
294 | // | ||
295 | fixed_t P_FindLowestFloorSurrounding(sector_t* sec) | ||
296 | { | ||
297 | int i; | ||
298 | line_t* check; | ||
299 | sector_t* other; | ||
300 | fixed_t floor = sec->floorheight; | ||
301 | |||
302 | for (i=0 ;i < sec->linecount ; i++) | ||
303 | { | ||
304 | check = sec->lines[i]; | ||
305 | other = getNextSector(check,sec); | ||
306 | |||
307 | if (!other) | ||
308 | continue; | ||
309 | |||
310 | if (other->floorheight < floor) | ||
311 | floor = other->floorheight; | ||
312 | } | ||
313 | return floor; | ||
314 | } | ||
315 | |||
316 | |||
317 | // | ||
318 | // P_FindHighestFloorSurrounding() | ||
319 | // | ||
320 | // Passed a sector, returns the fixed point value of the largest | ||
321 | // floor height in the surrounding sectors, not including that passed | ||
322 | // | ||
323 | // NOTE: if no surrounding sector exists -32000*FRACUINT is returned | ||
324 | // if compatibility then -500*FRACUNIT is the smallest return possible | ||
325 | // | ||
326 | fixed_t P_FindHighestFloorSurrounding(sector_t *sec) | ||
327 | { | ||
328 | int i; | ||
329 | line_t* check; | ||
330 | sector_t* other; | ||
331 | fixed_t floor = -500*FRACUNIT; | ||
332 | |||
333 | //jff 1/26/98 Fix initial value for floor to not act differently | ||
334 | //in sections of wad that are below -500 units | ||
335 | if (!comp[comp_model]) /* jff 3/12/98 avoid ovf */ | ||
336 | floor = -32000*FRACUNIT; // in height calculations | ||
337 | |||
338 | for (i=0 ;i < sec->linecount ; i++) | ||
339 | { | ||
340 | check = sec->lines[i]; | ||
341 | other = getNextSector(check,sec); | ||
342 | |||
343 | if (!other) | ||
344 | continue; | ||
345 | |||
346 | if (other->floorheight > floor) | ||
347 | floor = other->floorheight; | ||
348 | } | ||
349 | return floor; | ||
350 | } | ||
351 | |||
352 | |||
353 | // | ||
354 | // P_FindNextHighestFloor() | ||
355 | // | ||
356 | // Passed a sector and a floor height, returns the fixed point value | ||
357 | // of the smallest floor height in a surrounding sector larger than | ||
358 | // the floor height passed. If no such height exists the floorheight | ||
359 | // passed is returned. | ||
360 | // | ||
361 | // Rewritten by Lee Killough to avoid fixed array and to be faster | ||
362 | // | ||
363 | fixed_t P_FindNextHighestFloor(sector_t *sec, int currentheight) | ||
364 | { | ||
365 | sector_t *other; | ||
366 | int i; | ||
367 | |||
368 | for (i=0 ;i < sec->linecount ; i++) | ||
369 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
370 | other->floorheight > currentheight) | ||
371 | { | ||
372 | int height = other->floorheight; | ||
373 | while (++i < sec->linecount) | ||
374 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
375 | other->floorheight < height && | ||
376 | other->floorheight > currentheight) | ||
377 | height = other->floorheight; | ||
378 | return height; | ||
379 | } | ||
380 | /* cph - my guess at doom v1.2 - 1.4beta compatibility here. | ||
381 | * If there are no higher neighbouring sectors, Heretic just returned | ||
382 | * heightlist[0] (local variable), i.e. noise off the stack. 0 is right for | ||
383 | * RETURN01 E1M2, so let's take that. */ | ||
384 | return (compatibility_level < doom_1666_compatibility ? 0 : currentheight); | ||
385 | } | ||
386 | |||
387 | |||
388 | // | ||
389 | // P_FindNextLowestFloor() | ||
390 | // | ||
391 | // Passed a sector and a floor height, returns the fixed point value | ||
392 | // of the largest floor height in a surrounding sector smaller than | ||
393 | // the floor height passed. If no such height exists the floorheight | ||
394 | // passed is returned. | ||
395 | // | ||
396 | // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this | ||
397 | // | ||
398 | fixed_t P_FindNextLowestFloor(sector_t *sec, int currentheight) | ||
399 | { | ||
400 | sector_t *other; | ||
401 | int i; | ||
402 | |||
403 | for (i=0 ;i < sec->linecount ; i++) | ||
404 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
405 | other->floorheight < currentheight) | ||
406 | { | ||
407 | int height = other->floorheight; | ||
408 | while (++i < sec->linecount) | ||
409 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
410 | other->floorheight > height && | ||
411 | other->floorheight < currentheight) | ||
412 | height = other->floorheight; | ||
413 | return height; | ||
414 | } | ||
415 | return currentheight; | ||
416 | } | ||
417 | |||
418 | |||
419 | // | ||
420 | // P_FindNextLowestCeiling() | ||
421 | // | ||
422 | // Passed a sector and a ceiling height, returns the fixed point value | ||
423 | // of the largest ceiling height in a surrounding sector smaller than | ||
424 | // the ceiling height passed. If no such height exists the ceiling height | ||
425 | // passed is returned. | ||
426 | // | ||
427 | // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this | ||
428 | // | ||
429 | fixed_t P_FindNextLowestCeiling(sector_t *sec, int currentheight) | ||
430 | { | ||
431 | sector_t *other; | ||
432 | int i; | ||
433 | |||
434 | for (i=0 ;i < sec->linecount ; i++) | ||
435 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
436 | other->ceilingheight < currentheight) | ||
437 | { | ||
438 | int height = other->ceilingheight; | ||
439 | while (++i < sec->linecount) | ||
440 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
441 | other->ceilingheight > height && | ||
442 | other->ceilingheight < currentheight) | ||
443 | height = other->ceilingheight; | ||
444 | return height; | ||
445 | } | ||
446 | return currentheight; | ||
447 | } | ||
448 | |||
449 | |||
450 | // | ||
451 | // P_FindNextHighestCeiling() | ||
452 | // | ||
453 | // Passed a sector and a ceiling height, returns the fixed point value | ||
454 | // of the smallest ceiling height in a surrounding sector larger than | ||
455 | // the ceiling height passed. If no such height exists the ceiling height | ||
456 | // passed is returned. | ||
457 | // | ||
458 | // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this | ||
459 | // | ||
460 | fixed_t P_FindNextHighestCeiling(sector_t *sec, int currentheight) | ||
461 | { | ||
462 | sector_t *other; | ||
463 | int i; | ||
464 | |||
465 | for (i=0 ;i < sec->linecount ; i++) | ||
466 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
467 | other->ceilingheight > currentheight) | ||
468 | { | ||
469 | int height = other->ceilingheight; | ||
470 | while (++i < sec->linecount) | ||
471 | if ((other = getNextSector(sec->lines[i],sec)) && | ||
472 | other->ceilingheight < height && | ||
473 | other->ceilingheight > currentheight) | ||
474 | height = other->ceilingheight; | ||
475 | return height; | ||
476 | } | ||
477 | return currentheight; | ||
478 | } | ||
479 | |||
480 | |||
481 | // | ||
482 | // P_FindLowestCeilingSurrounding() | ||
483 | // | ||
484 | // Passed a sector, returns the fixed point value of the smallest | ||
485 | // ceiling height in the surrounding sectors, not including that passed | ||
486 | // | ||
487 | // NOTE: if no surrounding sector exists 32000*FRACUINT is returned | ||
488 | // but if compatibility then INT_MAX is the return | ||
489 | // | ||
490 | fixed_t P_FindLowestCeilingSurrounding(sector_t* sec) | ||
491 | { | ||
492 | int i; | ||
493 | line_t* check; | ||
494 | sector_t* other; | ||
495 | fixed_t height = INT_MAX; | ||
496 | |||
497 | /* jff 3/12/98 avoid ovf in height calculations */ | ||
498 | if (!comp[comp_model]) height = 32000*FRACUNIT; | ||
499 | |||
500 | for (i=0 ;i < sec->linecount ; i++) | ||
501 | { | ||
502 | check = sec->lines[i]; | ||
503 | other = getNextSector(check,sec); | ||
504 | |||
505 | if (!other) | ||
506 | continue; | ||
507 | |||
508 | if (other->ceilingheight < height) | ||
509 | height = other->ceilingheight; | ||
510 | } | ||
511 | return height; | ||
512 | } | ||
513 | |||
514 | |||
515 | // | ||
516 | // P_FindHighestCeilingSurrounding() | ||
517 | // | ||
518 | // Passed a sector, returns the fixed point value of the largest | ||
519 | // ceiling height in the surrounding sectors, not including that passed | ||
520 | // | ||
521 | // NOTE: if no surrounding sector exists -32000*FRACUINT is returned | ||
522 | // but if compatibility then 0 is the smallest return possible | ||
523 | // | ||
524 | fixed_t P_FindHighestCeilingSurrounding(sector_t* sec) | ||
525 | { | ||
526 | int i; | ||
527 | line_t* check; | ||
528 | sector_t* other; | ||
529 | fixed_t height = 0; | ||
530 | |||
531 | /* jff 1/26/98 Fix initial value for floor to not act differently | ||
532 | * in sections of wad that are below 0 units | ||
533 | * jff 3/12/98 avoid ovf in height calculations */ | ||
534 | if (!comp[comp_model]) height = -32000*FRACUNIT; | ||
535 | |||
536 | for (i=0 ;i < sec->linecount ; i++) | ||
537 | { | ||
538 | check = sec->lines[i]; | ||
539 | other = getNextSector(check,sec); | ||
540 | |||
541 | if (!other) | ||
542 | continue; | ||
543 | |||
544 | if (other->ceilingheight > height) | ||
545 | height = other->ceilingheight; | ||
546 | } | ||
547 | return height; | ||
548 | } | ||
549 | |||
550 | |||
551 | // | ||
552 | // P_FindShortestTextureAround() | ||
553 | // | ||
554 | // Passed a sector number, returns the shortest lower texture on a | ||
555 | // linedef bounding the sector. | ||
556 | // | ||
557 | // Note: If no lower texture exists 32000*FRACUNIT is returned. | ||
558 | // but if compatibility then INT_MAX is returned | ||
559 | // | ||
560 | // jff 02/03/98 Add routine to find shortest lower texture | ||
561 | // | ||
562 | fixed_t P_FindShortestTextureAround(int secnum) | ||
563 | { | ||
564 | int minsize = INT_MAX; | ||
565 | side_t* side; | ||
566 | int i; | ||
567 | sector_t *sec = §ors[secnum]; | ||
568 | |||
569 | if (!comp[comp_model]) | ||
570 | minsize = 32000<<FRACBITS; //jff 3/13/98 prevent overflow in height calcs | ||
571 | |||
572 | for (i = 0; i < sec->linecount; i++) | ||
573 | { | ||
574 | if (twoSided(secnum, i)) | ||
575 | { | ||
576 | side = getSide(secnum,i,0); | ||
577 | if (side->bottomtexture > 0) //jff 8/14/98 texture 0 is a placeholder | ||
578 | if (textureheight[side->bottomtexture] < minsize) | ||
579 | minsize = textureheight[side->bottomtexture]; | ||
580 | side = getSide(secnum,i,1); | ||
581 | if (side->bottomtexture > 0) //jff 8/14/98 texture 0 is a placeholder | ||
582 | if (textureheight[side->bottomtexture] < minsize) | ||
583 | minsize = textureheight[side->bottomtexture]; | ||
584 | } | ||
585 | } | ||
586 | return minsize; | ||
587 | } | ||
588 | |||
589 | |||
590 | // | ||
591 | // P_FindShortestUpperAround() | ||
592 | // | ||
593 | // Passed a sector number, returns the shortest upper texture on a | ||
594 | // linedef bounding the sector. | ||
595 | // | ||
596 | // Note: If no upper texture exists 32000*FRACUNIT is returned. | ||
597 | // but if compatibility then INT_MAX is returned | ||
598 | // | ||
599 | // jff 03/20/98 Add routine to find shortest upper texture | ||
600 | // | ||
601 | fixed_t P_FindShortestUpperAround(int secnum) | ||
602 | { | ||
603 | int minsize = INT_MAX; | ||
604 | side_t* side; | ||
605 | int i; | ||
606 | sector_t *sec = §ors[secnum]; | ||
607 | |||
608 | if (!comp[comp_model]) | ||
609 | minsize = 32000<<FRACBITS; //jff 3/13/98 prevent overflow | ||
610 | // in height calcs | ||
611 | for (i = 0; i < sec->linecount; i++) | ||
612 | { | ||
613 | if (twoSided(secnum, i)) | ||
614 | { | ||
615 | side = getSide(secnum,i,0); | ||
616 | if (side->toptexture > 0) //jff 8/14/98 texture 0 is a placeholder | ||
617 | if (textureheight[side->toptexture] < minsize) | ||
618 | minsize = textureheight[side->toptexture]; | ||
619 | side = getSide(secnum,i,1); | ||
620 | if (side->toptexture > 0) //jff 8/14/98 texture 0 is a placeholder | ||
621 | if (textureheight[side->toptexture] < minsize) | ||
622 | minsize = textureheight[side->toptexture]; | ||
623 | } | ||
624 | } | ||
625 | return minsize; | ||
626 | } | ||
627 | |||
628 | |||
629 | // | ||
630 | // P_FindModelFloorSector() | ||
631 | // | ||
632 | // Passed a floor height and a sector number, return a pointer to a | ||
633 | // a sector with that floor height across the lowest numbered two sided | ||
634 | // line surrounding the sector. | ||
635 | // | ||
636 | // Note: If no sector at that height bounds the sector passed, return NULL | ||
637 | // | ||
638 | // jff 02/03/98 Add routine to find numeric model floor | ||
639 | // around a sector specified by sector number | ||
640 | // jff 3/14/98 change first parameter to plain height to allow call | ||
641 | // from routine not using floormove_t | ||
642 | // | ||
643 | sector_t *P_FindModelFloorSector(fixed_t floordestheight,int secnum) | ||
644 | { | ||
645 | int i; | ||
646 | sector_t *sec=NULL; | ||
647 | int linecount; | ||
648 | |||
649 | sec = §ors[secnum]; //jff 3/2/98 woops! better do this | ||
650 | //jff 5/23/98 don't disturb sec->linecount while searching | ||
651 | // but allow early exit in old demos | ||
652 | linecount = sec->linecount; | ||
653 | for (i = 0; i < (demo_compatibility && sec->linecount<linecount? | ||
654 | sec->linecount : linecount); i++) | ||
655 | { | ||
656 | if ( twoSided(secnum, i) ) | ||
657 | { | ||
658 | if (getSide(secnum,i,0)->sector-sectors == secnum) | ||
659 | sec = getSector(secnum,i,1); | ||
660 | else | ||
661 | sec = getSector(secnum,i,0); | ||
662 | |||
663 | if (sec->floorheight == floordestheight) | ||
664 | return sec; | ||
665 | } | ||
666 | } | ||
667 | return NULL; | ||
668 | } | ||
669 | |||
670 | |||
671 | // | ||
672 | // P_FindModelCeilingSector() | ||
673 | // | ||
674 | // Passed a ceiling height and a sector number, return a pointer to a | ||
675 | // a sector with that ceiling height across the lowest numbered two sided | ||
676 | // line surrounding the sector. | ||
677 | // | ||
678 | // Note: If no sector at that height bounds the sector passed, return NULL | ||
679 | // | ||
680 | // jff 02/03/98 Add routine to find numeric model ceiling | ||
681 | // around a sector specified by sector number | ||
682 | // used only from generalized ceiling types | ||
683 | // jff 3/14/98 change first parameter to plain height to allow call | ||
684 | // from routine not using ceiling_t | ||
685 | // | ||
686 | sector_t *P_FindModelCeilingSector(fixed_t ceildestheight,int secnum) | ||
687 | { | ||
688 | int i; | ||
689 | sector_t *sec=NULL; | ||
690 | int linecount; | ||
691 | |||
692 | sec = §ors[secnum]; //jff 3/2/98 woops! better do this | ||
693 | //jff 5/23/98 don't disturb sec->linecount while searching | ||
694 | // but allow early exit in old demos | ||
695 | linecount = sec->linecount; | ||
696 | for (i = 0; i < (demo_compatibility && sec->linecount<linecount? | ||
697 | sec->linecount : linecount); i++) | ||
698 | { | ||
699 | if ( twoSided(secnum, i) ) | ||
700 | { | ||
701 | if (getSide(secnum,i,0)->sector-sectors == secnum) | ||
702 | sec = getSector(secnum,i,1); | ||
703 | else | ||
704 | sec = getSector(secnum,i,0); | ||
705 | |||
706 | if (sec->ceilingheight == ceildestheight) | ||
707 | return sec; | ||
708 | } | ||
709 | } | ||
710 | return NULL; | ||
711 | } | ||
712 | |||
713 | // | ||
714 | // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO | ||
715 | // | ||
716 | |||
717 | // Find the next sector with the same tag as a linedef. | ||
718 | // Rewritten by Lee Killough to use chained hashing to improve speed | ||
719 | |||
720 | int P_FindSectorFromLineTag(const line_t *line, int start) | ||
721 | { | ||
722 | start = start >= 0 ? sectors[start].nexttag : | ||
723 | sectors[(unsigned) line->tag % (unsigned) numsectors].firsttag; | ||
724 | while (start >= 0 && sectors[start].tag != line->tag) | ||
725 | start = sectors[start].nexttag; | ||
726 | return start; | ||
727 | } | ||
728 | |||
729 | // killough 4/16/98: Same thing, only for linedefs | ||
730 | |||
731 | int P_FindLineFromLineTag(const line_t *line, int start) | ||
732 | { | ||
733 | start = start >= 0 ? lines[start].nexttag : | ||
734 | lines[(unsigned) line->tag % (unsigned) numlines].firsttag; | ||
735 | while (start >= 0 && lines[start].tag != line->tag) | ||
736 | start = lines[start].nexttag; | ||
737 | return start; | ||
738 | } | ||
739 | |||
740 | // Hash the sector tags across the sectors and linedefs. | ||
741 | static void P_InitTagLists(void) | ||
742 | { | ||
743 | register int i; | ||
744 | |||
745 | for (i=numsectors; --i>=0; ) // Initially make all slots empty. | ||
746 | sectors[i].firsttag = -1; | ||
747 | for (i=numsectors; --i>=0; ) // Proceed from last to first sector | ||
748 | { // so that lower sectors appear first | ||
749 | int j = (unsigned) sectors[i].tag % (unsigned) numsectors; // Hash func | ||
750 | sectors[i].nexttag = sectors[j].firsttag; // Prepend sector to chain | ||
751 | sectors[j].firsttag = i; | ||
752 | } | ||
753 | |||
754 | // killough 4/17/98: same thing, only for linedefs | ||
755 | |||
756 | for (i=numlines; --i>=0; ) // Initially make all slots empty. | ||
757 | lines[i].firsttag = -1; | ||
758 | for (i=numlines; --i>=0; ) // Proceed from last to first linedef | ||
759 | { // so that lower linedefs appear first | ||
760 | int j = (unsigned) lines[i].tag % (unsigned) numlines; // Hash func | ||
761 | lines[i].nexttag = lines[j].firsttag; // Prepend linedef to chain | ||
762 | lines[j].firsttag = i; | ||
763 | } | ||
764 | } | ||
765 | |||
766 | // | ||
767 | // P_FindMinSurroundingLight() | ||
768 | // | ||
769 | // Passed a sector and a light level, returns the smallest light level | ||
770 | // in a surrounding sector less than that passed. If no smaller light | ||
771 | // level exists, the light level passed is returned. | ||
772 | // | ||
773 | int P_FindMinSurroundingLight | ||
774 | ( sector_t* sector, | ||
775 | int max ) | ||
776 | { | ||
777 | int i; | ||
778 | int min; | ||
779 | line_t* line; | ||
780 | sector_t* check; | ||
781 | |||
782 | min = max; | ||
783 | for (i=0 ; i < sector->linecount ; i++) | ||
784 | { | ||
785 | line = sector->lines[i]; | ||
786 | check = getNextSector(line,sector); | ||
787 | |||
788 | if (!check) | ||
789 | continue; | ||
790 | |||
791 | if (check->lightlevel < min) | ||
792 | min = check->lightlevel; | ||
793 | } | ||
794 | return min; | ||
795 | } | ||
796 | |||
797 | |||
798 | // | ||
799 | // P_CanUnlockGenDoor() | ||
800 | // | ||
801 | // Passed a generalized locked door linedef and a player, returns whether | ||
802 | // the player has the keys necessary to unlock that door. | ||
803 | // | ||
804 | // Note: The linedef passed MUST be a generalized locked door type | ||
805 | // or results are undefined. | ||
806 | // | ||
807 | // jff 02/05/98 routine added to test for unlockability of | ||
808 | // generalized locked doors | ||
809 | // | ||
810 | boolean P_CanUnlockGenDoor | ||
811 | ( line_t* line, | ||
812 | player_t* player) | ||
813 | { | ||
814 | // does this line special distinguish between skulls and keys? | ||
815 | int skulliscard = (line->special & LockedNKeys)>>LockedNKeysShift; | ||
816 | |||
817 | // determine for each case of lock type if player's keys are adequate | ||
818 | switch((line->special & LockedKey)>>LockedKeyShift) | ||
819 | { | ||
820 | case AnyKey: | ||
821 | if | ||
822 | ( | ||
823 | !player->cards[it_redcard] && | ||
824 | !player->cards[it_redskull] && | ||
825 | !player->cards[it_bluecard] && | ||
826 | !player->cards[it_blueskull] && | ||
827 | !player->cards[it_yellowcard] && | ||
828 | !player->cards[it_yellowskull] | ||
829 | ) | ||
830 | { | ||
831 | player->message = s_PD_ANY; // Ty 03/27/98 - externalized | ||
832 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
833 | return false; | ||
834 | } | ||
835 | break; | ||
836 | case RCard: | ||
837 | if | ||
838 | ( | ||
839 | !player->cards[it_redcard] && | ||
840 | (!skulliscard || !player->cards[it_redskull]) | ||
841 | ) | ||
842 | { | ||
843 | player->message = skulliscard? s_PD_REDK : s_PD_REDC; // Ty 03/27/98 - externalized | ||
844 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
845 | return false; | ||
846 | } | ||
847 | break; | ||
848 | case BCard: | ||
849 | if | ||
850 | ( | ||
851 | !player->cards[it_bluecard] && | ||
852 | (!skulliscard || !player->cards[it_blueskull]) | ||
853 | ) | ||
854 | { | ||
855 | player->message = skulliscard? s_PD_BLUEK : s_PD_BLUEC; // Ty 03/27/98 - externalized | ||
856 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
857 | return false; | ||
858 | } | ||
859 | break; | ||
860 | case YCard: | ||
861 | if | ||
862 | ( | ||
863 | !player->cards[it_yellowcard] && | ||
864 | (!skulliscard || !player->cards[it_yellowskull]) | ||
865 | ) | ||
866 | { | ||
867 | player->message = skulliscard? s_PD_YELLOWK : s_PD_YELLOWC; // Ty 03/27/98 - externalized | ||
868 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
869 | return false; | ||
870 | } | ||
871 | break; | ||
872 | case RSkull: | ||
873 | if | ||
874 | ( | ||
875 | !player->cards[it_redskull] && | ||
876 | (!skulliscard || !player->cards[it_redcard]) | ||
877 | ) | ||
878 | { | ||
879 | player->message = skulliscard? s_PD_REDK : s_PD_REDS; // Ty 03/27/98 - externalized | ||
880 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
881 | return false; | ||
882 | } | ||
883 | break; | ||
884 | case BSkull: | ||
885 | if | ||
886 | ( | ||
887 | !player->cards[it_blueskull] && | ||
888 | (!skulliscard || !player->cards[it_bluecard]) | ||
889 | ) | ||
890 | { | ||
891 | player->message = skulliscard? s_PD_BLUEK : s_PD_BLUES; // Ty 03/27/98 - externalized | ||
892 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
893 | return false; | ||
894 | } | ||
895 | break; | ||
896 | case YSkull: | ||
897 | if | ||
898 | ( | ||
899 | !player->cards[it_yellowskull] && | ||
900 | (!skulliscard || !player->cards[it_yellowcard]) | ||
901 | ) | ||
902 | { | ||
903 | player->message = skulliscard? s_PD_YELLOWK : s_PD_YELLOWS; // Ty 03/27/98 - externalized | ||
904 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
905 | return false; | ||
906 | } | ||
907 | break; | ||
908 | case AllKeys: | ||
909 | if | ||
910 | ( | ||
911 | !skulliscard && | ||
912 | ( | ||
913 | !player->cards[it_redcard] || | ||
914 | !player->cards[it_redskull] || | ||
915 | !player->cards[it_bluecard] || | ||
916 | !player->cards[it_blueskull] || | ||
917 | !player->cards[it_yellowcard] || | ||
918 | !player->cards[it_yellowskull] | ||
919 | ) | ||
920 | ) | ||
921 | { | ||
922 | player->message = s_PD_ALL6; // Ty 03/27/98 - externalized | ||
923 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
924 | return false; | ||
925 | } | ||
926 | if | ||
927 | ( | ||
928 | skulliscard && | ||
929 | ( | ||
930 | (!player->cards[it_redcard] && | ||
931 | !player->cards[it_redskull]) || | ||
932 | (!player->cards[it_bluecard] && | ||
933 | !player->cards[it_blueskull]) || | ||
934 | (!player->cards[it_yellowcard] && | ||
935 | !player->cards[it_yellowskull]) | ||
936 | ) | ||
937 | ) | ||
938 | { | ||
939 | player->message = s_PD_ALL3; // Ty 03/27/98 - externalized | ||
940 | S_StartSound(player->mo,sfx_oof); // killough 3/20/98 | ||
941 | return false; | ||
942 | } | ||
943 | break; | ||
944 | } | ||
945 | return true; | ||
946 | } | ||
947 | |||
948 | |||
949 | // | ||
950 | // P_SectorActive() | ||
951 | // | ||
952 | // Passed a linedef special class (floor, ceiling, lighting) and a sector | ||
953 | // returns whether the sector is already busy with a linedef special of the | ||
954 | // same class. If old demo compatibility true, all linedef special classes | ||
955 | // are the same. | ||
956 | // | ||
957 | // jff 2/23/98 added to prevent old demos from | ||
958 | // succeeding in starting multiple specials on one sector | ||
959 | // | ||
960 | boolean PUREFUNC P_SectorActive(special_e t, const sector_t *sec) | ||
961 | { | ||
962 | if (demo_compatibility) // return whether any thinker is active | ||
963 | return sec->floordata != NULL || sec->ceilingdata != NULL || sec->lightingdata != NULL; | ||
964 | else | ||
965 | switch (t) // return whether thinker of same type is active | ||
966 | { | ||
967 | case floor_special: | ||
968 | return sec->floordata != NULL; | ||
969 | case ceiling_special: | ||
970 | return sec->ceilingdata != NULL; | ||
971 | case lighting_special: | ||
972 | return sec->lightingdata != NULL; | ||
973 | } | ||
974 | return true; // don't know which special, must be active, shouldn't be here | ||
975 | } | ||
976 | |||
977 | |||
978 | // | ||
979 | // P_CheckTag() | ||
980 | // | ||
981 | // Passed a line, returns true if the tag is non-zero or the line special | ||
982 | // allows no tag without harm. If compatibility, all linedef specials are | ||
983 | // allowed to have zero tag. | ||
984 | // | ||
985 | // Note: Only line specials activated by walkover, pushing, or shooting are | ||
986 | // checked by this routine. | ||
987 | // | ||
988 | // jff 2/27/98 Added to check for zero tag allowed for regular special types | ||
989 | // | ||
990 | int P_CheckTag(line_t *line) | ||
991 | { | ||
992 | /* tag not zero, allowed, or | ||
993 | * killough 11/98: compatibility option */ | ||
994 | if (comp[comp_zerotags] || line->tag) | ||
995 | return 1; | ||
996 | |||
997 | switch(line->special) | ||
998 | { | ||
999 | case 1: // Manual door specials | ||
1000 | case 26: | ||
1001 | case 27: | ||
1002 | case 28: | ||
1003 | case 31: | ||
1004 | case 32: | ||
1005 | case 33: | ||
1006 | case 34: | ||
1007 | case 117: | ||
1008 | case 118: | ||
1009 | |||
1010 | case 139: // Lighting specials | ||
1011 | case 170: | ||
1012 | case 79: | ||
1013 | case 35: | ||
1014 | case 138: | ||
1015 | case 171: | ||
1016 | case 81: | ||
1017 | case 13: | ||
1018 | case 192: | ||
1019 | case 169: | ||
1020 | case 80: | ||
1021 | case 12: | ||
1022 | case 194: | ||
1023 | case 173: | ||
1024 | case 157: | ||
1025 | case 104: | ||
1026 | case 193: | ||
1027 | case 172: | ||
1028 | case 156: | ||
1029 | case 17: | ||
1030 | |||
1031 | case 195: // Thing teleporters | ||
1032 | case 174: | ||
1033 | case 97: | ||
1034 | case 39: | ||
1035 | case 126: | ||
1036 | case 125: | ||
1037 | case 210: | ||
1038 | case 209: | ||
1039 | case 208: | ||
1040 | case 207: | ||
1041 | |||
1042 | case 11: // Exits | ||
1043 | case 52: | ||
1044 | case 197: | ||
1045 | case 51: | ||
1046 | case 124: | ||
1047 | case 198: | ||
1048 | |||
1049 | case 48: // Scrolling walls | ||
1050 | case 85: | ||
1051 | return 1; // zero tag allowed | ||
1052 | |||
1053 | default: | ||
1054 | break; | ||
1055 | } | ||
1056 | return 0; // zero tag not allowed | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | // | ||
1061 | // P_IsSecret() | ||
1062 | // | ||
1063 | // Passed a sector, returns if the sector secret type is still active, i.e. | ||
1064 | // secret type is set and the secret has not yet been obtained. | ||
1065 | // | ||
1066 | // jff 3/14/98 added to simplify checks for whether sector is secret | ||
1067 | // in automap and other places | ||
1068 | // | ||
1069 | boolean PUREFUNC P_IsSecret(const sector_t *sec) | ||
1070 | { | ||
1071 | return (sec->special==9 || (sec->special&SECRET_MASK)); | ||
1072 | } | ||
1073 | |||
1074 | |||
1075 | // | ||
1076 | // P_WasSecret() | ||
1077 | // | ||
1078 | // Passed a sector, returns if the sector secret type is was active, i.e. | ||
1079 | // secret type was set and the secret has been obtained already. | ||
1080 | // | ||
1081 | // jff 3/14/98 added to simplify checks for whether sector is secret | ||
1082 | // in automap and other places | ||
1083 | // | ||
1084 | boolean PUREFUNC P_WasSecret(const sector_t *sec) | ||
1085 | { | ||
1086 | return (sec->oldspecial==9 || (sec->oldspecial&SECRET_MASK)); | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | ////////////////////////////////////////////////////////////////////////// | ||
1091 | // | ||
1092 | // Events | ||
1093 | // | ||
1094 | // Events are operations triggered by using, crossing, | ||
1095 | // or shooting special lines, or by timed thinkers. | ||
1096 | // | ||
1097 | ///////////////////////////////////////////////////////////////////////// | ||
1098 | |||
1099 | // | ||
1100 | // P_CrossSpecialLine - Walkover Trigger Dispatcher | ||
1101 | // | ||
1102 | // Called every time a thing origin is about | ||
1103 | // to cross a line with a non 0 special, whether a walkover type or not. | ||
1104 | // | ||
1105 | // jff 02/12/98 all W1 lines were fixed to check the result from the EV_ | ||
1106 | // function before clearing the special. This avoids losing the function | ||
1107 | // of the line, should the sector already be active when the line is | ||
1108 | // crossed. Change is qualified by demo_compatibility. | ||
1109 | // | ||
1110 | // CPhipps - take a line_t pointer instead of a line number, as in MBF | ||
1111 | void P_CrossSpecialLine(line_t *line, int side, mobj_t *thing) | ||
1112 | { | ||
1113 | int ok; | ||
1114 | |||
1115 | // Things that should never trigger lines | ||
1116 | if (!thing->player) | ||
1117 | { | ||
1118 | // Things that should NOT trigger specials... | ||
1119 | switch(thing->type) | ||
1120 | { | ||
1121 | case MT_ROCKET: | ||
1122 | case MT_PLASMA: | ||
1123 | case MT_BFG: | ||
1124 | case MT_TROOPSHOT: | ||
1125 | case MT_HEADSHOT: | ||
1126 | case MT_BRUISERSHOT: | ||
1127 | return; | ||
1128 | break; | ||
1129 | |||
1130 | default: break; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | //jff 02/04/98 add check here for generalized lindef types | ||
1135 | if (!demo_compatibility) // generalized types not recognized if old demo | ||
1136 | { | ||
1137 | // pointer to line function is NULL by default, set non-null if | ||
1138 | // line special is walkover generalized linedef type | ||
1139 | int (*linefunc)(line_t *line)=NULL; | ||
1140 | |||
1141 | // check each range of generalized linedefs | ||
1142 | if ((unsigned)line->special >= GenEnd) | ||
1143 | { | ||
1144 | // Out of range for GenFloors | ||
1145 | } | ||
1146 | else if ((unsigned)line->special >= GenFloorBase) | ||
1147 | { | ||
1148 | if (!thing->player) | ||
1149 | if ((line->special & FloorChange) || !(line->special & FloorModel)) | ||
1150 | return; // FloorModel is "Allow Monsters" if FloorChange is 0 | ||
1151 | if (!line->tag) //jff 2/27/98 all walk generalized types require tag | ||
1152 | return; | ||
1153 | linefunc = EV_DoGenFloor; | ||
1154 | } | ||
1155 | else if ((unsigned)line->special >= GenCeilingBase) | ||
1156 | { | ||
1157 | if (!thing->player) | ||
1158 | if ((line->special & CeilingChange) || !(line->special & CeilingModel)) | ||
1159 | return; // CeilingModel is "Allow Monsters" if CeilingChange is 0 | ||
1160 | if (!line->tag) //jff 2/27/98 all walk generalized types require tag | ||
1161 | return; | ||
1162 | linefunc = EV_DoGenCeiling; | ||
1163 | } | ||
1164 | else if ((unsigned)line->special >= GenDoorBase) | ||
1165 | { | ||
1166 | if (!thing->player) | ||
1167 | { | ||
1168 | if (!(line->special & DoorMonster)) | ||
1169 | return; // monsters disallowed from this door | ||
1170 | if (line->flags & ML_SECRET) // they can't open secret doors either | ||
1171 | return; | ||
1172 | } | ||
1173 | if (!line->tag) //3/2/98 move outside the monster check | ||
1174 | return; | ||
1175 | linefunc = EV_DoGenDoor; | ||
1176 | } | ||
1177 | else if ((unsigned)line->special >= GenLockedBase) | ||
1178 | { | ||
1179 | if (!thing->player) | ||
1180 | return; // monsters disallowed from unlocking doors | ||
1181 | if (((line->special&TriggerType)==WalkOnce) || ((line->special&TriggerType)==WalkMany)) | ||
1182 | { //jff 4/1/98 check for being a walk type before reporting door type | ||
1183 | if (!P_CanUnlockGenDoor(line,thing->player)) | ||
1184 | return; | ||
1185 | } | ||
1186 | else | ||
1187 | return; | ||
1188 | linefunc = EV_DoGenLockedDoor; | ||
1189 | } | ||
1190 | else if ((unsigned)line->special >= GenLiftBase) | ||
1191 | { | ||
1192 | if (!thing->player) | ||
1193 | if (!(line->special & LiftMonster)) | ||
1194 | return; // monsters disallowed | ||
1195 | if (!line->tag) //jff 2/27/98 all walk generalized types require tag | ||
1196 | return; | ||
1197 | linefunc = EV_DoGenLift; | ||
1198 | } | ||
1199 | else if ((unsigned)line->special >= GenStairsBase) | ||
1200 | { | ||
1201 | if (!thing->player) | ||
1202 | if (!(line->special & StairMonster)) | ||
1203 | return; // monsters disallowed | ||
1204 | if (!line->tag) //jff 2/27/98 all walk generalized types require tag | ||
1205 | return; | ||
1206 | linefunc = EV_DoGenStairs; | ||
1207 | } | ||
1208 | |||
1209 | if (linefunc) // if it was a valid generalized type | ||
1210 | switch((line->special & TriggerType) >> TriggerTypeShift) | ||
1211 | { | ||
1212 | case WalkOnce: | ||
1213 | if (linefunc(line)) | ||
1214 | line->special = 0; // clear special if a walk once type | ||
1215 | return; | ||
1216 | case WalkMany: | ||
1217 | linefunc(line); | ||
1218 | return; | ||
1219 | default: // if not a walk type, do nothing here | ||
1220 | return; | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | if (!thing->player) | ||
1225 | { | ||
1226 | ok = 0; | ||
1227 | switch(line->special) | ||
1228 | { | ||
1229 | case 39: // teleport trigger | ||
1230 | case 97: // teleport retrigger | ||
1231 | case 125: // teleport monsteronly trigger | ||
1232 | case 126: // teleport monsteronly retrigger | ||
1233 | case 4: // raise door | ||
1234 | case 10: // plat down-wait-up-stay trigger | ||
1235 | case 88: // plat down-wait-up-stay retrigger | ||
1236 | //jff 3/5/98 add ability of monsters etc. to use teleporters | ||
1237 | case 208: //silent thing teleporters | ||
1238 | case 207: | ||
1239 | case 243: //silent line-line teleporter | ||
1240 | case 244: //jff 3/6/98 make fit within DCK's 256 linedef types | ||
1241 | case 262: //jff 4/14/98 add monster only | ||
1242 | case 263: //jff 4/14/98 silent thing,line,line rev types | ||
1243 | case 264: //jff 4/14/98 plus player/monster silent line | ||
1244 | case 265: // reversed types | ||
1245 | case 266: | ||
1246 | case 267: | ||
1247 | case 268: | ||
1248 | case 269: | ||
1249 | ok = 1; | ||
1250 | break; | ||
1251 | } | ||
1252 | if (!ok) | ||
1253 | return; | ||
1254 | } | ||
1255 | |||
1256 | if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types | ||
1257 | return; | ||
1258 | |||
1259 | // Dispatch on the line special value to the line's action routine | ||
1260 | // If a once only function, and successful, clear the line special | ||
1261 | |||
1262 | switch (line->special) | ||
1263 | { | ||
1264 | // Regular walk once triggers | ||
1265 | |||
1266 | case 2: | ||
1267 | // Open Door | ||
1268 | if (EV_DoDoor(line,open) || demo_compatibility) | ||
1269 | line->special = 0; | ||
1270 | break; | ||
1271 | |||
1272 | case 3: | ||
1273 | // Close Door | ||
1274 | if (EV_DoDoor(line,close) || demo_compatibility) | ||
1275 | line->special = 0; | ||
1276 | break; | ||
1277 | |||
1278 | case 4: | ||
1279 | // Raise Door | ||
1280 | if (EV_DoDoor(line,normal) || demo_compatibility) | ||
1281 | line->special = 0; | ||
1282 | break; | ||
1283 | |||
1284 | case 5: | ||
1285 | // Raise Floor | ||
1286 | if (EV_DoFloor(line,raiseFloor) || demo_compatibility) | ||
1287 | line->special = 0; | ||
1288 | break; | ||
1289 | |||
1290 | case 6: | ||
1291 | // Fast Ceiling Crush & Raise | ||
1292 | if (EV_DoCeiling(line,fastCrushAndRaise) || demo_compatibility) | ||
1293 | line->special = 0; | ||
1294 | break; | ||
1295 | |||
1296 | case 8: | ||
1297 | // Build Stairs | ||
1298 | if (EV_BuildStairs(line,build8) || demo_compatibility) | ||
1299 | line->special = 0; | ||
1300 | break; | ||
1301 | |||
1302 | case 10: | ||
1303 | // PlatDownWaitUp | ||
1304 | if (EV_DoPlat(line,downWaitUpStay,0) || demo_compatibility) | ||
1305 | line->special = 0; | ||
1306 | break; | ||
1307 | |||
1308 | case 12: | ||
1309 | // Light Turn On - brightest near | ||
1310 | if (EV_LightTurnOn(line,0) || demo_compatibility) | ||
1311 | line->special = 0; | ||
1312 | break; | ||
1313 | |||
1314 | case 13: | ||
1315 | // Light Turn On 255 | ||
1316 | if (EV_LightTurnOn(line,255) || demo_compatibility) | ||
1317 | line->special = 0; | ||
1318 | break; | ||
1319 | |||
1320 | case 16: | ||
1321 | // Close Door 30 | ||
1322 | if (EV_DoDoor(line,close30ThenOpen) || demo_compatibility) | ||
1323 | line->special = 0; | ||
1324 | break; | ||
1325 | |||
1326 | case 17: | ||
1327 | // Start Light Strobing | ||
1328 | if (EV_StartLightStrobing(line) || demo_compatibility) | ||
1329 | line->special = 0; | ||
1330 | break; | ||
1331 | |||
1332 | case 19: | ||
1333 | // Lower Floor | ||
1334 | if (EV_DoFloor(line,lowerFloor) || demo_compatibility) | ||
1335 | line->special = 0; | ||
1336 | break; | ||
1337 | |||
1338 | case 22: | ||
1339 | // Raise floor to nearest height and change texture | ||
1340 | if (EV_DoPlat(line,raiseToNearestAndChange,0) || demo_compatibility) | ||
1341 | line->special = 0; | ||
1342 | break; | ||
1343 | |||
1344 | case 25: | ||
1345 | // Ceiling Crush and Raise | ||
1346 | if (EV_DoCeiling(line,crushAndRaise) || demo_compatibility) | ||
1347 | line->special = 0; | ||
1348 | break; | ||
1349 | |||
1350 | case 30: | ||
1351 | // Raise floor to shortest texture height | ||
1352 | // on either side of lines. | ||
1353 | if (EV_DoFloor(line,raiseToTexture) || demo_compatibility) | ||
1354 | line->special = 0; | ||
1355 | break; | ||
1356 | |||
1357 | case 35: | ||
1358 | // Lights Very Dark | ||
1359 | if (EV_LightTurnOn(line,35) || demo_compatibility) | ||
1360 | line->special = 0; | ||
1361 | break; | ||
1362 | |||
1363 | case 36: | ||
1364 | // Lower Floor (TURBO) | ||
1365 | if (EV_DoFloor(line,turboLower) || demo_compatibility) | ||
1366 | line->special = 0; | ||
1367 | break; | ||
1368 | |||
1369 | case 37: | ||
1370 | // LowerAndChange | ||
1371 | if (EV_DoFloor(line,lowerAndChange) || demo_compatibility) | ||
1372 | line->special = 0; | ||
1373 | break; | ||
1374 | |||
1375 | case 38: | ||
1376 | // Lower Floor To Lowest | ||
1377 | if (EV_DoFloor(line, lowerFloorToLowest) || demo_compatibility) | ||
1378 | line->special = 0; | ||
1379 | break; | ||
1380 | |||
1381 | case 39: | ||
1382 | // TELEPORT! //jff 02/09/98 fix using up with wrong side crossing | ||
1383 | if (EV_Teleport(line, side, thing) || demo_compatibility) | ||
1384 | line->special = 0; | ||
1385 | break; | ||
1386 | |||
1387 | case 40: | ||
1388 | // RaiseCeilingLowerFloor | ||
1389 | if (demo_compatibility) | ||
1390 | { | ||
1391 | EV_DoCeiling( line, raiseToHighest ); | ||
1392 | EV_DoFloor( line, lowerFloorToLowest ); //jff 02/12/98 doesn't work | ||
1393 | line->special = 0; | ||
1394 | } | ||
1395 | else | ||
1396 | if (EV_DoCeiling(line, raiseToHighest)) | ||
1397 | line->special = 0; | ||
1398 | break; | ||
1399 | |||
1400 | case 44: | ||
1401 | // Ceiling Crush | ||
1402 | if (EV_DoCeiling(line, lowerAndCrush) || demo_compatibility) | ||
1403 | line->special = 0; | ||
1404 | break; | ||
1405 | |||
1406 | case 52: | ||
1407 | // EXIT! | ||
1408 | // killough 10/98: prevent zombies from exiting levels | ||
1409 | if (!(thing->player && thing->player->health <= 0 && !comp[comp_zombie])) | ||
1410 | G_ExitLevel (); | ||
1411 | break; | ||
1412 | |||
1413 | case 53: | ||
1414 | // Perpetual Platform Raise | ||
1415 | if (EV_DoPlat(line,perpetualRaise,0) || demo_compatibility) | ||
1416 | line->special = 0; | ||
1417 | break; | ||
1418 | |||
1419 | case 54: | ||
1420 | // Platform Stop | ||
1421 | if (EV_StopPlat(line) || demo_compatibility) | ||
1422 | line->special = 0; | ||
1423 | break; | ||
1424 | |||
1425 | case 56: | ||
1426 | // Raise Floor Crush | ||
1427 | if (EV_DoFloor(line,raiseFloorCrush) || demo_compatibility) | ||
1428 | line->special = 0; | ||
1429 | break; | ||
1430 | |||
1431 | case 57: | ||
1432 | // Ceiling Crush Stop | ||
1433 | if (EV_CeilingCrushStop(line) || demo_compatibility) | ||
1434 | line->special = 0; | ||
1435 | break; | ||
1436 | |||
1437 | case 58: | ||
1438 | // Raise Floor 24 | ||
1439 | if (EV_DoFloor(line,raiseFloor24) || demo_compatibility) | ||
1440 | line->special = 0; | ||
1441 | break; | ||
1442 | |||
1443 | case 59: | ||
1444 | // Raise Floor 24 And Change | ||
1445 | if (EV_DoFloor(line,raiseFloor24AndChange) || demo_compatibility) | ||
1446 | line->special = 0; | ||
1447 | break; | ||
1448 | |||
1449 | case 100: | ||
1450 | // Build Stairs Turbo 16 | ||
1451 | if (EV_BuildStairs(line,turbo16) || demo_compatibility) | ||
1452 | line->special = 0; | ||
1453 | break; | ||
1454 | |||
1455 | case 104: | ||
1456 | // Turn lights off in sector(tag) | ||
1457 | if (EV_TurnTagLightsOff(line) || demo_compatibility) | ||
1458 | line->special = 0; | ||
1459 | break; | ||
1460 | |||
1461 | case 108: | ||
1462 | // Blazing Door Raise (faster than TURBO!) | ||
1463 | if (EV_DoDoor(line,blazeRaise) || demo_compatibility) | ||
1464 | line->special = 0; | ||
1465 | break; | ||
1466 | |||
1467 | case 109: | ||
1468 | // Blazing Door Open (faster than TURBO!) | ||
1469 | if (EV_DoDoor (line,blazeOpen) || demo_compatibility) | ||
1470 | line->special = 0; | ||
1471 | break; | ||
1472 | |||
1473 | case 110: | ||
1474 | // Blazing Door Close (faster than TURBO!) | ||
1475 | if (EV_DoDoor (line,blazeClose) || demo_compatibility) | ||
1476 | line->special = 0; | ||
1477 | break; | ||
1478 | |||
1479 | case 119: | ||
1480 | // Raise floor to nearest surr. floor | ||
1481 | if (EV_DoFloor(line,raiseFloorToNearest) || demo_compatibility) | ||
1482 | line->special = 0; | ||
1483 | break; | ||
1484 | |||
1485 | case 121: | ||
1486 | // Blazing PlatDownWaitUpStay | ||
1487 | if (EV_DoPlat(line,blazeDWUS,0) || demo_compatibility) | ||
1488 | line->special = 0; | ||
1489 | break; | ||
1490 | |||
1491 | case 124: | ||
1492 | // Secret EXIT | ||
1493 | // killough 10/98: prevent zombies from exiting levels | ||
1494 | // CPhipps - change for lxdoom's compatibility handling | ||
1495 | if (!(thing->player && thing->player->health <= 0 && !comp[comp_zombie])) | ||
1496 | G_SecretExitLevel (); | ||
1497 | break; | ||
1498 | |||
1499 | case 125: | ||
1500 | // TELEPORT MonsterONLY | ||
1501 | if (!thing->player && | ||
1502 | (EV_Teleport(line, side, thing) || demo_compatibility)) | ||
1503 | line->special = 0; | ||
1504 | break; | ||
1505 | |||
1506 | case 130: | ||
1507 | // Raise Floor Turbo | ||
1508 | if (EV_DoFloor(line,raiseFloorTurbo) || demo_compatibility) | ||
1509 | line->special = 0; | ||
1510 | break; | ||
1511 | |||
1512 | case 141: | ||
1513 | // Silent Ceiling Crush & Raise | ||
1514 | if (EV_DoCeiling(line,silentCrushAndRaise) || demo_compatibility) | ||
1515 | line->special = 0; | ||
1516 | break; | ||
1517 | |||
1518 | // Regular walk many retriggerable | ||
1519 | |||
1520 | case 72: | ||
1521 | // Ceiling Crush | ||
1522 | EV_DoCeiling( line, lowerAndCrush ); | ||
1523 | break; | ||
1524 | |||
1525 | case 73: | ||
1526 | // Ceiling Crush and Raise | ||
1527 | EV_DoCeiling(line,crushAndRaise); | ||
1528 | break; | ||
1529 | |||
1530 | case 74: | ||
1531 | // Ceiling Crush Stop | ||
1532 | EV_CeilingCrushStop(line); | ||
1533 | break; | ||
1534 | |||
1535 | case 75: | ||
1536 | // Close Door | ||
1537 | EV_DoDoor(line,close); | ||
1538 | break; | ||
1539 | |||
1540 | case 76: | ||
1541 | // Close Door 30 | ||
1542 | EV_DoDoor(line,close30ThenOpen); | ||
1543 | break; | ||
1544 | |||
1545 | case 77: | ||
1546 | // Fast Ceiling Crush & Raise | ||
1547 | EV_DoCeiling(line,fastCrushAndRaise); | ||
1548 | break; | ||
1549 | |||
1550 | case 79: | ||
1551 | // Lights Very Dark | ||
1552 | EV_LightTurnOn(line,35); | ||
1553 | break; | ||
1554 | |||
1555 | case 80: | ||
1556 | // Light Turn On - brightest near | ||
1557 | EV_LightTurnOn(line,0); | ||
1558 | break; | ||
1559 | |||
1560 | case 81: | ||
1561 | // Light Turn On 255 | ||
1562 | EV_LightTurnOn(line,255); | ||
1563 | break; | ||
1564 | |||
1565 | case 82: | ||
1566 | // Lower Floor To Lowest | ||
1567 | EV_DoFloor( line, lowerFloorToLowest ); | ||
1568 | break; | ||
1569 | |||
1570 | case 83: | ||
1571 | // Lower Floor | ||
1572 | EV_DoFloor(line,lowerFloor); | ||
1573 | break; | ||
1574 | |||
1575 | case 84: | ||
1576 | // LowerAndChange | ||
1577 | EV_DoFloor(line,lowerAndChange); | ||
1578 | break; | ||
1579 | |||
1580 | case 86: | ||
1581 | // Open Door | ||
1582 | EV_DoDoor(line,open); | ||
1583 | break; | ||
1584 | |||
1585 | case 87: | ||
1586 | // Perpetual Platform Raise | ||
1587 | EV_DoPlat(line,perpetualRaise,0); | ||
1588 | break; | ||
1589 | |||
1590 | case 88: | ||
1591 | // PlatDownWaitUp | ||
1592 | EV_DoPlat(line,downWaitUpStay,0); | ||
1593 | break; | ||
1594 | |||
1595 | case 89: | ||
1596 | // Platform Stop | ||
1597 | EV_StopPlat(line); | ||
1598 | break; | ||
1599 | |||
1600 | case 90: | ||
1601 | // Raise Door | ||
1602 | EV_DoDoor(line,normal); | ||
1603 | break; | ||
1604 | |||
1605 | case 91: | ||
1606 | // Raise Floor | ||
1607 | EV_DoFloor(line,raiseFloor); | ||
1608 | break; | ||
1609 | |||
1610 | case 92: | ||
1611 | // Raise Floor 24 | ||
1612 | EV_DoFloor(line,raiseFloor24); | ||
1613 | break; | ||
1614 | |||
1615 | case 93: | ||
1616 | // Raise Floor 24 And Change | ||
1617 | EV_DoFloor(line,raiseFloor24AndChange); | ||
1618 | break; | ||
1619 | |||
1620 | case 94: | ||
1621 | // Raise Floor Crush | ||
1622 | EV_DoFloor(line,raiseFloorCrush); | ||
1623 | break; | ||
1624 | |||
1625 | case 95: | ||
1626 | // Raise floor to nearest height | ||
1627 | // and change texture. | ||
1628 | EV_DoPlat(line,raiseToNearestAndChange,0); | ||
1629 | break; | ||
1630 | |||
1631 | case 96: | ||
1632 | // Raise floor to shortest texture height | ||
1633 | // on either side of lines. | ||
1634 | EV_DoFloor(line,raiseToTexture); | ||
1635 | break; | ||
1636 | |||
1637 | case 97: | ||
1638 | // TELEPORT! | ||
1639 | EV_Teleport( line, side, thing ); | ||
1640 | break; | ||
1641 | |||
1642 | case 98: | ||
1643 | // Lower Floor (TURBO) | ||
1644 | EV_DoFloor(line,turboLower); | ||
1645 | break; | ||
1646 | |||
1647 | case 105: | ||
1648 | // Blazing Door Raise (faster than TURBO!) | ||
1649 | EV_DoDoor (line,blazeRaise); | ||
1650 | break; | ||
1651 | |||
1652 | case 106: | ||
1653 | // Blazing Door Open (faster than TURBO!) | ||
1654 | EV_DoDoor (line,blazeOpen); | ||
1655 | break; | ||
1656 | |||
1657 | case 107: | ||
1658 | // Blazing Door Close (faster than TURBO!) | ||
1659 | EV_DoDoor (line,blazeClose); | ||
1660 | break; | ||
1661 | |||
1662 | case 120: | ||
1663 | // Blazing PlatDownWaitUpStay. | ||
1664 | EV_DoPlat(line,blazeDWUS,0); | ||
1665 | break; | ||
1666 | |||
1667 | case 126: | ||
1668 | // TELEPORT MonsterONLY. | ||
1669 | if (!thing->player) | ||
1670 | EV_Teleport( line, side, thing ); | ||
1671 | break; | ||
1672 | |||
1673 | case 128: | ||
1674 | // Raise To Nearest Floor | ||
1675 | EV_DoFloor(line,raiseFloorToNearest); | ||
1676 | break; | ||
1677 | |||
1678 | case 129: | ||
1679 | // Raise Floor Turbo | ||
1680 | EV_DoFloor(line,raiseFloorTurbo); | ||
1681 | break; | ||
1682 | |||
1683 | // Extended walk triggers | ||
1684 | |||
1685 | // jff 1/29/98 added new linedef types to fill all functions out so that | ||
1686 | // all have varieties SR, S1, WR, W1 | ||
1687 | |||
1688 | // killough 1/31/98: "factor out" compatibility test, by | ||
1689 | // adding inner switch qualified by compatibility flag. | ||
1690 | // relax test to demo_compatibility | ||
1691 | |||
1692 | // killough 2/16/98: Fix problems with W1 types being cleared too early | ||
1693 | |||
1694 | default: | ||
1695 | if (!demo_compatibility) | ||
1696 | switch (line->special) | ||
1697 | { | ||
1698 | // Extended walk once triggers | ||
1699 | |||
1700 | case 142: | ||
1701 | // Raise Floor 512 | ||
1702 | // 142 W1 EV_DoFloor(raiseFloor512) | ||
1703 | if (EV_DoFloor(line,raiseFloor512)) | ||
1704 | line->special = 0; | ||
1705 | break; | ||
1706 | |||
1707 | case 143: | ||
1708 | // Raise Floor 24 and change | ||
1709 | // 143 W1 EV_DoPlat(raiseAndChange,24) | ||
1710 | if (EV_DoPlat(line,raiseAndChange,24)) | ||
1711 | line->special = 0; | ||
1712 | break; | ||
1713 | |||
1714 | case 144: | ||
1715 | // Raise Floor 32 and change | ||
1716 | // 144 W1 EV_DoPlat(raiseAndChange,32) | ||
1717 | if (EV_DoPlat(line,raiseAndChange,32)) | ||
1718 | line->special = 0; | ||
1719 | break; | ||
1720 | |||
1721 | case 145: | ||
1722 | // Lower Ceiling to Floor | ||
1723 | // 145 W1 EV_DoCeiling(lowerToFloor) | ||
1724 | if (EV_DoCeiling( line, lowerToFloor )) | ||
1725 | line->special = 0; | ||
1726 | break; | ||
1727 | |||
1728 | case 146: | ||
1729 | // Lower Pillar, Raise Donut | ||
1730 | // 146 W1 EV_DoDonut() | ||
1731 | if (EV_DoDonut(line)) | ||
1732 | line->special = 0; | ||
1733 | break; | ||
1734 | |||
1735 | case 199: | ||
1736 | // Lower ceiling to lowest surrounding ceiling | ||
1737 | // 199 W1 EV_DoCeiling(lowerToLowest) | ||
1738 | if (EV_DoCeiling(line,lowerToLowest)) | ||
1739 | line->special = 0; | ||
1740 | break; | ||
1741 | |||
1742 | case 200: | ||
1743 | // Lower ceiling to highest surrounding floor | ||
1744 | // 200 W1 EV_DoCeiling(lowerToMaxFloor) | ||
1745 | if (EV_DoCeiling(line,lowerToMaxFloor)) | ||
1746 | line->special = 0; | ||
1747 | break; | ||
1748 | |||
1749 | case 207: | ||
1750 | // killough 2/16/98: W1 silent teleporter (normal kind) | ||
1751 | if (EV_SilentTeleport(line, side, thing)) | ||
1752 | line->special = 0; | ||
1753 | break; | ||
1754 | |||
1755 | //jff 3/16/98 renumber 215->153 | ||
1756 | case 153: //jff 3/15/98 create texture change no motion type | ||
1757 | // Texture/Type Change Only (Trig) | ||
1758 | // 153 W1 Change Texture/Type Only | ||
1759 | if (EV_DoChange(line,trigChangeOnly)) | ||
1760 | line->special = 0; | ||
1761 | break; | ||
1762 | |||
1763 | case 239: //jff 3/15/98 create texture change no motion type | ||
1764 | // Texture/Type Change Only (Numeric) | ||
1765 | // 239 W1 Change Texture/Type Only | ||
1766 | if (EV_DoChange(line,numChangeOnly)) | ||
1767 | line->special = 0; | ||
1768 | break; | ||
1769 | |||
1770 | case 219: | ||
1771 | // Lower floor to next lower neighbor | ||
1772 | // 219 W1 Lower Floor Next Lower Neighbor | ||
1773 | if (EV_DoFloor(line,lowerFloorToNearest)) | ||
1774 | line->special = 0; | ||
1775 | break; | ||
1776 | |||
1777 | case 227: | ||
1778 | // Raise elevator next floor | ||
1779 | // 227 W1 Raise Elevator next floor | ||
1780 | if (EV_DoElevator(line,elevateUp)) | ||
1781 | line->special = 0; | ||
1782 | break; | ||
1783 | |||
1784 | case 231: | ||
1785 | // Lower elevator next floor | ||
1786 | // 231 W1 Lower Elevator next floor | ||
1787 | if (EV_DoElevator(line,elevateDown)) | ||
1788 | line->special = 0; | ||
1789 | break; | ||
1790 | |||
1791 | case 235: | ||
1792 | // Elevator to current floor | ||
1793 | // 235 W1 Elevator to current floor | ||
1794 | if (EV_DoElevator(line,elevateCurrent)) | ||
1795 | line->special = 0; | ||
1796 | break; | ||
1797 | |||
1798 | case 243: //jff 3/6/98 make fit within DCK's 256 linedef types | ||
1799 | // killough 2/16/98: W1 silent teleporter (linedef-linedef kind) | ||
1800 | if (EV_SilentLineTeleport(line, side, thing, false)) | ||
1801 | line->special = 0; | ||
1802 | break; | ||
1803 | |||
1804 | case 262: //jff 4/14/98 add silent line-line reversed | ||
1805 | if (EV_SilentLineTeleport(line, side, thing, true)) | ||
1806 | line->special = 0; | ||
1807 | break; | ||
1808 | |||
1809 | case 264: //jff 4/14/98 add monster-only silent line-line reversed | ||
1810 | if (!thing->player && | ||
1811 | EV_SilentLineTeleport(line, side, thing, true)) | ||
1812 | line->special = 0; | ||
1813 | break; | ||
1814 | |||
1815 | case 266: //jff 4/14/98 add monster-only silent line-line | ||
1816 | if (!thing->player && | ||
1817 | EV_SilentLineTeleport(line, side, thing, false)) | ||
1818 | line->special = 0; | ||
1819 | break; | ||
1820 | |||
1821 | case 268: //jff 4/14/98 add monster-only silent | ||
1822 | if (!thing->player && EV_SilentTeleport(line, side, thing)) | ||
1823 | line->special = 0; | ||
1824 | break; | ||
1825 | |||
1826 | //jff 1/29/98 end of added W1 linedef types | ||
1827 | |||
1828 | // Extended walk many retriggerable | ||
1829 | |||
1830 | //jff 1/29/98 added new linedef types to fill all functions | ||
1831 | //out so that all have varieties SR, S1, WR, W1 | ||
1832 | |||
1833 | case 147: | ||
1834 | // Raise Floor 512 | ||
1835 | // 147 WR EV_DoFloor(raiseFloor512) | ||
1836 | EV_DoFloor(line,raiseFloor512); | ||
1837 | break; | ||
1838 | |||
1839 | case 148: | ||
1840 | // Raise Floor 24 and Change | ||
1841 | // 148 WR EV_DoPlat(raiseAndChange,24) | ||
1842 | EV_DoPlat(line,raiseAndChange,24); | ||
1843 | break; | ||
1844 | |||
1845 | case 149: | ||
1846 | // Raise Floor 32 and Change | ||
1847 | // 149 WR EV_DoPlat(raiseAndChange,32) | ||
1848 | EV_DoPlat(line,raiseAndChange,32); | ||
1849 | break; | ||
1850 | |||
1851 | case 150: | ||
1852 | // Start slow silent crusher | ||
1853 | // 150 WR EV_DoCeiling(silentCrushAndRaise) | ||
1854 | EV_DoCeiling(line,silentCrushAndRaise); | ||
1855 | break; | ||
1856 | |||
1857 | case 151: | ||
1858 | // RaiseCeilingLowerFloor | ||
1859 | // 151 WR EV_DoCeiling(raiseToHighest), | ||
1860 | // EV_DoFloor(lowerFloortoLowest) | ||
1861 | EV_DoCeiling( line, raiseToHighest ); | ||
1862 | EV_DoFloor( line, lowerFloorToLowest ); | ||
1863 | break; | ||
1864 | |||
1865 | case 152: | ||
1866 | // Lower Ceiling to Floor | ||
1867 | // 152 WR EV_DoCeiling(lowerToFloor) | ||
1868 | EV_DoCeiling( line, lowerToFloor ); | ||
1869 | break; | ||
1870 | |||
1871 | //jff 3/16/98 renumber 153->256 | ||
1872 | case 256: | ||
1873 | // Build stairs, step 8 | ||
1874 | // 256 WR EV_BuildStairs(build8) | ||
1875 | EV_BuildStairs(line,build8); | ||
1876 | break; | ||
1877 | |||
1878 | //jff 3/16/98 renumber 154->257 | ||
1879 | case 257: | ||
1880 | // Build stairs, step 16 | ||
1881 | // 257 WR EV_BuildStairs(turbo16) | ||
1882 | EV_BuildStairs(line,turbo16); | ||
1883 | break; | ||
1884 | |||
1885 | case 155: | ||
1886 | // Lower Pillar, Raise Donut | ||
1887 | // 155 WR EV_DoDonut() | ||
1888 | EV_DoDonut(line); | ||
1889 | break; | ||
1890 | |||
1891 | case 156: | ||
1892 | // Start lights strobing | ||
1893 | // 156 WR Lights EV_StartLightStrobing() | ||
1894 | EV_StartLightStrobing(line); | ||
1895 | break; | ||
1896 | |||
1897 | case 157: | ||
1898 | // Lights to dimmest near | ||
1899 | // 157 WR Lights EV_TurnTagLightsOff() | ||
1900 | EV_TurnTagLightsOff(line); | ||
1901 | break; | ||
1902 | |||
1903 | case 201: | ||
1904 | // Lower ceiling to lowest surrounding ceiling | ||
1905 | // 201 WR EV_DoCeiling(lowerToLowest) | ||
1906 | EV_DoCeiling(line,lowerToLowest); | ||
1907 | break; | ||
1908 | |||
1909 | case 202: | ||
1910 | // Lower ceiling to highest surrounding floor | ||
1911 | // 202 WR EV_DoCeiling(lowerToMaxFloor) | ||
1912 | EV_DoCeiling(line,lowerToMaxFloor); | ||
1913 | break; | ||
1914 | |||
1915 | case 208: | ||
1916 | // killough 2/16/98: WR silent teleporter (normal kind) | ||
1917 | EV_SilentTeleport(line, side, thing); | ||
1918 | break; | ||
1919 | |||
1920 | case 212: //jff 3/14/98 create instant toggle floor type | ||
1921 | // Toggle floor between C and F instantly | ||
1922 | // 212 WR Instant Toggle Floor | ||
1923 | EV_DoPlat(line,toggleUpDn,0); | ||
1924 | break; | ||
1925 | |||
1926 | //jff 3/16/98 renumber 216->154 | ||
1927 | case 154: //jff 3/15/98 create texture change no motion type | ||
1928 | // Texture/Type Change Only (Trigger) | ||
1929 | // 154 WR Change Texture/Type Only | ||
1930 | EV_DoChange(line,trigChangeOnly); | ||
1931 | break; | ||
1932 | |||
1933 | case 240: //jff 3/15/98 create texture change no motion type | ||
1934 | // Texture/Type Change Only (Numeric) | ||
1935 | // 240 WR Change Texture/Type Only | ||
1936 | EV_DoChange(line,numChangeOnly); | ||
1937 | break; | ||
1938 | |||
1939 | case 220: | ||
1940 | // Lower floor to next lower neighbor | ||
1941 | // 220 WR Lower Floor Next Lower Neighbor | ||
1942 | EV_DoFloor(line,lowerFloorToNearest); | ||
1943 | break; | ||
1944 | |||
1945 | case 228: | ||
1946 | // Raise elevator next floor | ||
1947 | // 228 WR Raise Elevator next floor | ||
1948 | EV_DoElevator(line,elevateUp); | ||
1949 | break; | ||
1950 | |||
1951 | case 232: | ||
1952 | // Lower elevator next floor | ||
1953 | // 232 WR Lower Elevator next floor | ||
1954 | EV_DoElevator(line,elevateDown); | ||
1955 | break; | ||
1956 | |||
1957 | case 236: | ||
1958 | // Elevator to current floor | ||
1959 | // 236 WR Elevator to current floor | ||
1960 | EV_DoElevator(line,elevateCurrent); | ||
1961 | break; | ||
1962 | |||
1963 | case 244: //jff 3/6/98 make fit within DCK's 256 linedef types | ||
1964 | // killough 2/16/98: WR silent teleporter (linedef-linedef kind) | ||
1965 | EV_SilentLineTeleport(line, side, thing, false); | ||
1966 | break; | ||
1967 | |||
1968 | case 263: //jff 4/14/98 add silent line-line reversed | ||
1969 | EV_SilentLineTeleport(line, side, thing, true); | ||
1970 | break; | ||
1971 | |||
1972 | case 265: //jff 4/14/98 add monster-only silent line-line reversed | ||
1973 | if (!thing->player) | ||
1974 | EV_SilentLineTeleport(line, side, thing, true); | ||
1975 | break; | ||
1976 | |||
1977 | case 267: //jff 4/14/98 add monster-only silent line-line | ||
1978 | if (!thing->player) | ||
1979 | EV_SilentLineTeleport(line, side, thing, false); | ||
1980 | break; | ||
1981 | |||
1982 | case 269: //jff 4/14/98 add monster-only silent | ||
1983 | if (!thing->player) | ||
1984 | EV_SilentTeleport(line, side, thing); | ||
1985 | break; | ||
1986 | |||
1987 | //jff 1/29/98 end of added WR linedef types | ||
1988 | } | ||
1989 | break; | ||
1990 | } | ||
1991 | } | ||
1992 | |||
1993 | // | ||
1994 | // P_ShootSpecialLine - Gun trigger special dispatcher | ||
1995 | // | ||
1996 | // Called when a thing shoots a special line with bullet, shell, saw, or fist. | ||
1997 | // | ||
1998 | // jff 02/12/98 all G1 lines were fixed to check the result from the EV_ | ||
1999 | // function before clearing the special. This avoids losing the function | ||
2000 | // of the line, should the sector already be in motion when the line is | ||
2001 | // impacted. Change is qualified by demo_compatibility. | ||
2002 | // | ||
2003 | void P_ShootSpecialLine | ||
2004 | ( mobj_t* thing, | ||
2005 | line_t* line ) | ||
2006 | { | ||
2007 | //jff 02/04/98 add check here for generalized linedef | ||
2008 | if (!demo_compatibility) | ||
2009 | { | ||
2010 | // pointer to line function is NULL by default, set non-null if | ||
2011 | // line special is gun triggered generalized linedef type | ||
2012 | int (*linefunc)(line_t *line)=NULL; | ||
2013 | |||
2014 | // check each range of generalized linedefs | ||
2015 | if ((unsigned)line->special >= GenEnd) | ||
2016 | { | ||
2017 | // Out of range for GenFloors | ||
2018 | } | ||
2019 | else if ((unsigned)line->special >= GenFloorBase) | ||
2020 | { | ||
2021 | if (!thing->player) | ||
2022 | if ((line->special & FloorChange) || !(line->special & FloorModel)) | ||
2023 | return; // FloorModel is "Allow Monsters" if FloorChange is 0 | ||
2024 | if (!line->tag) //jff 2/27/98 all gun generalized types require tag | ||
2025 | return; | ||
2026 | |||
2027 | linefunc = EV_DoGenFloor; | ||
2028 | } | ||
2029 | else if ((unsigned)line->special >= GenCeilingBase) | ||
2030 | { | ||
2031 | if (!thing->player) | ||
2032 | if ((line->special & CeilingChange) || !(line->special & CeilingModel)) | ||
2033 | return; // CeilingModel is "Allow Monsters" if CeilingChange is 0 | ||
2034 | if (!line->tag) //jff 2/27/98 all gun generalized types require tag | ||
2035 | return; | ||
2036 | linefunc = EV_DoGenCeiling; | ||
2037 | } | ||
2038 | else if ((unsigned)line->special >= GenDoorBase) | ||
2039 | { | ||
2040 | if (!thing->player) | ||
2041 | { | ||
2042 | if (!(line->special & DoorMonster)) | ||
2043 | return; // monsters disallowed from this door | ||
2044 | if (line->flags & ML_SECRET) // they can't open secret doors either | ||
2045 | return; | ||
2046 | } | ||
2047 | if (!line->tag) //jff 3/2/98 all gun generalized types require tag | ||
2048 | return; | ||
2049 | linefunc = EV_DoGenDoor; | ||
2050 | } | ||
2051 | else if ((unsigned)line->special >= GenLockedBase) | ||
2052 | { | ||
2053 | if (!thing->player) | ||
2054 | return; // monsters disallowed from unlocking doors | ||
2055 | if (((line->special&TriggerType)==GunOnce) || ((line->special&TriggerType)==GunMany)) | ||
2056 | { //jff 4/1/98 check for being a gun type before reporting door type | ||
2057 | if (!P_CanUnlockGenDoor(line,thing->player)) | ||
2058 | return; | ||
2059 | } | ||
2060 | else | ||
2061 | return; | ||
2062 | if (!line->tag) //jff 2/27/98 all gun generalized types require tag | ||
2063 | return; | ||
2064 | |||
2065 | linefunc = EV_DoGenLockedDoor; | ||
2066 | } | ||
2067 | else if ((unsigned)line->special >= GenLiftBase) | ||
2068 | { | ||
2069 | if (!thing->player) | ||
2070 | if (!(line->special & LiftMonster)) | ||
2071 | return; // monsters disallowed | ||
2072 | linefunc = EV_DoGenLift; | ||
2073 | } | ||
2074 | else if ((unsigned)line->special >= GenStairsBase) | ||
2075 | { | ||
2076 | if (!thing->player) | ||
2077 | if (!(line->special & StairMonster)) | ||
2078 | return; // monsters disallowed | ||
2079 | if (!line->tag) //jff 2/27/98 all gun generalized types require tag | ||
2080 | return; | ||
2081 | linefunc = EV_DoGenStairs; | ||
2082 | } | ||
2083 | else if ((unsigned)line->special >= GenCrusherBase) | ||
2084 | { | ||
2085 | if (!thing->player) | ||
2086 | if (!(line->special & StairMonster)) | ||
2087 | return; // monsters disallowed | ||
2088 | if (!line->tag) //jff 2/27/98 all gun generalized types require tag | ||
2089 | return; | ||
2090 | linefunc = EV_DoGenCrusher; | ||
2091 | } | ||
2092 | |||
2093 | if (linefunc) | ||
2094 | switch((line->special & TriggerType) >> TriggerTypeShift) | ||
2095 | { | ||
2096 | case GunOnce: | ||
2097 | if (linefunc(line)) | ||
2098 | P_ChangeSwitchTexture(line,0); | ||
2099 | return; | ||
2100 | case GunMany: | ||
2101 | if (linefunc(line)) | ||
2102 | P_ChangeSwitchTexture(line,1); | ||
2103 | return; | ||
2104 | default: // if not a gun type, do nothing here | ||
2105 | return; | ||
2106 | } | ||
2107 | } | ||
2108 | |||
2109 | // Impacts that other things can activate. | ||
2110 | if (!thing->player) | ||
2111 | { | ||
2112 | int ok = 0; | ||
2113 | switch(line->special) | ||
2114 | { | ||
2115 | case 46: | ||
2116 | // 46 GR Open door on impact weapon is monster activatable | ||
2117 | ok = 1; | ||
2118 | break; | ||
2119 | } | ||
2120 | if (!ok) | ||
2121 | return; | ||
2122 | } | ||
2123 | |||
2124 | if (!P_CheckTag(line)) //jff 2/27/98 disallow zero tag on some types | ||
2125 | return; | ||
2126 | |||
2127 | switch(line->special) | ||
2128 | { | ||
2129 | case 24: | ||
2130 | // 24 G1 raise floor to highest adjacent | ||
2131 | if (EV_DoFloor(line,raiseFloor) || demo_compatibility) | ||
2132 | P_ChangeSwitchTexture(line,0); | ||
2133 | break; | ||
2134 | |||
2135 | case 46: | ||
2136 | // 46 GR open door, stay open | ||
2137 | EV_DoDoor(line,open); | ||
2138 | P_ChangeSwitchTexture(line,1); | ||
2139 | break; | ||
2140 | |||
2141 | case 47: | ||
2142 | // 47 G1 raise floor to nearest and change texture and type | ||
2143 | if (EV_DoPlat(line,raiseToNearestAndChange,0) || demo_compatibility) | ||
2144 | P_ChangeSwitchTexture(line,0); | ||
2145 | break; | ||
2146 | |||
2147 | //jff 1/30/98 added new gun linedefs here | ||
2148 | // killough 1/31/98: added demo_compatibility check, added inner switch | ||
2149 | |||
2150 | default: | ||
2151 | if (!demo_compatibility) | ||
2152 | switch (line->special) | ||
2153 | { | ||
2154 | case 197: | ||
2155 | // Exit to next level | ||
2156 | // killough 10/98: prevent zombies from exiting levels | ||
2157 | if(thing->player && thing->player->health<=0 && !comp[comp_zombie]) | ||
2158 | break; | ||
2159 | P_ChangeSwitchTexture(line,0); | ||
2160 | G_ExitLevel(); | ||
2161 | break; | ||
2162 | |||
2163 | case 198: | ||
2164 | // Exit to secret level | ||
2165 | // killough 10/98: prevent zombies from exiting levels | ||
2166 | if(thing->player && thing->player->health<=0 && !comp[comp_zombie]) | ||
2167 | break; | ||
2168 | P_ChangeSwitchTexture(line,0); | ||
2169 | G_SecretExitLevel(); | ||
2170 | break; | ||
2171 | //jff end addition of new gun linedefs | ||
2172 | } | ||
2173 | break; | ||
2174 | } | ||
2175 | } | ||
2176 | |||
2177 | |||
2178 | // | ||
2179 | // P_PlayerInSpecialSector() | ||
2180 | // | ||
2181 | // Called every tick frame | ||
2182 | // that the player origin is in a special sector | ||
2183 | // | ||
2184 | // Changed to ignore sector types the engine does not recognize | ||
2185 | // | ||
2186 | void P_PlayerInSpecialSector (player_t* player) | ||
2187 | { | ||
2188 | sector_t* sector; | ||
2189 | |||
2190 | sector = player->mo->subsector->sector; | ||
2191 | |||
2192 | // Falling, not all the way down yet? | ||
2193 | // Sector specials don't apply in mid-air | ||
2194 | if (player->mo->z != sector->floorheight) | ||
2195 | return; | ||
2196 | |||
2197 | // Has hit ground. | ||
2198 | //jff add if to handle old vs generalized types | ||
2199 | if (sector->special<32) // regular sector specials | ||
2200 | { | ||
2201 | switch (sector->special) | ||
2202 | { | ||
2203 | case 5: | ||
2204 | // 5/10 unit damage per 31 ticks | ||
2205 | if (!player->powers[pw_ironfeet]) | ||
2206 | if (!(leveltime&0x1f)) | ||
2207 | P_DamageMobj (player->mo, NULL, NULL, 10); | ||
2208 | break; | ||
2209 | |||
2210 | case 7: | ||
2211 | // 2/5 unit damage per 31 ticks | ||
2212 | if (!player->powers[pw_ironfeet]) | ||
2213 | if (!(leveltime&0x1f)) | ||
2214 | P_DamageMobj (player->mo, NULL, NULL, 5); | ||
2215 | break; | ||
2216 | |||
2217 | case 16: | ||
2218 | // 10/20 unit damage per 31 ticks | ||
2219 | case 4: | ||
2220 | // 10/20 unit damage plus blinking light (light already spawned) | ||
2221 | if (!player->powers[pw_ironfeet] | ||
2222 | || (P_Random(pr_slimehurt)<5) ) // even with suit, take damage | ||
2223 | { | ||
2224 | if (!(leveltime&0x1f)) | ||
2225 | P_DamageMobj (player->mo, NULL, NULL, 20); | ||
2226 | } | ||
2227 | break; | ||
2228 | |||
2229 | case 9: | ||
2230 | // Tally player in secret sector, clear secret special | ||
2231 | player->secretcount++; | ||
2232 | sector->special = 0; | ||
2233 | break; | ||
2234 | |||
2235 | case 11: | ||
2236 | // Exit on health < 11, take 10/20 damage per 31 ticks | ||
2237 | if (comp[comp_god]) /* killough 2/21/98: add compatibility switch */ | ||
2238 | player->cheats &= ~CF_GODMODE; // on godmode cheat clearing | ||
2239 | // does not affect invulnerability | ||
2240 | if (!(leveltime&0x1f)) | ||
2241 | P_DamageMobj (player->mo, NULL, NULL, 20); | ||
2242 | |||
2243 | if (player->health <= 10) | ||
2244 | G_ExitLevel(); | ||
2245 | break; | ||
2246 | |||
2247 | default: | ||
2248 | //jff 1/24/98 Don't exit as DOOM2 did, just ignore | ||
2249 | break; | ||
2250 | }; | ||
2251 | } | ||
2252 | else //jff 3/14/98 handle extended sector types for secrets and damage | ||
2253 | { | ||
2254 | switch ((sector->special&DAMAGE_MASK)>>DAMAGE_SHIFT) | ||
2255 | { | ||
2256 | case 0: // no damage | ||
2257 | break; | ||
2258 | case 1: // 2/5 damage per 31 ticks | ||
2259 | if (!player->powers[pw_ironfeet]) | ||
2260 | if (!(leveltime&0x1f)) | ||
2261 | P_DamageMobj (player->mo, NULL, NULL, 5); | ||
2262 | break; | ||
2263 | case 2: // 5/10 damage per 31 ticks | ||
2264 | if (!player->powers[pw_ironfeet]) | ||
2265 | if (!(leveltime&0x1f)) | ||
2266 | P_DamageMobj (player->mo, NULL, NULL, 10); | ||
2267 | break; | ||
2268 | case 3: // 10/20 damage per 31 ticks | ||
2269 | if (!player->powers[pw_ironfeet] | ||
2270 | || (P_Random(pr_slimehurt)<5)) // take damage even with suit | ||
2271 | { | ||
2272 | if (!(leveltime&0x1f)) | ||
2273 | P_DamageMobj (player->mo, NULL, NULL, 20); | ||
2274 | } | ||
2275 | break; | ||
2276 | } | ||
2277 | if (sector->special&SECRET_MASK) | ||
2278 | { | ||
2279 | player->secretcount++; | ||
2280 | sector->special &= ~SECRET_MASK; | ||
2281 | if (sector->special<32) // if all extended bits clear, | ||
2282 | sector->special=0; // sector is not special anymore | ||
2283 | } | ||
2284 | |||
2285 | // phares 3/19/98: | ||
2286 | // | ||
2287 | // If FRICTION_MASK or PUSH_MASK is set, we don't care at this | ||
2288 | // point, since the code to deal with those situations is | ||
2289 | // handled by Thinkers. | ||
2290 | |||
2291 | } | ||
2292 | } | ||
2293 | |||
2294 | // | ||
2295 | // P_UpdateSpecials() | ||
2296 | // | ||
2297 | // Check level timer, frag counter, | ||
2298 | // animate flats, scroll walls, | ||
2299 | // change button textures | ||
2300 | // | ||
2301 | // Reads and modifies globals: | ||
2302 | // levelTimer, levelTimeCount, | ||
2303 | // levelFragLimit, levelFragLimitCount | ||
2304 | // | ||
2305 | |||
2306 | static boolean levelTimer; | ||
2307 | static int levelTimeCount; | ||
2308 | boolean levelFragLimit; // Ty 03/18/98 Added -frags support | ||
2309 | int levelFragLimitCount; // Ty 03/18/98 Added -frags support | ||
2310 | |||
2311 | void P_UpdateSpecials (void) | ||
2312 | { | ||
2313 | anim_t* anim; | ||
2314 | int pic; | ||
2315 | int i; | ||
2316 | |||
2317 | // Downcount level timer, exit level if elapsed | ||
2318 | if (levelTimer == true) | ||
2319 | { | ||
2320 | levelTimeCount--; | ||
2321 | if (!levelTimeCount) | ||
2322 | G_ExitLevel(); | ||
2323 | } | ||
2324 | |||
2325 | // Check frag counters, if frag limit reached, exit level // Ty 03/18/98 | ||
2326 | // Seems like the total frags should be kept in a simple | ||
2327 | // array somewhere, but until they are... | ||
2328 | if (levelFragLimit == true) // we used -frags so compare count | ||
2329 | { | ||
2330 | int k,m,fragcount,exitflag=false; | ||
2331 | for (k=0;k<MAXPLAYERS;k++) | ||
2332 | { | ||
2333 | if (!playeringame[k]) continue; | ||
2334 | fragcount = 0; | ||
2335 | for (m=0;m<MAXPLAYERS;m++) | ||
2336 | { | ||
2337 | if (!playeringame[m]) continue; | ||
2338 | fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m]; | ||
2339 | } | ||
2340 | if (fragcount >= levelFragLimitCount) exitflag = true; | ||
2341 | if (exitflag == true) break; // skip out of the loop--we're done | ||
2342 | } | ||
2343 | if (exitflag == true) | ||
2344 | G_ExitLevel(); | ||
2345 | } | ||
2346 | |||
2347 | // Animate flats and textures globally | ||
2348 | for (anim = anims ; anim < lastanim ; anim++) | ||
2349 | { | ||
2350 | for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++) | ||
2351 | { | ||
2352 | pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics ); | ||
2353 | if (anim->istexture) | ||
2354 | texturetranslation[i] = pic; | ||
2355 | else | ||
2356 | flattranslation[i] = pic; | ||
2357 | } | ||
2358 | } | ||
2359 | |||
2360 | // Check buttons (retriggerable switches) and change texture on timeout | ||
2361 | for (i = 0; i < MAXBUTTONS; i++) | ||
2362 | if (buttonlist[i].btimer) | ||
2363 | { | ||
2364 | buttonlist[i].btimer--; | ||
2365 | if (!buttonlist[i].btimer) | ||
2366 | { | ||
2367 | switch(buttonlist[i].where) | ||
2368 | { | ||
2369 | case top: | ||
2370 | sides[buttonlist[i].line->sidenum[0]].toptexture = | ||
2371 | buttonlist[i].btexture; | ||
2372 | break; | ||
2373 | |||
2374 | case middle: | ||
2375 | sides[buttonlist[i].line->sidenum[0]].midtexture = | ||
2376 | buttonlist[i].btexture; | ||
2377 | break; | ||
2378 | |||
2379 | case bottom: | ||
2380 | sides[buttonlist[i].line->sidenum[0]].bottomtexture = | ||
2381 | buttonlist[i].btexture; | ||
2382 | break; | ||
2383 | } | ||
2384 | { | ||
2385 | /* don't take the address of the switch's sound origin, | ||
2386 | * unless in a compatibility mode. */ | ||
2387 | mobj_t *so = (mobj_t *)buttonlist[i].soundorg; | ||
2388 | if (comp[comp_sound] || compatibility_level < prboom_6_compatibility) | ||
2389 | /* since the buttonlist array is usually zeroed out, | ||
2390 | * button popouts generally appear to come from (0,0) */ | ||
2391 | so = (mobj_t *)&buttonlist[i].soundorg; | ||
2392 | S_StartSound(so, sfx_swtchn); | ||
2393 | } | ||
2394 | memset(&buttonlist[i],0,sizeof(button_t)); | ||
2395 | } | ||
2396 | } | ||
2397 | } | ||
2398 | |||
2399 | ////////////////////////////////////////////////////////////////////// | ||
2400 | // | ||
2401 | // Sector and Line special thinker spawning at level startup | ||
2402 | // | ||
2403 | ////////////////////////////////////////////////////////////////////// | ||
2404 | |||
2405 | // | ||
2406 | // P_SpawnSpecials | ||
2407 | // After the map has been loaded, | ||
2408 | // scan for specials that spawn thinkers | ||
2409 | // | ||
2410 | |||
2411 | // Parses command line parameters. | ||
2412 | void P_SpawnSpecials (void) | ||
2413 | { | ||
2414 | sector_t* sector; | ||
2415 | int i; | ||
2416 | int episode; | ||
2417 | |||
2418 | episode = 1; | ||
2419 | if (W_CheckNumForName("texture2") >= 0) | ||
2420 | episode = 2; | ||
2421 | |||
2422 | // See if -timer needs to be used. | ||
2423 | levelTimer = false; | ||
2424 | |||
2425 | i = M_CheckParm("-avg"); // Austin Virtual Gaming 20 min timer on DM play | ||
2426 | if (i && deathmatch) | ||
2427 | { | ||
2428 | levelTimer = true; | ||
2429 | levelTimeCount = 20 * 60 * TICRATE; | ||
2430 | } | ||
2431 | |||
2432 | i = M_CheckParm("-timer"); // user defined timer on game play | ||
2433 | if (i && deathmatch) | ||
2434 | { | ||
2435 | int time; | ||
2436 | time = atoi(myargv[i+1]) * 60 * TICRATE; | ||
2437 | levelTimer = true; | ||
2438 | levelTimeCount = time; | ||
2439 | } | ||
2440 | |||
2441 | // See if -frags has been used | ||
2442 | levelFragLimit = false; | ||
2443 | i = M_CheckParm("-frags"); // Ty 03/18/98 Added -frags support | ||
2444 | if (i && deathmatch) | ||
2445 | { | ||
2446 | int frags; | ||
2447 | frags = atoi(myargv[i+1]); | ||
2448 | if (frags <= 0) frags = 10; // default 10 if no count provided | ||
2449 | levelFragLimit = true; | ||
2450 | levelFragLimitCount = frags; | ||
2451 | } | ||
2452 | |||
2453 | |||
2454 | // Init special sectors. | ||
2455 | sector = sectors; | ||
2456 | for (i=0 ; i<numsectors ; i++, sector++) | ||
2457 | { | ||
2458 | if (!sector->special) | ||
2459 | continue; | ||
2460 | |||
2461 | if (sector->special&SECRET_MASK) //jff 3/15/98 count extended | ||
2462 | totalsecret++; // secret sectors too | ||
2463 | |||
2464 | switch (sector->special&31) | ||
2465 | { | ||
2466 | case 1: | ||
2467 | // random off | ||
2468 | P_SpawnLightFlash (sector); | ||
2469 | break; | ||
2470 | |||
2471 | case 2: | ||
2472 | // strobe fast | ||
2473 | P_SpawnStrobeFlash(sector,FASTDARK,0); | ||
2474 | break; | ||
2475 | |||
2476 | case 3: | ||
2477 | // strobe slow | ||
2478 | P_SpawnStrobeFlash(sector,SLOWDARK,0); | ||
2479 | break; | ||
2480 | |||
2481 | case 4: | ||
2482 | // strobe fast/death slime | ||
2483 | P_SpawnStrobeFlash(sector,FASTDARK,0); | ||
2484 | sector->special |= 3<<DAMAGE_SHIFT; //jff 3/14/98 put damage bits in | ||
2485 | break; | ||
2486 | |||
2487 | case 8: | ||
2488 | // glowing light | ||
2489 | P_SpawnGlowingLight(sector); | ||
2490 | break; | ||
2491 | case 9: | ||
2492 | // secret sector | ||
2493 | if (sector->special<32) //jff 3/14/98 bits don't count unless not | ||
2494 | totalsecret++; // a generalized sector type | ||
2495 | break; | ||
2496 | |||
2497 | case 10: | ||
2498 | // door close in 30 seconds | ||
2499 | P_SpawnDoorCloseIn30 (sector); | ||
2500 | break; | ||
2501 | |||
2502 | case 12: | ||
2503 | // sync strobe slow | ||
2504 | P_SpawnStrobeFlash (sector, SLOWDARK, 1); | ||
2505 | break; | ||
2506 | |||
2507 | case 13: | ||
2508 | // sync strobe fast | ||
2509 | P_SpawnStrobeFlash (sector, FASTDARK, 1); | ||
2510 | break; | ||
2511 | |||
2512 | case 14: | ||
2513 | // door raise in 5 minutes | ||
2514 | P_SpawnDoorRaiseIn5Mins (sector, i); | ||
2515 | break; | ||
2516 | |||
2517 | case 17: | ||
2518 | // fire flickering | ||
2519 | P_SpawnFireFlicker(sector); | ||
2520 | break; | ||
2521 | } | ||
2522 | } | ||
2523 | |||
2524 | P_RemoveAllActiveCeilings(); // jff 2/22/98 use killough's scheme | ||
2525 | |||
2526 | P_RemoveAllActivePlats(); // killough | ||
2527 | |||
2528 | for (i = 0;i < MAXBUTTONS;i++) | ||
2529 | memset(&buttonlist[i],0,sizeof(button_t)); | ||
2530 | |||
2531 | // P_InitTagLists() must be called before P_FindSectorFromLineTag() | ||
2532 | // or P_FindLineFromLineTag() can be called. | ||
2533 | |||
2534 | P_InitTagLists(); // killough 1/30/98: Create xref tables for tags | ||
2535 | |||
2536 | P_SpawnScrollers(); // killough 3/7/98: Add generalized scrollers | ||
2537 | |||
2538 | P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs | ||
2539 | |||
2540 | P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs | ||
2541 | |||
2542 | for (i=0; i<numlines; i++) | ||
2543 | switch (lines[i].special) | ||
2544 | { | ||
2545 | int s, sec; | ||
2546 | |||
2547 | // killough 3/7/98: | ||
2548 | // support for drawn heights coming from different sector | ||
2549 | case 242: | ||
2550 | sec = sides[*lines[i].sidenum].sector-sectors; | ||
2551 | for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;) | ||
2552 | sectors[s].heightsec = sec; | ||
2553 | break; | ||
2554 | |||
2555 | // killough 3/16/98: Add support for setting | ||
2556 | // floor lighting independently (e.g. lava) | ||
2557 | case 213: | ||
2558 | sec = sides[*lines[i].sidenum].sector-sectors; | ||
2559 | for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;) | ||
2560 | sectors[s].floorlightsec = sec; | ||
2561 | break; | ||
2562 | |||
2563 | // killough 4/11/98: Add support for setting | ||
2564 | // ceiling lighting independently | ||
2565 | case 261: | ||
2566 | sec = sides[*lines[i].sidenum].sector-sectors; | ||
2567 | for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;) | ||
2568 | sectors[s].ceilinglightsec = sec; | ||
2569 | break; | ||
2570 | |||
2571 | // killough 10/98: | ||
2572 | // | ||
2573 | // Support for sky textures being transferred from sidedefs. | ||
2574 | // Allows scrolling and other effects (but if scrolling is | ||
2575 | // used, then the same sector tag needs to be used for the | ||
2576 | // sky sector, the sky-transfer linedef, and the scroll-effect | ||
2577 | // linedef). Still requires user to use F_SKY1 for the floor | ||
2578 | // or ceiling texture, to distinguish floor and ceiling sky. | ||
2579 | |||
2580 | case 271: // Regular sky | ||
2581 | case 272: // Same, only flipped | ||
2582 | for (s = -1; (s = P_FindSectorFromLineTag(lines+i,s)) >= 0;) | ||
2583 | sectors[s].sky = i | PL_SKYFLAT; | ||
2584 | break; | ||
2585 | } | ||
2586 | } | ||
2587 | |||
2588 | // killough 2/28/98: | ||
2589 | // | ||
2590 | // This function, with the help of r_plane.c and r_bsp.c, supports generalized | ||
2591 | // scrolling floors and walls, with optional mobj-carrying properties, e.g. | ||
2592 | // conveyor belts, rivers, etc. A linedef with a special type affects all | ||
2593 | // tagged sectors the same way, by creating scrolling and/or object-carrying | ||
2594 | // properties. Multiple linedefs may be used on the same sector and are | ||
2595 | // cumulative, although the special case of scrolling a floor and carrying | ||
2596 | // things on it, requires only one linedef. The linedef's direction determines | ||
2597 | // the scrolling direction, and the linedef's length determines the scrolling | ||
2598 | // speed. This was designed so that an edge around the sector could be used to | ||
2599 | // control the direction of the sector's scrolling, which is usually what is | ||
2600 | // desired. | ||
2601 | // | ||
2602 | // Process the active scrollers. | ||
2603 | // | ||
2604 | // This is the main scrolling code | ||
2605 | // killough 3/7/98 | ||
2606 | |||
2607 | void T_Scroll(scroll_t *s) | ||
2608 | { | ||
2609 | fixed_t dx = s->dx, dy = s->dy; | ||
2610 | |||
2611 | if (s->control != -1) | ||
2612 | { // compute scroll amounts based on a sector's height changes | ||
2613 | fixed_t height = sectors[s->control].floorheight + | ||
2614 | sectors[s->control].ceilingheight; | ||
2615 | fixed_t delta = height - s->last_height; | ||
2616 | s->last_height = height; | ||
2617 | dx = FixedMul(dx, delta); | ||
2618 | dy = FixedMul(dy, delta); | ||
2619 | } | ||
2620 | |||
2621 | // killough 3/14/98: Add acceleration | ||
2622 | if (s->accel) | ||
2623 | { | ||
2624 | s->vdx = dx += s->vdx; | ||
2625 | s->vdy = dy += s->vdy; | ||
2626 | } | ||
2627 | |||
2628 | if (!(dx | dy)) // no-op if both (x,y) offsets 0 | ||
2629 | return; | ||
2630 | |||
2631 | switch (s->type) | ||
2632 | { | ||
2633 | side_t *side; | ||
2634 | sector_t *sec; | ||
2635 | fixed_t height, waterheight; // killough 4/4/98: add waterheight | ||
2636 | msecnode_t *node; | ||
2637 | mobj_t *thing; | ||
2638 | |||
2639 | case sc_side: // killough 3/7/98: Scroll wall texture | ||
2640 | side = sides + s->affectee; | ||
2641 | side->textureoffset += dx; | ||
2642 | side->rowoffset += dy; | ||
2643 | break; | ||
2644 | |||
2645 | case sc_floor: // killough 3/7/98: Scroll floor texture | ||
2646 | sec = sectors + s->affectee; | ||
2647 | sec->floor_xoffs += dx; | ||
2648 | sec->floor_yoffs += dy; | ||
2649 | break; | ||
2650 | |||
2651 | case sc_ceiling: // killough 3/7/98: Scroll ceiling texture | ||
2652 | sec = sectors + s->affectee; | ||
2653 | sec->ceiling_xoffs += dx; | ||
2654 | sec->ceiling_yoffs += dy; | ||
2655 | break; | ||
2656 | |||
2657 | case sc_carry: | ||
2658 | |||
2659 | // killough 3/7/98: Carry things on floor | ||
2660 | // killough 3/20/98: use new sector list which reflects true members | ||
2661 | // killough 3/27/98: fix carrier bug | ||
2662 | // killough 4/4/98: Underwater, carry things even w/o gravity | ||
2663 | |||
2664 | sec = sectors + s->affectee; | ||
2665 | height = sec->floorheight; | ||
2666 | waterheight = sec->heightsec != -1 && | ||
2667 | sectors[sec->heightsec].floorheight > height ? | ||
2668 | sectors[sec->heightsec].floorheight : INT_MIN; | ||
2669 | |||
2670 | for (node = sec->touching_thinglist; node; node = node->m_snext) | ||
2671 | if (!((thing = node->m_thing)->flags & MF_NOCLIP) && | ||
2672 | (!(thing->flags & MF_NOGRAVITY || thing->z > height) || | ||
2673 | thing->z < waterheight)) | ||
2674 | { | ||
2675 | // Move objects only if on floor or underwater, | ||
2676 | // non-floating, and clipped. | ||
2677 | thing->momx += dx; | ||
2678 | thing->momy += dy; | ||
2679 | } | ||
2680 | break; | ||
2681 | |||
2682 | case sc_carry_ceiling: // to be added later | ||
2683 | break; | ||
2684 | } | ||
2685 | } | ||
2686 | |||
2687 | // | ||
2688 | // Add_Scroller() | ||
2689 | // | ||
2690 | // Add a generalized scroller to the thinker list. | ||
2691 | // | ||
2692 | // type: the enumerated type of scrolling: floor, ceiling, floor carrier, | ||
2693 | // wall, floor carrier & scroller | ||
2694 | // | ||
2695 | // (dx,dy): the direction and speed of the scrolling or its acceleration | ||
2696 | // | ||
2697 | // control: the sector whose heights control this scroller's effect | ||
2698 | // remotely, or -1 if no control sector | ||
2699 | // | ||
2700 | // affectee: the index of the affected object (sector or sidedef) | ||
2701 | // | ||
2702 | // accel: non-zero if this is an accelerative effect | ||
2703 | // | ||
2704 | |||
2705 | static void Add_Scroller(int type, fixed_t dx, fixed_t dy, | ||
2706 | int control, int affectee, int accel) | ||
2707 | { | ||
2708 | scroll_t *s = Z_Malloc(sizeof *s, PU_LEVSPEC, 0); | ||
2709 | s->thinker.function = T_Scroll; | ||
2710 | s->type = type; | ||
2711 | s->dx = dx; | ||
2712 | s->dy = dy; | ||
2713 | s->accel = accel; | ||
2714 | s->vdx = s->vdy = 0; | ||
2715 | if ((s->control = control) != -1) | ||
2716 | s->last_height = | ||
2717 | sectors[control].floorheight + sectors[control].ceilingheight; | ||
2718 | s->affectee = affectee; | ||
2719 | P_AddThinker(&s->thinker); | ||
2720 | } | ||
2721 | |||
2722 | // Adds wall scroller. Scroll amount is rotated with respect to wall's | ||
2723 | // linedef first, so that scrolling towards the wall in a perpendicular | ||
2724 | // direction is translated into vertical motion, while scrolling along | ||
2725 | // the wall in a parallel direction is translated into horizontal motion. | ||
2726 | // | ||
2727 | // killough 5/25/98: cleaned up arithmetic to avoid drift due to roundoff | ||
2728 | // | ||
2729 | // killough 10/98: | ||
2730 | // fix scrolling aliasing problems, caused by long linedefs causing overflowing | ||
2731 | |||
2732 | static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l, | ||
2733 | int control, int accel) | ||
2734 | { | ||
2735 | fixed_t x = D_abs(l->dx), y = D_abs(l->dy), d; | ||
2736 | if (y > x) | ||
2737 | d = x, x = y, y = d; | ||
2738 | d = FixedDiv(x, finesine[(tantoangle[FixedDiv(y,x) >> DBITS] + ANG90) | ||
2739 | >> ANGLETOFINESHIFT]); | ||
2740 | |||
2741 | // CPhipps - Import scroller calc overflow fix, compatibility optioned | ||
2742 | if (compatibility_level >= lxdoom_1_compatibility) { | ||
2743 | x = (fixed_t)(((int_64_t)dy * -(int_64_t)l->dy - (int_64_t)dx * (int_64_t)l->dx) / (int_64_t)d); // killough 10/98: | ||
2744 | y = (fixed_t)(((int_64_t)dy * (int_64_t)l->dx - (int_64_t)dx * (int_64_t)l->dy) / (int_64_t)d); // Use long long arithmetic | ||
2745 | } else { | ||
2746 | x = -FixedDiv(FixedMul(dy, l->dy) + FixedMul(dx, l->dx), d); | ||
2747 | y = -FixedDiv(FixedMul(dx, l->dy) - FixedMul(dy, l->dx), d); | ||
2748 | } | ||
2749 | Add_Scroller(sc_side, x, y, control, *l->sidenum, accel); | ||
2750 | } | ||
2751 | |||
2752 | // Amount (dx,dy) vector linedef is shifted right to get scroll amount | ||
2753 | #define SCROLL_SHIFT 5 | ||
2754 | |||
2755 | // Factor to scale scrolling effect into mobj-carrying properties = 3/32. | ||
2756 | // (This is so scrolling floors and objects on them can move at same speed.) | ||
2757 | #define CARRYFACTOR ((fixed_t)(FRACUNIT*.09375)) | ||
2758 | |||
2759 | // Initialize the scrollers | ||
2760 | static void P_SpawnScrollers(void) | ||
2761 | { | ||
2762 | int i; | ||
2763 | line_t *l = lines; | ||
2764 | |||
2765 | for (i=0;i<numlines;i++,l++) | ||
2766 | { | ||
2767 | fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling | ||
2768 | fixed_t dy = l->dy >> SCROLL_SHIFT; | ||
2769 | int control = -1, accel = 0; // no control sector or acceleration | ||
2770 | int special = l->special; | ||
2771 | |||
2772 | // killough 3/7/98: Types 245-249 are same as 250-254 except that the | ||
2773 | // first side's sector's heights cause scrolling when they change, and | ||
2774 | // this linedef controls the direction and speed of the scrolling. The | ||
2775 | // most complicated linedef since donuts, but powerful :) | ||
2776 | // | ||
2777 | // killough 3/15/98: Add acceleration. Types 214-218 are the same but | ||
2778 | // are accelerative. | ||
2779 | |||
2780 | if (special >= 245 && special <= 249) // displacement scrollers | ||
2781 | { | ||
2782 | special += 250-245; | ||
2783 | control = sides[*l->sidenum].sector - sectors; | ||
2784 | } | ||
2785 | else | ||
2786 | if (special >= 214 && special <= 218) // accelerative scrollers | ||
2787 | { | ||
2788 | accel = 1; | ||
2789 | special += 250-214; | ||
2790 | control = sides[*l->sidenum].sector - sectors; | ||
2791 | } | ||
2792 | |||
2793 | switch (special) | ||
2794 | { | ||
2795 | register int s; | ||
2796 | |||
2797 | case 250: // scroll effect ceiling | ||
2798 | for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;) | ||
2799 | Add_Scroller(sc_ceiling, -dx, dy, control, s, accel); | ||
2800 | break; | ||
2801 | |||
2802 | case 251: // scroll effect floor | ||
2803 | case 253: // scroll and carry objects on floor | ||
2804 | for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;) | ||
2805 | Add_Scroller(sc_floor, -dx, dy, control, s, accel); | ||
2806 | if (special != 253) | ||
2807 | break; | ||
2808 | |||
2809 | case 252: // carry objects on floor | ||
2810 | dx = FixedMul(dx,CARRYFACTOR); | ||
2811 | dy = FixedMul(dy,CARRYFACTOR); | ||
2812 | for (s=-1; (s = P_FindSectorFromLineTag(l,s)) >= 0;) | ||
2813 | Add_Scroller(sc_carry, dx, dy, control, s, accel); | ||
2814 | break; | ||
2815 | |||
2816 | // killough 3/1/98: scroll wall according to linedef | ||
2817 | // (same direction and speed as scrolling floors) | ||
2818 | case 254: | ||
2819 | for (s=-1; (s = P_FindLineFromLineTag(l,s)) >= 0;) | ||
2820 | if (s != i) | ||
2821 | Add_WallScroller(dx, dy, lines+s, control, accel); | ||
2822 | break; | ||
2823 | |||
2824 | case 255: // killough 3/2/98: scroll according to sidedef offsets | ||
2825 | s = lines[i].sidenum[0]; | ||
2826 | Add_Scroller(sc_side, -sides[s].textureoffset, | ||
2827 | sides[s].rowoffset, -1, s, accel); | ||
2828 | break; | ||
2829 | |||
2830 | case 48: // scroll first side | ||
2831 | Add_Scroller(sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel); | ||
2832 | break; | ||
2833 | |||
2834 | case 85: // jff 1/30/98 2-way scroll | ||
2835 | Add_Scroller(sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel); | ||
2836 | break; | ||
2837 | } | ||
2838 | } | ||
2839 | } | ||
2840 | |||
2841 | // e6y | ||
2842 | // restored boom's friction code | ||
2843 | |||
2844 | ///////////////////////////// | ||
2845 | // | ||
2846 | // Add a friction thinker to the thinker list | ||
2847 | // | ||
2848 | // Add_Friction adds a new friction thinker to the list of active thinkers. | ||
2849 | // | ||
2850 | |||
2851 | static void Add_Friction(int friction, int movefactor, int affectee) | ||
2852 | { | ||
2853 | friction_t *f = Z_Malloc(sizeof *f, PU_LEVSPEC, 0); | ||
2854 | |||
2855 | f->thinker.function/*.acp1*/ = /*(actionf_p1) */T_Friction; | ||
2856 | f->friction = friction; | ||
2857 | f->movefactor = movefactor; | ||
2858 | f->affectee = affectee; | ||
2859 | P_AddThinker(&f->thinker); | ||
2860 | } | ||
2861 | |||
2862 | ///////////////////////////// | ||
2863 | // | ||
2864 | // This is where abnormal friction is applied to objects in the sectors. | ||
2865 | // A friction thinker has been spawned for each sector where less or | ||
2866 | // more friction should be applied. The amount applied is proportional to | ||
2867 | // the length of the controlling linedef. | ||
2868 | |||
2869 | void T_Friction(friction_t *f) | ||
2870 | { | ||
2871 | sector_t *sec; | ||
2872 | mobj_t *thing; | ||
2873 | msecnode_t* node; | ||
2874 | |||
2875 | if (compatibility || !variable_friction) | ||
2876 | return; | ||
2877 | |||
2878 | sec = sectors + f->affectee; | ||
2879 | |||
2880 | // Be sure the special sector type is still turned on. If so, proceed. | ||
2881 | // Else, bail out; the sector type has been changed on us. | ||
2882 | |||
2883 | if (!(sec->special & FRICTION_MASK)) | ||
2884 | return; | ||
2885 | |||
2886 | // Assign the friction value to players on the floor, non-floating, | ||
2887 | // and clipped. Normally the object's friction value is kept at | ||
2888 | // ORIG_FRICTION and this thinker changes it for icy or muddy floors. | ||
2889 | |||
2890 | // In Phase II, you can apply friction to Things other than players. | ||
2891 | |||
2892 | // When the object is straddling sectors with the same | ||
2893 | // floorheight that have different frictions, use the lowest | ||
2894 | // friction value (muddy has precedence over icy). | ||
2895 | |||
2896 | node = sec->touching_thinglist; // things touching this sector | ||
2897 | while (node) | ||
2898 | { | ||
2899 | thing = node->m_thing; | ||
2900 | if (thing->player && | ||
2901 | !(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) && | ||
2902 | thing->z <= sec->floorheight) | ||
2903 | { | ||
2904 | if ((thing->friction == ORIG_FRICTION) || // normal friction? | ||
2905 | (f->friction < thing->friction)) | ||
2906 | { | ||
2907 | thing->friction = f->friction; | ||
2908 | thing->movefactor = f->movefactor; | ||
2909 | } | ||
2910 | } | ||
2911 | node = node->m_snext; | ||
2912 | } | ||
2913 | } | ||
2914 | |||
2915 | |||
2916 | // killough 3/7/98 -- end generalized scroll effects | ||
2917 | |||
2918 | //////////////////////////////////////////////////////////////////////////// | ||
2919 | // | ||
2920 | // FRICTION EFFECTS | ||
2921 | // | ||
2922 | // phares 3/12/98: Start of friction effects | ||
2923 | // | ||
2924 | // As the player moves, friction is applied by decreasing the x and y | ||
2925 | // momentum values on each tic. By varying the percentage of decrease, | ||
2926 | // we can simulate muddy or icy conditions. In mud, the player slows | ||
2927 | // down faster. In ice, the player slows down more slowly. | ||
2928 | // | ||
2929 | // The amount of friction change is controlled by the length of a linedef | ||
2930 | // with type 223. A length < 100 gives you mud. A length > 100 gives you ice. | ||
2931 | // | ||
2932 | // Also, each sector where these effects are to take place is given a | ||
2933 | // new special type _______. Changing the type value at runtime allows | ||
2934 | // these effects to be turned on or off. | ||
2935 | // | ||
2936 | // Sector boundaries present problems. The player should experience these | ||
2937 | // friction changes only when his feet are touching the sector floor. At | ||
2938 | // sector boundaries where floor height changes, the player can find | ||
2939 | // himself still 'in' one sector, but with his feet at the floor level | ||
2940 | // of the next sector (steps up or down). To handle this, Thinkers are used | ||
2941 | // in icy/muddy sectors. These thinkers examine each object that is touching | ||
2942 | // their sectors, looking for players whose feet are at the same level as | ||
2943 | // their floors. Players satisfying this condition are given new friction | ||
2944 | // values that are applied by the player movement code later. | ||
2945 | // | ||
2946 | // killough 8/28/98: | ||
2947 | // | ||
2948 | // Completely redid code, which did not need thinkers, and which put a heavy | ||
2949 | // drag on CPU. Friction is now a property of sectors, NOT objects inside | ||
2950 | // them. All objects, not just players, are affected by it, if they touch | ||
2951 | // the sector's floor. Code simpler and faster, only calling on friction | ||
2952 | // calculations when an object needs friction considered, instead of doing | ||
2953 | // friction calculations on every sector during every tic. | ||
2954 | // | ||
2955 | // Although this -might- ruin Boom demo sync involving friction, it's the only | ||
2956 | // way, short of code explosion, to fix the original design bug. Fixing the | ||
2957 | // design bug in Boom's original friction code, while maintaining demo sync | ||
2958 | // under every conceivable circumstance, would double or triple code size, and | ||
2959 | // would require maintenance of buggy legacy code which is only useful for old | ||
2960 | // demos. Doom demos, which are more important IMO, are not affected by this | ||
2961 | // change. | ||
2962 | // | ||
2963 | ///////////////////////////// | ||
2964 | // | ||
2965 | // Initialize the sectors where friction is increased or decreased | ||
2966 | |||
2967 | static void P_SpawnFriction(void) | ||
2968 | { | ||
2969 | int i; | ||
2970 | line_t *l = lines; | ||
2971 | |||
2972 | // killough 8/28/98: initialize all sectors to normal friction first | ||
2973 | for (i = 0; i < numsectors; i++) | ||
2974 | { | ||
2975 | sectors[i].friction = ORIG_FRICTION; | ||
2976 | sectors[i].movefactor = ORIG_FRICTION_FACTOR; | ||
2977 | } | ||
2978 | |||
2979 | for (i = 0 ; i < numlines ; i++,l++) | ||
2980 | if (l->special == 223) | ||
2981 | { | ||
2982 | int length = P_AproxDistance(l->dx,l->dy)>>FRACBITS; | ||
2983 | int friction = (0x1EB8*length)/0x80 + 0xD000; | ||
2984 | int movefactor, s; | ||
2985 | |||
2986 | // The following check might seem odd. At the time of movement, | ||
2987 | // the move distance is multiplied by 'friction/0x10000', so a | ||
2988 | // higher friction value actually means 'less friction'. | ||
2989 | |||
2990 | if (friction > ORIG_FRICTION) // ice | ||
2991 | movefactor = ((0x10092 - friction)*(0x70))/0x158; | ||
2992 | else | ||
2993 | movefactor = ((friction - 0xDB34)*(0xA))/0x80; | ||
2994 | |||
2995 | if (mbf_features) | ||
2996 | { // killough 8/28/98: prevent odd situations | ||
2997 | if (friction > FRACUNIT) | ||
2998 | friction = FRACUNIT; | ||
2999 | if (friction < 0) | ||
3000 | friction = 0; | ||
3001 | if (movefactor < 32) | ||
3002 | movefactor = 32; | ||
3003 | } | ||
3004 | |||
3005 | for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; ) | ||
3006 | { | ||
3007 | // killough 8/28/98: | ||
3008 | // | ||
3009 | // Instead of spawning thinkers, which are slow and expensive, | ||
3010 | // modify the sector's own friction values. Friction should be | ||
3011 | // a property of sectors, not objects which reside inside them. | ||
3012 | // Original code scanned every object in every friction sector | ||
3013 | // on every tic, adjusting its friction, putting unnecessary | ||
3014 | // drag on CPU. New code adjusts friction of sector only once | ||
3015 | // at level startup, and then uses this friction value. | ||
3016 | |||
3017 | //e6y: boom's friction code for boom compatibility | ||
3018 | if (!demo_compatibility && !mbf_features) | ||
3019 | Add_Friction(friction,movefactor,s); | ||
3020 | |||
3021 | sectors[s].friction = friction; | ||
3022 | sectors[s].movefactor = movefactor; | ||
3023 | } | ||
3024 | } | ||
3025 | } | ||
3026 | |||
3027 | // | ||
3028 | // phares 3/12/98: End of friction effects | ||
3029 | // | ||
3030 | //////////////////////////////////////////////////////////////////////////// | ||
3031 | |||
3032 | //////////////////////////////////////////////////////////////////////////// | ||
3033 | // | ||
3034 | // PUSH/PULL EFFECT | ||
3035 | // | ||
3036 | // phares 3/20/98: Start of push/pull effects | ||
3037 | // | ||
3038 | // This is where push/pull effects are applied to objects in the sectors. | ||
3039 | // | ||
3040 | // There are four kinds of push effects | ||
3041 | // | ||
3042 | // 1) Pushing Away | ||
3043 | // | ||
3044 | // Pushes you away from a point source defined by the location of an | ||
3045 | // MT_PUSH Thing. The force decreases linearly with distance from the | ||
3046 | // source. This force crosses sector boundaries and is felt w/in a circle | ||
3047 | // whose center is at the MT_PUSH. The force is felt only if the point | ||
3048 | // MT_PUSH can see the target object. | ||
3049 | // | ||
3050 | // 2) Pulling toward | ||
3051 | // | ||
3052 | // Same as Pushing Away except you're pulled toward an MT_PULL point | ||
3053 | // source. This force crosses sector boundaries and is felt w/in a circle | ||
3054 | // whose center is at the MT_PULL. The force is felt only if the point | ||
3055 | // MT_PULL can see the target object. | ||
3056 | // | ||
3057 | // 3) Wind | ||
3058 | // | ||
3059 | // Pushes you in a constant direction. Full force above ground, half | ||
3060 | // force on the ground, nothing if you're below it (water). | ||
3061 | // | ||
3062 | // 4) Current | ||
3063 | // | ||
3064 | // Pushes you in a constant direction. No force above ground, full | ||
3065 | // force if on the ground or below it (water). | ||
3066 | // | ||
3067 | // The magnitude of the force is controlled by the length of a controlling | ||
3068 | // linedef. The force vector for types 3 & 4 is determined by the angle | ||
3069 | // of the linedef, and is constant. | ||
3070 | // | ||
3071 | // For each sector where these effects occur, the sector special type has | ||
3072 | // to have the PUSH_MASK bit set. If this bit is turned off by a switch | ||
3073 | // at run-time, the effect will not occur. The controlling sector for | ||
3074 | // types 1 & 2 is the sector containing the MT_PUSH/MT_PULL Thing. | ||
3075 | |||
3076 | |||
3077 | #define PUSH_FACTOR 7 | ||
3078 | |||
3079 | ///////////////////////////// | ||
3080 | // | ||
3081 | // Add a push thinker to the thinker list | ||
3082 | |||
3083 | static void Add_Pusher(int type, int x_mag, int y_mag, mobj_t* source, int affectee) | ||
3084 | { | ||
3085 | pusher_t *p = Z_Malloc(sizeof *p, PU_LEVSPEC, 0); | ||
3086 | |||
3087 | p->thinker.function = T_Pusher; | ||
3088 | p->source = source; | ||
3089 | p->type = type; | ||
3090 | p->x_mag = x_mag>>FRACBITS; | ||
3091 | p->y_mag = y_mag>>FRACBITS; | ||
3092 | p->magnitude = P_AproxDistance(p->x_mag,p->y_mag); | ||
3093 | if (source) // point source exist? | ||
3094 | { | ||
3095 | p->radius = (p->magnitude)<<(FRACBITS+1); // where force goes to zero | ||
3096 | p->x = p->source->x; | ||
3097 | p->y = p->source->y; | ||
3098 | } | ||
3099 | p->affectee = affectee; | ||
3100 | P_AddThinker(&p->thinker); | ||
3101 | } | ||
3102 | |||
3103 | ///////////////////////////// | ||
3104 | // | ||
3105 | // PIT_PushThing determines the angle and magnitude of the effect. | ||
3106 | // The object's x and y momentum values are changed. | ||
3107 | // | ||
3108 | // tmpusher belongs to the point source (MT_PUSH/MT_PULL). | ||
3109 | // | ||
3110 | // killough 10/98: allow to affect things besides players | ||
3111 | |||
3112 | pusher_t* tmpusher; // pusher structure for blockmap searches | ||
3113 | |||
3114 | static boolean PIT_PushThing(mobj_t* thing) | ||
3115 | { | ||
3116 | /* killough 10/98: made more general */ | ||
3117 | if (!mbf_features ? | ||
3118 | thing->player && !(thing->flags & (MF_NOCLIP | MF_NOGRAVITY)) : | ||
3119 | (sentient(thing) || thing->flags & MF_SHOOTABLE) && | ||
3120 | !(thing->flags & MF_NOCLIP)) | ||
3121 | { | ||
3122 | angle_t pushangle; | ||
3123 | fixed_t speed; | ||
3124 | fixed_t sx = tmpusher->x; | ||
3125 | fixed_t sy = tmpusher->y; | ||
3126 | |||
3127 | speed = (tmpusher->magnitude - | ||
3128 | ((P_AproxDistance(thing->x - sx,thing->y - sy) | ||
3129 | >>FRACBITS)>>1))<<(FRACBITS-PUSH_FACTOR-1); | ||
3130 | |||
3131 | // killough 10/98: make magnitude decrease with square | ||
3132 | // of distance, making it more in line with real nature, | ||
3133 | // so long as it's still in range with original formula. | ||
3134 | // | ||
3135 | // Removes angular distortion, and makes effort required | ||
3136 | // to stay close to source, grow increasingly hard as you | ||
3137 | // get closer, as expected. Still, it doesn't consider z :( | ||
3138 | |||
3139 | if (speed > 0 && mbf_features) | ||
3140 | { | ||
3141 | int x = (thing->x-sx) >> FRACBITS; | ||
3142 | int y = (thing->y-sy) >> FRACBITS; | ||
3143 | speed = (int)(((uint_64_t) tmpusher->magnitude << 23) / (x*x+y*y+1)); | ||
3144 | } | ||
3145 | |||
3146 | // If speed <= 0, you're outside the effective radius. You also have | ||
3147 | // to be able to see the push/pull source point. | ||
3148 | |||
3149 | if (speed > 0 && P_CheckSight(thing,tmpusher->source)) | ||
3150 | { | ||
3151 | pushangle = R_PointToAngle2(thing->x,thing->y,sx,sy); | ||
3152 | if (tmpusher->source->type == MT_PUSH) | ||
3153 | pushangle += ANG180; // away | ||
3154 | pushangle >>= ANGLETOFINESHIFT; | ||
3155 | thing->momx += FixedMul(speed,finecosine[pushangle]); | ||
3156 | thing->momy += FixedMul(speed,finesine[pushangle]); | ||
3157 | } | ||
3158 | } | ||
3159 | return true; | ||
3160 | } | ||
3161 | |||
3162 | ///////////////////////////// | ||
3163 | // | ||
3164 | // T_Pusher looks for all objects that are inside the radius of | ||
3165 | // the effect. | ||
3166 | // | ||
3167 | |||
3168 | void T_Pusher(pusher_t *p) | ||
3169 | { | ||
3170 | sector_t *sec; | ||
3171 | mobj_t *thing; | ||
3172 | msecnode_t* node; | ||
3173 | int xspeed,yspeed; | ||
3174 | int xl,xh,yl,yh,bx,by; | ||
3175 | int radius; | ||
3176 | int ht = 0; | ||
3177 | |||
3178 | if (!allow_pushers) | ||
3179 | return; | ||
3180 | |||
3181 | sec = sectors + p->affectee; | ||
3182 | |||
3183 | // Be sure the special sector type is still turned on. If so, proceed. | ||
3184 | // Else, bail out; the sector type has been changed on us. | ||
3185 | |||
3186 | if (!(sec->special & PUSH_MASK)) | ||
3187 | return; | ||
3188 | |||
3189 | // For constant pushers (wind/current) there are 3 situations: | ||
3190 | // | ||
3191 | // 1) Affected Thing is above the floor. | ||
3192 | // | ||
3193 | // Apply the full force if wind, no force if current. | ||
3194 | // | ||
3195 | // 2) Affected Thing is on the ground. | ||
3196 | // | ||
3197 | // Apply half force if wind, full force if current. | ||
3198 | // | ||
3199 | // 3) Affected Thing is below the ground (underwater effect). | ||
3200 | // | ||
3201 | // Apply no force if wind, full force if current. | ||
3202 | |||
3203 | if (p->type == p_push) | ||
3204 | { | ||
3205 | |||
3206 | // Seek out all pushable things within the force radius of this | ||
3207 | // point pusher. Crosses sectors, so use blockmap. | ||
3208 | |||
3209 | tmpusher = p; // MT_PUSH/MT_PULL point source | ||
3210 | radius = p->radius; // where force goes to zero | ||
3211 | tmbbox[BOXTOP] = p->y + radius; | ||
3212 | tmbbox[BOXBOTTOM] = p->y - radius; | ||
3213 | tmbbox[BOXRIGHT] = p->x + radius; | ||
3214 | tmbbox[BOXLEFT] = p->x - radius; | ||
3215 | |||
3216 | xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; | ||
3217 | xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; | ||
3218 | yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; | ||
3219 | yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; | ||
3220 | for (bx=xl ; bx<=xh ; bx++) | ||
3221 | for (by=yl ; by<=yh ; by++) | ||
3222 | P_BlockThingsIterator(bx,by,PIT_PushThing); | ||
3223 | return; | ||
3224 | } | ||
3225 | |||
3226 | // constant pushers p_wind and p_current | ||
3227 | |||
3228 | if (sec->heightsec != -1) // special water sector? | ||
3229 | ht = sectors[sec->heightsec].floorheight; | ||
3230 | node = sec->touching_thinglist; // things touching this sector | ||
3231 | for ( ; node ; node = node->m_snext) | ||
3232 | { | ||
3233 | thing = node->m_thing; | ||
3234 | if (!thing->player || (thing->flags & (MF_NOGRAVITY | MF_NOCLIP))) | ||
3235 | continue; | ||
3236 | if (p->type == p_wind) | ||
3237 | { | ||
3238 | if (sec->heightsec == -1) // NOT special water sector | ||
3239 | if (thing->z > thing->floorz) // above ground | ||
3240 | { | ||
3241 | xspeed = p->x_mag; // full force | ||
3242 | yspeed = p->y_mag; | ||
3243 | } | ||
3244 | else // on ground | ||
3245 | { | ||
3246 | xspeed = (p->x_mag)>>1; // half force | ||
3247 | yspeed = (p->y_mag)>>1; | ||
3248 | } | ||
3249 | else // special water sector | ||
3250 | { | ||
3251 | if (thing->z > ht) // above ground | ||
3252 | { | ||
3253 | xspeed = p->x_mag; // full force | ||
3254 | yspeed = p->y_mag; | ||
3255 | } | ||
3256 | else if (thing->player->viewz < ht) // underwater | ||
3257 | xspeed = yspeed = 0; // no force | ||
3258 | else // wading in water | ||
3259 | { | ||
3260 | xspeed = (p->x_mag)>>1; // half force | ||
3261 | yspeed = (p->y_mag)>>1; | ||
3262 | } | ||
3263 | } | ||
3264 | } | ||
3265 | else // p_current | ||
3266 | { | ||
3267 | if (sec->heightsec == -1) // NOT special water sector | ||
3268 | if (thing->z > sec->floorheight) // above ground | ||
3269 | xspeed = yspeed = 0; // no force | ||
3270 | else // on ground | ||
3271 | { | ||
3272 | xspeed = p->x_mag; // full force | ||
3273 | yspeed = p->y_mag; | ||
3274 | } | ||
3275 | else // special water sector | ||
3276 | if (thing->z > ht) // above ground | ||
3277 | xspeed = yspeed = 0; // no force | ||
3278 | else // underwater | ||
3279 | { | ||
3280 | xspeed = p->x_mag; // full force | ||
3281 | yspeed = p->y_mag; | ||
3282 | } | ||
3283 | } | ||
3284 | thing->momx += xspeed<<(FRACBITS-PUSH_FACTOR); | ||
3285 | thing->momy += yspeed<<(FRACBITS-PUSH_FACTOR); | ||
3286 | } | ||
3287 | } | ||
3288 | |||
3289 | ///////////////////////////// | ||
3290 | // | ||
3291 | // P_GetPushThing() returns a pointer to an MT_PUSH or MT_PULL thing, | ||
3292 | // NULL otherwise. | ||
3293 | |||
3294 | mobj_t* P_GetPushThing(int s) | ||
3295 | { | ||
3296 | mobj_t* thing; | ||
3297 | sector_t* sec; | ||
3298 | |||
3299 | sec = sectors + s; | ||
3300 | thing = sec->thinglist; | ||
3301 | while (thing) | ||
3302 | { | ||
3303 | switch(thing->type) | ||
3304 | { | ||
3305 | case MT_PUSH: | ||
3306 | case MT_PULL: | ||
3307 | return thing; | ||
3308 | default: | ||
3309 | break; | ||
3310 | } | ||
3311 | thing = thing->snext; | ||
3312 | } | ||
3313 | return NULL; | ||
3314 | } | ||
3315 | |||
3316 | ///////////////////////////// | ||
3317 | // | ||
3318 | // Initialize the sectors where pushers are present | ||
3319 | // | ||
3320 | |||
3321 | static void P_SpawnPushers(void) | ||
3322 | { | ||
3323 | int i; | ||
3324 | line_t *l = lines; | ||
3325 | register int s; | ||
3326 | mobj_t* thing; | ||
3327 | |||
3328 | for (i = 0 ; i < numlines ; i++,l++) | ||
3329 | switch(l->special) | ||
3330 | { | ||
3331 | case 224: // wind | ||
3332 | for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; ) | ||
3333 | Add_Pusher(p_wind,l->dx,l->dy,NULL,s); | ||
3334 | break; | ||
3335 | case 225: // current | ||
3336 | for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; ) | ||
3337 | Add_Pusher(p_current,l->dx,l->dy,NULL,s); | ||
3338 | break; | ||
3339 | case 226: // push/pull | ||
3340 | for (s = -1; (s = P_FindSectorFromLineTag(l,s)) >= 0 ; ) | ||
3341 | { | ||
3342 | thing = P_GetPushThing(s); | ||
3343 | if (thing) // No MT_P* means no effect | ||
3344 | Add_Pusher(p_push,l->dx,l->dy,thing,s); | ||
3345 | } | ||
3346 | break; | ||
3347 | } | ||
3348 | } | ||
3349 | |||
3350 | // | ||
3351 | // phares 3/20/98: End of Pusher effects | ||
3352 | // | ||
3353 | //////////////////////////////////////////////////////////////////////////// | ||