Add terrain pointer to mobj_t

This commit is contained in:
Sally Coolatta 2021-12-09 00:56:05 -05:00
parent a8615cac5b
commit 150faf9de6
11 changed files with 203 additions and 43 deletions

View file

@ -5176,6 +5176,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
return;
mo->standingslope = NULL;
mo->terrain = NULL;
mo->eflags |= MFE_SPRUNG;

View file

@ -14,9 +14,13 @@
#include "k_terrain.h"
#include "dehacked.h" // get_number
#include "doomdata.h"
#include "doomdef.h"
#include "doomtype.h"
#include "fastcmp.h"
#include "m_fixed.h"
#include "p_local.h"
#include "p_mobj.h"
#include "r_textures.h"
#include "w_wad.h"
#include "z_zone.h"
@ -120,10 +124,51 @@ terrain_t *K_GetTerrainForTextureName(const char *checkName)
return K_GetTerrainForTextureNum( R_CheckTextureNumForName(checkName) );
}
void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID)
{
levelflat_t *levelFlat = NULL;
if (mo == NULL || P_MobjWasRemoved(mo) == true)
{
// Invalid object.
return;
}
if (flatID < 0 || flatID >= (signed)numlevelflats)
{
// Clearly invalid floor...
mo->terrain = NULL;
return;
}
if (mo->flags & MF_NOCLIPHEIGHT)
{
// You can't collide with floors anyway!
mo->terrain = NULL;
return;
}
// Update the object's terrain pointer.
levelFlat = &levelflats[flatID];
mo->terrain = K_GetTerrainForTextureName(levelFlat->name);
}
//
// Parser code starts here.
//
static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val)
{
if (stricmp(val, "true") == 0)
{
*inputFlags |= newFlag;
}
else if (stricmp(val, "false") == 0)
{
*inputFlags &= ~newFlag;
}
}
static void K_TerrainDefaults(terrain_t *terrain)
{
terrain->splashID = UINT16_MAX;
@ -132,6 +177,8 @@ static void K_TerrainDefaults(terrain_t *terrain)
terrain->friction = FRACUNIT;
terrain->offroad = 0;
terrain->damageType = -1;
terrain->trickPanel = 0;
terrain->flags = 0;
}
static void K_NewTerrainDefs(void)
@ -159,12 +206,24 @@ static void K_ParseTerrainParameter(UINT32 i, char *param, char *val)
}
else if (stricmp(param, "offroad") == 0)
{
terrain->offroad = (UINT8)get_number(val);
terrain->offroad = (UINT8)get_number(val); // offroad strength enum?
}
else if (stricmp(param, "damageType") == 0)
{
terrain->damageType = (INT16)get_number(val);
}
else if (stricmp(param, "trickPanel") == 0)
{
terrain->trickPanel = (UINT8)get_number(val); // trick panel strength enum?
}
else if (stricmp(param, "liquid") == 0)
{
K_FlagBoolean(&terrain->flags, TRF_LIQUID, val);
}
else if (stricmp(param, "sneakerPanel") == 0)
{
K_FlagBoolean(&terrain->flags, TRF_SNEAKERPANEL, val);
}
}
static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *))
@ -210,14 +269,13 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size)
while (tkn && (pos = M_GetTokenPos()) < size)
{
boolean result = true;
boolean valid = true;
// Avoid anything inside bracketed stuff, only look for external keywords.
if (fastcmp(tkn, "{") || fastcmp(tkn, "}"))
{
CONS_Alert(CONS_ERROR, "Rogue bracket detected in TERRAIN lump.\n");
Z_Free(tkn);
return false;
valid = false;
}
// Check for valid fields.
else if (stricmp(tkn, "terrain") == 0)
@ -249,28 +307,28 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size)
CONS_Printf("Created new Terrain type '%s'\n", t->name);
}
result = K_DoTERRAINLumpParse(i, K_ParseTerrainParameter);
valid = K_DoTERRAINLumpParse(i, K_ParseTerrainParameter);
}
// TODO: the other block types!
else
{
CONS_Alert(CONS_NOTICE, "No terrain type name.\n");
CONS_Alert(CONS_ERROR, "No terrain type name.\n");
valid = false;
}
}
else
{
CONS_Alert(CONS_NOTICE, "Unknown field '%s' found in TERRAIN lump.\n", tkn);
Z_Free(tkn);
return false;
CONS_Alert(CONS_ERROR, "Unknown field '%s' found in TERRAIN lump.\n", tkn);
valid = false;
}
if (result == false)
Z_Free(tkn);
if (valid == false)
{
Z_Free(tkn);
return false;
}
Z_Free(tkn);
tkn = M_GetToken(NULL);
}

