aboutsummaryrefslogtreecommitdiff
path: root/src/p_doors.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/p_doors.c')
-rw-r--r--src/p_doors.c711
1 files changed, 711 insertions, 0 deletions
diff --git a/src/p_doors.c b/src/p_doors.c
new file mode 100644
index 0000000..ba9561c
--- /dev/null
+++ b/src/p_doors.c
@@ -0,0 +1,711 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Door animation code (opening/closing)
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "p_spec.h"
36#include "p_tick.h"
37#include "s_sound.h"
38#include "sounds.h"
39#include "r_main.h"
40#include "dstrings.h"
41#include "d_deh.h" // Ty 03/27/98 - externalized
42#include "lprintf.h"
43
44///////////////////////////////////////////////////////////////
45//
46// Door action routines, called once per tick
47//
48///////////////////////////////////////////////////////////////
49
50//
51// T_VerticalDoor
52//
53// Passed a door structure containing all info about the door.
54// See P_SPEC.H for fields.
55// Returns nothing.
56//
57// jff 02/08/98 all cases with labels beginning with gen added to support
58// generalized line type behaviors.
59
60void T_VerticalDoor (vldoor_t* door)
61{
62 result_e res;
63
64 // Is the door waiting, going up, or going down?
65 switch(door->direction)
66 {
67 case 0:
68 // Door is waiting
69 if (!--door->topcountdown) // downcount and check
70 {
71 switch(door->type)
72 {
73 case blazeRaise:
74 case genBlazeRaise:
75 door->direction = -1; // time to go back down
76 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
77 break;
78
79 case normal:
80 case genRaise:
81 door->direction = -1; // time to go back down
82 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
83 break;
84
85 case close30ThenOpen:
86 case genCdO:
87 door->direction = 1; // time to go back up
88 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
89 break;
90
91 case genBlazeCdO:
92 door->direction = 1; // time to go back up
93 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
94 break;
95
96 default:
97 break;
98 }
99 }
100 break;
101
102 case 2:
103 // Special case for sector type door that opens in 5 mins
104 if (!--door->topcountdown) // 5 minutes up?
105 {
106 switch(door->type)
107 {
108 case raiseIn5Mins:
109 door->direction = 1; // time to raise then
110 door->type = normal; // door acts just like normal 1 DR door now
111 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
112 break;
113
114 default:
115 break;
116 }
117 }
118 break;
119
120 case -1:
121 // Door is moving down
122 res = T_MovePlane
123 (
124 door->sector,
125 door->speed,
126 door->sector->floorheight,
127 false,
128 1,
129 door->direction
130 );
131
132 /* killough 10/98: implement gradual lighting effects */
133 // e6y: "Tagged doors don't trigger special lighting" handled wrong
134 // http://sourceforge.net/tracker/index.php?func=detail&aid=1411400&group_id=148658&atid=772943
135 // Old code: if (door->lighttag && door->topheight - door->sector->floorheight)
136 if (door->lighttag && door->topheight - door->sector->floorheight && compatibility_level >= mbf_compatibility)
137 EV_LightTurnOnPartway(door->line,
138 FixedDiv(door->sector->ceilingheight -
139 door->sector->floorheight,
140 door->topheight -
141 door->sector->floorheight));
142
143 // handle door reaching bottom
144 if (res == pastdest)
145 {
146 switch(door->type)
147 {
148 // regular open and close doors are all done, remove them
149 case blazeRaise:
150 case blazeClose:
151 case genBlazeRaise:
152 case genBlazeClose:
153 door->sector->ceilingdata = NULL; //jff 2/22/98
154 P_RemoveThinker (&door->thinker); // unlink and free
155 // killough 4/15/98: remove double-closing sound of blazing doors
156 if (comp[comp_blazing])
157 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
158 break;
159
160 case normal:
161 case close:
162 case genRaise:
163 case genClose:
164 door->sector->ceilingdata = NULL; //jff 2/22/98
165 P_RemoveThinker (&door->thinker); // unlink and free
166 break;
167
168 // close then open doors start waiting
169 case close30ThenOpen:
170 door->direction = 0;
171 door->topcountdown = TICRATE*30;
172 break;
173
174 case genCdO:
175 case genBlazeCdO:
176 door->direction = 0;
177 door->topcountdown = door->topwait; // jff 5/8/98 insert delay
178 break;
179
180 default:
181 break;
182 }
183 // e6y: "Tagged doors don't trigger special lighting" handled wrong
184 // http://sourceforge.net/tracker/index.php?func=detail&aid=1411400&group_id=148658&atid=772943
185 if (door->lighttag && door->topheight - door->sector->floorheight && compatibility_level < mbf_compatibility)
186 EV_LightTurnOnPartway(door->line,0);
187 }
188 /* jff 1/31/98 turn lighting off in tagged sectors of manual doors
189 * killough 10/98: replaced with gradual lighting code
190 */
191 else if (res == crushed) // handle door meeting obstruction on way down
192 {
193 switch(door->type)
194 {
195 case genClose:
196 case genBlazeClose:
197 case blazeClose:
198 case close: // Close types do not bounce, merely wait
199 break;
200
201 case blazeRaise:
202 case genBlazeRaise:
203 door->direction = 1;
204 if (!comp[comp_blazing]) {
205 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
206 break;
207 }
208
209 default: // other types bounce off the obstruction
210 door->direction = 1;
211 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
212 break;
213 }
214 }
215 break;
216
217 case 1:
218 // Door is moving up
219 res = T_MovePlane
220 (
221 door->sector,
222 door->speed,
223 door->topheight,
224 false,
225 1,
226 door->direction
227 );
228
229 /* killough 10/98: implement gradual lighting effects */
230 // e6y: "Tagged doors don't trigger special lighting" handled wrong
231 // http://sourceforge.net/tracker/index.php?func=detail&aid=1411400&group_id=148658&atid=772943
232 // Old code: if (door->lighttag && door->topheight - door->sector->floorheight)
233 if (door->lighttag && door->topheight - door->sector->floorheight && compatibility_level >= mbf_compatibility)
234 EV_LightTurnOnPartway(door->line,
235 FixedDiv(door->sector->ceilingheight -
236 door->sector->floorheight,
237 door->topheight -
238 door->sector->floorheight));
239
240 // handle door reaching the top
241 if (res == pastdest)
242 {
243 switch(door->type)
244 {
245 case blazeRaise: // regular open/close doors start waiting
246 case normal:
247 case genRaise:
248 case genBlazeRaise:
249 door->direction = 0; // wait at top with delay
250 door->topcountdown = door->topwait;
251 break;
252
253 case close30ThenOpen: // close and close/open doors are done
254 case blazeOpen:
255 case open:
256 case genBlazeOpen:
257 case genOpen:
258 case genCdO:
259 case genBlazeCdO:
260 door->sector->ceilingdata = NULL; //jff 2/22/98
261 P_RemoveThinker (&door->thinker); // unlink and free
262 break;
263
264 default:
265 break;
266 }
267
268 /* jff 1/31/98 turn lighting on in tagged sectors of manual doors
269 * killough 10/98: replaced with gradual lighting code */
270 // e6y: "Tagged doors don't trigger special lighting" handled wrong
271 // http://sourceforge.net/tracker/index.php?func=detail&aid=1411400&group_id=148658&atid=772943
272 if (door->lighttag && door->topheight - door->sector->floorheight && compatibility_level < mbf_compatibility)
273 EV_LightTurnOnPartway(door->line,FRACUNIT);
274 }
275 break;
276 }
277}
278
279///////////////////////////////////////////////////////////////
280//
281// Door linedef handlers
282//
283///////////////////////////////////////////////////////////////
284
285//
286// EV_DoLockedDoor
287//
288// Handle opening a tagged locked door
289//
290// Passed the line activating the door, the type of door,
291// and the thing that activated the line
292// Returns true if a thinker created
293//
294int EV_DoLockedDoor
295( line_t* line,
296 vldoor_e type,
297 mobj_t* thing )
298{
299 player_t* p;
300
301 // only players can open locked doors
302 p = thing->player;
303 if (!p)
304 return 0;
305
306 // check type of linedef, and if key is possessed to open it
307 switch(line->special)
308 {
309 case 99: // Blue Lock
310 case 133:
311 if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
312 {
313 p->message = s_PD_BLUEO; // Ty 03/27/98 - externalized
314 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
315 return 0;
316 }
317 break;
318
319 case 134: // Red Lock
320 case 135:
321 if (!p->cards[it_redcard] && !p->cards[it_redskull])
322 {
323 p->message = s_PD_REDO; // Ty 03/27/98 - externalized
324 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
325 return 0;
326 }
327 break;
328
329 case 136: // Yellow Lock
330 case 137:
331 if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull])
332 {
333 p->message = s_PD_YELLOWO; // Ty 03/27/98 - externalized
334 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
335 return 0;
336 }
337 break;
338 }
339
340 // got the key, so open the door
341 return EV_DoDoor(line,type);
342}
343
344
345//
346// EV_DoDoor
347//
348// Handle opening a tagged door
349//
350// Passed the line activating the door and the type of door
351// Returns true if a thinker created
352//
353int EV_DoDoor
354( line_t* line,
355 vldoor_e type )
356{
357 int secnum,rtn;
358 sector_t* sec;
359 vldoor_t* door;
360
361 secnum = -1;
362 rtn = 0;
363
364 // open all doors with the same tag as the activating line
365 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
366 {
367 sec = &sectors[secnum];
368 // if the ceiling already moving, don't start the door action
369 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
370 continue;
371
372 // new door thinker
373 rtn = 1;
374 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
375 memset(door, 0, sizeof(*door));
376 P_AddThinker (&door->thinker);
377 sec->ceilingdata = door; //jff 2/22/98
378
379 door->thinker.function = T_VerticalDoor;
380 door->sector = sec;
381 door->type = type;
382 door->topwait = VDOORWAIT;
383 door->speed = VDOORSPEED;
384 door->line = line; // jff 1/31/98 remember line that triggered us
385 door->lighttag = 0; /* killough 10/98: no light effects with tagged doors */
386
387 // setup door parameters according to type of door
388 switch(type)
389 {
390 case blazeClose:
391 door->topheight = P_FindLowestCeilingSurrounding(sec);
392 door->topheight -= 4*FRACUNIT;
393 door->direction = -1;
394 door->speed = VDOORSPEED * 4;
395 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
396 break;
397
398 case close:
399 door->topheight = P_FindLowestCeilingSurrounding(sec);
400 door->topheight -= 4*FRACUNIT;
401 door->direction = -1;
402 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
403 break;
404
405 case close30ThenOpen:
406 door->topheight = sec->ceilingheight;
407 door->direction = -1;
408 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
409 break;
410
411 case blazeRaise:
412 case blazeOpen:
413 door->direction = 1;
414 door->topheight = P_FindLowestCeilingSurrounding(sec);
415 door->topheight -= 4*FRACUNIT;
416 door->speed = VDOORSPEED * 4;
417 if (door->topheight != sec->ceilingheight)
418 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
419 break;
420
421 case normal:
422 case open:
423 door->direction = 1;
424 door->topheight = P_FindLowestCeilingSurrounding(sec);
425 door->topheight -= 4*FRACUNIT;
426 if (door->topheight != sec->ceilingheight)
427 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
428 break;
429
430 default:
431 break;
432 }
433 }
434 return rtn;
435}
436
437
438//
439// EV_VerticalDoor
440//
441// Handle opening a door manually, no tag value
442//
443// Passed the line activating the door and the thing activating it
444// Returns true if a thinker created
445//
446// jff 2/12/98 added int return value, fixed all returns
447//
448int EV_VerticalDoor
449( line_t* line,
450 mobj_t* thing )
451{
452 player_t* player;
453 int secnum;
454 sector_t* sec;
455 vldoor_t* door;
456
457 // Check for locks
458 player = thing->player;
459
460 switch(line->special)
461 {
462 case 26: // Blue Lock
463 case 32:
464 if ( !player )
465 return 0;
466 if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
467 {
468 player->message = s_PD_BLUEK; // Ty 03/27/98 - externalized
469 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
470 return 0;
471 }
472 break;
473
474 case 27: // Yellow Lock
475 case 34:
476 if ( !player )
477 return 0;
478 if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull])
479 {
480 player->message = s_PD_YELLOWK; // Ty 03/27/98 - externalized
481 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
482 return 0;
483 }
484 break;
485
486 case 28: // Red Lock
487 case 33:
488 if ( !player )
489 return 0;
490 if (!player->cards[it_redcard] && !player->cards[it_redskull])
491 {
492 player->message = s_PD_REDK; // Ty 03/27/98 - externalized
493 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
494 return 0;
495 }
496 break;
497
498 default:
499 break;
500 }
501
502 // if the wrong side of door is pushed, give oof sound
503 if (line->sidenum[1]==NO_INDEX) // killough
504 {
505 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
506 return 0;
507 }
508
509 // get the sector on the second side of activating linedef
510 sec = sides[line->sidenum[1]].sector;
511 secnum = sec-sectors;
512
513 /* if door already has a thinker, use it
514 * cph 2001/04/05 -
515 * Ok, this is a disaster area. We're assuming that sec->ceilingdata
516 * is a vldoor_t! What if this door is controlled by both DR lines
517 * and by switches? I don't know how to fix that.
518 * Secondly, original Doom didn't distinguish floor/lighting/ceiling
519 * actions, so we need to do the same in demo compatibility mode.
520 */
521 door = sec->ceilingdata;
522 if (demo_compatibility) {
523 if (!door) door = sec->floordata;
524 if (!door) door = sec->lightingdata;
525 }
526 /* If this is a repeatable line, and the door is already moving, then we can just reverse the current action. Note that in prboom 2.3.0 I erroneously removed the if-this-is-repeatable check, hence the prboom_4_compatibility clause below (foolishly assumed that already moving implies repeatable - but it could be moving due to another switch, e.g. lv19-509) */
527 if (door &&
528 ((compatibility_level == prboom_4_compatibility) ||
529 (line->special == 1) || (line->special == 117) || (line->special == 26) || (line->special == 27) || (line->special == 28)
530 )
531 ) {
532 /* For old demos we have to emulate the old buggy behavior and
533 * mess up non-T_VerticalDoor actions.
534 */
535 if (compatibility_level < prboom_4_compatibility ||
536 door->thinker.function == T_VerticalDoor) {
537 /* cph - we are writing outval to door->direction iff it is non-zero */
538 signed int outval = 0;
539
540 /* An already moving repeatable door which is being re-pressed, or a
541 * monster is trying to open a closing door - so change direction
542 * DEMOSYNC: we only read door->direction now if it really is a door.
543 */
544 if (door->thinker.function == T_VerticalDoor && door->direction == -1) {
545 outval = 1; /* go back up */
546 } else if (player) {
547 outval = -1; /* go back down */
548 }
549
550 /* Write this to the thinker. In demo compatibility mode, we might be
551 * overwriting a field of a non-vldoor_t thinker - we need to add any
552 * other thinker types here if any demos depend on specific fields
553 * being corrupted by this.
554 */
555 if (outval) {
556 if (door->thinker.function == T_VerticalDoor) {
557 door->direction = outval;
558 } else if (door->thinker.function == T_PlatRaise) {
559 plat_t* p = (plat_t*)door;
560 p->wait = outval;
561 } else {
562 lprintf(LO_DEBUG, "EV_VerticalDoor: unknown thinker.function in thinker corruption emulation");
563 }
564
565 return 1;
566 }
567 }
568 /* Either we're in prboom >=v2.3 and it's not a door, or it's a door but
569 * we're a monster and don't want to shut it; exit with no action.
570 */
571 return 0;
572 }
573
574 // emit proper sound
575 switch(line->special)
576 {
577 case 117: // blazing door raise
578 case 118: // blazing door open
579 S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
580 break;
581
582 default: // normal or locked door sound
583 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
584 break;
585 }
586
587 // new door thinker
588 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
589 memset(door, 0, sizeof(*door));
590 P_AddThinker (&door->thinker);
591 sec->ceilingdata = door; //jff 2/22/98
592 door->thinker.function = T_VerticalDoor;
593 door->sector = sec;
594 door->direction = 1;
595 door->speed = VDOORSPEED;
596 door->topwait = VDOORWAIT;
597 door->line = line; // jff 1/31/98 remember line that triggered us
598
599 /* killough 10/98: use gradual lighting changes if nonzero tag given */
600 door->lighttag = comp[comp_doorlight] ? 0 : line->tag;
601
602 // set the type of door from the activating linedef type
603 switch(line->special)
604 {
605 case 1:
606 case 26:
607 case 27:
608 case 28:
609 door->type = normal;
610 break;
611
612 case 31:
613 case 32:
614 case 33:
615 case 34:
616 door->type = open;
617 line->special = 0;
618 break;
619
620 case 117: // blazing door raise
621 door->type = blazeRaise;
622 door->speed = VDOORSPEED*4;
623 break;
624 case 118: // blazing door open
625 door->type = blazeOpen;
626 line->special = 0;
627 door->speed = VDOORSPEED*4;
628 break;
629
630 default:
631 door->lighttag = 0; // killough 10/98
632 break;
633 }
634
635 // find the top and bottom of the movement range
636 door->topheight = P_FindLowestCeilingSurrounding(sec);
637 door->topheight -= 4*FRACUNIT;
638 return 1;
639}
640
641
642///////////////////////////////////////////////////////////////
643//
644// Sector type door spawners
645//
646///////////////////////////////////////////////////////////////
647
648//
649// P_SpawnDoorCloseIn30()
650//
651// Spawn a door that closes after 30 seconds (called at level init)
652//
653// Passed the sector of the door, whose type specified the door action
654// Returns nothing
655//
656void P_SpawnDoorCloseIn30 (sector_t* sec)
657{
658 vldoor_t* door;
659
660 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
661
662 memset(door, 0, sizeof(*door));
663 P_AddThinker (&door->thinker);
664
665 sec->ceilingdata = door; //jff 2/22/98
666 sec->special = 0;
667
668 door->thinker.function = T_VerticalDoor;
669 door->sector = sec;
670 door->direction = 0;
671 door->type = normal;
672 door->speed = VDOORSPEED;
673 door->topcountdown = 30 * 35;
674 door->line = NULL; // jff 1/31/98 remember line that triggered us
675 door->lighttag = 0; /* killough 10/98: no lighting changes */
676}
677
678//
679// P_SpawnDoorRaiseIn5Mins()
680//
681// Spawn a door that opens after 5 minutes (called at level init)
682//
683// Passed the sector of the door, whose type specified the door action
684// Returns nothing
685//
686void P_SpawnDoorRaiseIn5Mins
687( sector_t* sec,
688 int secnum )
689{
690 vldoor_t* door;
691
692 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
693
694 memset(door, 0, sizeof(*door));
695 P_AddThinker (&door->thinker);
696
697 sec->ceilingdata = door; //jff 2/22/98
698 sec->special = 0;
699
700 door->thinker.function = T_VerticalDoor;
701 door->sector = sec;
702 door->direction = 2;
703 door->type = raiseIn5Mins;
704 door->speed = VDOORSPEED;
705 door->topheight = P_FindLowestCeilingSurrounding(sec);
706 door->topheight -= 4*FRACUNIT;
707 door->topwait = VDOORWAIT;
708 door->topcountdown = 5 * 60 * 35;
709 door->line = NULL; // jff 1/31/98 remember line that triggered us
710 door->lighttag = 0; /* killough 10/98: no lighting changes */
711}