Fix red, moved around a bit to much.
[kugel-rb.git] / apps / plugins / doom / p_doors.c
blob0b6d777e17e813f2104901b3a747049d94aeaaf5
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
25 * 02111-1307, USA.
27 * DESCRIPTION:
28 * Door animation code (opening/closing)
30 *-----------------------------------------------------------------------------*/
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
41 #include "rockmacros.h"
43 ///////////////////////////////////////////////////////////////
45 // Door action routines, called once per tick
47 ///////////////////////////////////////////////////////////////
50 // T_VerticalDoor
52 // Passed a door structure containing all info about the door.
53 // See P_SPEC.H for fields.
54 // Returns nothing.
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)
61 result_e res;
63 // Is the door waiting, going up, or going down?
64 switch(door->direction)
66 case 0:
67 // Door is waiting
68 if (!--door->topcountdown) // downcount and check
70 switch(door->type)
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;
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;
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;
90 case genBlazeCdO:
91 door->direction = 1; // time to go back up
92 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_bdopn);
93 break;
95 default:
96 break;
99 break;
101 case 2:
102 // Special case for sector type door that opens in 5 mins
103 if (!--door->topcountdown) // 5 minutes up?
105 switch(door->type)
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;
113 default:
114 break;
117 break;
119 case -1:
120 // Door is moving down
121 res = T_MovePlane
123 door->sector,
124 door->speed,
125 door->sector->floorheight,
126 false,
128 door->direction
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));
139 // handle door reaching bottom
140 if (res == pastdest)
142 switch(door->type)
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;
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;
164 // close then open doors start waiting
165 case close30ThenOpen:
166 door->direction = 0;
167 door->topcountdown = TICRATE*30;
168 break;
170 case genCdO:
171 case genBlazeCdO:
172 door->direction = 0;
173 door->topcountdown = door->topwait; // jff 5/8/98 insert delay
174 break;
176 default:
177 break;
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
185 switch(door->type)
187 case genClose:
188 case genBlazeClose:
189 case blazeClose:
190 case p_close: // Close types do not bounce, merely wait
191 break;
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;
201 default: // other types bounce off the obstruction
202 door->direction = 1;
203 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_doropn);
204 break;
207 break;
209 case 1:
210 // Door is moving up
211 res = T_MovePlane
213 door->sector,
214 door->speed,
215 door->topheight,
216 false,
218 door->direction
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));
229 // handle door reaching the top
230 if (res == pastdest)
232 switch(door->type)
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;
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;
253 default:
254 break;
257 /* jff 1/31/98 turn lighting on in tagged sectors of manual doors
258 * killough 10/98: replaced with gradual lighting code */
260 break;
264 ///////////////////////////////////////////////////////////////
266 // Door linedef handlers
268 ///////////////////////////////////////////////////////////////
271 // EV_DoLockedDoor
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
279 int EV_DoLockedDoor
280 ( line_t* line,
281 vldoor_e type,
282 mobj_t* thing )
284 player_t* p;
286 // only players can open locked doors
287 p = thing->player;
288 if (!p)
289 return 0;
291 // check type of linedef, and if key is possessed to open it
292 switch(line->special)
294 case 99: // Blue Lock
295 case 133:
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
300 return 0;
302 break;
304 case 134: // Red Lock
305 case 135:
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
310 return 0;
312 break;
314 case 136: // Yellow Lock
315 case 137:
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
320 return 0;
322 break;
325 // got the key, so open the door
326 return EV_DoDoor(line,type);
331 // EV_DoDoor
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
338 int EV_DoDoor
339 ( line_t* line,
340 vldoor_e type )
342 int secnum,rtn;
343 sector_t* sec;
344 vldoor_t* door;
346 secnum = -1;
347 rtn = 0;
349 // open all doors with the same tag as the activating line
350 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
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;
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
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 */
371 // setup door parameters according to type of door
372 switch(type)
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;
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;
389 case close30ThenOpen:
390 door->topheight = sec->ceilingheight;
391 door->direction = -1;
392 S_StartSound((mobj_t *)&door->sector->soundorg,sfx_dorcls);
393 break;
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;
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;
414 default:
415 break;
418 return rtn;
423 // EV_VerticalDoor
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
432 int EV_VerticalDoor
433 ( line_t* line,
434 mobj_t* thing )
436 player_t* player;
437 int secnum;
438 sector_t* sec;
439 vldoor_t* door;
441 // Check for locks
442 player = thing->player;
444 switch(line->special)
446 case 26: // Blue Lock
447 case 32:
448 if ( !player )
449 return 0;
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
454 return 0;
456 break;
458 case 27: // Yellow Lock
459 case 34:
460 if ( !player )
461 return 0;
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
466 return 0;
468 break;
470 case 28: // Red Lock
471 case 33:
472 if ( !player )
473 return 0;
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
478 return 0;
480 break;
482 default:
483 break;
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
490 return 0;
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
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.
505 door = sec->ceilingdata;
506 if (demo_compatibility) {
507 if (!door) door = sec->floordata;
508 if (!door) door = sec->lightingdata;
510 if (door)
512 switch(line->special)
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
523 if (!thing->player)
524 return 0; // JDC: bad guys never close doors
526 door->direction = -1; // start going down immediately
528 return 1;
532 // emit proper sound
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);
538 break;
540 case 1: // normal door sound
541 case 31:
542 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
543 break;
545 default: // locked door sound
546 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
547 break;
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
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)
567 case 1:
568 case 26:
569 case 27:
570 case 28:
571 door->type = normal;
572 break;
574 case 31:
575 case 32:
576 case 33:
577 case 34:
578 door->type = p_open;
579 line->special = 0;
580 break;
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;
592 default:
593 door->lighttag = 0; // killough 10/98
594 break;
597 // find the top and bottom of the movement range
598 door->topheight = P_FindLowestCeilingSurrounding(sec);
599 door->topheight -= 4*FRACUNIT;
600 return 1;
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
616 // Returns nothing
618 void P_SpawnDoorCloseIn30 (sector_t* sec)
620 vldoor_t* door;
622 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
624 P_AddThinker (&door->thinker);
626 sec->ceilingdata = door; //jff 2/22/98
627 sec->special = 0;
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 */
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
645 // Returns nothing
647 void P_SpawnDoorRaiseIn5Mins
648 ( sector_t* sec,
649 int secnum )
651 (void)secnum;
652 vldoor_t* door;
654 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
656 P_AddThinker (&door->thinker);
658 sec->ceilingdata = door; //jff 2/22/98
659 sec->special = 0;
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 */