View file

@ -14,8 +14,11 @@
#ifndef __K_TERRAIN_H__
#define __K_TERRAIN_H__
#include "doomdata.h"
#include "doomdef.h"
#include "doomtype.h"
#include "m_fixed.h"
#include "p_mobj.h"
#define TERRAIN_NAME_LEN 32
@ -41,6 +44,13 @@ typedef struct t_footstep_s
UINT16 sound; // Sound to play.
} t_footstep_t;
typedef enum
{
// Terrain flag values.
TRF_LIQUID = 1, // Texture water properties (wavy, slippery, etc)
TRF_SNEAKERPANEL = 1<<1 // Texture is a booster
} terrain_flags_t;
typedef struct terrain_s
{
// Terrain definition.
@ -57,6 +67,8 @@ typedef struct terrain_s
fixed_t friction; // The default friction of this texture.
UINT8 offroad; // The default offroad level of this texture.
INT16 damageType; // The default damage type of this texture. (Negative means no damage).
UINT8 trickPanel; // Trick panel strength
UINT32 flags; // Flag values (see: terrain_flags_t)
} terrain_t;
// Arrays for all terrain definitions.
@ -78,6 +90,8 @@ terrain_t *K_GetDefaultTerrain(void);
terrain_t *K_GetTerrainForTextureNum(INT32 textureNum);
terrain_t *K_GetTerrainForTextureName(const char *checkName);
void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID);
void K_InitTerrain(UINT16 wadNum);
#endif // __K_TERRAIN_H__

View file

@ -1061,6 +1061,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
P_SetThingPosition(target);
target->standingslope = NULL;
target->terrain = NULL;
target->pmomz = 0;
target->player->playerstate = PST_DEAD;

View file

@ -384,6 +384,7 @@ extern camera_t *mapcampointer;
extern fixed_t tmx;
extern fixed_t tmy;
extern pslope_t *tmfloorslope, *tmceilingslope;
extern INT32 tmfloorpic, tmceilingpic;
/* cphipps 2004/08/30 */
extern void P_MapStart(void);

View file

