mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'more-bot-crudules' into 'master'
More bot crudules See merge request KartKrew/Kart!788
This commit is contained in:
commit
bc2d4a2d83
9 changed files with 255 additions and 30 deletions
27
src/k_bot.c
27
src/k_bot.c
|
|
@ -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?
|
||||
|
|
|
|||
220
src/k_botitem.c
220
src/k_botitem.c
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue