Merge branch 'toast_slopes' into 'next'

Some slope improvements/fixes (plus P_GetMobjGravity)

Dear Red, I did some things.

* Made the slope flag SL_NOPHYSICS actually have an effect like we wanted to, but didn't get around to implementing yet - activated by setting the slope's linedef flags to have ML_NOSONIC.
* Made downhill slope thrusts proportional to an object's gravity and friction.
* To make the above happen - seperated out the gravity value finding code in P_CheckGravity into a seperate function, P_GetMobjGravity. (p_mobj.c, p_local.h) I also made this function available to Lua.
* Turned those PANIC n console messages (which would inevitably be followed up with a crash, since we're accessing invalid memory immediately after) into a descriptive I_Error.
* Put the SRB2CB type-shimming behind an ESLOPE_TYPESHIM ifdef.
* Removed SPRINGCLEAN-ifdef'd code.
* Cleaned up some eosteric comments.
* NEW SINCE RED +1'd THIS: The teetering code now takes slopes into account pretty well. There are edge circumstances as outlined in commit 9d221f4f3f, but this is unilaterally better behaviour in every way and the teetering code was kind of a mess anyways.
* NEW SINCE RED AND ALAM +1'd THIS: P_ReverseQuantiseMomentumToSlope. Simple function that replaces the inverse angle stuff (which also wasn't using InvAngle, just ANGLE_MAX - angle - which is inaccurate!!)

Current testing files available at /toaster/slptst3.wad and /toaster/gravitytest.lua on the ftp.

I want to do more to the branch like implement SL_ANCHORVERTEX in the near future, but this is probably safe to merge in its current state.

See merge request !77
This commit is contained in:
Inuyasha 2016-06-22 19:03:58 -04:00
commit 26b3f2e0dc
8 changed files with 171 additions and 376 deletions

View file

@ -431,6 +431,12 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Kalaron/Eternity Engine slope code (SRB2CB ported)
#define ESLOPE
#ifdef ESLOPE
/// Backwards compatibility with SRB2CB's slope linedef types.
/// \note A simple shim that prints a warning.
#define ESLOPE_TYPESHIM
#endif
/// Delete file while the game is running.
/// \note EXTREMELY buggy, tends to crash game.
//#define DELFILE

View file

