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:
  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. //          __libclog_printf("Sector with more than 20 adjoining sectors\n" );
  358.             break;
  359.         }
  360.     }
  361.    
  362.     // Find lowest height in list
  363.     if (!h)
  364.         return currentheight;
  365.                
  366.     min = heightlist[0];
  367.    
  368.     // Range checking?
  369.     for (i = 1;i < h;i++)
  370.         if (heightlist[i] < min)
  371.             min = heightlist[i];
  372.                        
  373.     return min;
  374. }
  375.  
  376.  
  377. //
  378. // FIND LOWEST CEILING IN THE SURROUNDING SECTORS
  379. //
  380. fixed_t
  381. P_FindLowestCeilingSurrounding(sector_t* sec)
  382. {
  383.     int                 i;
  384.     line_t*             check;
  385.     sector_t*           other;
  386.     fixed_t             height = MAXINT;
  387.        
  388.     for (i=0 ;i < sec->linecount ; i++)
  389.     {
  390.         check = sec->lines[i];
  391.         other = getNextSector(check,sec);
  392.  
  393.         if (!other)
  394.             continue;
  395.  
  396.         if (other->ceilingheight < height)
  397.             height = other->ceilingheight;
  398.     }
  399.     return height;
  400. }
  401.  
  402.  
  403. //
  404. // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
  405. //
  406. fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
  407. {
  408.     int         i;
  409.     line_t*     check;
  410.     sector_t*   other;
  411.     fixed_t     height = 0;
  412.        
  413.     for (i=0 ;i < sec->linecount ; i++)
  414.     {
  415.         check = sec->lines[i];
  416.         other = getNextSector(check,sec);
  417.  
  418.         if (!other)
  419.             continue;
  420.  
  421.         if (other->ceilingheight > height)
  422.             height = other->ceilingheight;
  423.     }
  424.     return height;
  425. }
  426.  
  427.  
  428.  
  429. //
  430. // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
  431. //
  432. int
  433. P_FindSectorFromLineTag
  434. ( line_t*       line,
  435.   int           start )
  436. {
  437.     int i;
  438.        
  439.     for (i=start+1;i<numsectors;i++)
  440.         if (sectors[i].tag == line->tag)
  441.             return i;
  442.    
  443.     return -1;
  444. }
  445.  
  446.  
  447.  
  448.  
  449. //
  450. // Find minimum light from an adjacent sector
  451. //
  452. int
  453. P_FindMinSurroundingLight
  454. ( sector_t*     sector,
  455.   int           max )
  456. {
  457.     int         i;
  458.     int         min;
  459.     line_t*     line;
  460.     sector_t*   check;
  461.        
  462.     min = max;
  463.     for (i=0 ; i < sector->linecount ; i++)
  464.     {
  465.         line = sector->lines[i];
  466.         check = getNextSector(line,sector);
  467.  
  468.         if (!check)
  469.             continue;
  470.  
  471.         if (check->lightlevel < min)
  472.             min = check->lightlevel;
  473.     }
  474.     return min;
  475. }
  476.  
  477.  
  478.  
  479. //
  480. // EVENTS
  481. // Events are operations triggered by using, crossing,
  482. // or shooting special lines, or by timed thinkers.
  483. //
  484.  
  485. //
  486. // P_CrossSpecialLine - TRIGGER
  487. // Called every time a thing origin is about
  488. //  to cross a line with a non 0 special.
  489. //
  490. void
  491. P_CrossSpecialLine
  492. ( int           linenum,
  493.   int           side,
  494.   mobj_t*       thing )
  495. {
  496.     line_t*     line;
  497.     int         ok;
  498.  
  499.     line = &lines[linenum];
  500.    
  501.     //  Triggers that other things can activate
  502.     if (!thing->player)
  503.     {
  504.         // Things that should NOT trigger specials...
  505.         switch(thing->type)
  506.         {
  507.           case MT_ROCKET:
  508.           case MT_PLASMA:
  509.           case MT_BFG:
  510.           case MT_TROOPSHOT:
  511.           case MT_HEADSHOT:
  512.           case MT_BRUISERSHOT:
  513.             return;
  514.             break;
  515.            
  516.           default: break;
  517.         }
  518.                
  519.         ok = 0;
  520.         switch(line->special)
  521.         {
  522.           case 39:      // TELEPORT TRIGGER
  523.           case 97:      // TELEPORT RETRIGGER
  524.           case 125:     // TELEPORT MONSTERONLY TRIGGER
  525.           case 126:     // TELEPORT MONSTERONLY RETRIGGER
  526.           case 4:       // RAISE DOOR
  527.           case 10:      // PLAT DOWN-WAIT-UP-STAY TRIGGER
  528.           case 88:      // PLAT DOWN-WAIT-UP-STAY RETRIGGER
  529.             ok = 1;
  530.             break;
  531.         }
  532.         if (!ok)
  533.             return;
  534.     }
  535.  
  536.    
  537.     // Note: could use some const's here.
  538.     switch (line->special)
  539.     {
  540.         // TRIGGERS.
  541.         // All from here to RETRIGGERS.
  542.       case 2:
  543.         // Open Door
  544.         EV_DoDoor(line,open);
  545.         line->special = 0;
  546.         break;
  547.  
  548.       case 3:
  549.         // Close Door
  550.         EV_DoDoor(line,close);
  551.         line->special = 0;
  552.         break;
  553.  
  554.       case 4:
  555.         // Raise Door
  556.         EV_DoDoor(line,normal);
  557.         line->special = 0;
  558.         break;
  559.        
  560.       case 5:
  561.         // Raise Floor
  562.         EV_DoFloor(line,raiseFloor);
  563.         line->special = 0;
  564.         break;
  565.        
  566.       case 6:
  567.         // Fast Ceiling Crush & Raise
  568.         EV_DoCeiling(line,fastCrushAndRaise);
  569.         line->special = 0;
  570.         break;
  571.        
  572.       case 8:
  573.         // Build Stairs
  574.         EV_BuildStairs(line,build8);
  575.         line->special = 0;
  576.         break;
  577.        
  578.       case 10:
  579.         // PlatDownWaitUp
  580.         EV_DoPlat(line,downWaitUpStay,0);
  581.         line->special = 0;
  582.         break;
  583.        
  584.       case 12:
  585.         // Light Turn On - brightest near
  586.         EV_LightTurnOn(line,0);
  587.         line->special = 0;
  588.         break;
  589.        
  590.       case 13:
  591.         // Light Turn On 255
  592.         EV_LightTurnOn(line,255);
  593.         line->special = 0;
  594.         break;
  595.        
  596.       case 16:
  597.         // Close Door 30
  598.         EV_DoDoor(line,close30ThenOpen);
  599.         line->special = 0;
  600.         break;
  601.        
  602.       case 17:
  603.         // Start Light Strobing
  604.         EV_StartLightStrobing(line);
  605.         line->special = 0;
  606.         break;
  607.        
  608.       case 19:
  609.         // Lower Floor
  610.         EV_DoFloor(line,lowerFloor);
  611.         line->special = 0;
  612.         break;
  613.        
  614.       case 22:
  615.         // Raise floor to nearest height and change texture
  616.         EV_DoPlat(line,raiseToNearestAndChange,0);
  617.         line->special = 0;
  618.         break;
  619.        
  620.       case 25:
  621.         // Ceiling Crush and Raise
  622.         EV_DoCeiling(line,crushAndRaise);
  623.         line->special = 0;
  624.         break;
  625.        
  626.       case 30:
  627.         // Raise floor to shortest texture height
  628.         //  on either side of lines.
  629.         EV_DoFloor(line,raiseToTexture);
  630.         line->special = 0;
  631.         break;
  632.        
  633.       case 35:
  634.         // Lights Very Dark
  635.         EV_LightTurnOn(line,35);
  636.         line->special = 0;
  637.         break;
  638.        
  639.       case 36:
  640.         // Lower Floor (TURBO)
  641.         EV_DoFloor(line,turboLower);
  642.         line->special = 0;
  643.         break;
  644.        
  645.       case 37:
  646.         // LowerAndChange
  647.         EV_DoFloor(line,lowerAndChange);
  648.         line->special = 0;
  649.         break;
  650.        
  651.       case 38:
  652.         // Lower Floor To Lowest
  653.         EV_DoFloor( line, lowerFloorToLowest );
  654.         line->special = 0;
  655.         break;
  656.        
  657.       case 39:
  658.         // TELEPORT!
  659.         EV_Teleport( line, side, thing );
  660.         line->special = 0;
  661.         break;
  662.  
  663.       case 40:
  664.         // RaiseCeilingLowerFloor
  665.         EV_DoCeiling( line, raiseToHighest );
  666.         EV_DoFloor( line, lowerFloorToLowest );
  667.         line->special = 0;
  668.         break;
  669.        
  670.       case 44:
  671.         // Ceiling Crush
  672.         EV_DoCeiling( line, lowerAndCrush );
  673.         line->special = 0;
  674.         break;
  675.        
  676.       case 52:
  677.         // EXIT!
  678.         G_ExitLevel ();
  679.         break;
  680.        
  681.       case 53:
  682.         // Perpetual Platform Raise
  683.         EV_DoPlat(line,perpetualRaise,0);
  684.         line->special = 0;
  685.         break;
  686.        
  687.       case 54:
  688.         // Platform Stop
  689.         EV_StopPlat(line);
  690.         line->special = 0;
  691.         break;
  692.  
  693.       case 56:
  694.         // Raise Floor Crush
  695.         EV_DoFloor(line,raiseFloorCrush);
  696.         line->special = 0;
  697.         break;
  698.  
  699.       case 57:
  700.         // Ceiling Crush Stop
  701.         EV_CeilingCrushStop(line);
  702.         line->special = 0;
  703.         break;
  704.        
  705.       case 58:
  706.         // Raise Floor 24
  707.         EV_DoFloor(line,raiseFloor24);
  708.         line->special = 0;
  709.         break;
  710.  
  711.       case 59:
  712.         // Raise Floor 24 And Change
  713.         EV_DoFloor(line,raiseFloor24AndChange);
  714.         line->special = 0;
  715.         break;
  716.        
  717.       case 104:
  718.         // Turn lights off in sector(tag)
  719.         EV_TurnTagLightsOff(line);
  720.         line->special = 0;
  721.         break;
  722.        
  723.       case 108:
  724.         // Blazing Door Raise (faster than TURBO!)
  725.         EV_DoDoor (line,blazeRaise);
  726.         line->special = 0;
  727.         break;
  728.        
  729.       case 109:
  730.         // Blazing Door Open (faster than TURBO!)
  731.         EV_DoDoor (line,blazeOpen);
  732.         line->special = 0;
  733.         break;
  734.        
  735.       case 100:
  736.         // Build Stairs Turbo 16
  737.         EV_BuildStairs(line,turbo16);
  738.         line->special = 0;
  739.         break;
  740.        
  741.       case 110:
  742.         // Blazing Door Close (faster than TURBO!)
  743.         EV_DoDoor (line,blazeClose);
  744.         line->special = 0;
  745.         break;
  746.  
  747.       case 119:
  748.         // Raise floor to nearest surr. floor
  749.         EV_DoFloor(line,raiseFloorToNearest);
  750.         line->special = 0;
  751.         break;
  752.        
  753.       case 121:
  754.         // Blazing PlatDownWaitUpStay
  755.         EV_DoPlat(line,blazeDWUS,0);
  756.         line->special = 0;
  757.         break;
  758.        
  759.       case 124:
  760.         // Secret EXIT
  761.         G_SecretExitLevel ();
  762.         break;
  763.                
  764.       case 125:
  765.         // TELEPORT MonsterONLY
  766.         if (!thing->player)
  767.         {
  768.             EV_Teleport( line, side, thing );
  769.             line->special = 0;
  770.         }
  771.         break;
  772.        
  773.       case 130:
  774.         // Raise Floor Turbo
  775.         EV_DoFloor(line,raiseFloorTurbo);
  776.         line->special = 0;
  777.         break;
  778.        
  779.       case 141:
  780.         // Silent Ceiling Crush & Raise
  781.         EV_DoCeiling(line,silentCrushAndRaise);
  782.         line->special = 0;
  783.         break;
  784.        
  785.         // RETRIGGERS.  All from here till end.
  786.       case 72:
  787.         // Ceiling Crush
  788.         EV_DoCeiling( line, lowerAndCrush );
  789.         break;
  790.  
  791.       case 73:
  792.         // Ceiling Crush and Raise
  793.         EV_DoCeiling(line,crushAndRaise);
  794.         break;
  795.  
  796.       case 74:
  797.         // Ceiling Crush Stop
  798.         EV_CeilingCrushStop(line);
  799.         break;
  800.        
  801.       case 75:
  802.         // Close Door
  803.         EV_DoDoor(line,close);
  804.         break;
  805.        
  806.       case 76:
  807.         // Close Door 30
  808.         EV_DoDoor(line,close30ThenOpen);
  809.         break;
  810.        
  811.       case 77:
  812.         // Fast Ceiling Crush & Raise
  813.         EV_DoCeiling(line,fastCrushAndRaise);
  814.         break;
  815.        
  816.       case 79:
  817.         // Lights Very Dark
  818.         EV_LightTurnOn(line,35);
  819.         break;
  820.        
  821.       case 80:
  822.         // Light Turn On - brightest near
  823.         EV_LightTurnOn(line,0);
  824.         break;
  825.        
  826.       case 81:
  827.         // Light Turn On 255
  828.         EV_LightTurnOn(line,255);
  829.         break;
  830.        
  831.       case 82:
  832.         // Lower Floor To Lowest
  833.         EV_DoFloor( line, lowerFloorToLowest );
  834.         break;
  835.        
  836.       case 83:
  837.         // Lower Floor
  838.         EV_DoFloor(line,lowerFloor);
  839.         break;
  840.  
  841.       case 84:
  842.         // LowerAndChange
  843.         EV_DoFloor(line,lowerAndChange);
  844.         break;
  845.  
  846.       case 86:
  847.         // Open Door
  848.         EV_DoDoor(line,open);
  849.         break;
  850.        
  851.       case 87:
  852.         // Perpetual Platform Raise
  853.         EV_DoPlat(line,perpetualRaise,0);
  854.         break;
  855.        
  856.       case 88:
  857.         // PlatDownWaitUp
  858.         EV_DoPlat(line,downWaitUpStay,0);
  859.         break;
  860.        
  861.       case 89:
  862.         // Platform Stop
  863.         EV_StopPlat(line);
  864.         break;
  865.        
  866.       case 90:
  867.         // Raise Door
  868.         EV_DoDoor(line,normal);
  869.         break;
  870.        
  871.       case 91:
  872.         // Raise Floor
  873.         EV_DoFloor(line,raiseFloor);
  874.         break;
  875.        
  876.       case 92:
  877.         // Raise Floor 24
  878.         EV_DoFloor(line,raiseFloor24);
  879.         break;
  880.        
  881.       case 93:
  882.         // Raise Floor 24 And Change
  883.         EV_DoFloor(line,raiseFloor24AndChange);
  884.         break;
  885.        
  886.       case 94:
  887.         // Raise Floor Crush
  888.         EV_DoFloor(line,raiseFloorCrush);
  889.         break;
  890.        
  891.       case 95:
  892.         // Raise floor to nearest height
  893.         // and change texture.
  894.         EV_DoPlat(line,raiseToNearestAndChange,0);
  895.         break;
  896.        
  897.       case 96:
  898.         // Raise floor to shortest texture height
  899.         // on either side of lines.
  900.         EV_DoFloor(line,raiseToTexture);
  901.         break;
  902.        
  903.       case 97:
  904.         // TELEPORT!
  905.         EV_Teleport( line, side, thing );
  906.         break;
  907.        
  908.       case 98:
  909.         // Lower Floor (TURBO)
  910.         EV_DoFloor(line,turboLower);
  911.         break;
  912.  
  913.       case 105:
  914.         // Blazing Door Raise (faster than TURBO!)
  915.         EV_DoDoor (line,blazeRaise);
  916.         break;
  917.        
  918.       case 106:
  919.         // Blazing Door Open (faster than TURBO!)
  920.         EV_DoDoor (line,blazeOpen);
  921.         break;
  922.  
  923.       case 107:
  924.         // Blazing Door Close (faster than TURBO!)
  925.         EV_DoDoor (line,blazeClose);
  926.         break;
  927.  
  928.       case 120:
  929.         // Blazing PlatDownWaitUpStay.
  930.         EV_DoPlat(line,blazeDWUS,0);
  931.         break;
  932.        
  933.       case 126:
  934.         // TELEPORT MonsterONLY.
  935.         if (!thing->player)
  936.             EV_Teleport( line, side, thing );
  937.         break;
  938.        
  939.       case 128:
  940.         // Raise To Nearest Floor
  941.         EV_DoFloor(line,raiseFloorToNearest);
  942.         break;
  943.        
  944.       case 129:
  945.         // Raise Floor Turbo
  946.         EV_DoFloor(line,raiseFloorTurbo);
  947.         break;
  948.     }
  949. }
  950.  
  951.  
  952.  
  953. //
  954. // P_ShootSpecialLine - IMPACT SPECIALS
  955. // Called when a thing shoots a special line.
  956. //
  957. void
  958. P_ShootSpecialLine
  959. ( mobj_t*       thing,
  960.   line_t*       line )
  961. {
  962.     int         ok;
  963.    
  964.     //  Impacts that other things can activate.
  965.     if (!thing->player)
  966.     {
  967.         ok = 0;
  968.         switch(line->special)
  969.         {
  970.           case 46:
  971.             // OPEN DOOR IMPACT
  972.             ok = 1;
  973.             break;
  974.         }
  975.         if (!ok)
  976.             return;
  977.     }
  978.  
  979.     switch(line->special)
  980.     {
  981.       case 24:
  982.         // RAISE FLOOR
  983.         EV_DoFloor(line,raiseFloor);
  984.         P_ChangeSwitchTexture(line,0);
  985.         break;
  986.        
  987.       case 46:
  988.         // OPEN DOOR
  989.         EV_DoDoor(line,open);
  990.         P_ChangeSwitchTexture(line,1);
  991.         break;
  992.        
  993.       case 47:
  994.         // RAISE FLOOR NEAR AND CHANGE
  995.         EV_DoPlat(line,raiseToNearestAndChange,0);
  996.         P_ChangeSwitchTexture(line,0);
  997.         break;
  998.     }
  999. }
  1000.  
  1001.  
  1002.  
  1003. //
  1004. // P_PlayerInSpecialSector
  1005. // Called every tic frame
  1006. //  that the player origin is in a special sector
  1007. //
  1008. void P_PlayerInSpecialSector (player_t* player)
  1009. {
  1010.     sector_t*   sector;
  1011.        
  1012.     sector = player->mo->subsector->sector;
  1013.  
  1014.     // Falling, not all the way down yet?
  1015.     if (player->mo->z != sector->floorheight)
  1016.         return;
  1017.  
  1018.     // Has hitten ground.
  1019.     switch (sector->special)
  1020.     {
  1021.       case 5:
  1022.         // HELLSLIME DAMAGE
  1023.         if (!player->powers[pw_ironfeet])
  1024.             if (!(leveltime&0x1f))
  1025.                 P_DamageMobj (player->mo, NULL, NULL, 10);
  1026.         break;
  1027.        
  1028.       case 7:
  1029.         // NUKAGE DAMAGE
  1030.         if (!player->powers[pw_ironfeet])
  1031.             if (!(leveltime&0x1f))
  1032.                 P_DamageMobj (player->mo, NULL, NULL, 5);
  1033.         break;
  1034.        
  1035.       case 16:
  1036.         // SUPER HELLSLIME DAMAGE
  1037.       case 4:
  1038.         // STROBE HURT
  1039.         if (!player->powers[pw_ironfeet]
  1040.             || (P_Random()<5) )
  1041.         {
  1042.             if (!(leveltime&0x1f))
  1043.                 P_DamageMobj (player->mo, NULL, NULL, 20);
  1044.         }
  1045.         break;
  1046.                        
  1047.       case 9:
  1048.         // SECRET SECTOR
  1049.         player->secretcount++;
  1050.         sector->special = 0;
  1051.         break;
  1052.                        
  1053.       case 11:
  1054.         // EXIT SUPER DAMAGE! (for E1M8 finale)
  1055.         player->cheats &= ~CF_GODMODE;
  1056.  
  1057.         if (!(leveltime&0x1f))
  1058.             P_DamageMobj (player->mo, NULL, NULL, 20);
  1059.  
  1060.         if (player->health <= 10)
  1061.             G_ExitLevel();
  1062.         break;
  1063.                        
  1064.       default:
  1065.         I_Error ("P_PlayerInSpecialSector: "
  1066.                  "unknown special %i",
  1067.                  sector->special);
  1068.         break;
  1069.     };
  1070. }
  1071.  
  1072.  
  1073.  
  1074.  
  1075. //
  1076. // P_UpdateSpecials
  1077. // Animate planes, scroll walls, etc.
  1078. //
  1079. boolean         levelTimer;
  1080. int             levelTimeCount;
  1081.  
  1082. void P_UpdateSpecials (void)
  1083. {
  1084.     anim_t*     anim;
  1085.     int         pic;
  1086.     int         i;
  1087.     line_t*     line;
  1088.  
  1089.    
  1090.     //  LEVEL TIMER
  1091.     if (levelTimer == true)
  1092.     {
  1093.         levelTimeCount--;
  1094.         if (!levelTimeCount)
  1095.             G_ExitLevel();
  1096.     }
  1097.    
  1098.     //  ANIMATE FLATS AND TEXTURES GLOBALLY
  1099.     for (anim = anims ; anim < lastanim ; anim++)
  1100.     {
  1101.         for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
  1102.         {
  1103.             pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics );
  1104.             if (anim->istexture)
  1105.                 texturetranslation[i] = pic;
  1106.             else
  1107.                 flattranslation[i] = pic;
  1108.         }
  1109.     }
  1110.  
  1111.    
  1112.     //  ANIMATE LINE SPECIALS
  1113.     for (i = 0; i < numlinespecials; i++)
  1114.     {
  1115.         line = linespeciallist[i];
  1116.         switch(line->special)
  1117.         {
  1118.           case 48:
  1119.             // EFFECT FIRSTCOL SCROLL +
  1120.             sides[line->sidenum[0]].textureoffset += FRACUNIT;
  1121.             break;
  1122.         }
  1123.     }
  1124.  
  1125.    
  1126.     //  DO BUTTONS
  1127.     for (i = 0; i < MAXBUTTONS; i++)
  1128.         if (buttonlist[i].btimer)
  1129.         {
  1130.             buttonlist[i].btimer--;
  1131.             if (!buttonlist[i].btimer)
  1132.             {
  1133.                 switch(buttonlist[i].where)
  1134.                 {
  1135.                   case top:
  1136.                     sides[buttonlist[i].line->sidenum[0]].toptexture =
  1137.                         buttonlist[i].btexture;
  1138.                     break;
  1139.                    
  1140.                   case middle:
  1141.                     sides[buttonlist[i].line->sidenum[0]].midtexture =
  1142.                         buttonlist[i].btexture;
  1143.                     break;
  1144.                    
  1145.                   case bottom:
  1146.                     sides[buttonlist[i].line->sidenum[0]].bottomtexture =
  1147.                         buttonlist[i].btexture;
  1148.                     break;
  1149.                 }
  1150.                 S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn);
  1151.                 memset(&buttonlist[i],0,sizeof(button_t));
  1152.             }
  1153.         }
  1154.        
  1155. }
  1156.  
  1157.  
  1158.  
  1159. //
  1160. // Special Stuff that can not be categorized
  1161. //
  1162. int EV_DoDonut(line_t*  line)
  1163. {
  1164.     sector_t*           s1;
  1165.     sector_t*           s2;
  1166.     sector_t*           s3;
  1167.     int                 secnum;
  1168.     int                 rtn;
  1169.     int                 i;
  1170.     floormove_t*        floor;
  1171.        
  1172.     secnum = -1;
  1173.     rtn = 0;
  1174.     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  1175.     {
  1176.         s1 = &sectors[secnum];
  1177.                
  1178.         // ALREADY MOVING?  IF SO, KEEP GOING...
  1179.         if (s1->specialdata)
  1180.             continue;
  1181.                        
  1182.         rtn = 1;
  1183.         s2 = getNextSector(s1->lines[0],s1);
  1184.         for (i = 0;i < s2->linecount;i++)
  1185.         {
  1186.             if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
  1187.                 (s2->lines[i]->backsector == s1))
  1188.                 continue;
  1189.             s3 = s2->lines[i]->backsector;
  1190.            
  1191.             //  Spawn rising slime
  1192.             floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  1193.             P_AddThinker (&floor->thinker);
  1194.             s2->specialdata = floor;
  1195.             floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  1196.             floor->type = donutRaise;
  1197.             floor->crush = false;
  1198.             floor->direction = 1;
  1199.             floor->sector = s2;
  1200.             floor->speed = FLOORSPEED / 2;
  1201.             floor->texture = s3->floorpic;
  1202.             floor->newspecial = 0;
  1203.             floor->floordestheight = s3->floorheight;
  1204.            
  1205.             //  Spawn lowering donut-hole
  1206.             floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  1207.             P_AddThinker (&floor->thinker);
  1208.             s1->specialdata = floor;
  1209.             floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  1210.             floor->type = lowerFloor;
  1211.             floor->crush = false;
  1212.             floor->direction = -1;
  1213.             floor->sector = s1;
  1214.             floor->speed = FLOORSPEED / 2;
  1215.             floor->floordestheight = s3->floorheight;
  1216.             break;
  1217.         }
  1218.     }
  1219.     return rtn;
  1220. }
  1221.  
  1222.  
  1223.  
  1224. //
  1225. // SPECIAL SPAWNING
  1226. //
  1227.  
  1228. //
  1229. // P_SpawnSpecials
  1230. // After the map has been loaded, scan for specials
  1231. //  that spawn thinkers
  1232. //
  1233. short           numlinespecials;
  1234. line_t*         linespeciallist[MAXLINEANIMS];
  1235.  
  1236.  
  1237. // Parses command line parameters.
  1238. void P_SpawnSpecials (void)
  1239. {
  1240.     sector_t*   sector;
  1241.     int         i;
  1242.     int         episode;
  1243.  
  1244.     episode = 1;
  1245.     if (W_CheckNumForName("texture2") >= 0)
  1246.         episode = 2;
  1247.  
  1248.    
  1249.     // See if -TIMER needs to be used.
  1250.     levelTimer = false;
  1251.        
  1252.     i = M_CheckParm("-avg");
  1253.     if (i && deathmatch)
  1254.     {
  1255.         levelTimer = true;
  1256.         levelTimeCount = 20 * 60 * 35;
  1257.     }
  1258.        
  1259.     i = M_CheckParm("-timer");
  1260.     if (i && deathmatch)
  1261.     {
  1262.         int     time;
  1263.         time = atoi(myargv[i+1]) * 60 * 35;
  1264.         levelTimer = true;
  1265.         levelTimeCount = time;
  1266.     }
  1267.    
  1268.     //  Init special SECTORs.
  1269.     sector = sectors;
  1270.     for (i=0 ; i<numsectors ; i++, sector++)
  1271.     {
  1272.         if (!sector->special)
  1273.             continue;
  1274.        
  1275.         switch (sector->special)
  1276.         {
  1277.           case 1:
  1278.             // FLICKERING LIGHTS
  1279.             P_SpawnLightFlash (sector);
  1280.             break;
  1281.  
  1282.           case 2:
  1283.             // STROBE FAST
  1284.             P_SpawnStrobeFlash(sector,FASTDARK,0);
  1285.             break;
  1286.            
  1287.           case 3:
  1288.             // STROBE SLOW
  1289.             P_SpawnStrobeFlash(sector,SLOWDARK,0);
  1290.             break;
  1291.            
  1292.           case 4:
  1293.             // STROBE FAST/DEATH SLIME
  1294.             P_SpawnStrobeFlash(sector,FASTDARK,0);
  1295.             sector->special = 4;
  1296.             break;
  1297.            
  1298.           case 8:
  1299.             // GLOWING LIGHT
  1300.             P_SpawnGlowingLight(sector);
  1301.             break;
  1302.           case 9:
  1303.             // SECRET SECTOR
  1304.             totalsecret++;
  1305.             break;
  1306.            
  1307.           case 10:
  1308.             // DOOR CLOSE IN 30 SECONDS
  1309.             P_SpawnDoorCloseIn30 (sector);
  1310.             break;
  1311.            
  1312.           case 12:
  1313.             // SYNC STROBE SLOW
  1314.             P_SpawnStrobeFlash (sector, SLOWDARK, 1);
  1315.             break;
  1316.  
  1317.           case 13:
  1318.             // SYNC STROBE FAST
  1319.             P_SpawnStrobeFlash (sector, FASTDARK, 1);
  1320.             break;
  1321.  
  1322.           case 14:
  1323.             // DOOR RAISE IN 5 MINUTES
  1324.             P_SpawnDoorRaiseIn5Mins (sector, i);
  1325.             break;
  1326.            
  1327.           case 17:
  1328.             P_SpawnFireFlicker(sector);
  1329.             break;
  1330.         }
  1331.     }
  1332.  
  1333.    
  1334.     //  Init line EFFECTs
  1335.     numlinespecials = 0;
  1336.     for (i = 0;i < numlines; i++)
  1337.     {
  1338.         switch(lines[i].special)
  1339.         {
  1340.           case 48:
  1341.             // EFFECT FIRSTCOL SCROLL+
  1342.             linespeciallist[numlinespecials] = &lines[i];
  1343.             numlinespecials++;
  1344.             break;
  1345.         }
  1346.     }
  1347.  
  1348.    
  1349.     //  Init other misc stuff
  1350.     for (i = 0;i < MAXCEILINGS;i++)
  1351.         activeceilings[i] = NULL;
  1352.  
  1353.     for (i = 0;i < MAXPLATS;i++)
  1354.         activeplats[i] = NULL;
  1355.    
  1356.     for (i = 0;i < MAXBUTTONS;i++)
  1357.         memset(&buttonlist[i],0,sizeof(button_t));
  1358.  
  1359.     // UNUSED: no horizonal sliders.
  1360.     //  P_InitSlidingDoorFrames();
  1361. }
  1362.