home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #2 / amigaacscoverdisc1998-021998.iso / games / doom / source / linuxdoom-1.10 / p_spec.c < prev    next >
C/C++ Source or Header  |  1997-12-22  |  25KB  |  1,363 lines

  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 = §ors[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.