Subversion Repositories Kolibri OS

Rev

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