@ -24,12 +24,13 @@
#include "r_sky.h"
#include "s_sound.h"
#include "w_wad.h"
#include "k_kart.h" // SRB2kart 011617
#include "k_collide.h"
#include "k_respawn.h"
#include "hu_stuff.h" // SRB2kart
#include "i_system.h" // SRB2kart
#include "k_terrain.h"
#include "r_splats.h"
@ -60,6 +61,7 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz
mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
ffloor_t *tmfloorrover, *tmceilingrover;
pslope_t *tmfloorslope, *tmceilingslope;
INT32 tmfloorpic, tmceilingpic;
static fixed_t tmfloorstep;
static fixed_t tmceilingstep;
@ -303,6 +305,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
}
object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you.
object->terrain = NULL;
object->eflags |= MFE_SPRUNG; // apply this flag asap!
spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify
@ -441,6 +444,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
object->standingslope = NULL; // No launching off at silly angles for you.
object->terrain = NULL;
switch (spring->type)
{
@ -1427,6 +1431,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = thing->z + thing->height;
tmfloorrover = NULL;
tmfloorslope = NULL;
tmfloorpic = -1;
}
return true;
}
@ -1446,6 +1451,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = tmceilingz = topz; // block while in air
tmceilingrover = NULL;
tmceilingslope = NULL;
tmceilingpic = -1;
tmfloorthing = thing; // needed for side collision
}
else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height)
@ -1453,6 +1459,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmceilingz = topz;
tmceilingrover = NULL;
tmceilingslope = NULL;
tmceilingpic = -1;
tmfloorthing = thing; // thing we may stand on
}
}
@ -1468,6 +1475,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmceilingz = thing->z;
tmceilingrover = NULL;
tmceilingslope = NULL;
tmceilingpic = -1;
}
return true;
}
@ -1487,6 +1495,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = tmceilingz = topz; // block while in air
tmfloorrover = NULL;
tmfloorslope = NULL;
tmfloorpic = -1;
tmfloorthing = thing; // needed for side collision
}
else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z)
@ -1494,6 +1503,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = topz;
tmfloorrover = NULL;
tmfloorslope = NULL;
tmfloorpic = -1;
tmfloorthing = thing; // thing we may stand on
}
}
@ -1673,6 +1683,7 @@ static boolean PIT_CheckLine(line_t *ld)
ceilingline = ld;
tmceilingrover = openceilingrover;
tmceilingslope = opentopslope;
tmceilingpic = opentoppic;
tmceilingstep = openceilingstep;
if (thingtop == tmthing->ceilingz)
{
@ -1685,6 +1696,7 @@ static boolean PIT_CheckLine(line_t *ld)
tmfloorz = openbottom;
tmfloorrover = openfloorrover;
tmfloorslope = openbottomslope;
tmfloorpic = openbottompic;
tmfloorstep = openfloorstep;
if (tmthing->z == tmthing->floorz)
{
@ -1781,6 +1793,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingrover = NULL;
tmfloorslope = newsubsec->sector->f_slope;
tmceilingslope = newsubsec->sector->c_slope;
tmfloorpic = newsubsec->sector->floorpic;
tmceilingpic = newsubsec->sector->ceilingpic;
tmfloorstep = 0;
tmceilingstep = 0;
@ -1834,6 +1848,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = topheight - sinklevel;
tmfloorrover = rover;
tmfloorslope = *rover->t_slope;
tmfloorpic = *rover->toppic;
}
}
else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0)
@ -1842,6 +1857,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingz = bottomheight + sinklevel;
tmceilingrover = rover;
tmceilingslope = *rover->b_slope;
tmceilingpic = *rover->bottompic;
}
}
}
@ -1865,6 +1881,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = thing->z;
tmfloorrover = rover;
tmfloorslope = NULL;
tmfloorpic = *rover->toppic;
}
}
// Quicksand blocks never change heights otherwise.
@ -1882,6 +1899,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = tmdropoffz = topheight;
tmfloorrover = rover;
tmfloorslope = *rover->t_slope;
tmfloorpic = *rover->toppic;
}
if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
&& !(rover->flags & FF_PLATFORM)
@ -1890,6 +1908,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingz = tmdrpoffceilz = bottomheight;
tmceilingrover = rover;
tmceilingslope = *rover->b_slope;
tmceilingpic = *rover->bottompic;
}
}
}
@ -1964,12 +1983,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = tmdropoffz = polytop;
tmfloorslope = NULL;
tmfloorrover = NULL;
tmfloorpic = polysec->ceilingpic;
}
if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) {
tmceilingz = tmdrpoffceilz = polybottom;
tmceilingslope = NULL;
tmceilingrover = NULL;
tmceilingpic = polysec->floorpic;
}
}
plink = (polymaplink_t *)(plink->link.next);
@ -2387,6 +2408,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
ffloor_t *oldceilrover = tmceilingrover;
pslope_t *oldfslope = tmfloorslope;
pslope_t *oldcslope = tmceilingslope;
INT32 oldfpic = tmfloorpic;
INT32 oldcpic = tmceilingpic;
// Move the player
P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true);
@ -2403,6 +2426,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
tmceilingrover = oldceilrover;
tmfloorslope = oldfslope;
tmceilingslope = oldcslope;
tmfloorpic = oldfpic;
tmceilingpic = oldcpic;
thing->momz = stand->momz;
}
else
@ -2616,9 +2641,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (!(thing->flags & MF_NOCLIPHEIGHT))
{
// Assign thing's standingslope if needed
if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) {
if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP))
{
K_UpdateMobjTerrain(thing, tmfloorpic);
if (!startingonground && tmfloorslope)
{
P_HandleSlopeLanding(thing, tmfloorslope);
}
if (thing->momz <= 0)
{
@ -2626,12 +2656,19 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
{
P_PlayerHitFloor(thing->player, true);
}
}
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) {
}
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP))
{
K_UpdateMobjTerrain(thing, tmceilingpic);
if (!startingonground && tmceilingslope)
{
P_HandleSlopeLanding(thing, tmceilingslope);
}
if (thing->momz >= 0)
{
@ -2639,12 +2676,18 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
{
P_PlayerHitFloor(thing->player, true);
}
}
}
else // don't set standingslope if you're not going to clip against it
}
else
{
// don't set standingslope if you're not going to clip against it
thing->standingslope = NULL;
thing->terrain = NULL;
}
/* FIXME: slope step down (even up) has some false
positives, so just ignore them entirely. */

