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