Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // Emacs style mode select   -*- C++ -*-
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION: Door animation code (opening/closing)
  20. //
  21. //-----------------------------------------------------------------------------
  22.  
  23. static const char
  24. rcsid[] = "$Id: p_doors.c,v 1.4 1997/02/03 16:47:53 b1 Exp $";
  25.  
  26.  
  27. #include "z_zone.h"
  28. #include "doomdef.h"
  29. #include "p_local.h"
  30.  
  31. #include "s_sound.h"
  32.  
  33.  
  34. // State.
  35. #include "doomstat.h"
  36. #include "r_state.h"
  37.  
  38. // Data.
  39. #include "dstrings.h"
  40. #include "sounds.h"
  41.  
  42. #if 0
  43. //
  44. // Sliding door frame information
  45. //
  46. slidename_t     slideFrameNames[MAXSLIDEDOORS] =
  47. {
  48.     {"GDOORF1","GDOORF2","GDOORF3","GDOORF4",   // front
  49.      "GDOORB1","GDOORB2","GDOORB3","GDOORB4"},  // back
  50.          
  51.     {"\0","\0","\0","\0"}
  52. };
  53. #endif
  54.  
  55.  
  56. //
  57. // VERTICAL DOORS
  58. //
  59.  
  60. //
  61. // T_VerticalDoor
  62. //
  63. void T_VerticalDoor (vldoor_t* door)
  64. {
  65.     result_e    res;
  66.        
  67.     switch(door->direction)
  68.     {
  69.       case 0:
  70.         // WAITING
  71.         if (!--door->topcountdown)
  72.         {
  73.             switch(door->type)
  74.             {
  75.               case blazeRaise:
  76.                 door->direction = -1; // time to go back down
  77.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  78.                              sfx_bdcls);
  79.                 break;
  80.                
  81.               case normal:
  82.                 door->direction = -1; // time to go back down
  83.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  84.                              sfx_dorcls);
  85.                 break;
  86.                
  87.               case close30ThenOpen:
  88.                 door->direction = 1;
  89.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  90.                              sfx_doropn);
  91.                 break;
  92.                
  93.               default:
  94.                 break;
  95.             }
  96.         }
  97.         break;
  98.        
  99.       case 2:
  100.         //  INITIAL WAIT
  101.         if (!--door->topcountdown)
  102.         {
  103.             switch(door->type)
  104.             {
  105.               case raiseIn5Mins:
  106.                 door->direction = 1;
  107.                 door->type = normal;
  108.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  109.                              sfx_doropn);
  110.                 break;
  111.                
  112.               default:
  113.                 break;
  114.             }
  115.         }
  116.         break;
  117.        
  118.       case -1:
  119.         // DOWN
  120.         res = T_MovePlane(door->sector,
  121.                           door->speed,
  122.                           door->sector->floorheight,
  123.                           false,1,door->direction);
  124.         if (res == pastdest)
  125.         {
  126.             switch(door->type)
  127.             {
  128.               case blazeRaise:
  129.               case blazeClose:
  130.                 door->sector->specialdata = NULL;
  131.                 P_RemoveThinker (&door->thinker);  // unlink and free
  132.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  133.                              sfx_bdcls);
  134.                 break;
  135.                
  136.               case normal:
  137.               case close:
  138.                 door->sector->specialdata = NULL;
  139.                 P_RemoveThinker (&door->thinker);  // unlink and free
  140.                 break;
  141.                
  142.               case close30ThenOpen:
  143.                 door->direction = 0;
  144.                 door->topcountdown = 35*30;
  145.                 break;
  146.                
  147.               default:
  148.                 break;
  149.             }
  150.         }
  151.         else if (res == crushed)
  152.         {
  153.             switch(door->type)
  154.             {
  155.               case blazeClose:
  156.               case close:               // DO NOT GO BACK UP!
  157.                 break;
  158.                
  159.               default:
  160.                 door->direction = 1;
  161.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  162.                              sfx_doropn);
  163.                 break;
  164.             }
  165.         }
  166.         break;
  167.        
  168.       case 1:
  169.         // UP
  170.         res = T_MovePlane(door->sector,
  171.                           door->speed,
  172.                           door->topheight,
  173.                           false,1,door->direction);
  174.        
  175.         if (res == pastdest)
  176.         {
  177.             switch(door->type)
  178.             {
  179.               case blazeRaise:
  180.               case normal:
  181.                 door->direction = 0; // wait at top
  182.                 door->topcountdown = door->topwait;
  183.                 break;
  184.                
  185.               case close30ThenOpen:
  186.               case blazeOpen:
  187.               case open:
  188.                 door->sector->specialdata = NULL;
  189.                 P_RemoveThinker (&door->thinker);  // unlink and free
  190.                 break;
  191.                
  192.               default:
  193.                 break;
  194.             }
  195.         }
  196.         break;
  197.     }
  198. }
  199.  
  200.  
  201. //
  202. // EV_DoLockedDoor
  203. // Move a locked door up/down
  204. //
  205.  
  206. int
  207. EV_DoLockedDoor
  208. ( line_t*       line,
  209.   vldoor_e      type,
  210.   mobj_t*       thing )
  211. {
  212.     player_t*   p;
  213.        
  214.     p = thing->player;
  215.        
  216.     if (!p)
  217.         return 0;
  218.                
  219.     switch(line->special)
  220.     {
  221.       case 99:  // Blue Lock
  222.       case 133:
  223.         if ( !p )
  224.             return 0;
  225.         if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
  226.         {
  227.             p->message = PD_BLUEO;
  228.             S_StartSound(NULL,sfx_oof);
  229.             return 0;
  230.         }
  231.         break;
  232.        
  233.       case 134: // Red Lock
  234.       case 135:
  235.         if ( !p )
  236.             return 0;
  237.         if (!p->cards[it_redcard] && !p->cards[it_redskull])
  238.         {
  239.             p->message = PD_REDO;
  240.             S_StartSound(NULL,sfx_oof);
  241.             return 0;
  242.         }
  243.         break;
  244.        
  245.       case 136: // Yellow Lock
  246.       case 137:
  247.         if ( !p )
  248.             return 0;
  249.         if (!p->cards[it_yellowcard] &&
  250.             !p->cards[it_yellowskull])
  251.         {
  252.             p->message = PD_YELLOWO;
  253.             S_StartSound(NULL,sfx_oof);
  254.             return 0;
  255.         }
  256.         break; 
  257.     }
  258.  
  259.     return EV_DoDoor(line,type);
  260. }
  261.  
  262.  
  263. int
  264. EV_DoDoor
  265. ( line_t*       line,
  266.   vldoor_e      type )
  267. {
  268.     int         secnum,rtn;
  269.     sector_t*   sec;
  270.     vldoor_t*   door;
  271.        
  272.     secnum = -1;
  273.     rtn = 0;
  274.    
  275.     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  276.     {
  277.         sec = &sectors[secnum];
  278.         if (sec->specialdata)
  279.             continue;
  280.                
  281.        
  282.         // new door thinker
  283.         rtn = 1;
  284.         door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
  285.         P_AddThinker (&door->thinker);
  286.         sec->specialdata = door;
  287.  
  288.         door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
  289.         door->sector = sec;
  290.         door->type = type;
  291.         door->topwait = VDOORWAIT;
  292.         door->speed = VDOORSPEED;
  293.                
  294.         switch(type)
  295.         {
  296.           case blazeClose:
  297.             door->topheight = P_FindLowestCeilingSurrounding(sec);
  298.             door->topheight -= 4*FRACUNIT;
  299.             door->direction = -1;
  300.             door->speed = VDOORSPEED * 4;
  301.             S_StartSound((mobj_t *)&door->sector->soundorg,
  302.                          sfx_bdcls);
  303.             break;
  304.            
  305.           case close:
  306.             door->topheight = P_FindLowestCeilingSurrounding(sec);
  307.             door->topheight -= 4*FRACUNIT;
  308.             door->direction = -1;
  309.             S_StartSound((mobj_t *)&door->sector->soundorg,
  310.                          sfx_dorcls);
  311.             break;
  312.            
  313.           case close30ThenOpen:
  314.             door->topheight = sec->ceilingheight;
  315.             door->direction = -1;
  316.             S_StartSound((mobj_t *)&door->sector->soundorg,
  317.                          sfx_dorcls);
  318.             break;
  319.            
  320.           case blazeRaise:
  321.           case blazeOpen:
  322.             door->direction = 1;
  323.             door->topheight = P_FindLowestCeilingSurrounding(sec);
  324.             door->topheight -= 4*FRACUNIT;
  325.             door->speed = VDOORSPEED * 4;
  326.             if (door->topheight != sec->ceilingheight)
  327.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  328.                              sfx_bdopn);
  329.             break;
  330.            
  331.           case normal:
  332.           case open:
  333.             door->direction = 1;
  334.             door->topheight = P_FindLowestCeilingSurrounding(sec);
  335.             door->topheight -= 4*FRACUNIT;
  336.             if (door->topheight != sec->ceilingheight)
  337.                 S_StartSound((mobj_t *)&door->sector->soundorg,
  338.                              sfx_doropn);
  339.             break;
  340.            
  341.           default:
  342.             break;
  343.         }
  344.                
  345.     }
  346.     return rtn;
  347. }
  348.  
  349.  
  350. //
  351. // EV_VerticalDoor : open a door manually, no tag value
  352. //
  353. void
  354. EV_VerticalDoor
  355. ( line_t*       line,
  356.   mobj_t*       thing )
  357. {
  358.     player_t*   player;
  359.     int         secnum;
  360.     sector_t*   sec;
  361.     vldoor_t*   door;
  362.     int         side;
  363.        
  364.     side = 0;   // only front sides can be used
  365.  
  366.     //  Check for locks
  367.     player = thing->player;
  368.                
  369.     switch(line->special)
  370.     {
  371.       case 26: // Blue Lock
  372.       case 32:
  373.         if ( !player )
  374.             return;
  375.        
  376.         if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
  377.         {
  378.             player->message = PD_BLUEK;
  379.             S_StartSound(NULL,sfx_oof);
  380.             return;
  381.         }
  382.         break;
  383.        
  384.       case 27: // Yellow Lock
  385.       case 34:
  386.         if ( !player )
  387.             return;
  388.        
  389.         if (!player->cards[it_yellowcard] &&
  390.             !player->cards[it_yellowskull])
  391.         {
  392.             player->message = PD_YELLOWK;
  393.             S_StartSound(NULL,sfx_oof);
  394.             return;
  395.         }
  396.         break;
  397.        
  398.       case 28: // Red Lock
  399.       case 33:
  400.         if ( !player )
  401.             return;
  402.        
  403.         if (!player->cards[it_redcard] && !player->cards[it_redskull])
  404.         {
  405.             player->message = PD_REDK;
  406.             S_StartSound(NULL,sfx_oof);
  407.             return;
  408.         }
  409.         break;
  410.     }
  411.        
  412.     // if the sector has an active thinker, use it
  413.     sec = sides[ line->sidenum[side^1]] .sector;
  414.     secnum = sec-sectors;
  415.  
  416.     if (sec->specialdata)
  417.     {
  418.         door = sec->specialdata;
  419.         switch(line->special)
  420.         {
  421.           case  1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
  422.           case  26:
  423.           case  27:
  424.           case  28:
  425.           case  117:
  426.             if (door->direction == -1)
  427.                 door->direction = 1;    // go back up
  428.             else
  429.             {
  430.                 if (!thing->player)
  431.                     return;             // JDC: bad guys never close doors
  432.                
  433.                 door->direction = -1;   // start going down immediately
  434.             }
  435.             return;
  436.         }
  437.     }
  438.        
  439.     // for proper sound
  440.     switch(line->special)
  441.     {
  442.       case 117: // BLAZING DOOR RAISE
  443.       case 118: // BLAZING DOOR OPEN
  444.         S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
  445.         break;
  446.        
  447.       case 1:   // NORMAL DOOR SOUND
  448.       case 31:
  449.         S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
  450.         break;
  451.        
  452.       default:  // LOCKED DOOR SOUND
  453.         S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
  454.         break;
  455.     }
  456.        
  457.    
  458.     // new door thinker
  459.     door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
  460.     P_AddThinker (&door->thinker);
  461.     sec->specialdata = door;
  462.     door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
  463.     door->sector = sec;
  464.     door->direction = 1;
  465.     door->speed = VDOORSPEED;
  466.     door->topwait = VDOORWAIT;
  467.  
  468.     switch(line->special)
  469.     {
  470.       case 1:
  471.       case 26:
  472.       case 27:
  473.       case 28:
  474.         door->type = normal;
  475.         break;
  476.        
  477.       case 31:
  478.       case 32:
  479.       case 33:
  480.       case 34:
  481.         door->type = open;
  482.         line->special = 0;
  483.         break;
  484.        
  485.       case 117: // blazing door raise
  486.         door->type = blazeRaise;
  487.         door->speed = VDOORSPEED*4;
  488.         break;
  489.       case 118: // blazing door open
  490.         door->type = blazeOpen;
  491.         line->special = 0;
  492.         door->speed = VDOORSPEED*4;
  493.         break;
  494.     }
  495.    
  496.     // find the top and bottom of the movement range
  497.     door->topheight = P_FindLowestCeilingSurrounding(sec);
  498.     door->topheight -= 4*FRACUNIT;
  499. }
  500.  
  501.  
  502. //
  503. // Spawn a door that closes after 30 seconds
  504. //
  505. void P_SpawnDoorCloseIn30 (sector_t* sec)
  506. {
  507.     vldoor_t*   door;
  508.        
  509.     door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
  510.  
  511.     P_AddThinker (&door->thinker);
  512.  
  513.     sec->specialdata = door;
  514.     sec->special = 0;
  515.  
  516.     door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
  517.     door->sector = sec;
  518.     door->direction = 0;
  519.     door->type = normal;
  520.     door->speed = VDOORSPEED;
  521.     door->topcountdown = 30 * 35;
  522. }
  523.  
  524. //
  525. // Spawn a door that opens after 5 minutes
  526. //
  527. void
  528. P_SpawnDoorRaiseIn5Mins
  529. ( sector_t*     sec,
  530.   int           secnum )
  531. {
  532.     vldoor_t*   door;
  533.        
  534.     door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
  535.    
  536.     P_AddThinker (&door->thinker);
  537.  
  538.     sec->specialdata = door;
  539.     sec->special = 0;
  540.  
  541.     door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
  542.     door->sector = sec;
  543.     door->direction = 2;
  544.     door->type = raiseIn5Mins;
  545.     door->speed = VDOORSPEED;
  546.     door->topheight = P_FindLowestCeilingSurrounding(sec);
  547.     door->topheight -= 4*FRACUNIT;
  548.     door->topwait = VDOORWAIT;
  549.     door->topcountdown = 5 * 60 * 35;
  550. }
  551.  
  552.  
  553.  
  554. // UNUSED
  555. // Separate into p_slidoor.c?
  556.  
  557. #if 0           // ABANDONED TO THE MISTS OF TIME!!!
  558. //
  559. // EV_SlidingDoor : slide a door horizontally
  560. // (animate midtexture, then set noblocking line)
  561. //
  562.  
  563.  
  564. slideframe_t slideFrames[MAXSLIDEDOORS];
  565.  
  566. void P_InitSlidingDoorFrames(void)
  567. {
  568.     int         i;
  569.     int         f1;
  570.     int         f2;
  571.     int         f3;
  572.     int         f4;
  573.        
  574.     // DOOM II ONLY...
  575.     if ( gamemode != commercial)
  576.         return;
  577.        
  578.     for (i = 0;i < MAXSLIDEDOORS; i++)
  579.     {
  580.         if (!slideFrameNames[i].frontFrame1[0])
  581.             break;
  582.                        
  583.         f1 = R_TextureNumForName(slideFrameNames[i].frontFrame1);
  584.         f2 = R_TextureNumForName(slideFrameNames[i].frontFrame2);
  585.         f3 = R_TextureNumForName(slideFrameNames[i].frontFrame3);
  586.         f4 = R_TextureNumForName(slideFrameNames[i].frontFrame4);
  587.  
  588.         slideFrames[i].frontFrames[0] = f1;
  589.         slideFrames[i].frontFrames[1] = f2;
  590.         slideFrames[i].frontFrames[2] = f3;
  591.         slideFrames[i].frontFrames[3] = f4;
  592.                
  593.         f1 = R_TextureNumForName(slideFrameNames[i].backFrame1);
  594.         f2 = R_TextureNumForName(slideFrameNames[i].backFrame2);
  595.         f3 = R_TextureNumForName(slideFrameNames[i].backFrame3);
  596.         f4 = R_TextureNumForName(slideFrameNames[i].backFrame4);
  597.  
  598.         slideFrames[i].backFrames[0] = f1;
  599.         slideFrames[i].backFrames[1] = f2;
  600.         slideFrames[i].backFrames[2] = f3;
  601.         slideFrames[i].backFrames[3] = f4;
  602.     }
  603. }
  604.  
  605.  
  606. //
  607. // Return index into "slideFrames" array
  608. // for which door type to use
  609. //
  610. int P_FindSlidingDoorType(line_t*       line)
  611. {
  612.     int         i;
  613.     int         val;
  614.        
  615.     for (i = 0;i < MAXSLIDEDOORS;i++)
  616.     {
  617.         val = sides[line->sidenum[0]].midtexture;
  618.         if (val == slideFrames[i].frontFrames[0])
  619.             return i;
  620.     }
  621.        
  622.     return -1;
  623. }
  624.  
  625. void T_SlidingDoor (slidedoor_t*        door)
  626. {
  627.     switch(door->status)
  628.     {
  629.       case sd_opening:
  630.         if (!door->timer--)
  631.         {
  632.             if (++door->frame == SNUMFRAMES)
  633.             {
  634.                 // IF DOOR IS DONE OPENING...
  635.                 sides[door->line->sidenum[0]].midtexture = 0;
  636.                 sides[door->line->sidenum[1]].midtexture = 0;
  637.                 door->line->flags &= ML_BLOCKING^0xff;
  638.                                        
  639.                 if (door->type == sdt_openOnly)
  640.                 {
  641.                     door->frontsector->specialdata = NULL;
  642.                     P_RemoveThinker (&door->thinker);
  643.                     break;
  644.                 }
  645.                                        
  646.                 door->timer = SDOORWAIT;
  647.                 door->status = sd_waiting;
  648.             }
  649.             else
  650.             {
  651.                 // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
  652.                 door->timer = SWAITTICS;
  653.                                        
  654.                 sides[door->line->sidenum[0]].midtexture =
  655.                     slideFrames[door->whichDoorIndex].
  656.                     frontFrames[door->frame];
  657.                 sides[door->line->sidenum[1]].midtexture =
  658.                     slideFrames[door->whichDoorIndex].
  659.                     backFrames[door->frame];
  660.             }
  661.         }
  662.         break;
  663.                        
  664.       case sd_waiting:
  665.         // IF DOOR IS DONE WAITING...
  666.         if (!door->timer--)
  667.         {
  668.             // CAN DOOR CLOSE?
  669.             if (door->frontsector->thinglist != NULL ||
  670.                 door->backsector->thinglist != NULL)
  671.             {
  672.                 door->timer = SDOORWAIT;
  673.                 break;
  674.             }
  675.  
  676.             //door->frame = SNUMFRAMES-1;
  677.             door->status = sd_closing;
  678.             door->timer = SWAITTICS;
  679.         }
  680.         break;
  681.                        
  682.       case sd_closing:
  683.         if (!door->timer--)
  684.         {
  685.             if (--door->frame < 0)
  686.             {
  687.                 // IF DOOR IS DONE CLOSING...
  688.                 door->line->flags |= ML_BLOCKING;
  689.                 door->frontsector->specialdata = NULL;
  690.                 P_RemoveThinker (&door->thinker);
  691.                 break;
  692.             }
  693.             else
  694.             {
  695.                 // IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
  696.                 door->timer = SWAITTICS;
  697.                                        
  698.                 sides[door->line->sidenum[0]].midtexture =
  699.                     slideFrames[door->whichDoorIndex].
  700.                     frontFrames[door->frame];
  701.                 sides[door->line->sidenum[1]].midtexture =
  702.                     slideFrames[door->whichDoorIndex].
  703.                     backFrames[door->frame];
  704.             }
  705.         }
  706.         break;
  707.     }
  708. }
  709.  
  710.  
  711.  
  712. void
  713. EV_SlidingDoor
  714. ( line_t*       line,
  715.   mobj_t*       thing )
  716. {
  717.     sector_t*           sec;
  718.     slidedoor_t*        door;
  719.        
  720.     // DOOM II ONLY...
  721.     if (gamemode != commercial)
  722.         return;
  723.    
  724.     // Make sure door isn't already being animated
  725.     sec = line->frontsector;
  726.     door = NULL;
  727.     if (sec->specialdata)
  728.     {
  729.         if (!thing->player)
  730.             return;
  731.                        
  732.         door = sec->specialdata;
  733.         if (door->type == sdt_openAndClose)
  734.         {
  735.             if (door->status == sd_waiting)
  736.                 door->status = sd_closing;
  737.         }
  738.         else
  739.             return;
  740.     }
  741.    
  742.     // Init sliding door vars
  743.     if (!door)
  744.     {
  745.         door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
  746.         P_AddThinker (&door->thinker);
  747.         sec->specialdata = door;
  748.                
  749.         door->type = sdt_openAndClose;
  750.         door->status = sd_opening;
  751.         door->whichDoorIndex = P_FindSlidingDoorType(line);
  752.  
  753.         if (door->whichDoorIndex < 0)
  754.             I_Error("EV_SlidingDoor: Can't use texture for sliding door!");
  755.                        
  756.         door->frontsector = sec;
  757.         door->backsector = line->backsector;
  758.         door->thinker.function = T_SlidingDoor;
  759.         door->timer = SWAITTICS;
  760.         door->frame = 0;
  761.         door->line = line;
  762.     }
  763. }
  764. #endif
  765.