View file

@ -342,6 +342,7 @@ fixed_t openceilingstep;
fixed_t openceilingdrop;
fixed_t openfloorstep;
fixed_t openfloordrop;
INT32 opentoppic, openbottompic;
// P_CameraLineOpening
// P_LineOpening, but for camera
@ -537,6 +538,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
highceiling = INT32_MIN;
lowfloor = INT32_MAX;
opentopslope = openbottomslope = NULL;
opentoppic = openbottompic = -1;
openceilingstep = 0;
openceilingdrop = 0;
openfloorstep = 0;
@ -556,6 +558,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
opentop = height[lo];
highceiling = height[hi];
opentopslope = sector[lo]->c_slope;
opentoppic = sector[lo]->ceilingpic;
if (mobj)
{
@ -575,6 +578,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
openbottom = height[hi];
lowfloor = height[lo];
openbottomslope = sector[hi]->f_slope;
openbottompic = sector[hi]->floorpic;
if (mobj)
{
@ -747,6 +751,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (bottomheight < open[FRONT].top) {
open[FRONT].top = bottomheight;
opentopslope = *rover->b_slope;
opentoppic = *rover->bottompic;
open[FRONT].ceilingrover = rover;
}
else if (bottomheight < highceiling)
@ -758,6 +763,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (topheight > open[FRONT].bottom) {
open[FRONT].bottom = topheight;
openbottomslope = *rover->t_slope;
openbottompic = *rover->toppic;
open[FRONT].floorrover = rover;
}
else if (topheight > lowfloor)
@ -789,6 +795,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (bottomheight < open[BACK].top) {
open[BACK].top = bottomheight;
opentopslope = *rover->b_slope;
opentoppic = *rover->bottompic;
open[BACK].ceilingrover = rover;
}
else if (bottomheight < highceiling)
@ -800,6 +807,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (topheight > open[BACK].bottom) {
open[BACK].bottom = topheight;
openbottomslope = *rover->t_slope;
openbottompic = *rover->toppic;
open[BACK].floorrover = rover;
}
else if (topheight > lowfloor)

View file

@ -63,6 +63,7 @@ extern fixed_t openceilingstep;
extern fixed_t openceilingdrop;
extern fixed_t openfloorstep;
extern fixed_t openfloordrop;
extern INT32 opentoppic, openbottompic;
void P_LineOpening(line_t *plinedef, mobj_t *mobj);

View file

@ -40,6 +40,7 @@
#include "k_color.h"
#include "k_respawn.h"
#include "k_bot.h"
#include "k_terrain.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
@ -1505,7 +1506,10 @@ void P_XYMovement(mobj_t *mo)
oldy = mo->y;
if (mo->flags & MF_NOCLIPHEIGHT)
{
mo->standingslope = NULL;
mo->terrain = NULL;
}
// adjust various things based on slope
if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) {
@ -1671,6 +1675,7 @@ void P_XYMovement(mobj_t *mo)
{
mo->momz = transfermomz;
mo->standingslope = NULL;
mo->terrain = NULL;
P_SetPitchRoll(mo, ANGLE_90,
transferslope->xydirection
+ (transferslope->zangle
@ -1782,6 +1787,7 @@ void P_XYMovement(mobj_t *mo)
mo->momz = P_MobjFlip(mo)*FRACUNIT/2;
mo->z = predictedz + P_MobjFlip(mo);
mo->standingslope = NULL;
mo->terrain = NULL;
//CONS_Printf("Launched off of flat surface running into downward slope\n");
}
}
@ -2274,6 +2280,8 @@ boolean P_ZMovement(mobj_t *mo)
}
P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly
K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? tmceilingpic : tmfloorpic));
if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM))
{
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
@ -2503,13 +2511,18 @@ boolean P_ZMovement(mobj_t *mo)
if (mo->type == MT_STEAM)
return true;
}
else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
else
{
mo->terrain = NULL;
if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
{
/// \todo may not be needed (done in P_MobjThinker normally)
mo->eflags &= ~MFE_JUSTHITFLOOR;
P_CheckGravity(mo, true);
}
}
if (((mo->z + mo->height > mo->ceilingz && !(mo->eflags & MFE_VERTICALFLIP))
|| (mo->z < mo->floorz && mo->eflags & MFE_VERTICALFLIP))
@ -2712,15 +2725,24 @@ void P_PlayerZMovement(mobj_t *mo)
if (onground && !(mo->flags & MF_NOCLIPHEIGHT))
{
if (mo->eflags & MFE_VERTICALFLIP)
{
mo->z = mo->ceilingz - mo->height;
}
else
{
mo->z = mo->floorz;
}
K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingpic : tmfloorpic));
// Get up if you fell.
if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0 && mo->player->tumbleBounces == 0)
{
P_SetPlayerMobjState(mo, S_KART_STILL);
}
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope))
{
// Handle landing on slope during Z movement
P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope));
}
@ -2736,12 +2758,20 @@ void P_PlayerZMovement(mobj_t *mo)
P_PlayerPolyObjectZMovement(mo);
if (clipmomz)
{
mo->momz = (tmfloorthing ? tmfloorthing->momz : 0);
}
}
else if (tmfloorthing)
{
mo->momz = tmfloorthing->momz;
}
else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
}
else
{
mo->terrain = NULL;
if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
{
if (P_IsObjectInGoop(mo) && !(mo->flags & MF_NOCLIPHEIGHT))
{
@ -2760,6 +2790,7 @@ void P_PlayerZMovement(mobj_t *mo)
mo->eflags &= ~MFE_JUSTHITFLOOR;
P_CheckGravity(mo, true);
}
}
if (((mo->eflags & MFE_VERTICALFLIP && mo->z < mo->floorz) || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z + mo->height > mo->ceilingz))
&& !(mo->flags & MF_NOCLIPHEIGHT))

View file

@ -395,6 +395,7 @@ typedef struct mobj_s
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
struct terrain_s *terrain; // Terrain definition of the floor this object last hit. NULL when in the air.
INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls
// WARNING: New fields must be added separately to savegame and Lua.

View file

@ -850,6 +850,7 @@ void P_SlopeLaunch(mobj_t *mo)
//CONS_Printf("Launched off of slope.\n");
mo->standingslope = NULL;
mo->terrain = NULL;
if (mo->player)
{