added DSDA's thrust properties for UDMF

This commit is contained in:
Christoph Oelckers 2023-10-29 23:18:06 +01:00
parent bdee1f3d34
commit ad778b0bcc
5 changed files with 208 additions and 1 deletions

View file

@ -372,6 +372,12 @@ Note: All <bool> fields default to false unless mentioned otherwise.
colormap = <string>; // only provided for backwards compatibility. Do not use in GZDoom projects. colormap = <string>; // only provided for backwards compatibility. Do not use in GZDoom projects.
xthrust = <float>; // applies thrust to actors - x-magnitude
ythrust = <float>; // applies thrust to actors - y-magnitude
thrustgroup = <int>; // specifies which actors get thrusted. Bitfield with (1 = static objects, 2 = player, 4 = monsters, 8 = projectiles, 16 = actors with +WINDTHRUST)
thrustlocation = <int>; // specifies where in the sector actors get thrusted: (1 = on the ground, 2 = in the air, 4 = on the ceiling)
* Note about dropactors * Note about dropactors
The spec requires this to be false by default. Currently, however, ZDoom assumes this to be true The spec requires this to be false by default. Currently, however, ZDoom assumes this to be true

View file

@ -872,6 +872,7 @@ set (PCH_SOURCES
playsim/mapthinkers/a_pillar.cpp playsim/mapthinkers/a_pillar.cpp
playsim/mapthinkers/a_plats.cpp playsim/mapthinkers/a_plats.cpp
playsim/mapthinkers/a_pusher.cpp playsim/mapthinkers/a_pusher.cpp
playsim/mapthinkers/a_thruster.cpp
playsim/mapthinkers/a_scroll.cpp playsim/mapthinkers/a_scroll.cpp
playsim/mapthinkers/dsectoreffect.cpp playsim/mapthinkers/dsectoreffect.cpp
playsim/a_pickups.cpp playsim/a_pickups.cpp

View file

@ -53,6 +53,7 @@
#include "maploader.h" #include "maploader.h"
#include "texturemanager.h" #include "texturemanager.h"
#include "a_scroll.h" #include "a_scroll.h"
#include "p_spec_thinkers.h"
//=========================================================================== //===========================================================================
// //
@ -450,6 +451,7 @@ class UDMFParser : public UDMFParserBase
TArray<vertex_t> ParsedVertices; TArray<vertex_t> ParsedVertices;
TArray<UDMFScroll> UDMFSectorScrollers; TArray<UDMFScroll> UDMFSectorScrollers;
TArray<UDMFScroll> UDMFWallScrollers; TArray<UDMFScroll> UDMFWallScrollers;
TArray<UDMFScroll> UDMFThrusters;
FDynamicColormap *fogMap = nullptr, *normMap = nullptr; FDynamicColormap *fogMap = nullptr, *normMap = nullptr;
FMissingTextureTracker &missingTex; FMissingTextureTracker &missingTex;
@ -1639,6 +1641,10 @@ public:
double friction = -FLT_MAX, movefactor = -FLT_MAX; double friction = -FLT_MAX, movefactor = -FLT_MAX;
DVector2 thrust = { 0,0 };
int thrustgroup = 0;
int thrustlocation = 0;
const double scrollfactor = 1 / 3.2; // I hope this is correct, it's just a guess taken from Eternity's code. const double scrollfactor = 1 / 3.2; // I hope this is correct, it's just a guess taken from Eternity's code.
memset(sec, 0, sizeof(*sec)); memset(sec, 0, sizeof(*sec));
@ -2140,6 +2146,22 @@ public:
sec->planes[sector_t::ceiling].skytexture[1] = TexMan.CheckForTexture(CheckString(key), ETextureType::Wall, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst); sec->planes[sector_t::ceiling].skytexture[1] = TexMan.CheckForTexture(CheckString(key), ETextureType::Wall, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst);
break; break;
case NAME_xthrust:
thrust.X = CheckFloat(key);
break;
case NAME_ythrust:
thrust.Y = CheckFloat(key);
break;
case NAME_thrustgroup:
thrustgroup = CheckInt(key);
break;
case NAME_thrustlocation:
thrustlocation = CheckInt(key);
break;
// These two are used by Eternity for something I do not understand. // These two are used by Eternity for something I do not understand.
//case NAME_portal_ceil_useglobaltex: //case NAME_portal_ceil_useglobaltex:
//case NAME_portal_floor_useglobaltex: //case NAME_portal_floor_useglobaltex:
@ -2205,7 +2227,7 @@ public:
sec->Flags &= ~SECF_DAMAGEFLAGS; sec->Flags &= ~SECF_DAMAGEFLAGS;
} }
// Cannot be initialized yet because they need the final sector array. // These cannot be initialized yet because they need the final sector array.
if (scroll_ceil_type != NAME_None) if (scroll_ceil_type != NAME_None)
{ {
UDMFSectorScrollers.Push({ true, index, scroll_ceil_x, scroll_ceil_y, scroll_ceil_type }); UDMFSectorScrollers.Push({ true, index, scroll_ceil_x, scroll_ceil_y, scroll_ceil_type });
@ -2214,6 +2236,10 @@ public:
{ {
UDMFSectorScrollers.Push({ false, index, scroll_floor_x, scroll_floor_y, scroll_floor_type }); UDMFSectorScrollers.Push({ false, index, scroll_floor_x, scroll_floor_y, scroll_floor_type });
} }
if (!thrust.isZero())
{
UDMFThrusters.Push({ thrustlocation, index, thrust.X, thrust.Y, thrustgroup });
}
// Reset the planes to their defaults if not all of the plane equation's parameters were found. // Reset the planes to their defaults if not all of the plane equation's parameters were found.
@ -2613,6 +2639,10 @@ public:
loader->CreateScroller(EScroll::sc_side, scroll.x, scroll.y, nullptr, &Level->sides[sd], 0); loader->CreateScroller(EScroll::sc_side, scroll.x, scroll.y, nullptr, &Level->sides[sd], 0);
} }
} }
for (auto& scroll : UDMFThrusters)
{
Level->CreateThinker<DThruster>(&Level->sectors[scroll.index], scroll.x, scroll.y, scroll.scrolltype, scroll.where);
}
} }
}; };

