From 52f82b4c64a3f56a18149efded7eeecae230491a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 30 May 2022 08:26:13 -0400 Subject: [PATCH 01/17] Better bot spindash behaviors For Chrome Gadget --- src/k_bot.c | 50 ++++++++++++++++++++++++-------------------------- src/k_bot.h | 2 +- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index b2115bbea..4ceb90c21 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -804,9 +804,11 @@ static UINT8 K_TrySpindash(player_t *player) const fixed_t baseAccel = K_GetNewSpeed(player) - oldSpeed; const fixed_t speedDiff = player->speed - player->lastspeed; - if (player->spindashboost || player->tiregrease) + const INT32 angleDiff = AngleDelta(player->mo->angle, K_MomentumAngle(player->mo)); + + if (player->spindashboost || player->tiregrease // You just released a spindash, you don't need to try again yet, jeez. + || P_PlayerInPain(player) || !P_IsObjectOnGround(player->mo)) // Not in a state where we want 'em to spindash. { - // You just released a spindash, you don't need to try again yet, jeez. player->botvars.spindashconfirm = 0; return 0; } @@ -837,36 +839,13 @@ static UINT8 K_TrySpindash(player_t *player) } } - // Logic for normal racing. - if (player->flashing > 0) - { - // Don't bother trying to spindash. - // Trying to spindash while flashing is fine during POSITION, but not during the actual race. - return 0; - } - - if (speedDiff < (baseAccel / 4)) - { - if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM) - { - player->botvars.spindashconfirm++; - } - } - else - { - if (player->botvars.spindashconfirm > 0) - { - player->botvars.spindashconfirm--; - } - } - if (player->botvars.spindashconfirm >= BOTSPINDASHCONFIRM) { INT32 chargingPoint = (K_GetSpindashChargeTime(player) + difficultyModifier); // Release quicker the higher the difficulty is. // Sounds counter-productive, but that's actually the best strategy after the race has started. - chargingPoint -= player->botvars.difficulty * difficultyModifier; + chargingPoint -= min(DIFFICULTBOT, player->botvars.difficulty) * difficultyModifier; if (player->spindash > chargingPoint) { @@ -876,6 +855,25 @@ static UINT8 K_TrySpindash(player_t *player) return 2; } + else + { + // Logic for normal racing. + if (speedDiff < (baseAccel / 4) // Moving too slowly + || angleDiff > ANG60) // Being pushed backwards + { + if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM) + { + player->botvars.spindashconfirm++; + } + } + else if (player->botvars.spindashconfirm >= BOTSPINDASHCONFIRM) + { + if (player->botvars.spindashconfirm > 0) + { + player->botvars.spindashconfirm--; + } + } + } // We're doing just fine, we don't need to spindash, thanks. return 0; diff --git a/src/k_bot.h b/src/k_bot.h index f03187205..831f0ab44 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -28,7 +28,7 @@ #define BOTTURNCONFIRM 4 // How many tics without being able to accelerate before we'll let you spindash. -#define BOTSPINDASHCONFIRM (TICRATE/4) +#define BOTSPINDASHCONFIRM (TICRATE) // Point for bots to aim for typedef struct botprediction_s { From 3e4a1feb84ddf756530fa0873bc7d0cd85a42fdc Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 30 May 2022 08:26:38 -0400 Subject: [PATCH 02/17] Better bot controller direction enforce --- 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 4ceb90c21..2f00f0754 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -1320,7 +1320,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (botController != NULL && (botController->flags & ML_EFFECT1)) { - const fixed_t dist = (player->mo->radius * 4); + const fixed_t dist = DEFAULT_WAYPOINT_RADIUS * player->mo->scale; // X Offset: Movement direction destangle = FixedAngle(sides[botController->sidenum[0]].textureoffset); From 0e95110136e2b796472beb423f57c680e9d9f32a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 30 May 2022 19:28:40 -0400 Subject: [PATCH 03/17] Bot prediction uses pathfinding A subtle change, but means the bots are thinking ahead more about the track's design, rather than just what's in front of them. Instead of just "convenient" paths, they'll actively think about which path is the shortest. The most significant thing this effects is making them use shortcuts more often. --- src/k_bot.c | 152 +++++++++++++++++++--------------------------------- src/k_bot.h | 2 +- 2 files changed, 55 insertions(+), 99 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 2f00f0754..f36943e45 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -639,132 +639,88 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t static botprediction_t *K_CreateBotPrediction(player_t *player) { // Stair janking makes it harder to steer, so attempt to steer harder. - const UINT8 jankDiv = (player->stairjank > 0 ? 2 : 1); + const UINT8 jankDiv = (player->stairjank > 0) ? 2 : 1; const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN) / jankDiv; // Reduce prediction based on how fast you can turn - const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to - const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict + 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 = (768 * mapobjectscale) / FRACUNIT; + const INT32 startDist = (DEFAULT_WAYPOINT_RADIUS * 2 * mapobjectscale) / FRACUNIT; const INT32 distance = ((speed / FRACUNIT) * futuresight) + startDist; - botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); - waypoint_t *wp = player->nextwaypoint; - - INT32 distanceleft = distance; - fixed_t smallestradius = INT32_MAX; - angle_t angletonext = ANGLE_MAX; - // Halves radius when encountering a wall on your way to your destination. fixed_t radreduce = FRACUNIT; - size_t nwp; + INT32 distanceleft = distance; + fixed_t smallestradius = INT32_MAX; + angle_t angletonext = ANGLE_MAX; + INT32 disttonext = INT32_MAX; + + waypoint_t *wp = player->nextwaypoint; + mobj_t *prevwpmobj = player->mo; + + const boolean useshortcuts = K_BotCanTakeCut(player); + const boolean huntbackwards = false; + boolean pathfindsuccess = false; + path_t pathtofinish = {0}; + + botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); size_t i; - // Reduce distance left by your distance to the starting waypoint. - // This prevents looking too far ahead if the closest waypoint is really far away. - distanceleft -= P_AproxDistance(player->mo->x - wp->mobj->x, player->mo->y - wp->mobj->y) / FRACUNIT; + // 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; - // We don't want to look ahead at all, just go to the first waypoint. - if (distanceleft <= 0) - { - predict->x = wp->mobj->x; - predict->y = wp->mobj->y; - predict->radius = wp->mobj->radius; - return predict; - } - - angletonext = R_PointToAngle2( - player->mo->x, player->mo->y, - wp->mobj->x, wp->mobj->y + pathfindsuccess = K_PathfindToWaypoint( + player->nextwaypoint, K_GetFinishLineWaypoint(), + &pathtofinish, + useshortcuts, huntbackwards ); - // Go through waypoints until we've traveled the distance we wanted to predict ahead! - while (distanceleft > 0) + // Go through the waypoints until we've traveled the distance we wanted to predict ahead! + if (pathfindsuccess == true) { - INT32 disttonext = INT32_MAX; - - if (wp->mobj->radius < smallestradius) + for (i = 0; i < pathtofinish.numnodes; i++) { - smallestradius = wp->mobj->radius; - } + wp = (waypoint_t *)pathtofinish.array[i].nodedata; - if (wp->numnextwaypoints == 0) - { - // Well, this is where I get off. - distanceleft = 0; - break; - } - - // Calculate nextwaypoints index to use - // nextwaypoints[0] by default - nwp = 0; - - // There are multiple nextwaypoints, - // so we need to find the most convenient one to us. - // Let's compare the angle to the player's! - if (wp->numnextwaypoints > 1) - { - angle_t delta = ANGLE_MAX; - angle_t a = ANGLE_MAX; - - for (i = 0; i < wp->numnextwaypoints; i++) + if (i > 0) { - if (K_GetWaypointIsEnabled(wp->nextwaypoints[i]) == false) - { - continue; - } + prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj; + } - if (K_GetWaypointIsShortcut(wp->nextwaypoints[i]) == true && K_BotCanTakeCut(player) == false) - { - continue; - } + 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; - // Unlike the other parts of this function, we're comparing the player's physical position, NOT the position of the waypoint!! - // This should roughly correspond with how players will think about path splits. - a = R_PointToAngle2( - player->mo->x, player->mo->y, - wp->nextwaypoints[i]->mobj->x, wp->nextwaypoints[i]->mobj->y - ); - if (a > ANGLE_180) - { - a = InvAngle(a); - } + if (wp->mobj->radius < smallestradius) + { + smallestradius = wp->mobj->radius; + } - a = player->mo->angle - a; + if (P_TraceBotTraversal(player->mo, wp->mobj) == false) + { + // If we can't get a direct path to this waypoint, predict less. + disttonext <<= 2; + radreduce = FRACUNIT >> 1; + } - if (a < delta) - { - nwp = i; - delta = a; - } + distanceleft -= disttonext; + + if (distanceleft <= 0) + { + // We're done!! + break; } } - - angletonext = R_PointToAngle2( - wp->mobj->x, wp->mobj->y, - wp->nextwaypoints[nwp]->mobj->x, wp->nextwaypoints[nwp]->mobj->y - ); - disttonext = (INT32)wp->nextwaypointdistances[nwp]; - - if (P_TraceBotTraversal(player->mo, wp->nextwaypoints[nwp]->mobj) == false) + if (i == pathtofinish.numnodes) { - // If we can't get a direct path to this waypoint, we don't want to check much further... - disttonext *= 2; - radreduce = FRACUNIT/2; + // Reached the finish!! + distanceleft = 0; } - if (disttonext > distanceleft) - { - break; - } - - distanceleft -= disttonext; - - wp = wp->nextwaypoints[nwp]; + Z_Free(pathtofinish.array); } // Set our predicted point's coordinates, @@ -858,7 +814,7 @@ static UINT8 K_TrySpindash(player_t *player) else { // Logic for normal racing. - if (speedDiff < (baseAccel / 4) // Moving too slowly + if (speedDiff < (baseAccel / 8) // Moving too slowly || angleDiff > ANG60) // Being pushed backwards { if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM) diff --git a/src/k_bot.h b/src/k_bot.h index 831f0ab44..f476848f0 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -28,7 +28,7 @@ #define BOTTURNCONFIRM 4 // How many tics without being able to accelerate before we'll let you spindash. -#define BOTSPINDASHCONFIRM (TICRATE) +#define BOTSPINDASHCONFIRM (2*TICRATE) // Point for bots to aim for typedef struct botprediction_s { From fae9939a25e33f083f62c26b65d76b5a2bf93f5d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 30 May 2022 19:29:58 -0400 Subject: [PATCH 04/17] Make slope speed scale more significant Pull that prediction BACK when you're going up slopes! --- src/k_bot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index f36943e45..73e964f69 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -347,8 +347,8 @@ static fixed_t K_BotSpeedScaled(player_t *player, fixed_t speed) // Going downhill: FRACUNIT*2 slopeMul = FRACUNIT + FINECOSINE(angle >> ANGLETOFINESHIFT); - // Range: 0.9 to 1.1 - result = FixedMul(result, (FRACUNIT*9/10) + (slopeMul/10)); + // Range: 0.5 to 1.5 + result = FixedMul(result, (FRACUNIT>>1) + (slopeMul >> 1)); } } From ee5e96b65eb23394d434ac0329a47591b054bbc7 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 30 May 2022 19:30:17 -0400 Subject: [PATCH 05/17] Simplify angle/speed radius logic --- src/k_bot.c | 71 ++++++++++++++++++++--------------------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 73e964f69..a9124d91f 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -961,29 +961,27 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * // Handle steering towards waypoints! INT32 turnamt = 0; SINT8 turnsign = 0; - angle_t moveangle, angle; - INT16 anglediff; + angle_t moveangle; + INT32 anglediff; I_Assert(predict != NULL); moveangle = player->mo->angle; - angle = (moveangle - destangle); + anglediff = AngleDeltaSigned(moveangle, destangle); - if (angle < ANGLE_180) + if (anglediff < 0) { - turnsign = -1; // Turn right - anglediff = AngleFixed(angle)>>FRACBITS; + turnsign = 1; } else { - turnsign = 1; // Turn left - anglediff = 360-(AngleFixed(angle)>>FRACBITS); + turnsign = -1; } anglediff = abs(anglediff); turnamt = KART_FULLTURN * turnsign; - if (anglediff > 90) + if (anglediff > ANGLE_90) { // Wrong way! cmd->forwardmove = -MAXPLMOVE; @@ -992,7 +990,7 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * else { const fixed_t playerwidth = (player->mo->radius * 2); - fixed_t realrad = predict->radius - (playerwidth * 4); // Remove a "safe" distance away from the edges of the road + fixed_t realrad = predict->radius*3/4; // Remove a "safe" distance away from the edges of the road fixed_t rad = realrad; fixed_t dirdist = K_DistanceOfLineFromPoint( player->mo->x, player->mo->y, @@ -1000,19 +998,26 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * predict->x, predict->y ); - if (realrad < player->mo->radius) + if (realrad < playerwidth) { - realrad = player->mo->radius; + realrad = playerwidth; } - if (anglediff > 0) - { - // Become more precise based on how hard you need to turn - // This makes predictions into turns a little nicer - // Facing 90 degrees away from the predicted point gives you a 1/3 radius - rad = FixedMul(rad, ((135 - anglediff) * FRACUNIT) / 135); - } + // Become more precise based on how hard you need to turn + // This makes predictions into turns a little nicer + // Facing 90 degrees away from the predicted point gives you 0 radius + rad = FixedMul(rad, + FixedDiv(max(0, ANGLE_90 - anglediff), ANGLE_90) + ); + // Become more precise the slower you're moving + // Also helps with turns + // Full speed uses full radius + rad = FixedMul(rad, + FixedDiv(K_BotSpeedScaled(player, player->speed), K_GetKartSpeed(player, false, false)) + ); + + // Cap the radius to reasonable bounds if (rad > realrad) { rad = realrad; @@ -1022,36 +1027,14 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t * rad = playerwidth; } - cmd->buttons |= BT_ACCELERATE; - // Full speed ahead! + cmd->buttons |= BT_ACCELERATE; cmd->forwardmove = MAXPLMOVE; if (dirdist <= rad) { - fixed_t speedmul = FixedDiv(K_BotSpeedScaled(player, player->speed), K_GetKartSpeed(player, false, false)); - fixed_t speedrad = rad/4; - - if (speedmul > FRACUNIT) - { - speedmul = FRACUNIT; - } - - // Increase radius with speed - // At low speed, the CPU will try to be more accurate - // At high speed, they're more likely to lawnmower - speedrad += FixedMul(speedmul, rad - speedrad); - - if (speedrad < playerwidth) - { - speedrad = playerwidth; - } - - if (dirdist <= speedrad) - { - // Don't turn at all - turnamt = 0; - } + // Going the right way, don't turn at all. + turnamt = 0; } } From bfa3c40033ee2636990297273dc83fcebef50198 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 03:51:35 -0400 Subject: [PATCH 06/17] Improve bot traversal for the prediction HatesSector was returning false positive for intangible FOFs, making them play really poorly in Desert Palace --- src/k_bot.c | 25 +++++++++++++++---------- src/k_botsearch.c | 22 +++++++++------------- src/p_sight.c | 43 +++++++++++++++++++++---------------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index a9124d91f..4c2bb1123 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -685,11 +685,23 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) { wp = (waypoint_t *)pathtofinish.array[i].nodedata; - if (i > 0) + if (i == 0) + { + prevwpmobj = player->mo; + } + else { prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj; } + if (P_TraceBotTraversal(player->mo, wp->mobj) == false) + { + // If we can't get a direct path to this waypoint, stop predicting. + distanceleft = 0; + radreduce = FRACUNIT >> 1; + break; + } + 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; @@ -698,13 +710,6 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) smallestradius = wp->mobj->radius; } - if (P_TraceBotTraversal(player->mo, wp->mobj) == false) - { - // If we can't get a direct path to this waypoint, predict less. - disttonext <<= 2; - radreduce = FRACUNIT >> 1; - } - distanceleft -= disttonext; if (distanceleft <= 0) @@ -733,8 +738,8 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) if (distanceleft > 0) { // Scaled with the leftover anglemul! - predict->x += P_ReturnThrustX(NULL, angletonext, distanceleft * FRACUNIT); - predict->y += P_ReturnThrustY(NULL, angletonext, distanceleft * FRACUNIT); + predict->x += P_ReturnThrustX(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); + predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); } return predict; diff --git a/src/k_botsearch.c b/src/k_botsearch.c index b62b55852..1192324e3 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -172,26 +172,24 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec) boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t y) { const boolean flip = (player->mo->eflags & MFE_VERTICALFLIP); - INT32 specialflag = 0; fixed_t highestfloor = INT32_MAX; sector_t *bestsector = NULL; ffloor_t *rover; + // TODO: Properly support SF_FLIPSPECIAL_FLOOR / SF_FLIPSPECIAL_CEILING. + // An earlier attempt at it caused lots of false positives and other weird + // quirks with intangible FOFs. + if (flip == true) { - specialflag = SF_FLIPSPECIAL_CEILING; highestfloor = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight); } else { - specialflag = SF_FLIPSPECIAL_FLOOR; highestfloor = P_GetZAt(sec->f_slope, x, y, sec->floorheight); } - if (sec->flags & specialflag) - { - bestsector = sec; - } + bestsector = sec; for (rover = sec->ffloors; rover; rover = rover->next) { @@ -209,15 +207,13 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t if (!(rover->flags & FF_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)) { // Bad intangible sector at our height, so we DEFINITELY want to avoid return true; } - } - if ((rover->flags & FF_BLOCKPLAYER) && !(rover->master->frontsector->flags & specialflag)) - { + // Ignore them, we want the one below it. continue; } @@ -225,7 +221,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t if (flip == true) { if (bottom < highestfloor - && bottom >= player->mo->z + player->mo->height) + && bottom >= player->mo->z + player->mo->height) { bestsector = rover->master->frontsector; highestfloor = bottom; @@ -234,7 +230,7 @@ boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, fixed_t else { if (top > highestfloor - && top <= player->mo->z) + && top <= player->mo->z) { bestsector = rover->master->frontsector; highestfloor = top; diff --git a/src/p_sight.c b/src/p_sight.c index 4faffcf32..10d670ede 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -516,6 +516,7 @@ typedef struct { divline_t strace; // from t1 to t2 fixed_t bbox[4]; mobj_t *compareThing; + boolean alreadyHates; } traceblocking_t; static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb) @@ -664,6 +665,7 @@ boolean P_TraceBlockingLines(mobj_t *t1, mobj_t *t2) tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y; tb.compareThing = t1; + tb.alreadyHates = false; // the head node is the last node output return P_CrossBSPNodeBlocking((INT32)numnodes - 1, &tb); @@ -760,31 +762,17 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t return false; } - if (tb->compareThing->player != NULL) + if (tb->compareThing->player != NULL && tb->alreadyHates == false) { - // Treat damage sectors like walls - boolean alreadyHates = K_BotHatesThisSector( - tb->compareThing->player, tb->compareThing->subsector->sector, - tb->compareThing->x, tb->compareThing->y - ); + // Treat damage sectors like walls, if you're not already in a bad sector. + vertex_t pos; + P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); - if (alreadyHates == false) + if (K_BotHatesThisSector(tb->compareThing->player, line->frontsector, pos.x, pos.y) + || K_BotHatesThisSector(tb->compareThing->player, line->backsector, pos.x, pos.y)) { - INT32 lineside = 0; - vertex_t pos; - - P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos); - lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line); - - if (K_BotHatesThisSector( - tb->compareThing->player, - ((lineside == 1) ? line->frontsector : line->backsector), - pos.x, pos.y - )) - { - // This line does not block us, but we don't want to be in it. - return false; - } + // This line does not block us, but we don't want to be in it. + return false; } } } @@ -864,6 +852,17 @@ boolean P_TraceBotTraversal(mobj_t *t1, mobj_t *t2) tb.bbox[BOXTOP] = t2->y, tb.bbox[BOXBOTTOM] = t1->y; tb.compareThing = t1; + if (t1->player != NULL) + { + tb.alreadyHates = K_BotHatesThisSector( + t1->player, t1->subsector->sector, + t1->x, t1->y + ); + } + else + { + tb.alreadyHates = false; + } // the head node is the last node output return P_CrossBSPNodeBotTraversal((INT32)numnodes - 1, &tb); From 754004e07c64d0a2ca04cf40691b15819b840e1c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 26 Aug 2022 20:19:13 -0400 Subject: [PATCH 07/17] Fix bots acting weird near the finish line --- src/k_bot.c | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index d27b4d543..605a955c2 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -657,6 +657,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) angle_t angletonext = ANGLE_MAX; INT32 disttonext = INT32_MAX; + waypoint_t *finishLine = K_GetFinishLineWaypoint(); waypoint_t *wp = player->nextwaypoint; mobj_t *prevwpmobj = player->mo; @@ -673,7 +674,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) disttonext = P_AproxDistance(prevwpmobj->x - wp->mobj->x, prevwpmobj->y - wp->mobj->y) / FRACUNIT; pathfindsuccess = K_PathfindToWaypoint( - player->nextwaypoint, K_GetFinishLineWaypoint(), + player->nextwaypoint, finishLine, &pathtofinish, useshortcuts, huntbackwards ); @@ -694,17 +695,16 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) prevwpmobj = ((waypoint_t *)pathtofinish.array[ i - 1 ].nodedata)->mobj; } - if (P_TraceBotTraversal(player->mo, wp->mobj) == false) - { - // If we can't get a direct path to this waypoint, stop predicting. - distanceleft = 0; - radreduce = FRACUNIT >> 1; - break; - } - 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; + if (P_TraceBotTraversal(player->mo, wp->mobj) == false) + { + // If we can't get a direct path to this waypoint, predict less. + distanceleft -= disttonext; + radreduce = FRACUNIT >> 1; + } + if (wp->mobj->radius < smallestradius) { smallestradius = wp->mobj->radius; @@ -717,12 +717,35 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) // We're done!! break; } - } - if (i == pathtofinish.numnodes) - { - // Reached the finish!! - distanceleft = 0; + if (i == pathtofinish.numnodes-1 && disttonext > 0) + { + // We were pathfinding to the finish, but we want to go past it. + // Set up a new pathfind. + + waypoint_t *next = NULL; + + if (finishLine->numnextwaypoints == 0) + { + distanceleft = 0; + break; + } + + // default to first one + next = wp->nextwaypoints[0]; + + pathfindsuccess = K_PathfindToWaypoint( + next, finishLine, + &pathtofinish, + useshortcuts, huntbackwards + ); + + if (pathfindsuccess == false) + { + distanceleft = 0; + break; + } + } } Z_Free(pathtofinish.array); From 7d67e02ea39523003e7bd319da6ea01d9279af92 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 27 Aug 2022 00:04:33 -0400 Subject: [PATCH 08/17] Bot perfstats Show how long they take to think on all of their main tasks --- src/d_clisrv.c | 10 ++-- src/d_netcmd.c | 9 +++- src/k_bot.c | 7 +++ src/k_botsearch.c | 7 ++- src/lua_hooklib.c | 4 +- src/m_perfstats.c | 126 ++++++++++++++++++++++++++++++++++++++++++++-- src/m_perfstats.h | 22 ++++++++ 7 files changed, 175 insertions(+), 10 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index e26debd91..f26ec7274 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -5092,7 +5092,7 @@ static void SV_Maketic(void) { INT32 i; - ps_botticcmd_time = 0; + PS_ResetBotInfo(); for (i = 0; i < MAXPLAYERS; i++) { @@ -5101,9 +5101,13 @@ static void SV_Maketic(void) if (K_PlayerUsesBotMovement(&players[i])) { - precise_t t = I_GetPreciseTime(); + const precise_t t = I_GetPreciseTime(); + K_BuildBotTiccmd(&players[i], &netcmds[maketic%BACKUPTICS][i]); - ps_botticcmd_time += I_GetPreciseTime() - t; + + ps_bots[i].isBot = true; + ps_bots[i].total = I_GetPreciseTime() - t; + ps_botticcmd_time += ps_bots[i].total; continue; } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 7e8143427..1fef5acd1 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -61,6 +61,7 @@ #include "k_follower.h" #include "doomstat.h" #include "deh_tables.h" +#include "m_perfstats.h" #ifdef NETGAME_DEVMODE #define CV_RESTRICT CV_NETVAR @@ -511,7 +512,13 @@ consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_ consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL); static CV_PossibleValue_t perfstats_cons_t[] = { - {0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}}; + {PS_OFF, "Off"}, + {PS_RENDER, "Rendering"}, + {PS_LOGIC, "Logic"}, + {PS_BOT, "Bots"}, + {PS_THINKFRAME, "ThinkFrame"}, + {0, NULL} +}; consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL); consvar_t cv_director = CVAR_INIT ("director", "Off", 0, CV_OnOff, NULL); diff --git a/src/k_bot.c b/src/k_bot.c index 605a955c2..6bc0f573d 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -28,6 +28,7 @@ #include "r_things.h" // numskins #include "k_race.h" // finishBeamLine #include "k_boss.h" +#include "m_perfstats.h" /*-------------------------------------------------- @@ -638,6 +639,8 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t --------------------------------------------------*/ static botprediction_t *K_CreateBotPrediction(player_t *player) { + const precise_t time = I_GetPreciseTime(); + // Stair janking makes it harder to steer, so attempt to steer harder. const UINT8 jankDiv = (player->stairjank > 0) ? 2 : 1; @@ -765,6 +768,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) predict->y += P_ReturnThrustY(NULL, angletonext, min(disttonext, distanceleft) * FRACUNIT); } + ps_bots[player - players].prediction += I_GetPreciseTime() - time; return predict; } @@ -1219,6 +1223,7 @@ static INT32 K_HandleBotReverse(player_t *player, ticcmd_t *cmd, botprediction_t --------------------------------------------------*/ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { + precise_t t = 0; botprediction_t *predict = NULL; boolean trySpindash = true; angle_t destangle = 0; @@ -1439,7 +1444,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) { // Don't pointlessly try to use rings/sneakers while charging a spindash. // TODO: Allowing projectile items like orbinaut while e-braking would be nice, maybe just pass in the spindash variable? + t = I_GetPreciseTime(); K_BotItemUsage(player, cmd, turnamt); + ps_bots[player - players].item = I_GetPreciseTime() - t; } if (turnamt != 0) diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 1192324e3..af7464c30 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -27,6 +27,7 @@ #include "m_random.h" #include "r_things.h" // numskins #include "p_slopes.h" // P_GetZAt +#include "m_perfstats.h" struct globalsmuggle { @@ -613,6 +614,8 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) --------------------------------------------------*/ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) { + const precise_t time = I_GetPreciseTime(); + INT32 xl, xh, yl, yh, bx, by; fixed_t distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); @@ -727,7 +730,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) // Check if our side is invalid, if so, don't do the code below. if (gotoSide != -1 && globalsmuggle.gotoObjs[gotoSide] == 0) { - // Do not use a side + // Do not use a side gotoSide = -1; } @@ -769,6 +772,8 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) //distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); } } + + ps_bots[player - players].nudge += I_GetPreciseTime() - time; } /*-------------------------------------------------- diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 0a46674c2..771182a59 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -482,7 +482,7 @@ void LUAh_ThinkFrame(void) if (hookp->type != hook_ThinkFrame) continue; - if (cv_perfstats.value == 3) + if (cv_perfstats.value == PS_THINKFRAME) time_taken = I_GetPreciseTime(); PushHook(gL, hookp); if (lua_pcall(gL, 0, 0, 1)) { @@ -491,7 +491,7 @@ void LUAh_ThinkFrame(void) lua_pop(gL, 1); hookp->error = true; } - if (cv_perfstats.value == 3) + if (cv_perfstats.value == PS_THINKFRAME) { lua_Debug ar; time_taken = I_GetPreciseTime() - time_taken; diff --git a/src/m_perfstats.c b/src/m_perfstats.c index a1d4d0fba..0be2eb805 100644 --- a/src/m_perfstats.c +++ b/src/m_perfstats.c @@ -18,6 +18,7 @@ #include "i_time.h" #include "z_zone.h" #include "p_local.h" +#include "g_game.h" #ifdef HWRENDER #include "hardware/hw_main.h" @@ -62,6 +63,8 @@ ps_hookinfo_t *thinkframe_hooks = NULL; int thinkframe_hooks_length = 0; int thinkframe_hooks_capacity = 16; +ps_botinfo_t ps_bots[MAXPLAYERS]; + static INT32 draw_row; void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) @@ -85,6 +88,12 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src) thinkframe_hooks_length = index + 1; } +void PS_ResetBotInfo(void) +{ + memset(ps_bots, 0, sizeof(ps_bots)); + ps_botticcmd_time = 0; +} + static void PS_SetFrameTime(void) { precise_t currenttime = I_GetPreciseTime(); @@ -486,15 +495,126 @@ void M_DrawPerfStats(void) PS_SetFrameTime(); - if (cv_perfstats.value == 1) // rendering + if (cv_perfstats.value == PS_RENDER) // rendering { M_DrawRenderStats(); } - else if (cv_perfstats.value == 2) // logic + else if (cv_perfstats.value == PS_LOGIC) // logic { M_DrawTickStats(); } - else if (cv_perfstats.value == 3) // lua thinkframe + else if (cv_perfstats.value == PS_BOT) // bot ticcmd + { + if (vid.width < 640 || vid.height < 400) // low resolution + { + // it's not gonna fit very well.. + V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400"); + } + else // high resolution + { + precise_t otherTime = 0; + int i; + + // text writing position + int x = 2; + int y = 4; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (ps_bots[i].isBot == false) + { + continue; + } + + snprintf(s, sizeof s - 1, "Bot %d (%s):", i + 1, player_names[i]); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].total) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Prediction:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].prediction) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Nudge:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].nudge) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Item:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "%ld", (long)((ps_bots[i].item) / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + snprintf(s, sizeof s - 1, "Other:"); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + otherTime = ps_bots[i].total - ps_bots[i].prediction - ps_bots[i].nudge - ps_bots[i].item; + snprintf(s, sizeof s - 1, "%ld", (long)(otherTime / (I_GetPrecisePrecision() / 1000000))); + V_DrawRightAlignedSmallString(x + 98, y, V_MONOSPACE | V_ALLOWLOWERCASE, s); + + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + + // add an extra space + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + } + } + } + else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe { if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) return; diff --git a/src/m_perfstats.h b/src/m_perfstats.h index dae2f2030..2c448031c 100644 --- a/src/m_perfstats.h +++ b/src/m_perfstats.h @@ -16,6 +16,15 @@ #include "lua_script.h" #include "p_local.h" +typedef enum +{ + PS_OFF = 0, + PS_RENDER, + PS_LOGIC, + PS_BOT, + PS_THINKFRAME, +} ps_types_t; + extern precise_t ps_tictime; extern precise_t ps_playerthink_time; @@ -37,6 +46,19 @@ typedef struct void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src); +typedef struct +{ + boolean isBot; + precise_t total; + precise_t prediction; // K_CreateBotPrediction + precise_t nudge; // K_NudgePredictionTowardsObjects + precise_t item; // K_BotItemUsage +} ps_botinfo_t; + +extern ps_botinfo_t ps_bots[MAXPLAYERS]; + +void PS_ResetBotInfo(void); + void M_DrawPerfStats(void); #endif From b9e3bdff94f5e248ae2222b59b81ea90766df046 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 25 May 2022 23:01:47 -0400 Subject: [PATCH 09/17] Better tripwire leniency vfx --- src/d_player.h | 2 + src/deh_tables.c | 18 ++++++ src/hardware/hw_main.c | 2 +- src/info.c | 45 +++++++++++++- src/info.h | 19 +++++- src/k_kart.c | 132 ++++++++++++----------------------------- src/lua_mobjlib.c | 10 +++- src/p_mobj.c | 41 +++++++++++++ src/p_mobj.h | 2 + src/p_saveg.c | 12 +++- src/r_things.c | 2 +- 11 files changed, 185 insertions(+), 100 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 33e7026e3..31154ea76 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -260,6 +260,8 @@ typedef enum #define TUMBLEBOUNCES 3 #define TUMBLEGRAVITY (4*FRACUNIT) +#define TRIPWIRETIME (TICRATE) + //} // for kickstartaccel diff --git a/src/deh_tables.c b/src/deh_tables.c index 2796b23dc..2be68bd1c 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3805,6 +3805,22 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BATTLEBUMPER_EXBLAST9", "S_BATTLEBUMPER_EXBLAST10", + // Tripwire + "S_TRIPWIREBOOST_TOP1", + "S_TRIPWIREBOOST_TOP2", + "S_TRIPWIREBOOST_TOP3", + "S_TRIPWIREBOOST_TOP4", + "S_TRIPWIREBOOST_TOP5", + "S_TRIPWIREBOOST_TOP6", + "S_TRIPWIREBOOST_TOP7", + "S_TRIPWIREBOOST_BOTTOM1", + "S_TRIPWIREBOOST_BOTTOM2", + "S_TRIPWIREBOOST_BOTTOM3", + "S_TRIPWIREBOOST_BOTTOM4", + "S_TRIPWIREBOOST_BOTTOM5", + "S_TRIPWIREBOOST_BOTTOM6", + "S_TRIPWIREBOOST_BOTTOM7", + // DEZ respawn laser "S_DEZLASER", "S_DEZLASER_TRAIL1", @@ -5338,6 +5354,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_BATTLEBUMPER_DEBRIS", "MT_BATTLEBUMPER_BLAST", + "MT_TRIPWIREBOOST", + "MT_DEZLASER", "MT_WAYPOINT", diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 871ecf6ad..01e900c38 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5129,7 +5129,7 @@ static void HWR_ProjectSprite(mobj_t *thing) R_InterpolateMobjState(thing, FRACUNIT, &interp); } - dispoffset = thing->info->dispoffset; + dispoffset = thing->dispoffset; // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) diff --git a/src/info.c b/src/info.c index db656a3a7..afd2db52a 100644 --- a/src/info.c +++ b/src/info.c @@ -580,7 +580,7 @@ char sprnames[NUMSPRITES + 1][5] = "BEXS", // Battle Bumper Explosion: Shell "BDEB", // Battle Bumper Explosion: Debris "BEXB", // Battle Bumper Explosion: Blast - + "TWBT", // Tripwire Boost "DEZL", // DEZ Laser respawn // Additional Kart Objects @@ -4361,6 +4361,22 @@ state_t states[NUMSTATES] = {SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS80, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST10}, // S_BATTLEBUMPER_EXBLAST9 {SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS90, 2, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER_EXBLAST10 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP2}, // S_TRIPWIREBOOST_TOP1 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|1, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP3}, // S_TRIPWIREBOOST_TOP2 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|2, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP4}, // S_TRIPWIREBOOST_TOP3 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|3, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP5}, // S_TRIPWIREBOOST_TOP4 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|4, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP6}, // S_TRIPWIREBOOST_TOP5 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|5, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP7}, // S_TRIPWIREBOOST_TOP6 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|6, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP1}, // S_TRIPWIREBOOST_TOP7 + + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM2}, // S_TRIPWIREBOOST_BOTTOM1 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|1, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM3}, // S_TRIPWIREBOOST_BOTTOM2 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|2, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM4}, // S_TRIPWIREBOOST_BOTTOM3 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|3, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM5}, // S_TRIPWIREBOOST_BOTTOM4 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|4, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM6}, // S_TRIPWIREBOOST_BOTTOM5 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|5, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM7}, // S_TRIPWIREBOOST_BOTTOM6 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|6, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM1}, // S_TRIPWIREBOOST_BOTTOM7 + {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER {SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1 {SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL3}, // S_DEZLASER_TRAIL2 @@ -24164,6 +24180,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_TRIPWIREBOOST + -1, // doomednum + S_TRIPWIREBOOST_TOP1, // spawnstate + 1000, // spawnhealth + S_TRIPWIREBOOST_BOTTOM1, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 16*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags + S_NULL // raisestate + }, + { // MT_DEZLASER -1, // doomednum S_DEZLASER, // spawnstate diff --git a/src/info.h b/src/info.h index 4a490ba9f..32f44df12 100644 --- a/src/info.h +++ b/src/info.h @@ -1126,7 +1126,7 @@ typedef enum sprite SPR_BEXS, // Battle Bumper Explosion: Shell SPR_BDEB, // Battle Bumper Explosion: Debris SPR_BEXB, // Battle Bumper Explosion: Blast - + SPR_TWBT, // Tripwire Boost SPR_DEZL, // DEZ Laser respawn // Additional Kart Objects @@ -4794,6 +4794,21 @@ typedef enum state S_BATTLEBUMPER_EXBLAST9, S_BATTLEBUMPER_EXBLAST10, + S_TRIPWIREBOOST_TOP1, + S_TRIPWIREBOOST_TOP2, + S_TRIPWIREBOOST_TOP3, + S_TRIPWIREBOOST_TOP4, + S_TRIPWIREBOOST_TOP5, + S_TRIPWIREBOOST_TOP6, + S_TRIPWIREBOOST_TOP7, + S_TRIPWIREBOOST_BOTTOM1, + S_TRIPWIREBOOST_BOTTOM2, + S_TRIPWIREBOOST_BOTTOM3, + S_TRIPWIREBOOST_BOTTOM4, + S_TRIPWIREBOOST_BOTTOM5, + S_TRIPWIREBOOST_BOTTOM6, + S_TRIPWIREBOOST_BOTTOM7, + // DEZ Laser respawn S_DEZLASER, S_DEZLASER_TRAIL1, @@ -6364,6 +6379,8 @@ typedef enum mobj_type MT_BATTLEBUMPER_DEBRIS, MT_BATTLEBUMPER_BLAST, + MT_TRIPWIREBOOST, + MT_DEZLASER, MT_WAYPOINT, diff --git a/src/k_kart.c b/src/k_kart.c index f47bf3b17..ed4510534 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4939,90 +4939,6 @@ void K_DriftDustHandling(mobj_t *spawner) } } -static void K_SpawnTripwireVFX(mobj_t *mo) -{ - tic_t t = leveltime; - angle_t ang, aoff; - SINT8 sign = 1; - boolean altColor = false; - mobj_t *dust; - boolean drifting = false; - UINT8 i; - - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - if (!P_IsObjectOnGround(mo)) - return; - - if (mo->player) - { - ang = mo->player->drawangle; - - if (mo->player->drift != 0) - { - drifting = true; - ang += (mo->player->drift * ((ANGLE_270 + ANGLE_22h) / 5)); // -112.5 doesn't work. I fucking HATE SRB2 angles - if (mo->player->drift < 0) - sign = 1; - else - sign = -1; - } - } - else - ang = mo->angle; - - if (drifting == false) - { - i = (t & 1); - - if (i & 1) - sign = -1; - else - sign = 1; - } - else - { - if (t & 1) - { - return; - } - - t /= 2; - i = (t & 1); - } - - aoff = (ang + ANGLE_180) + (ANGLE_45 * sign); - - dust = P_SpawnMobj(mo->x + FixedMul(24*mo->scale, FINECOSINE(aoff>>ANGLETOFINESHIFT)), - mo->y + FixedMul(24*mo->scale, FINESINE(aoff>>ANGLETOFINESHIFT)), - mo->z, MT_DRIFTDUST); - - P_SetTarget(&dust->target, mo); - P_InitAngle(dust, ang - (ANGLE_90 * sign)); // point completely perpendicular from the player - P_SetScale(dust, mo->scale); - dust->destscale = mo->scale * 6; - dust->scalespeed = mo->scale/12; - K_FlipFromObject(dust, mo); - - altColor = (sign > 0); - - if ((t / 2) & 1) - { - dust->tics++; // "randomize" animation - altColor = !altColor; - } - - dust->colorized = true; - dust->color = altColor ? SKINCOLOR_BLOSSOM : SKINCOLOR_JAWZ; - - dust->momx = (4*mo->momx)/5; - dust->momy = (4*mo->momy)/5; - dust->momz = (4*P_GetMobjZMovement(mo))/5; - - P_Thrust(dust, dust->angle, 4*mo->scale); -} - void K_Squish(mobj_t *mo) { const fixed_t maxstretch = 4*FRACUNIT; @@ -7289,6 +7205,43 @@ static void K_LookForRings(mobj_t *pmo) P_BlockThingsIterator(bx, by, PIT_AttractingRings); } +static void K_UpdateTripwire(player_t *player) +{ + fixed_t speedThreshold = K_GetKartSpeed(player, false) *3/4; + boolean goodSpeed = (player->speed >= speedThreshold); + + if (player->tripwireLeniency > 0) + { + player->tripwireLeniency--; + } + + if (goodSpeed == false && player->tripwireLeniency > 0) + { + // Decrease at double speed when your speed is bad. + player->tripwireLeniency--; + } + + if (K_TripwirePassConditions(player) == true) + { + if (player->tripwireLeniency == 0) + { + mobj_t *front = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRIPWIREBOOST); + mobj_t *back = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRIPWIREBOOST); + + P_SetTarget(&front->target, player->mo); + P_SetTarget(&back->target, player->mo); + + front->dispoffset = 1; + + back->dispoffset = -1; + back->extravalue1 = 1; + P_SetMobjState(back, S_TRIPWIREBOOST_BOTTOM1); + } + + player->tripwireLeniency = max(player->tripwireLeniency, TRIPWIRETIME); + } +} + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -7644,16 +7597,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_HandleTumbleBounce(player); } - if (player->tripwireLeniency > 0) - { - player->tripwireLeniency--; - K_SpawnTripwireVFX(player->mo); - } - - if (K_TripwirePassConditions(player) == true) - { - player->tripwireLeniency = max(player->tripwireLeniency, TICRATE); - } + K_UpdateTripwire(player); K_KartPlayerHUDUpdate(player); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 4fd02d9a1..418a43bf9 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -99,7 +99,8 @@ enum mobj_e { mobj_sprxoff, mobj_spryoff, mobj_sprzoff, - mobj_hitlag + mobj_hitlag, + mobj_dispoffset }; static const char *const mobj_opt[] = { @@ -180,6 +181,7 @@ static const char *const mobj_opt[] = { "spryoff", "sprzoff", "hitlag", + "dispoffset", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -458,6 +460,9 @@ static int mobj_get(lua_State *L) case mobj_hitlag: lua_pushinteger(L, mo->hitlag); break; + case mobj_dispoffset: + lua_pushinteger(L, mo->dispoffset); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -830,6 +835,9 @@ static int mobj_set(lua_State *L) case mobj_hitlag: mo->hitlag = luaL_checkinteger(L, 3); break; + case mobj_dispoffset: + mo->dispoffset = luaL_checkinteger(L, 3); + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_mobj.c b/src/p_mobj.c index 4731094e1..6f7bb34b5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7163,6 +7163,47 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } } break; + case MT_TRIPWIREBOOST: + if (!mobj->target || !mobj->target->health + || !mobj->target->player || !mobj->target->player->tripwireLeniency) + { + P_RemoveMobj(mobj); + return false; + } + + mobj->angle = K_MomentumAngle(mobj->target); + P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height >> 1)); + mobj->target->destscale = mobj->target->scale; + P_SetScale(mobj, mobj->target->scale); + + if (mobj->extravalue1) + { + mobj->angle += ANGLE_180; + } + + { + UINT8 trans = ((mobj->target->player->tripwireLeniency + 1) * (NUMTRANSMAPS+1)) / TRIPWIRETIME; + + if (trans > NUMTRANSMAPS) + trans = NUMTRANSMAPS; + + trans = NUMTRANSMAPS - trans; + + if (trans >= NUMTRANSMAPS) + { + mobj->renderflags |= RF_DONTDRAW; + } + else + { + mobj->renderflags &= ~(RF_TRANSMASK); + + if (trans != 0) + { + mobj->renderflags |= (trans << RF_TRANSSHIFT); + } + } + } + break; case MT_BOOSTFLAME: if (!mobj->target || !mobj->target->health) { diff --git a/src/p_mobj.h b/src/p_mobj.h index 0f05d7c90..3b947bec6 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -408,6 +408,8 @@ typedef struct mobj_s struct terrain_s *terrain; // Terrain definition of the floor this object last hit. NULL when in the air. INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls + INT32 dispoffset; + // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 81adeca60..4422eaf20 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1600,7 +1600,7 @@ typedef enum MD2_SPRITEXOFFSET = 1<<20, MD2_SPRITEYOFFSET = 1<<21, MD2_FLOORSPRITESLOPE = 1<<22, - // 1<<23 was taken out, maybe reuse later + MD2_DISPOFFSET = 1<<23, MD2_HITLAG = 1<<24, MD2_WAYPOINTCAP = 1<<25, MD2_KITEMCAP = 1<<26, @@ -1841,6 +1841,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) } if (mobj->hitlag) diff2 |= MD2_HITLAG; + if (mobj->dispoffset) + diff2 |= MD2_DISPOFFSET; if (mobj == waypointcap) diff2 |= MD2_WAYPOINTCAP; if (mobj == kitemcap) @@ -2049,6 +2051,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) { WRITEINT32(save_p, mobj->hitlag); } + if (diff2 & MD2_DISPOFFSET) + { + WRITEINT32(save_p, mobj->dispoffset); + } if (diff2 & MD2_LASTMOMZ) { WRITEINT32(save_p, mobj->lastmomz); @@ -3154,6 +3160,10 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) { mobj->hitlag = READINT32(save_p); } + if (diff2 & MD2_DISPOFFSET) + { + mobj->dispoffset = READINT32(save_p); + } if (diff2 & MD2_LASTMOMZ) { mobj->lastmomz = READINT32(save_p); diff --git a/src/r_things.c b/src/r_things.c index 4d5df9484..cc5694dff 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1503,7 +1503,7 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; - INT32 dispoffset = thing->info->dispoffset; + INT32 dispoffset = thing->dispoffset; //SoM: 3/17/2000 fixed_t gz = 0, gzt = 0; From bdd786d8ab0c5554673f4424b5cf6149ec12e454 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 Aug 2022 18:35:38 +0100 Subject: [PATCH 10/17] BLASTER finalisation - BLASTER >= 180% speed, smaller boost otherwise - Flickers under 150% - Invinc-coloured when invincibility - Ketchup coloured when boosting, invisible otherwise --- src/info.c | 29 ++++++++++------------------- src/info.h | 21 ++++++--------------- src/k_kart.c | 22 +++++++++++----------- src/p_mobj.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/info.c b/src/info.c index afd2db52a..8fd5f929c 100644 --- a/src/info.c +++ b/src/info.c @@ -580,7 +580,8 @@ char sprnames[NUMSPRITES + 1][5] = "BEXS", // Battle Bumper Explosion: Shell "BDEB", // Battle Bumper Explosion: Debris "BEXB", // Battle Bumper Explosion: Blast - "TWBT", // Tripwire Boost + "TWBS", // Tripwire Boost + "TWBT", // Tripwire BLASTER "DEZL", // DEZ Laser respawn // Additional Kart Objects @@ -4361,21 +4362,11 @@ state_t states[NUMSTATES] = {SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS80, 2, {NULL}, 0, 0, S_BATTLEBUMPER_EXBLAST10}, // S_BATTLEBUMPER_EXBLAST9 {SPR_BEXB, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_TRANS90, 2, {NULL}, 0, 0, S_NULL}, // S_BATTLEBUMPER_EXBLAST10 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP2}, // S_TRIPWIREBOOST_TOP1 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|1, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP3}, // S_TRIPWIREBOOST_TOP2 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|2, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP4}, // S_TRIPWIREBOOST_TOP3 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|3, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP5}, // S_TRIPWIREBOOST_TOP4 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|4, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP6}, // S_TRIPWIREBOOST_TOP5 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|5, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP7}, // S_TRIPWIREBOOST_TOP6 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|6, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_TOP1}, // S_TRIPWIREBOOST_TOP7 + {SPR_TWBS, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_TOP + {SPR_TWBS, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|FF_VERTICALFLIP|FF_HORIZONTALFLIP, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_BOTTOM - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM2}, // S_TRIPWIREBOOST_BOTTOM1 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|1, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM3}, // S_TRIPWIREBOOST_BOTTOM2 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|2, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM4}, // S_TRIPWIREBOOST_BOTTOM3 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|3, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM5}, // S_TRIPWIREBOOST_BOTTOM4 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|4, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM6}, // S_TRIPWIREBOOST_BOTTOM5 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|5, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM7}, // S_TRIPWIREBOOST_BOTTOM6 - {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_VERTICALFLIP|FF_HORIZONTALFLIP|6, 2, {NULL}, 0, 0, S_TRIPWIREBOOST_BOTTOM1}, // S_TRIPWIREBOOST_BOTTOM7 + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_BLAST_TOP + {SPR_TWBT, FF_FULLBRIGHT|FF_ADD|FF_ANIMATE|FF_VERTICALFLIP|FF_HORIZONTALFLIP, -1, {NULL}, 6, 2, S_NULL}, // S_TRIPWIREBOOST_BLAST_BOTTOM {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER {SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1 @@ -24182,17 +24173,17 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_TRIPWIREBOOST -1, // doomednum - S_TRIPWIREBOOST_TOP1, // spawnstate + S_TRIPWIREBOOST_TOP, // spawnstate 1000, // spawnhealth - S_TRIPWIREBOOST_BOTTOM1, // seestate + S_TRIPWIREBOOST_BOTTOM, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate + S_TRIPWIREBOOST_BLAST_TOP, // meleestate + S_TRIPWIREBOOST_BLAST_BOTTOM, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound diff --git a/src/info.h b/src/info.h index 32f44df12..175de9cab 100644 --- a/src/info.h +++ b/src/info.h @@ -1126,7 +1126,8 @@ typedef enum sprite SPR_BEXS, // Battle Bumper Explosion: Shell SPR_BDEB, // Battle Bumper Explosion: Debris SPR_BEXB, // Battle Bumper Explosion: Blast - SPR_TWBT, // Tripwire Boost + SPR_TWBS, // Tripwire Boost + SPR_TWBT, // Tripwire BLASTER SPR_DEZL, // DEZ Laser respawn // Additional Kart Objects @@ -4794,20 +4795,10 @@ typedef enum state S_BATTLEBUMPER_EXBLAST9, S_BATTLEBUMPER_EXBLAST10, - S_TRIPWIREBOOST_TOP1, - S_TRIPWIREBOOST_TOP2, - S_TRIPWIREBOOST_TOP3, - S_TRIPWIREBOOST_TOP4, - S_TRIPWIREBOOST_TOP5, - S_TRIPWIREBOOST_TOP6, - S_TRIPWIREBOOST_TOP7, - S_TRIPWIREBOOST_BOTTOM1, - S_TRIPWIREBOOST_BOTTOM2, - S_TRIPWIREBOOST_BOTTOM3, - S_TRIPWIREBOOST_BOTTOM4, - S_TRIPWIREBOOST_BOTTOM5, - S_TRIPWIREBOOST_BOTTOM6, - S_TRIPWIREBOOST_BOTTOM7, + S_TRIPWIREBOOST_TOP, + S_TRIPWIREBOOST_BOTTOM, + S_TRIPWIREBOOST_BLAST_TOP, + S_TRIPWIREBOOST_BLAST_BOTTOM, // DEZ Laser respawn S_DEZLASER, diff --git a/src/k_kart.c b/src/k_kart.c index ed4510534..e05eab0c4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7207,23 +7207,23 @@ static void K_LookForRings(mobj_t *pmo) static void K_UpdateTripwire(player_t *player) { - fixed_t speedThreshold = K_GetKartSpeed(player, false) *3/4; + fixed_t speedThreshold = (3*K_GetKartSpeed(player, false, true))/4; boolean goodSpeed = (player->speed >= speedThreshold); + boolean boostExists = (player->tripwireLeniency > 0); // can't be checked later because of subtractions... - if (player->tripwireLeniency > 0) + if (boostExists) { player->tripwireLeniency--; - } - - if (goodSpeed == false && player->tripwireLeniency > 0) - { - // Decrease at double speed when your speed is bad. - player->tripwireLeniency--; + if (goodSpeed == false && player->tripwireLeniency > 0) + { + // Decrease at double speed when your speed is bad. + player->tripwireLeniency--; + } } if (K_TripwirePassConditions(player) == true) { - if (player->tripwireLeniency == 0) + if (!boostExists) { mobj_t *front = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRIPWIREBOOST); mobj_t *back = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_TRIPWIREBOOST); @@ -7232,10 +7232,10 @@ static void K_UpdateTripwire(player_t *player) P_SetTarget(&back->target, player->mo); front->dispoffset = 1; - + front->old_angle = back->old_angle = K_MomentumAngle(player->mo); back->dispoffset = -1; back->extravalue1 = 1; - P_SetMobjState(back, S_TRIPWIREBOOST_BOTTOM1); + P_SetMobjState(back, S_TRIPWIREBOOST_BOTTOM); } player->tripwireLeniency = max(player->tripwireLeniency, TRIPWIRETIME); diff --git a/src/p_mobj.c b/src/p_mobj.c index 6f7bb34b5..ee4b85059 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7182,6 +7182,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } { + fixed_t convSpeed = (mobj->target->player->speed * 100) / K_GetKartSpeed(mobj->target->player, false, true); UINT8 trans = ((mobj->target->player->tripwireLeniency + 1) * (NUMTRANSMAPS+1)) / TRIPWIRETIME; if (trans > NUMTRANSMAPS) @@ -7189,18 +7190,58 @@ static boolean P_MobjRegularThink(mobj_t *mobj) trans = NUMTRANSMAPS - trans; - if (trans >= NUMTRANSMAPS) + if ((trans >= NUMTRANSMAPS) // not a valid visibility + || (convSpeed < 150 && !(mobj->target->player->tripwireLeniency & 1)) // < 150% flickering + || (mobj->target->player->curshield == KSHIELD_FLAME && mobj->target->player->flamedash <= 0)) // flame shield but NOT boosting { mobj->renderflags |= RF_DONTDRAW; } else { - mobj->renderflags &= ~(RF_TRANSMASK); + boolean blastermode = (convSpeed >= 180); + mobj->renderflags &= ~(RF_TRANSMASK|RF_DONTDRAW); if (trans != 0) { mobj->renderflags |= (trans << RF_TRANSSHIFT); } + mobj->renderflags |= (mobj->target->renderflags & RF_DONTDRAW); + + if (mobj->target->player->invincibilitytimer > 0) + { + if (mobj->target->player->invincibilitytimer > itemtime+(2*TICRATE)) + { + mobj->color = K_RainbowColor(leveltime / 2); + } + else + { + mobj->color = SKINCOLOR_INVINCFLASH; + } + mobj->colorized = true; + } + else if (mobj->target->player->curshield == KSHIELD_FLAME && mobj->target->player->flamedash > 0) + { + mobj->color = SKINCOLOR_KETCHUP; + mobj->colorized = true; + } + else + { + mobj->color = SKINCOLOR_NONE; + mobj->colorized = false; + } + + if (blastermode == !(mobj->flags2 & MF2_AMBUSH)) + { + mobj->flags2 ^= MF2_AMBUSH; + if (blastermode) + { + P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BLAST_BOTTOM : S_TRIPWIREBOOST_BLAST_TOP); + } + else + { + P_SetMobjState(mobj, (mobj->extravalue1) ? S_TRIPWIREBOOST_BOTTOM : S_TRIPWIREBOOST_TOP); + } + } } } break; @@ -9882,6 +9923,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Sprite rendering mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexoffset = mobj->spriteyoffset = 0; + mobj->dispoffset = info->dispoffset; mobj->floorspriteslope = NULL; // set subsector and/or block links From ebcb76645b8479e9c9fac621cf01f713cb7a86ad Mon Sep 17 00:00:00 2001 From: SteelT Date: Mon, 29 Aug 2022 20:16:46 -0400 Subject: [PATCH 11/17] Adjust default camera dist and height cam_dist is now 190 cam_height is now 75 --- src/p_user.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index ec4d540c1..4030232f7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2727,17 +2727,17 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0, static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL), - CVAR_INIT ("cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL), - CVAR_INIT ("cam3_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL), - CVAR_INIT ("cam4_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL) + CVAR_INIT ("cam_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam2_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam3_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam4_dist", "190", CV_FLOAT|CV_SAVE, NULL, NULL) }; consvar_t cv_cam_height[MAXSPLITSCREENPLAYERS] = { - CVAR_INIT ("cam_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL), - CVAR_INIT ("cam2_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL), - CVAR_INIT ("cam3_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL), - CVAR_INIT ("cam4_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL) + CVAR_INIT ("cam_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam2_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam3_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam4_height", "75", CV_FLOAT|CV_SAVE, NULL, NULL) }; consvar_t cv_cam_still[MAXSPLITSCREENPLAYERS] = { From 31835b380b6c52e584634a3d584e1426b344a947 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 29 Aug 2022 17:02:34 -0700 Subject: [PATCH 12/17] Set tripwire blaster destscale instead of player's --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ee4b85059..a09c9c3c6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7173,7 +7173,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->angle = K_MomentumAngle(mobj->target); P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height >> 1)); - mobj->target->destscale = mobj->target->scale; + mobj->destscale = mobj->target->scale; P_SetScale(mobj, mobj->target->scale); if (mobj->extravalue1) From 97fab1ab20872b2750f6cb1bebb35a5327b54840 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Aug 2022 18:16:51 +0100 Subject: [PATCH 13/17] Levels of tripwire pass conditions. - Invinc and sneaker can go up to BLASTER. - Flame shield and momentum make only the boost by themselves. - Hyuu and grow ignore tripwire so don't make ANY aura without any of the prior also occouring. --- src/k_bot.c | 2 +- src/k_kart.c | 25 +++++++++++++++++-------- src/k_kart.h | 8 +++++++- src/p_mobj.c | 5 +++-- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/k_bot.c b/src/k_bot.c index 0ae14c50e..f784afcf6 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -279,7 +279,7 @@ boolean K_BotCanTakeCut(player_t *player) { if ( #if 1 - K_TripwirePassConditions(player) == true + K_TripwirePassConditions(player) != TRIPWIRE_NONE #else K_ApplyOffroad(player) == false #endif diff --git a/src/k_kart.c b/src/k_kart.c index e05eab0c4..246e1b777 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2944,23 +2944,32 @@ boolean K_SlopeResistance(player_t *player) return false; } -boolean K_TripwirePassConditions(player_t *player) +UINT8 K_TripwirePassConditions(player_t *player) { if ( player->invincibilitytimer || - player->sneakertimer || - player->growshrinktimer > 0 || + player->sneakertimer + ) + return TRIPWIRE_BLASTER; + + if ( player->flamedash || - player->hyudorotimer || player->speed > 2 * K_GetKartSpeed(player, false, true) ) - return true; - return false; + return TRIPWIRE_BOOST; + + if ( + player->growshrinktimer > 0 || + player->hyudorotimer + ) + return TRIPWIRE_IGNORE; + + return TRIPWIRE_NONE; } boolean K_TripwirePass(player_t *player) { - return (K_TripwirePassConditions(player) || (player->tripwireLeniency > 0)); + return ((K_TripwirePassConditions(player) != TRIPWIRE_NONE) || (player->tripwireLeniency > 0)); } boolean K_WaterRun(player_t *player) @@ -7221,7 +7230,7 @@ static void K_UpdateTripwire(player_t *player) } } - if (K_TripwirePassConditions(player) == true) + if (K_TripwirePassConditions(player) != TRIPWIRE_NONE) { if (!boostExists) { diff --git a/src/k_kart.h b/src/k_kart.h index 797899cea..271ce5ac3 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -121,7 +121,13 @@ void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); boolean K_SlopeResistance(player_t *player); -boolean K_TripwirePassConditions(player_t *player); + +#define TRIPWIRE_BLASTER 0x03 +#define TRIPWIRE_BOOST 0x02 +#define TRIPWIRE_IGNORE 0x01 +#define TRIPWIRE_NONE 0x00 +UINT8 K_TripwirePassConditions(player_t *player); + boolean K_TripwirePass(player_t *player); boolean K_WaterRun(player_t *player); void K_ApplyTripWire(player_t *player, tripwirestate_t state); diff --git a/src/p_mobj.c b/src/p_mobj.c index a09c9c3c6..3e5b0768c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7184,6 +7184,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { fixed_t convSpeed = (mobj->target->player->speed * 100) / K_GetKartSpeed(mobj->target->player, false, true); UINT8 trans = ((mobj->target->player->tripwireLeniency + 1) * (NUMTRANSMAPS+1)) / TRIPWIRETIME; + UINT8 triplevel = K_TripwirePassConditions(mobj->target->player); if (trans > NUMTRANSMAPS) trans = NUMTRANSMAPS; @@ -7192,13 +7193,13 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if ((trans >= NUMTRANSMAPS) // not a valid visibility || (convSpeed < 150 && !(mobj->target->player->tripwireLeniency & 1)) // < 150% flickering - || (mobj->target->player->curshield == KSHIELD_FLAME && mobj->target->player->flamedash <= 0)) // flame shield but NOT boosting + || (triplevel < TRIPWIRE_BOOST)) // Not strong enough to make an aura { mobj->renderflags |= RF_DONTDRAW; } else { - boolean blastermode = (convSpeed >= 180); + boolean blastermode = (convSpeed >= 180) && (triplevel >= TRIPWIRE_BLASTER); mobj->renderflags &= ~(RF_TRANSMASK|RF_DONTDRAW); if (trans != 0) From 6b8d729b2ca3430fff0fa49648b81d938bc58369 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Aug 2022 19:29:12 +0100 Subject: [PATCH 14/17] Blaster polish * Use leveltime instead of leniency for flicker, which makes it work as intended * Make the threshold for tripwire BLASTER 200% (from 180%) * Always colorize boost/BLASTER when you have a Flame Shield * Hide boost/BLASTER if you're using flamedash specifically --- src/p_mobj.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 3e5b0768c..441173a36 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7192,14 +7192,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj) trans = NUMTRANSMAPS - trans; if ((trans >= NUMTRANSMAPS) // not a valid visibility - || (convSpeed < 150 && !(mobj->target->player->tripwireLeniency & 1)) // < 150% flickering - || (triplevel < TRIPWIRE_BOOST)) // Not strong enough to make an aura + || (convSpeed < 150 && (leveltime & 1)) // < 150% flickering + || (triplevel < TRIPWIRE_BOOST) // Not strong enough to make an aura + || mobj->target->player->flamedash) // Flameshield dash { mobj->renderflags |= RF_DONTDRAW; } else { - boolean blastermode = (convSpeed >= 180) && (triplevel >= TRIPWIRE_BLASTER); + boolean blastermode = (convSpeed >= 200) && (triplevel >= TRIPWIRE_BLASTER); mobj->renderflags &= ~(RF_TRANSMASK|RF_DONTDRAW); if (trans != 0) @@ -7220,7 +7221,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } mobj->colorized = true; } - else if (mobj->target->player->curshield == KSHIELD_FLAME && mobj->target->player->flamedash > 0) + else if (mobj->target->player->curshield == KSHIELD_FLAME) { mobj->color = SKINCOLOR_KETCHUP; mobj->colorized = true; From 2c91f83a025ad458eb1d65858c6cb11a674f531c Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Aug 2022 21:22:26 +0100 Subject: [PATCH 15/17] Store tripwire pass level on the player Fixes tripwire leniency fadeout - previously broken two commits ago --- src/d_player.h | 18 ++++++++++----- src/g_game.c | 1 - src/k_kart.c | 53 ++++++++++++++++++++++++++------------------- src/k_kart.h | 8 +------ src/lua_playerlib.c | 8 +++++++ src/p_map.c | 2 +- src/p_mobj.c | 5 ++--- src/p_saveg.c | 6 +++-- src/p_spec.c | 2 +- 9 files changed, 61 insertions(+), 42 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 31154ea76..85eec2e3e 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -204,11 +204,19 @@ typedef enum typedef enum { - TRIP_NONE, - TRIP_PASSED, - TRIP_BLOCKED, + TRIPSTATE_NONE, + TRIPSTATE_PASSED, + TRIPSTATE_BLOCKED, } tripwirestate_t; +typedef enum +{ + TRIPWIRE_NONE, + TRIPWIRE_IGNORE, + TRIPWIRE_BOOST, + TRIPWIRE_BLASTER, +} tripwirepass_t; + typedef enum { // Unsynced, HUD or clientsided effects @@ -446,6 +454,8 @@ typedef struct player_s UINT16 draftleeway; // Leniency timer before removing draft power SINT8 lastdraft; // (-1 to 15) - Last player being drafted + UINT8 tripwireState; // see tripwirestate_t + UINT8 tripwirePass; // see tripwirepass_t UINT16 tripwireLeniency; // When reaching a state that lets you go thru tripwire, you get an extra second leniency after it ends to still go through it. UINT16 itemroulette; // Used for the roulette when deciding what item to give you (was "pw_kartitem") @@ -515,8 +525,6 @@ typedef struct player_s SINT8 glanceDir; // Direction the player is trying to look backwards in - UINT8 tripWireState; // see tripwirestate_t - // SINT8 lives; diff --git a/src/g_game.c b/src/g_game.c index 68286da99..155a62a0f 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2410,7 +2410,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->karthud[khud_fault] = khudfault; p->nocontrol = nocontrol; p->kickstartaccel = kickstartaccel; - p->tripWireState = TRIP_NONE; p->botvars.rubberband = FRACUNIT; p->botvars.controller = UINT16_MAX; diff --git a/src/k_kart.c b/src/k_kart.c index 246e1b777..189b946cd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2944,7 +2944,7 @@ boolean K_SlopeResistance(player_t *player) return false; } -UINT8 K_TripwirePassConditions(player_t *player) +tripwirepass_t K_TripwirePassConditions(player_t *player) { if ( player->invincibilitytimer || @@ -2969,7 +2969,7 @@ UINT8 K_TripwirePassConditions(player_t *player) boolean K_TripwirePass(player_t *player) { - return ((K_TripwirePassConditions(player) != TRIPWIRE_NONE) || (player->tripwireLeniency > 0)); + return (player->tripwirePass != TRIPWIRE_NONE); } boolean K_WaterRun(player_t *player) @@ -3676,7 +3676,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) player->tumbleBounces = 1; - if (player->tripWireState == TRIP_PASSED) + if (player->tripwireState == TRIPSTATE_PASSED) { player->tumbleHeight = 50; } @@ -3790,15 +3790,15 @@ void K_TumbleInterrupt(player_t *player) void K_ApplyTripWire(player_t *player, tripwirestate_t state) { - if (state == TRIP_PASSED) + if (state == TRIPSTATE_PASSED) S_StartSound(player->mo, sfx_ssa015); - else if (state == TRIP_BLOCKED) + else if (state == TRIPSTATE_BLOCKED) S_StartSound(player->mo, sfx_kc40); - player->tripWireState = state; + player->tripwireState = state; K_AddHitLag(player->mo, 10, false); - if (state == TRIP_PASSED && player->spinouttimer && + if (state == TRIPSTATE_PASSED && player->spinouttimer && player->speed > 2 * K_GetKartSpeed(player, false, true)) { K_TumblePlayer(player, NULL, NULL); @@ -7219,18 +7219,9 @@ static void K_UpdateTripwire(player_t *player) fixed_t speedThreshold = (3*K_GetKartSpeed(player, false, true))/4; boolean goodSpeed = (player->speed >= speedThreshold); boolean boostExists = (player->tripwireLeniency > 0); // can't be checked later because of subtractions... + tripwirepass_t triplevel = K_TripwirePassConditions(player); - if (boostExists) - { - player->tripwireLeniency--; - if (goodSpeed == false && player->tripwireLeniency > 0) - { - // Decrease at double speed when your speed is bad. - player->tripwireLeniency--; - } - } - - if (K_TripwirePassConditions(player) != TRIPWIRE_NONE) + if (triplevel != TRIPWIRE_NONE) { if (!boostExists) { @@ -7247,8 +7238,26 @@ static void K_UpdateTripwire(player_t *player) P_SetMobjState(back, S_TRIPWIREBOOST_BOTTOM); } + player->tripwirePass = triplevel; player->tripwireLeniency = max(player->tripwireLeniency, TRIPWIRETIME); } + else + { + if (boostExists) + { + player->tripwireLeniency--; + if (goodSpeed == false && player->tripwireLeniency > 0) + { + // Decrease at double speed when your speed is bad. + player->tripwireLeniency--; + } + } + + if (player->tripwireLeniency <= 0) + { + player->tripwirePass = TRIPWIRE_NONE; + } + } } /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c @@ -7718,14 +7727,14 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Handle invincibility sfx K_UpdateInvincibilitySounds(player); // Also thanks, VAda! - if (player->tripWireState != TRIP_NONE) + if (player->tripwireState != TRIPSTATE_NONE) { - if (player->tripWireState == TRIP_PASSED) + if (player->tripwireState == TRIPSTATE_PASSED) S_StartSound(player->mo, sfx_cdfm63); - else if (player->tripWireState == TRIP_BLOCKED) + else if (player->tripwireState == TRIPSTATE_BLOCKED) S_StartSound(player->mo, sfx_kc4c); - player->tripWireState = TRIP_NONE; + player->tripwireState = TRIPSTATE_NONE; } K_KartEbrakeVisuals(player); diff --git a/src/k_kart.h b/src/k_kart.h index 271ce5ac3..00c36ea76 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -121,13 +121,7 @@ void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); boolean K_SlopeResistance(player_t *player); - -#define TRIPWIRE_BLASTER 0x03 -#define TRIPWIRE_BOOST 0x02 -#define TRIPWIRE_IGNORE 0x01 -#define TRIPWIRE_NONE 0x00 -UINT8 K_TripwirePassConditions(player_t *player); - +tripwirepass_t K_TripwirePassConditions(player_t *player); boolean K_TripwirePass(player_t *player); boolean K_WaterRun(player_t *player); void K_ApplyTripWire(player_t *player, tripwirestate_t state); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index c448a287a..1d5f6bee7 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -292,6 +292,10 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->draftleeway); else if (fastcmp(field,"lastdraft")) lua_pushinteger(L, plr->lastdraft); + else if (fastcmp(field,"tripwireState")) + lua_pushinteger(L, plr->tripwireState); + else if (fastcmp(field,"tripwirePass")) + lua_pushinteger(L, plr->tripwirePass); else if (fastcmp(field,"tripwireLeniency")) lua_pushinteger(L, plr->tripwireLeniency); else if (fastcmp(field,"itemroulette")) @@ -646,6 +650,10 @@ static int player_set(lua_State *L) plr->draftleeway = luaL_checkinteger(L, 3); else if (fastcmp(field,"lastdraft")) plr->lastdraft = luaL_checkinteger(L, 3); + else if (fastcmp(field,"tripwireState")) + plr->tripwireState = luaL_checkinteger(L, 3); + else if (fastcmp(field,"tripwirePass")) + plr->tripwirePass = luaL_checkinteger(L, 3); else if (fastcmp(field,"tripwireLeniency")) plr->tripwireLeniency = luaL_checkinteger(L, 3); else if (fastcmp(field,"itemroulette")) diff --git a/src/p_map.c b/src/p_map.c index 3d6938ed2..d667b0346 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3801,7 +3801,7 @@ void P_BouncePlayerMove(mobj_t *mo) if (P_IsLineTripWire(bestslideline)) { // TRIPWIRE CANNOT BE MADE NONBOUNCY - K_ApplyTripWire(mo->player, TRIP_BLOCKED); + K_ApplyTripWire(mo->player, TRIPSTATE_BLOCKED); } else { diff --git a/src/p_mobj.c b/src/p_mobj.c index 441173a36..8e6e0eb2a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7184,7 +7184,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) { fixed_t convSpeed = (mobj->target->player->speed * 100) / K_GetKartSpeed(mobj->target->player, false, true); UINT8 trans = ((mobj->target->player->tripwireLeniency + 1) * (NUMTRANSMAPS+1)) / TRIPWIRETIME; - UINT8 triplevel = K_TripwirePassConditions(mobj->target->player); if (trans > NUMTRANSMAPS) trans = NUMTRANSMAPS; @@ -7193,14 +7192,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if ((trans >= NUMTRANSMAPS) // not a valid visibility || (convSpeed < 150 && (leveltime & 1)) // < 150% flickering - || (triplevel < TRIPWIRE_BOOST) // Not strong enough to make an aura + || (mobj->target->player->tripwirePass < TRIPWIRE_BOOST) // Not strong enough to make an aura || mobj->target->player->flamedash) // Flameshield dash { mobj->renderflags |= RF_DONTDRAW; } else { - boolean blastermode = (convSpeed >= 200) && (triplevel >= TRIPWIRE_BLASTER); + boolean blastermode = (convSpeed >= 200) && (mobj->target->player->tripwirePass >= TRIPWIRE_BLASTER); mobj->renderflags &= ~(RF_TRANSMASK|RF_DONTDRAW); if (trans != 0) diff --git a/src/p_saveg.c b/src/p_saveg.c index 4422eaf20..5569f24d5 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -291,6 +291,8 @@ static void P_NetArchivePlayers(void) WRITEUINT16(save_p, players[i].draftleeway); WRITESINT8(save_p, players[i].lastdraft); + WRITEUINT8(save_p, players[i].tripwireState); + WRITEUINT8(save_p, players[i].tripwirePass); WRITEUINT16(save_p, players[i].tripwireLeniency); WRITEUINT16(save_p, players[i].itemroulette); @@ -355,7 +357,6 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].spheredigestion); WRITESINT8(save_p, players[i].glanceDir); - WRITEUINT8(save_p, players[i].tripWireState); WRITEUINT8(save_p, players[i].typing_timer); WRITEUINT8(save_p, players[i].typing_duration); @@ -575,6 +576,8 @@ static void P_NetUnArchivePlayers(void) players[i].draftleeway = READUINT16(save_p); players[i].lastdraft = READSINT8(save_p); + players[i].tripwireState = READUINT8(save_p); + players[i].tripwirePass = READUINT8(save_p); players[i].tripwireLeniency = READUINT16(save_p); players[i].itemroulette = READUINT16(save_p); @@ -639,7 +642,6 @@ static void P_NetUnArchivePlayers(void) players[i].spheredigestion = READUINT32(save_p); players[i].glanceDir = READSINT8(save_p); - players[i].tripWireState = READUINT8(save_p); players[i].typing_timer = READUINT8(save_p); players[i].typing_duration = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 6d437fa08..942e72fb6 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2070,7 +2070,7 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) if (P_IsLineTripWire(line)) { - K_ApplyTripWire(player, TRIP_PASSED); + K_ApplyTripWire(player, TRIPSTATE_PASSED); } switch (line->special) From befda8b38e17c038ab3906400917606db898b83b Mon Sep 17 00:00:00 2001 From: VelocitOni Date: Tue, 30 Aug 2022 23:41:13 -0400 Subject: [PATCH 16/17] Made states in deh_tables.c match info.h Copy-pasted from info.h to deh_tables.c, fixes Opulence barrels problem. --- src/deh_tables.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 2be68bd1c..47a6ca515 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -3806,20 +3806,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_BATTLEBUMPER_EXBLAST10", // Tripwire - "S_TRIPWIREBOOST_TOP1", - "S_TRIPWIREBOOST_TOP2", - "S_TRIPWIREBOOST_TOP3", - "S_TRIPWIREBOOST_TOP4", - "S_TRIPWIREBOOST_TOP5", - "S_TRIPWIREBOOST_TOP6", - "S_TRIPWIREBOOST_TOP7", - "S_TRIPWIREBOOST_BOTTOM1", - "S_TRIPWIREBOOST_BOTTOM2", - "S_TRIPWIREBOOST_BOTTOM3", - "S_TRIPWIREBOOST_BOTTOM4", - "S_TRIPWIREBOOST_BOTTOM5", - "S_TRIPWIREBOOST_BOTTOM6", - "S_TRIPWIREBOOST_BOTTOM7", + "S_TRIPWIREBOOST_TOP", + "S_TRIPWIREBOOST_BOTTOM", + "S_TRIPWIREBOOST_BLAST_TOP", + "S_TRIPWIREBOOST_BLAST_BOTTOM", // DEZ respawn laser "S_DEZLASER", From a0034750764e665faeec46a9fa4298956e37de36 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 31 Aug 2022 16:37:52 -0700 Subject: [PATCH 17/17] Use mapobjectscale in K_FakeBotResults Fixes a crash if bot scale is way too small and should be more consistent? --- src/k_grandprix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_grandprix.c b/src/k_grandprix.c index 740730c6f..077532fa3 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -639,7 +639,7 @@ void K_RetireBots(void) --------------------------------------------------*/ void K_FakeBotResults(player_t *bot) { - const UINT32 distfactor = FixedMul(32 * bot->mo->scale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; + const UINT32 distfactor = FixedMul(32 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)) / FRACUNIT; UINT32 worstdist = 0; tic_t besttime = UINT32_MAX; UINT8 numplayers = 0;