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

@ -371,6 +371,12 @@ Note: All <bool> fields default to false unless mentioned otherwise.
skyceiling2 = <string> // defines secondary upper sky for this sector. skyceiling2 = <string> // defines secondary upper sky for this sector.
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

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;
}
}
}
}