Merge branch 'more-bot-crudules' into 'master'

More bot crudules

See merge request KartKrew/Kart!788
This commit is contained in:
Oni 2022-11-28 01:15:45 +00:00
commit bc2d4a2d83
9 changed files with 255 additions and 30 deletions

View file

@ -710,7 +710,7 @@ static botprediction_t *K_CreateBotPrediction(player_t *player)
if (P_TraceBotTraversal(player->mo, wp->mobj) == false)
{
// If we can't get a direct path to this waypoint, predict less.
distanceleft -= disttonext;
distanceleft /= 2;
radreduce = FRACUNIT >> 1;
}
@ -745,6 +745,25 @@ 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;
}
@ -875,7 +894,7 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player)
debugMobj->frame |= FF_TRANS20|FF_FULLBRIGHT;
debugMobj->color = SKINCOLOR_ORANGE;
debugMobj->scale *= 2;
P_SetScale(debugMobj, debugMobj->destscale * 2);
debugMobj->tics = 2;
@ -902,7 +921,7 @@ static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player)
radiusMobj->frame |= FF_TRANS20|FF_FULLBRIGHT;
radiusMobj->color = SKINCOLOR_YELLOW;
radiusMobj->scale /= 2;
P_SetScale(debugMobj, debugMobj->destscale / 2);
radiusMobj->tics = 2;
}
@ -1452,7 +1471,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
}
}
if (spindash == 0)
if (spindash == 0 && player->exiting == 0)
{
// 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?

View file

@ -486,6 +486,12 @@ static void K_BotItemGenericOrbitShield(player_t *player, ticcmd_t *cmd)
--------------------------------------------------*/
static void K_BotItemSneaker(player_t *player, ticcmd_t *cmd)
{
if (P_IsObjectOnGround(player->mo) == false)
{
// Don't use while mid-air.
return;
}
if ((player->offroad && K_ApplyOffroad(player)) // Stuck in offroad, use it NOW
|| K_GetWaypointIsShortcut(player->nextwaypoint) == true // Going toward a shortcut!
|| player->speed < K_GetKartSpeed(player, false, true) / 2 // Being slowed down too much
@ -518,6 +524,12 @@ static void K_BotItemSneaker(player_t *player, ticcmd_t *cmd)
--------------------------------------------------*/
static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd)
{
if (P_IsObjectOnGround(player->mo) == false)
{
// Don't use while mid-air.
return;
}
if (player->botvars.itemconfirm > TICRATE)
{
if (player->sneakertimer == 0 && K_ItemButtonWasDown(player) == false)
@ -892,9 +904,9 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
}
/*--------------------------------------------------
static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd)
static void K_BotItemBallhog(player_t *player, ticcmd_t *cmd)
Item usage for Drop Target throwing.
Item usage for Ballhog throwing.
Input Arguments:-
player - Bot to do this for.
@ -903,14 +915,15 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
Return:-
None
--------------------------------------------------*/
static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd)
static void K_BotItemBallhog(player_t *player, ticcmd_t *cmd)
{
const fixed_t topspeed = K_GetKartSpeed(player, false, true);
fixed_t radius = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = -1;
boolean tryLookback = false;
UINT8 snipeMul = 2;
player_t *target = NULL;
boolean hold = false;
if (player->speed > topspeed)
{
@ -918,8 +931,6 @@ static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd)
snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!!
}
player->botvars.itemconfirm++;
target = K_PlayerInCone(player, radius, 15, false);
if (target != NULL)
{
@ -943,7 +954,89 @@ static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd)
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 25*TICRATE)
if (target != NULL)
{
// Charge up!
hold = true;
}
else
{
// If we lose sight of the target, then we'll just
// let go and it'll do a partial-blast.
// If we've been waiting for too long though, then
// we'll go for the full charge :)
player->botvars.itemconfirm++;
hold = (player->botvars.itemconfirm > 10*TICRATE);
}
if (hold == true)
{
cmd->throwdir = KART_FULLTURN * throwdir;
cmd->buttons |= BT_ATTACK;
}
}
/*--------------------------------------------------
static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd, INT16 turnamt)
Item usage for Drop Target throwing.
Input Arguments:-
player - Bot to do this for.
cmd - Bot's ticcmd to edit.
turnamt - How hard they currently are turning.
Return:-
None
--------------------------------------------------*/
static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
const fixed_t topspeed = K_GetKartSpeed(player, false, true);
fixed_t radius = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = -1;
boolean tryLookback = false;
UINT8 snipeMul = 2;
player_t *target = NULL;
if (player->speed > topspeed)
{
radius = FixedMul(radius, FixedDiv(player->speed, topspeed));
snipeMul = 3; // Confirm faster when you'll throw it with a bunch of extra speed!!
}
player->botvars.itemconfirm++;
if (abs(turnamt) >= KART_FULLTURN/2)
{
player->botvars.itemconfirm += player->botvars.difficulty / 2;
throwdir = -1;
}
target = K_PlayerInCone(player, radius, 15, false);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul);
throwdir = 1;
}
else
{
target = K_PlayerInCone(player, radius, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
throwdir = -1;
tryLookback = true;
}
}
if (tryLookback == true && throwdir == -1)
{
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
@ -1166,6 +1259,92 @@ static void K_BotItemFlame(player_t *player, ticcmd_t *cmd)
}
}
/*--------------------------------------------------
static void K_BotItemGardenTopDeploy(player_t *player, ticcmd_t *cmd)
Item usage for deploying the Garden Top.
Input Arguments:-
player - Bot to do this for.
cmd - Bot's ticcmd to edit.
Return:-
None
--------------------------------------------------*/
static void K_BotItemGardenTopDeploy(player_t *player, ticcmd_t *cmd)
{
//if (player->curshield != KSHIELD_TOP)
if (player->botvars.itemconfirm++ > 2*TICRATE)
{
K_BotGenericPressItem(player, cmd, 0);
}
}
/*--------------------------------------------------
static void K_BotItemGardenTop(player_t *player, ticcmd_t *cmd, INT16 turnamt)
Item usage for Garden Top movement.
Input Arguments:-
player - Bot to do this for.
cmd - Bot's ticcmd to edit.
turnamt - How hard they currently are turning.
Return:-
None
--------------------------------------------------*/
static void K_BotItemGardenTop(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
const fixed_t topspeed = K_GetKartSpeed(player, false, true);
fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = -1;
UINT8 snipeMul = 1;
player_t *target = NULL;
if (player->speed > topspeed)
{
radius = FixedMul(radius, FixedDiv(player->speed, topspeed));
snipeMul = 2; // Confirm faster when you'll throw it with a bunch of extra speed!!
}
player->botvars.itemconfirm++;
target = K_PlayerInCone(player, radius, 15, false);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul);
throwdir = 1;
}
if (player->topdriftheld > 0)
{
// Grinding in place.
// Wait until we're mostly done turning.
// Cancel early if we hit max thrust speed.
if ((abs(turnamt) >= KART_FULLTURN/8)
&& (player->topdriftheld <= GARDENTOP_MAXGRINDTIME))
{
cmd->buttons |= BT_DRIFT;
}
}
else
{
const angle_t maxDelta = ANGLE_11hh;
angle_t delta = AngleDelta(player->mo->angle, K_MomentumAngle(player->mo));
if (delta > maxDelta)
{
// Do we need to turn? Start grinding!
cmd->buttons |= BT_DRIFT;
}
}
if (player->botvars.itemconfirm > 25*TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
}
/*--------------------------------------------------
static void K_BotItemRings(player_t *player, ticcmd_t *cmd)
@ -1182,6 +1361,12 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd)
{
INT32 saferingsval = 16 - K_GetKartRingPower(player, false);
if (P_IsObjectOnGround(player->mo) == false)
{
// Don't use while mid-air.
return;
}
if (player->speed < K_GetKartSpeed(player, false, true) / 2 // Being slowed down too much
|| player->speedboost > (FRACUNIT/5)) // Have another type of boost (tethering)
{
@ -1242,7 +1427,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
// Use rings!
if (leveltime > starttime && !player->exiting)
if (leveltime > starttime)
{
K_BotItemRings(player, cmd);
}
@ -1293,7 +1478,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
case KITEM_SPB:
case KITEM_GROW:
case KITEM_SHRINK:
case KITEM_HYUDORO:
case KITEM_SUPERRING:
K_BotItemGenericTap(player, cmd);
break;
@ -1325,8 +1509,6 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
K_BotItemGenericOrbitShield(player, cmd);
}
else if (player->position != 1) // Hold onto orbiting items when in 1st :)
/* FALLTHRU */
case KITEM_BALLHOG:
{
K_BotItemOrbinaut(player, cmd);
}
@ -1352,8 +1534,12 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
}
break;
case KITEM_LANDMINE:
case KITEM_HYUDORO: // Function re-use, as they have about the same usage.
K_BotItemLandmine(player, cmd, turnamt);
break;
case KITEM_BALLHOG:
K_BotItemBallhog(player, cmd);
break;
case KITEM_DROPTARGET:
if (!(player->pflags & PF_ITEMOUT))
{
@ -1361,7 +1547,17 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt)
}
else
{
K_BotItemDropTarget(player, cmd);
K_BotItemDropTarget(player, cmd, turnamt);
}
break;
case KITEM_GARDENTOP:
if (player->curshield != KSHIELD_TOP)
{
K_BotItemGardenTopDeploy(player, cmd);
}
else
{
K_BotItemGardenTop(player, cmd, turnamt);
}
break;
case KITEM_LIGHTNINGSHIELD:

View file

@ -149,7 +149,7 @@ static boolean K_BotHatesThisSectorsSpecial(player_t *player, sector_t *sec)
return true;
}
if (sec->offroad > FRACUNIT) // Only care about strong offroad.
if (sec->offroad > 0)
{
return !K_BotCanTakeCut(player);
}

View file

@ -9067,6 +9067,11 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
if (angledelta < nextbestdelta && momdelta < nextbestmomdelta)
{
if (waypoint->prevwaypoints[i] == finishline) // NEVER allow finish line.
{
continue;
}
if (P_TraceWaypointTraversal(player->mo, waypoint->prevwaypoints[i]->mobj) == false)
{
// Save sight checks when all of the other checks pass, so we only do it if we have to

View file

@ -361,7 +361,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
// remember: huge radius
if (closestdist <= rad && checkdist <= rad && finishline != NULL)
{
if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj)) // Intentionally not P_TraceWaypointTraversal
if (!P_TraceWaypointTraversal(mobj, checkwaypoint->mobj))
{
// Save sight checks when all of the other checks pass, so we only do it if we have to
continue;
@ -379,7 +379,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
}
else if (checkdist < closestdist && bestfindist == INT32_MAX)
{
if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj)) // Intentionally not P_TraceWaypointTraversal
if (!P_TraceWaypointTraversal(mobj, checkwaypoint->mobj))
{
// Save sight checks when all of the other checks pass, so we only do it if we have to
continue;

View file

@ -750,9 +750,6 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
if (player->mo->health <= 0)
continue; // dead
if (player->bot)
continue; // ignore bots
if (dist > 0
&& P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist)
continue; // Too far away

View file

@ -4538,7 +4538,7 @@ boolean P_SupermanLook4Players(mobj_t *actor)
{
if (playeringame[c] && !players[c].spectator)
{
if (!players[c].mo || players[c].bot)
if (!players[c].mo)
continue;
if (players[c].mo->health <= 0)

View file

@ -334,6 +334,12 @@ static boolean P_CanTraceBlockingLine(seg_t *seg, divline_t *divl, register los_
(void)divl;
if (!(line->flags & ML_TWOSIDED))
{
// stop because it is not two sided anyway
return false;
}
if (P_IsLineBlocking(line, los->compareThing) == true)
{
// This line will always block us
@ -380,11 +386,16 @@ static boolean P_CanBotTraverse(seg_t *seg, divline_t *divl, register los_t *los
if (los->compareThing->player != NULL && los->alreadyHates == false)
{
// Treat damage sectors like walls, if you're not already in a bad sector.
sector_t *front, *back;
vertex_t pos;
P_ClosestPointOnLine(los->compareThing->x, los->compareThing->y, line, &pos);
if (K_BotHatesThisSector(los->compareThing->player, line->frontsector, pos.x, pos.y)
|| K_BotHatesThisSector(los->compareThing->player, line->backsector, pos.x, pos.y))
front = seg->frontsector;
back = seg->backsector;
if (K_BotHatesThisSector(los->compareThing->player, front, pos.x, pos.y)
|| K_BotHatesThisSector(los->compareThing->player, back, pos.x, pos.y))
{
// This line does not block us, but we don't want to be in it.
return false;

View file

@ -4282,7 +4282,7 @@ boolean P_IsPlayerValid(size_t playernum)
boolean P_CanPlayerTrigger(size_t playernum)
{
return P_IsPlayerValid(playernum) && !players[playernum].bot;
return P_IsPlayerValid(playernum);
}
/// \todo check continues for proper splitscreen support?
@ -4310,7 +4310,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector)
mobj_t *mo2;
INT32 i;
if (player->bot || sector->ceilingdata || sector->floordata)
if (sector->ceilingdata || sector->floordata)
return;
// Find the center of the Eggtrap and release all the pretty animals!
@ -4517,9 +4517,6 @@ static void P_EvaluateDamageType(player_t *player, sector_t *sector, boolean isT
static void P_EvaluateLinedefExecutorTrigger(player_t *player, sector_t *sector, boolean isTouching)
{
if (player->bot)
return;
if (!sector->triggertag)
return;