Bots: Improve spindash behaviors further

- Added new spindashing conditions:
   - In offroad.
   - Trying to go up-hill on a steep slope.
   - On a conveyor going the opposite direction they're trying to go. (Barren Badlands)
- Instead of checking for any spindash condition and adding to the confirm timer, it adds to the confirm timer for every single condition.
    - Increased the confirm time from 2sec to 3sec to accommodate for this change.
- Fixed not using precise momentum angle, causing the low-speed scenarios spindash is intended for to not always work.
- Bots now check for spindash conditions even in damage states, allowing for spindashes after a spinout.
- Fixed the spindash confirm not decreasing over time when entering a condition and then exiting it, causing random spindashes when it wouldn't make sense.
This commit is contained in:
Sally Coolatta 2023-05-14 18:26:31 -04:00
parent d1ec068e84
commit 34b12cc436
4 changed files with 63 additions and 18 deletions

View file

@ -859,10 +859,10 @@ static UINT8 K_TrySpindash(player_t *player)
const fixed_t baseAccel = K_GetNewSpeed(player) - oldSpeed;
const fixed_t speedDiff = player->speed - player->lastspeed;
const INT32 angleDiff = AngleDelta(player->mo->angle, K_MomentumAngle(player->mo));
const INT32 angleDiff = AngleDelta(player->mo->angle, K_MomentumAngleReal(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.
|| P_IsObjectOnGround(player->mo) == false) // Not in a state where we want 'em to spindash.
{
player->botvars.spindashconfirm = 0;
return 0;
@ -913,15 +913,52 @@ static UINT8 K_TrySpindash(player_t *player)
else
{
// Logic for normal racing.
if (speedDiff < (baseAccel / 8) // Moving too slowly
|| angleDiff > ANG60) // Being pushed backwards
boolean anyCondition = false;
boolean uphill = false;
#define AddForCondition(x) \
if (x) \
{ \
anyCondition = true;\
if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM) \
{ \
player->botvars.spindashconfirm++; \
} \
}
if (player->mo->standingslope != NULL)
{
if (player->botvars.spindashconfirm < BOTSPINDASHCONFIRM)
const pslope_t *slope = player->mo->standingslope;
if (!(slope->flags & SL_NOPHYSICS) && abs(slope->zdelta) >= FRACUNIT/21)
{
player->botvars.spindashconfirm++;
fixed_t slopeDot = 0;
angle_t angle = K_MomentumAngle(player->mo) - slope->xydirection;
if (P_MobjFlip(player->mo) * slope->zdelta < 0)
{
angle ^= ANGLE_180;
}
slopeDot = FINECOSINE(angle >> ANGLETOFINESHIFT);
uphill = (slopeDot < -FRACUNIT/2);
}
}
else if (player->botvars.spindashconfirm >= BOTSPINDASHCONFIRM)
AddForCondition(player->offroad > 0); // In offroad
AddForCondition(speedDiff < (baseAccel >> 4)); // Moving too slowly
AddForCondition(angleDiff > ANG60); // Being pushed backwards
AddForCondition(uphill == true); // Going up a steep slope
if (player->cmomx || player->cmomy)
{
angle_t cAngle = R_PointToDist2(0, 0, player->cmomx, player->cmomy);
angle_t cDelta = AngleDelta(player->mo->angle, cAngle);
AddForCondition(cDelta > ANGLE_90); // Conveyor going against you
}
if (anyCondition == false)
{
if (player->botvars.spindashconfirm > 0)
{

View file

@ -32,7 +32,7 @@ extern "C" {
#define BOTTURNCONFIRM 4
// How many tics without being able to accelerate before we'll let you spindash.
#define BOTSPINDASHCONFIRM (2*TICRATE)
#define BOTSPINDASHCONFIRM (3*TICRATE)
// Point for bots to aim for
struct botprediction_t {

View file

@ -2622,7 +2622,7 @@ static void K_HandleDelayedHitByEm(player_t *player)
void K_MomentumToFacing(player_t *player)
{
angle_t dangle = player->mo->angle - K_MomentumAngle(player->mo);
angle_t dangle = player->mo->angle - K_MomentumAngleReal(player->mo);
if (dangle > ANGLE_180)
dangle = InvAngle(dangle);
@ -3468,14 +3468,21 @@ fixed_t K_3dKartMovement(player_t *player)
return finalspeed;
}
fixed_t K_MomentumThreshold(const mobj_t *mo)
angle_t K_MomentumAngleEx(const mobj_t *mo, const fixed_t threshold)
{
return 6 * mo->scale;
if (FixedHypot(mo->momx, mo->momy) > threshold)
{
return R_PointToAngle2(0, 0, mo->momx, mo->momy);
}
else
{
return mo->angle; // default to facing angle, rather than 0
}
}
angle_t K_MomentumAngle(mobj_t *mo)
angle_t K_MomentumAngleReal(const mobj_t *mo)
{
if (FixedHypot(mo->momx, mo->momy) > K_MomentumThreshold(mo))
if (mo->momx || mo->momy)
{
return R_PointToAngle2(0, 0, mo->momx, mo->momy);
}
@ -3530,8 +3537,8 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDam
const fixed_t scaleDiff = abs(mo2->scale - mo1->scale);
angle_t mo1angle = K_MomentumAngle(mo1);
angle_t mo2angle = K_MomentumAngle(mo2);
angle_t mo1angle = K_MomentumAngleReal(mo1);
angle_t mo2angle = K_MomentumAngleReal(mo2);
INT32 angleDiff = 0;
if (mo1speed > 0 && mo2speed > 0)
@ -10229,7 +10236,7 @@ boolean K_FastFallBounce(player_t *player)
static void K_AirFailsafe(player_t *player)
{
const fixed_t maxSpeed = K_MomentumThreshold(player->mo);
const fixed_t maxSpeed = K_MomentumAngle(player->mo);
const fixed_t thrustSpeed = 6*player->mo->scale; // 10*player->mo->scale
if (player->speed > maxSpeed // Above the max speed that you're allowed to use this technique.

View file

@ -83,8 +83,9 @@ void K_KartResetPlayerColor(player_t *player);
boolean K_PressingEBrake(player_t *player);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
void K_KartPlayerAfterThink(player_t *player);
fixed_t K_MomentumThreshold(const mobj_t *mo);
angle_t K_MomentumAngle(mobj_t *mo);
angle_t K_MomentumAngleEx(const mobj_t *mo, const fixed_t threshold);
angle_t K_MomentumAngleReal(const mobj_t *mo);
#define K_MomentumAngle(mo) K_MomentumAngleEx(mo, 6 * mo->scale)
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage);
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage);
void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload);