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

射击游戏

开发平台:

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:
  20. // Implements special effects:
  21. // Texture animation, height or lighting changes
  22. //  according to adjacent sectors, respective
  23. //  utility functions, etc.
  24. // Line Tag handling. Line and Sector triggers.
  25. //
  26. //-----------------------------------------------------------------------------
  27. static const char
  28. rcsid[] = "$Id: p_spec.c,v 1.6 1997/02/03 22:45:12 b1 Exp $";
  29. #include <stdlib.h>
  30. #include "doomdef.h"
  31. #include "doomstat.h"
  32. #include "i_system.h"
  33. #include "z_zone.h"
  34. #include "m_argv.h"
  35. #include "m_random.h"
  36. #include "w_wad.h"
  37. #include "r_local.h"
  38. #include "p_local.h"
  39. #include "g_game.h"
  40. #include "s_sound.h"
  41. // State.
  42. #include "r_state.h"
  43. // Data.
  44. #include "sounds.h"
  45. //
  46. // Animating textures and planes
  47. // There is another anim_t used in wi_stuff, unrelated.
  48. //
  49. typedef struct
  50. {
  51.     boolean istexture;
  52.     int picnum;
  53.     int basepic;
  54.     int numpics;
  55.     int speed;
  56.     
  57. } anim_t;
  58. //
  59. //      source animation definition
  60. //
  61. typedef struct
  62. {
  63.     boolean istexture; // if false, it is a flat
  64.     char endname[9];
  65.     char startname[9];
  66.     int speed;
  67. } animdef_t;
  68. #define MAXANIMS                32
  69. extern anim_t anims[MAXANIMS];
  70. extern anim_t* lastanim;
  71. //
  72. // P_InitPicAnims
  73. //
  74. // Floor/ceiling animation sequences,
  75. //  defined by first and last frame,
  76. //  i.e. the flat (64x64 tile) name to
  77. //  be used.
  78. // The full animation sequence is given
  79. //  using all the flats between the start
  80. //  and end entry, in the order found in
  81. //  the WAD file.
  82. //
  83. animdef_t animdefs[] =
  84. {
  85.     {false, "NUKAGE3", "NUKAGE1", 8},
  86.     {false, "FWATER4", "FWATER1", 8},
  87.     {false, "SWATER4", "SWATER1",  8},
  88.     {false, "LAVA4", "LAVA1", 8},
  89.     {false, "BLOOD3", "BLOOD1", 8},
  90.     // DOOM II flat animations.
  91.     {false, "RROCK08", "RROCK05", 8},
  92.     {false, "SLIME04", "SLIME01", 8},
  93.     {false, "SLIME08", "SLIME05", 8},
  94.     {false, "SLIME12", "SLIME09", 8},
  95.     {true, "BLODGR4", "BLODGR1", 8},
  96.     {true, "SLADRIP3", "SLADRIP1", 8},
  97.     {true, "BLODRIP4", "BLODRIP1", 8},
  98.     {true, "FIREWALL", "FIREWALA", 8},
  99.     {true, "GSTFONT3", "GSTFONT1", 8},
  100.     {true, "FIRELAVA", "FIRELAV3", 8},
  101.     {true, "FIREMAG3", "FIREMAG1", 8},
  102.     {true, "FIREBLU2", "FIREBLU1", 8},
  103.     {true, "ROCKRED3", "ROCKRED1", 8},
  104.     {true, "BFALL4", "BFALL1", 8},
  105.     {true, "SFALL4", "SFALL1", 8},
  106.     {true, "WFALL4", "WFALL1", 8},
  107.     {true, "DBRAIN4", "DBRAIN1", 8},
  108.     {-1}
  109. };
  110. anim_t anims[MAXANIMS];
  111. anim_t* lastanim;
  112. //
  113. //      Animating line specials
  114. //
  115. #define MAXLINEANIMS            64
  116. extern  short numlinespecials;
  117. extern  line_t* linespeciallist[MAXLINEANIMS];
  118. void P_InitPicAnims (void)
  119. {
  120.     int i;
  121.     
  122.     // Init animation
  123.     lastanim = anims;
  124.     for (i=0 ; animdefs[i].istexture != -1 ; i++)
  125.     {
  126. if (animdefs[i].istexture)
  127. {
  128.     // different episode ?
  129.     if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
  130. continue;
  131.     lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
  132.     lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
  133. }
  134. else
  135. {
  136.     if (W_CheckNumForName(animdefs[i].startname) == -1)
  137. continue;
  138.     lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
  139.     lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
  140. }
  141. lastanim->istexture = animdefs[i].istexture;
  142. lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
  143. if (lastanim->numpics < 2)
  144.     I_Error ("P_InitPicAnims: bad cycle from %s to %s",
  145.      animdefs[i].startname,
  146.      animdefs[i].endname);
  147. lastanim->speed = animdefs[i].speed;
  148. lastanim++;
  149.     }
  150. }
  151. //
  152. // UTILITIES
  153. //
  154. //
  155. // getSide()
  156. // Will return a side_t*
  157. //  given the number of the current sector,
  158. //  the line number, and the side (0/1) that you want.
  159. //
  160. side_t*
  161. getSide
  162. ( int currentSector,
  163.   int line,
  164.   int side )
  165. {
  166.     return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
  167. }
  168. //
  169. // getSector()
  170. // Will return a sector_t*
  171. //  given the number of the current sector,
  172. //  the line number and the side (0/1) that you want.
  173. //
  174. sector_t*
  175. getSector
  176. ( int currentSector,
  177.   int line,
  178.   int side )
  179. {
  180.     return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
  181. }
  182. //
  183. // twoSided()
  184. // Given the sector number and the line number,
  185. //  it will tell you whether the line is two-sided or not.
  186. //
  187. int
  188. twoSided
  189. ( int sector,
  190.   int line )
  191. {
  192.     return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
  193. }
  194. //
  195. // getNextSector()
  196. // Return sector_t * of sector next to current.
  197. // NULL if not two-sided line
  198. //
  199. sector_t*
  200. getNextSector
  201. ( line_t* line,
  202.   sector_t* sec )
  203. {
  204.     if (!(line->flags & ML_TWOSIDED))
  205. return NULL;
  206.     if (line->frontsector == sec)
  207. return line->backsector;
  208.     return line->frontsector;
  209. }
  210. //
  211. // P_FindLowestFloorSurrounding()
  212. // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
  213. //
  214. fixed_t P_FindLowestFloorSurrounding(sector_t* sec)
  215. {
  216.     int i;
  217.     line_t* check;
  218.     sector_t* other;
  219.     fixed_t floor = sec->floorheight;
  220.     for (i=0 ;i < sec->linecount ; i++)
  221.     {
  222. check = sec->lines[i];
  223. other = getNextSector(check,sec);
  224. if (!other)
  225.     continue;
  226. if (other->floorheight < floor)
  227.     floor = other->floorheight;
  228.     }
  229.     return floor;
  230. }
  231. //
  232. // P_FindHighestFloorSurrounding()
  233. // FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
  234. //
  235. fixed_t P_FindHighestFloorSurrounding(sector_t *sec)
  236. {
  237.     int i;
  238.     line_t* check;
  239.     sector_t* other;
  240.     fixed_t floor = -500*FRACUNIT;
  241.     for (i=0 ;i < sec->linecount ; i++)
  242.     {
  243. check = sec->lines[i];
  244. other = getNextSector(check,sec);
  245. if (!other)
  246.     continue;
  247. if (other->floorheight > floor)
  248.     floor = other->floorheight;
  249.     }
  250.     return floor;
  251. }
  252. //
  253. // P_FindNextHighestFloor
  254. // FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
  255. // Note: this should be doable w/o a fixed array.
  256. // 20 adjoining sectors max!
  257. #define MAX_ADJOINING_SECTORS     20
  258. fixed_t
  259. P_FindNextHighestFloor
  260. ( sector_t* sec,
  261.   int currentheight )
  262. {
  263.     int i;
  264.     int h;
  265.     int min;
  266.     line_t* check;
  267.     sector_t* other;
  268.     fixed_t height = currentheight;
  269.     
  270.     fixed_t heightlist[MAX_ADJOINING_SECTORS];
  271.     for (i=0, h=0 ;i < sec->linecount ; i++)
  272.     {
  273. check = sec->lines[i];
  274. other = getNextSector(check,sec);
  275. if (!other)
  276.     continue;
  277. if (other->floorheight > height)
  278.     heightlist[h++] = other->floorheight;
  279. // Check for overflow. Exit.
  280. if ( h >= MAX_ADJOINING_SECTORS )
  281. {
  282.     fprintf( stderr,
  283.      "Sector with more than 20 adjoining sectorsn" );
  284.     break;
  285. }
  286.     }
  287.     
  288.     // Find lowest height in list
  289.     if (!h)
  290. return currentheight;
  291.     min = heightlist[0];
  292.     
  293.     // Range checking? 
  294.     for (i = 1;i < h;i++)
  295. if (heightlist[i] < min)
  296.     min = heightlist[i];
  297.     return min;
  298. }
  299. //
  300. // FIND LOWEST CEILING IN THE SURROUNDING SECTORS
  301. //
  302. fixed_t
  303. P_FindLowestCeilingSurrounding(sector_t* sec)
  304. {
  305.     int i;
  306.     line_t* check;
  307.     sector_t* other;
  308.     fixed_t height = MAXINT;
  309.     for (i=0 ;i < sec->linecount ; i++)
  310.     {
  311. check = sec->lines[i];
  312. other = getNextSector(check,sec);
  313. if (!other)
  314.     continue;
  315. if (other->ceilingheight < height)
  316.     height = other->ceilingheight;
  317.     }
  318.     return height;
  319. }
  320. //
  321. // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
  322. //
  323. fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
  324. {
  325.     int i;
  326.     line_t* check;
  327.     sector_t* other;
  328.     fixed_t height = 0;
  329.     for (i=0 ;i < sec->linecount ; i++)
  330.     {
  331. check = sec->lines[i];
  332. other = getNextSector(check,sec);
  333. if (!other)
  334.     continue;
  335. if (other->ceilingheight > height)
  336.     height = other->ceilingheight;
  337.     }
  338.     return height;
  339. }
  340. //
  341. // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
  342. //
  343. int
  344. P_FindSectorFromLineTag
  345. ( line_t* line,
  346.   int start )
  347. {
  348.     int i;
  349.     for (i=start+1;i<numsectors;i++)
  350. if (sectors[i].tag == line->tag)
  351.     return i;
  352.     
  353.     return -1;
  354. }
  355. //
  356. // Find minimum light from an adjacent sector
  357. //
  358. int
  359. P_FindMinSurroundingLight
  360. ( sector_t* sector,
  361.   int max )
  362. {
  363.     int i;
  364.     int min;
  365.     line_t* line;
  366.     sector_t* check;
  367.     min = max;
  368.     for (i=0 ; i < sector->linecount ; i++)
  369.     {
  370. line = sector->lines[i];
  371. check = getNextSector(line,sector);
  372. if (!check)
  373.     continue;
  374. if (check->lightlevel < min)
  375.     min = check->lightlevel;
  376.     }
  377.     return min;
  378. }
  379. //
  380. // EVENTS
  381. // Events are operations triggered by using, crossing,
  382. // or shooting special lines, or by timed thinkers.
  383. //
  384. //
  385. // P_CrossSpecialLine - TRIGGER
  386. // Called every time a thing origin is about
  387. //  to cross a line with a non 0 special.
  388. //
  389. void
  390. P_CrossSpecialLine
  391. ( int linenum,
  392.   int side,
  393.   mobj_t* thing )
  394. {
  395.     line_t* line;
  396.     int ok;
  397.     line = &lines[linenum];
  398.     
  399.     // Triggers that other things can activate
  400.     if (!thing->player)
  401.     {
  402. // Things that should NOT trigger specials...
  403. switch(thing->type)
  404. {
  405.   case MT_ROCKET:
  406.   case MT_PLASMA:
  407.   case MT_BFG:
  408.   case MT_TROOPSHOT:
  409.   case MT_HEADSHOT:
  410.   case MT_BRUISERSHOT:
  411.     return;
  412.     break;
  413.     
  414.   default: break;
  415. }
  416. ok = 0;
  417. switch(line->special)
  418. {
  419.   case 39: // TELEPORT TRIGGER
  420.   case 97: // TELEPORT RETRIGGER
  421.   case 125: // TELEPORT MONSTERONLY TRIGGER
  422.   case 126: // TELEPORT MONSTERONLY RETRIGGER
  423.   case 4: // RAISE DOOR
  424.   case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER
  425.   case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER
  426.     ok = 1;
  427.     break;
  428. }
  429. if (!ok)
  430.     return;
  431.     }
  432.     
  433.     // Note: could use some const's here.
  434.     switch (line->special)
  435.     {
  436. // TRIGGERS.
  437. // All from here to RETRIGGERS.
  438.       case 2:
  439. // Open Door
  440. EV_DoDoor(line,open);
  441. line->special = 0;
  442. break;
  443.       case 3:
  444. // Close Door
  445. EV_DoDoor(line,close);
  446. line->special = 0;
  447. break;
  448.       case 4:
  449. // Raise Door
  450. EV_DoDoor(line,normal);
  451. line->special = 0;
  452. break;
  453.       case 5:
  454. // Raise Floor
  455. EV_DoFloor(line,raiseFloor);
  456. line->special = 0;
  457. break;
  458.       case 6:
  459. // Fast Ceiling Crush & Raise
  460. EV_DoCeiling(line,fastCrushAndRaise);
  461. line->special = 0;
  462. break;
  463.       case 8:
  464. // Build Stairs
  465. EV_BuildStairs(line,build8);
  466. line->special = 0;
  467. break;
  468.       case 10:
  469. // PlatDownWaitUp
  470. EV_DoPlat(line,downWaitUpStay,0);
  471. line->special = 0;
  472. break;
  473.       case 12:
  474. // Light Turn On - brightest near
  475. EV_LightTurnOn(line,0);
  476. line->special = 0;
  477. break;
  478.       case 13:
  479. // Light Turn On 255
  480. EV_LightTurnOn(line,255);
  481. line->special = 0;
  482. break;
  483.       case 16:
  484. // Close Door 30
  485. EV_DoDoor(line,close30ThenOpen);
  486. line->special = 0;
  487. break;
  488.       case 17:
  489. // Start Light Strobing
  490. EV_StartLightStrobing(line);
  491. line->special = 0;
  492. break;
  493.       case 19:
  494. // Lower Floor
  495. EV_DoFloor(line,lowerFloor);
  496. line->special = 0;
  497. break;
  498.       case 22:
  499. // Raise floor to nearest height and change texture
  500. EV_DoPlat(line,raiseToNearestAndChange,0);
  501. line->special = 0;
  502. break;
  503.       case 25:
  504. // Ceiling Crush and Raise
  505. EV_DoCeiling(line,crushAndRaise);
  506. line->special = 0;
  507. break;
  508.       case 30:
  509. // Raise floor to shortest texture height
  510. //  on either side of lines.
  511. EV_DoFloor(line,raiseToTexture);
  512. line->special = 0;
  513. break;
  514.       case 35:
  515. // Lights Very Dark
  516. EV_LightTurnOn(line,35);
  517. line->special = 0;
  518. break;
  519.       case 36:
  520. // Lower Floor (TURBO)
  521. EV_DoFloor(line,turboLower);
  522. line->special = 0;
  523. break;
  524.       case 37:
  525. // LowerAndChange
  526. EV_DoFloor(line,lowerAndChange);
  527. line->special = 0;
  528. break;
  529.       case 38:
  530. // Lower Floor To Lowest
  531. EV_DoFloor( line, lowerFloorToLowest );
  532. line->special = 0;
  533. break;
  534.       case 39:
  535. // TELEPORT!
  536. EV_Teleport( line, side, thing );
  537. line->special = 0;
  538. break;
  539.       case 40:
  540. // RaiseCeilingLowerFloor
  541. EV_DoCeiling( line, raiseToHighest );
  542. EV_DoFloor( line, lowerFloorToLowest );
  543. line->special = 0;
  544. break;
  545.       case 44:
  546. // Ceiling Crush
  547. EV_DoCeiling( line, lowerAndCrush );
  548. line->special = 0;
  549. break;
  550.       case 52:
  551. // EXIT!
  552. G_ExitLevel ();
  553. break;
  554.       case 53:
  555. // Perpetual Platform Raise
  556. EV_DoPlat(line,perpetualRaise,0);
  557. line->special = 0;
  558. break;
  559.       case 54:
  560. // Platform Stop
  561. EV_StopPlat(line);
  562. line->special = 0;
  563. break;
  564.       case 56:
  565. // Raise Floor Crush
  566. EV_DoFloor(line,raiseFloorCrush);
  567. line->special = 0;
  568. break;
  569.       case 57:
  570. // Ceiling Crush Stop
  571. EV_CeilingCrushStop(line);
  572. line->special = 0;
  573. break;
  574.       case 58:
  575. // Raise Floor 24
  576. EV_DoFloor(line,raiseFloor24);
  577. line->special = 0;
  578. break;
  579.       case 59:
  580. // Raise Floor 24 And Change
  581. EV_DoFloor(line,raiseFloor24AndChange);
  582. line->special = 0;
  583. break;
  584.       case 104:
  585. // Turn lights off in sector(tag)
  586. EV_TurnTagLightsOff(line);
  587. line->special = 0;
  588. break;
  589.       case 108:
  590. // Blazing Door Raise (faster than TURBO!)
  591. EV_DoDoor (line,blazeRaise);
  592. line->special = 0;
  593. break;
  594.       case 109:
  595. // Blazing Door Open (faster than TURBO!)
  596. EV_DoDoor (line,blazeOpen);
  597. line->special = 0;
  598. break;
  599.       case 100:
  600. // Build Stairs Turbo 16
  601. EV_BuildStairs(line,turbo16);
  602. line->special = 0;
  603. break;
  604.       case 110:
  605. // Blazing Door Close (faster than TURBO!)
  606. EV_DoDoor (line,blazeClose);
  607. line->special = 0;
  608. break;
  609.       case 119:
  610. // Raise floor to nearest surr. floor
  611. EV_DoFloor(line,raiseFloorToNearest);
  612. line->special = 0;
  613. break;
  614.       case 121:
  615. // Blazing PlatDownWaitUpStay
  616. EV_DoPlat(line,blazeDWUS,0);
  617. line->special = 0;
  618. break;
  619.       case 124:
  620. // Secret EXIT
  621. G_SecretExitLevel ();
  622. break;
  623.       case 125:
  624. // TELEPORT MonsterONLY
  625. if (!thing->player)
  626. {
  627.     EV_Teleport( line, side, thing );
  628.     line->special = 0;
  629. }
  630. break;
  631.       case 130:
  632. // Raise Floor Turbo
  633. EV_DoFloor(line,raiseFloorTurbo);
  634. line->special = 0;
  635. break;
  636.       case 141:
  637. // Silent Ceiling Crush & Raise
  638. EV_DoCeiling(line,silentCrushAndRaise);
  639. line->special = 0;
  640. break;
  641. // RETRIGGERS.  All from here till end.
  642.       case 72:
  643. // Ceiling Crush
  644. EV_DoCeiling( line, lowerAndCrush );
  645. break;
  646.       case 73:
  647. // Ceiling Crush and Raise
  648. EV_DoCeiling(line,crushAndRaise);
  649. break;
  650.       case 74:
  651. // Ceiling Crush Stop
  652. EV_CeilingCrushStop(line);
  653. break;
  654.       case 75:
  655. // Close Door
  656. EV_DoDoor(line,close);
  657. break;
  658.       case 76:
  659. // Close Door 30
  660. EV_DoDoor(line,close30ThenOpen);
  661. break;
  662.       case 77:
  663. // Fast Ceiling Crush & Raise
  664. EV_DoCeiling(line,fastCrushAndRaise);
  665. break;
  666.       case 79:
  667. // Lights Very Dark
  668. EV_LightTurnOn(line,35);
  669. break;
  670.       case 80:
  671. // Light Turn On - brightest near
  672. EV_LightTurnOn(line,0);
  673. break;
  674.       case 81:
  675. // Light Turn On 255
  676. EV_LightTurnOn(line,255);
  677. break;
  678.       case 82:
  679. // Lower Floor To Lowest
  680. EV_DoFloor( line, lowerFloorToLowest );
  681. break;
  682.       case 83:
  683. // Lower Floor
  684. EV_DoFloor(line,lowerFloor);
  685. break;
  686.       case 84:
  687. // LowerAndChange
  688. EV_DoFloor(line,lowerAndChange);
  689. break;
  690.       case 86:
  691. // Open Door
  692. EV_DoDoor(line,open);
  693. break;
  694.       case 87:
  695. // Perpetual Platform Raise
  696. EV_DoPlat(line,perpetualRaise,0);
  697. break;
  698.       case 88:
  699. // PlatDownWaitUp
  700. EV_DoPlat(line,downWaitUpStay,0);
  701. break;
  702.       case 89:
  703. // Platform Stop
  704. EV_StopPlat(line);
  705. break;
  706.       case 90:
  707. // Raise Door
  708. EV_DoDoor(line,normal);
  709. break;
  710.       case 91:
  711. // Raise Floor
  712. EV_DoFloor(line,raiseFloor);
  713. break;
  714.       case 92:
  715. // Raise Floor 24
  716. EV_DoFloor(line,raiseFloor24);
  717. break;
  718.       case 93:
  719. // Raise Floor 24 And Change
  720. EV_DoFloor(line,raiseFloor24AndChange);
  721. break;
  722.       case 94:
  723. // Raise Floor Crush
  724. EV_DoFloor(line,raiseFloorCrush);
  725. break;
  726.       case 95:
  727. // Raise floor to nearest height
  728. // and change texture.
  729. EV_DoPlat(line,raiseToNearestAndChange,0);
  730. break;
  731.       case 96:
  732. // Raise floor to shortest texture height
  733. // on either side of lines.
  734. EV_DoFloor(line,raiseToTexture);
  735. break;
  736.       case 97:
  737. // TELEPORT!
  738. EV_Teleport( line, side, thing );
  739. break;
  740.       case 98:
  741. // Lower Floor (TURBO)
  742. EV_DoFloor(line,turboLower);
  743. break;
  744.       case 105:
  745. // Blazing Door Raise (faster than TURBO!)
  746. EV_DoDoor (line,blazeRaise);
  747. break;
  748.       case 106:
  749. // Blazing Door Open (faster than TURBO!)
  750. EV_DoDoor (line,blazeOpen);
  751. break;
  752.       case 107:
  753. // Blazing Door Close (faster than TURBO!)
  754. EV_DoDoor (line,blazeClose);
  755. break;
  756.       case 120:
  757. // Blazing PlatDownWaitUpStay.
  758. EV_DoPlat(line,blazeDWUS,0);
  759. break;
  760.       case 126:
  761. // TELEPORT MonsterONLY.
  762. if (!thing->player)
  763.     EV_Teleport( line, side, thing );
  764. break;
  765.       case 128:
  766. // Raise To Nearest Floor
  767. EV_DoFloor(line,raiseFloorToNearest);
  768. break;
  769.       case 129:
  770. // Raise Floor Turbo
  771. EV_DoFloor(line,raiseFloorTurbo);
  772. break;
  773.     }
  774. }
  775. //
  776. // P_ShootSpecialLine - IMPACT SPECIALS
  777. // Called when a thing shoots a special line.
  778. //
  779. void
  780. P_ShootSpecialLine
  781. ( mobj_t* thing,
  782.   line_t* line )
  783. {
  784.     int ok;
  785.     
  786.     // Impacts that other things can activate.
  787.     if (!thing->player)
  788.     {
  789. ok = 0;
  790. switch(line->special)
  791. {
  792.   case 46:
  793.     // OPEN DOOR IMPACT
  794.     ok = 1;
  795.     break;
  796. }
  797. if (!ok)
  798.     return;
  799.     }
  800.     switch(line->special)
  801.     {
  802.       case 24:
  803. // RAISE FLOOR
  804. EV_DoFloor(line,raiseFloor);
  805. P_ChangeSwitchTexture(line,0);
  806. break;
  807.       case 46:
  808. // OPEN DOOR
  809. EV_DoDoor(line,open);
  810. P_ChangeSwitchTexture(line,1);
  811. break;
  812.       case 47:
  813. // RAISE FLOOR NEAR AND CHANGE
  814. EV_DoPlat(line,raiseToNearestAndChange,0);
  815. P_ChangeSwitchTexture(line,0);
  816. break;
  817.     }
  818. }
  819. //
  820. // P_PlayerInSpecialSector
  821. // Called every tic frame
  822. //  that the player origin is in a special sector
  823. //
  824. void P_PlayerInSpecialSector (player_t* player)
  825. {
  826.     sector_t* sector;
  827.     sector = player->mo->subsector->sector;
  828.     // Falling, not all the way down yet?
  829.     if (player->mo->z != sector->floorheight)
  830. return;
  831.     // Has hitten ground.
  832.     switch (sector->special)
  833.     {
  834.       case 5:
  835. // HELLSLIME DAMAGE
  836. if (!player->powers[pw_ironfeet])
  837.     if (!(leveltime&0x1f))
  838. P_DamageMobj (player->mo, NULL, NULL, 10);
  839. break;
  840.       case 7:
  841. // NUKAGE DAMAGE
  842. if (!player->powers[pw_ironfeet])
  843.     if (!(leveltime&0x1f))
  844. P_DamageMobj (player->mo, NULL, NULL, 5);
  845. break;
  846.       case 16:
  847. // SUPER HELLSLIME DAMAGE
  848.       case 4:
  849. // STROBE HURT
  850. if (!player->powers[pw_ironfeet]
  851.     || (P_Random()<5) )
  852. {
  853.     if (!(leveltime&0x1f))
  854. P_DamageMobj (player->mo, NULL, NULL, 20);
  855. }
  856. break;
  857.       case 9:
  858. // SECRET SECTOR
  859. player->secretcount++;
  860. sector->special = 0;
  861. break;
  862.       case 11:
  863. // EXIT SUPER DAMAGE! (for E1M8 finale)
  864. player->cheats &= ~CF_GODMODE;
  865. if (!(leveltime&0x1f))
  866.     P_DamageMobj (player->mo, NULL, NULL, 20);
  867. if (player->health <= 10)
  868.     G_ExitLevel();
  869. break;
  870.       default:
  871. I_Error ("P_PlayerInSpecialSector: "
  872.  "unknown special %i",
  873.  sector->special);
  874. break;
  875.     };
  876. }
  877. //
  878. // P_UpdateSpecials
  879. // Animate planes, scroll walls, etc.
  880. //
  881. boolean levelTimer;
  882. int levelTimeCount;
  883. void P_UpdateSpecials (void)
  884. {
  885.     anim_t* anim;
  886.     int pic;
  887.     int i;
  888.     line_t* line;
  889.     
  890.     // LEVEL TIMER
  891.     if (levelTimer == true)
  892.     {
  893. levelTimeCount--;
  894. if (!levelTimeCount)
  895.     G_ExitLevel();
  896.     }
  897.     
  898.     // ANIMATE FLATS AND TEXTURES GLOBALLY
  899.     for (anim = anims ; anim < lastanim ; anim++)
  900.     {
  901. for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
  902. {
  903.     pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics );
  904.     if (anim->istexture)
  905. texturetranslation[i] = pic;
  906.     else
  907. flattranslation[i] = pic;
  908. }
  909.     }
  910.     
  911.     // ANIMATE LINE SPECIALS
  912.     for (i = 0; i < numlinespecials; i++)
  913.     {
  914. line = linespeciallist[i];
  915. switch(line->special)
  916. {
  917.   case 48:
  918.     // EFFECT FIRSTCOL SCROLL +
  919.     sides[line->sidenum[0]].textureoffset += FRACUNIT;
  920.     break;
  921. }
  922.     }
  923.     
  924.     // DO BUTTONS
  925.     for (i = 0; i < MAXBUTTONS; i++)
  926. if (buttonlist[i].btimer)
  927. {
  928.     buttonlist[i].btimer--;
  929.     if (!buttonlist[i].btimer)
  930.     {
  931. switch(buttonlist[i].where)
  932. {
  933.   case top:
  934.     sides[buttonlist[i].line->sidenum[0]].toptexture =
  935. buttonlist[i].btexture;
  936.     break;
  937.     
  938.   case middle:
  939.     sides[buttonlist[i].line->sidenum[0]].midtexture =
  940. buttonlist[i].btexture;
  941.     break;
  942.     
  943.   case bottom:
  944.     sides[buttonlist[i].line->sidenum[0]].bottomtexture =
  945. buttonlist[i].btexture;
  946.     break;
  947. }
  948. S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn);
  949. memset(&buttonlist[i],0,sizeof(button_t));
  950.     }
  951. }
  952. }
  953. //
  954. // Special Stuff that can not be categorized
  955. //
  956. int EV_DoDonut(line_t* line)
  957. {
  958.     sector_t* s1;
  959.     sector_t* s2;
  960.     sector_t* s3;
  961.     int secnum;
  962.     int rtn;
  963.     int i;
  964.     floormove_t* floor;
  965.     secnum = -1;
  966.     rtn = 0;
  967.     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  968.     {
  969. s1 = &sectors[secnum];
  970. // ALREADY MOVING?  IF SO, KEEP GOING...
  971. if (s1->specialdata)
  972.     continue;
  973. rtn = 1;
  974. s2 = getNextSector(s1->lines[0],s1);
  975. for (i = 0;i < s2->linecount;i++)
  976. {
  977.     if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
  978. (s2->lines[i]->backsector == s1))
  979. continue;
  980.     s3 = s2->lines[i]->backsector;
  981.     
  982.     // Spawn rising slime
  983.     floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  984.     P_AddThinker (&floor->thinker);
  985.     s2->specialdata = floor;
  986.     floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  987.     floor->type = donutRaise;
  988.     floor->crush = false;
  989.     floor->direction = 1;
  990.     floor->sector = s2;
  991.     floor->speed = FLOORSPEED / 2;
  992.     floor->texture = s3->floorpic;
  993.     floor->newspecial = 0;
  994.     floor->floordestheight = s3->floorheight;
  995.     
  996.     // Spawn lowering donut-hole
  997.     floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  998.     P_AddThinker (&floor->thinker);
  999.     s1->specialdata = floor;
  1000.     floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  1001.     floor->type = lowerFloor;
  1002.     floor->crush = false;
  1003.     floor->direction = -1;
  1004.     floor->sector = s1;
  1005.     floor->speed = FLOORSPEED / 2;
  1006.     floor->floordestheight = s3->floorheight;
  1007.     break;
  1008. }
  1009.     }
  1010.     return rtn;
  1011. }
  1012. //
  1013. // SPECIAL SPAWNING
  1014. //
  1015. //
  1016. // P_SpawnSpecials
  1017. // After the map has been loaded, scan for specials
  1018. //  that spawn thinkers
  1019. //
  1020. short numlinespecials;
  1021. line_t* linespeciallist[MAXLINEANIMS];
  1022. // Parses command line parameters.
  1023. void P_SpawnSpecials (void)
  1024. {
  1025.     sector_t* sector;
  1026.     int i;
  1027.     int episode;
  1028.     episode = 1;
  1029.     if (W_CheckNumForName("texture2") >= 0)
  1030. episode = 2;
  1031.     
  1032.     // See if -TIMER needs to be used.
  1033.     levelTimer = false;
  1034.     i = M_CheckParm("-avg");
  1035.     if (i && deathmatch)
  1036.     {
  1037. levelTimer = true;
  1038. levelTimeCount = 20 * 60 * 35;
  1039.     }
  1040.     i = M_CheckParm("-timer");
  1041.     if (i && deathmatch)
  1042.     {
  1043. int time;
  1044. time = atoi(myargv[i+1]) * 60 * 35;
  1045. levelTimer = true;
  1046. levelTimeCount = time;
  1047.     }
  1048.     
  1049.     // Init special SECTORs.
  1050.     sector = sectors;
  1051.     for (i=0 ; i<numsectors ; i++, sector++)
  1052.     {
  1053. if (!sector->special)
  1054.     continue;
  1055. switch (sector->special)
  1056. {
  1057.   case 1:
  1058.     // FLICKERING LIGHTS
  1059.     P_SpawnLightFlash (sector);
  1060.     break;
  1061.   case 2:
  1062.     // STROBE FAST
  1063.     P_SpawnStrobeFlash(sector,FASTDARK,0);
  1064.     break;
  1065.     
  1066.   case 3:
  1067.     // STROBE SLOW
  1068.     P_SpawnStrobeFlash(sector,SLOWDARK,0);
  1069.     break;
  1070.     
  1071.   case 4:
  1072.     // STROBE FAST/DEATH SLIME
  1073.     P_SpawnStrobeFlash(sector,FASTDARK,0);
  1074.     sector->special = 4;
  1075.     break;
  1076.     
  1077.   case 8:
  1078.     // GLOWING LIGHT
  1079.     P_SpawnGlowingLight(sector);
  1080.     break;
  1081.   case 9:
  1082.     // SECRET SECTOR
  1083.     totalsecret++;
  1084.     break;
  1085.     
  1086.   case 10:
  1087.     // DOOR CLOSE IN 30 SECONDS
  1088.     P_SpawnDoorCloseIn30 (sector);
  1089.     break;
  1090.     
  1091.   case 12:
  1092.     // SYNC STROBE SLOW
  1093.     P_SpawnStrobeFlash (sector, SLOWDARK, 1);
  1094.     break;
  1095.   case 13:
  1096.     // SYNC STROBE FAST
  1097.     P_SpawnStrobeFlash (sector, FASTDARK, 1);
  1098.     break;
  1099.   case 14:
  1100.     // DOOR RAISE IN 5 MINUTES
  1101.     P_SpawnDoorRaiseIn5Mins (sector, i);
  1102.     break;
  1103.     
  1104.   case 17:
  1105.     P_SpawnFireFlicker(sector);
  1106.     break;
  1107. }
  1108.     }
  1109.     
  1110.     // Init line EFFECTs
  1111.     numlinespecials = 0;
  1112.     for (i = 0;i < numlines; i++)
  1113.     {
  1114. switch(lines[i].special)
  1115. {
  1116.   case 48:
  1117.     // EFFECT FIRSTCOL SCROLL+
  1118.     linespeciallist[numlinespecials] = &lines[i];
  1119.     numlinespecials++;
  1120.     break;
  1121. }
  1122.     }
  1123.     
  1124.     // Init other misc stuff
  1125.     for (i = 0;i < MAXCEILINGS;i++)
  1126. activeceilings[i] = NULL;
  1127.     for (i = 0;i < MAXPLATS;i++)
  1128. activeplats[i] = NULL;
  1129.     
  1130.     for (i = 0;i < MAXBUTTONS;i++)
  1131. memset(&buttonlist[i],0,sizeof(button_t));
  1132.     // UNUSED: no horizonal sliders.
  1133.     // P_InitSlidingDoorFrames();
  1134. }