summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_ceilng.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/p_ceilng.c')
-rw-r--r--apps/plugins/doom/p_ceilng.c468
1 files changed, 468 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_ceilng.c b/apps/plugins/doom/p_ceilng.c
new file mode 100644
index 0000000..db5a701
--- /dev/null
+++ b/apps/plugins/doom/p_ceilng.c
@@ -0,0 +1,468 @@
+/* Emacs style mode select -*- C++ -*-
+ *-----------------------------------------------------------------------------
+ *
+ *
+ * PrBoom a Doom port merged with LxDoom and LSDLDoom
+ * based on BOOM, a modified and improved DOOM engine
+ * Copyright (C) 1999 by
+ * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
+ * Copyright (C) 1999-2000 by
+ * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * DESCRIPTION:
+ * Ceiling aninmation (lowering, crushing, raising)
+ *
+ *-----------------------------------------------------------------------------*/
+
+#include "doomstat.h"
+#include "r_main.h"
+#include "p_spec.h"
+#include "p_tick.h"
+#include "s_sound.h"
+#include "sounds.h"
+#include "z_zone.h"
+#include "doomdef.h"
+#define PU_LEVSPEC 51 // a special thinker in a level
+#include "rockmacros.h"
+
+// the list of ceilings moving currently, including crushers
+ceilinglist_t *activeceilings;
+
+/////////////////////////////////////////////////////////////////
+//
+// Ceiling action routine and linedef type handler
+//
+/////////////////////////////////////////////////////////////////
+
+//
+// T_MoveCeiling
+//
+// Action routine that moves ceilings. Called once per tick.
+//
+// Passed a ceiling_t structure that contains all the info about the move.
+// see P_SPEC.H for fields. No return.
+//
+// jff 02/08/98 all cases with labels beginning with gen added to support
+// generalized line type behaviors.
+//
+void T_MoveCeiling (ceiling_t* ceiling)
+{
+ result_e res;
+
+ switch(ceiling->direction)
+ {
+ case 0:
+ // If ceiling in stasis, do nothing
+ break;
+
+ case 1:
+ // Ceiling is moving up
+ res = T_MovePlane
+ (
+ ceiling->sector,
+ ceiling->speed,
+ ceiling->topheight,
+ false,
+ 1,
+ ceiling->direction
+ );
+
+ // if not a silent crusher, make moving sound
+ if (!(leveltime&7))
+ {
+ switch(ceiling->type)
+ {
+ case silentCrushAndRaise:
+ case genSilentCrusher:
+ break;
+ default:
+ S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
+ break;
+ }
+ }
+
+ // handle reaching destination height
+ if (res == pastdest)
+ {
+ switch(ceiling->type)
+ {
+ // plain movers are just removed
+ case raiseToHighest:
+ case genCeiling:
+ P_RemoveActiveCeiling(ceiling);
+ break;
+
+ // movers with texture change, change the texture then get removed
+ case genCeilingChgT:
+ case genCeilingChg0:
+ ceiling->sector->special = ceiling->newspecial;
+ //jff 3/14/98 transfer old special field as well
+ ceiling->sector->oldspecial = ceiling->oldspecial;
+ case genCeilingChg:
+ ceiling->sector->ceilingpic = ceiling->texture;
+ P_RemoveActiveCeiling(ceiling);
+ break;
+
+ // crushers reverse direction at the top
+ case silentCrushAndRaise:
+ S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
+ case genSilentCrusher:
+ case genCrusher:
+ case fastCrushAndRaise:
+ case crushAndRaise:
+ ceiling->direction = -1;
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case -1:
+ // Ceiling moving down
+ res = T_MovePlane
+ (
+ ceiling->sector,
+ ceiling->speed,
+ ceiling->bottomheight,
+ ceiling->crush,
+ 1,
+ ceiling->direction
+ );
+
+ // if not silent crusher type make moving sound
+ if (!(leveltime&7))
+ {
+ switch(ceiling->type)
+ {
+ case silentCrushAndRaise:
+ case genSilentCrusher:
+ break;
+ default:
+ S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
+ }
+ }
+
+ // handle reaching destination height
+ if (res == pastdest)
+ {
+ switch(ceiling->type)
+ {
+ // 02/09/98 jff change slow crushers' speed back to normal
+ // start back up
+ case genSilentCrusher:
+ case genCrusher:
+ if (ceiling->oldspeed<CEILSPEED*3)
+ ceiling->speed = ceiling->oldspeed;
+ ceiling->direction = 1; //jff 2/22/98 make it go back up!
+ break;
+
+ // make platform stop at bottom of all crusher strokes
+ // except generalized ones, reset speed, start back up
+ case silentCrushAndRaise:
+ S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
+ case crushAndRaise:
+ ceiling->speed = CEILSPEED;
+ case fastCrushAndRaise:
+ ceiling->direction = 1;
+ break;
+
+ // in the case of ceiling mover/changer, change the texture
+ // then remove the active ceiling
+ case genCeilingChgT:
+ case genCeilingChg0:
+ ceiling->sector->special = ceiling->newspecial;
+ //jff add to fix bug in special transfers from changes
+ ceiling->sector->oldspecial = ceiling->oldspecial;
+ case genCeilingChg:
+ ceiling->sector->ceilingpic = ceiling->texture;
+ P_RemoveActiveCeiling(ceiling);
+ break;
+
+ // all other case, just remove the active ceiling
+ case lowerAndCrush:
+ case lowerToFloor:
+ case lowerToLowest:
+ case lowerToMaxFloor:
+ case genCeiling:
+ P_RemoveActiveCeiling(ceiling);
+ break;
+
+ default:
+ break;
+ }
+ }
+ else // ( res != pastdest )
+ {
+ // handle the crusher encountering an obstacle
+ if (res == crushed)
+ {
+ switch(ceiling->type)
+ {
+ //jff 02/08/98 slow down slow crushers on obstacle
+ case genCrusher:
+ case genSilentCrusher:
+ if (ceiling->oldspeed < CEILSPEED*3)
+ ceiling->speed = CEILSPEED / 8;
+ break;
+ case silentCrushAndRaise:
+ case crushAndRaise:
+ case lowerAndCrush:
+ ceiling->speed = CEILSPEED / 8;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+
+//
+// EV_DoCeiling
+//
+// Move a ceiling up/down or start a crusher
+//
+// Passed the linedef activating the function and the type of function desired
+// returns true if a thinker started
+//
+int EV_DoCeiling
+( line_t* line,
+ ceiling_e type )
+{
+ int secnum;
+ int rtn;
+ sector_t* sec;
+ ceiling_t* ceiling;
+
+ secnum = -1;
+ rtn = 0;
+
+ // Reactivate in-stasis ceilings...for certain types.
+ // This restarts a crusher after it has been stopped
+ switch(type)
+ {
+ case fastCrushAndRaise:
+ case silentCrushAndRaise:
+ case crushAndRaise:
+ //jff 4/5/98 return if activated
+ rtn = P_ActivateInStasisCeiling(line);
+ default:
+ break;
+ }
+
+ // affects all sectors with the same tag as the linedef
+ while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+ {
+ sec = &sectors[secnum];
+
+ // if ceiling already moving, don't start a second function on it
+ if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
+ continue;
+
+ // create a new ceiling thinker
+ rtn = 1;
+ ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
+ P_AddThinker (&ceiling->thinker);
+ sec->ceilingdata = ceiling; //jff 2/22/98
+ ceiling->thinker.function = T_MoveCeiling;
+ ceiling->sector = sec;
+ ceiling->crush = false;
+
+ // setup ceiling structure according to type of function
+ switch(type)
+ {
+ case fastCrushAndRaise:
+ ceiling->crush = true;
+ ceiling->topheight = sec->ceilingheight;
+ ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
+ ceiling->direction = -1;
+ ceiling->speed = CEILSPEED * 2;
+ break;
+
+ case silentCrushAndRaise:
+ case crushAndRaise:
+ ceiling->crush = true;
+ ceiling->topheight = sec->ceilingheight;
+ case lowerAndCrush:
+ case lowerToFloor:
+ ceiling->bottomheight = sec->floorheight;
+ if (type != lowerToFloor)
+ ceiling->bottomheight += 8*FRACUNIT;
+ ceiling->direction = -1;
+ ceiling->speed = CEILSPEED;
+ break;
+
+ case raiseToHighest:
+ ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
+ ceiling->direction = 1;
+ ceiling->speed = CEILSPEED;
+ break;
+
+ case lowerToLowest:
+ ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
+ ceiling->direction = -1;
+ ceiling->speed = CEILSPEED;
+ break;
+
+ case lowerToMaxFloor:
+ ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
+ ceiling->direction = -1;
+ ceiling->speed = CEILSPEED;
+ break;
+
+ default:
+ break;
+ }
+
+ // add the ceiling to the active list
+ ceiling->tag = sec->tag;
+ ceiling->type = type;
+ P_AddActiveCeiling(ceiling);
+ }
+ return rtn;
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// Active ceiling list primitives
+//
+/////////////////////////////////////////////////////////////////////
+
+// jff 2/22/98 - modified Lee's plat code to work for ceilings
+//
+// The following were all rewritten by Lee Killough
+// to use the new structure which places no limits
+// on active ceilings. It also avoids spending as much
+// time searching for active ceilings. Previously a
+// fixed-size array was used, with NULL indicating
+// empty entries, while now a doubly-linked list
+// is used.
+
+//
+// P_ActivateInStasisCeiling()
+//
+// Reactivates all stopped crushers with the right tag
+//
+// Passed the line reactivating the crusher
+// Returns true if a ceiling reactivated
+//
+//jff 4/5/98 return if activated
+int P_ActivateInStasisCeiling(line_t *line)
+{
+ ceilinglist_t *cl;
+ int rtn=0;
+
+ for (cl=activeceilings; cl; cl=cl->next)
+ {
+ ceiling_t *ceiling = cl->ceiling;
+ if (ceiling->tag == line->tag && ceiling->direction == 0)
+ {
+ ceiling->direction = ceiling->olddirection;
+ ceiling->thinker.function = T_MoveCeiling;
+ //jff 4/5/98 return if activated
+ rtn=1;
+ }
+ }
+ return rtn;
+}
+
+//
+// EV_CeilingCrushStop()
+//
+// Stops all active ceilings with the right tag
+//
+// Passed the linedef stopping the ceilings
+// Returns true if a ceiling put in stasis
+//
+int EV_CeilingCrushStop(line_t* line)
+{
+ int rtn=0;
+
+ ceilinglist_t *cl;
+ for (cl=activeceilings; cl; cl=cl->next)
+ {
+ ceiling_t *ceiling = cl->ceiling;
+ if (ceiling->direction != 0 && ceiling->tag == line->tag)
+ {
+ ceiling->olddirection = ceiling->direction;
+ ceiling->direction = 0;
+ ceiling->thinker.function = NULL;
+ rtn=1;
+ }
+ }
+ return rtn;
+}
+
+//
+// P_AddActiveCeiling()
+//
+// Adds a ceiling to the head of the list of active ceilings
+//
+// Passed the ceiling motion structure
+// Returns nothing
+//
+void P_AddActiveCeiling(ceiling_t* ceiling)
+{
+ ceilinglist_t *list = malloc(sizeof *list);
+ list->ceiling = ceiling;
+ ceiling->list = list;
+ if ((list->next = activeceilings))
+ list->next->prev = &list->next;
+ list->prev = &activeceilings;
+ activeceilings = list;
+}
+
+//
+// P_RemoveActiveCeiling()
+//
+// Removes a ceiling from the list of active ceilings
+//
+// Passed the ceiling motion structure
+// Returns nothing
+//
+void P_RemoveActiveCeiling(ceiling_t* ceiling)
+{
+ ceilinglist_t *list = ceiling->list;
+ ceiling->sector->ceilingdata = NULL; //jff 2/22/98
+ P_RemoveThinker(&ceiling->thinker);
+ if ((*list->prev = list->next))
+ list->next->prev = list->prev;
+ free(list);
+}
+
+//
+// P_RemoveAllActiveCeilings()
+//
+// Removes all ceilings from the active ceiling list
+//
+// Passed nothing, returns nothing
+//
+void P_RemoveAllActiveCeilings(void)
+{
+ while (activeceilings)
+ {
+ ceilinglist_t *next = activeceilings->next;
+ free(activeceilings);
+ activeceilings = next;
+ }
+}