From 33a1ca583126cf6bf1f31772f9f6109cc0fdef51 Mon Sep 17 00:00:00 2001 From: Ashnal Date: Mon, 16 Sep 2024 00:47:45 +0000 Subject: [PATCH] Slope launch physiscs adjustments --- src/k_kart.c | 1 + src/p_map.c | 23 ++- src/p_maputl.c | 458 ++++++++++++++++++++++++------------------------- src/p_maputl.h | 10 ++ src/p_mobj.c | 81 ++++++--- src/typedef.h | 1 + 6 files changed, 316 insertions(+), 258 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 95faa2a7b..6ac5d873c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12552,6 +12552,7 @@ boolean K_FastFallBounce(player_t *player) } player->mo->momz = bounce * P_MobjFlip(player->mo); + CONS_Printf("%s FastFallBounce %d\n", player_names[player-players], player->mo->momz); return true; } diff --git a/src/p_map.c b/src/p_map.c index bc91b61a6..c1f9425af 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2775,6 +2775,17 @@ fixed_t P_GetThingStepUp(mobj_t *thing, fixed_t destX, fixed_t destY) maxstep = 0; } + if (thing->standingslope) + { + vector3_t slopemom = {0,0,0}; + slopemom.x = thing->momx; + slopemom.y = thing->momy; + slopemom.z = 0; + P_QuantizeMomentumToSlope(&slopemom, thing->standingslope); + fixed_t momentumzdelta = FixedDiv(slopemom.z, FixedHypot(slopemom.x, slopemom.y)); // so this lets us know what the zdelta is for the vector the player is travelling along, in addition to the slope's zdelta in its xydirection + maxstep += abs(momentumzdelta); + } + return maxstep; } @@ -2793,6 +2804,13 @@ increment_move fixed_t thingtop; fixed_t stairjank = 0; g_tm.floatok = false; + fixed_t oldfloorz = INT32_MAX; // Ramp detection + pslope_t *oldslope = NULL; + angle_t moveangle = R_PointToAngle2(thing->x,thing->y,x,y); + + boolean samepos = false; + if (thing->x == x && thing->y == y) + samepos = true; // reset this to 0 at the start of each trymove call as it's only used here numspechitint = 0U; @@ -2842,6 +2860,9 @@ increment_move boolean move_ok = P_CheckPosition(thing, tryx, tryy, result); + oldslope = thing->standingslope; + oldfloorz = thing->floorz; + if (P_MobjWasRemoved(thing)) { return false; @@ -2956,7 +2977,7 @@ increment_move } else if (g_tm.floorz - g_tm.dropoffz > maxstep) return false; // don't stand over a dropoff - } + } } } while (tryx != x || tryy != y); diff --git a/src/p_maputl.c b/src/p_maputl.c index bb33160c9..c5d588777 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -29,6 +29,7 @@ // // P_ClosestPointOnLine // Finds the closest point on a given line to the supplied point +// Considers line length to be infinite, and can return results outside of the actual linedef bounds // void P_ClosestPointOnLine(fixed_t x, fixed_t y, const line_t *line, vertex_t *result) { @@ -68,6 +69,27 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, const line_t *line, vertex_t *re return; } +// +// P_ClosestPointOnLineWithinLine +// Finds the closest point on a given line to the supplied point +// Like P_ClosestPointOnLine, except the result is constrained within the actual line +// +void P_ClosestPointOnLineWithinLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) +{ + P_ClosestPointOnLine(x, y, line, result); + + // Determine max and min bounds of the line + fixed_t maxx = max(line->v1->x, line->v2->x); + fixed_t maxy = max(line->v1->y, line->v2->y); + fixed_t minx = min(line->v1->x, line->v2->x); + fixed_t miny = min(line->v1->y, line->v2->y); + + // Constrain result to line by ensuring x and y don't go beyond the maximums + result->x = min(max(result->x, minx),maxx); + result->y = min(max(result->y, miny),maxy); + return; +} + /// Similar to FV3_ClosestPointOnLine() except it actually works. void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t *result) { @@ -527,6 +549,107 @@ static boolean P_MidtextureIsSolid(line_t *linedef, mobj_t *mobj) return ((linedef->flags & ML_MIDSOLID) == ML_MIDSOLID); } +boolean P_FoFOpening(sector_t *sector, line_t *linedef, mobj_t *mobj, opening_t *open, fofopening_t *fofopen) +{ + fixed_t delta1, delta2; + fixed_t thingtop = mobj->z + mobj->height; + boolean ret = false; // DId we find any relevant FoFs? + // Check for frontsector's fake floors + for (ffloor_t *rover = sector->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight, midheight; + + if (!(rover->fofflags & FOF_EXISTS)) + continue; + + if (P_CheckSolidFFloorSurface(mobj, rover)) + ; + else if (!((rover->fofflags & FOF_BLOCKPLAYER && mobj->player) + || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) + continue; + + ret = true; // Found a FoF that matters + + if (open->fofType != LO_FOF_ANY) + { + topheight = P_VeryTopOfFOF(rover); + bottomheight = P_VeryBottomOfFOF(rover); + } + else + { + topheight = P_GetFOFTopZ(mobj, sector, rover, g_tm.x, g_tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, sector, rover, g_tm.x, g_tm.y, linedef); + } + + switch (open->fofType) + { + case LO_FOF_FLOORS: + { + if (mobj->z >= topheight) + { + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) + { + if (topheight > fofopen->floor) + { + fofopen->floor = topheight; + fofopen->floorrover = rover; + } + } + } + break; + } + case LO_FOF_CEILINGS: + { + if (thingtop <= bottomheight) + { + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) + { + if (bottomheight < fofopen->ceiling) + { + fofopen->ceiling = bottomheight; + fofopen->ceilingrover = rover; + } + } + } + break; + } + default: + { + midheight = bottomheight + (topheight - bottomheight) / 2; + delta1 = abs(mobj->z - midheight); + delta2 = abs(thingtop - midheight); + + if (delta1 > delta2) + { + // thing is below FOF + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) + { + if (bottomheight < fofopen->ceiling) + { + fofopen->ceiling = bottomheight; + fofopen->ceilingrover = rover; + } + } + } + else + { + // thing is above FOF + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) + { + if (topheight > fofopen->floor) + { + fofopen->floor = topheight; + fofopen->floorrover = rover; + } + } + } + break; + } + } + } + return ret; +} + void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) { enum { FRONT, BACK }; @@ -589,7 +712,17 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) height[FRONT] = P_GetCeilingZ(mobj, front, g_tm.x, g_tm.y, linedef); height[BACK] = P_GetCeilingZ(mobj, back, g_tm.x, g_tm.y, linedef); - hi = ( height[0] < height[1] ); + if (height[FRONT] == height[BACK] && (front->c_slope || back->c_slope)) + { + fixed_t savedradius = mobj->radius; // forgive me. Perhaps it would be better to refactor these functions to take a radius of fixed_t instead? thats all they grab from the mobj + mobj->radius = 1; // I need the same calculation, but at the center of the mobj + hi = ( P_GetCeilingZ(mobj, front, g_tm.x, g_tm.y, linedef) < P_GetCeilingZ(mobj, back, g_tm.x, g_tm.y, linedef) ); + hi = !hi; // actually lets do a funny and flip these + mobj->radius = savedradius; + } + else + hi = ( height[FRONT] < height[BACK] ); + lo = ! hi; open->ceiling = height[lo]; @@ -609,7 +742,17 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) height[FRONT] = P_GetFloorZ(mobj, front, g_tm.x, g_tm.y, linedef); height[BACK] = P_GetFloorZ(mobj, back, g_tm.x, g_tm.y, linedef); - hi = ( height[0] < height[1] ); + if (height[FRONT] == height[BACK] && (front->f_slope || back->f_slope)) + { + fixed_t savedradius = mobj->radius; // forgive me. Perhaps it would be better to refactor these functions to take a radius of fixed_t instead? thats all they grab from the mobj + mobj->radius = 1; // I need the same calculation, but at the center of the mobj + hi = ( P_GetFloorZ(mobj, front, g_tm.x, g_tm.y, linedef) < P_GetFloorZ(mobj, back, g_tm.x, g_tm.y, linedef) ); + hi = !hi; // actually lets do a funny and flip these + mobj->radius = savedradius; + } + else + hi = ( height[FRONT] < height[BACK] ); + lo = ! hi; open->floor = height[hi]; @@ -760,261 +903,104 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) // Check for fake floors in the sector. if (front->ffloors || back->ffloors) { - ffloor_t *rover; - fixed_t delta1, delta2; - - /* yuck */ - struct - { - fixed_t ceiling; - fixed_t floor; - ffloor_t * ceilingrover; - ffloor_t * floorrover; - } fofopen[2] = { + boolean anyfrontfofs, anybackfofs; + fofopening_t fofopen[2] = { { INT32_MAX, INT32_MIN, NULL, NULL }, { INT32_MAX, INT32_MIN, NULL, NULL }, }; - // Check for frontsector's fake floors - for (rover = front->ffloors; rover; rover = rover->next) + anyfrontfofs = P_FoFOpening(front, linedef, mobj, open, &fofopen[FRONT]); + anybackfofs = P_FoFOpening(back, linedef, mobj, open, &fofopen[BACK]); + + if (anyfrontfofs || anybackfofs) // if all front and back fofs are irrelevant then skip { - fixed_t topheight, bottomheight, midheight; - - if (!(rover->fofflags & FOF_EXISTS)) - continue; - - if (P_CheckSolidFFloorSurface(mobj, rover)) - ; - else if (!((rover->fofflags & FOF_BLOCKPLAYER && mobj->player) - || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) - continue; - - if (open->fofType != LO_FOF_ANY) + if (fofopen[FRONT].ceiling == fofopen[BACK].ceiling && ((fofopen[FRONT].ceilingrover && *fofopen[FRONT].ceilingrover->b_slope) || (fofopen[BACK].ceilingrover && *fofopen[BACK].ceilingrover->b_slope))) { - topheight = P_VeryTopOfFOF(rover); - bottomheight = P_VeryBottomOfFOF(rover); + fixed_t savedradius = mobj->radius; // forgive me. Perhaps it would be better to refactor these functions to take a radius of fixed_t instead? thats all they grabn from the mobj + mobj->radius = 1; // I need the same calculation, but at the center of the mobj + fofopening_t temp[2] = { + { INT32_MAX, INT32_MIN, NULL, NULL }, + { INT32_MAX, INT32_MIN, NULL, NULL } + }; + P_FoFOpening(front, linedef, mobj, open, &temp[FRONT]); + P_FoFOpening(back, linedef, mobj, open, &temp[BACK]); + hi = ( temp[FRONT].ceiling < temp[BACK].ceiling ); + mobj->radius = savedradius; } else - { - topheight = P_GetFOFTopZ(mobj, front, rover, g_tm.x, g_tm.y, linedef); - bottomheight = P_GetFOFBottomZ(mobj, front, rover, g_tm.x, g_tm.y, linedef); - } + hi = ( fofopen[FRONT].ceiling < fofopen[BACK].ceiling ); - switch (open->fofType) - { - case LO_FOF_FLOORS: - { - if (mobj->z >= topheight) - { - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) - { - if (topheight > fofopen[FRONT].floor) - { - fofopen[FRONT].floor = topheight; - fofopen[FRONT].floorrover = rover; - } - } - } - break; - } - case LO_FOF_CEILINGS: - { - if (thingtop <= bottomheight) - { - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) - { - if (bottomheight < fofopen[FRONT].ceiling) - { - fofopen[FRONT].ceiling = bottomheight; - fofopen[FRONT].ceilingrover = rover; - } - } - } - break; - } - default: - { - midheight = bottomheight + (topheight - bottomheight) / 2; - delta1 = abs(mobj->z - midheight); - delta2 = abs(thingtop - midheight); + lo = ! hi; - if (delta1 > delta2) - { - // thing is below FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) - { - if (bottomheight < fofopen[FRONT].ceiling) - { - fofopen[FRONT].ceiling = bottomheight; - fofopen[FRONT].ceilingrover = rover; - } - } - } - else - { - // thing is above FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) - { - if (topheight > fofopen[FRONT].floor) - { - fofopen[FRONT].floor = topheight; - fofopen[FRONT].floorrover = rover; - } - } - } - break; + if (fofopen[lo].ceiling <= open->ceiling) + { + topedge[lo] = P_GetFFloorBottomZAt(fofopen[lo].ceilingrover, cross.x, cross.y); + + if (fofopen[hi].ceiling < open->ceiling) + { + topedge[hi] = P_GetFFloorBottomZAt(fofopen[hi].ceilingrover, cross.x, cross.y); + } + + open->ceiling = fofopen[lo].ceiling; + open->ceilingrover = fofopen[lo].ceilingrover; + open->ceilingslope = *fofopen[lo].ceilingrover->b_slope; + open->ceilingpic = *fofopen[lo].ceilingrover->bottompic; + open->ceilingstep = ( thingtop - topedge[lo] ); + open->ceilingdrop = ( topedge[hi] - topedge[lo] ); + + if (fofopen[hi].ceiling < open->highceiling) + { + open->highceiling = fofopen[hi].ceiling; } } - } - - // Check for backsectors fake floors - for (rover = back->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight, midheight; - - if (!(rover->fofflags & FOF_EXISTS)) - continue; - - if (P_CheckSolidFFloorSurface(mobj, rover)) - ; - else if (!((rover->fofflags & FOF_BLOCKPLAYER && mobj->player) - || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) - continue; - - if (open->fofType != LO_FOF_ANY) + else if (fofopen[lo].ceiling < open->highceiling) { - topheight = P_VeryTopOfFOF(rover); - bottomheight = P_VeryBottomOfFOF(rover); + open->highceiling = fofopen[lo].ceiling; + } + + if (fofopen[FRONT].floor == fofopen[BACK].floor && ((fofopen[FRONT].floorrover && *fofopen[FRONT].floorrover->t_slope) || (fofopen[BACK].floorrover && *fofopen[BACK].floorrover->t_slope))) + { + fixed_t savedradius = mobj->radius; // forgive me. Perhaps it would be better to refactor these functions to take a radius of fixed_t instead? thats all they grabn from the mobj + mobj->radius = 1; // I need the same calculation, but at the center of the mobj + fofopening_t temp[2] = { + { INT32_MAX, INT32_MIN, NULL, NULL }, + { INT32_MAX, INT32_MIN, NULL, NULL } + }; + P_FoFOpening(front, linedef, mobj, open, &temp[FRONT]); + P_FoFOpening(back, linedef, mobj, open, &temp[BACK]); + hi = ( temp[FRONT].ceiling < temp[BACK].ceiling ); + mobj->radius = savedradius; } else - { - topheight = P_GetFOFTopZ(mobj, back, rover, g_tm.x, g_tm.y, linedef); - bottomheight = P_GetFOFBottomZ(mobj, back, rover, g_tm.x, g_tm.y, linedef); - } + hi = ( fofopen[FRONT].floor < fofopen[BACK].floor ); - switch (open->fofType) - { - case LO_FOF_FLOORS: - { - if (mobj->z >= topheight) - { - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) - { - if (topheight > fofopen[BACK].floor) - { - fofopen[BACK].floor = topheight; - fofopen[BACK].floorrover = rover; - } - } - } - break; - } - case LO_FOF_CEILINGS: - { - if (thingtop <= bottomheight) - { - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) - { - if (bottomheight < fofopen[BACK].ceiling) - { - fofopen[BACK].ceiling = bottomheight; - fofopen[BACK].ceilingrover = rover; - } - } - } - break; - } - default: - { - midheight = bottomheight + (topheight - bottomheight) / 2; - delta1 = abs(mobj->z - midheight); - delta2 = abs(thingtop - midheight); + lo = ! hi; - if (delta1 > delta2) - { - // thing is below FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) - { - if (bottomheight < fofopen[BACK].ceiling) - { - fofopen[BACK].ceiling = bottomheight; - fofopen[BACK].ceilingrover = rover; - } - } - } - else - { - // thing is above FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) - { - if (topheight > fofopen[BACK].floor) - { - fofopen[BACK].floor = topheight; - fofopen[BACK].floorrover = rover; - } - } - } - break; + if (fofopen[hi].floor >= open->floor) + { + botedge[hi] = P_GetFFloorTopZAt(fofopen[hi].floorrover, cross.x, cross.y); + + if (fofopen[lo].floor > open->floor) + { + botedge[lo] = P_GetFFloorTopZAt(fofopen[lo].floorrover, cross.x, cross.y); + } + + open->floor = fofopen[hi].floor; + open->floorrover = fofopen[hi].floorrover; + open->floorslope = *fofopen[hi].floorrover->t_slope; + open->floorpic = *fofopen[hi].floorrover->toppic; + open->floorstep = ( botedge[hi] - mobj->z ); + open->floordrop = ( botedge[hi] - botedge[lo] ); + + if (fofopen[lo].floor > open->lowfloor) + { + open->lowfloor = fofopen[lo].floor; } } - } - - hi = ( fofopen[0].ceiling < fofopen[1].ceiling ); - lo = ! hi; - - if (fofopen[lo].ceiling <= open->ceiling) - { - topedge[lo] = P_GetFFloorBottomZAt(fofopen[lo].ceilingrover, cross.x, cross.y); - - if (fofopen[hi].ceiling < open->ceiling) + else if (fofopen[hi].floor > open->lowfloor) { - topedge[hi] = P_GetFFloorBottomZAt(fofopen[hi].ceilingrover, cross.x, cross.y); + open->lowfloor = fofopen[hi].floor; } - - open->ceiling = fofopen[lo].ceiling; - open->ceilingrover = fofopen[lo].ceilingrover; - open->ceilingslope = *fofopen[lo].ceilingrover->b_slope; - open->ceilingpic = *fofopen[lo].ceilingrover->bottompic; - open->ceilingstep = ( thingtop - topedge[lo] ); - open->ceilingdrop = ( topedge[hi] - topedge[lo] ); - - if (fofopen[hi].ceiling < open->highceiling) - { - open->highceiling = fofopen[hi].ceiling; - } - } - else if (fofopen[lo].ceiling < open->highceiling) - { - open->highceiling = fofopen[lo].ceiling; - } - - hi = ( fofopen[0].floor < fofopen[1].floor ); - lo = ! hi; - - if (fofopen[hi].floor >= open->floor) - { - botedge[hi] = P_GetFFloorTopZAt(fofopen[hi].floorrover, cross.x, cross.y); - - if (fofopen[lo].floor > open->floor) - { - botedge[lo] = P_GetFFloorTopZAt(fofopen[lo].floorrover, cross.x, cross.y); - } - - open->floor = fofopen[hi].floor; - open->floorrover = fofopen[hi].floorrover; - open->floorslope = *fofopen[hi].floorrover->t_slope; - open->floorpic = *fofopen[hi].floorrover->toppic; - open->floorstep = ( botedge[hi] - mobj->z ); - open->floordrop = ( botedge[hi] - botedge[lo] ); - - if (fofopen[lo].floor > open->lowfloor) - { - open->lowfloor = fofopen[lo].floor; - } - } - else if (fofopen[hi].floor > open->lowfloor) - { - open->lowfloor = fofopen[hi].floor; } } } diff --git a/src/p_maputl.h b/src/p_maputl.h index 6ee7f91aa..f4d998184 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -48,6 +48,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, #define P_AproxDistance(dx, dy) FixedHypot(dx, dy) void P_ClosestPointOnLine(fixed_t x, fixed_t y, const line_t *line, vertex_t *result); +void P_ClosestPointOnLineWithinLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result); void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result); INT32 P_PointOnLineSide(fixed_t x, fixed_t y, const line_t *line); void P_MakeDivline(const line_t *li, divline_t *dl); @@ -74,10 +75,19 @@ struct opening_t UINT8 fofType; // LO_FOF_ types for forcing FOF collide }; +struct fofopening_t +{ + fixed_t ceiling; + fixed_t floor; + ffloor_t * ceilingrover; + ffloor_t * floorrover; +}; + #define LO_FOF_ANY (0) #define LO_FOF_FLOORS (1) #define LO_FOF_CEILINGS (2) +boolean P_FoFOpening(sector_t *sector, line_t *linedef, mobj_t *mobj, opening_t *open, fofopening_t *fofopen); void P_LineOpening(line_t *plinedef, mobj_t *mobj, opening_t *open); typedef enum diff --git a/src/p_mobj.c b/src/p_mobj.c index 785f9f6a1..1b56232a4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1613,8 +1613,9 @@ boolean P_XYMovement(mobj_t *mo) boolean moved; pslope_t *oldslope = NULL; vector3_t slopemom = {0,0,0}; - fixed_t predictedz = 0; + fixed_t predictedz = INT32_MAX; // Need a sentinel value TryMoveResult_t result = {0}; + fixed_t momentumzdelta = INT32_MAX; I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -1650,11 +1651,13 @@ boolean P_XYMovement(mobj_t *mo) } // adjust various things based on slope - if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) + if (mo->standingslope && mo->standingslope->zdelta != 0) { if (!P_IsObjectOnGround(mo)) { // We fell off at some point? Do the twisty thing! + // if (mo->player) + // CONS_Printf("Twisty thing launch?\n"); P_SlopeLaunch(mo); xmove = mo->momx; ymove = mo->momy; @@ -1670,9 +1673,16 @@ boolean P_XYMovement(mobj_t *mo) xmove = slopemom.x; ymove = slopemom.y; - predictedz = mo->z + slopemom.z; // We'll use this later... - + momentumzdelta = FixedDiv(slopemom.z, FixedHypot(xmove, ymove)); // so this lets us know what the zdelta is for the vector the player is travelling along, in addition to the slope's zdelta in its xydirection oldslope = mo->standingslope; + + // if (mo->player) + // CONS_Printf("%s zdelta %d momzdelta %d\n",player_names[mo->player-players], mo->standingslope->zdelta, momentumzdelta); + if (abs(momentumzdelta) >= FRACUNIT/6) + predictedz = mo->z + slopemom.z; + else + predictedz = mo->z; + } } else if (P_IsObjectOnGround(mo) && !mo->momz) predictedz = mo->z; @@ -1752,7 +1762,7 @@ boolean P_XYMovement(mobj_t *mo) // Wall transfer part 1. pslope_t *transferslope = NULL; fixed_t transfermomz = 0; - if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls + if (oldslope && (P_MobjFlip(mo)*slopemom.z > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls { transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. @@ -1906,27 +1916,34 @@ boolean P_XYMovement(mobj_t *mo) mo->standingslope = oldslope; P_SetPitchRollFromSlope(mo, mo->standingslope); P_SlopeLaunch(mo); - - //CONS_Printf("launched off of slope - "); + if (mo->player) + CONS_Printf("%s Slope change launch old angle %f - new angle %f = %f\n", + player_names[mo->player-players], + FIXED_TO_FLOAT(AngleFixed(oldangle)), + FIXED_TO_FLOAT(AngleFixed(newangle)), + FIXED_TO_FLOAT(AngleFixed(oldangle-newangle)) + ); } - - /* - CONS_Printf("old angle %f - new angle %f = %f\n", - FIXED_TO_FLOAT(AngleFixed(oldangle)), - FIXED_TO_FLOAT(AngleFixed(newangle)), - FIXED_TO_FLOAT(AngleFixed(oldangle-newangle)) - ); - */ - } - else if (predictedz - mo->z > abs(slopemom.z / 2)) + else { - // Now check if we were supposed to stick to this slope - //CONS_Printf("%d-%d > %d\n", (predictedz), (mo->z), (slopemom.z/2)); - P_SlopeLaunch(mo); + // if (mo->player) + // CONS_Printf("Ramp Launch %d %d+%d > 0 && %d-%d > %d ", mo->scale, FixedDiv(slopemom.z, mo->scale), P_GetMobjGravity(mo)*24, predictedz, mo->z, slopemom.z/2); + if ( // If slope aligned momz is more than gravity, and mobj clipped along ramp edge instead of following slope plane, then launch + ( !(mo->eflags & MFE_VERTICALFLIP) && FixedDiv(slopemom.z, mo->scale) + P_GetMobjGravity(mo)*24 > 0 && predictedz - mo->z > slopemom.z*4/5 ) + || ( (mo->eflags & MFE_VERTICALFLIP) && FixedDiv(slopemom.z, mo->scale) + P_GetMobjGravity(mo)*24 < 0 && predictedz - mo->z < slopemom.z*4/5 ) + ) + { + if (mo->player) + CONS_Printf("%s Ramp Launch %d %d %d+%d > 0 && %d-%d > %d True\n", player_names[mo->player-players], mo->scale, momentumzdelta, FixedDiv(slopemom.z, mo->scale), P_GetMobjGravity(mo)*24, predictedz, mo->z, slopemom.z*4/5); + P_SlopeLaunch(mo); + } + // else + // if (mo->player) + // CONS_Printf("False\n"); } } - else if (moved && mo->standingslope && predictedz) + else if (moved && mo->standingslope && predictedz != INT32_MAX) // Predicted z must be changed { angle_t moveangle = K_MomentumAngle(mo); angle_t newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT)); @@ -2264,7 +2281,11 @@ boolean P_ZMovement(mobj_t *mo) if (mo->flags & MF_NOCLIPHEIGHT) mo->standingslope = NULL; else if (!onground) + { + if (mo->player) + // CONS_Printf("ZMovement launch?\n"); P_SlopeLaunch(mo); + } } switch (mo->type) @@ -2798,6 +2819,20 @@ void P_PlayerZMovement(mobj_t *mo) mo->eflags &= ~MFE_APPLYPMOMZ; } + if (mo->eflags & MFE_JUSTSTEPPEDDOWN && abs(mo->momz) > 1) + { + CONS_Printf("%s Check Step up momz reset %d < %d + %d", player_names[mo->player-players], abs(mo->momz), P_GetThingStepUp(mo, mo->x, mo->y)/6, abs(P_GetMobjGravity(mo)*3)); + if (abs(mo->momz) < P_GetThingStepUp(mo, mo->x, mo->y)/6 + abs(P_GetMobjGravity(mo)*3)) + { + CONS_Printf(" True\n"); + mo->momz = 0; + } + else + { + CONS_Printf(" False\n"); + } + } + mo->z += mo->momz; onground = P_IsObjectOnGround(mo); @@ -2811,7 +2846,11 @@ void P_PlayerZMovement(mobj_t *mo) if (mo->flags & MF_NOCLIPHEIGHT) mo->standingslope = NULL; else if (!onground) + { + CONS_Printf("%s PlayerZMovement launch %d ", player_names[mo->player-players], mo->momz); P_SlopeLaunch(mo); + CONS_Printf("%d\n", mo->momz); + } } // clip movement diff --git a/src/typedef.h b/src/typedef.h index a46b50eb1..31fe9f698 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -301,6 +301,7 @@ TYPEDEF (BasicFF_t); TYPEDEF (divline_t); TYPEDEF (intercept_t); TYPEDEF (opening_t); +TYPEDEF (fofopening_t); // p_mobj.h TYPEDEF (mobj_t);