summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_doors.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/p_doors.c')
-rw-r--r--apps/plugins/doom/p_doors.c672
1 files changed, 672 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_doors.c b/apps/plugins/doom/p_doors.c
new file mode 100644
index 0000000000..9d8f28cd7a
--- /dev/null
+++ b/apps/plugins/doom/p_doors.c
@@ -0,0 +1,672 @@
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 * Door animation code (opening/closing)
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "p_spec.h"
34#include "p_tick.h"
35#include "s_sound.h"
36#include "sounds.h"
37#include "r_main.h"
38#include "dstrings.h"
39//#include "d_deh.h" // Ty 03/27/98 - externalized
40
41#include "rockmacros.h"
42
43///////////////////////////////////////////////////////////////
44//
45// Door action routines, called once per tick
46//
47///////////////////////////////////////////////////////////////
48
49//
50// T_VerticalDoor
51//
52// Passed a door structure containing all info about the door.
53// See P_SPEC.H for fields.
54// Returns nothing.
55//
56// jff 02/08/98 all cases with labels beginning with gen added to support
57// generalized line type behaviors.
58
59void T_VerticalDoor (vldoor_t* door)
60{
61 result_e res;
62
63 // Is the door waiting, going up, or going down?
64 switch(door->direction)
65 {
66 case 0:
67 // Door is waiting
68 if (!--door->topcountdown) // downcount and check
69 {
70 switch(door->type)
71 {
72 case blazeRaise:
73 case genBlazeRaise:
74 door->direction = -1; // time to go back down
75 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
76 break;
77
78 case normal:
79 case genRaise:
80 door->direction = -1; // time to go back down
81 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
82 break;
83
84 case close30ThenOpen:
85 case genCdO:
86 door->direction = 1; // time to go back up
87 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
88 break;
89
90 case genBlazeCdO:
91 door->direction = 1; // time to go back up
92 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
93 break;
94
95 default:
96 break;
97 }
98 }
99 break;
100
101 case 2:
102 // Special case for sector type door that opens in 5 mins
103 if (!--door->topcountdown) // 5 minutes up?
104 {
105 switch(door->type)
106 {
107 case raiseIn5Mins:
108 door->direction = 1; // time to raise then
109 door->type = normal; // door acts just like normal 1 DR door now
110 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
111 break;
112
113 default:
114 break;
115 }
116 }
117 break;
118
119 case -1:
120 // Door is moving down
121 res = T_MovePlane
122 (
123 door->sector,
124 door->speed,
125 door->sector->floorheight,
126 false,
127 1,
128 door->direction
129 );
130
131 /* killough 10/98: implement gradual lighting effects */
132 if (door->lighttag && door->topheight - door->sector->floorheight)
133 EV_LightTurnOnPartway(door->line,
134 FixedDiv(door->sector->ceilingheight -
135 door->sector->floorheight,
136 door->topheight -
137 door->sector->floorheight));
138
139 // handle door reaching bottom
140 if (res == pastdest)
141 {
142 switch(door->type)
143 {
144 // regular open and close doors are all done, remove them
145 case blazeRaise:
146 case blazeClose:
147 case genBlazeRaise:
148 case genBlazeClose:
149 door->sector->ceilingdata = NULL; //jff 2/22/98
150 P_RemoveThinker (&door->thinker); // unlink and free
151 // killough 4/15/98: remove double-closing sound of blazing doors
152 if (comp[comp_blazing])
153 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
154 break;
155
156 case normal:
157 case p_close:
158 case genRaise:
159 case genClose:
160 door->sector->ceilingdata = NULL; //jff 2/22/98
161 P_RemoveThinker (&door->thinker); // unlink and free
162 break;
163
164 // close then open doors start waiting
165 case close30ThenOpen:
166 door->direction = 0;
167 door->topcountdown = TICRATE*30;
168 break;
169
170 case genCdO:
171 case genBlazeCdO:
172 door->direction = 0;
173 door->topcountdown = door->topwait; // jff 5/8/98 insert delay
174 break;
175
176 default:
177 break;
178 }
179 }
180 /* jff 1/31/98 turn lighting off in tagged sectors of manual doors
181 * killough 10/98: replaced with gradual lighting code
182 */
183 else if (res == crushed) // handle door meeting obstruction on way down
184 {
185 switch(door->type)
186 {
187 case genClose:
188 case genBlazeClose:
189 case blazeClose:
190 case p_close: // Close types do not bounce, merely wait
191 break;
192
193 case blazeRaise:
194 case genBlazeRaise:
195 door->direction = 1;
196 if (!comp[comp_blazing]) {
197 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
198 break;
199 }
200
201 default: // other types bounce off the obstruction
202 door->direction = 1;
203 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
204 break;
205 }
206 }
207 break;
208
209 case 1:
210 // Door is moving up
211 res = T_MovePlane
212 (
213 door->sector,
214 door->speed,
215 door->topheight,
216 false,
217 1,
218 door->direction
219 );
220
221 /* killough 10/98: implement gradual lighting effects */
222 if (door->lighttag && door->topheight - door->sector->floorheight)
223 EV_LightTurnOnPartway(door->line,
224 FixedDiv(door->sector->ceilingheight -
225 door->sector->floorheight,
226 door->topheight -
227 door->sector->floorheight));
228
229 // handle door reaching the top
230 if (res == pastdest)
231 {
232 switch(door->type)
233 {
234 case blazeRaise: // regular open/close doors start waiting
235 case normal:
236 case genRaise:
237 case genBlazeRaise:
238 door->direction = 0; // wait at top with delay
239 door->topcountdown = door->topwait;
240 break;
241
242 case close30ThenOpen: // close and close/open doors are done
243 case blazeOpen:
244 case p_open:
245 case genBlazeOpen:
246 case genOpen:
247 case genCdO:
248 case genBlazeCdO:
249 door->sector->ceilingdata = NULL; //jff 2/22/98
250 P_RemoveThinker (&door->thinker); // unlink and free
251 break;
252
253 default:
254 break;
255 }
256
257 /* jff 1/31/98 turn lighting on in tagged sectors of manual doors
258 * killough 10/98: replaced with gradual lighting code */
259 }
260 break;
261 }
262}
263
264///////////////////////////////////////////////////////////////
265//
266// Door linedef handlers
267//
268///////////////////////////////////////////////////////////////
269
270//
271// EV_DoLockedDoor
272//
273// Handle opening a tagged locked door
274//
275// Passed the line activating the door, the type of door,
276// and the thing that activated the line
277// Returns true if a thinker created
278//
279int EV_DoLockedDoor
280( line_t* line,
281 vldoor_e type,
282 mobj_t* thing )
283{
284 player_t* p;
285
286 // only players can open locked doors
287 p = thing->player;
288 if (!p)
289 return 0;
290
291 // check type of linedef, and if key is possessed to open it
292 switch(line->special)
293 {
294 case 99: // Blue Lock
295 case 133:
296 if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
297 {
298 p->message = PD_BLUEO; // Ty 03/27/98 - externalized
299 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
300 return 0;
301 }
302 break;
303
304 case 134: // Red Lock
305 case 135:
306 if (!p->cards[it_redcard] && !p->cards[it_redskull])
307 {
308 p->message = PD_REDO; // Ty 03/27/98 - externalized
309 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
310 return 0;
311 }
312 break;
313
314 case 136: // Yellow Lock
315 case 137:
316 if (!p->cards[it_yellowcard] && !p->cards[it_yellowskull])
317 {
318 p->message = PD_YELLOWO; // Ty 03/27/98 - externalized
319 S_StartSound(p->mo,sfx_oof); // killough 3/20/98
320 return 0;
321 }
322 break;
323 }
324
325 // got the key, so open the door
326 return EV_DoDoor(line,type);
327}
328
329
330//
331// EV_DoDoor
332//
333// Handle opening a tagged door
334//
335// Passed the line activating the door and the type of door
336// Returns true if a thinker created
337//
338int EV_DoDoor
339( line_t* line,
340 vldoor_e type )
341{
342 int secnum,rtn;
343 sector_t* sec;
344 vldoor_t* door;
345
346 secnum = -1;
347 rtn = 0;
348
349 // open all doors with the same tag as the activating line
350 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
351 {
352 sec = &sectors[secnum];
353 // if the ceiling already moving, don't start the door action
354 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
355 continue;
356
357 // new door thinker
358 rtn = 1;
359 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
360 P_AddThinker (&door->thinker);
361 sec->ceilingdata = door; //jff 2/22/98
362
363 door->thinker.function = T_VerticalDoor;
364 door->sector = sec;
365 door->type = type;
366 door->topwait = VDOORWAIT;
367 door->speed = VDOORSPEED;
368 door->line = line; // jff 1/31/98 remember line that triggered us
369 door->lighttag = 0; /* killough 10/98: no light effects with tagged doors */
370
371 // setup door parameters according to type of door
372 switch(type)
373 {
374 case blazeClose:
375 door->topheight = P_FindLowestCeilingSurrounding(sec);
376 door->topheight -= 4*FRACUNIT;
377 door->direction = -1;
378 door->speed = VDOORSPEED * 4;
379 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdcls);
380 break;
381
382 case p_close:
383 door->topheight = P_FindLowestCeilingSurrounding(sec);
384 door->topheight -= 4*FRACUNIT;
385 door->direction = -1;
386 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
387 break;
388
389 case close30ThenOpen:
390 door->topheight = sec->ceilingheight;
391 door->direction = -1;
392 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
393 break;
394
395 case blazeRaise:
396 case blazeOpen:
397 door->direction = 1;
398 door->topheight = P_FindLowestCeilingSurrounding(sec);
399 door->topheight -= 4*FRACUNIT;
400 door->speed = VDOORSPEED * 4;
401 if (door->topheight != sec->ceilingheight)
402 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
403 break;
404
405 case normal:
406 case p_open:
407 door->direction = 1;
408 door->topheight = P_FindLowestCeilingSurrounding(sec);
409 door->topheight -= 4*FRACUNIT;
410 if (door->topheight != sec->ceilingheight)
411 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
412 break;
413
414 default:
415 break;
416 }
417 }
418 return rtn;
419}
420
421
422//
423// EV_VerticalDoor
424//
425// Handle opening a door manually, no tag value
426//
427// Passed the line activating the door and the thing activating it
428// Returns true if a thinker created
429//
430// jff 2/12/98 added int return value, fixed all returns
431//
432int EV_VerticalDoor
433( line_t* line,
434 mobj_t* thing )
435{
436 player_t* player;
437 int secnum;
438 sector_t* sec;
439 vldoor_t* door;
440
441 // Check for locks
442 player = thing->player;
443
444 switch(line->special)
445 {
446 case 26: // Blue Lock
447 case 32:
448 if ( !player )
449 return 0;
450 if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
451 {
452 player->message = PD_BLUEK; // Ty 03/27/98 - externalized
453 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
454 return 0;
455 }
456 break;
457
458 case 27: // Yellow Lock
459 case 34:
460 if ( !player )
461 return 0;
462 if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull])
463 {
464 player->message = PD_YELLOWK; // Ty 03/27/98 - externalized
465 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
466 return 0;
467 }
468 break;
469
470 case 28: // Red Lock
471 case 33:
472 if ( !player )
473 return 0;
474 if (!player->cards[it_redcard] && !player->cards[it_redskull])
475 {
476 player->message = PD_REDK; // Ty 03/27/98 - externalized
477 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
478 return 0;
479 }
480 break;
481
482 default:
483 break;
484 }
485
486 // if the wrong side of door is pushed, give oof sound
487 if (line->sidenum[1]==-1) // killough
488 {
489 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
490 return 0;
491 }
492
493 // get the sector on the second side of activating linedef
494 sec = sides[line->sidenum[1]].sector;
495 secnum = sec-sectors;
496
497 /* if door already has a thinker, use it
498 * cph 2001/04/05 -
499 * Ok, this is a disaster area. We're assuming that sec->ceilingdata
500 * is a vldoor_t! What if this door is controlled by both DR lines
501 * and by switches? I don't know how to fix that.
502 * Secondly, original Doom didn't distinguish floor/lighting/ceiling
503 * actions, so we need to do the same in demo compatibility mode.
504 */
505 door = sec->ceilingdata;
506 if (demo_compatibility) {
507 if (!door) door = sec->floordata;
508 if (!door) door = sec->lightingdata;
509 }
510 if (door)
511 {
512 switch(line->special)
513 {
514 case 1: // only for "raise" doors, not "open"s
515 case 26:
516 case 27:
517 case 28:
518 case 117:
519 if (door->direction == -1)
520 door->direction = 1; // go back up
521 else
522 {
523 if (!thing->player)
524 return 0; // JDC: bad guys never close doors
525
526 door->direction = -1; // start going down immediately
527 }
528 return 1;
529 }
530 }
531
532 // emit proper sound
533 switch(line->special)
534 {
535 case 117: // blazing door raise
536 case 118: // blazing door open
537 S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
538 break;
539
540 case 1: // normal door sound
541 case 31:
542 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
543 break;
544
545 default: // locked door sound
546 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
547 break;
548 }
549
550 // new door thinker
551 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
552 P_AddThinker (&door->thinker);
553 sec->ceilingdata = door; //jff 2/22/98
554 door->thinker.function = T_VerticalDoor;
555 door->sector = sec;
556 door->direction = 1;
557 door->speed = VDOORSPEED;
558 door->topwait = VDOORWAIT;
559 door->line = line; // jff 1/31/98 remember line that triggered us
560
561 /* killough 10/98: use gradual lighting changes if nonzero tag given */
562 door->lighttag = comp[comp_doorlight] ? 0 : line->tag;
563
564 // set the type of door from the activating linedef type
565 switch(line->special)
566 {
567 case 1:
568 case 26:
569 case 27:
570 case 28:
571 door->type = normal;
572 break;
573
574 case 31:
575 case 32:
576 case 33:
577 case 34:
578 door->type = p_open;
579 line->special = 0;
580 break;
581
582 case 117: // blazing door raise
583 door->type = blazeRaise;
584 door->speed = VDOORSPEED*4;
585 break;
586 case 118: // blazing door open
587 door->type = blazeOpen;
588 line->special = 0;
589 door->speed = VDOORSPEED*4;
590 break;
591
592 default:
593 door->lighttag = 0; // killough 10/98
594 break;
595 }
596
597 // find the top and bottom of the movement range
598 door->topheight = P_FindLowestCeilingSurrounding(sec);
599 door->topheight -= 4*FRACUNIT;
600 return 1;
601}
602
603
604///////////////////////////////////////////////////////////////
605//
606// Sector type door spawners
607//
608///////////////////////////////////////////////////////////////
609
610//
611// P_SpawnDoorCloseIn30()
612//
613// Spawn a door that closes after 30 seconds (called at level init)
614//
615// Passed the sector of the door, whose type specified the door action
616// Returns nothing
617//
618void P_SpawnDoorCloseIn30 (sector_t* sec)
619{
620 vldoor_t* door;
621
622 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
623
624 P_AddThinker (&door->thinker);
625
626 sec->ceilingdata = door; //jff 2/22/98
627 sec->special = 0;
628
629 door->thinker.function = T_VerticalDoor;
630 door->sector = sec;
631 door->direction = 0;
632 door->type = normal;
633 door->speed = VDOORSPEED;
634 door->topcountdown = 30 * 35;
635 door->line = NULL; // jff 1/31/98 remember line that triggered us
636 door->lighttag = 0; /* killough 10/98: no lighting changes */
637}
638
639//
640// P_SpawnDoorRaiseIn5Mins()
641//
642// Spawn a door that opens after 5 minutes (called at level init)
643//
644// Passed the sector of the door, whose type specified the door action
645// Returns nothing
646//
647void P_SpawnDoorRaiseIn5Mins
648( sector_t* sec,
649 int secnum )
650{
651 (void)secnum;
652 vldoor_t* door;
653
654 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
655
656 P_AddThinker (&door->thinker);
657
658 sec->ceilingdata = door; //jff 2/22/98
659 sec->special = 0;
660
661 door->thinker.function = T_VerticalDoor;
662 door->sector = sec;
663 door->direction = 2;
664 door->type = raiseIn5Mins;
665 door->speed = VDOORSPEED;
666 door->topheight = P_FindLowestCeilingSurrounding(sec);
667 door->topheight -= 4*FRACUNIT;
668 door->topwait = VDOORWAIT;
669 door->topcountdown = 5 * 60 * 35;
670 door->line = NULL; // jff 1/31/98 remember line that triggered us
671 door->lighttag = 0; /* killough 10/98: no lighting changes */
672}