home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / p_spec.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  26.6 KB  |  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.