mirror of
https://github.com/odamex/odamex
synced 2026-08-19 02:23:09 -04:00
3628 lines
89 KiB
C++
3628 lines
89 KiB
C++
// Emacs style mode select -*- C++ -*-
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Id$
|
|
//
|
|
// Copyright (C) 2006-2026 by The Odamex Team.
|
|
//
|
|
// 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:
|
|
// [Blair] Define the Doom (Doom in Doom) format doom map spec.
|
|
// Includes sector specials, linedef types, line crossing.
|
|
// "Attempts" to be Boom compatible, hence the name.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "odamex.h"
|
|
#include "p_local.h"
|
|
#include "p_lnspec.h"
|
|
#include "m_wdlstats.h"
|
|
#include "c_cvars.h"
|
|
#include "d_player.h"
|
|
#include "p_boomfspec.h"
|
|
|
|
EXTERN_CVAR(sv_allowexit)
|
|
EXTERN_CVAR(co_pursuit)
|
|
EXTERN_CVAR(co_helpfriends)
|
|
EXTERN_CVAR(co_monsterbacking)
|
|
EXTERN_CVAR(co_avoidhazards)
|
|
EXTERN_CVAR(co_monstersclimbsteep)
|
|
EXTERN_CVAR(co_mbfphys)
|
|
|
|
//
|
|
// P_CrossCompatibleSpecialLine - Walkover Trigger Dispatcher
|
|
//
|
|
// Called every time a thing origin is about
|
|
// to cross a line with a non 0 special, whether a walkover type or not.
|
|
//
|
|
// jff 02/12/98 all W1 lines were fixed to check the result from the EV_
|
|
// function before clearing the special. This avoids losing the function
|
|
// of the line, should the sector already be active when the line is
|
|
// crossed. Change is qualified by demo_compatibility.
|
|
//
|
|
// CPhipps - take a line_t pointer instead of a line number, as in MBF
|
|
|
|
bool P_CrossCompatibleSpecialLine(line_t* line, int side, AActor* thing,
|
|
bool bossaction)
|
|
{
|
|
int ok;
|
|
bool resetinv = false;
|
|
|
|
// Things that should never trigger lines
|
|
//
|
|
// e6y: Improved support for Doom v1.2
|
|
/*
|
|
if (compatibility_level == doom_12_compatibility)
|
|
{
|
|
if (line->special > 98 && line->special != 104)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
*/
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
{
|
|
// Things that should NOT trigger specials...
|
|
switch (thing->type)
|
|
{
|
|
case MT_ROCKET:
|
|
case MT_PLASMA:
|
|
case MT_BFG:
|
|
case MT_TROOPSHOT:
|
|
case MT_HEADSHOT:
|
|
case MT_BRUISERSHOT:
|
|
return false;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// jff 02/04/98 add check here for generalized lindef types
|
|
if (!demoplayback) // generalized types not recognized if old demo
|
|
{
|
|
// pointer to line function is NULL by default, set non-null if
|
|
// line special is walkover generalized linedef type
|
|
bool (*linefunc)(line_t& line) = nullptr;
|
|
|
|
// check each range of generalized linedefs
|
|
if ((unsigned)line->special >= GenEnd)
|
|
{
|
|
// Out of range for GenFloors
|
|
}
|
|
else if ((unsigned)line->special >= GenFloorBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if ((line->special & FloorChange) || !(line->special & FloorModel))
|
|
return false; // FloorModel is "Allow Monsters" if FloorChange is 0
|
|
if (!line->id) //jff 2/27/98 all walk generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenFloor;
|
|
}
|
|
else if ((unsigned)line->special >= GenCeilingBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if ((line->special & CeilingChange) || !(line->special & CeilingModel))
|
|
return false; // CeilingModel is "Allow Monsters" if CeilingChange is 0
|
|
if (!line->id) //jff 2/27/98 all walk generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenCeiling;
|
|
}
|
|
else if ((unsigned)line->special >= GenDoorBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
{
|
|
if (!(line->special & DoorMonster))
|
|
return false; // monsters disallowed from this door
|
|
if (line->flags & ML_SECRET) // they can't open secret doors either
|
|
return false;
|
|
}
|
|
if (!line->id) //3/2/98 move outside the monster check
|
|
return false;
|
|
linefunc = EV_DoGenDoor;
|
|
}
|
|
else if ((unsigned)line->special >= GenLockedBase)
|
|
{
|
|
if ((!P_IsPlayerOrAvatar(*thing)) ||
|
|
bossaction) // boss actions can't handle locked doors
|
|
return false; // monsters disallowed from unlocking doors
|
|
if (((line->special & TriggerType) == WalkOnce) ||
|
|
((line->special & TriggerType) == WalkMany))
|
|
{ // jff 4/1/98 check for being a walk type before reporting door type
|
|
if (!P_CanUnlockGenDoor(line, thing->player))
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
linefunc = EV_DoGenLockedDoor;
|
|
}
|
|
else if ((unsigned)line->special >= GenLiftBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if (!(line->special & LiftMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id) //jff 2/27/98 all walk generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenLift;
|
|
}
|
|
else if ((unsigned)line->special >= GenStairsBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if (!(line->special & StairMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id) //jff 2/27/98 all walk generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenStairs;
|
|
}
|
|
else if ((unsigned)line->special >= GenCrusherBase)
|
|
{
|
|
// haleyjd 06/09/09: This was completely forgotten in BOOM, disabling
|
|
// all generalized walk-over crusher types!
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if (!(line->special & StairMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id) //jff 2/27/98 all walk generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenCrusher;
|
|
}
|
|
|
|
if (linefunc) // if it was a valid generalized type
|
|
switch ((line->special & TriggerType) >> TriggerTypeShift)
|
|
{
|
|
case WalkOnce:
|
|
if (linefunc(*line))
|
|
{
|
|
return true;
|
|
}
|
|
// FIXME: is this fallthrough intended?
|
|
case WalkMany:
|
|
linefunc(*line);
|
|
return true;
|
|
default: // if not a walk type, do nothing here
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ((!P_IsPlayerOrAvatar(*thing)) || bossaction)
|
|
{
|
|
ok = 0;
|
|
switch (line->special)
|
|
{
|
|
// teleporters are blocked for boss actions.
|
|
case 39: // teleport trigger
|
|
case 97: // teleport retrigger
|
|
case 125: // teleport monsteronly trigger
|
|
case 126: // teleport monsteronly retrigger
|
|
// jff 3/5/98 add ability of monsters etc. to use teleporters
|
|
case 208: // silent thing teleporters
|
|
case 207:
|
|
case 243: // silent line-line teleporter
|
|
case 244: // jff 3/6/98 make fit within DCK's 256 linedef types
|
|
case 262: // jff 4/14/98 add monster only
|
|
case 263: // jff 4/14/98 silent thing,line,line rev types
|
|
case 264: // jff 4/14/98 plus player/monster silent line
|
|
case 265: // reversed types
|
|
case 266:
|
|
case 267:
|
|
case 268:
|
|
case 269:
|
|
if (bossaction)
|
|
return false;
|
|
[[fallthrough]];
|
|
case 4: // raise door
|
|
case 10: // plat down-wait-up-stay trigger
|
|
case 88: // plat down-wait-up-stay retrigger
|
|
ok = 1;
|
|
break;
|
|
}
|
|
if (!ok && !bossaction) // Bossactions can use any linedef except teleports.
|
|
return false;
|
|
}
|
|
|
|
if (!P_CheckTag(line)) // jff 2/27/98 disallow zero tag on some types
|
|
return false;
|
|
|
|
// Dispatch on the line special value to the line's action routine
|
|
// If a once only function, and successful, clear the line special
|
|
|
|
// Do not teleport on the wrong side
|
|
if (side)
|
|
{
|
|
if (P_IsTeleportLine(line->special))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
switch (line->special)
|
|
{
|
|
// Regular walk once triggers
|
|
|
|
case 2:
|
|
// Open Door
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
// Close Door
|
|
if (EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
// Raise Door
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
// Raise Floor
|
|
if (EV_DoFloor(DFloor::floorRaiseToLowestCeiling, line, line->id, SPEED(floors::SLOW),
|
|
0, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 6:
|
|
// Fast Ceiling Crush & Raise
|
|
if (EV_DoCeiling(DCeiling::fastCrushAndRaise, line, line->id, SPEED(ceilings::NORMAL),
|
|
SPEED(ceilings::NORMAL), 0, true, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 8:
|
|
// Build Stairs
|
|
if (EV_BuildStairs(line->id, DFloor::buildUp, line, 8 * FRACUNIT, SPEED(stairs::SLOW),
|
|
TICS(0), 0, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 10:
|
|
// PlatDownWaitUp
|
|
if (EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::FAST),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 12:
|
|
// Light Turn On - brightest near
|
|
EV_LightTurnOn(line->id, -1);
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 13:
|
|
// Light Turn On 255
|
|
EV_LightTurnOn(line->id, 255);
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 16:
|
|
// Close Door 30
|
|
if (EV_DoDoor(DDoor::doorCloseWaitOpen, line, thing, line->id, SPEED(doors::SLOW),
|
|
OCTICS(240), NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 17:
|
|
// Start Light Strobing
|
|
EV_StartLightStrobing(line->id, TICS(5), TICS(35));
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 19:
|
|
// Lower Floor
|
|
if (EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::SLOW),
|
|
(128 - 128) * FRACUNIT, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 22:
|
|
// Raise floor to nearest height and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platRaiseAndStay, 0, SPEED(plats::SLOW / 2), 0, 0,
|
|
1))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 25:
|
|
// Ceiling Crush and Raise
|
|
if (EV_DoCeiling(DCeiling::crushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 30:
|
|
// Raise floor to shortest texture height
|
|
// on either side of lines.
|
|
if (EV_DoFloor(DFloor::floorRaiseByTexture, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 35:
|
|
// Lights Very Dark
|
|
EV_LightTurnOn(line->id, 35);
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 36:
|
|
// Lower Floor (TURBO)
|
|
if (EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::FAST),
|
|
(136 - 128) * FRACUNIT, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 37:
|
|
// LowerAndChange
|
|
if (EV_DoFloor(DFloor::floorLowerAndChange, line, line->id, SPEED(floors::SLOW),
|
|
0 * FRACUNIT, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 38:
|
|
// Lower Floor To Lowest
|
|
if (EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 39:
|
|
// TELEPORT! //jff 02/09/98 fix using up with wrong side crossing
|
|
if (EV_LineTeleport(line, side, thing))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 40:
|
|
// RaiseCeilingLowerFloor -- only raises ceiling
|
|
EV_DoCeiling(DCeiling::ceilRaiseToHighest, line, line->id, SPEED(ceilings::SLOW), 0, 0, 0,
|
|
0, 0);
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 44:
|
|
// Ceiling Crush
|
|
if (EV_DoCeiling(DCeiling::lowerAndCrush, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW) / 2, 0, true, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 2069:
|
|
resetinv = true;
|
|
[[fallthrough]];
|
|
case 52:
|
|
// EXIT!
|
|
// killough 10/98: prevent zombies from exiting levels
|
|
if (bossaction || ((!(thing->player && thing->player->health <= 0)) &&
|
|
CheckIfExitIsGood(thing)))
|
|
{
|
|
G_ExitLevel(0, 1, resetinv);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 53:
|
|
// Perpetual Platform Raise
|
|
if (EV_DoPlat(line->id, line, DPlat::platPerpetualRaise, 0, SPEED(plats::SLOW),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 54:
|
|
// Platform Stop
|
|
EV_StopPlat(line->id);
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 56:
|
|
// Raise Floor Crush
|
|
if (EV_DoFloor(DFloor::floorRaiseAndCrush, line, line->id, SPEED(floors::SLOW), 0, true,
|
|
0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 57:
|
|
// Ceiling Crush Stop
|
|
if (EV_CeilingCrushStop(line->id))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 58:
|
|
// Raise Floor 24
|
|
if (EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 24, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 59:
|
|
// Raise Floor 24 And Change
|
|
if (EV_DoFloor(DFloor::floorRaiseAndChange, line, line->id, SPEED(floors::SLOW),
|
|
24 * FRACUNIT, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 100:
|
|
// Build Stairs Turbo 16
|
|
if (EV_BuildStairs(line->id, DFloor::buildUp, line, 16 * FRACUNIT, SPEED(stairs::TURBO),
|
|
TICS(0), 0, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 104:
|
|
// Turn lights off in sector(tag)
|
|
EV_TurnTagLightsOff(line->id);
|
|
return true;
|
|
//line->special = 0;
|
|
break;
|
|
|
|
case 108:
|
|
// Blazing Door Raise (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::FAST),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 109:
|
|
// Blazing Door Open (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 110:
|
|
// Blazing Door Close (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 119:
|
|
// Raise floor to nearest surr. floor
|
|
if (EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 121:
|
|
// Blazing PlatDownWaitUpStay
|
|
if (EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::TURBO),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 2072:
|
|
resetinv = true;
|
|
[[fallthrough]];
|
|
case 124:
|
|
// Secret EXIT
|
|
// killough 10/98: prevent zombies from exiting levels
|
|
// CPhipps - change for lxdoom's compatibility handling
|
|
if (bossaction || ((!(thing->player && thing->player->health <= 0)) &&
|
|
CheckIfExitIsGood(thing)))
|
|
{
|
|
G_SecretExitLevel(0, 1, resetinv);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 125:
|
|
// TELEPORT MonsterONLY
|
|
if (!P_IsPlayerOrAvatar(*thing) &&
|
|
(EV_LineTeleport(line, side, thing)))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 130:
|
|
// Raise Floor Turbo
|
|
if (EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::FAST), 0, 0,
|
|
0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 141:
|
|
// Silent Ceiling Crush & Raise
|
|
if (EV_DoCeiling(DCeiling::silentCrushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 1, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
// Regular walk many retriggerable
|
|
|
|
case 72:
|
|
// Ceiling Crush
|
|
EV_DoCeiling(DCeiling::lowerAndCrush, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW) / 2, 0, true, 0, 0);
|
|
return true;
|
|
|
|
case 73:
|
|
// Ceiling Crush and Raise
|
|
EV_DoCeiling(DCeiling::crushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 0, 0);
|
|
return true;
|
|
|
|
case 74:
|
|
// Ceiling Crush Stop
|
|
EV_CeilingCrushStop(line->id);
|
|
return true;
|
|
|
|
case 75:
|
|
// Close Door
|
|
EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey);
|
|
return true;
|
|
|
|
case 76:
|
|
// Close Door 30
|
|
EV_DoDoor(DDoor::doorCloseWaitOpen, line, thing, line->id, SPEED(doors::SLOW),
|
|
OCTICS(240), NoKey);
|
|
return true;
|
|
|
|
case 77:
|
|
// Fast Ceiling Crush & Raise
|
|
EV_DoCeiling(DCeiling::fastCrushAndRaise, line, line->id, SPEED(ceilings::NORMAL),
|
|
SPEED(ceilings::NORMAL), 0, true, 0, 0);
|
|
return true;
|
|
|
|
case 79:
|
|
// Lights Very Dark
|
|
EV_LightTurnOn(line->id, 35);
|
|
return true;
|
|
|
|
case 80:
|
|
// Light Turn On - brightest near
|
|
EV_LightTurnOn(line->id, -1);
|
|
return true;
|
|
|
|
case 81:
|
|
// Light Turn On 255
|
|
EV_LightTurnOn(line->id, 255);
|
|
return true;
|
|
|
|
case 82:
|
|
// Lower Floor To Lowest
|
|
EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0, 0, 0);
|
|
return true;
|
|
|
|
case 83:
|
|
// Lower Floor
|
|
EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::SLOW),
|
|
(128 - 128) * FRACUNIT, 0, 0);
|
|
return true;
|
|
|
|
case 84:
|
|
// LowerAndChange
|
|
EV_DoFloor(DFloor::floorLowerAndChange, line, line->id, SPEED(floors::SLOW),
|
|
0 * FRACUNIT, 0, 0);
|
|
return true;
|
|
|
|
case 86:
|
|
// Open Door
|
|
EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey);
|
|
return true;
|
|
|
|
case 87:
|
|
// Perpetual Platform Raise
|
|
EV_DoPlat(line->id, line, DPlat::platPerpetualRaise, 0, SPEED(plats::SLOW),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0);
|
|
return true;
|
|
|
|
case 88:
|
|
// PlatDownWaitUp
|
|
EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::FAST),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0);
|
|
return true;
|
|
|
|
case 89:
|
|
// Platform Stop
|
|
EV_StopPlat(line->id);
|
|
return true;
|
|
|
|
case 90:
|
|
// Raise Door
|
|
EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::SLOW), TICS(doors::WAIT),
|
|
NoKey);
|
|
return true;
|
|
|
|
case 91:
|
|
// Raise Floor
|
|
EV_DoFloor(DFloor::floorRaiseToLowestCeiling, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0);
|
|
return true;
|
|
|
|
case 92:
|
|
// Raise Floor 24
|
|
EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 24, 0, 0);
|
|
return true;
|
|
|
|
case 93:
|
|
// Raise Floor 24 And Change
|
|
EV_DoFloor(DFloor::floorRaiseAndChange, line, line->id, SPEED(floors::SLOW),
|
|
24 * FRACUNIT, 0, 0);
|
|
return true;
|
|
|
|
case 94:
|
|
// Raise Floor Crush
|
|
EV_DoFloor(DFloor::floorRaiseAndCrush, line, line->id, SPEED(floors::SLOW), 0, true, 0);
|
|
return true;
|
|
|
|
case 95:
|
|
// Raise floor to nearest height
|
|
// and change texture.
|
|
EV_DoPlat(line->id, line, DPlat::platRaiseAndStay, 0, SPEED(plats::SLOW / 2), 0, 0, 1);
|
|
return true;
|
|
|
|
case 96:
|
|
// Raise floor to shortest texture height
|
|
// on either side of lines.
|
|
EV_DoFloor(DFloor::floorRaiseByTexture, line, line->id, SPEED(floors::SLOW), 0, 0, 0);
|
|
return true;
|
|
|
|
case 97:
|
|
// TELEPORT!
|
|
EV_LineTeleport(line, side, thing);
|
|
return true;
|
|
|
|
case 98:
|
|
// Lower Floor (TURBO)
|
|
EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::FAST),
|
|
(136 - 128) * FRACUNIT, 0, 0);
|
|
return true;
|
|
|
|
case 105:
|
|
// Blazing Door Raise (faster than TURBO!)
|
|
EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::FAST), TICS(doors::WAIT),
|
|
NoKey);
|
|
return true;
|
|
|
|
case 106:
|
|
// Blazing Door Open (faster than TURBO!)
|
|
EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), 0, NoKey);
|
|
return true;
|
|
|
|
case 107:
|
|
// Blazing Door Close (faster than TURBO!)
|
|
EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::FAST), 0, NoKey);
|
|
return true;
|
|
|
|
case 120:
|
|
// Blazing PlatDownWaitUpStay.
|
|
EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::TURBO),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0);
|
|
return true;
|
|
|
|
case 126:
|
|
// TELEPORT MonsterONLY.
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
{
|
|
EV_LineTeleport(line, side, thing);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 128:
|
|
// Raise To Nearest Floor
|
|
EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::SLOW), 0, 0, 0);
|
|
return true;
|
|
|
|
case 129:
|
|
// Raise Floor Turbo
|
|
EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::FAST), 0, 0, 0);
|
|
return true;
|
|
|
|
// Extended walk triggers
|
|
|
|
// jff 1/29/98 added new linedef types to fill all functions out so that
|
|
// all have varieties SR, S1, WR, W1
|
|
|
|
// killough 1/31/98: "factor out" compatibility test, by
|
|
// adding inner switch qualified by compatibility flag.
|
|
|
|
// killough 2/16/98: Fix problems with W1 types being cleared too early
|
|
|
|
default:
|
|
switch (line->special)
|
|
{
|
|
// Extended walk once triggers
|
|
|
|
case 142:
|
|
// Raise Floor 512
|
|
// 142 W1 EV_DoFloor(raiseFloor512)
|
|
if (EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 64 * 8, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 143:
|
|
// Raise Floor 24 and change
|
|
// 143 W1 EV_DoPlat(raiseAndChange,24)
|
|
if (EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 3 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 144:
|
|
// Raise Floor 32 and change
|
|
// 144 W1 EV_DoPlat(raiseAndChange,32)
|
|
if (EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 4 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 145:
|
|
// Lower Ceiling to Floor
|
|
// 145 W1 EV_DoCeiling(lowerToFloor)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToFloor, line, line->id, SPEED(ceilings::SLOW), 0,
|
|
0, 0, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 146:
|
|
// Lower Pillar, Raise Donut
|
|
// 146 W1 EV_DoDonut()
|
|
if (EV_DoDonut(line))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 199:
|
|
// Lower ceiling to lowest surrounding ceiling
|
|
// 199 W1 EV_DoCeiling(lowerToLowest)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToLowest, line, line->id, SPEED(ceilings::SLOW),
|
|
0, 0, 0, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 200:
|
|
// Lower ceiling to highest surrounding floor
|
|
// 200 W1 EV_DoCeiling(lowerToMaxFloor)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToHighestFloor, line, line->id,
|
|
SPEED(ceilings::SLOW), 0, 0, 0, 0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 207:
|
|
// killough 2/16/98: W1 silent teleporter (normal kind)
|
|
if (EV_SilentTeleport(line->args[0], 0, line->args[2], 0, line, side, thing))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
// jff 3/16/98 renumber 215->153
|
|
case 153: // jff 3/15/98 create texture change no motion type
|
|
// Texture/Type Change Only (Trig)
|
|
// 153 W1 Change Texture/Type Only
|
|
if (EV_DoChange(line, trigChangeOnly, line->id))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 239: // jff 3/15/98 create texture change no motion type
|
|
// Texture/Type Change Only (Numeric)
|
|
// 239 W1 Change Texture/Type Only
|
|
if (EV_DoChange(line, numChangeOnly, line->id))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 219:
|
|
// Lower floor to next lower neighbor
|
|
// 219 W1 Lower Floor Next Lower Neighbor
|
|
if (EV_DoFloor(DFloor::floorLowerToNearest, line, line->id, SPEED(floors::SLOW), 0,
|
|
0, 0))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 227:
|
|
// Raise elevator next floor
|
|
// 227 W1 Raise Elevator next floor
|
|
if (EV_DoElevator(line, DElevator::elevateUp, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 231:
|
|
// Lower elevator next floor
|
|
// 231 W1 Lower Elevator next floor
|
|
if (EV_DoElevator(line, DElevator::elevateDown, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 235:
|
|
// Elevator to current floor
|
|
// 235 W1 Elevator to current floor
|
|
if (EV_DoElevator(line, DElevator::elevateCurrent, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 243: // jff 3/6/98 make fit within DCK's 256 linedef types
|
|
// killough 2/16/98: W1 silent teleporter (linedef-linedef kind)
|
|
if (thing && EV_SilentLineTeleport(line, side, thing, line->id, false))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 262: // jff 4/14/98 add silent line-line reversed
|
|
if (thing && EV_SilentLineTeleport(line, side, thing, line->id, true))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 264: // jff 4/14/98 add monster-only silent line-line reversed
|
|
if (!P_IsPlayerOrAvatar(*thing) &&
|
|
EV_SilentLineTeleport(line, side, thing, line->id, true))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 266: // jff 4/14/98 add monster-only silent line-line
|
|
if (!P_IsPlayerOrAvatar(*thing) &&
|
|
EV_SilentLineTeleport(line, side, thing, line->id, false))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
case 268: // jff 4/14/98 add monster-only silent
|
|
if (!P_IsPlayerOrAvatar(*thing) &&
|
|
EV_SilentTeleport(line->args[0], 0, line->args[2], 0, line, side, thing))
|
|
{
|
|
return true;
|
|
//line->special = 0;
|
|
}
|
|
break;
|
|
|
|
// jff 1/29/98 end of added W1 linedef types
|
|
|
|
// Extended walk many retriggerable
|
|
|
|
// jff 1/29/98 added new linedef types to fill all functions
|
|
// out so that all have varieties SR, S1, WR, W1
|
|
|
|
case 147:
|
|
// Raise Floor 512
|
|
// 147 WR EV_DoFloor(raiseFloor512)
|
|
EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 64 * 8, 0, 0);
|
|
return true;
|
|
|
|
case 148:
|
|
// Raise Floor 24 and Change
|
|
// 148 WR EV_DoPlat(raiseAndChange,24)
|
|
EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 3 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2);
|
|
return true;
|
|
|
|
case 149:
|
|
// Raise Floor 32 and Change
|
|
// 149 WR EV_DoPlat(raiseAndChange,32)
|
|
EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 4 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2);
|
|
return true;
|
|
|
|
case 150:
|
|
// Start slow silent crusher
|
|
// 150 WR EV_DoCeiling(silentCrushAndRaise)
|
|
EV_DoCeiling(DCeiling::silentCrushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 1, 0);
|
|
return true;
|
|
|
|
case 151:
|
|
// RaiseCeilingLowerFloor
|
|
// 151 WR EV_DoCeiling(raiseToHighest),
|
|
// EV_DoFloor(lowerFloortoLowest)
|
|
EV_DoCeiling(DCeiling::ceilRaiseToHighest, line, line->id, SPEED(ceilings::SLOW), 0,
|
|
0, 0, 0, 0);
|
|
EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0);
|
|
return true;
|
|
|
|
case 152:
|
|
// Lower Ceiling to Floor
|
|
// 152 WR EV_DoCeiling(lowerToFloor)
|
|
EV_DoCeiling(DCeiling::ceilLowerToFloor, line, line->id, SPEED(ceilings::SLOW), 0, 0,
|
|
0, 0, 0);
|
|
return true;
|
|
|
|
// jff 3/16/98 renumber 153->256
|
|
case 256:
|
|
// Build stairs, step 8
|
|
// 256 WR EV_BuildStairs(build8)
|
|
EV_BuildStairs(line->id, DFloor::buildUp, line, 8 * FRACUNIT, SPEED(stairs::SLOW),
|
|
0, 0, 0, 0);
|
|
return true;
|
|
|
|
// jff 3/16/98 renumber 154->257
|
|
case 257:
|
|
// Build stairs, step 16
|
|
// 257 WR EV_BuildStairs(turbo16)
|
|
EV_BuildStairs(line->id, DFloor::buildUp, line, 16 * FRACUNIT, SPEED(stairs::TURBO),
|
|
0, 0, 0, 0);
|
|
return true;
|
|
|
|
case 155:
|
|
// Lower Pillar, Raise Donut
|
|
// 155 WR EV_DoDonut()
|
|
EV_DoDonut(line);
|
|
return true;
|
|
|
|
case 156:
|
|
// Start lights strobing
|
|
// 156 WR Lights EV_StartLightStrobing()
|
|
EV_StartLightStrobing(line->id, TICS(5), TICS(35));
|
|
return true;
|
|
|
|
case 157:
|
|
// Lights to dimmest near
|
|
// 157 WR Lights EV_TurnTagLightsOff()
|
|
EV_TurnTagLightsOff(line->id);
|
|
return true;
|
|
|
|
case 201:
|
|
// Lower ceiling to lowest surrounding ceiling
|
|
// 201 WR EV_DoCeiling(lowerToLowest)
|
|
EV_DoCeiling(DCeiling::ceilLowerToLowest, line, line->id, SPEED(ceilings::SLOW), 0, 0,
|
|
0, 0, 0);
|
|
return true;
|
|
|
|
case 202:
|
|
// Lower ceiling to highest surrounding floor
|
|
// 202 WR EV_DoCeiling(lowerToMaxFloor)
|
|
EV_DoCeiling(DCeiling::ceilLowerToHighestFloor, line, line->id, SPEED(ceilings::SLOW),
|
|
0, 0, 0, 0, 0);
|
|
return true;
|
|
|
|
case 208:
|
|
// killough 2/16/98: WR silent teleporter (normal kind)
|
|
EV_SilentTeleport(line->args[0], 0, line->args[2], 0, line, side, thing);
|
|
return true;
|
|
|
|
case 212: // jff 3/14/98 create instant toggle floor type
|
|
// Toggle floor between C and F instantly
|
|
// 212 WR Instant Toggle Floor
|
|
EV_DoPlat(line->id, line, DPlat::platToggle, 0, 0, 0, 0, 0);
|
|
return true;
|
|
|
|
// jff 3/16/98 renumber 216->154
|
|
case 154: // jff 3/15/98 create texture change no motion type
|
|
// Texture/Type Change Only (Trigger)
|
|
// 154 WR Change Texture/Type Only
|
|
EV_DoChange(line, trigChangeOnly, line->id);
|
|
return true;
|
|
|
|
case 240: // jff 3/15/98 create texture change no motion type
|
|
// Texture/Type Change Only (Numeric)
|
|
// 240 WR Change Texture/Type Only
|
|
EV_DoChange(line, numChangeOnly, line->id);
|
|
return true;
|
|
|
|
case 220:
|
|
// Lower floor to next lower neighbor
|
|
// 220 WR Lower Floor Next Lower Neighbor
|
|
EV_DoFloor(DFloor::floorLowerToNearest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0);
|
|
return true;
|
|
|
|
case 228:
|
|
// Raise elevator next floor
|
|
// 228 WR Raise Elevator next floor
|
|
EV_DoElevator(line, DElevator::elevateUp, SPEED(ELEVATORSPEED), 0, line->id);
|
|
return true;
|
|
|
|
case 232:
|
|
// Lower elevator next floor
|
|
// 232 WR Lower Elevator next floor
|
|
EV_DoElevator(line, DElevator::elevateDown, SPEED(ELEVATORSPEED), 0,
|
|
line->id);
|
|
return true;
|
|
|
|
case 236:
|
|
// Elevator to current floor
|
|
// 236 WR Elevator to current floor
|
|
EV_DoElevator(line, DElevator::elevateCurrent, SPEED(ELEVATORSPEED), 0,
|
|
line->id);
|
|
return true;
|
|
|
|
case 244: // jff 3/6/98 make fit within DCK's 256 linedef types
|
|
// killough 2/16/98: WR silent teleporter (linedef-linedef kind)
|
|
if (thing)
|
|
{
|
|
EV_SilentLineTeleport(line, side, thing, line->id, false);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 263: // jff 4/14/98 add silent line-line reversed
|
|
if (thing)
|
|
{
|
|
EV_SilentLineTeleport(line, side, thing, line->id, true);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 265: // jff 4/14/98 add monster-only silent line-line reversed
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
{
|
|
EV_SilentLineTeleport(line, side, thing, line->id, true);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 267: // jff 4/14/98 add monster-only silent line-line
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
{
|
|
EV_SilentLineTeleport(line, side, thing, line->id, false);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 269: // jff 4/14/98 add monster-only silent
|
|
if (!thing->player)
|
|
{
|
|
EV_SilentTeleport(line->args[0], 0, line->args[2], 0, line, side, thing);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
// jff 1/29/98 end of added WR linedef types
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void P_ApplyGeneralizedSectorDamage(player_t& player, int bits)
|
|
{
|
|
switch (bits & 3)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
P_ApplySectorDamage(player, 5, 0);
|
|
break;
|
|
case 2:
|
|
P_ApplySectorDamage(player, 10, 0);
|
|
break;
|
|
case 3:
|
|
P_ApplySectorDamage(player, 20, 5);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void P_CollectSecretBoom(sector_t& sector, player_t& player)
|
|
{
|
|
sector.special &= ~SECRET_MASK;
|
|
|
|
if (sector.special < 32) // if all extended bits clear,
|
|
sector.special = 0; // sector is not special anymore
|
|
|
|
P_CollectSecretCommon(sector, player);
|
|
}
|
|
|
|
void P_PlayerInCompatibleSector(player_t& player)
|
|
{
|
|
// Spectators should not be affected by special sectors
|
|
if (player.spectator)
|
|
return;
|
|
|
|
// Being destroyed / unlinked from the map?
|
|
if (not (player.mo && player.mo->subsector))
|
|
return;
|
|
|
|
// Falling, not all the way down yet?
|
|
if (player.mo->z != P_FloorHeight(player.mo) && !player.mo->waterlevel)
|
|
return;
|
|
|
|
sector_t& sector = *player.mo->subsector->sector;
|
|
if (sector.special == 0 && sector.damageamount > 0) // Odamex Static Init Damage
|
|
{
|
|
if (sector.damageamount < 20)
|
|
{
|
|
P_ApplySectorDamageNoRandom(player, sector.damageamount, MOD_UNKNOWN);
|
|
}
|
|
else if (sector.damageamount < 50)
|
|
{
|
|
P_ApplySectorDamage(player, sector.damageamount, 5, MOD_UNKNOWN);
|
|
}
|
|
else
|
|
{
|
|
P_ApplySectorDamageNoWait(player, sector.damageamount, MOD_UNKNOWN);
|
|
}
|
|
}
|
|
// jff add if to handle old vs generalized types
|
|
else if (sector.special < 32) // regular sector specials
|
|
{
|
|
switch (sector.special)
|
|
{
|
|
case 5:
|
|
P_ApplySectorDamage(player, 10, 0, MOD_SLIME);
|
|
break;
|
|
case 7:
|
|
P_ApplySectorDamage(player, 5, 0, MOD_SLIME);
|
|
break;
|
|
case 16:
|
|
case 4:
|
|
P_ApplySectorDamage(player, 20, 5, MOD_SLIME);
|
|
break;
|
|
case 9:
|
|
P_CollectSecretVanilla(sector, player);
|
|
break;
|
|
case 11:
|
|
P_ApplySectorDamageEndLevel(player);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else // jff 3/14/98 handle extended sector damage
|
|
{
|
|
if (sector.special & DEATH_MASK)
|
|
{
|
|
switch ((sector.special & DAMAGE_MASK) >> DAMAGE_SHIFT)
|
|
{
|
|
case 0: // Kill player unless invuln or rad suit or IDDQD
|
|
if (!player.powers[pw_invulnerability] && !player.powers[pw_ironfeet] && !(player.cheats & CF_GODMODE))
|
|
{
|
|
P_DamageMobj(player.mo, NULL, NULL, 999, MOD_UNKNOWN); // 999 so BUDDHA can survive
|
|
}
|
|
break;
|
|
case 1: // Kill player with no scruples unless IDDQD
|
|
if(!(player.cheats & CF_GODMODE))
|
|
{
|
|
P_DamageMobj(player.mo, NULL, NULL, 10000, MOD_UNKNOWN);
|
|
}
|
|
break;
|
|
case 2: // Kill all players and exit. There's no delay here so it may confuse
|
|
// some players. Do NOT kill players with IDDQD.
|
|
if (serverside)
|
|
{
|
|
if (sv_allowexit)
|
|
{
|
|
for (auto& pl : ::players)
|
|
{
|
|
if (pl.ingame() && pl.health > 0 && !(pl.cheats & CF_GODMODE))
|
|
{
|
|
P_DamageMobj(pl.mo, NULL, NULL, 10000, MOD_EXIT);
|
|
}
|
|
}
|
|
G_ExitLevel(0, 1);
|
|
}
|
|
else if (!(player.cheats & CF_GODMODE)) // Do NOT kill players with IDDQD.
|
|
{
|
|
P_DamageMobj(
|
|
player.mo, NULL, NULL, 10000,
|
|
MOD_EXIT); // Exiting not allowed, kill only activator here
|
|
// even if fragexitswitch = 0
|
|
}
|
|
}
|
|
break;
|
|
case 3: // Kill all players and secret exit. There's no delay here so it may
|
|
// confuse some players. Do NOT kill players with IDDQD.
|
|
if (serverside)
|
|
{
|
|
if (sv_allowexit)
|
|
{
|
|
for (auto& pl : ::players)
|
|
{
|
|
if (pl.ingame() && pl.health > 0 && !(pl.cheats & CF_GODMODE))
|
|
{
|
|
P_DamageMobj(pl.mo, NULL, NULL, 10000, MOD_EXIT);
|
|
}
|
|
}
|
|
G_SecretExitLevel(0, 1);
|
|
}
|
|
else if (!(player.cheats & CF_GODMODE)) // Do NOT kill players with IDDQD.
|
|
{
|
|
P_DamageMobj(
|
|
player.mo, NULL, NULL, 10000,
|
|
MOD_EXIT); // Exiting not allowed, kill only activator here
|
|
// even if fragexitswitch = 0
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (!(player.cheats & CF_GODMODE)) // Do NOT damage players with IDDQD.
|
|
{
|
|
P_ApplyGeneralizedSectorDamage(player, (sector.special & DAMAGE_MASK) >>
|
|
DAMAGE_SHIFT);
|
|
}
|
|
}
|
|
|
|
if (sector.flags & SECF_SECRET)
|
|
{
|
|
P_CollectSecretBoom(sector, player);
|
|
}
|
|
}
|
|
|
|
//
|
|
// P_ActorInCompatibleSector
|
|
// Really only used for one function -- kill land monsters sector action.
|
|
//
|
|
bool P_ActorInCompatibleSector(AActor* actor)
|
|
{
|
|
if (not (actor && actor->subsector))
|
|
return false;
|
|
|
|
const bool sectorHasKillMonstersAction = actor->subsector->sector->special & KILL_MONSTERS_MASK;
|
|
|
|
if (sectorHasKillMonstersAction && actor->z == actor->floorz &&
|
|
!P_IsPlayerOrAvatar(*actor) && actor->flags & MF_SHOOTABLE && !(actor->flags & MF_FLOAT))
|
|
{
|
|
P_DamageMobj(actor, NULL, NULL, 10000);
|
|
|
|
// must have been killed
|
|
if (actor->health <= 0)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void P_PostProcessCompatibleSidedefSpecial(side_t* sd, mapsidedef_t* msd,
|
|
sector_t* sec, int i)
|
|
{
|
|
switch (sd->special)
|
|
{
|
|
case 242: // variable colormap via 242 linedef
|
|
// [RH] The colormap num we get here isn't really a colormap,
|
|
// but a packed ARGB word for blending, so we also allow
|
|
// the blend to be specified directly by the texture names
|
|
// instead of figuring something out from the colormap.
|
|
P_SetTransferHeightBlends(sd, msd);
|
|
break;
|
|
|
|
case OdamexStaticInits + 1: // init_color
|
|
// [RH] Set sector color and fog
|
|
// upper "texture" is light color
|
|
// lower "texture" is fog color
|
|
{
|
|
unsigned int color = 0xffffff, fog = 0x000000;
|
|
|
|
SetTextureNoErr(&sd->bottomtexture, &fog, msd->bottomtexture);
|
|
SetTextureNoErr(&sd->toptexture, &color, msd->toptexture);
|
|
sd->midtexture = R_TextureNumForName(msd->midtexture);
|
|
|
|
if (fog != 0x000000 || color != 0xffffff)
|
|
{
|
|
dyncolormap_t* colormap =
|
|
GetSpecialLights(((argb_t)color).getr(), ((argb_t)color).getg(),
|
|
((argb_t)color).getb(), ((argb_t)fog).getr(),
|
|
((argb_t)fog).getg(), ((argb_t)fog).getb());
|
|
|
|
for (sector_t& sector : R_GetSectors())
|
|
{
|
|
if (sector.tag == sd->tag)
|
|
sector.colormap = colormap;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
case 260: // killough 4/11/98: apply translucency to 2s
|
|
normal texture sd->midtexture = strncasecmp("TRANMAP", msd->midtexture, 8) ?
|
|
(sd->special = W_CheckNumForName(msd->midtexture)) < 0 ||
|
|
W_LumpLength(sd->special) != 65536 ?
|
|
sd->special=0, R_TextureNumForName(msd->midtexture) :
|
|
(sd->special++, 0) : (sd->special=0);
|
|
sd->toptexture = R_TextureNumForName(msd->toptexture);
|
|
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
|
break;
|
|
*/
|
|
default: // normal cases
|
|
sd->midtexture = R_TextureNumForName(msd->midtexture);
|
|
sd->toptexture = R_TextureNumForName(msd->toptexture);
|
|
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void P_SpawnCompatibleExtra(int i)
|
|
{
|
|
int s;
|
|
sector_t* sec;
|
|
float grav;
|
|
int damage;
|
|
fixed_t xoffs;
|
|
fixed_t yoffs;
|
|
angle_t angle;
|
|
|
|
switch (lines[i].special)
|
|
{
|
|
// killough 3/7/98:
|
|
// support for drawn heights coming from different sector
|
|
case 242:
|
|
sec = sides[*lines[i].sidenum].sector;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
sectors[s].heightsec = sec;
|
|
break;
|
|
|
|
// killough 3/16/98: Add support for setting
|
|
// floor lighting independently (e.g. lava)
|
|
case 213:
|
|
sec = sides[*lines[i].sidenum].sector;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
sectors[s].floorlightsec = sec;
|
|
break;
|
|
|
|
// killough 4/11/98: Add support for setting
|
|
// ceiling lighting independently
|
|
case 261:
|
|
sec = sides[*lines[i].sidenum].sector;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
sectors[s].ceilinglightsec = sec;
|
|
break;
|
|
|
|
// killough 10/98:
|
|
//
|
|
// Support for sky textures being transferred from sidedefs.
|
|
// Allows scrolling and other effects (but if scrolling is
|
|
// used, then the same sector tag needs to be used for the
|
|
// sky sector, the sky-transfer linedef, and the scroll-effect
|
|
// linedef). Still requires user to use F_SKY1 for the floor
|
|
// or ceiling texture, to distinguish floor and ceiling sky.
|
|
|
|
case 271: // Regular sky
|
|
case 272: // Same, only flipped
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
sectors[s].sky = (i + 1) | PL_SKYFLAT;
|
|
break;
|
|
|
|
case OdamexStaticInits: // Gravity
|
|
grav =
|
|
((float)P_AproxDistance(lines[i].dx, lines[i].dy)) / (FRACUNIT * 100.0f);
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0;)
|
|
sectors[s].gravity = grav;
|
|
break;
|
|
|
|
case OdamexStaticInits + 2: // Damage
|
|
damage = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0;)
|
|
{
|
|
sectors[s].damageamount = damage;
|
|
sectors[s].damageinterval = 32;
|
|
sectors[s].leakrate = 0;
|
|
sectors[s].mod = MOD_UNKNOWN;
|
|
}
|
|
break;
|
|
|
|
// 2048-2056 ID24 flat offset and rotation
|
|
// floor offset
|
|
case 2048:
|
|
xoffs = lines[i].dx;
|
|
yoffs = lines[i].dy;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].floor_xoffs -= xoffs;
|
|
sectors[s].floor_yoffs += yoffs;
|
|
}
|
|
break;
|
|
// ceiling offset
|
|
case 2049:
|
|
xoffs = lines[i].dx;
|
|
yoffs = lines[i].dy;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].ceiling_xoffs -= xoffs;
|
|
sectors[s].ceiling_yoffs += yoffs;
|
|
}
|
|
break;
|
|
// floor and ceiling offset
|
|
case 2050:
|
|
xoffs = lines[i].dx;
|
|
yoffs = lines[i].dy;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].floor_xoffs -= xoffs;
|
|
sectors[s].floor_yoffs += yoffs;
|
|
sectors[s].ceiling_xoffs -= xoffs;
|
|
sectors[s].ceiling_yoffs += yoffs;
|
|
}
|
|
break;
|
|
// floor rotation
|
|
case 2051:
|
|
angle = P_PointToAngle(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].floor_angle -= angle;
|
|
}
|
|
break;
|
|
// ceiling rotation
|
|
case 2052:
|
|
angle = P_PointToAngle(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].ceiling_angle -= angle;
|
|
}
|
|
break;
|
|
// floor and ceiling rotation
|
|
case 2053:
|
|
angle = P_PointToAngle(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].floor_angle -= angle;
|
|
sectors[s].ceiling_angle -= angle;
|
|
}
|
|
break;
|
|
// floor offset and rotation
|
|
case 2054:
|
|
angle = P_PointToAngle(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
|
xoffs = lines[i].dx;
|
|
yoffs = lines[i].dy;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].floor_angle -= angle;
|
|
sectors[s].floor_xoffs -= xoffs;
|
|
sectors[s].floor_yoffs += yoffs;
|
|
}
|
|
break;
|
|
// ceiling offset and rotation
|
|
case 2055:
|
|
angle = P_PointToAngle(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
|
xoffs = lines[i].dx;
|
|
yoffs = lines[i].dy;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].ceiling_angle -= angle;
|
|
sectors[s].ceiling_xoffs -= xoffs;
|
|
sectors[s].ceiling_yoffs += yoffs;
|
|
}
|
|
break;
|
|
// floor and ceiling offset and rotation
|
|
case 2056:
|
|
angle = P_PointToAngle(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
|
|
xoffs = lines[i].dx;
|
|
yoffs = lines[i].dy;
|
|
for (s = -1; (s = P_FindSectorFromTag(lines[i].id, s)) >= 0;)
|
|
{
|
|
sectors[s].floor_angle -= angle;
|
|
sectors[s].ceiling_angle -= angle;
|
|
sectors[s].floor_xoffs -= xoffs;
|
|
sectors[s].floor_yoffs += yoffs;
|
|
sectors[s].ceiling_xoffs -= xoffs;
|
|
sectors[s].ceiling_yoffs += yoffs;
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// P_SpawnCompatibleSectorSpecial
|
|
// After the map has been loaded, scan for specials
|
|
// that spawn thinkers.
|
|
// Only runs for maps in Doom format.
|
|
//
|
|
|
|
void P_SpawnCompatibleSectorSpecial(sector_t* sector)
|
|
{
|
|
if (sector->special & SECRET_MASK) // jff 3/15/98 count extended
|
|
P_AddSectorSecret(sector);
|
|
|
|
if (sector->special & FRICTION_MASK)
|
|
sector->flags |= SECF_FRICTION;
|
|
|
|
if (sector->special & PUSH_MASK)
|
|
sector->flags |= SECF_PUSH;
|
|
|
|
switch (sector->special & 31)
|
|
{
|
|
case 1:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// random off
|
|
P_SpawnLightFlash(sector);
|
|
break;
|
|
|
|
case 2:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// strobe fast
|
|
P_SpawnStrobeFlash(sector, STROBEBRIGHT, FASTDARK, false);
|
|
break;
|
|
|
|
case 3:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// strobe slow
|
|
P_SpawnStrobeFlash(sector, STROBEBRIGHT, SLOWDARK, false);
|
|
break;
|
|
|
|
case 4:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// strobe fast/death slime
|
|
P_SpawnStrobeFlash(sector, STROBEBRIGHT, FASTDARK, false);
|
|
sector->special |= 3 << DAMAGE_SHIFT; // jff 3/14/98 put damage bits in
|
|
break;
|
|
|
|
case 8:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// glowing light
|
|
P_SpawnGlowingLight(sector);
|
|
break;
|
|
case 9:
|
|
// secret sector
|
|
if (sector->special < 32) // jff 3/14/98 bits don't count unless not
|
|
P_AddSectorSecret(sector);
|
|
break;
|
|
|
|
case 10:
|
|
if (!serverside)
|
|
break;
|
|
// door close in 30 seconds
|
|
P_SpawnDoorCloseIn30(sector);
|
|
break;
|
|
|
|
case 12:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// sync strobe slow
|
|
P_SpawnStrobeFlash(sector, STROBEBRIGHT, SLOWDARK, true);
|
|
break;
|
|
|
|
case 13:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// sync strobe fast
|
|
P_SpawnStrobeFlash(sector, STROBEBRIGHT, FASTDARK, true);
|
|
break;
|
|
|
|
case 14:
|
|
if (!serverside)
|
|
break;
|
|
// door raise in 5 minutes
|
|
P_SpawnDoorRaiseIn5Mins(sector);
|
|
break;
|
|
|
|
case 17:
|
|
if (IgnoreSpecial)
|
|
break;
|
|
// fire flickering
|
|
P_SpawnFireFlicker(sector);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void P_SpawnCompatibleScroller(line_t* l, int i)
|
|
{
|
|
// [Blair] don't run scrolling on clients to prevent desyncs
|
|
if (IgnoreSpecial)
|
|
return;
|
|
|
|
fixed_t dx = l->dx >> SCROLL_SHIFT; // direction and speed of scrolling
|
|
fixed_t dy = l->dy >> SCROLL_SHIFT;
|
|
int control = -1, accel = 0; // no control sector or acceleration
|
|
int special = l->special;
|
|
|
|
if (demoplayback && special != 48) // demo compat
|
|
return; // e6y
|
|
|
|
// killough 3/7/98: Types 245-249 are same as 250-254 except that the
|
|
// first side's sector's heights cause scrolling when they change, and
|
|
// this linedef controls the direction and speed of the scrolling. The
|
|
// most complicated linedef since donuts, but powerful :)
|
|
//
|
|
// killough 3/15/98: Add acceleration. Types 214-218 are the same but
|
|
// are accelerative.
|
|
|
|
if (special >= 245 && special <= 249) // displacement scrollers
|
|
{
|
|
special += 250 - 245;
|
|
control = sides[*l->sidenum].sector - sectors;
|
|
}
|
|
else if (special >= 214 && special <= 218) // accelerative scrollers
|
|
{
|
|
accel = 1;
|
|
special += 250 - 214;
|
|
control = sides[*l->sidenum].sector - sectors;
|
|
}
|
|
|
|
switch (special)
|
|
{
|
|
int s;
|
|
|
|
case 250: // scroll effect ceiling
|
|
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0;)
|
|
new DScroller(DScroller::sc_ceiling, -dx, dy, control, s, accel);
|
|
break;
|
|
|
|
case 251: // scroll effect floor
|
|
case 253: // scroll and carry objects on floor
|
|
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0;)
|
|
new DScroller(DScroller::sc_floor, -dx, dy, control, s, accel);
|
|
if (special != 253)
|
|
break;
|
|
[[fallthrough]];
|
|
|
|
case 252: // carry objects on floor
|
|
dx = FixedMul(dx, CARRYFACTOR);
|
|
dy = FixedMul(dy, CARRYFACTOR);
|
|
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0;)
|
|
new DScroller(DScroller::sc_carry, dx, dy, control, s, accel);
|
|
break;
|
|
|
|
// killough 3/1/98: scroll wall according to linedef
|
|
// (same direction and speed as scrolling floors)
|
|
case 254:
|
|
if (l->id == 0)
|
|
{
|
|
new DScroller(dx, dy, l, control, accel);
|
|
}
|
|
else
|
|
{
|
|
for (s = -1; (s = P_FindLineFromLineTag(l, s)) >= 0;)
|
|
if (s != i)
|
|
new DScroller(dx, dy, lines + s, control, accel);
|
|
}
|
|
break;
|
|
|
|
case 255: // killough 3/2/98: scroll according to sidedef offsets
|
|
s = lines[i].sidenum[0];
|
|
new DScroller(DScroller::sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1,
|
|
s, accel);
|
|
break;
|
|
|
|
// MBF21 scrollers and double sided variants from ID24
|
|
case 1025:
|
|
case 1026:
|
|
case 2085:
|
|
case 2086:
|
|
control = sides[*l->sidenum].sector - sectors;
|
|
[[fallthrough]];
|
|
case 1024: // special 255 with tag control
|
|
case 2084:
|
|
if (l->id == 0)
|
|
PrintFmt(PRINT_HIGH, "Line {} is missing a tag!", i);
|
|
|
|
if (special == 1026 || special == 2086)
|
|
accel = 1;
|
|
|
|
s = lines[i].sidenum[0];
|
|
dx = -sides[s].textureoffset / 8;
|
|
dy = sides[s].rowoffset / 8;
|
|
for (s = -1; (s = P_FindLineFromLineTag(l, s)) >= 0;)
|
|
if (s != i)
|
|
{
|
|
new DScroller(DScroller::sc_side, dx, dy, control, lines[s].sidenum[0],
|
|
accel);
|
|
if (lines[s].sidenum[1] != R_NOSIDE)
|
|
new DScroller(DScroller::sc_side, -dx, dy, control, lines[s].sidenum[1],
|
|
accel);
|
|
}
|
|
break;
|
|
|
|
case 2082: // scroll both sides left
|
|
if (lines[i].sidenum[1] != R_NOSIDE)
|
|
new DScroller(DScroller::sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[1], accel);
|
|
[[fallthrough]];
|
|
case 48: // scroll first side
|
|
new DScroller(DScroller::sc_side, FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
|
|
break;
|
|
|
|
case 2083: // scroll both sides right
|
|
if (lines[i].sidenum[1] != R_NOSIDE)
|
|
new DScroller(DScroller::sc_side, FRACUNIT, 0, -1, lines[i].sidenum[1], accel);
|
|
[[fallthrough]];
|
|
case 85: // jff 1/30/98 2-way scroll
|
|
new DScroller(DScroller::sc_side, -FRACUNIT, 0, -1, lines[i].sidenum[0], accel);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// killough 3/7/98 -- end generalized scroll effects
|
|
|
|
void P_SpawnCompatibleFriction(line_t* l)
|
|
{
|
|
if (l->special == 223)
|
|
{
|
|
int value;
|
|
bool use_thinker;
|
|
|
|
value = P_AproxDistance(l->dx, l->dy) >> FRACBITS;
|
|
use_thinker = !demoplayback;
|
|
|
|
P_ApplySectorFriction(l->id, value, use_thinker);
|
|
}
|
|
}
|
|
|
|
void P_SpawnCompatiblePusher(line_t* l)
|
|
{
|
|
int s;
|
|
AActor* thing;
|
|
|
|
switch (l->special)
|
|
{
|
|
case 224: // wind
|
|
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0;)
|
|
new DPusher(DPusher::p_wind, l, 0, 0, NULL, s);
|
|
break;
|
|
case 225: // current
|
|
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0;)
|
|
new DPusher(DPusher::p_current, l, 0, 0, NULL, s);
|
|
break;
|
|
case 226: // push/pull
|
|
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0;)
|
|
{
|
|
thing = P_GetPushThing(s);
|
|
if (thing) // No MT_P* means no effect
|
|
new DPusher(DPusher::p_push, l, 0, 0, thing, s);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// P_UseCompatibleSpecialLine
|
|
//
|
|
//
|
|
// Called when a thing uses (pushes) a special line.
|
|
// Only the front sides of lines are usable.
|
|
// Dispatches to the appropriate linedef function handler.
|
|
//
|
|
// Passed the thing using the line, the line being used, and the side used
|
|
// Returns true if a thinker was created
|
|
//
|
|
bool P_UseCompatibleSpecialLine(AActor* thing, line_t* line, int side,
|
|
bool bossaction)
|
|
{
|
|
bool resetinv = false; // used for exits
|
|
bool reuse = false;
|
|
bool trigger = false; // used for bossactions
|
|
// e6y
|
|
// b.m. side test was broken in boom201
|
|
if (side) // jff 6/1/98 fix inadvertent deletion of side test
|
|
return false;
|
|
|
|
// jff 02/04/98 add check here for generalized floor/ceil mover
|
|
|
|
// pointer to line function is NULL by default, set non-null if
|
|
// line special is push or switch generalized linedef type
|
|
bool (*linefunc)(line_t& line) = nullptr;
|
|
|
|
// check each range of generalized linedefs
|
|
if ((unsigned)line->special >= GenEnd)
|
|
{
|
|
// Out of range for GenFloors
|
|
}
|
|
else if ((unsigned)line->special >= GenFloorBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if ((line->special & FloorChange) || !(line->special & FloorModel))
|
|
return false; // FloorModel is "Allow Monsters" if FloorChange is 0
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 2/27/98 all non-manual
|
|
return false; // generalized types require tag
|
|
linefunc = EV_DoGenFloor;
|
|
}
|
|
else if ((unsigned)line->special >= GenCeilingBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if ((line->special & CeilingChange) || !(line->special & CeilingModel))
|
|
return false; // CeilingModel is "Allow Monsters" if CeilingChange is
|
|
// 0
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 2/27/98 all non-manual
|
|
return false; // generalized types require tag
|
|
linefunc = EV_DoGenCeiling;
|
|
}
|
|
else if ((unsigned)line->special >= GenDoorBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
{
|
|
if (!(line->special & DoorMonster))
|
|
return false; // monsters disallowed from this door
|
|
if (line->flags & ML_SECRET) // they can't open secret doors either
|
|
return false;
|
|
}
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 3/2/98 all non-manual
|
|
return false; // generalized types require tag
|
|
linefunc = EV_DoGenDoor;
|
|
}
|
|
else if ((unsigned)line->special >= GenLockedBase)
|
|
{
|
|
if ((!P_IsPlayerOrAvatar(*thing)) || bossaction)
|
|
return false; // monsters disallowed from unlocking doors
|
|
if (!P_CanUnlockGenDoor(line, thing->player))
|
|
return false;
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 2/27/98 all non-manual
|
|
return false; // generalized types require tag
|
|
|
|
linefunc = EV_DoGenLockedDoor;
|
|
}
|
|
else if ((unsigned)line->special >= GenLiftBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if (!(line->special & LiftMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 2/27/98 all non-manual
|
|
return false; // generalized types require tag
|
|
linefunc = EV_DoGenLift;
|
|
}
|
|
else if ((unsigned)line->special >= GenStairsBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if (!(line->special & StairMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 2/27/98 all non-manual
|
|
return false; // generalized types require tag
|
|
linefunc = EV_DoGenStairs;
|
|
}
|
|
else if ((unsigned)line->special >= GenCrusherBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
if (!(line->special & CrusherMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id &&
|
|
((line->special & 6) != 6)) // e6y //jff 2/27/98 all non-manual
|
|
return false; // generalized types require tag
|
|
linefunc = EV_DoGenCrusher;
|
|
}
|
|
|
|
if (linefunc)
|
|
switch ((line->special & TriggerType) >> TriggerTypeShift)
|
|
{
|
|
case PushOnce:
|
|
if (!side)
|
|
{
|
|
if (linefunc(*line))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
}
|
|
break;
|
|
case PushMany:
|
|
if (!side)
|
|
{
|
|
linefunc(*line);
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case SwitchOnce:
|
|
if (linefunc(*line))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case SwitchMany:
|
|
if (linefunc(*line))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
default: // if not a switch/push type, do nothing here
|
|
return false;
|
|
}
|
|
|
|
// Switches that other things can activate.
|
|
if (thing && !P_IsPlayerOrAvatar(*thing) && !bossaction)
|
|
{
|
|
// never open secret doors
|
|
if (line->flags & ML_SECRET)
|
|
return false;
|
|
|
|
switch (line->special)
|
|
{
|
|
case 1: // MANUAL DOOR RAISE
|
|
case 32: // MANUAL BLUE
|
|
case 33: // MANUAL RED
|
|
case 34: // MANUAL YELLOW
|
|
// jff 3/5/98 add ability to use teleporters for monsters
|
|
case 195: // switch teleporters
|
|
case 174:
|
|
case 210: // silent switch teleporters
|
|
case 209:
|
|
break;
|
|
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bossaction)
|
|
{
|
|
switch (line->special)
|
|
{
|
|
// 0-tag specials, locked switches and teleporters need to be blocked for boss
|
|
// actions.
|
|
case 1: // MANUAL DOOR RAISE
|
|
case 32: // MANUAL BLUE
|
|
case 33: // MANUAL RED
|
|
case 34: // MANUAL YELLOW
|
|
case 117: // Blazing door raise
|
|
case 118: // Blazing door open
|
|
case 133: // BlzOpenDoor BLUE
|
|
case 135: // BlzOpenDoor RED
|
|
case 137: // BlzOpenDoor YEL
|
|
|
|
case 99: // BlzOpenDoor BLUE
|
|
case 134: // BlzOpenDoor RED
|
|
case 136: // BlzOpenDoor YELLOW
|
|
|
|
// jff 3/5/98 add ability to use teleporters for monsters
|
|
case 195: // switch teleporters
|
|
case 174:
|
|
case 210: // silent switch teleporters
|
|
case 209:
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!P_CheckTag(line)) // jff 2/27/98 disallow zero tag on some types
|
|
return false;
|
|
|
|
// Dispatch to handler according to linedef type
|
|
switch (line->special)
|
|
{
|
|
// Manual doors, push type with no tag
|
|
case 1: // Vertical Door
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, 0, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 26: // Blue Door/Locked
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, 0, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), (card_t)(BCard | CardIsSkull)))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 27: // Yellow Door /Locked
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, 0, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), (card_t)(YCard | CardIsSkull)))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 28: // Red Door /Locked
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, 0, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), (card_t)(RCard | CardIsSkull)))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 31: // Manual door open
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, 0, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 32: // Blue locked door open
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, 0, SPEED(doors::SLOW),
|
|
0, (card_t)(BCard | CardIsSkull)))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 33: // Red locked door open
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, 0, SPEED(doors::SLOW), 0,
|
|
(card_t)(RCard | CardIsSkull)))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 34: // Yellow locked door open
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, 0, SPEED(doors::SLOW), 0,
|
|
(card_t)(YCard | CardIsSkull)))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 117: // Blazing door raise
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, 0, SPEED(doors::FAST),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 118: // Blazing door open
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, 0, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
// Switches (non-retriggerable)
|
|
case 7:
|
|
// Build Stairs
|
|
if (EV_BuildStairs(line->id, DFloor::buildUp, line, 8 * FRACUNIT, SPEED(stairs::SLOW),
|
|
0, 0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 9:
|
|
// Change Donut
|
|
if (EV_DoDonut(line))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 2070:
|
|
resetinv = true;
|
|
[[fallthrough]];
|
|
case 11:
|
|
/* Exit level
|
|
* killough 10/98: prevent zombies from exiting levels
|
|
*/
|
|
if (!bossaction && thing && thing->player && thing->player->health <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (thing && CheckIfExitIsGood(thing))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
G_ExitLevel(0, 1, resetinv);
|
|
}
|
|
break;
|
|
|
|
case 14:
|
|
// Raise Floor 32 and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 4 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 15:
|
|
// Raise Floor 24 and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 3 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 18:
|
|
// Raise Floor to next highest floor
|
|
if (EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::SLOW), 0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 20:
|
|
// Raise Plat next highest floor and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platRaiseAndStay, 0, SPEED(plats::SLOW / 2), 0, 0, 1))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 21:
|
|
// PlatDownWaitUpStay
|
|
if (EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::FAST),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 23:
|
|
// Lower Floor to Lowest
|
|
if (EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 29:
|
|
// Raise Door
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 41:
|
|
// Lower Ceiling to Floor
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToFloor, line, line->id, SPEED(ceilings::SLOW), 0, 0,
|
|
0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 71:
|
|
// Turbo Lower Floor
|
|
if (EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::FAST),
|
|
(136 - 128) * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 49:
|
|
// Ceiling Crush And Raise
|
|
if (EV_DoCeiling(DCeiling::crushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 50:
|
|
// Close Door
|
|
if (EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 2073:
|
|
resetinv = true;
|
|
[[fallthrough]];
|
|
case 51:
|
|
/* Secret EXIT
|
|
* killough 10/98: prevent zombies from exiting levels
|
|
*/
|
|
if (!bossaction && thing && thing->player && thing->player->health <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (thing && CheckIfExitIsGood(thing))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
G_SecretExitLevel(0, 1, resetinv);
|
|
}
|
|
break;
|
|
|
|
case 55:
|
|
// Raise Floor Crush
|
|
if (EV_DoFloor(DFloor::floorRaiseAndCrush, line, line->id, SPEED(floors::SLOW), 0, true,
|
|
0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 101:
|
|
// Raise Floor
|
|
if (EV_DoFloor (DFloor::floorRaiseToLowestCeiling, line, line->id, SPEED(floors::SLOW), 0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 102:
|
|
// Lower Floor to Surrounding floor height
|
|
if (EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::SLOW),
|
|
(128 - 128) * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 103:
|
|
// Open Door
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 111:
|
|
// Blazing Door Raise (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::FAST),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 112:
|
|
// Blazing Door Open (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 113:
|
|
// Blazing Door Close (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 122:
|
|
// Blazing PlatDownWaitUpStay
|
|
if (EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::TURBO),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 127:
|
|
// Build Stairs Turbo 16
|
|
if (EV_BuildStairs(line->id, DFloor::buildUp, line, 16 * FRACUNIT, SPEED(stairs::TURBO),
|
|
TICS(0), 0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 131:
|
|
// Raise Floor Turbo
|
|
if (EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::FAST), 0, 0,
|
|
0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 133:
|
|
// BlzOpenDoor BLUE
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id,
|
|
SPEED(doors::FAST), TICS(0), (card_t)(BCard | CardIsSkull)))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 135:
|
|
// BlzOpenDoor RED
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), TICS(0),
|
|
(card_t)(RCard | CardIsSkull)))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 137:
|
|
// BlzOpenDoor YELLOW
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), TICS(0),
|
|
(card_t)(YCard | CardIsSkull)))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 140:
|
|
// Raise Floor 512
|
|
if (EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 64 * 8, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
// killough 1/31/98: factored out compatibility check;
|
|
// added inner switch, relaxed check to demo_compatibility
|
|
|
|
default:
|
|
switch (line->special)
|
|
{
|
|
// jff 1/29/98 added linedef types to fill all functions out so that
|
|
// all possess SR, S1, WR, W1 types
|
|
|
|
case 158:
|
|
// Raise Floor to shortest lower texture
|
|
// 158 S1 EV_DoFloor(raiseToTexture), CSW(0)
|
|
if (EV_DoFloor(DFloor::floorRaiseByTexture, line, line->id, SPEED(floors::SLOW), 0,
|
|
false, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 159:
|
|
// Raise Floor to shortest lower texture
|
|
// 159 S1 EV_DoFloor(lowerAndChange)
|
|
if (EV_DoFloor(DFloor::floorLowerAndChange, line, line->id, SPEED(floors::SLOW),
|
|
0 * FRACUNIT, false, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 160:
|
|
// Raise Floor 24 and change
|
|
// 160 S1 EV_DoFloor(raiseFloor24AndChange)
|
|
if (EV_DoFloor(DFloor::floorRaiseAndChange, line, line->id, SPEED(floors::SLOW),
|
|
24 * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 161:
|
|
// Raise Floor 24
|
|
// 161 S1 EV_DoFloor(raiseFloor24)
|
|
if (EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 24, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 162:
|
|
// Moving floor min n to max n
|
|
// 162 S1 EV_DoPlat(perpetualRaise,0)
|
|
if (EV_DoPlat(line->id, line, DPlat::platPerpetualRaise, 0, SPEED(floors::SLOW),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 163:
|
|
// Stop Moving floor
|
|
// 163 S1 EV_DoPlat(perpetualRaise,0)
|
|
EV_StopPlat(line->id);
|
|
reuse = false;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 164:
|
|
// Start fast crusher
|
|
// 164 S1 EV_DoCeiling(fastCrushAndRaise)
|
|
if (EV_DoCeiling(DCeiling::fastCrushAndRaise, line, line->id, SPEED(ceilings::NORMAL),
|
|
SPEED(ceilings::NORMAL), 0, true, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 165:
|
|
// Start slow silent crusher
|
|
// 165 S1 EV_DoCeiling(silentCrushAndRaise)
|
|
if (EV_DoCeiling(DCeiling::silentCrushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 1, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 166:
|
|
// Raise ceiling, Lower floor
|
|
// 166 S1 EV_DoCeiling(raiseToHighest), EV_DoFloor(lowerFloortoLowest)
|
|
if (EV_DoCeiling(DCeiling::ceilRaiseToHighest, line, line->id, SPEED(ceilings::SLOW),
|
|
0, 0, 0, 0, 0) ||
|
|
EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0,
|
|
0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 167:
|
|
// Lower ceiling and Crush
|
|
// 167 S1 EV_DoCeiling(lowerAndCrush)
|
|
if (EV_DoCeiling(DCeiling::lowerAndCrush, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW) / 2, 0, true, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 168:
|
|
// Stop crusher
|
|
// 168 S1 EV_CeilingCrushStop()
|
|
if (EV_CeilingCrushStop(line->id))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 169:
|
|
// Lights to brightest neighbor sector
|
|
// 169 S1 EV_LightTurnOn(0)
|
|
EV_LightTurnOn(line->id, -1);
|
|
reuse = false;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 170:
|
|
// Lights to near dark
|
|
// 170 S1 EV_LightTurnOn(35)
|
|
EV_LightTurnOn(line->id, 35);
|
|
reuse = false;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 171:
|
|
// Lights on full
|
|
// 171 S1 EV_LightTurnOn(255)
|
|
EV_LightTurnOn(line->id, 255);
|
|
reuse = false;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 172:
|
|
// Start Lights Strobing
|
|
// 172 S1 EV_StartLightStrobing()
|
|
EV_StartLightStrobing(line->id, TICS(5), TICS(35));
|
|
reuse = false;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 173:
|
|
// Lights to Dimmest Near
|
|
// 173 S1 EV_TurnTagLightsOff()
|
|
EV_TurnTagLightsOff(line->id);
|
|
reuse = false;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 174:
|
|
// Teleport
|
|
// 174 S1 Teleport(side,thing)
|
|
if (EV_LineTeleport(line, side, thing))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 175:
|
|
// Close Door, Open in 30 secs
|
|
// 175 S1 EV_DoDoor(close30ThenOpen)
|
|
if (EV_DoDoor(DDoor::doorCloseWaitOpen, line, thing, line->id, SPEED(floors::SLOW),
|
|
OCTICS(240), NoKey))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 189: // jff 3/15/98 create texture change no motion type
|
|
// Texture Change Only (Trigger)
|
|
// 189 S1 Change Texture/Type Only
|
|
if (EV_DoChange(line, trigChangeOnly, line->id))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 203:
|
|
// Lower ceiling to lowest surrounding ceiling
|
|
// 203 S1 EV_DoCeiling(lowerToLowest)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToLowest, line, line->id, SPEED(ceilings::SLOW),
|
|
0, 0, 0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 204:
|
|
// Lower ceiling to highest surrounding floor
|
|
// 204 S1 EV_DoCeiling(lowerToMaxFloor)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToHighestFloor, line, line->id,
|
|
SPEED(ceilings::SLOW), 0, 0, 0, 0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 209:
|
|
// killough 1/31/98: silent teleporter
|
|
// jff 209 S1 SilentTeleport
|
|
if (EV_SilentTeleport(line->args[0], 0, line->args[2], 0, line, side, thing))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 241: // jff 3/15/98 create texture change no motion type
|
|
// Texture Change Only (Numeric)
|
|
// 241 S1 Change Texture/Type Only
|
|
if (EV_DoChange(line, numChangeOnly, line->id))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 221:
|
|
// Lower floor to next lowest floor
|
|
// 221 S1 Lower Floor To Nearest Floor
|
|
if (EV_DoFloor(DFloor::floorLowerToNearest, line, line->id, SPEED(floors::SLOW), 0,
|
|
0, 0))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 229:
|
|
// Raise elevator next floor
|
|
// 229 S1 Raise Elevator next floor
|
|
if (EV_DoElevator(line, DElevator::elevateUp, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 233:
|
|
// Lower elevator next floor
|
|
// 233 S1 Lower Elevator next floor
|
|
if (EV_DoElevator(line, DElevator::elevateDown, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 237:
|
|
// Elevator to current floor
|
|
// 237 S1 Elevator to current floor
|
|
if (EV_DoElevator(line, DElevator::elevateCurrent, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
reuse = false;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
// jff 1/29/98 end of added S1 linedef types
|
|
|
|
// jff 1/29/98 added linedef types to fill all functions out so that
|
|
// all possess SR, S1, WR, W1 types
|
|
|
|
case 78: // jff 3/15/98 create texture change no motion type
|
|
// Texture Change Only (Numeric)
|
|
// 78 SR Change Texture/Type Only
|
|
if (EV_DoChange(line, numChangeOnly, line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 176:
|
|
// Raise Floor to shortest lower texture
|
|
// 176 SR EV_DoFloor(raiseToTexture), CSW(1)
|
|
if (EV_DoChange(line, numChangeOnly, line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 177:
|
|
// Raise Floor to shortest lower texture
|
|
// 177 SR EV_DoFloor(lowerAndChange)
|
|
if (EV_DoFloor(DFloor::floorLowerAndChange, line, line->id, SPEED(floors::SLOW),
|
|
0 * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 178:
|
|
// Raise Floor 512
|
|
// 178 SR EV_DoFloor(raiseFloor512)
|
|
if (EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 64 * 8, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 179:
|
|
// Raise Floor 24 and change
|
|
// 179 SR EV_DoFloor(raiseFloor24AndChange)
|
|
if (EV_DoFloor(DFloor::floorRaiseAndChange, line, line->id, SPEED(floors::SLOW),
|
|
24 * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
// Raise Floor 24
|
|
// 180 SR EV_DoFloor(raiseFloor24)
|
|
if (EV_DoFloor(DFloor::floorRaiseByValue, line, line->id, SPEED(floors::SLOW),
|
|
FRACUNIT * 24, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 181:
|
|
// Moving floor min n to max n
|
|
// 181 SR EV_DoPlat(perpetualRaise,0)
|
|
|
|
EV_DoPlat(line->id, line, DPlat::platPerpetualRaise, 0, SPEED(floors::SLOW),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0);
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 182:
|
|
// Stop Moving floor
|
|
// 182 SR EV_DoPlat(perpetualRaise,0)
|
|
EV_StopPlat(line->id);
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 183:
|
|
// Start fast crusher
|
|
// 183 SR EV_DoCeiling(fastCrushAndRaise)
|
|
if (EV_DoCeiling(DCeiling::fastCrushAndRaise, line, line->id, SPEED(ceilings::NORMAL),
|
|
SPEED(ceilings::NORMAL), 0, true, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 184:
|
|
// Start slow crusher
|
|
// 184 SR EV_DoCeiling(crushAndRaise)
|
|
if (EV_DoCeiling(DCeiling::crushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 185:
|
|
// Start slow silent crusher
|
|
// 185 SR EV_DoCeiling(silentCrushAndRaise)
|
|
if (EV_DoCeiling(DCeiling::silentCrushAndRaise, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW), 0, true, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 186:
|
|
// Raise ceiling, Lower floor
|
|
// 186 SR EV_DoCeiling(raiseToHighest), EV_DoFloor(lowerFloortoLowest)
|
|
if (EV_DoCeiling(DCeiling::ceilRaiseToHighest, line, line->id, SPEED(ceilings::SLOW),
|
|
0, 0, 0, 0, 0) ||
|
|
EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0,
|
|
0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 187:
|
|
// Lower ceiling and Crush
|
|
// 187 SR EV_DoCeiling(lowerAndCrush)
|
|
if (EV_DoCeiling(DCeiling::lowerAndCrush, line, line->id, SPEED(ceilings::SLOW),
|
|
SPEED(ceilings::SLOW) / 2, 0, true, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 188:
|
|
// Stop crusher
|
|
// 188 SR EV_CeilingCrushStop()
|
|
if (EV_CeilingCrushStop(line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 190: // jff 3/15/98 create texture change no motion type
|
|
// Texture Change Only (Trigger)
|
|
// 190 SR Change Texture/Type Only
|
|
if (EV_DoChange(line, trigChangeOnly, line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 191:
|
|
// Lower Pillar, Raise Donut
|
|
// 191 SR EV_DoDonut()
|
|
if (EV_DoDonut(line))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 192:
|
|
// Lights to brightest neighbor sector
|
|
// 192 SR EV_LightTurnOn(0)
|
|
EV_LightTurnOn(line->id, -1);
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 193:
|
|
// Start Lights Strobing
|
|
// 193 SR EV_StartLightStrobing()
|
|
EV_StartLightStrobing(line->id, TICS(5), TICS(35));
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 194:
|
|
// Lights to Dimmest Near
|
|
// 194 SR EV_TurnTagLightsOff()
|
|
EV_TurnTagLightsOff(line->id);
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 195:
|
|
// Teleport
|
|
// 195 SR Teleport(side,thing)
|
|
if (EV_LineTeleport(line, side, thing))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 196:
|
|
// Close Door, Open in 30 secs
|
|
// 196 SR EV_DoDoor(close30ThenOpen)
|
|
if (EV_DoDoor(DDoor::doorCloseWaitOpen, line, thing, line->id, SPEED(doors::SLOW),
|
|
OCTICS(240), NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 205:
|
|
// Lower ceiling to lowest surrounding ceiling
|
|
// 205 SR EV_DoCeiling(lowerToLowest)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToLowest, line, line->id, SPEED(ceilings::SLOW),
|
|
0, 0, 0, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 206:
|
|
// Lower ceiling to highest surrounding floor
|
|
// 206 SR EV_DoCeiling(lowerToMaxFloor)
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToHighestFloor, line, line->id,
|
|
SPEED(ceilings::SLOW), 0, 0, 0, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 210:
|
|
// killough 1/31/98: silent teleporter
|
|
// jff 210 SR SilentTeleport
|
|
if (EV_SilentTeleport(line->args[0], 0, line->args[2], 0, line, side, thing))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 211: // jff 3/14/98 create instant toggle floor type
|
|
// Toggle Floor Between C and F Instantly
|
|
// 211 SR Toggle Floor Instant
|
|
if (EV_DoPlat(line->id, line, DPlat::platToggle, 0, 0, 0, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 222:
|
|
// Lower floor to next lowest floor
|
|
// 222 SR Lower Floor To Nearest Floor
|
|
if (EV_DoFloor(DFloor::floorLowerToNearest, line, line->id, SPEED(floors::SLOW), 0,
|
|
0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 230:
|
|
// Raise elevator next floor
|
|
// 230 SR Raise Elevator next floor
|
|
if (EV_DoElevator(line, DElevator::elevateUp, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 234:
|
|
// Lower elevator next floor
|
|
// 234 SR Lower Elevator next floor
|
|
if (EV_DoElevator(line, DElevator::elevateDown, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 238:
|
|
// Elevator to current floor
|
|
// 238 SR Elevator to current floor
|
|
if (EV_DoElevator(line, DElevator::elevateCurrent, SPEED(ELEVATORSPEED), 0,
|
|
line->id))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 258:
|
|
// Build stairs, step 8
|
|
// 258 SR EV_BuildStairs(build8)
|
|
if (EV_BuildStairs(line->id, DFloor::buildUp, line, 8 * FRACUNIT,
|
|
SPEED(stairs::SLOW), 0, 0, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 259:
|
|
// Build stairs, step 16
|
|
// 259 SR EV_BuildStairs(turbo16)
|
|
if (EV_BuildStairs(line->id, DFloor::buildUp, line, 16 * FRACUNIT,
|
|
SPEED(stairs::TURBO), 0, 0, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
// 1/29/98 jff end of added SR linedef types
|
|
}
|
|
break;
|
|
|
|
// Buttons (retriggerable switches)
|
|
case 42:
|
|
// Close Door
|
|
if (EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 43:
|
|
// Lower Ceiling to Floor
|
|
if (EV_DoCeiling(DCeiling::ceilLowerToFloor, line, line->id, SPEED(ceilings::SLOW), 0, 0,
|
|
false, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 45:
|
|
// Lower Floor to Surrounding floor height
|
|
if (EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::SLOW),
|
|
(128 - 128) * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 60:
|
|
// Lower Floor to Lowest
|
|
if (EV_DoFloor(DFloor::floorLowerToLowest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 61:
|
|
// Open Door
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 62:
|
|
// PlatDownWaitUpStay
|
|
if (EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::FAST),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 63:
|
|
// Raise Door
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::SLOW),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 64:
|
|
// Raise Floor to ceiling
|
|
if (EV_DoFloor(DFloor::floorRaiseToLowestCeiling, line, line->id, SPEED(floors::SLOW),
|
|
0, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 66:
|
|
// Raise Floor 24 and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 3 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 67:
|
|
// Raise Floor 32 and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platUpByValueStay, FRACUNIT * 4 * 8,
|
|
SPEED(plats::SLOW / 2), 0, 0, 2))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 65:
|
|
// Raise Floor Crush
|
|
if (EV_DoFloor(DFloor::floorRaiseAndCrush, line, line->id, SPEED(floors::SLOW), 0, true,
|
|
0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 68:
|
|
// Raise Plat to next highest floor and change texture
|
|
if (EV_DoPlat(line->id, line, DPlat::platRaiseAndStay, 0, SPEED(plats::SLOW / 2), 0, 0,
|
|
1))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 69:
|
|
// Raise Floor to next highest floor
|
|
if (EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::SLOW), 0, 0,
|
|
0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 70:
|
|
// Turbo Lower Floor
|
|
if (EV_DoFloor(DFloor::floorLowerToHighest, line, line->id, SPEED(floors::FAST),
|
|
(136 - 128) * FRACUNIT, 0, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 114:
|
|
// Blazing Door Raise (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorRaise, line, thing, line->id, SPEED(doors::FAST),
|
|
TICS(doors::WAIT), NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 115:
|
|
// Blazing Door Open (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 116:
|
|
// Blazing Door Close (faster than TURBO!)
|
|
if (EV_DoDoor(DDoor::doorClose, line, thing, line->id, SPEED(doors::FAST), 0, NoKey))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 123:
|
|
// Blazing PlatDownWaitUpStay
|
|
if (EV_DoPlat(line->id, line, DPlat::platDownWaitUpStay, 0, SPEED(plats::TURBO),
|
|
TICS(plats::WAIT), 0 * FRACUNIT, 0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 132:
|
|
// Raise Floor Turbo
|
|
if (EV_DoFloor(DFloor::floorRaiseToNearest, line, line->id, SPEED(floors::FAST), 0, 0,
|
|
0))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 99:
|
|
// BlzOpenDoor BLUE
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), TICS(0),
|
|
(card_t)(BCard | CardIsSkull)))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 134:
|
|
// BlzOpenDoor RED
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), TICS(0),
|
|
(card_t)(RCard | CardIsSkull)))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
case 136:
|
|
// BlzOpenDoor YELLOW
|
|
if (EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::FAST), TICS(0),
|
|
(card_t)(YCard | CardIsSkull)))
|
|
{
|
|
reuse = true;
|
|
trigger = true;
|
|
}
|
|
break;
|
|
|
|
case 138:
|
|
// Light Turn On
|
|
EV_LightTurnOn(line->id, 255);
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
|
|
case 139:
|
|
// Light Turn Off
|
|
EV_LightTurnOn(line->id, 35);
|
|
reuse = true;
|
|
trigger = true;
|
|
|
|
break;
|
|
}
|
|
|
|
if (trigger && !bossaction)
|
|
{
|
|
if (serverside)
|
|
{
|
|
P_ChangeSwitchTexture(line, reuse, true);
|
|
OnChangedSwitchTexture(line, reuse);
|
|
}
|
|
}
|
|
|
|
if (!trigger && bossaction)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//
|
|
// P_ShootSpecialLine - Gun trigger special dispatcher
|
|
//
|
|
// Called when a thing shoots a special line with bullet, shell, saw, or fist.
|
|
//
|
|
// jff 02/12/98 all G1 lines were fixed to check the result from the EV_
|
|
// function before clearing the special. This avoids losing the function
|
|
// of the line, should the sector already be in motion when the line is
|
|
// impacted. Change is qualified by demo_compatibility.
|
|
//
|
|
|
|
bool P_ShootCompatibleSpecialLine(AActor* thing, line_t* line)
|
|
{
|
|
bool resetinv = false;
|
|
|
|
// pointer to line function is NULL by default, set non-null if
|
|
// line special is gun triggered generalized linedef type
|
|
bool (*linefunc)(line_t& line) = nullptr;
|
|
|
|
// check each range of generalized linedefs
|
|
if ((unsigned)line->special >= GenEnd)
|
|
{
|
|
// Out of range for GenFloors
|
|
}
|
|
else if ((unsigned)line->special >= GenFloorBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
if ((line->special & FloorChange) || !(line->special & FloorModel))
|
|
return false; // FloorModel is "Allow Monsters" if FloorChange is 0
|
|
if (!line->id) //jff 2/27/98 all gun generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenFloor;
|
|
}
|
|
else if ((unsigned)line->special >= GenCeilingBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
if ((line->special & CeilingChange) || !(line->special & CeilingModel))
|
|
return false; // CeilingModel is "Allow Monsters" if CeilingChange is 0
|
|
if (!line->id) //jff 2/27/98 all gun generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenCeiling;
|
|
}
|
|
else if ((unsigned)line->special >= GenDoorBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
{
|
|
if (!(line->special & DoorMonster))
|
|
return false; // monsters disallowed from this door
|
|
if (line->flags & ML_SECRET) // they can't open secret doors either
|
|
return false;
|
|
}
|
|
if (!line->id) //jff 2/27/98 all gun generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenDoor;
|
|
}
|
|
else if ((unsigned)line->special >= GenLockedBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
return false; // monsters disallowed from unlocking doors
|
|
if (((line->special & TriggerType) == GunOnce) ||
|
|
((line->special & TriggerType) == GunMany))
|
|
{ // jff 4/1/98 check for being a gun type before reporting door type
|
|
if (!P_CanUnlockGenDoor(line, thing->player))
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
if (!line->id) //jff 2/27/98 all gun generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenLockedDoor;
|
|
}
|
|
else if ((unsigned)line->special >= GenLiftBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
if (!(line->special & LiftMonster))
|
|
return false; // monsters disallowed
|
|
linefunc = EV_DoGenLift;
|
|
}
|
|
else if ((unsigned)line->special >= GenStairsBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
if (!(line->special & StairMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id) //jff 2/27/98 all gun generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenStairs;
|
|
}
|
|
else if ((unsigned)line->special >= GenCrusherBase)
|
|
{
|
|
if (!P_IsPlayerOrAvatar(*thing))
|
|
if (!(line->special & StairMonster))
|
|
return false; // monsters disallowed
|
|
if (!line->id) //jff 2/27/98 all gun generalized types require tag
|
|
return false;
|
|
linefunc = EV_DoGenCrusher;
|
|
}
|
|
|
|
if (linefunc)
|
|
switch ((line->special & TriggerType) >> TriggerTypeShift)
|
|
{
|
|
case GunOnce:
|
|
if (linefunc(*line))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
case GunMany:
|
|
if (linefunc(*line))
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
default: // if not a gun type, do nothing here
|
|
return false;
|
|
}
|
|
|
|
// Impacts that other things can activate.
|
|
if (thing && !P_IsPlayerOrAvatar(*thing))
|
|
{
|
|
int ok = 0;
|
|
switch (line->special)
|
|
{
|
|
case 46:
|
|
// 46 GR Open door on impact weapon is monster activatable
|
|
ok = 1;
|
|
break;
|
|
}
|
|
if (!ok)
|
|
return false;
|
|
}
|
|
|
|
if (!P_CheckTag(line)) // jff 2/27/98 disallow zero tag on some types
|
|
return false;
|
|
|
|
switch (line->special)
|
|
{
|
|
case 24:
|
|
// 24 G1 raise floor to highest adjacent
|
|
if (EV_DoFloor(DFloor::floorRaiseToLowestCeiling, line, line->id, SPEED(floors::SLOW),
|
|
0, 0, 0) ||
|
|
demoplayback)
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 46:
|
|
// 46 GR open door, stay open
|
|
EV_DoDoor(DDoor::doorOpen, line, thing, line->id, SPEED(doors::SLOW), 0, NoKey);
|
|
return true;
|
|
|
|
case 47:
|
|
// 47 G1 raise floor to nearest and change texture and type
|
|
if (EV_DoPlat(line->id, line, DPlat::platRaiseAndStay, 0, SPEED(doors::SLOW), 0, 0,
|
|
1) ||
|
|
demoplayback)
|
|
{
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
// jff 1/30/98 added new gun linedefs here
|
|
// killough 1/31/98: added demo_compatibility check, added inner switch
|
|
|
|
default:
|
|
switch (line->special)
|
|
{
|
|
case 2071:
|
|
resetinv = true;
|
|
[[fallthrough]];
|
|
case 197:
|
|
// Exit to next level
|
|
// killough 10/98: prevent zombies from exiting levels
|
|
if (thing && thing->player && thing->player->health <= 0)
|
|
break;
|
|
if (thing && CheckIfExitIsGood(thing))
|
|
{
|
|
G_ExitLevel(0, 1, resetinv);
|
|
return true;
|
|
}
|
|
break;
|
|
|
|
case 2074:
|
|
resetinv = true;
|
|
[[fallthrough]];
|
|
case 198:
|
|
// Exit to secret level
|
|
// killough 10/98: prevent zombies from exiting levels
|
|
if (thing && thing->player && thing->player->health <= 0)
|
|
break;
|
|
if (thing && CheckIfExitIsGood(thing))
|
|
{
|
|
G_SecretExitLevel(0, 1, resetinv);
|
|
return true;
|
|
}
|
|
break;
|
|
// jff end addition of new gun linedefs
|
|
}
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uint32_t P_TranslateCompatibleLineFlags(const uint32_t flags, const bool reserved)
|
|
{
|
|
// no comp_reservedlineflag, it's only needed for playback of
|
|
// a small set of early mbf21 demos from before its introduction
|
|
|
|
uint32_t filter;
|
|
|
|
if (demoplayback || flags & ML_RESERVED || reserved)
|
|
filter = 0x01ff;
|
|
else
|
|
filter = 0x3fff;
|
|
|
|
return (flags & filter);
|
|
}
|
|
|
|
void P_PostProcessCompatibleLinedefSpecial(line_t* line)
|
|
{
|
|
switch (line->special)
|
|
{ // killough 4/11/98: handle special types
|
|
case 260: // killough 4/11/98: translucent 2s textures
|
|
#if 0
|
|
lump = sides[*ld->sidenum].special; // translucency from sidedef
|
|
if (!ld->tag) // if tag==0,
|
|
ld->tranlump = lump; // affect this linedef only
|
|
else
|
|
for (line_t& lineit : R_GetLines()) // if tag!=0,
|
|
if (lineit.tag == ld->tag) // affect all matching linedefs
|
|
lineit.tranlump = lump;
|
|
#else
|
|
// [RH] Second arg controls how opaque it is.
|
|
if (line->id == 0)
|
|
line->lucency = (byte)128;
|
|
else
|
|
for (line_t& lineit : R_GetLines())
|
|
if (lineit.id == line->id)
|
|
lineit.lucency = (byte)128;
|
|
#endif
|
|
line->special = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool P_IsMBFCompatMode()
|
|
{
|
|
return P_AllowDropOff() || co_pursuit || co_helpfriends || co_monsterbacking ||
|
|
co_avoidhazards || co_monstersclimbsteep || co_mbfphys;
|
|
}
|