text: // Emacs style mode select   -*- C++ -*-
  //-----------------------------------------------------------------------------
  //
  // $Id:$
  //
  // Copyright (C) 1993-1996 by id Software, Inc.
  //
  // This program is free software; you can redistribute it and/or
  // modify it under the terms of the GNU General Public License
  // as published by the Free Software Foundation; either version 2
  // of the License, or (at your option) any later version.
  //
  // This program is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  //
  // DESCRIPTION:  none
  //      Implements special effects:
  //      Texture animation, height or lighting changes
  //       according to adjacent sectors, respective
  //       utility functions, etc.
  //
  //-----------------------------------------------------------------------------
  
  
  #ifndef __P_SPEC__
  #define __P_SPEC__
  
  
  //
  // End-level timer (-TIMER option)
  //
  extern  boolean levelTimer;
  extern  int     levelTimeCount;
  
  
  //      Define values for map objects
  #define MO_TELEPORTMAN          14
  
  
  // at game start
  void    P_InitPicAnims (void);
  
  // at map load
  void    P_SpawnSpecials (void);
  
  // every tic
  void    P_UpdateSpecials (void);
  
  // when needed
  boolean
  P_UseSpecialLine
  ( mobj_t*       thing,
    line_t*       line,
    int           side );
  
  void
  P_ShootSpecialLine
  ( mobj_t*       thing,
    line_t*       line );
  
  void
  P_CrossSpecialLine
  ( int           linenum,
    int           side,
    mobj_t*       thing );
  
  void    P_PlayerInSpecialSector (player_t* player);
  
  int
  twoSided
  ( int           sector,
    int           line );
  
  sector_t*
  getSector
  ( int           currentSector,
    int           line,
    int           side );
  
  side_t*
  getSide
  ( int           currentSector,
    int           line,
    int           side );
  
  fixed_t P_FindLowestFloorSurrounding(sector_t* sec);
  fixed_t P_FindHighestFloorSurrounding(sector_t* sec);
  
  fixed_t
  P_FindNextHighestFloor
  ( sector_t*     sec,
    int           currentheight );
  
  fixed_t P_FindLowestCeilingSurrounding(sector_t* sec);
  fixed_t P_FindHighestCeilingSurrounding(sector_t* sec);
  
  int
  P_FindSectorFromLineTag
  ( line_t*       line,
    int           start );
  
  int
  P_FindMinSurroundingLight
  ( sector_t*     sector,
    int           max );
  
  sector_t*
  getNextSector
  ( line_t*       line,
    sector_t*     sec );
  
  
  //
  // SPECIAL
  //
  int EV_DoDonut(line_t* line);
  
  
  
  //
  // P_LIGHTS
  //
  typedef struct
  {
      thinker_t   thinker;
      sector_t*   sector;
      int         count;
      int         maxlight;
      int         minlight;
  
  } fireflicker_t;
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      sector_t*   sector;
      int         count;
      int         maxlight;
      int         minlight;
      int         maxtime;
      int         mintime;
  
  } lightflash_t;
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      sector_t*   sector;
      int         count;
      int         minlight;
      int         maxlight;
      int         darktime;
      int         brighttime;
  
  } strobe_t;
  
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      sector_t*   sector;
      int         minlight;
      int         maxlight;
      int         direction;
  
  } glow_t;
  
  
  #define GLOWSPEED                       8
  #define STROBEBRIGHT            5
  #define FASTDARK                        15
  #define SLOWDARK                        35
  
  void    P_SpawnFireFlicker (sector_t* sector);
  void    T_LightFlash (lightflash_t* flash);
  void    P_SpawnLightFlash (sector_t* sector);
  void    T_StrobeFlash (strobe_t* flash);
  
  void
  P_SpawnStrobeFlash
  ( sector_t*     sector,
    int           fastOrSlow,
    int           inSync );
  
  void    EV_StartLightStrobing(line_t* line);
  void    EV_TurnTagLightsOff(line_t* line);
  
  void
  EV_LightTurnOn
  ( line_t*       line,
    int           bright );
  
  void    T_Glow(glow_t* g);
  void    P_SpawnGlowingLight(sector_t* sector);
  
  
  
  
  //
  // P_SWITCH
  //
  typedef struct
  {
      char        name1[9];
      char        name2[9];
      short       episode;
  
  } switchlist_t;
  
  
  typedef enum
  {
      top,
      middle,
      bottom
  
  } bwhere_e;
  
  
  typedef struct
  {
      line_t*     line;
      bwhere_e    where;
      int         btexture;
      int         btimer;
      mobj_t*     soundorg;
  
  } button_t;
  
  
  
  
   // max # of wall switches in a level
  #define MAXSWITCHES             50
  
   // 4 players, 4 buttons each at once, max.
  #define MAXBUTTONS              16
  
   // 1 second, in ticks.
  #define BUTTONTIME      35
  
  extern button_t buttonlist[MAXBUTTONS];
  
  void
  P_ChangeSwitchTexture
  ( line_t*       line,
    int           useAgain );
  
  void P_InitSwitchList(void);
  
  
  //
  // P_PLATS
  //
  typedef enum
  {
      up,
      down,
      waiting,
      in_stasis
  
  } plat_e;
  
  
  
  typedef enum
  {
      perpetualRaise,
      downWaitUpStay,
      raiseAndChange,
      raiseToNearestAndChange,
      blazeDWUS
  
  } plattype_e;
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      sector_t*   sector;
      fixed_t     speed;
      fixed_t     low;
      fixed_t     high;
      int         wait;
      int         count;
      plat_e      status;
      plat_e      oldstatus;
      boolean     crush;
      int         tag;
      plattype_e  type;
  
  } plat_t;
  
  
  
  #define PLATWAIT                3
  #define PLATSPEED               FRACUNIT
  #define MAXPLATS                30
  
  
  extern plat_t*  activeplats[MAXPLATS];
  
  void    T_PlatRaise(plat_t*     plat);
  
  int
  EV_DoPlat
  ( line_t*       line,
    plattype_e    type,
    int           amount );
  
  void    P_AddActivePlat(plat_t* plat);
  void    P_RemoveActivePlat(plat_t* plat);
  void    EV_StopPlat(line_t* line);
  void    P_ActivateInStasis(int tag);
  
  
  //
  // P_DOORS
  //
  typedef enum
  {
      normal,
      close30ThenOpen,
      close,
      open,
      raiseIn5Mins,
      blazeRaise,
      blazeOpen,
      blazeClose
  
  } vldoor_e;
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      vldoor_e    type;
      sector_t*   sector;
      fixed_t     topheight;
      fixed_t     speed;
  
      // 1 = up, 0 = waiting at top, -1 = down
      int             direction;
  
      // tics to wait at the top
      int             topwait;
      // (keep in case a door going down is reset)
      // when it reaches 0, start going down
      int             topcountdown;
  
  } vldoor_t;
  
  
  
  #define VDOORSPEED              FRACUNIT*2
  #define VDOORWAIT               150
  
  void
  EV_VerticalDoor
  ( line_t*       line,
    mobj_t*       thing );
  
  int
  EV_DoDoor
  ( line_t*       line,
    vldoor_e      type );
  
  int
  EV_DoLockedDoor
  ( line_t*       line,
    vldoor_e      type,
    mobj_t*       thing );
  
  void    T_VerticalDoor (vldoor_t* door);
  void    P_SpawnDoorCloseIn30 (sector_t* sec);
  
  void
  P_SpawnDoorRaiseIn5Mins
  ( sector_t*     sec,
    int           secnum );
  
  
  
  #if 0 // UNUSED
  //
  //      Sliding doors...
  //
  typedef enum
  {
      sd_opening,
      sd_waiting,
      sd_closing
  
  } sd_e;
  
  
  
  typedef enum
  {
      sdt_openOnly,
      sdt_closeOnly,
      sdt_openAndClose
  
  } sdt_e;
  
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      sdt_e       type;
      line_t*     line;
      int         frame;
      int         whichDoorIndex;
      int         timer;
      sector_t*   frontsector;
      sector_t*   backsector;
      sd_e         status;
  
  } slidedoor_t;
  
  
  
  typedef struct
  {
      char        frontFrame1[9];
      char        frontFrame2[9];
      char        frontFrame3[9];
      char        frontFrame4[9];
      char        backFrame1[9];
      char        backFrame2[9];
      char        backFrame3[9];
      char        backFrame4[9];
  
  } slidename_t;
  
  
  
  typedef struct
  {
      int             frontFrames[4];
      int             backFrames[4];
  
  } slideframe_t;
  
  
  
  // how many frames of animation
  #define SNUMFRAMES              4
  
  #define SDOORWAIT               35*3
  #define SWAITTICS               4
  
  // how many diff. types of anims
  #define MAXSLIDEDOORS   5
  
  void P_InitSlidingDoorFrames(void);
  
  void
  EV_SlidingDoor
  ( line_t*       line,
    mobj_t*       thing );
  #endif
  
  
  
  //
  // P_CEILNG
  //
  typedef enum
  {
      lowerToFloor,
      raiseToHighest,
      lowerAndCrush,
      crushAndRaise,
      fastCrushAndRaise,
      silentCrushAndRaise
  
  } ceiling_e;
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      ceiling_e   type;
      sector_t*   sector;
      fixed_t     bottomheight;
      fixed_t     topheight;
      fixed_t     speed;
      boolean     crush;
  
      // 1 = up, 0 = waiting, -1 = down
      int         direction;
  
      // ID
      int         tag;
      int         olddirection;
  
  } ceiling_t;
  
  
  
  
  
  #define CEILSPEED               FRACUNIT
  #define CEILWAIT                150
  #define MAXCEILINGS             30
  
  extern ceiling_t*       activeceilings[MAXCEILINGS];
  
  int
  EV_DoCeiling
  ( line_t*       line,
    ceiling_e     type );
  
  void    T_MoveCeiling (ceiling_t* ceiling);
  void    P_AddActiveCeiling(ceiling_t* c);
  void    P_RemoveActiveCeiling(ceiling_t* c);
  int     EV_CeilingCrushStop(line_t* line);
  void    P_ActivateInStasisCeiling(line_t* line);
  
  
  //
  // P_FLOOR
  //
  typedef enum
  {
      // lower floor to highest surrounding floor
      lowerFloor,
  
      // lower floor to lowest surrounding floor
      lowerFloorToLowest,
  
      // lower floor to highest surrounding floor VERY FAST
      turboLower,
  
      // raise floor to lowest surrounding CEILING
      raiseFloor,
  
      // raise floor to next highest surrounding floor
      raiseFloorToNearest,
  
      // raise floor to shortest height texture around it
      raiseToTexture,
  
      // lower floor to lowest surrounding floor
      //  and change floorpic
      lowerAndChange,
  
      raiseFloor24,
      raiseFloor24AndChange,
      raiseFloorCrush,
  
       // raise to next highest floor, turbo-speed
      raiseFloorTurbo,
      donutRaise,
      raiseFloor512
  
  } floor_e;
  
  
  
  
  typedef enum
  {
      build8,     // slowly build by 8
      turbo16     // quickly build by 16
  
  } stair_e;
  
  
  
  typedef struct
  {
      thinker_t   thinker;
      floor_e     type;
      boolean     crush;
      sector_t*   sector;
      int         direction;
      int         newspecial;
      short       texture;
      fixed_t     floordestheight;
      fixed_t     speed;
  
  } floormove_t;
  
  
  
  #define FLOORSPEED              FRACUNIT
  
  typedef enum
  {
      ok,
      crushed,
      pastdest
  
  } result_e;
  
  result_e
  T_MovePlane
  ( sector_t*     sector,
    fixed_t       speed,
    fixed_t       dest,
    boolean       crush,
    int           floorOrCeiling,
    int           direction );
  
  int
  EV_BuildStairs
  ( line_t*       line,
    stair_e       type );
  
  int
  EV_DoFloor
  ( line_t*       line,
    floor_e       floortype );
  
  void T_MoveFloor( floormove_t* floor);
  
  //
  // P_TELEPT
  //
  int
  EV_Teleport
  ( line_t*       line,
    int           side,
    mobj_t*       thing );
  
  #endif
  //-----------------------------------------------------------------------------
  //
  // $Log:$
  //
  //-----------------------------------------------------------------------------
  