1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
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.
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.
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
28 * Door animation code (opening/closing)
30 *-----------------------------------------------------------------------------*/
39 #include "d_deh.h" // Ty 03/27/98 - externalized
41 #include "rockmacros.h"
43 ///////////////////////////////////////////////////////////////
45 // Door action routines, called once per tick
47 ///////////////////////////////////////////////////////////////
52 // Passed a door structure containing all info about the door.
53 // See P_SPEC.H for fields.
56 // jff 02/08/98 all cases with labels beginning with gen added to support
57 // generalized line type behaviors.
59 void T_VerticalDoor (vldoor_t
* door
)
63 // Is the door waiting, going up, or going down?
64 switch(door
->direction
)
68 if (!--door
->topcountdown
) // downcount and check
74 door
->direction
= -1; // time to go back down
75 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_bdcls
);
80 door
->direction
= -1; // time to go back down
81 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_dorcls
);
86 door
->direction
= 1; // time to go back up
87 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_doropn
);
91 door
->direction
= 1; // time to go back up
92 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_bdopn
);
102 // Special case for sector type door that opens in 5 mins
103 if (!--door
->topcountdown
) // 5 minutes up?
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
);
120 // Door is moving down
125 door
->sector
->floorheight
,
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
,
137 door
->sector
->floorheight
));
139 // handle door reaching bottom
144 // regular open and close doors are all done, remove them
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
);
160 door
->sector
->ceilingdata
= NULL
; //jff 2/22/98
161 P_RemoveThinker (&door
->thinker
); // unlink and free
164 // close then open doors start waiting
165 case close30ThenOpen
:
167 door
->topcountdown
= TICRATE
*30;
173 door
->topcountdown
= door
->topwait
; // jff 5/8/98 insert delay
180 /* jff 1/31/98 turn lighting off in tagged sectors of manual doors
181 * killough 10/98: replaced with gradual lighting code
183 else if (res
== crushed
) // handle door meeting obstruction on way down
190 case p_close
: // Close types do not bounce, merely wait
196 if (!comp
[comp_blazing
]) {
197 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_bdopn
);
201 default: // other types bounce off the obstruction
203 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_doropn
);
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
,
227 door
->sector
->floorheight
));
229 // handle door reaching the top
234 case blazeRaise
: // regular open/close doors start waiting
238 door
->direction
= 0; // wait at top with delay
239 door
->topcountdown
= door
->topwait
;
242 case close30ThenOpen
: // close and close/open doors are done
249 door
->sector
->ceilingdata
= NULL
; //jff 2/22/98
250 P_RemoveThinker (&door
->thinker
); // unlink and free
257 /* jff 1/31/98 turn lighting on in tagged sectors of manual doors
258 * killough 10/98: replaced with gradual lighting code */
264 ///////////////////////////////////////////////////////////////
266 // Door linedef handlers
268 ///////////////////////////////////////////////////////////////
273 // Handle opening a tagged locked door
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
286 // only players can open locked doors
291 // check type of linedef, and if key is possessed to open it
292 switch(line
->special
)
294 case 99: // Blue Lock
296 if (!p
->cards
[it_bluecard
] && !p
->cards
[it_blueskull
])
298 p
->message
= s_PD_BLUEO
; // Ty 03/27/98 - externalized
299 S_StartSound(p
->mo
,sfx_oof
); // killough 3/20/98
304 case 134: // Red Lock
306 if (!p
->cards
[it_redcard
] && !p
->cards
[it_redskull
])
308 p
->message
= s_PD_REDO
; // Ty 03/27/98 - externalized
309 S_StartSound(p
->mo
,sfx_oof
); // killough 3/20/98
314 case 136: // Yellow Lock
316 if (!p
->cards
[it_yellowcard
] && !p
->cards
[it_yellowskull
])
318 p
->message
= s_PD_YELLOWO
; // Ty 03/27/98 - externalized
319 S_StartSound(p
->mo
,sfx_oof
); // killough 3/20/98
325 // got the key, so open the door
326 return EV_DoDoor(line
,type
);
333 // Handle opening a tagged door
335 // Passed the line activating the door and the type of door
336 // Returns true if a thinker created
349 // open all doors with the same tag as the activating line
350 while ((secnum
= P_FindSectorFromLineTag(line
,secnum
)) >= 0)
352 sec
= §ors
[secnum
];
353 // if the ceiling already moving, don't start the door action
354 if (P_SectorActive(ceiling_special
,sec
)) //jff 2/22/98
359 door
= Z_Malloc (sizeof(*door
), PU_LEVSPEC
, 0);
360 P_AddThinker (&door
->thinker
);
361 sec
->ceilingdata
= door
; //jff 2/22/98
363 door
->thinker
.function
= T_VerticalDoor
;
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 */
371 // setup door parameters according to type of door
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
);
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
);
389 case close30ThenOpen
:
390 door
->topheight
= sec
->ceilingheight
;
391 door
->direction
= -1;
392 S_StartSound((mobj_t
*)&door
->sector
->soundorg
,sfx_dorcls
);
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
);
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
);
425 // Handle opening a door manually, no tag value
427 // Passed the line activating the door and the thing activating it
428 // Returns true if a thinker created
430 // jff 2/12/98 added int return value, fixed all returns
442 player
= thing
->player
;
444 switch(line
->special
)
446 case 26: // Blue Lock
450 if (!player
->cards
[it_bluecard
] && !player
->cards
[it_blueskull
])
452 player
->message
= s_PD_BLUEK
; // Ty 03/27/98 - externalized
453 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
458 case 27: // Yellow Lock
462 if (!player
->cards
[it_yellowcard
] && !player
->cards
[it_yellowskull
])
464 player
->message
= s_PD_YELLOWK
; // Ty 03/27/98 - externalized
465 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
474 if (!player
->cards
[it_redcard
] && !player
->cards
[it_redskull
])
476 player
->message
= s_PD_REDK
; // Ty 03/27/98 - externalized
477 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
486 // if the wrong side of door is pushed, give oof sound
487 if (line
->sidenum
[1]==-1) // killough
489 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
493 // get the sector on the second side of activating linedef
494 sec
= sides
[line
->sidenum
[1]].sector
;
495 secnum
= sec
-sectors
;
497 /* if door already has a thinker, use it
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.
505 door
= sec
->ceilingdata
;
506 if (demo_compatibility
) {
507 if (!door
) door
= sec
->floordata
;
508 if (!door
) door
= sec
->lightingdata
;
512 switch(line
->special
)
514 case 1: // only for "raise" doors, not "open"s
519 if (door
->direction
== -1)
520 door
->direction
= 1; // go back up
524 return 0; // JDC: bad guys never close doors
526 door
->direction
= -1; // start going down immediately
533 switch(line
->special
)
535 case 117: // blazing door raise
536 case 118: // blazing door open
537 S_StartSound((mobj_t
*)&sec
->soundorg
,sfx_bdopn
);
540 case 1: // normal door sound
542 S_StartSound((mobj_t
*)&sec
->soundorg
,sfx_doropn
);
545 default: // locked door sound
546 S_StartSound((mobj_t
*)&sec
->soundorg
,sfx_doropn
);
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
;
557 door
->speed
= VDOORSPEED
;
558 door
->topwait
= VDOORWAIT
;
559 door
->line
= line
; // jff 1/31/98 remember line that triggered us
561 /* killough 10/98: use gradual lighting changes if nonzero tag given */
562 door
->lighttag
= comp
[comp_doorlight
] ? 0 : line
->tag
;
564 // set the type of door from the activating linedef type
565 switch(line
->special
)
582 case 117: // blazing door raise
583 door
->type
= blazeRaise
;
584 door
->speed
= VDOORSPEED
*4;
586 case 118: // blazing door open
587 door
->type
= blazeOpen
;
589 door
->speed
= VDOORSPEED
*4;
593 door
->lighttag
= 0; // killough 10/98
597 // find the top and bottom of the movement range
598 door
->topheight
= P_FindLowestCeilingSurrounding(sec
);
599 door
->topheight
-= 4*FRACUNIT
;
604 ///////////////////////////////////////////////////////////////
606 // Sector type door spawners
608 ///////////////////////////////////////////////////////////////
611 // P_SpawnDoorCloseIn30()
613 // Spawn a door that closes after 30 seconds (called at level init)
615 // Passed the sector of the door, whose type specified the door action
618 void P_SpawnDoorCloseIn30 (sector_t
* sec
)
622 door
= Z_Malloc ( sizeof(*door
), PU_LEVSPEC
, 0);
624 P_AddThinker (&door
->thinker
);
626 sec
->ceilingdata
= door
; //jff 2/22/98
629 door
->thinker
.function
= T_VerticalDoor
;
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 */
640 // P_SpawnDoorRaiseIn5Mins()
642 // Spawn a door that opens after 5 minutes (called at level init)
644 // Passed the sector of the door, whose type specified the door action
647 void P_SpawnDoorRaiseIn5Mins
654 door
= Z_Malloc ( sizeof(*door
), PU_LEVSPEC
, 0);
656 P_AddThinker (&door
->thinker
);
658 sec
->ceilingdata
= door
; //jff 2/22/98
661 door
->thinker
.function
= T_VerticalDoor
;
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 */