ypr0: Fix graphical eq keymap.
[maemo-rb.git] / apps / plugins / doom / p_doors.c
blob750b3474bd07d5cdeb141e337ea9b6e72e252b38
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 sector_t* sec;
438 vldoor_t* door;
440 // Check for locks
441 player = thing->player;
443 switch(line->special)
445 case 26: // Blue Lock
446 case 32:
447 if ( !player )
448 return 0;
449 if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
451 player->message = s_PD_BLUEK; // Ty 03/27/98 - externalized
452 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
453 return 0;
455 break;
457 case 27: // Yellow Lock
458 case 34:
459 if ( !player )
460 return 0;
461 if (!player->cards[it_yellowcard] && !player->cards[it_yellowskull])
463 player->message = s_PD_YELLOWK; // Ty 03/27/98 - externalized
464 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
465 return 0;
467 break;
469 case 28: // Red Lock
470 case 33:
471 if ( !player )
472 return 0;
473 if (!player->cards[it_redcard] && !player->cards[it_redskull])
475 player->message = s_PD_REDK; // Ty 03/27/98 - externalized
476 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
477 return 0;
479 break;
481 default:
482 break;
485 // if the wrong side of door is pushed, give oof sound
486 if (line->sidenum[1]==-1) // killough
488 S_StartSound(player->mo,sfx_oof); // killough 3/20/98
489 return 0;
492 // get the sector on the second side of activating linedef
493 sec = sides[line->sidenum[1]].sector;
495 /* if door already has a thinker, use it
496 * cph 2001/04/05 -
497 * Ok, this is a disaster area. We're assuming that sec->ceilingdata
498 * is a vldoor_t! What if this door is controlled by both DR lines
499 * and by switches? I don't know how to fix that.
500 * Secondly, original Doom didn't distinguish floor/lighting/ceiling
501 * actions, so we need to do the same in demo compatibility mode.
503 door = sec->ceilingdata;
504 if (demo_compatibility) {
505 if (!door) door = sec->floordata;
506 if (!door) door = sec->lightingdata;
508 if (door)
510 switch(line->special)
512 case 1: // only for "raise" doors, not "open"s
513 case 26:
514 case 27:
515 case 28:
516 case 117:
517 if (door->direction == -1)
518 door->direction = 1; // go back up
519 else
521 if (!thing->player)
522 return 0; // JDC: bad guys never close doors
524 door->direction = -1; // start going down immediately
526 return 1;
530 // emit proper sound
531 switch(line->special)
533 case 117: // blazing door raise
534 case 118: // blazing door open
535 S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
536 break;
538 case 1: // normal door sound
539 case 31:
540 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
541 break;
543 default: // locked door sound
544 S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
545 break;
548 // new door thinker
549 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
550 P_AddThinker (&door->thinker);
551 sec->ceilingdata = door; //jff 2/22/98
552 door->thinker.function = T_VerticalDoor;
553 door->sector = sec;
554 door->direction = 1;
555 door->speed = VDOORSPEED;
556 door->topwait = VDOORWAIT;
557 door->line = line; // jff 1/31/98 remember line that triggered us
559 /* killough 10/98: use gradual lighting changes if nonzero tag given */
560 door->lighttag = comp[comp_doorlight] ? 0 : line->tag;
562 // set the type of door from the activating linedef type
563 switch(line->special)
565 case 1:
566 case 26:
567 case 27:
568 case 28:
569 door->type = normal;
570 break;
572 case 31:
573 case 32:
574 case 33:
575 case 34:
576 door->type = p_open;
577 line->special = 0;
578 break;
580 case 117: // blazing door raise
581 door->type = blazeRaise;
582 door->speed = VDOORSPEED*4;
583 break;
584 case 118: // blazing door open
585 door->type = blazeOpen;
586 line->special = 0;
587 door->speed = VDOORSPEED*4;
588 break;
590 default:
591 door->lighttag = 0; // killough 10/98
592 break;
595 // find the top and bottom of the movement range
596 door->topheight = P_FindLowestCeilingSurrounding(sec);
597 door->topheight -= 4*FRACUNIT;
598 return 1;
602 ///////////////////////////////////////////////////////////////
604 // Sector type door spawners
606 ///////////////////////////////////////////////////////////////
609 // P_SpawnDoorCloseIn30()
611 // Spawn a door that closes after 30 seconds (called at level init)
613 // Passed the sector of the door, whose type specified the door action
614 // Returns nothing
616 void P_SpawnDoorCloseIn30 (sector_t* sec)
618 vldoor_t* door;
620 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
622 P_AddThinker (&door->thinker);
624 sec->ceilingdata = door; //jff 2/22/98
625 sec->special = 0;
627 door->thinker.function = T_VerticalDoor;
628 door->sector = sec;
629 door->direction = 0;
630 door->type = normal;
631 door->speed = VDOORSPEED;
632 door->topcountdown = 30 * 35;
633 door->line = NULL; // jff 1/31/98 remember line that triggered us
634 door->lighttag = 0; /* killough 10/98: no lighting changes */
638 // P_SpawnDoorRaiseIn5Mins()
640 // Spawn a door that opens after 5 minutes (called at level init)
642 // Passed the sector of the door, whose type specified the door action
643 // Returns nothing
645 void P_SpawnDoorRaiseIn5Mins
646 ( sector_t* sec,
647 int secnum )
649 (void)secnum;
650 vldoor_t* door;
652 door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
654 P_AddThinker (&door->thinker);
656 sec->ceilingdata = door; //jff 2/22/98
657 sec->special = 0;
659 door->thinker.function = T_VerticalDoor;
660 door->sector = sec;
661 door->direction = 2;
662 door->type = raiseIn5Mins;
663 door->speed = VDOORSPEED;
664 door->topheight = P_FindLowestCeilingSurrounding(sec);
665 door->topheight -= 4*FRACUNIT;
666 door->topwait = VDOORWAIT;
667 door->topcountdown = 5 * 60 * 35;
668 door->line = NULL; // jff 1/31/98 remember line that triggered us
669 door->lighttag = 0; /* killough 10/98: no lighting changes */