og-odamex/common/dsectoreffect.cpp
2026-01-05 01:52:47 +00:00

317 lines
7 KiB
C++

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id$
//
// Copyright (C) 1998-2006 by Randy Heit (ZDoom).
// 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:
// Separated Sector effects (?)
//
//-----------------------------------------------------------------------------
#include "odamex.h"
#include "p_local.h"
#include "dsectoreffect.h"
EXTERN_CVAR(co_boomphys) // [ML] Roll-up of various compat options
IMPLEMENT_SERIAL (DSectorEffect, DThinker)
DSectorEffect::DSectorEffect ()
{
m_Sector = NULL;
}
DSectorEffect::~DSectorEffect ()
{
}
void DSectorEffect::Destroy ()
{
if (m_Sector)
{
if (m_Sector->floordata == this)
m_Sector->floordata = NULL;
if (m_Sector->ceilingdata == this)
m_Sector->ceilingdata = NULL;
if (m_Sector->lightingdata == this)
m_Sector->lightingdata = NULL;
}
Super::Destroy();
}
DSectorEffect::DSectorEffect (sector_t *sector)
{
m_Sector = sector;
}
// Base Clone method, for cloning sector actions.
//
// This class must not be called directly. Subclass it if you need it.
//
// All subclasses should allocate a subclass with `new`, orphan it,
// then set the sector of the subclass to the passed sector.
DSectorEffect* DSectorEffect::Clone(sector_t *sector) const
{
throw CFatalError("DSectorEffect::Clone() called as a base class.");
}
void DSectorEffect::Serialize (FArchive &arc)
{
Super::Serialize (arc);
if (arc.IsStoring ())
arc << m_Sector;
else
arc >> m_Sector;
}
IMPLEMENT_SERIAL (DMover, DSectorEffect)
DMover::DMover ()
{
}
DMover::DMover (sector_t *sector)
: DSectorEffect (sector)
{
}
void DMover::Serialize (FArchive &arc)
{
Super::Serialize (arc);
}
IMPLEMENT_SERIAL (DMovingFloor, DMover)
DMovingFloor::DMovingFloor ()
{
}
DMovingFloor::DMovingFloor (sector_t *sector)
: DMover (sector)
{
sector->floordata = this;
}
void DMovingFloor::Serialize (FArchive &arc)
{
Super::Serialize (arc);
}
IMPLEMENT_SERIAL (DMovingCeiling, DMover)
DMovingCeiling::DMovingCeiling ()
{
}
DMovingCeiling::DMovingCeiling (sector_t *sector)
: DMover (sector)
{
sector->ceilingdata = this;
}
void DMovingCeiling::Serialize (FArchive &arc)
{
Super::Serialize (arc);
}
//
// Move a plane (floor or ceiling) and check for crushing
// [RH] Crush specifies the actual amount of crushing damage inflictable.
// (Use -1 to prevent it from trying to crush)
//
DMover::EResult DMover::MovePlane (fixed_t speed, fixed_t dest, int crush,
int floorOrCeiling, int direction, bool hexencrush)
{
bool flag;
fixed_t lastpos;
switch (floorOrCeiling)
{
case 0:
// FLOOR
switch (direction)
{
case -1:
// DOWN
lastpos = P_FloorHeight(m_Sector);
if (lastpos - speed < dest)
{
P_ChangeFloorHeight(m_Sector, dest - lastpos);
flag = P_ChangeSector (m_Sector, crush);
if (flag == true)
{
P_ChangeFloorHeight(m_Sector, lastpos - dest);
P_ChangeSector (m_Sector, crush);
//return crushed;
}
return pastdest;
}
else
{
P_ChangeFloorHeight(m_Sector, -speed);
flag = P_ChangeSector (m_Sector, crush);
// comp_floors: co_boomsectortouch enables Boom behaviour which
// allows floor to lower when actors on it are stuck in ceiling
// [ML] Now part of co_boomphys
if (flag == true && !co_boomphys)
{
P_ChangeFloorHeight(m_Sector, speed); // should be lastpos
P_ChangeSector (m_Sector, crush);
return crushed;
}
}
break;
case 1:
// UP
lastpos = P_FloorHeight(m_Sector);
// comp_floors: jff 02/04/98 keep floor from moving thru ceilings
// co_boomsectortouch enables Boom behaviour where a rising floor
// is prevented from moving higher than the ceiling above it
// [ML] Now part of co_boomphys
if (co_boomphys)
{
fixed_t h = P_CeilingHeight(m_Sector);
if (dest > h) // floor is trying to rise through ceiling
dest = h;
}
if (lastpos + speed > dest)
{
P_ChangeFloorHeight(m_Sector, dest - lastpos);
flag = P_ChangeSector (m_Sector, crush);
if (flag == true)
{
P_ChangeFloorHeight(m_Sector, lastpos - dest);
P_ChangeSector (m_Sector, crush);
}
return pastdest;
}
else
{
// COULD GET CRUSHED
P_ChangeFloorHeight(m_Sector, speed);
flag = P_ChangeSector (m_Sector, crush);
if (flag == true)
{
// comp_floors: jff 1/25/98 fix floor crusher
// co_boomsectortouch enables Boom behaviour where rising
// floor holds in place until victim moves or is crushed
// [ML] Now part of co_boomphys
if (!hexencrush && crush > NO_CRUSH && !co_boomphys)
return crushed;
P_ChangeFloorHeight(m_Sector, -speed);
P_ChangeSector (m_Sector, crush);
return crushed;
}
}
break;
}
break;
case 1:
// CEILING
switch(direction)
{
case -1:
// DOWN
lastpos = P_CeilingHeight(m_Sector);
// comp_floors: jff 02/04/98 keep ceiling from moving thru floors
// co_boomsectortouch enables Boom behaviour where a lowering
// ceiling is prevented from moving lower than the floor below it
// [ML] Now part of co_boomphys
if (co_boomphys)
{
fixed_t h = P_FloorHeight(m_Sector);
if (dest < h) // ceiling is trying to lower through floor
dest = h;
}
if (lastpos - speed < dest)
{
P_SetCeilingHeight(m_Sector, dest);
flag = P_ChangeSector (m_Sector, crush);
if (flag == true)
{
P_SetCeilingHeight(m_Sector, lastpos);
P_ChangeSector (m_Sector, crush);
}
return pastdest;
}
else
{
// COULD GET CRUSHED
P_SetCeilingHeight(m_Sector, lastpos - speed);
flag = P_ChangeSector (m_Sector, crush);
if (flag == true)
{
if (crush > NO_CRUSH)
return crushed;
P_SetCeilingHeight(m_Sector, lastpos);
P_ChangeSector (m_Sector, crush);
return crushed;
}
}
break;
case 1:
// UP
lastpos = P_CeilingHeight(m_Sector);
if (lastpos + speed > dest)
{
P_SetCeilingHeight(m_Sector, dest);
flag = P_ChangeSector (m_Sector, crush);
if (flag == true)
{
P_SetCeilingHeight(m_Sector, lastpos);
P_ChangeSector (m_Sector, crush);
}
return pastdest;
}
else
{
P_SetCeilingHeight(m_Sector, lastpos + speed);
flag = P_ChangeSector (m_Sector, crush);
// UNUSED
#if 0
if (flag == true)
{
P_ChangeCeilingHeight(m_Sector, -speed);
P_ChangeSector (m_Sector, crush);
return crushed;
}
#endif
}
break;
}
break;
}
return ok;
}
VERSION_CONTROL (dsectoreffect_cpp, "$Id$")