@ -986,6 +986,7 @@ static const char *credits[] = {
"\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom)
"Andrew \"orospakr\" Clunis",
"Gregor \"Oogaland\" Dick",
"Vivian \"toaster\" Grannell",
"Julio \"Chaos Zero 64\" Guir",
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"Matthew \"Shuffle\" Marsalko",

View file

@ -437,6 +437,16 @@ static int lib_pMobjFlip(lua_State *L)
return 1;
}
static int lib_pGetMobjGravity(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjGravity(mobj));
return 1;
}
static int lib_pWeaponOrPanel(lua_State *L)
{
mobjtype_t type = luaL_checkinteger(L, 1);
@ -2008,6 +2018,7 @@ static luaL_Reg lib[] = {
{"P_SPMAngle",lib_pSPMAngle},
{"P_SpawnPlayerMissile",lib_pSpawnPlayerMissile},
{"P_MobjFlip",lib_pMobjFlip},
{"P_GetMobjGravity",lib_pGetMobjGravity},
{"P_WeaponOrPanel",lib_pWeaponOrPanel},
{"P_FlashPal",lib_pFlashPal},
{"P_GetClosestAxis",lib_pGetClosestAxis},

View file

@ -251,6 +251,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype
#endif
void P_ColorTeamMissile(mobj_t *missile, player_t *source);
SINT8 P_MobjFlip(mobj_t *mobj);
fixed_t P_GetMobjGravity(mobj_t *mo);
boolean P_WeaponOrPanel(mobjtype_t type);
boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled);

View file

@ -1252,13 +1252,12 @@ static void P_PlayerFlip(mobj_t *mo)
}
//
// P_CheckGravity
// P_GetMobjGravity
//
// Checks the current gravity state
// of the object. If affect is true,
// a gravity force will be applied.
// Returns the current gravity
// value of the object.
//
void P_CheckGravity(mobj_t *mo, boolean affect)
fixed_t P_GetMobjGravity(mobj_t *mo)
{
fixed_t gravityadd = 0;
boolean no3dfloorgrav = true; // Custom gravity
@ -1317,9 +1316,6 @@ void P_CheckGravity(mobj_t *mo, boolean affect)
if (mo->eflags & MFE_UNDERWATER && !goopgravity)
gravityadd = gravityadd/3;
if (!mo->momz) // mobj at stop, no floor, so feel the push of gravity!
gravityadd <<= 1;
if (mo->player)
{
if (mo->player->charability == CA_FLY && (mo->player->powers[pw_tailsfly]
@ -1400,12 +1396,31 @@ void P_CheckGravity(mobj_t *mo, boolean affect)
if (goopgravity)
gravityadd = -gravityadd/5;
if (affect)
mo->momz += FixedMul(gravityadd, mo->scale);
if (mo->player && !!(mo->eflags & MFE_VERTICALFLIP) != wasflip)
P_PlayerFlip(mo);
gravityadd = FixedMul(gravityadd, mo->scale);
return gravityadd;
}
//
// P_CheckGravity
//
// Checks the current gravity state
// of the object. If affect is true,
// a gravity force will be applied.
//
void P_CheckGravity(mobj_t *mo, boolean affect)
{
fixed_t gravityadd = P_GetMobjGravity(mo);
if (!mo->momz) // mobj at stop, no floor, so feel the push of gravity!
gravityadd <<= 1;
if (affect)
mo->momz += gravityadd;
if (mo->type == MT_SKIM && mo->z + mo->momz <= mo->watertop && mo->z >= mo->watertop)
{
mo->momz = 0;
@ -1480,7 +1495,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
&& abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale)
&& (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING))
#ifdef ESLOPE
&& !(player->mo->standingslope && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
&& !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2))
#endif
)
{
@ -2154,16 +2169,6 @@ static boolean P_ZMovement(mobj_t *mo)
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
#ifdef ESLOPE
if (mo->standingslope)
{
if (mo->flags & MF_NOCLIPHEIGHT)
mo->standingslope = NULL;
else if (!P_IsObjectOnGround(mo))
P_SlopeLaunch(mo);
}
#endif
// Intercept the stupid 'fall through 3dfloors' bug
if (mo->subsector->sector->ffloors)
P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
@ -2178,6 +2183,16 @@ static boolean P_ZMovement(mobj_t *mo)
}
mo->z += mo->momz;
#ifdef ESLOPE
if (mo->standingslope)
{
if (mo->flags & MF_NOCLIPHEIGHT)
mo->standingslope = NULL;
else if (!P_IsObjectOnGround(mo))
P_SlopeLaunch(mo);
}
#endif
switch (mo->type)
{
case MT_THROWNBOUNCE:
@ -2364,10 +2379,7 @@ static boolean P_ZMovement(mobj_t *mo)
if ((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) {
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
// Reverse quantizing might could use its own function later
mo->standingslope->zangle = ANGLE_MAX-mo->standingslope->zangle;
P_QuantizeMomentumToSlope(&mom, mo->standingslope);
mo->standingslope->zangle = ANGLE_MAX-mo->standingslope->zangle;
P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope);
}
#endif

View file

@ -199,7 +199,6 @@ static fixed_t P_GetExtent(sector_t *sector, line_t *line)
// Find furthest vertex from the reference line. It, along with the two ends
// of the line, will define the plane.
// SRB2CBTODO: Use a formula to get the slope to slide objects depending on how steep
for(i = 0; i < sector->linecount; i++)
{
line_t *li = sector->lines[i];
@ -231,7 +230,6 @@ static fixed_t P_GetExtent(sector_t *sector, line_t *line)
//
// Creates one or more slopes based on the given line type and front/back
// sectors.
// Kalaron: Check if dynamic slopes need recalculation
//
void P_SpawnSlope_Line(int linenum)
{
@ -276,7 +274,6 @@ void P_SpawnSlope_Line(int linenum)
ny = -FixedDiv(line->dx, len);
}
// SRB2CBTODO: Transform origin relative to the bounds of an individual FOF
origin.x = line->v1->x + (line->v2->x - line->v1->x)/2;
origin.y = line->v1->y + (line->v2->y - line->v1->y)/2;
@ -327,7 +324,7 @@ void P_SpawnSlope_Line(int linenum)
// fslope->normal is a 3D line perpendicular to the 3D vector
// Sync the linedata of the line that started this slope
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
// TODO: Anything special for control sector based slopes later?
fslope->sourceline = line;
// To find the real highz/lowz of a slope, you need to check all the vertexes
@ -379,7 +376,7 @@ void P_SpawnSlope_Line(int linenum)
cslope->refpos = 2;
// Sync the linedata of the line that started this slope
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
// TODO: Anything special for control sector based slopes later?
cslope->sourceline = line;
// Remember the way the slope is formed
@ -445,7 +442,7 @@ void P_SpawnSlope_Line(int linenum)
fslope->refpos = 3;
// Sync the linedata of the line that started this slope
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
// TODO: Anything special for control sector based slopes later?
fslope->sourceline = line;
// Remember the way the slope is formed
@ -488,7 +485,7 @@ void P_SpawnSlope_Line(int linenum)
cslope->refpos = 4;
// Sync the linedata of the line that started this slope
// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
// TODO: Anything special for control sector based slopes later?
cslope->sourceline = line;
// Remember the way the slope is formed
@ -554,16 +551,11 @@ static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag
ret->vertices[2] = mt;
}
if (!ret->vertices[0])
CONS_Printf("PANIC 0\n");
if (!ret->vertices[1])
CONS_Printf("PANIC 1\n");
if (!ret->vertices[2])
CONS_Printf("PANIC 2\n");
// Now set heights for each vertex, because they haven't been set yet
for (i = 0; i < 3; i++) {
mt = ret->vertices[i];
if (!mt) // If a vertex wasn't found, it's game over. There's nothing you can do to recover (except maybe try and kill the slope instead - TODO?)
I_Error("P_NewVertexSlope: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1);
if (mt->extrainfo)
mt->z = mt->options;
else
@ -623,265 +615,10 @@ pslope_t *P_SlopeById(UINT16 id)
return ret;
}
#ifdef SPRINGCLEAN
#include "byteptr.h"
#include "p_setup.h"
#include "p_local.h"
//==========================================================================
//
// P_SetSlopesFromVertexHeights
//
//==========================================================================
void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum)
{
mapthing_t *mt;
boolean vt_found = false;
size_t i, j, k, l, q;
//size_t i;
//mapthing_t *mt;
char *data;
char *datastart;
// SRB2CBTODO: WHAT IS (5 * sizeof (short))?! It = 10
// anything else seems to make a map not load properly,
// but this hard-coded value MUST have some reason for being what it is
size_t snummapthings = W_LumpLength(lumpnum) / (5 * sizeof (short));
mapthing_t *smapthings = Z_Calloc(snummapthings * sizeof (*smapthings), PU_LEVEL, NULL);
fixed_t x, y;
sector_t *sector;
// Spawn axis points first so they are
// at the front of the list for fast searching.
data = datastart = W_CacheLumpNum(lumpnum, PU_LEVEL);
mt = smapthings;
for (i = 0; i < snummapthings; i++, mt++)
{
mt->x = READINT16(data);
mt->y = READINT16(data);
mt->angle = READINT16(data);
mt->type = READINT16(data);
mt->options = READINT16(data);
// mt->z hasn't been set yet!
//mt->extrainfo = (byte)(mt->type >> 12); // slope things are special, they have a bigger range of types
//mt->type &= 4095; // SRB2CBTODO: WHAT IS THIS???? Mobj type limits?!!!!
x = mt->x*FRACUNIT;
y = mt->y*FRACUNIT;
sector = R_PointInSubsector(x, y)->sector;
// Z for objects
#ifdef ESLOPE
if (sector->f_slope)
mt->z = (short)(P_GetZAt(sector->f_slope, x, y)>>FRACBITS);
else
#endif
mt->z = (short)(sector->floorheight>>FRACBITS);
mt->z = mt->z + (mt->options >> ZSHIFT);
if (mt->type == THING_VertexFloorZ || mt->type == THING_VertexCeilingZ) // THING_VertexFloorZ
{
for(l = 0; l < numvertexes; l++)
{
if (vertexes[l].x == mt->x*FRACUNIT && vertexes[l].y == mt->y*FRACUNIT)
{
if (mt->type == THING_VertexFloorZ)
{
vertexes[l].z = mt->z*FRACUNIT;
//I_Error("Z value: %i", vertexes[l].z/FRACUNIT);
}
else
{
vertexes[l].z = mt->z*FRACUNIT; // celing floor
}
vt_found = true;
}
}
//mt->type = 0; // VPHYSICS: Dynamic slopes
if (vt_found)
{
for (k = 0; k < numsectors; k++)
{
sector_t *sec = &sectors[k];
if (sec->linecount != 3) continue; // only works with triangular sectors
v3float_t vt1, vt2, vt3; // cross = ret->normalf
v3float_t vec1, vec2;
int vi1, vi2, vi3;
vi1 = (int)(sec->lines[0]->v1 - vertexes);
vi2 = (int)(sec->lines[0]->v2 - vertexes);
vi3 = (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2)?
(int)(sec->lines[1]->v2 - vertexes) : (int)(sec->lines[1]->v1 - vertexes);
//if (vertexes[vi1].z)
// I_Error("OSNAP %i", vertexes[vi1].z/FRACUNIT);
//if (vertexes[vi2].z)
// I_Error("OSNAP %i", vertexes[vi2].z/FRACUNIT);
//if (vertexes[vi3].z)
// I_Error("OSNAP %i", vertexes[vi3].z/FRACUNIT);
//I_Error("%i, %i", mt->z*FRACUNIT, vertexes[vi1].z);
//I_Error("%i, %i, %i", mt->x, mt->y, mt->z);
//P_SpawnMobj(mt->x*FRACUNIT, mt->y*FRACUNIT, mt->z*FRACUNIT, MT_RING);
// TODO: Make sure not to spawn in the same place 2x! (we need an object in every vertex of the
// triangle sector to setup the real vertex slopes
// Check for the vertexes of all sectors
for(q = 0; q < numvertexes; q++)
{
if (vertexes[q].x == mt->x*FRACUNIT && vertexes[q].y == mt->y*FRACUNIT)
{
//I_Error("yeah %i", vertexes[q].z);
P_SpawnMobj(vertexes[q].x, vertexes[q].y, vertexes[q].z, MT_RING);
#if 0
if ((mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
P_SpawnMobj(vertexes[vi1].x, vertexes[vi1].y, vertexes[vi1].z, MT_RING);
else if ((mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
P_SpawnMobj(vertexes[vi2].x, vertexes[vi2].y, vertexes[vi2].z, MT_BOUNCETV);
else if ((mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z)
&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z))
P_SpawnMobj(vertexes[vi3].x, vertexes[vi3].y, vertexes[vi3].z, MT_GFZFLOWER1);
else
#endif
continue;
}
}
vt1.x = FIXED_TO_FLOAT(vertexes[vi1].x);
vt1.y = FIXED_TO_FLOAT(vertexes[vi1].y);
vt2.x = FIXED_TO_FLOAT(vertexes[vi2].x);
vt2.y = FIXED_TO_FLOAT(vertexes[vi2].y);
vt3.x = FIXED_TO_FLOAT(vertexes[vi3].x);
vt3.y = FIXED_TO_FLOAT(vertexes[vi3].y);
for(j = 0; j < 2; j++)
{
fixed_t z3;
//I_Error("Lo hicimos");
vt1.z = mt->z;//FIXED_TO_FLOAT(j==0 ? sec->floorheight : sec->ceilingheight);
vt2.z = mt->z;//FIXED_TO_FLOAT(j==0? sec->floorheight : sec->ceilingheight);
z3 = mt->z;//j==0? sec->floorheight : sec->ceilingheight; // Destination height
vt3.z = FIXED_TO_FLOAT(z3);
if (P_PointOnLineSide(vertexes[vi3].x, vertexes[vi3].y, sec->lines[0]) == 0)
{
vec1.x = vt2.x - vt3.x;
vec1.y = vt2.y - vt3.y;
vec1.z = vt2.z - vt3.z;
vec2.x = vt1.x - vt3.x;
vec2.y = vt1.y - vt3.y;
vec2.z = vt1.z - vt3.z;
}
else
{
vec1.x = vt1.x - vt3.x;
vec1.y = vt1.y - vt3.y;
vec1.z = vt1.z - vt3.z;
vec2.x = vt2.x - vt3.x;
vec2.y = vt2.y - vt3.y;
vec2.z = vt2.z - vt3.z;
}
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
memset(ret, 0, sizeof(*ret));
{
M_CrossProduct3f(&ret->normalf, &vec1, &vec2);
// Cross product length
float len = (float)sqrt(ret->normalf.x * ret->normalf.x +
ret->normalf.y * ret->normalf.y +
ret->normalf.z * ret->normalf.z);
if (len == 0)
{
// Only happens when all vertices in this sector are on the same line.
// Let's just ignore this case.
//CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", (int)(x>>16), (int)(y>>16));
return;
}
// cross/len
ret->normalf.x /= len;
ret->normalf.y /= len;
ret->normalf.z /= len;
// ZDoom cross = ret->normalf
// Fix backward normals
if ((ret->normalf.z < 0 && j == 0) || (ret->normalf.z > 0 && j == 1))
{
// cross = -cross
ret->normalf.x = -ret->normalf.x;
ret->normalf.y = -ret->normalf.x;
ret->normalf.z = -ret->normalf.x;
}
}
secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
srcplane->a = FLOAT_TO_FIXED (ret->normalf.x);
srcplane->b = FLOAT_TO_FIXED (ret->normalf.y);
srcplane->c = FLOAT_TO_FIXED (ret->normalf.z);
//srcplane->ic = FixedDiv(FRACUNIT, srcplane->c);
srcplane->d = -TMulScale16 (srcplane->a, vertexes[vi3].x,
srcplane->b, vertexes[vi3].y,
srcplane->c, z3);
if (j == 0)
{
sec->f_slope = ret;
sec->f_slope->secplane = *srcplane;
}
else if (j == 1)
{
sec->c_slope = ret;
sec->c_slope->secplane = *srcplane;
}
}
}
}
}
}
Z_Free(datastart);
}
#endif
// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes
void P_ResetDynamicSlopes(void) {
size_t i;
#if 1 // Rewrite old specials to new ones, and give a console warning
#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
boolean warned = false;
#endif
@ -894,7 +631,7 @@ void P_ResetDynamicSlopes(void) {
{
switch (lines[i].special)
{
#if 1 // Rewrite old specials to new ones, and give a console warning
#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
#define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");}
case 386:
case 387:
@ -1018,7 +755,11 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
// When given a vector, rotates it and aligns it to a slope
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
{
vector3_t axis;
vector3_t axis; // Fuck you, C90.
if (slope->flags & SL_NOPHYSICS)
return; // No physics, no quantizing.
axis.x = -slope->d.y;
axis.y = slope->d.x;
axis.z = 0;
@ -1026,24 +767,38 @@ void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
FV3_Rotate(momentum, &axis, slope->zangle >> ANGLETOFINESHIFT);
}
//
// P_ReverseQuantizeMomentumToSlope
//
// When given a vector, rotates and aligns it to a flat surface (from being relative to a given slope)
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
{
slope->zangle = InvAngle(slope->zangle);
P_QuantizeMomentumToSlope(momentum, slope);
slope->zangle = InvAngle(slope->zangle);
}
//
// P_SlopeLaunch
//
// Handles slope ejection for objects
void P_SlopeLaunch(mobj_t *mo)
{
// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
// vertical launch given from slopes while increasing the horizontal launch
// given. Good for SRB2's gravity and horizontal speeds.
vector3_t slopemom;
slopemom.x = mo->momx;
slopemom.y = mo->momy;
slopemom.z = mo->momz*2;
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching.
{
// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
// vertical launch given from slopes while increasing the horizontal launch
// given. Good for SRB2's gravity and horizontal speeds.
vector3_t slopemom;
slopemom.x = mo->momx;
slopemom.y = mo->momy;
slopemom.z = mo->momz*2;
P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
mo->momx = slopemom.x;
mo->momy = slopemom.y;
mo->momz = slopemom.z/2;
mo->momx = slopemom.x;
mo->momy = slopemom.y;
mo->momz = slopemom.z/2;
}
//CONS_Printf("Launched off of slope.\n");
mo->standingslope = NULL;
@ -1052,17 +807,21 @@ void P_SlopeLaunch(mobj_t *mo)
// Function to help handle landing on slopes
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
{
vector3_t mom;
vector3_t mom; // Ditto.
if (slope->flags & SL_NOPHYSICS) { // No physics, no need to make anything complicated.
if (P_MobjFlip(thing)*(thing->momz) < 0) { // falling, land on slope
thing->momz = -P_MobjFlip(thing);
thing->standingslope = slope;
}
return;
}
mom.x = thing->momx;
mom.y = thing->momy;
mom.z = thing->momz*2;
//CONS_Printf("langing on slope\n");
// Reverse quantizing might could use its own function later
slope->zangle = ANGLE_MAX-slope->zangle;
P_QuantizeMomentumToSlope(&mom, slope);
slope->zangle = ANGLE_MAX-slope->zangle;
P_ReverseQuantizeMomentumToSlope(&mom, slope);
if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope
thing->momx = mom.x;
@ -1082,6 +841,9 @@ void P_ButteredSlope(mobj_t *mo)
if (!mo->standingslope)
return;
if (mo->standingslope->flags & SL_NOPHYSICS)
return; // No physics, no butter.
if (mo->flags & (MF_NOCLIPHEIGHT|MF_NOGRAVITY))
return; // don't slide down slopes if you can't touch them or you're not affected by gravity
@ -1106,8 +868,6 @@ void P_ButteredSlope(mobj_t *mo)
mult = FINECOSINE(angle >> ANGLETOFINESHIFT);
}
//CONS_Printf("%d\n", mult);
thrust = FixedMul(thrust, FRACUNIT*2/3 + mult/8);
}
@ -1115,10 +875,11 @@ void P_ButteredSlope(mobj_t *mo)
thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/16);
// This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down
// Multiply by gravity
thrust = FixedMul(thrust, gravity); // TODO account for per-sector gravity etc
// Multiply by scale (gravity strength depends on mobj scale)
thrust = FixedMul(thrust, mo->scale);
// Let's get the gravity strength for the object...
thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo)));
// ... and its friction against the ground for good measure (divided by original friction to keep behaviour for normal slopes the same).
thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION));
P_Thrust(mo, mo->standingslope->xydirection, thrust);
}

View file

@ -21,26 +21,6 @@ void P_RunDynamicSlopes(void);
// sectors.
void P_SpawnSlope_Line(int linenum);
#ifdef SPRINGCLEAN
// Loads just map objects that make slopes,
// terrain affecting objects have to be spawned first
void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum);
typedef enum
{
THING_SlopeFloorPointLine = 9500,
THING_SlopeCeilingPointLine = 9501,
THING_SetFloorSlope = 9502,
THING_SetCeilingSlope = 9503,
THING_CopyFloorPlane = 9510,
THING_CopyCeilingPlane = 9511,
THING_VavoomFloor=1500,
THING_VavoomCeiling=1501,
THING_VertexFloorZ=1504,
THING_VertexCeilingZ=1505,
} slopething_e;
#endif
//
// P_CopySectorSlope
//
@ -55,6 +35,7 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
// Lots of physics-based bullshit
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
void P_SlopeLaunch(mobj_t *mo);
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
void P_ButteredSlope(mobj_t *mo);

View file

@ -1851,12 +1851,8 @@ static void P_CheckBouncySectors(player_t *player)
momentum.y = player->mo->momy;
momentum.z = player->mo->momz*2;
if (slope) {
// Reverse quantizing might could use its own function later
slope->zangle = ANGLE_MAX-slope->zangle;
P_QuantizeMomentumToSlope(&momentum, slope);
slope->zangle = ANGLE_MAX-slope->zangle;
}
if (slope)
P_ReverseQuantizeMomentumToSlope(&momentum, slope);
newmom = momentum.z = -FixedMul(momentum.z,linedist)/2;
#else
@ -2856,16 +2852,18 @@ static void P_DoTeeter(player_t *player)
{
boolean teeter = false;
boolean roverfloor; // solid 3d floors?
fixed_t floorheight, ceilingheight;
fixed_t topheight, bottomheight; // for 3d floor usage
const fixed_t tiptop = FixedMul(MAXSTEPMOVE, player->mo->scale); // Distance you have to be above the ground in order to teeter.
if (player->mo->standingslope && player->mo->standingslope->zdelta >= (FRACUNIT/2)) // Always teeter if the slope is too steep.
teeter = true;
else // Let's do some checks...
{
subsector_t *subsec[4]; // changed abcd into array instead
UINT8 i;
subsec[0] = R_PointInSubsector(player->mo->x + FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y + FixedMul(5*FRACUNIT, player->mo->scale));
subsec[1] = R_PointInSubsector(player->mo->x - FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y + FixedMul(5*FRACUNIT, player->mo->scale));
subsec[2] = R_PointInSubsector(player->mo->x + FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y - FixedMul(5*FRACUNIT, player->mo->scale));
subsec[3] = R_PointInSubsector(player->mo->x - FixedMul(5*FRACUNIT, player->mo->scale), player->mo->y - FixedMul(5*FRACUNIT, player->mo->scale));
sector_t *sec;
fixed_t highestceilingheight = INT32_MIN;
fixed_t lowestfloorheight = INT32_MAX;
teeter = false;
roverfloor = false;
@ -2873,13 +2871,43 @@ static void P_DoTeeter(player_t *player)
{
ffloor_t *rover;
if (!(subsec[i]->sector->ffloors))
#define xsign ((i & 1) ? -1 : 1) // 0 -> 1 | 1 -> -1 | 2 -> 1 | 3 -> -1
#define ysign ((i & 2) ? 1 : -1) // 0 -> 1 | 1 -> 1 | 2 -> -1 | 3 -> -1
fixed_t checkx = player->mo->x + (xsign*FixedMul(5*FRACUNIT, player->mo->scale));
fixed_t checky = player->mo->y + (ysign*FixedMul(5*FRACUNIT, player->mo->scale));
#undef xsign
#undef ysign
sec = R_PointInSubsector(checkx, checky)->sector;
ceilingheight = sec->ceilingheight;
floorheight = sec->floorheight;
#ifdef ESLOPE
if (sec->c_slope)
ceilingheight = P_GetZAt(sec->c_slope, checkx, checky);
if (sec->f_slope)
floorheight = P_GetZAt(sec->f_slope, checkx, checky);
#endif
highestceilingheight = (ceilingheight > highestceilingheight) ? ceilingheight : highestceilingheight;
lowestfloorheight = (floorheight < lowestfloorheight) ? floorheight : lowestfloorheight;
if (!(sec->ffloors))
continue; // move on to the next subsector
for (rover = subsec[i]->sector->ffloors; rover; rover = rover->next)
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS)) continue;
topheight = *rover->topheight;
bottomheight = *rover->bottomheight;
#ifdef ESLOPE
if (*rover->t_slope)
topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
if (*rover->b_slope)
bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
#endif
if (P_CheckSolidLava(player->mo, rover))
;
else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND))
@ -2887,12 +2915,12 @@ static void P_DoTeeter(player_t *player)
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if (*rover->bottomheight > subsec[i]->sector->ceilingheight) // Above the ceiling
if (bottomheight > ceilingheight) // Above the ceiling
continue;
if (*rover->bottomheight > player->mo->z + player->mo->height + tiptop
|| (*rover->topheight < player->mo->z
&& player->mo->z + player->mo->height < subsec[i]->sector->ceilingheight - tiptop))
if (bottomheight > player->mo->z + player->mo->height + tiptop
|| (topheight < player->mo->z
&& player->mo->z + player->mo->height < ceilingheight - tiptop))
{
teeter = true;
roverfloor = true;
@ -2906,12 +2934,12 @@ static void P_DoTeeter(player_t *player)
}
else
{
if (*rover->topheight < subsec[i]->sector->floorheight) // Below the floor
if (topheight < floorheight) // Below the floor
continue;
if (*rover->topheight < player->mo->z - tiptop
|| (*rover->bottomheight > player->mo->z + player->mo->height
&& player->mo->z > subsec[i]->sector->floorheight + tiptop))
if (topheight < player->mo->z - tiptop
|| (bottomheight > player->mo->z + player->mo->height
&& player->mo->z > floorheight + tiptop))
{
teeter = true;
roverfloor = true;
@ -2929,18 +2957,12 @@ static void P_DoTeeter(player_t *player)
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if (!teeter && !roverfloor && (subsec[0]->sector->ceilingheight > player->mo->ceilingz + tiptop
|| subsec[1]->sector->ceilingheight > player->mo->ceilingz + tiptop
|| subsec[2]->sector->ceilingheight > player->mo->ceilingz + tiptop
|| subsec[3]->sector->ceilingheight > player->mo->ceilingz + tiptop))
if (!teeter && !roverfloor && (highestceilingheight > player->mo->ceilingz + tiptop))
teeter = true;
}
else
{
if (!teeter && !roverfloor && (subsec[0]->sector->floorheight < player->mo->floorz - tiptop
|| subsec[1]->sector->floorheight < player->mo->floorz - tiptop
|| subsec[2]->sector->floorheight < player->mo->floorz - tiptop
|| subsec[3]->sector->floorheight < player->mo->floorz - tiptop))
if (!teeter && !roverfloor && (lowestfloorheight < player->mo->floorz - tiptop))
teeter = true;
}
}
@ -3670,7 +3692,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
{
if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<<FRACBITS, player->mo->scale) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING)
#ifdef ESLOPE
&& (!player->mo->standingslope || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
&& (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
#endif
)
{
@ -3703,7 +3725,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20))
&& !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
#ifdef ESLOPE
|| (player->mo->standingslope && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
|| (player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
#endif
) && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING))
{
@ -3719,7 +3741,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH)
&& player->speed < FixedMul(5*FRACUNIT,player->mo->scale)
#ifdef ESLOPE
&& (!player->mo->standingslope || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
&& (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
#endif
)
{
@ -4705,7 +4727,7 @@ static void P_3dMovement(player_t *player)
#ifdef ESLOPE
if ((totalthrust.x || totalthrust.y)
&& player->mo->standingslope && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) {
&& player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) {
// Factor thrust to slope, but only for the part pushing up it!
// The rest is unaffected.
angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-player->mo->standingslope->xydirection;