p_doors.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:16k
源码类别:

射击游戏

开发平台:

Visual C++

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