View file

@ -44,3 +44,18 @@ protected:
friend bool PIT_PushThing (AActor *thing); friend bool PIT_PushThing (AActor *thing);
}; };
class DThruster : public DThinker
{
DECLARE_CLASS(DThruster, DThinker)
DVector2 m_PushVec;
sector_t* m_Sector;
int m_Type;
int m_Location;
public:
void Construct(sector_t* sec, double dx, double dy, int type, int location);
void Serialize(FSerializer& arc);
void Tick();
};

View file

@ -0,0 +1,155 @@
//-----------------------------------------------------------------------------
//
// Copyright 2023 Ryan Krafnick
// Copyright 2023 Christoph Oelckers
//
// 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:
// UDMF-style thruster
//
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include "actor.h"
#include "p_spec.h"
#include "serializer.h"
#include "serializer_doom.h"
#include "p_spec_thinkers.h"
EXTERN_CVAR(Bool, var_pushers);
IMPLEMENT_CLASS(DThruster, false, false)
enum
{
THRUST_STATIC = 0x01,
THRUST_PLAYER = 0x02,
THRUST_MONSTER = 0x04,
THRUST_PROJECTILE = 0x08,
THRUST_WINDTHRUST = 0x10,
THRUST_GROUNDED = 1,
THRUST_AIRBORNE = 2,
THRUST_CEILING = 4
};
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void DThruster::Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc("type", m_Type)
("location", m_Location)
("pushvec", m_PushVec)
("sector", m_Sector);
}
//-----------------------------------------------------------------------------
//
// Add a thrust thinker to the thinker list
//
//-----------------------------------------------------------------------------
void DThruster::Construct(sector_t* sec, double dx, double dy, int type, int location)
{
m_Type = type;
m_Location = location;
m_Sector = sec;
m_PushVec = { dx, dy };
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
void DThruster::Tick ()
{
sector_t* sec = m_Sector;
if (m_PushVec.isZero())
return;
for (auto node = sec->touching_thinglist; node; node = node->m_snext)
{
bool thrust_it = false;
AActor* thing = node->m_thing;
if (thing->flags & MF_NOCLIP)
continue;
if (!(thing->flags & MF_NOGRAVITY) && thing->Z() <= thing->floorz)
{
if (m_Location & THRUST_GROUNDED)
thrust_it = true;
}
else if (
thing->flags & MF_SPAWNCEILING &&
thing->flags & MF_NOGRAVITY &&
thing->Top() == thing->ceilingz
)
{
if (m_Location & THRUST_CEILING)
thrust_it = true;
}
else if (thing->flags & MF_NOGRAVITY || thing->Z() > thing->floorz)
{
if (m_Location & THRUST_AIRBORNE)
thrust_it = true;
}
if (thrust_it)
{
thrust_it = false;
if (thing->flags2 & MF2_WINDTHRUST && m_Type & THRUST_WINDTHRUST)
thrust_it = true;
else if (thing->flags3 & MF3_ISMONSTER)
{
if (m_Type & THRUST_MONSTER)
thrust_it = true;
}
else if (thing->player)
{
if (m_Type & THRUST_PLAYER)
thrust_it = true;
}
else if (thing->flags & MF_MISSILE)
{
if (m_Type & THRUST_PROJECTILE)
thrust_it = true;
}
else
{
if (m_Type & THRUST_STATIC)
thrust_it = true;
}
if (thrust_it)
{
thing->Vel += m_PushVec;
}
}
}
}