From b72b8f354e0ea8513379b72a4bb7847f01816907 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 May 2023 19:48:08 -0400 Subject: [PATCH 01/12] lowfloor/highceiling respects FOFs properly Found while working on bot changes to respect step-up, lowfloor would occasionally be the floor below instead of the FOF. Also code cleanup to remove redundant / unused stuff. --- src/p_maputl.c | 162 +++++++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 65 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 1a73ccea9..5750dc03d 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -745,7 +745,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (linedef->polyobj->flags & POF_TESTHEIGHT) { const sector_t *polysec = linedef->backsector; - fixed_t polytop, polybottom; + fixed_t polytop, polybottom, polymid; fixed_t delta1, delta2; if (linedef->polyobj->flags & POF_CLIPPLANES) @@ -759,25 +759,32 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) polybottom = INT32_MIN; } - delta1 = abs(mobj->z - (polybottom + ((polytop - polybottom)/2))); - delta2 = abs(thingtop - (polybottom + ((polytop - polybottom)/2))); + polymid = polybottom + (polytop - polybottom) / 2; + delta1 = abs(mobj->z - polymid); + delta2 = abs(thingtop - polymid); - if (polybottom < opentop && delta1 >= delta2) + if (delta1 >= delta2) { - opentop = polybottom; - } - else if (polybottom < highceiling && delta1 >= delta2) - { - highceiling = polybottom; + if (polybottom < opentop) + { + opentop = polybottom; + } + else if (polybottom < highceiling) + { + highceiling = polybottom; + } } - if (polytop > openbottom && delta1 < delta2) + if (delta1 <= delta2) { - openbottom = polytop; - } - else if (polytop > lowfloor && delta1 < delta2) - { - lowfloor = polytop; + if (polytop > openbottom) + { + openbottom = polytop; + } + else if (polytop > lowfloor) + { + lowfloor = polytop; + } } } // otherwise don't do anything special, pretend there's nothing else there @@ -802,13 +809,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) { INT32_MAX, INT32_MIN, NULL, NULL }, }; - const fixed_t oldopentop = opentop; - const fixed_t oldopenbottom = openbottom; - // Check for frontsector's fake floors for (rover = front->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; + fixed_t topheight, bottomheight, midheight; + if (!(rover->fofflags & FOF_EXISTS)) continue; @@ -821,38 +826,42 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) topheight = P_GetFOFTopZ(mobj, front, rover, tm.x, tm.y, linedef); bottomheight = P_GetFOFBottomZ(mobj, front, rover, tm.x, tm.y, linedef); - delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + midheight = bottomheight + (topheight - bottomheight) / 2; + delta1 = abs(mobj->z - midheight); + delta2 = abs(thingtop - midheight); - if (delta1 >= delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) // thing is below FOF + if (delta1 >= delta2) { - if (bottomheight < open[FRONT].top) { - open[FRONT].top = bottomheight; - opentopslope = *rover->b_slope; - opentoppic = *rover->bottompic; - open[FRONT].ceilingrover = rover; + // thing is below FOF + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) + { + if (bottomheight < open[FRONT].top) + { + open[FRONT].top = bottomheight; + open[FRONT].ceilingrover = rover; + } } - else if (bottomheight < highceiling) - highceiling = bottomheight; } - if (delta1 < delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) // thing is above FOF + if (delta1 <= delta2) { - if (topheight > open[FRONT].bottom) { - open[FRONT].bottom = topheight; - openbottomslope = *rover->t_slope; - openbottompic = *rover->toppic; - open[FRONT].floorrover = rover; + // thing is above FOF + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) + { + if (topheight > open[FRONT].bottom) + { + open[FRONT].bottom = topheight; + open[FRONT].floorrover = rover; + } } - else if (topheight > lowfloor) - lowfloor = topheight; } } // Check for backsectors fake floors for (rover = back->ffloors; rover; rover = rover->next) { - fixed_t topheight, bottomheight; + fixed_t topheight, bottomheight, midheight; + if (!(rover->fofflags & FOF_EXISTS)) continue; @@ -865,70 +874,93 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) topheight = P_GetFOFTopZ(mobj, back, rover, tm.x, tm.y, linedef); bottomheight = P_GetFOFBottomZ(mobj, back, rover, tm.x, tm.y, linedef); - delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + midheight = bottomheight + (topheight - bottomheight) / 2; + delta1 = abs(mobj->z - midheight); + delta2 = abs(thingtop - midheight); - if (delta1 >= delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) // thing is below FOF + if (delta1 >= delta2) { - if (bottomheight < open[BACK].top) { - open[BACK].top = bottomheight; - opentopslope = *rover->b_slope; - opentoppic = *rover->bottompic; - open[BACK].ceilingrover = rover; + // thing is below FOF + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) + { + if (bottomheight < open[BACK].top) + { + open[BACK].top = bottomheight; + open[BACK].ceilingrover = rover; + } } - else if (bottomheight < highceiling) - highceiling = bottomheight; } - if (delta1 < delta2 && (rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) // thing is above FOF + if (delta1 <= delta2) { - if (topheight > open[BACK].bottom) { - open[BACK].bottom = topheight; - openbottomslope = *rover->t_slope; - openbottompic = *rover->toppic; - open[BACK].floorrover = rover; + // thing is above FOF + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) + { + if (topheight > open[BACK].bottom) + { + open[BACK].bottom = topheight; + open[BACK].floorrover = rover; + } } - else if (topheight > lowfloor) - lowfloor = topheight; } } - lo = ( open[0].top > open[1].top ); + hi = ( open[0].top < open[1].top ); + lo = ! hi; - if (open[lo].top <= oldopentop) + if (open[lo].top <= opentop) { - hi = ! lo; - topedge[lo] = P_GetFFloorBottomZAt(open[lo].ceilingrover, cross.x, cross.y); - if (open[hi].top < oldopentop) + if (open[hi].top < opentop) { topedge[hi] = P_GetFFloorBottomZAt(open[hi].ceilingrover, cross.x, cross.y); } opentop = open[lo].top; openceilingrover = open[lo].ceilingrover; + opentopslope = *open[lo].ceilingrover->b_slope; + opentoppic = *open[lo].ceilingrover->bottompic; openceilingstep = ( thingtop - topedge[lo] ); openceilingdrop = ( topedge[hi] - topedge[lo] ); + + if (open[hi].top < highceiling) + { + highceiling = open[hi].top; + } + } + else if (open[lo].top < highceiling) + { + highceiling = open[lo].top; } hi = ( open[0].bottom < open[1].bottom ); + lo = ! hi; - if (open[hi].bottom >= oldopenbottom) + if (open[hi].bottom >= openbottom) { - lo = ! hi; - botedge[hi] = P_GetFFloorTopZAt(open[hi].floorrover, cross.x, cross.y); - if (open[lo].bottom > oldopenbottom) + if (open[lo].bottom > openbottom) { botedge[lo] = P_GetFFloorTopZAt(open[lo].floorrover, cross.x, cross.y); } openbottom = open[hi].bottom; openfloorrover = open[hi].floorrover; + openbottomslope = *open[hi].floorrover->t_slope; + openbottompic = *open[hi].floorrover->toppic; openfloorstep = ( botedge[hi] - mobj->z ); openfloordrop = ( botedge[hi] - botedge[lo] ); + + if (open[lo].top > lowfloor) + { + lowfloor = open[lo].top; + } + } + else if (open[hi].top > lowfloor) + { + lowfloor = open[hi].top; } } } From 3450a0126f3ece75cc07edfcee9debbb53cae27f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 May 2023 19:52:40 -0400 Subject: [PATCH 02/12] Bot traversal wall detection improved, and waypoints do it too --- src/p_sight.c | 81 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/src/p_sight.c b/src/p_sight.c index 785f4248a..a516a288b 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -360,7 +360,10 @@ static boolean P_CanTraceBlockingLine(seg_t *seg, divline_t *divl, register los_ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los) { + const boolean flip = ((los->t1->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); line_t *line = seg->linedef; + fixed_t frac = 0; + boolean canStepUp, canDropOff; fixed_t maxstep = 0; if (P_CanTraceBlockingLine(seg, divl, los) == false) @@ -369,45 +372,57 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los return false; } + // calculate fractional intercept (how far along we are divided by how far we are from t2) + frac = P_InterceptVector2(&los->strace, divl); + + // calculate position at intercept + tm.x = los->strace.x + FixedMul(los->strace.dx, frac); + tm.y = los->strace.y + FixedMul(los->strace.dy, frac); + // set openrange, opentop, openbottom - tm.x = los->t1->x; - tm.y = los->t1->y; P_LineOpening(line, los->t1); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); - if ((openrange < los->t1->height) // doesn't fit - || (opentop - los->t1->z < los->t1->height) // mobj is too high - || (openbottom - los->t1->z > maxstep)) // too big a step up + if (openrange < los->t1->height) { - // This line situationally blocks us + // Can't fit return false; } - if (los->t1->player != NULL && los->alreadyHates == false) + canStepUp = ((flip ? (highceiling - opentop) : (openbottom - lowfloor)) <= maxstep); + canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); + + if (canStepUp || canDropOff) { - // Treat damage sectors like walls, if you're not already in a bad sector. - sector_t *front, *back; - vertex_t pos; - - P_ClosestPointOnLine(tm.x, tm.y, line, &pos); - - front = seg->frontsector; - back = seg->backsector; - - if (K_BotHatesThisSector(los->t1->player, front, pos.x, pos.y) - || K_BotHatesThisSector(los->t1->player, back, pos.x, pos.y)) + if (los->t1->player != NULL && los->alreadyHates == false) { - // This line does not block us, but we don't want to be in it. - return false; + // Treat damage sectors like walls, if you're not already in a bad sector. + sector_t *front, *back; + + front = seg->frontsector; + back = seg->backsector; + + if (K_BotHatesThisSector(los->t1->player, front, tm.x, tm.y) + || K_BotHatesThisSector(los->t1->player, back, tm.x, tm.y)) + { + // This line does not block us, but we don't want to be in it. + return false; + } } + + return true; } - return true; + return false; } static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t *los) { + const boolean flip = ((los->t1->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); line_t *line = seg->linedef; + fixed_t frac = 0; + boolean canStepUp, canDropOff; + fixed_t maxstep = 0; if (P_CanTraceBlockingLine(seg, divl, los) == false) { @@ -422,7 +437,29 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t return false; } - return true; + // calculate fractional intercept (how far along we are divided by how far we are from t2) + frac = P_InterceptVector2(&los->strace, divl); + + // calculate position at intercept + tm.x = los->strace.x + FixedMul(los->strace.dx, frac); + tm.y = los->strace.y + FixedMul(los->strace.dy, frac); + + P_LineOpening(line, los->t1); + maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); + + if (openrange < los->t1->height) + { + // Can't fit + return false; + } + + // If we can step up... + canStepUp = ((flip ? (highceiling - opentop) : (openbottom - lowfloor)) <= maxstep); + + // Or if we're on the higher side... + canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); + + return (canStepUp || canDropOff); } // From d12942238285f79988367b7922499fe80713ff2d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 May 2023 19:55:41 -0400 Subject: [PATCH 03/12] Bots can now see TERRAIN-based offroad / damage --- src/k_botsearch.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/k_botsearch.c b/src/k_botsearch.c index f619035e9..1dd3132b1 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -142,16 +142,33 @@ UINT8 K_EggboxStealth(fixed_t x, fixed_t y) Return:- true if avoiding this sector special, false otherwise. --------------------------------------------------*/ -static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) +static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec, const boolean flip) { - if (sec->damagetype != SD_NONE) - { - return true; - } + terrain_t *terrain = K_GetTerrainForFlatNum(flip ? sec->ceilingpic : sec->floorpic); - if (sec->offroad > 0) + if (terrain != NULL) { - return !K_BotCanTakeCut(player); + if (terrain->damageType != SD_NONE) + { + return true; + } + + if (terrain->offroad > 0) + { + return !K_BotCanTakeCut(player); + } + } + else + { + if (sec->damagetype != SD_NONE) + { + return true; + } + + if (sec->offroad > 0) + { + return !K_BotCanTakeCut(player); + } } return false; @@ -200,7 +217,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t if (!(rover->fofflags & FOF_BLOCKPLAYER)) { if ((top >= player->mo->z) && (bottom <= player->mo->z + player->mo->height) - && K_BotHatesThisSectorsSpecial(player, rover->master->frontsector)) + && K_BotHatesThisSectorsSpecial(player, rover->master->frontsector, flip)) { // Bad intangible sector at our height, so we DEFINITELY want to avoid return true; @@ -236,7 +253,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t return false; } - return K_BotHatesThisSectorsSpecial(player, bestsector); + return K_BotHatesThisSectorsSpecial(player, bestsector, flip); } /*-------------------------------------------------- From a2c57d706634ee86e569f7cc5ded8f215c1ff712 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 May 2023 20:27:11 -0400 Subject: [PATCH 04/12] Fix bot extra friction on ice TERRAIN --- src/k_kart.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ccd006e83..9685280b2 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10224,22 +10224,23 @@ static void K_AirFailsafe(player_t *player) // fixed_t K_PlayerBaseFriction(player_t *player, fixed_t original) { + const fixed_t factor = FixedDiv(FRACUNIT - original, FRACUNIT - ORIG_FRICTION); fixed_t frict = original; if (K_PodiumSequence() == true) { - frict -= FRACUNIT >> 4; + frict -= FixedMul(FRACUNIT >> 4, factor); } else if (K_PlayerUsesBotMovement(player) == true) { // A bit extra friction to help them without drifting. // Remove this line once they can drift. - frict -= FRACUNIT >> 5; + frict -= FixedMul(FRACUNIT >> 5, factor); // Bots gain more traction as they rubberband. if (player->botvars.rubberband > FRACUNIT) { - static const fixed_t extraFriction = FRACUNIT >> 5; + const fixed_t extraFriction = FixedMul(FRACUNIT >> 5, factor); const fixed_t mul = player->botvars.rubberband - FRACUNIT; frict -= FixedMul(extraFriction, mul); } From 7d4720b1a688900200a12152b689f746d3137a98 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 May 2023 20:28:42 -0400 Subject: [PATCH 05/12] Fix bot rubberband being different per map scale --- src/k_bot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 3e490031a..be22c6a29 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -439,7 +439,7 @@ static line_t *K_FindBotController(mobj_t *mo) --------------------------------------------------*/ static UINT32 K_BotRubberbandDistance(player_t *player) { - const UINT32 spacing = FixedDiv(640 * FRACUNIT, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; + const UINT32 spacing = FixedDiv(640 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; const UINT8 portpriority = player - players; UINT8 pos = 0; UINT8 i; From a8af5b7616830262218775f0f2a82f81c83f8c65 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 10 May 2023 22:25:24 -0400 Subject: [PATCH 06/12] Improve general bot handling - Their waypoint radius gets thinner quicker - Waypoint distance is scaled with each ones' floor slope, instead of done once at the end of the prediction. - Prediction is pulled back further when it goes through a wall - Prediction starts earlier and goes less far - Bots will brake at shallower angles (allows them to brake-turn more often) - K_AddDodgeObject and K_AddAttackObject now adjust based on the radius of the object - Fixed K_AddDodgeObject adding to the goto objects instead of avoid objects - Optimized blockmap search size for K_FindObjectsForNudging - Current waypoint is no longer cleared each frame --- src/k_bot.c | 117 +++++++++++++++++++++++++--------------------- src/k_botsearch.c | 77 +++++++++++++++++++++++------- src/k_kart.c | 7 ++- 3 files changed, 129 insertions(+), 72 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index be22c6a29..bcf5619d6 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -639,7 +639,7 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) { static const fixed_t maxReduce = FRACUNIT/32; - static const angle_t maxDelta = ANGLE_45; + static const angle_t maxDelta = ANGLE_22h; fixed_t radius = waypoint->mobj->radius; fixed_t reduce = FRACUNIT; @@ -678,6 +678,35 @@ static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) return FixedMul(radius, reduce); } +static fixed_t K_ScaleWPDistWithSlope(fixed_t disttonext, angle_t angletonext, const pslope_t *slope, SINT8 flip) +{ + if (slope == NULL) + { + return disttonext; + } + + if ((slope->flags & SL_NOPHYSICS) == 0 && abs(slope->zdelta) >= FRACUNIT/21) + { + // Displace the prediction to go with the slope physics. + fixed_t slopeMul = FRACUNIT; + angle_t angle = angletonext - slope->xydirection; + + if (flip * slope->zdelta < 0) + { + angle ^= ANGLE_180; + } + + // Going uphill: 0 + // Going downhill: FRACUNIT*2 + slopeMul = FRACUNIT + FINECOSINE(angle >> ANGLETOFINESHIFT); + + // Range: 0.25 to 1.75 + return FixedMul(disttonext, (FRACUNIT >> 2) + ((slopeMul * 3) >> 2)); + } + + return disttonext; +} + /*-------------------------------------------------- static botprediction_t *K_CreateBotPrediction(player_t *player) @@ -701,8 +730,8 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const tic_t futuresight = (TICRATE * KART_FULLTURN) / max(1, handling); // How far ahead into the future to try and predict const fixed_t speed = K_BotSpeedScaled(player, P_AproxDistance(player->mo->momx, player->mo->momy)); - const INT32 startDist = (DEFAULT_WAYPOINT_RADIUS * 2 * mapobjectscale) / FRACUNIT; - const INT32 maxDist = startDist * 4; // This function gets very laggy when it goes far distances, and going too far isn't very helpful anyway. + const INT32 startDist = 0; //(DEFAULT_WAYPOINT_RADIUS * mapobjectscale) / FRACUNIT; + const INT32 maxDist = (DEFAULT_WAYPOINT_RADIUS * 3 * mapobjectscale) / FRACUNIT; // This function gets very laggy when it goes far distances, and going too far isn't very helpful anyway. const INT32 distance = min(((speed / FRACUNIT) * (INT32)futuresight) + startDist, maxDist); // Halves radius when encountering a wall on your way to your destination. @@ -712,6 +741,8 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) fixed_t smallestradius = INT32_MAX; angle_t angletonext = ANGLE_MAX; INT32 disttonext = INT32_MAX; + INT32 distscaled = INT32_MAX; + pslope_t *nextslope = player->mo->standingslope; waypoint_t *wp = player->nextwaypoint; mobj_t *prevwpmobj = player->mo; @@ -721,15 +752,25 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) boolean pathfindsuccess = false; path_t pathtofinish = {0}; - botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); + botprediction_t *predict = NULL; size_t i; + if (wp == NULL || P_MobjWasRemoved(wp->mobj) == true) + { + // Can't do any of this if we don't have a waypoint. + return NULL; + } + + predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); + // Init defaults in case of pathfind failure angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y); - disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT; + disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y); + nextslope = wp->mobj->standingslope; + distscaled = K_ScaleWPDistWithSlope(disttonext, angletonext, nextslope, P_MobjFlip(wp->mobj)) / FRACUNIT; pathfindsuccess = K_PathfindThruCircuit( - player->nextwaypoint, (unsigned)distanceleft, + wp, (unsigned)distanceleft, &pathtofinish, useshortcuts, huntbackwards ); @@ -753,12 +794,14 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) } angletonext = R_PointToAngle2(prevwpmobj->x, prevwpmobj->y, wp->mobj->x, wp->mobj->y); - disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT; + disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y); + nextslope = wp->mobj->standingslope; + distscaled = K_ScaleWPDistWithSlope(disttonext, angletonext, nextslope, P_MobjFlip(wp->mobj)) / FRACUNIT; if (P_TraceBotTraversal(player->mo, wp->mobj) == false) { - // If we can't get a direct path to this waypoint, predict less. - distanceleft /= 2; + // If we can't get a direct path to this waypoint, reduce our prediction drastically. + distscaled *= 4; radreduce = FRACUNIT >> 1; } @@ -768,7 +811,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) smallestradius = radius; } - distanceleft -= disttonext; + distanceleft -= distscaled; if (distanceleft <= 0) { @@ -794,25 +837,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); } - if (player->mo->standingslope != NULL) - { - const pslope_t *slope = player->mo->standingslope; - - if (!(slope->flags & SL_NOPHYSICS) && abs(slope->zdelta) >= FRACUNIT/21) - { - // Displace the prediction to go against the slope physics. - angle_t angle = slope->xydirection; - - if (P_MobjFlip(player->mo) * slope->zdelta < 0) - { - angle ^= ANGLE_180; - } - - predict->x -= P_ReturnThrustX(NULL, angle, startDist * abs(slope->zdelta)); - predict->y -= P_ReturnThrustY(NULL, angle, startDist * abs(slope->zdelta)); - } - } - ps_bots[player - players].prediction += I_GetPreciseTime() - time; return predict; } @@ -1109,7 +1133,7 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * anglediff = abs(anglediff); turnamt = KART_FULLTURN * turnsign; - if (anglediff > ANGLE_90) + if (anglediff > ANGLE_67h) { // Wrong way! cmd->forwardmove = -MAXPLMOVE; @@ -1502,18 +1526,13 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (predict == NULL) { // Create a prediction. - if (player->nextwaypoint != NULL - && player->nextwaypoint->mobj != NULL - && !P_MobjWasRemoved(player->nextwaypoint->mobj)) - { - predict = K_CreateBotPrediction(player); - K_NudgePredictionTowardsObjects(predict, player); - destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); - } + predict = K_CreateBotPrediction(player); } if (predict != NULL) { + K_NudgePredictionTowardsObjects(predict, player); + destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); turnamt = K_HandleBotTrack(player, cmd, predict, destangle); } cmd->buttons &= ~(BT_ACCELERATE|BT_BRAKE); @@ -1539,18 +1558,13 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (predict == NULL) { // Create a prediction. - if (player->nextwaypoint != NULL - && player->nextwaypoint->mobj != NULL - && !P_MobjWasRemoved(player->nextwaypoint->mobj)) - { - predict = K_CreateBotPrediction(player); - K_NudgePredictionTowardsObjects(predict, player); - destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); - } + predict = K_CreateBotPrediction(player); } if (predict != NULL) { + K_NudgePredictionTowardsObjects(predict, player); + destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); turnamt = K_HandleBotTrack(player, cmd, predict, destangle); } } @@ -1561,18 +1575,13 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (predict == NULL) { // Create a prediction. - if (player->nextwaypoint != NULL - && player->nextwaypoint->mobj != NULL - && !P_MobjWasRemoved(player->nextwaypoint->mobj)) - { - predict = K_CreateBotPrediction(player); - K_NudgePredictionTowardsObjects(predict, player); - destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); - } + predict = K_CreateBotPrediction(player); } if (predict != NULL) { + K_NudgePredictionTowardsObjects(predict, player); + destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); turnamt = K_HandleBotTrack(player, cmd, predict, destangle); } } diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 1dd3132b1..cdb818730 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -271,6 +271,8 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t --------------------------------------------------*/ static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) { + fixed_t x, y; + angle_t a, dir; UINT8 i; I_Assert(side <= 1); @@ -280,10 +282,21 @@ static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) return; } + x = thing->x; + y = thing->y; + a = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, x, y); + + dir = a + (side ? -ANGLE_90 : ANGLE_90); + x += FixedMul(thing->radius, FINECOSINE(dir >> ANGLETOFINESHIFT)); + y += FixedMul(thing->radius, FINESINE(dir >> ANGLETOFINESHIFT)); + + x /= mapobjectscale; + y /= mapobjectscale; + for (i = 0; i < weight; i++) { - globalsmuggle.gotoAvgX[side] += thing->x / mapobjectscale; - globalsmuggle.gotoAvgY[side] += thing->y / mapobjectscale; + globalsmuggle.gotoAvgX[side] += x; + globalsmuggle.gotoAvgY[side] += y; globalsmuggle.gotoObjs[side]++; } } @@ -303,6 +316,8 @@ static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) --------------------------------------------------*/ static void K_AddDodgeObject(mobj_t *thing, UINT8 side, UINT8 weight) { + fixed_t x, y; + angle_t a, dir; UINT8 i; I_Assert(side <= 1); @@ -312,11 +327,22 @@ static void K_AddDodgeObject(mobj_t *thing, UINT8 side, UINT8 weight) return; } + x = thing->x; + y = thing->y; + a = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, x, y); + + dir = a + (side ? -ANGLE_90 : ANGLE_90); + x += FixedMul(thing->radius, FINECOSINE(dir >> ANGLETOFINESHIFT)); + y += FixedMul(thing->radius, FINESINE(dir >> ANGLETOFINESHIFT)); + + x /= mapobjectscale; + y /= mapobjectscale; + for (i = 0; i < weight; i++) { - globalsmuggle.gotoAvgX[side] += thing->x / mapobjectscale; - globalsmuggle.gotoAvgY[side] += thing->y / mapobjectscale; - globalsmuggle.gotoObjs[side]++; + globalsmuggle.avoidAvgX[side] += x; + globalsmuggle.avoidAvgY[side] += y; + globalsmuggle.avoidObjs[side]++; } } @@ -366,7 +392,7 @@ static boolean K_PlayerAttackSteer(mobj_t *thing, UINT8 side, UINT8 weight, bool --------------------------------------------------*/ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) { - INT16 anglediff; + INT16 angledelta, anglediff; fixed_t fulldist; angle_t destangle, angle, predictangle; UINT8 side = 0; @@ -404,15 +430,15 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) if (angle < ANGLE_180) { - anglediff = AngleFixed(angle)>>FRACBITS; + angledelta = AngleFixed(angle)>>FRACBITS; } else { - anglediff = 360-(AngleFixed(angle)>>FRACBITS); + angledelta = 360-(AngleFixed(angle)>>FRACBITS); side = 1; } - anglediff = abs(anglediff); + anglediff = abs(angledelta); switch (thing->type) { @@ -638,23 +664,40 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) INT32 xl, xh, yl, yh, bx, by; - fixed_t distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); + fixed_t distToPredict = 0; + angle_t angleToPredict = 0; fixed_t avgX = 0, avgY = 0; fixed_t avgDist = 0; - const fixed_t baseNudge = predict->radius; - fixed_t maxNudge = distToPredict; + fixed_t baseNudge = 0; + fixed_t maxNudge = 0; fixed_t nudgeDist = 0; angle_t nudgeDir = 0; SINT8 gotoSide = -1; UINT8 i; + if (predict == NULL) + { + ps_bots[player - players].nudge += I_GetPreciseTime() - time; + return; + } + + distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); + angleToPredict = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); + + globalsmuggle.distancetocheck = distToPredict >> 1; + + baseNudge = predict->radius * 2; + maxNudge = distToPredict; + globalsmuggle.botmo = player->mo; globalsmuggle.predict = predict; - globalsmuggle.distancetocheck = distToPredict; + // silly variable reuse + avgX = globalsmuggle.botmo->x + FixedMul(globalsmuggle.distancetocheck, FINECOSINE(angleToPredict >> ANGLETOFINESHIFT)); + avgY = globalsmuggle.botmo->y + FixedMul(globalsmuggle.distancetocheck, FINESINE(angleToPredict >> ANGLETOFINESHIFT)); for (i = 0; i < 2; i++) { @@ -665,10 +708,10 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) globalsmuggle.avoidObjs[i] = 0; } - xl = (unsigned)(globalsmuggle.botmo->x - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(globalsmuggle.botmo->x + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(globalsmuggle.botmo->y - globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(globalsmuggle.botmo->y + globalsmuggle.distancetocheck - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(avgX - (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(avgX + (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(avgY - (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(avgY + (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); diff --git a/src/k_kart.c b/src/k_kart.c index 9685280b2..c6bac7c57 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8352,7 +8352,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) boolean updaterespawn = false; // Our current waypoint. - player->currentwaypoint = bestwaypoint = waypoint; + bestwaypoint = waypoint; + + if (bestwaypoint != NULL) + { + player->currentwaypoint = bestwaypoint; + } // check the waypoint's location in relation to the player // If it's generally in front, it's fine, otherwise, use the best next/previous waypoint. From 66f0c7c9f011f81f6a6904456a1dd6d882e3a25f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 12 May 2023 23:10:56 -0400 Subject: [PATCH 07/12] Fix waypoint traversal with slopes --- src/p_maputl.c | 46 ++++++++++++++++++++-------------------------- src/p_sight.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 5750dc03d..0693c20b3 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -607,10 +607,20 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) int hi = 0; int lo = 0; + // set these defaults so that polyobjects don't interfere with collision above or below them + opentop = highceiling = INT32_MAX; + openbottom = lowfloor = INT32_MIN; + openrange = 0; + opentopslope = openbottomslope = NULL; + opentoppic = openbottompic = -1; + openceilingstep = 0; + openceilingdrop = 0; + openfloorstep = 0; + openfloordrop = 0; + if (linedef->sidenum[1] == 0xffff) { // single sided line - openrange = 0; return; } @@ -637,22 +647,9 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) } openfloorrover = openceilingrover = NULL; - if (linedef->polyobj) + if (!linedef->polyobj) { - // set these defaults so that polyobjects don't interfere with collision above or below them - opentop = INT32_MAX; - openbottom = INT32_MIN; - highceiling = INT32_MIN; - lowfloor = INT32_MAX; - opentopslope = openbottomslope = NULL; - opentoppic = openbottompic = -1; - openceilingstep = 0; - openceilingdrop = 0; - openfloorstep = 0; - openfloordrop = 0; - } - else - { // Set open and high/low values here + // Set open and high/low values here fixed_t height[2]; const sector_t * sector[2] = { front, back }; @@ -774,8 +771,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) highceiling = polybottom; } } - - if (delta1 <= delta2) + else { if (polytop > openbottom) { @@ -842,8 +838,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) } } } - - if (delta1 <= delta2) + else { // thing is above FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) @@ -890,8 +885,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) } } } - - if (delta1 <= delta2) + else { // thing is above FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) @@ -953,14 +947,14 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) openfloorstep = ( botedge[hi] - mobj->z ); openfloordrop = ( botedge[hi] - botedge[lo] ); - if (open[lo].top > lowfloor) + if (open[lo].bottom > lowfloor) { - lowfloor = open[lo].top; + lowfloor = open[lo].bottom; } } - else if (open[hi].top > lowfloor) + else if (open[hi].bottom > lowfloor) { - lowfloor = open[hi].top; + lowfloor = open[hi].bottom; } } } diff --git a/src/p_sight.c b/src/p_sight.c index a516a288b..901e1003f 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -444,9 +444,38 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t tm.x = los->strace.x + FixedMul(los->strace.dx, frac); tm.y = los->strace.y + FixedMul(los->strace.dy, frac); + // set openrange, opentop, openbottom P_LineOpening(line, los->t1); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); +#if 0 + if (los->t2->type == MT_WAYPOINT) + { + waypoint_t *wp = K_SearchWaypointHeapForMobj(los->t2); + + if (wp != NULL) + { + CONS_Printf( + "========\nID: %d\nopenrange: %.2f >= %.2f\n", + K_GetWaypointID(wp), + FIXED_TO_FLOAT(openrange), + FIXED_TO_FLOAT(los->t1->height) + ); + + if (openrange >= los->t1->height) + { + CONS_Printf( + "openbottom: %.2f\nlowfloor: %.2f\nstep: %.2f <= %.2f\n", + FIXED_TO_FLOAT(openbottom), + FIXED_TO_FLOAT(lowfloor), + FIXED_TO_FLOAT(openbottom - lowfloor), + FIXED_TO_FLOAT(maxstep) + ); + } + } + } +#endif + if (openrange < los->t1->height) { // Can't fit @@ -459,7 +488,12 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t // Or if we're on the higher side... canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); - return (canStepUp || canDropOff); + if (canStepUp || canDropOff) + { + return true; + } + + return false; } // From 6fa821b2d3e6f783beffa79a674064b6d2026a03 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 13 May 2023 00:39:36 -0400 Subject: [PATCH 08/12] Local P_LineOpening result + traversal leniency P_LineOpening results are stored in a locally made struct instead of being a bunch of disorganized globals. Waypoint traversals can go thru 1 line, if it was blocked by step-up rules, for free, similar concept to sound-blocking lines in Doom. --- src/p_map.c | 78 ++++++----- src/p_maputl.c | 366 ++++++++++++++++++++++++------------------------- src/p_maputl.h | 22 +-- src/p_sight.c | 60 ++++---- src/typedef.h | 1 + 5 files changed, 268 insertions(+), 259 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 320760582..5b539ad28 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1671,6 +1671,8 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // Adjusts tm.floorz and tm.ceilingz as lines are contacted - FOR CAMERA ONLY static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) { + opening_t open = {0}; + if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return BMIT_CONTINUE; @@ -1704,25 +1706,25 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld) } // set openrange, opentop, openbottom - P_CameraLineOpening(ld); + P_CameraLineOpening(ld, &open); // adjust floor / ceiling heights - if (opentop < tm.ceilingz) + if (open.ceiling < tm.ceilingz) { - tm.ceilingz = opentop; + tm.ceilingz = open.ceiling; tm.ceilingline = ld; } - if (openbottom > tm.floorz) + if (open.floor > tm.floorz) { - tm.floorz = openbottom; + tm.floorz = open.floor; } - if (highceiling > tm.drpoffceilz) - tm.drpoffceilz = highceiling; + if (open.highceiling > tm.drpoffceilz) + tm.drpoffceilz = open.highceiling; - if (lowfloor < tm.dropoffz) - tm.dropoffz = lowfloor; + if (open.lowfloor < tm.dropoffz) + tm.dropoffz = open.lowfloor; return BMIT_CONTINUE; } @@ -1773,6 +1775,7 @@ boolean P_IsLineTripWire(const line_t *ld) static BlockItReturn_t PIT_CheckLine(line_t *ld) { const fixed_t thingtop = tm.thing->z + tm.thing->height; + opening_t open = {0}; if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return BMIT_CONTINUE; @@ -1845,41 +1848,41 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) return BMIT_ABORT; // set openrange, opentop, openbottom - P_LineOpening(ld, tm.thing); + P_LineOpening(ld, tm.thing, &open); // adjust floor / ceiling heights - if (opentop < tm.ceilingz) + if (open.ceiling < tm.ceilingz) { - tm.ceilingz = opentop; + tm.ceilingz = open.ceiling; tm.ceilingline = ld; - tm.ceilingrover = openceilingrover; - tm.ceilingslope = opentopslope; - tm.ceilingpic = opentoppic; - tm.ceilingstep = openceilingstep; + tm.ceilingrover = open.ceilingrover; + tm.ceilingslope = open.ceilingslope; + tm.ceilingpic = open.ceilingpic; + tm.ceilingstep = open.ceilingstep; if (thingtop == tm.thing->ceilingz) { - tm.thing->ceilingdrop = openceilingdrop; + tm.thing->ceilingdrop = open.ceilingdrop; } } - if (openbottom > tm.floorz) + if (open.floor > tm.floorz) { - tm.floorz = openbottom; - tm.floorrover = openfloorrover; - tm.floorslope = openbottomslope; - tm.floorpic = openbottompic; - tm.floorstep = openfloorstep; + tm.floorz = open.floor; + tm.floorrover = open.floorrover; + tm.floorslope = open.floorslope; + tm.floorpic = open.floorpic; + tm.floorstep = open.floorstep; if (tm.thing->z == tm.thing->floorz) { - tm.thing->floordrop = openfloordrop; + tm.thing->floordrop = open.floordrop; } } - if (highceiling > tm.drpoffceilz) - tm.drpoffceilz = highceiling; + if (open.highceiling > tm.drpoffceilz) + tm.drpoffceilz = open.highceiling; - if (lowfloor < tm.dropoffz) - tm.dropoffz = lowfloor; + if (open.lowfloor < tm.dropoffz) + tm.dropoffz = open.lowfloor; // we've crossed the line if (P_SpecialIsLinedefCrossType(ld)) @@ -3462,6 +3465,7 @@ static void P_HitBounceLine(line_t *ld) static boolean PTR_SlideCameraTraverse(intercept_t *in) { line_t *li; + opening_t open = {0}; I_Assert(in->isaline); @@ -3476,15 +3480,15 @@ static boolean PTR_SlideCameraTraverse(intercept_t *in) } // set openrange, opentop, openbottom - P_CameraLineOpening(li); + P_CameraLineOpening(li, &open); - if (openrange < mapcampointer->height) + if (open.range < mapcampointer->height) goto isblocking; // doesn't fit - if (opentop - mapcampointer->z < mapcampointer->height) + if (open.ceiling - mapcampointer->z < mapcampointer->height) goto isblocking; // mobj is too high - if (openbottom - mapcampointer->z > 0) // We don't want to make the camera step up. + if (open.floor - mapcampointer->z > 0) // We don't want to make the camera step up. goto isblocking; // too big a step up // this line doesn't block movement @@ -3509,6 +3513,8 @@ isblocking: /* static boolean PTR_LineIsBlocking(line_t *li) { + opening_t open = {0}; + // one-sided linedefs are always solid to sliding movement. if (!li->backsector) return !P_PointOnLineSide(slidemo->x, slidemo->y, li); @@ -3517,15 +3523,15 @@ static boolean PTR_LineIsBlocking(line_t *li) return true; // set openrange, opentop, openbottom - P_LineOpening(li, slidemo); + P_LineOpening(li, slidemo, &open); - if (openrange < slidemo->height) + if (open.range < slidemo->height) return true; // doesn't fit - if (opentop - slidemo->z < slidemo->height) + if (open.ceiling - slidemo->z < slidemo->height) return true; // mobj is too high - if (openbottom - slidemo->z > P_GetThingStepUp(slidemo, slidemo->x, slidemo->y)) + if (open.floor - slidemo->z > P_GetThingStepUp(slidemo, slidemo->x, slidemo->y)) return true; // too big a step up return false; diff --git a/src/p_maputl.c b/src/p_maputl.c index 0693c20b3..14958c941 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -335,28 +335,24 @@ line_t * P_FindNearestLine // Sets opentop and openbottom to the window through a two sided line. // OPTIMIZE: keep this precalculated // -fixed_t opentop, openbottom, openrange, lowfloor, highceiling; -pslope_t *opentopslope, *openbottomslope; -ffloor_t *openfloorrover, *openceilingrover; -fixed_t openceilingstep; -fixed_t openceilingdrop; -fixed_t openfloorstep; -fixed_t openfloordrop; -INT32 opentoppic, openbottompic; // P_CameraLineOpening // P_LineOpening, but for camera // Tails 09-29-2002 -void P_CameraLineOpening(line_t *linedef) +void P_CameraLineOpening(line_t *linedef, opening_t *open) { sector_t *front; sector_t *back; fixed_t frontfloor, frontceiling, backfloor, backceiling; + fixed_t thingtop; + + open->ceiling = open->highceiling = INT32_MAX; + open->floor = open->lowfloor = INT32_MIN; + open->range = 0; if (linedef->sidenum[1] == 0xffff) { // single sided line - openrange = 0; return; } @@ -368,14 +364,14 @@ void P_CameraLineOpening(line_t *linedef) if (front->camsec >= 0) { // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) - frontfloor = P_GetSectorFloorZAt (§ors[front->camsec], camera[0].x, camera[0].y); - frontceiling = P_GetSectorCeilingZAt(§ors[front->camsec], camera[0].x, camera[0].y); + frontfloor = P_GetSectorFloorZAt (§ors[front->camsec], mapcampointer->x, mapcampointer->y); + frontceiling = P_GetSectorCeilingZAt(§ors[front->camsec], mapcampointer->x, mapcampointer->y); } else if (front->heightsec >= 0) { // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) - frontfloor = P_GetSectorFloorZAt (§ors[front->heightsec], camera[0].x, camera[0].y); - frontceiling = P_GetSectorCeilingZAt(§ors[front->heightsec], camera[0].x, camera[0].y); + frontfloor = P_GetSectorFloorZAt (§ors[front->heightsec], mapcampointer->x, mapcampointer->x); + frontceiling = P_GetSectorCeilingZAt(§ors[front->heightsec], mapcampointer->x, mapcampointer->y); } else { @@ -386,103 +382,101 @@ void P_CameraLineOpening(line_t *linedef) if (back->camsec >= 0) { // SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope) - backfloor = P_GetSectorFloorZAt (§ors[back->camsec], camera[0].x, camera[0].y); - backceiling = P_GetSectorCeilingZAt(§ors[back->camsec], camera[0].x, camera[0].y); + backfloor = P_GetSectorFloorZAt (§ors[back->camsec], mapcampointer->x, mapcampointer->y); + backceiling = P_GetSectorCeilingZAt(§ors[back->camsec], mapcampointer->x, mapcampointer->y); } else if (back->heightsec >= 0) { // SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope) - backfloor = P_GetSectorFloorZAt (§ors[back->heightsec], camera[0].x, camera[0].y); - backceiling = P_GetSectorCeilingZAt(§ors[back->heightsec], camera[0].x, camera[0].y); + backfloor = P_GetSectorFloorZAt (§ors[back->heightsec], mapcampointer->x, mapcampointer->y); + backceiling = P_GetSectorCeilingZAt(§ors[back->heightsec], mapcampointer->x, mapcampointer->y); } else { - backfloor = P_CameraGetFloorZ(mapcampointer, back, tm.x, tm.y, linedef); + backfloor = P_CameraGetFloorZ (mapcampointer, back, tm.x, tm.y, linedef); backceiling = P_CameraGetCeilingZ(mapcampointer, back, tm.x, tm.y, linedef); } + thingtop = mapcampointer->z + mapcampointer->height; + + if (frontceiling < backceiling) { - fixed_t thingtop = mapcampointer->z + mapcampointer->height; - - if (frontceiling < backceiling) - { - opentop = frontceiling; - highceiling = backceiling; - } - else - { - opentop = backceiling; - highceiling = frontceiling; - } - - if (frontfloor > backfloor) - { - openbottom = frontfloor; - lowfloor = backfloor; - } - else - { - openbottom = backfloor; - lowfloor = frontfloor; - } - - // Check for fake floors in the sector. - if (front->ffloors || back->ffloors) - { - ffloor_t *rover; - fixed_t delta1, delta2; - - // Check for frontsector's fake floors - if (front->ffloors) - for (rover = front->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) - continue; - - topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tm.x, tm.y, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tm.x, tm.y, linedef); - - delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < opentop && delta1 >= delta2) - opentop = bottomheight; - else if (bottomheight < highceiling && delta1 >= delta2) - highceiling = bottomheight; - - if (topheight > openbottom && delta1 < delta2) - openbottom = topheight; - else if (topheight > lowfloor && delta1 < delta2) - lowfloor = topheight; - } - - // Check for backsectors fake floors - if (back->ffloors) - for (rover = back->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) - continue; - - topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tm.x, tm.y, linedef); - bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tm.x, tm.y, linedef); - - delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < opentop && delta1 >= delta2) - opentop = bottomheight; - else if (bottomheight < highceiling && delta1 >= delta2) - highceiling = bottomheight; - - if (topheight > openbottom && delta1 < delta2) - openbottom = topheight; - else if (topheight > lowfloor && delta1 < delta2) - lowfloor = topheight; - } - } - openrange = opentop - openbottom; - return; + open->ceiling = frontceiling; + open->highceiling = backceiling; } + else + { + open->ceiling = backceiling; + open->highceiling = frontceiling; + } + + if (frontfloor > backfloor) + { + open->floor = frontfloor; + open->lowfloor = backfloor; + } + else + { + open->floor = backfloor; + open->lowfloor = frontfloor; + } + + // Check for fake floors in the sector. + if (front->ffloors || back->ffloors) + { + ffloor_t *rover; + fixed_t delta1, delta2; + + // Check for frontsector's fake floors + if (front->ffloors) + for (rover = front->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) + continue; + + topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tm.x, tm.y, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tm.x, tm.y, linedef); + + delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); + delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + if (bottomheight < open->ceiling && delta1 >= delta2) + open->ceiling = bottomheight; + else if (bottomheight < open->highceiling && delta1 >= delta2) + open->highceiling = bottomheight; + + if (topheight > open->floor && delta1 < delta2) + open->floor = topheight; + else if (topheight > open->lowfloor && delta1 < delta2) + open->lowfloor = topheight; + } + + // Check for backsectors fake floors + if (back->ffloors) + for (rover = back->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + if (!(rover->fofflags & FOF_BLOCKOTHERS) || !(rover->fofflags & FOF_RENDERALL) || !(rover->fofflags & FOF_EXISTS) || (rover->master->frontsector->flags & MSF_NOCLIPCAMERA)) + continue; + + topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tm.x, tm.y, linedef); + bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tm.x, tm.y, linedef); + + delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); + delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + if (bottomheight < open->ceiling && delta1 >= delta2) + open->ceiling = bottomheight; + else if (bottomheight < open->highceiling && delta1 >= delta2) + open->highceiling = bottomheight; + + if (topheight > open->floor && delta1 < delta2) + open->floor = topheight; + else if (topheight > open->lowfloor && delta1 < delta2) + open->lowfloor = topheight; + } + } + + open->range = (open->ceiling - open->floor); } boolean @@ -592,7 +586,7 @@ static boolean P_MidtextureIsSolid(line_t *linedef, mobj_t *mobj) return ((linedef->flags & ML_MIDSOLID) == ML_MIDSOLID); } -void P_LineOpening(line_t *linedef, mobj_t *mobj) +void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) { enum { FRONT, BACK }; @@ -608,15 +602,14 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) int lo = 0; // set these defaults so that polyobjects don't interfere with collision above or below them - opentop = highceiling = INT32_MAX; - openbottom = lowfloor = INT32_MIN; - openrange = 0; - opentopslope = openbottomslope = NULL; - opentoppic = openbottompic = -1; - openceilingstep = 0; - openceilingdrop = 0; - openfloorstep = 0; - openfloordrop = 0; + open->ceiling = open->highceiling = INT32_MAX; + open->floor = open->lowfloor = INT32_MIN; + open->range = 0; + open->ceilingslope = open->floorslope = NULL; + open->ceilingrover = open->floorrover = NULL; + open->ceilingpic = open->floorpic = -1; + open->ceilingstep = open->floorstep = 0; + open->ceilingdrop = open->floordrop = 0; if (linedef->sidenum[1] == 0xffff) { @@ -646,7 +639,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) thingtop = mobj->z + mobj->height; } - openfloorrover = openceilingrover = NULL; if (!linedef->polyobj) { // Set open and high/low values here @@ -659,18 +651,18 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) hi = ( height[0] < height[1] ); lo = ! hi; - opentop = height[lo]; - highceiling = height[hi]; - opentopslope = sector[lo]->c_slope; - opentoppic = sector[lo]->ceilingpic; + open->ceiling = height[lo]; + open->highceiling = height[hi]; + open->ceilingslope = sector[lo]->c_slope; + open->ceilingpic = sector[lo]->ceilingpic; if (mobj) { topedge[FRONT] = P_GetSectorCeilingZAt(front, cross.x, cross.y); topedge[BACK] = P_GetSectorCeilingZAt(back, cross.x, cross.y); - openceilingstep = ( thingtop - topedge[lo] ); - openceilingdrop = ( topedge[hi] - topedge[lo] ); + open->ceilingstep = ( thingtop - topedge[lo] ); + open->ceilingdrop = ( topedge[hi] - topedge[lo] ); } height[FRONT] = P_GetFloorZ(mobj, front, tm.x, tm.y, linedef); @@ -679,18 +671,18 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) hi = ( height[0] < height[1] ); lo = ! hi; - openbottom = height[hi]; - lowfloor = height[lo]; - openbottomslope = sector[hi]->f_slope; - openbottompic = sector[hi]->floorpic; + open->floor = height[hi]; + open->lowfloor = height[lo]; + open->floorslope = sector[hi]->f_slope; + open->floorpic = sector[hi]->floorpic; if (mobj) { botedge[FRONT] = P_GetSectorFloorZAt(front, cross.x, cross.y); botedge[BACK] = P_GetSectorFloorZAt(back, cross.x, cross.y); - openfloorstep = ( botedge[hi] - mobj->z ); - openfloordrop = ( botedge[hi] - botedge[lo] ); + open->floorstep = ( botedge[hi] - mobj->z ); + open->floordrop = ( botedge[hi] - botedge[lo] ); } } @@ -712,25 +704,25 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 > delta2) { // Below - if (opentop > texbottom) + if (open->ceiling > texbottom) { - topedge[lo] -= ( opentop - texbottom ); + topedge[lo] -= ( open->ceiling - texbottom ); - opentop = texbottom; - openceilingstep = ( thingtop - topedge[lo] ); - openceilingdrop = ( topedge[hi] - topedge[lo] ); + open->ceiling = texbottom; + open->ceilingstep = ( thingtop - topedge[lo] ); + open->ceilingdrop = ( topedge[hi] - topedge[lo] ); } } else { // Above - if (openbottom < textop) + if (open->floor < textop) { - botedge[hi] += ( textop - openbottom ); + botedge[hi] += ( textop - open->floor ); - openbottom = textop; - openfloorstep = ( botedge[hi] - mobj->z ); - openfloordrop = ( botedge[hi] - botedge[lo] ); + open->floor = textop; + open->floorstep = ( botedge[hi] - mobj->z ); + open->floordrop = ( botedge[hi] - botedge[lo] ); } } } @@ -760,26 +752,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) delta1 = abs(mobj->z - polymid); delta2 = abs(thingtop - polymid); - if (delta1 >= delta2) + if (delta1 > delta2) { - if (polybottom < opentop) + if (polybottom < open->ceiling) { - opentop = polybottom; + open->ceiling = polybottom; } - else if (polybottom < highceiling) + else if (polybottom < open->highceiling) { - highceiling = polybottom; + open->highceiling = polybottom; } } else { - if (polytop > openbottom) + if (polytop > open->floor) { - openbottom = polytop; + open->floor = polytop; } - else if (polytop > lowfloor) + else if (polytop > open->lowfloor) { - lowfloor = polytop; + open->lowfloor = polytop; } } } @@ -796,11 +788,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) /* yuck */ struct { - fixed_t top; - fixed_t bottom; + fixed_t ceiling; + fixed_t floor; ffloor_t * ceilingrover; ffloor_t * floorrover; - } open[2] = { + } fofopen[2] = { { INT32_MAX, INT32_MIN, NULL, NULL }, { INT32_MAX, INT32_MIN, NULL, NULL }, }; @@ -831,10 +823,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // thing is below FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) { - if (bottomheight < open[FRONT].top) + if (bottomheight < fofopen[FRONT].ceiling) { - open[FRONT].top = bottomheight; - open[FRONT].ceilingrover = rover; + fofopen[FRONT].ceiling = bottomheight; + fofopen[FRONT].ceilingrover = rover; } } } @@ -843,10 +835,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // thing is above FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) { - if (topheight > open[FRONT].bottom) + if (topheight > fofopen[FRONT].floor) { - open[FRONT].bottom = topheight; - open[FRONT].floorrover = rover; + fofopen[FRONT].floor = topheight; + fofopen[FRONT].floorrover = rover; } } } @@ -878,10 +870,10 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // thing is below FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) { - if (bottomheight < open[BACK].top) + if (bottomheight < fofopen[BACK].ceiling) { - open[BACK].top = bottomheight; - open[BACK].ceilingrover = rover; + fofopen[BACK].ceiling = bottomheight; + fofopen[BACK].ceilingrover = rover; } } } @@ -890,77 +882,77 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) // thing is above FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) { - if (topheight > open[BACK].bottom) + if (topheight > fofopen[BACK].floor) { - open[BACK].bottom = topheight; - open[BACK].floorrover = rover; + fofopen[BACK].floor = topheight; + fofopen[BACK].floorrover = rover; } } } } - hi = ( open[0].top < open[1].top ); + hi = ( fofopen[0].ceiling < fofopen[1].ceiling ); lo = ! hi; - if (open[lo].top <= opentop) + if (fofopen[lo].ceiling <= open->ceiling) { - topedge[lo] = P_GetFFloorBottomZAt(open[lo].ceilingrover, cross.x, cross.y); + topedge[lo] = P_GetFFloorBottomZAt(fofopen[lo].ceilingrover, cross.x, cross.y); - if (open[hi].top < opentop) + if (fofopen[hi].ceiling < open->ceiling) { - topedge[hi] = P_GetFFloorBottomZAt(open[hi].ceilingrover, cross.x, cross.y); + topedge[hi] = P_GetFFloorBottomZAt(fofopen[hi].ceilingrover, cross.x, cross.y); } - opentop = open[lo].top; - openceilingrover = open[lo].ceilingrover; - opentopslope = *open[lo].ceilingrover->b_slope; - opentoppic = *open[lo].ceilingrover->bottompic; - openceilingstep = ( thingtop - topedge[lo] ); - openceilingdrop = ( topedge[hi] - topedge[lo] ); + 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 (open[hi].top < highceiling) + if (fofopen[hi].ceiling < open->highceiling) { - highceiling = open[hi].top; + open->highceiling = fofopen[hi].ceiling; } } - else if (open[lo].top < highceiling) + else if (fofopen[lo].ceiling < open->highceiling) { - highceiling = open[lo].top; + open->highceiling = fofopen[lo].ceiling; } - hi = ( open[0].bottom < open[1].bottom ); + hi = ( fofopen[0].floor < fofopen[1].floor ); lo = ! hi; - if (open[hi].bottom >= openbottom) + if (fofopen[hi].floor >= open->floor) { - botedge[hi] = P_GetFFloorTopZAt(open[hi].floorrover, cross.x, cross.y); + botedge[hi] = P_GetFFloorTopZAt(fofopen[hi].floorrover, cross.x, cross.y); - if (open[lo].bottom > openbottom) + if (fofopen[lo].floor > open->floor) { - botedge[lo] = P_GetFFloorTopZAt(open[lo].floorrover, cross.x, cross.y); + botedge[lo] = P_GetFFloorTopZAt(fofopen[lo].floorrover, cross.x, cross.y); } - openbottom = open[hi].bottom; - openfloorrover = open[hi].floorrover; - openbottomslope = *open[hi].floorrover->t_slope; - openbottompic = *open[hi].floorrover->toppic; - openfloorstep = ( botedge[hi] - mobj->z ); - openfloordrop = ( botedge[hi] - botedge[lo] ); + 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 (open[lo].bottom > lowfloor) + if (fofopen[lo].floor > open->lowfloor) { - lowfloor = open[lo].bottom; + open->lowfloor = fofopen[lo].floor; } } - else if (open[hi].bottom > lowfloor) + else if (fofopen[hi].floor > open->lowfloor) { - lowfloor = open[hi].bottom; + open->lowfloor = fofopen[hi].floor; } } } } - openrange = opentop - openbottom; + open->range = (open->ceiling - open->floor); } diff --git a/src/p_maputl.h b/src/p_maputl.h index 5718afd04..4656ffdd4 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -50,7 +50,7 @@ void P_ClosestPointOnLine(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, line_t *line); void P_MakeDivline(line_t *li, divline_t *dl); -void P_CameraLineOpening(line_t *plinedef); +void P_CameraLineOpening(line_t *plinedef, opening_t *open); fixed_t P_InterceptVector(divline_t *v2, divline_t *v1); INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld); line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, const INT32 special); @@ -61,16 +61,18 @@ void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_ boolean P_GetMidtextureTopBottom(line_t *linedef, fixed_t x, fixed_t y, fixed_t *return_top, fixed_t *return_bottom); -extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; -extern pslope_t *opentopslope, *openbottomslope; -extern ffloor_t *openfloorrover, *openceilingrover; -extern fixed_t openceilingstep; -extern fixed_t openceilingdrop; -extern fixed_t openfloorstep; -extern fixed_t openfloordrop; -extern INT32 opentoppic, openbottompic; +struct opening_t +{ + fixed_t ceiling, floor, range; + fixed_t lowfloor, highceiling; + pslope_t *floorslope, *ceilingslope; + ffloor_t *floorrover, *ceilingrover; + fixed_t ceilingstep, ceilingdrop; + fixed_t floorstep, floordrop; + INT32 ceilingpic, floorpic; +}; -void P_LineOpening(line_t *plinedef, mobj_t *mobj); +void P_LineOpening(line_t *plinedef, mobj_t *mobj, opening_t *open); typedef enum { diff --git a/src/p_sight.c b/src/p_sight.c index 901e1003f..761b4b47b 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -36,6 +36,7 @@ typedef struct mobj_t *t1, *t2; boolean alreadyHates; // For bot traversal, for if the bot is already in a sector it doesn't want to be + UINT8 traversed; } los_t; typedef boolean (*los_init_t)(mobj_t *, mobj_t *, register los_t *); @@ -51,6 +52,8 @@ typedef struct static INT32 sightcounts[2]; +#define TRAVERSE_MAX (2) + // // P_DivlineSide // @@ -365,6 +368,7 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los fixed_t frac = 0; boolean canStepUp, canDropOff; fixed_t maxstep = 0; + opening_t open = {0}; if (P_CanTraceBlockingLine(seg, divl, los) == false) { @@ -380,32 +384,32 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los tm.y = los->strace.y + FixedMul(los->strace.dy, frac); // set openrange, opentop, openbottom - P_LineOpening(line, los->t1); + P_LineOpening(line, los->t1, &open); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); - if (openrange < los->t1->height) + if (open.range < los->t1->height) { // Can't fit return false; } - canStepUp = ((flip ? (highceiling - opentop) : (openbottom - lowfloor)) <= maxstep); - canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); + // If we can step up... + canStepUp = ((flip ? (open.highceiling - open.ceiling) : (open.floor - open.lowfloor)) <= maxstep); + + // Or if we're on the higher side... + canDropOff = (flip ? (los->t1->z + los->t1->height <= open.ceiling) : (los->t1->z >= open.floor)); if (canStepUp || canDropOff) { if (los->t1->player != NULL && los->alreadyHates == false) { - // Treat damage sectors like walls, if you're not already in a bad sector. - sector_t *front, *back; + // Treat damage / offroad sectors like walls. + UINT8 side = P_DivlineSide(los->t2x, los->t2y, divl) & 1; + sector_t *sector = (side == 1) ? seg->backsector : seg->frontsector; - front = seg->frontsector; - back = seg->backsector; - - if (K_BotHatesThisSector(los->t1->player, front, tm.x, tm.y) - || K_BotHatesThisSector(los->t1->player, back, tm.x, tm.y)) + if (K_BotHatesThisSector(los->t1->player, sector, tm.x, tm.y)) { - // This line does not block us, but we don't want to be in it. + // This line does not block us, but we don't want to cross it regardless. return false; } } @@ -413,7 +417,8 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los return true; } - return false; + los->traversed++; + return (los->traversed < TRAVERSE_MAX); } static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t *los) @@ -423,6 +428,7 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t fixed_t frac = 0; boolean canStepUp, canDropOff; fixed_t maxstep = 0; + opening_t open = {0}; if (P_CanTraceBlockingLine(seg, divl, los) == false) { @@ -445,10 +451,10 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t tm.y = los->strace.y + FixedMul(los->strace.dy, frac); // set openrange, opentop, openbottom - P_LineOpening(line, los->t1); + P_LineOpening(line, los->t1, &open); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); -#if 0 +#if 1 if (los->t2->type == MT_WAYPOINT) { waypoint_t *wp = K_SearchWaypointHeapForMobj(los->t2); @@ -456,19 +462,19 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t if (wp != NULL) { CONS_Printf( - "========\nID: %d\nopenrange: %.2f >= %.2f\n", + "========\nID: %d\nrange: %.2f >= %.2f\n", K_GetWaypointID(wp), - FIXED_TO_FLOAT(openrange), + FIXED_TO_FLOAT(open.range), FIXED_TO_FLOAT(los->t1->height) ); - if (openrange >= los->t1->height) + if (open.range >= los->t1->height) { CONS_Printf( - "openbottom: %.2f\nlowfloor: %.2f\nstep: %.2f <= %.2f\n", - FIXED_TO_FLOAT(openbottom), - FIXED_TO_FLOAT(lowfloor), - FIXED_TO_FLOAT(openbottom - lowfloor), + "floor: %.2f\nlowfloor: %.2f\nstep: %.2f <= %.2f\n", + FIXED_TO_FLOAT(open.floor), + FIXED_TO_FLOAT(open.lowfloor), + FIXED_TO_FLOAT(open.floor - open.lowfloor), FIXED_TO_FLOAT(maxstep) ); } @@ -476,24 +482,25 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t } #endif - if (openrange < los->t1->height) + if (open.range < los->t1->height) { // Can't fit return false; } // If we can step up... - canStepUp = ((flip ? (highceiling - opentop) : (openbottom - lowfloor)) <= maxstep); + canStepUp = ((flip ? (open.highceiling - open.ceiling) : (open.floor - open.lowfloor)) <= maxstep); // Or if we're on the higher side... - canDropOff = (flip ? (los->t1->z + los->t1->height <= opentop) : (los->t1->z >= openbottom)); + canDropOff = (flip ? (los->t1->z + los->t1->height <= open.ceiling) : (los->t1->z >= open.floor)); if (canStepUp || canDropOff) { return true; } - return false; + los->traversed++; + return (los->traversed < TRAVERSE_MAX); } // @@ -748,6 +755,7 @@ static boolean P_CompareMobjsAcrossLines(mobj_t *t1, mobj_t *t2, register los_fu los.t1 = t1; los.t2 = t2; los.alreadyHates = false; + los.traversed = 0; los.topslope = (los.bottomslope = t2->z - (los.sightzstart = diff --git a/src/typedef.h b/src/typedef.h index ebe816913..16d9fa8c1 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -265,6 +265,7 @@ TYPEDEF (BasicFF_t); // p_maputl.h TYPEDEF (divline_t); TYPEDEF (intercept_t); +TYPEDEF (opening_t); // p_mobj.h TYPEDEF (mobj_t); From 002e25905baa5d93c7264d7d35bed04988b90b2a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 13 May 2023 01:14:40 -0400 Subject: [PATCH 09/12] Add FOF behavior switch to P_LineOpening Finally fixes the very specific issue on Endless Mine ( https://cdn.discordapp.com/attachments/1006454720686202951/1106749881663631420/image.png ) --- src/p_maputl.c | 78 ++++++++++++++++++++++++++++++++++++++------------ src/p_maputl.h | 5 ++++ src/p_sight.c | 4 ++- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 14958c941..10aa4bb3d 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -754,24 +754,30 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) if (delta1 > delta2) { - if (polybottom < open->ceiling) + if (open->fofType != LO_FOF_FLOORS) { - open->ceiling = polybottom; - } - else if (polybottom < open->highceiling) - { - open->highceiling = polybottom; + if (polybottom < open->ceiling) + { + open->ceiling = polybottom; + } + else if (polybottom < open->highceiling) + { + open->highceiling = polybottom; + } } } else { - if (polytop > open->floor) + if (open->fofType != LO_FOF_CEILINGS) { - open->floor = polytop; - } - else if (polytop > open->lowfloor) - { - open->lowfloor = polytop; + if (polytop > open->floor) + { + open->floor = polytop; + } + else if (polytop > open->lowfloor) + { + open->lowfloor = polytop; + } } } } @@ -811,15 +817,28 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) continue; - topheight = P_GetFOFTopZ(mobj, front, rover, tm.x, tm.y, linedef); - bottomheight = P_GetFOFBottomZ(mobj, front, rover, tm.x, tm.y, linedef); + if (open->fofType != LO_FOF_ANY) + { + topheight = P_VeryTopOfFOF(rover); + bottomheight = P_VeryBottomOfFOF(rover); + } + else + { + topheight = P_GetFOFTopZ(mobj, front, rover, tm.x, tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, front, rover, tm.x, tm.y, linedef); + } midheight = bottomheight + (topheight - bottomheight) / 2; delta1 = abs(mobj->z - midheight); delta2 = abs(thingtop - midheight); - if (delta1 >= delta2) + if (delta1 > delta2) { + if (open->fofType == LO_FOF_FLOORS) + { + continue; + } + // thing is below FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) { @@ -832,6 +851,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) } else { + if (open->fofType == LO_FOF_CEILINGS) + { + continue; + } + // thing is above FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) { @@ -858,15 +882,28 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) || (rover->fofflags & FOF_BLOCKOTHERS && !mobj->player))) continue; - topheight = P_GetFOFTopZ(mobj, back, rover, tm.x, tm.y, linedef); - bottomheight = P_GetFOFBottomZ(mobj, back, rover, tm.x, tm.y, linedef); + if (open->fofType != LO_FOF_ANY) + { + topheight = P_VeryTopOfFOF(rover); + bottomheight = P_VeryBottomOfFOF(rover); + } + else + { + topheight = P_GetFOFTopZ(mobj, back, rover, tm.x, tm.y, linedef); + bottomheight = P_GetFOFBottomZ(mobj, back, rover, tm.x, tm.y, linedef); + } midheight = bottomheight + (topheight - bottomheight) / 2; delta1 = abs(mobj->z - midheight); delta2 = abs(thingtop - midheight); - if (delta1 >= delta2) + if (delta1 > delta2) { + if (open->fofType == LO_FOF_FLOORS) + { + continue; + } + // thing is below FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) { @@ -879,6 +916,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) } else { + if (open->fofType == LO_FOF_CEILINGS) + { + continue; + } + // thing is above FOF if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) { diff --git a/src/p_maputl.h b/src/p_maputl.h index 4656ffdd4..0d6d5a346 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -70,8 +70,13 @@ struct opening_t fixed_t ceilingstep, ceilingdrop; fixed_t floorstep, floordrop; INT32 ceilingpic, floorpic; + UINT8 fofType; // LO_FOF_ types for forcing FOF collide }; +#define LO_FOF_ANY (0) +#define LO_FOF_FLOORS (1) +#define LO_FOF_CEILINGS (2) + void P_LineOpening(line_t *plinedef, mobj_t *mobj, opening_t *open); typedef enum diff --git a/src/p_sight.c b/src/p_sight.c index 761b4b47b..20d94484d 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -384,6 +384,7 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los tm.y = los->strace.y + FixedMul(los->strace.dy, frac); // set openrange, opentop, openbottom + open.fofType = (flip ? LO_FOF_CEILINGS : LO_FOF_FLOORS); P_LineOpening(line, los->t1, &open); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); @@ -451,10 +452,11 @@ static boolean P_CanWaypointTraverse(seg_t *seg, divline_t *divl, register los_t tm.y = los->strace.y + FixedMul(los->strace.dy, frac); // set openrange, opentop, openbottom + open.fofType = (flip ? LO_FOF_CEILINGS : LO_FOF_FLOORS); P_LineOpening(line, los->t1, &open); maxstep = P_GetThingStepUp(los->t1, tm.x, tm.y); -#if 1 +#if 0 if (los->t2->type == MT_WAYPOINT) { waypoint_t *wp = K_SearchWaypointHeapForMobj(los->t2); From 7db53abdf7a667de6d0a979314b9ca67594c19c6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 13 May 2023 01:23:52 -0400 Subject: [PATCH 10/12] Fix object nudge search being too small --- src/k_botsearch.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/k_botsearch.c b/src/k_botsearch.c index cdb818730..30cc03c99 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -665,6 +665,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) INT32 xl, xh, yl, yh, bx, by; fixed_t distToPredict = 0; + fixed_t radToPredict = 0; angle_t angleToPredict = 0; fixed_t avgX = 0, avgY = 0; @@ -685,9 +686,10 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) } distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); + radToPredict = distToPredict >> 1; angleToPredict = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); - globalsmuggle.distancetocheck = distToPredict >> 1; + globalsmuggle.distancetocheck = distToPredict; baseNudge = predict->radius * 2; maxNudge = distToPredict; @@ -696,8 +698,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) globalsmuggle.predict = predict; // silly variable reuse - avgX = globalsmuggle.botmo->x + FixedMul(globalsmuggle.distancetocheck, FINECOSINE(angleToPredict >> ANGLETOFINESHIFT)); - avgY = globalsmuggle.botmo->y + FixedMul(globalsmuggle.distancetocheck, FINESINE(angleToPredict >> ANGLETOFINESHIFT)); + avgX = globalsmuggle.botmo->x + FixedMul(radToPredict, FINECOSINE(angleToPredict >> ANGLETOFINESHIFT)); + avgY = globalsmuggle.botmo->y + FixedMul(radToPredict, FINESINE(angleToPredict >> ANGLETOFINESHIFT)); for (i = 0; i < 2; i++) { @@ -708,10 +710,10 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) globalsmuggle.avoidObjs[i] = 0; } - xl = (unsigned)(avgX - (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(avgX + (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(avgY - (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(avgY + (globalsmuggle.distancetocheck + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(avgX - (distToPredict + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(avgX + (distToPredict + MAXRADIUS) - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(avgY - (distToPredict + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(avgY + (distToPredict + MAXRADIUS) - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); From 5ac7926e399f29fc0a2930bc368ee118c19e92c4 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 13 May 2023 01:59:07 -0400 Subject: [PATCH 11/12] Prediction nudge is based on original WP radius Previously based on prediction radius, which meant it was so low that it might barely even nudge at all. Now we try to nudge a lot, but clamp the radius to make it thinner if it goes off-road. --- src/k_bot.c | 30 ++++++++++++++---------------- src/k_bot.h | 2 +- src/k_botsearch.c | 11 +++++------ 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index bcf5619d6..9f7fdc25e 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -625,7 +625,7 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t } /*-------------------------------------------------- - static fixed_t K_GetBotWaypointRadius(waypoint_t *waypoint) + static void K_GetBotWaypointRadius(waypoint_t *waypoint, fixed_t *smallestRadius, fixed_t *smallestScaled) Calculates a new waypoint radius size to use, making it thinner depending on how harsh the turn is. @@ -634,9 +634,9 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t waypoint - Waypoint to retrieve the radius of. Return:- - New radius value. + N/A --------------------------------------------------*/ -static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) +static void K_GetBotWaypointRadius(waypoint_t *const waypoint, fixed_t *smallestRadius, fixed_t *smallestScaled) { static const fixed_t maxReduce = FRACUNIT/32; static const angle_t maxDelta = ANGLE_22h; @@ -675,7 +675,8 @@ static fixed_t K_GetBotWaypointRadius(waypoint_t *const waypoint) reduce = FixedDiv(delta, maxDelta); reduce = FRACUNIT + FixedMul(reduce, maxReduce - FRACUNIT); - return FixedMul(radius, reduce); + *smallestRadius = min(*smallestRadius, radius); + *smallestScaled = min(*smallestScaled, FixedMul(radius, reduce)); } static fixed_t K_ScaleWPDistWithSlope(fixed_t disttonext, angle_t angletonext, const pslope_t *slope, SINT8 flip) @@ -735,10 +736,12 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const INT32 distance = min(((speed / FRACUNIT) * (INT32)futuresight) + startDist, maxDist); // Halves radius when encountering a wall on your way to your destination. - fixed_t radreduce = FRACUNIT; + fixed_t radReduce = FRACUNIT; + + fixed_t radius = INT32_MAX; + fixed_t radiusScaled = INT32_MAX; INT32 distanceleft = distance; - fixed_t smallestradius = INT32_MAX; angle_t angletonext = ANGLE_MAX; INT32 disttonext = INT32_MAX; INT32 distscaled = INT32_MAX; @@ -780,8 +783,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { for (i = 0; i < pathtofinish.numnodes; i++) { - fixed_t radius = 0; - wp = (waypoint_t *)pathtofinish.array[i].nodedata; if (i == 0) @@ -802,15 +803,10 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { // If we can't get a direct path to this waypoint, reduce our prediction drastically. distscaled *= 4; - radreduce = FRACUNIT >> 1; - } - - radius = K_GetBotWaypointRadius(wp); - if (radius < smallestradius) - { - smallestradius = radius; + radReduce = FRACUNIT >> 1; } + K_GetBotWaypointRadius(wp, &radius, &radiusScaled); distanceleft -= distscaled; if (distanceleft <= 0) @@ -827,7 +823,9 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) // and use the smallest radius of all of the waypoints in the chain! predict->x = wp->mobj->x; predict->y = wp->mobj->y; - predict->radius = FixedMul(smallestradius, radreduce); + + predict->baseRadius = radius; + predict->radius = FixedMul(radiusScaled, radReduce); // Set the prediction coordinates between the 2 waypoints if there's still distance left. if (distanceleft > 0) diff --git a/src/k_bot.h b/src/k_bot.h index bce0a1655..d98f7a1e9 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -37,7 +37,7 @@ extern "C" { // Point for bots to aim for struct botprediction_t { fixed_t x, y; - fixed_t radius; + fixed_t radius, baseRadius; }; diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 30cc03c99..6d3e97ed3 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -691,8 +691,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) globalsmuggle.distancetocheck = distToPredict; - baseNudge = predict->radius * 2; - maxNudge = distToPredict; + baseNudge = predict->baseRadius >> 3; + maxNudge = predict->baseRadius - baseNudge; globalsmuggle.botmo = player->mo; globalsmuggle.predict = predict; @@ -747,8 +747,6 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) // High handling characters dodge better nudgeDist = ((9 - globalsmuggle.botmo->player->kartweight) + 1) * baseNudge; - - maxNudge = max(distToPredict - predict->radius, predict->radius); if (nudgeDist > maxNudge) { nudgeDist = maxNudge; @@ -762,6 +760,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) predict->x += FixedMul(nudgeDist, FINECOSINE(nudgeDir >> ANGLETOFINESHIFT)); predict->y += FixedMul(nudgeDist, FINESINE(nudgeDir >> ANGLETOFINESHIFT)); + predict->radius = max(predict->radius - nudgeDist, baseNudge); distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); @@ -811,8 +810,6 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) // Acceleration characters are more aggressive nudgeDist = ((9 - globalsmuggle.botmo->player->kartspeed) + 1) * baseNudge; - - maxNudge = max(distToPredict - predict->radius, predict->radius); if (nudgeDist > maxNudge) { nudgeDist = maxNudge; @@ -822,6 +819,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) { predict->x = avgX; predict->y = avgY; + predict->radius = baseNudge; } else { @@ -833,6 +831,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) predict->x += FixedMul(nudgeDist, FINECOSINE(nudgeDir >> ANGLETOFINESHIFT)); predict->y += FixedMul(nudgeDist, FINESINE(nudgeDir >> ANGLETOFINESHIFT)); + predict->radius = max(predict->radius - nudgeDist, baseNudge); //distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); } From 7cb0b74cac3b336b762360bb6a8ee17ede454663 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 13 May 2023 04:13:35 -0400 Subject: [PATCH 12/12] Use more explicit floor/ceiling FOF sort --- src/p_maputl.c | 237 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 161 insertions(+), 76 deletions(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 10aa4bb3d..3ce1729cb 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -748,36 +748,67 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) polybottom = INT32_MIN; } - polymid = polybottom + (polytop - polybottom) / 2; - delta1 = abs(mobj->z - polymid); - delta2 = abs(thingtop - polymid); - - if (delta1 > delta2) + switch (open->fofType) { - if (open->fofType != LO_FOF_FLOORS) + case LO_FOF_FLOORS: { - if (polybottom < open->ceiling) + if (mobj->z >= polytop) { - open->ceiling = polybottom; - } - else if (polybottom < open->highceiling) - { - open->highceiling = polybottom; + if (polytop > open->floor) + { + open->floor = polytop; + } + else if (polytop > open->lowfloor) + { + open->lowfloor = polytop; + } } + break; } - } - else - { - if (open->fofType != LO_FOF_CEILINGS) + case LO_FOF_CEILINGS: { - if (polytop > open->floor) + if (thingtop <= polybottom) { - open->floor = polytop; + if (polybottom < open->ceiling) + { + open->ceiling = polybottom; + } + else if (polybottom < open->highceiling) + { + open->highceiling = polybottom; + } } - else if (polytop > open->lowfloor) + break; + } + default: + { + polymid = polybottom + (polytop - polybottom) / 2; + delta1 = abs(mobj->z - polymid); + delta2 = abs(thingtop - polymid); + + if (delta1 > delta2) { - open->lowfloor = polytop; + if (polybottom < open->ceiling) + { + open->ceiling = polybottom; + } + else if (polybottom < open->highceiling) + { + open->highceiling = polybottom; + } } + else + { + if (polytop > open->floor) + { + open->floor = polytop; + } + else if (polytop > open->lowfloor) + { + open->lowfloor = polytop; + } + } + break; } } } @@ -828,42 +859,69 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) bottomheight = P_GetFOFBottomZ(mobj, front, rover, tm.x, tm.y, linedef); } - midheight = bottomheight + (topheight - bottomheight) / 2; - delta1 = abs(mobj->z - midheight); - delta2 = abs(thingtop - midheight); - - if (delta1 > delta2) + switch (open->fofType) { - if (open->fofType == LO_FOF_FLOORS) + case LO_FOF_FLOORS: { - continue; - } - - // thing is below FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) - { - if (bottomheight < fofopen[FRONT].ceiling) + if (mobj->z >= topheight) { - fofopen[FRONT].ceiling = bottomheight; - fofopen[FRONT].ceilingrover = rover; + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) + { + if (topheight > fofopen[FRONT].floor) + { + fofopen[FRONT].floor = topheight; + fofopen[FRONT].floorrover = rover; + } + } } + break; } - } - else - { - if (open->fofType == LO_FOF_CEILINGS) + case LO_FOF_CEILINGS: { - continue; - } - - // thing is above FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) - { - if (topheight > fofopen[FRONT].floor) + if (thingtop <= bottomheight) { - fofopen[FRONT].floor = topheight; - fofopen[FRONT].floorrover = rover; + 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); + + 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; } } } @@ -893,42 +951,69 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj, opening_t *open) bottomheight = P_GetFOFBottomZ(mobj, back, rover, tm.x, tm.y, linedef); } - midheight = bottomheight + (topheight - bottomheight) / 2; - delta1 = abs(mobj->z - midheight); - delta2 = abs(thingtop - midheight); - - if (delta1 > delta2) + switch (open->fofType) { - if (open->fofType == LO_FOF_FLOORS) + case LO_FOF_FLOORS: { - continue; - } - - // thing is below FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_PLATFORM) - { - if (bottomheight < fofopen[BACK].ceiling) + if (mobj->z >= topheight) { - fofopen[BACK].ceiling = bottomheight; - fofopen[BACK].ceilingrover = rover; + if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) + { + if (topheight > fofopen[BACK].floor) + { + fofopen[BACK].floor = topheight; + fofopen[BACK].floorrover = rover; + } + } } + break; } - } - else - { - if (open->fofType == LO_FOF_CEILINGS) + case LO_FOF_CEILINGS: { - continue; - } - - // thing is above FOF - if ((rover->fofflags & FOF_INTANGIBLEFLATS) != FOF_REVERSEPLATFORM) - { - if (topheight > fofopen[BACK].floor) + if (thingtop <= bottomheight) { - fofopen[BACK].floor = topheight; - fofopen[BACK].floorrover = rover; + 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); + + 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; } } }