1 /** @file p.spec.cpp Map special effects.
2 *
3 * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4 * @authors Copyright © 2005-2014 Daniel Swanson <danij@dengine.net>
5 * @authors Copyright © 2003-2005 Samuel Villarreal <svkaiser@gmail.com>
6 * @authors Copyright © 1993-1996 id Software, Inc.
7 *
8 * @par License
9 * GPL: http://www.gnu.org/licenses/gpl.html
10 *
11 * <small>This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. This program is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details. You should have received a copy of the GNU
18 * General Public License along with this program; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA</small>
21 */
22
23 #include "jdoom64.h"
24 #include "p_spec.h"
25
26 #include <cstdio>
27 #include <cstring>
28 #include "gamesession.h"
29 #include "d_net.h"
30 #include "d_netsv.h"
31 #include "dmu_lib.h"
32 #include "m_argv.h"
33 #include "p_ceiling.h"
34 #include "p_door.h"
35 #include "p_floor.h"
36 #include "p_mapsetup.h"
37 #include "p_mapspec.h"
38 #include "p_plat.h"
39 #include "p_scroll.h"
40 #include "p_switch.h"
41 #include "p_tick.h"
42 #include "player.h"
43
44 static void P_CrossSpecialLine(Line *line, int side, mobj_t *thing);
45 static void P_ShootSpecialLine(mobj_t *thing, Line *line);
46
P_ActivateLine(Line * ld,mobj_t * mo,int side,int actType)47 dd_bool P_ActivateLine(Line *ld, mobj_t *mo, int side, int actType)
48 {
49 // Clients do not activate lines.
50 if(IS_CLIENT) return false;
51
52 switch(actType)
53 {
54 case SPAC_CROSS:
55 P_CrossSpecialLine(ld, side, mo);
56 return true;
57
58 case SPAC_USE:
59 return P_UseSpecialLine(mo, ld, side);
60
61 case SPAC_IMPACT:
62 P_ShootSpecialLine(mo, ld);
63 return true;
64
65 default:
66 DENG2_ASSERT(!"P_ActivateLine: Unknown activation type");
67 break;
68 }
69
70 return false;
71 }
72
73 /**
74 * Called every time a thing origin is about to cross a line with a non 0 special.
75 */
P_CrossSpecialLine(Line * line,int side,mobj_t * thing)76 static void P_CrossSpecialLine(Line *line, int side, mobj_t *thing)
77 {
78 // Extended functionality overrides old.
79 if(XL_CrossLine(line, side, thing)) return;
80
81 xline_t *xline = P_ToXLine(line);
82
83 // Triggers that other things can activate
84 if(!thing->player)
85 {
86 dd_bool ok = false;
87
88 // Things that should NOT trigger specials...
89 switch(thing->type)
90 {
91 case MT_ROCKET:
92 case MT_PLASMA:
93 case MT_BFG:
94 case MT_TROOPSHOT:
95 case MT_HEADSHOT:
96 case MT_BRUISERSHOT:
97 case MT_BRUISERSHOTRED: // jd64
98 case MT_NTROSHOT: // jd64
99 return;
100
101 default: break;
102 }
103
104 switch(xline->special)
105 {
106 case 39: ///< TELEPORT TRIGGER
107 case 97: ///< TELEPORT RETRIGGER
108 case 993: // jd64
109 case 125: ///< TELEPORT MONSTERONLY TRIGGER
110 case 126: ///< TELEPORT MONSTERONLY RETRIGGER
111 case 4: ///< RAISE DOOR
112 case 10: ///< PLAT DOWN-WAIT-UP-STAY TRIGGER
113 case 88: ///< PLAT DOWN-WAIT-UP-STAY RETRIGGER
114 case 415: // jd64
115 ok = true;
116 break;
117 }
118
119 // Anything can trigger this line!
120 if(xline->flags & ML_ALLTRIGGER)
121 ok = true;
122
123 if(!ok) return;
124 }
125
126 // Note: could use some const's here.
127 switch(xline->special)
128 {
129 // TRIGGERS.
130 // All from here to RETRIGGERS.
131 case 2:
132 // Open Door
133 EV_DoDoor(line, DT_OPEN);
134 xline->special = 0;
135 break;
136
137 case 3:
138 // Close Door
139 EV_DoDoor(line, DT_CLOSE);
140 xline->special = 0;
141 break;
142
143 case 4:
144 // Raise Door
145 EV_DoDoor(line, DT_NORMAL);
146 xline->special = 0;
147 break;
148
149 case 5:
150 // Raise Floor
151 EV_DoFloor(line, FT_RAISEFLOOR);
152 xline->special = 0;
153 break;
154
155 case 6:
156 // Fast Ceiling Crush & Raise
157 EV_DoCeiling(line, CT_CRUSHANDRAISEFAST);
158 xline->special = 0;
159 break;
160
161 case 8:
162 // Build Stairs
163 EV_BuildStairs(line, build8);
164 xline->special = 0;
165 break;
166
167 case 10:
168 // PlatDownWaitUp
169 EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0);
170 xline->special = 0;
171 break;
172
173 case 12:
174 // Light Turn On - brightest near
175 EV_LightTurnOn(line, 0);
176 xline->special = 0;
177 break;
178
179 case 13:
180 // Light Turn On - max
181 EV_LightTurnOn(line, 1);
182 xline->special = 0;
183 break;
184
185 case 16:
186 // Close Door 30
187 EV_DoDoor(line, DT_CLOSE30THENOPEN);
188 xline->special = 0;
189 break;
190
191 case 17:
192 // Start Light Strobing
193 EV_StartLightStrobing(line);
194 xline->special = 0;
195 break;
196
197 case 19:
198 // Lower Floor
199 EV_DoFloor(line, FT_LOWER);
200 xline->special = 0;
201 break;
202
203 case 22:
204 // Raise floor to nearest height and change texture
205 EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0);
206 xline->special = 0;
207 break;
208
209 case 25:
210 // Ceiling Crush and Raise
211 EV_DoCeiling(line, CT_CRUSHANDRAISE);
212 xline->special = 0;
213 break;
214
215 case 30:
216 // Raise floor to shortest texture height
217 // on either side of lines.
218 EV_DoFloor(line, FT_RAISETOTEXTURE);
219 xline->special = 0;
220 break;
221
222 case 35:
223 // Lights Very Dark
224 EV_LightTurnOn(line, 35.0f/255.0f);
225 xline->special = 0;
226 break;
227
228 case 36:
229 // Lower Floor (TURBO)
230 EV_DoFloor(line, FT_LOWERTURBO);
231 xline->special = 0;
232 break;
233
234 case 37:
235 // LowerAndChange
236 EV_DoFloor(line, FT_LOWERANDCHANGE);
237 xline->special = 0;
238 break;
239
240 case 38:
241 // Lower Floor To Lowest
242 EV_DoFloor(line, FT_LOWERTOLOWEST);
243 xline->special = 0;
244 break;
245
246 case 420: // jd64
247 EV_DoFloorAndCeiling(line, FT_TOHIGHESTPLUS8, CT_RAISETOHIGHEST);
248 xline->special = 0;
249 break;
250
251 case 430: // jd64
252 EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP);
253 break;
254
255 case 431: // jd64
256 EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP);
257 xline->special = 0;
258 break;
259
260 case 426: // jd64
261 EV_DoCeiling(line, CT_CUSTOM);
262 break;
263
264 case 427: // jd64
265 EV_DoCeiling(line, CT_CUSTOM);
266 xline->special = 0;
267 break;
268
269 case 991: // jd64
270 // TELEPORT!
271 EV_FadeSpawn(line, thing);
272 xline->special = 0;
273 break;
274
275 case 993: // jd64
276 if(!thing->player)
277 EV_FadeSpawn(line, thing);
278 xline->special = 0;
279 break;
280
281 case 992: // jd64
282 // Lower Ceiling to Floor
283 if(EV_DoCeiling(line, CT_LOWERTOFLOOR))
284 {
285 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
286 xline->special = 0;
287 }
288 break;
289
290 case 994: // jd64
291 /// @todo Might as well do this with XG.
292 /// Also, export this text string to DED.
293 P_SetMessage(thing->player, "You've found a secret area!");
294 thing->player->secretCount++;
295 thing->player->update |= PSF_COUNTERS;
296 xline->special = 0;
297 break;
298
299 case 995: // jd64
300 /// @todo Might as well do this with XG.
301 P_SetMessage(thing->player, "You've found a shrine!");
302 xline->special = 0;
303 break;
304
305 case 998: // jd64
306 // BE GONE!
307 EV_FadeAway(line, thing);
308 xline->special = 0;
309 break;
310
311 case 39:
312 // TELEPORT!
313 EV_Teleport(line, side, thing, true);
314 xline->special = 0;
315 break;
316
317 case 40:
318 // RaiseCeilingLowerFloor
319 EV_DoCeiling(line, CT_RAISETOHIGHEST);
320 EV_DoFloor(line, FT_LOWERTOLOWEST);
321 xline->special = 0;
322 break;
323
324 case 44:
325 // Ceiling Crush
326 EV_DoCeiling(line, CT_LOWERANDCRUSH);
327 xline->special = 0;
328 break;
329
330 case 52:
331 // EXIT!
332 G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next"));
333 break;
334
335 case 53:
336 // Perpetual Platform Raise
337 EV_DoPlat(line, PT_PERPETUALRAISE, 0);
338 xline->special = 0;
339 break;
340
341 case 54:
342 // Platform Stop
343 P_PlatDeactivate(xline->tag);
344 xline->special = 0;
345 break;
346
347 case 56:
348 // Raise Floor Crush
349 EV_DoFloor(line, FT_RAISEFLOORCRUSH);
350 xline->special = 0;
351 break;
352
353 case 57:
354 // Ceiling Crush Stop
355 P_CeilingDeactivate(xline->tag);
356 xline->special = 0;
357 break;
358
359 case 58:
360 // Raise Floor 24
361 EV_DoFloor(line, FT_RAISE24);
362 xline->special = 0;
363 break;
364
365 case 59:
366 // Raise Floor 24 And Change
367 EV_DoFloor(line, FT_RAISE24ANDCHANGE);
368 xline->special = 0;
369 break;
370
371 case 104:
372 // Turn lights off in sector(tag)
373 EV_TurnTagLightsOff(line);
374 xline->special = 0;
375 break;
376
377 case 108:
378 // Blazing Door Raise (faster than TURBO!)
379 EV_DoDoor(line, DT_BLAZERAISE);
380 xline->special = 0;
381 break;
382
383 case 109:
384 // Blazing Door Open (faster than TURBO!)
385 EV_DoDoor(line, DT_BLAZEOPEN);
386 xline->special = 0;
387 break;
388
389 case 100:
390 // Build Stairs Turbo 16
391 EV_BuildStairs(line, turbo16);
392 xline->special = 0;
393 break;
394
395 case 110:
396 // Blazing Door Close (faster than TURBO!)
397 EV_DoDoor(line, DT_BLAZECLOSE);
398 xline->special = 0;
399 break;
400
401 case 119:
402 // Raise floor to nearest surr. floor
403 EV_DoFloor(line, FT_RAISEFLOORTONEAREST);
404 xline->special = 0;
405 break;
406
407 case 121:
408 // Blazing PlatDownWaitUpStay
409 EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0);
410 xline->special = 0;
411 break;
412
413 case 124:
414 // Secret EXIT
415 G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true);
416 break;
417
418 case 125:
419 // TELEPORT MonsterONLY
420 if(!thing->player)
421 {
422 EV_Teleport(line, side, thing, true);
423 xline->special = 0;
424 }
425 break;
426
427 case 130:
428 // Raise Floor Turbo
429 EV_DoFloor(line, FT_RAISEFLOORTURBO);
430 xline->special = 0;
431 break;
432
433 case 141:
434 // Silent Ceiling Crush & Raise
435 EV_DoCeiling(line, CT_SILENTCRUSHANDRAISE);
436 xline->special = 0;
437 break;
438
439 // RETRIGGERS. All from here till end.
440 case 72:
441 // Ceiling Crush
442 EV_DoCeiling(line, CT_LOWERANDCRUSH);
443 break;
444
445 case 73:
446 // Ceiling Crush and Raise
447 EV_DoCeiling(line, CT_CRUSHANDRAISE);
448 break;
449
450 case 74:
451 // Ceiling Crush Stop
452 P_CeilingDeactivate(xline->tag);
453 break;
454
455 case 75:
456 // Close Door
457 EV_DoDoor(line, DT_CLOSE);
458 break;
459
460 case 76:
461 // Close Door 30
462 EV_DoDoor(line, DT_CLOSE30THENOPEN);
463 break;
464
465 case 77:
466 // Fast Ceiling Crush & Raise
467 EV_DoCeiling(line, CT_CRUSHANDRAISEFAST);
468 break;
469
470 case 79:
471 // Lights Very Dark
472 EV_LightTurnOn(line, 35.0f/255.0f);
473 break;
474
475 case 80:
476 // Light Turn On - brightest near
477 EV_LightTurnOn(line, 0);
478 break;
479
480 case 81:
481 // Light Turn On - max
482 EV_LightTurnOn(line, 1);
483 break;
484
485 case 82:
486 // Lower Floor To Lowest
487 EV_DoFloor(line, FT_LOWERTOLOWEST);
488 break;
489
490 case 83:
491 // Lower Floor
492 EV_DoFloor(line, FT_LOWER);
493 break;
494
495 case 84:
496 // LowerAndChange
497 EV_DoFloor(line, FT_LOWERANDCHANGE);
498 break;
499
500 case 86:
501 // Open Door
502 EV_DoDoor(line, DT_OPEN);
503 break;
504
505 case 87:
506 // Perpetual Platform Raise
507 EV_DoPlat(line, PT_PERPETUALRAISE, 0);
508 break;
509
510 case 88:
511 // PlatDownWaitUp
512 EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0);
513 break;
514
515 case 415: // jd64
516 if(thing->player)
517 EV_DoPlat(line, PT_UPWAITDOWNSTAY, 0);
518 break;
519
520 case 89:
521 // Platform Stop
522 P_PlatDeactivate(xline->tag);
523 break;
524
525 case 90:
526 // Raise Door
527 EV_DoDoor(line, DT_NORMAL);
528 break;
529
530 case 91:
531 // Raise Floor
532 EV_DoFloor(line, FT_RAISEFLOOR);
533 break;
534
535 case 92:
536 // Raise Floor 24
537 EV_DoFloor(line, FT_RAISE24);
538 break;
539
540 case 93:
541 // Raise Floor 24 And Change
542 EV_DoFloor(line, FT_RAISE24ANDCHANGE);
543 break;
544
545 case 94:
546 // Raise Floor Crush
547 EV_DoFloor(line, FT_RAISEFLOORCRUSH);
548 break;
549
550 case 95:
551 // Raise floor to nearest height
552 // and change texture.
553 EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0);
554 break;
555
556 case 96:
557 // Raise floor to shortest texture height
558 // on either side of lines.
559 EV_DoFloor(line, FT_RAISETOTEXTURE);
560 break;
561
562 case 97:
563 // TELEPORT!
564 EV_Teleport(line, side, thing, true);
565 break;
566
567 case 423: // jd64
568 // TELEPORT! (no fog)
569 // FIXME: DJS - might as well do this in XG.
570 EV_Teleport(line, side, thing, false);
571 break;
572
573 case 98:
574 // Lower Floor (TURBO)
575 EV_DoFloor(line, FT_LOWERTURBO);
576 break;
577
578 case 105:
579 // Blazing Door Raise (faster than TURBO!)
580 EV_DoDoor(line, DT_BLAZERAISE);
581 break;
582
583 case 106:
584 // Blazing Door Open (faster than TURBO!)
585 EV_DoDoor(line, DT_BLAZEOPEN);
586 break;
587
588 case 107:
589 // Blazing Door Close (faster than TURBO!)
590 EV_DoDoor(line, DT_BLAZECLOSE);
591 break;
592
593 case 120:
594 // Blazing PlatDownWaitUpStay.
595 EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0);
596 break;
597
598 case 126:
599 // TELEPORT MonsterONLY.
600 if(!thing->player)
601 EV_Teleport(line, side, thing, true);
602 break;
603
604 case 128:
605 // Raise To Nearest Floor
606 EV_DoFloor(line, FT_RAISEFLOORTONEAREST);
607 break;
608
609 case 129:
610 // Raise Floor Turbo
611 EV_DoFloor(line, FT_RAISEFLOORTURBO);
612 break;
613
614 case 155: // jd64
615 // Raise Floor 512
616 // FIXME: DJS - again, might as well do this in XG.
617 if(EV_DoFloor(line, FT_RAISE32))
618 {
619 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
620 P_ToXLine(line)->special = 0;
621 }
622 break;
623 }
624 }
625
626 /**
627 * Called when a thing shoots a special line.
628 */
P_ShootSpecialLine(mobj_t * thing,Line * line)629 static void P_ShootSpecialLine(mobj_t *thing, Line *line)
630 {
631 xline_t *xline = P_ToXLine(line);
632
633 // Impacts that other things can activate.
634 if(!thing->player)
635 {
636 switch(xline->special)
637 {
638 default: return;
639
640 case 46: ///< OPEN DOOR IMPACT
641 break;
642 }
643 }
644
645 switch(xline->special)
646 {
647 case 24: ///< RAISE FLOOR
648 EV_DoFloor(line, FT_RAISEFLOOR);
649 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
650 xline->special = 0;
651 break;
652
653 case 46: ///< OPEN DOOR
654 EV_DoDoor(line, DT_OPEN);
655 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
656 break;
657
658 case 47: ///< RAISE FLOOR NEAR AND CHANGE
659 EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0);
660 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
661 xline->special = 0;
662 break;
663
664 case 191: ///< LOWER FLOOR WAIT RAISE (jd64)
665 EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0);
666 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
667 break;
668 }
669 }
670
671 /**
672 * Called every tic frame that the player origin is in a special sector
673 */
P_PlayerInSpecialSector(player_t * player)674 void P_PlayerInSpecialSector(player_t *player)
675 {
676 Sector *sector = Mobj_Sector(player->plr->mo);
677
678 if(IS_CLIENT) return;
679
680 // Falling, not all the way down yet?
681 if(!FEQUAL(player->plr->mo->origin[VZ], P_GetDoublep(sector, DMU_FLOOR_HEIGHT))) return;
682
683 // Has hitten ground.
684 switch(P_ToXSector(sector)->special)
685 {
686 default: break;
687
688 case 5: ///< HELLSLIME DAMAGE
689 if(!player->powers[PT_IRONFEET])
690 if(!(mapTime & 0x1f))
691 P_DamageMobj(player->plr->mo, NULL, NULL, 10, false);
692 break;
693
694 case 7: ///< NUKAGE DAMAGE
695 if(!player->powers[PT_IRONFEET])
696 if(!(mapTime & 0x1f))
697 P_DamageMobj(player->plr->mo, NULL, NULL, 5, false);
698 break;
699
700 case 16: ///< SUPER HELLSLIME DAMAGE
701 case 4: ///< STROBE HURT
702 if(!player->powers[PT_IRONFEET] || (P_Random() < 5))
703 {
704 if(!(mapTime & 0x1f))
705 P_DamageMobj(player->plr->mo, NULL, NULL, 20, false);
706 }
707 break;
708
709 case 9: ///< SECRET SECTOR
710 player->secretCount++;
711 P_ToXSector(sector)->special = 0;
712 if(cfg.secretMsg)
713 {
714 P_SetMessage(player, "You've found a secret area!");
715 // S_ConsoleSound(SFX_SECRET, 0, player - players); // jd64
716 }
717 break;
718 }
719 }
720
721 /**
722 * d64tc
723 */
P_ThunderSector()724 void P_ThunderSector()
725 {
726 if(!(P_Random() < 10)) return;
727
728 iterlist_t *list = P_GetSectorIterListForTag(20000, false);
729 if(!list) return;
730
731 IterList_SetIteratorDirection(list, ITERLIST_FORWARD);
732 IterList_RewindIterator(list);
733
734 Sector *sec;
735 while((sec = (Sector *)IterList_MoveIterator(list)))
736 {
737 if(!(mapTime & 32))
738 {
739 P_SetFloatp(sec, DMU_LIGHT_LEVEL, 1);
740 }
741 }
742
743 S_StartSound(SFX_SSSIT | DDSF_NO_ATTENUATION, NULL);
744 }
745
P_SpawnSectorSpecialThinkers()746 void P_SpawnSectorSpecialThinkers()
747 {
748 // Clients spawn specials only on the server's instruction.
749 if(IS_CLIENT) return;
750
751 for(int i = 0; i < numsectors; ++i)
752 {
753 Sector *sec = (Sector *)P_ToPtr(DMU_SECTOR, i);
754 xsector_t *xsec = P_ToXSector(sec);
755
756 // XG sector types override the game's built-in types.
757 if(xsec->xg) continue;
758
759 // jd64 >
760 // DJS - yet more hacks! Why use the tag?
761 switch(xsec->tag)
762 {
763 default: break;
764
765 case 10000:
766 case 10001:
767 case 10002:
768 case 10003:
769 case 10004:
770 P_SpawnGlowingLight(sec);
771 break;
772
773 case 11000:
774 P_SpawnLightFlash(sec);
775 break;
776
777 case 12000:
778 P_SpawnFireFlicker(sec);
779 break;
780
781 case 13000:
782 P_SpawnLightBlink(sec);
783 break;
784
785 case 20000:
786 P_SpawnGlowingLight(sec);
787 break;
788 }
789 // < d64tc
790
791 switch(xsec->special)
792 {
793 default: break;
794
795 case 1: ///< FLICKERING LIGHTS
796 P_SpawnLightFlash(sec);
797 break;
798
799 case 2: ///< STROBE FAST
800 P_SpawnStrobeFlash(sec, FASTDARK, 0);
801 break;
802
803 case 3: ///< STROBE SLOW
804 P_SpawnStrobeFlash(sec, SLOWDARK, 0);
805 break;
806
807 case 4: ///< STROBE FAST/DEATH SLIME
808 P_SpawnStrobeFlash(sec, FASTDARK, 0);
809 xsec->special = 4;
810 break;
811
812 case 8: ///< GLOWING LIGHT
813 P_SpawnGlowingLight(sec);
814 break;
815
816 case 10: ///< DOOR CLOSE IN 30 SECONDS
817 P_SpawnDoorCloseIn30(sec);
818 break;
819
820 case 12: ///< SYNC STROBE SLOW
821 P_SpawnStrobeFlash(sec, SLOWDARK, 1);
822 break;
823
824 case 13: ///< SYNC STROBE FAST
825 P_SpawnStrobeFlash(sec, FASTDARK, 1);
826 break;
827
828 case 14: ///< DOOR RAISE IN 5 MINUTES
829 P_SpawnDoorRaiseIn5Mins(sec);
830 break;
831
832 case 17:
833 P_SpawnFireFlicker(sec);
834 break;
835 }
836 }
837 }
838
P_SpawnLineSpecialThinkers()839 void P_SpawnLineSpecialThinkers()
840 {
841 // Stub.
842 }
843
P_SpawnAllSpecialThinkers()844 void P_SpawnAllSpecialThinkers()
845 {
846 P_SpawnSectorSpecialThinkers();
847 P_SpawnLineSpecialThinkers();
848 }
849
P_UseSpecialLine2(mobj_t * mo,Line * line,int side)850 dd_bool P_UseSpecialLine2(mobj_t *mo, Line *line, int side)
851 {
852 xline_t *xline = P_ToXLine(line);
853
854 // Err...
855 // Use the back sides of VERY SPECIAL lines...
856 if(side)
857 {
858 switch(xline->special)
859 {
860 case 124: // Sliding door open&close (unused).
861 break;
862
863 default: return false;
864 }
865 }
866
867 // Switches that other things can activate.
868 if(!mo->player)
869 {
870 // Never open secret doors.
871 if(xline->flags & ML_SECRET)
872 return false;
873
874 switch(xline->special)
875 {
876 case 1: // MANUAL DOOR RAISE
877 case 32: // MANUAL BLUE
878 case 33: // MANUAL RED
879 case 34: // MANUAL YELLOW
880 break;
881
882 default:
883 return false;
884 break;
885 }
886 }
887
888 // Do something.
889 switch(xline->special)
890 {
891 // MANUALS
892 case 1: // Vertical Door
893 case 26: // Blue Door/Locked
894 case 27: // Yellow Door /Locked
895 case 28: // Red Door /Locked
896
897 case 31: // Manual door open
898 case 32: // Blue locked door open
899 case 33: // Red locked door open
900 case 34: // Yellow locked door open
901
902 case 117: // Blazing door raise
903 case 118: // Blazing door open
904 case 525: // jd64
905 case 526: // jd64
906 case 527: // jd64
907 EV_VerticalDoor(line, mo);
908 break;
909
910 //UNUSED - Door Slide Open&Close
911 // case 124:
912 // EV_SlidingDoor (line, mo);
913 // break;
914
915 // SWITCHES
916 case 7:
917 // Build Stairs,
918 if(EV_BuildStairs(line, build8))
919 {
920 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
921 xline->special = 0;
922 }
923 break;
924
925 case 9:
926 // Change Donut,
927 if(EV_DoDonut(line))
928 {
929 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
930 xline->special = 0;
931 }
932 break;
933
934 case 11:
935 // Exit level,
936 if(cyclingMaps && mapCycleNoExit)
937 break;
938
939 // Prevent zombies from exiting levels,
940 if(mo->player && mo->player->health <= 0 && !cfg.zombiesCanExit)
941 {
942 S_StartSound(SFX_NOWAY, mo);
943 return false;
944 }
945
946 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_SWTCHX, false, 0);
947 xline->special = 0;
948 G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next"));
949 break;
950
951 case 14:
952 // Raise Floor 32 and change texture.
953 if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32))
954 {
955 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
956 xline->special = 0;
957 }
958 break;
959
960 case 15:
961 // Raise Floor 24 and change texture.
962 if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24))
963 {
964 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
965 xline->special = 0;
966 }
967 break;
968
969 case 18:
970 // Raise Floor to next highest floor.
971 if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST))
972 {
973 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
974 xline->special = 0;
975 }
976 break;
977
978 case 20:
979 // Raise Plat next highest floor and change texture.
980 if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0))
981 {
982 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
983 xline->special = 0;
984 }
985 break;
986
987 case 21:
988 // PlatDownWaitUpStay.
989 if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0))
990 {
991 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
992 xline->special = 0;
993 }
994 break;
995
996 case 23:
997 // Lower Floor to Lowest.
998 if(EV_DoFloor(line, FT_LOWERTOLOWEST))
999 {
1000 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1001 xline->special = 0;
1002 }
1003 break;
1004
1005 case 29:
1006 // Raise Door.
1007 if(EV_DoDoor(line, DT_NORMAL))
1008 {
1009 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1010 xline->special = 0;
1011 }
1012 break;
1013
1014 case 41:
1015 // Lower Ceiling to Floor.
1016 if(EV_DoCeiling(line, CT_LOWERTOFLOOR))
1017 {
1018 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1019 xline->special = 0;
1020 }
1021 break;
1022
1023 case 71:
1024 // Turbo Lower Floor.
1025 if(EV_DoFloor(line, FT_LOWERTURBO))
1026 {
1027 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1028 xline->special = 0;
1029 }
1030 break;
1031
1032 case 49:
1033 // Ceiling Crush And Raise.
1034 if(EV_DoCeiling(line, CT_CRUSHANDRAISE))
1035 {
1036 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1037 xline->special = 0;
1038 }
1039 break;
1040
1041 case 50:
1042 // Close Door.
1043 if(EV_DoDoor(line, DT_CLOSE))
1044 {
1045 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1046 xline->special = 0;
1047 }
1048 break;
1049
1050 case 51:
1051 // Secret EXIT.
1052 if(cyclingMaps && mapCycleNoExit)
1053 break;
1054
1055 // Prevent zombies from exiting levels.
1056 if(mo->player && mo->player->health <= 0 && !cfg.zombiesCanExit)
1057 {
1058 S_StartSound(SFX_NOWAY, mo);
1059 return false;
1060 }
1061
1062 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1063 xline->special = 0;
1064 G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true);
1065 break;
1066
1067 case 55:
1068 // Raise Floor Crush.
1069 if(EV_DoFloor(line, FT_RAISEFLOORCRUSH))
1070 {
1071 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1072 xline->special = 0;
1073 }
1074 break;
1075
1076 case 101:
1077 // Raise Floor.
1078 if(EV_DoFloor(line, FT_RAISEFLOOR))
1079 {
1080 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1081 xline->special = 0;
1082 }
1083 break;
1084
1085 case 102:
1086 // Lower Floor to Surrounding floor height.
1087 if(EV_DoFloor(line, FT_LOWER))
1088 {
1089 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1090 xline->special = 0;
1091 }
1092 break;
1093
1094 case 103:
1095 // Open Door.
1096 if(EV_DoDoor(line, DT_OPEN))
1097 {
1098 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1099 xline->special = 0;
1100 }
1101 break;
1102
1103 case 111:
1104 // Blazing Door Raise (faster than TURBO!).
1105 if(EV_DoDoor(line, DT_BLAZERAISE))
1106 {
1107 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1108 xline->special = 0;
1109 }
1110 break;
1111
1112 case 112:
1113 // Blazing Door Open (faster than TURBO!).
1114 if(EV_DoDoor(line, DT_BLAZEOPEN))
1115 {
1116 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1117 xline->special = 0;
1118 }
1119 break;
1120
1121 case 113:
1122 // Blazing Door Close (faster than TURBO!).
1123 if(EV_DoDoor(line, DT_BLAZECLOSE))
1124 {
1125 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1126 xline->special = 0;
1127 }
1128 break;
1129
1130 case 122:
1131 // Blazing PlatDownWaitUpStay.
1132 if(EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0))
1133 {
1134 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1135 xline->special = 0;
1136 }
1137 break;
1138
1139 case 127:
1140 // Build Stairs Turbo 16.
1141 if(EV_BuildStairs(line, turbo16))
1142 {
1143 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1144 xline->special = 0;
1145 }
1146 break;
1147
1148 case 131:
1149 // Raise Floor Turbo.
1150 if(EV_DoFloor(line, FT_RAISEFLOORTURBO))
1151 {
1152 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1153 xline->special = 0;
1154 }
1155 break;
1156
1157 case 133:
1158 // BlzOpenDoor BLUE.
1159 case 135:
1160 // BlzOpenDoor RED.
1161 case 137:
1162 // BlzOpenDoor YELLOW.
1163 if(EV_DoLockedDoor(line, DT_BLAZEOPEN, mo))
1164 {
1165 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1166 xline->special = 0;
1167 }
1168 break;
1169
1170 case 140:
1171 // Raise Floor 512.
1172 if(EV_DoFloor(line, FT_RAISE512))
1173 {
1174 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1175 xline->special = 0;
1176 }
1177 break;
1178
1179 // BUTTONS
1180 case 42:
1181 // Close Door.
1182 if(EV_DoDoor(line, DT_CLOSE))
1183 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1184 break;
1185
1186 case 43:
1187 // Lower Ceiling to Floor.
1188 if(EV_DoCeiling(line, CT_LOWERTOFLOOR))
1189 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1190 break;
1191
1192 case 45:
1193 // Lower Floor to Surrounding floor height.
1194 if(EV_DoFloor(line, FT_LOWER))
1195 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1196 break;
1197
1198 case 60:
1199 // Lower Floor to Lowest.
1200 if(EV_DoFloor(line, FT_LOWERTOLOWEST))
1201 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1202 break;
1203
1204 case 61:
1205 // Open Door.
1206 if(EV_DoDoor(line, DT_OPEN))
1207 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1208 break;
1209
1210 case 62:
1211 // PlatDownWaitUpStay.
1212 if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 1))
1213 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1214 break;
1215
1216 case 63:
1217 // Raise Door.
1218 if(EV_DoDoor(line, DT_NORMAL))
1219 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1220 break;
1221
1222 case 64:
1223 // Raise Floor to ceiling.
1224 if(EV_DoFloor(line, FT_RAISEFLOOR))
1225 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1226 break;
1227
1228 case 66:
1229 // Raise Floor 24 and change texture.
1230 if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24))
1231 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1232 break;
1233
1234 case 67:
1235 // Raise Floor 32 and change texture.
1236 if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32))
1237 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1238 break;
1239
1240 case 65:
1241 // Raise Floor Crush.
1242 if(EV_DoFloor(line, FT_RAISEFLOORCRUSH))
1243 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1244 break;
1245
1246 case 68:
1247 // Raise Plat to next highest floor and change texture.
1248 if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0))
1249 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1250 break;
1251
1252 case 69:
1253 // Raise Floor to next highest floor.
1254 if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST))
1255 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1256 break;
1257
1258 case 70:
1259 // Turbo Lower Floor.
1260 if(EV_DoFloor(line, FT_LOWERTURBO))
1261 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1262 break;
1263
1264 case 114:
1265 // Blazing Door Raise (faster than TURBO!).
1266 if(EV_DoDoor(line, DT_BLAZERAISE))
1267 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1268 break;
1269
1270 case 115:
1271 // Blazing Door Open (faster than TURBO!).
1272 if(EV_DoDoor(line, DT_BLAZEOPEN))
1273 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1274 break;
1275
1276 case 116:
1277 // Blazing Door Close (faster than TURBO!).
1278 if(EV_DoDoor(line, DT_BLAZECLOSE))
1279 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1280 break;
1281
1282 case 123:
1283 // Blazing PlatDownWaitUpStay.
1284 if(EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0))
1285 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1286 break;
1287
1288 case 132:
1289 // Raise Floor Turbo.
1290 if(EV_DoFloor(line, FT_RAISEFLOORTURBO))
1291 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1292 break;
1293
1294 case 99:
1295 // BlzOpenDoor BLUE.
1296 case 134:
1297 // BlzOpenDoor RED.
1298 case 136:
1299 // BlzOpenDoor YELLOW.
1300 if(EV_DoLockedDoor(line, DT_BLAZERAISE, mo)) // jd64 was "DT_BLAZEOPEN"
1301 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1302 break;
1303
1304 case 138:
1305 // Light Turn On.
1306 EV_LightTurnOn(line, 1);
1307 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1308 break;
1309
1310 case 139:
1311 // Light Turn Off.
1312 EV_LightTurnOn(line, 35.0f/255.0f);
1313 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1314 break;
1315
1316 case 343: // jd64 - BlzOpenDoor LaserPowerup 1.
1317 case 344: // jd64 - BlzOpenDoor LaserPowerup 2.
1318 case 345: // jd64 - BlzOpenDoor LaserPowerup 3.
1319 if(EV_DoLockedDoor(line, DT_BLAZEOPEN, mo))
1320 {
1321 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1322 xline->special = 0;
1323 }
1324 break;
1325
1326 case 414: // jd64
1327 if(EV_DoPlat(line, PT_UPWAITDOWNSTAY, 1))
1328 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1329 break;
1330
1331 case 416: // jd64
1332 if(EV_DoFloorAndCeiling(line, FT_TOHIGHESTPLUS8, CT_RAISETOHIGHEST))
1333 {
1334 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1335 xline->special = 0;
1336 }
1337 break;
1338
1339 case 424: // jd64
1340 if(EV_DoCeiling(line, CT_CUSTOM))
1341 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1342 break;
1343
1344 case 425: // jd64
1345 if(EV_DoCeiling(line, CT_CUSTOM))
1346 {
1347 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1348 xline->special = 0;
1349 }
1350 break;
1351
1352 case 428: // jd64
1353 if(EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP))
1354 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, BUTTONTIME);
1355 break;
1356
1357 case 429: // jd64
1358 if(EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP))
1359 {
1360 P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0);
1361 xline->special = 0;
1362 }
1363 break;
1364 }
1365
1366 return true;
1367 }
1368