BotLib: Prematurely commit all this new nav-stuff because some people like

to compile their games.
This commit is contained in:
Marco Cawthorne 2022-03-13 17:10:12 -07:00
parent e437550c73
commit bbfc8c945c
Signed by: eukara
GPG Key ID: C196CD8BA993248A
5 changed files with 191 additions and 46 deletions

View File

@ -47,12 +47,6 @@ class player:base_player
PREDICTED_INT(mode_tempstate);
#ifdef CLIENT
/* External model */
entity p_model;
int p_hand_bone;
int p_model_bone;
float lastweapon;
virtual void(void) draw;
virtual float() predraw;
virtual void(void) postdraw;

View File

@ -63,6 +63,7 @@ class bot:player
/* cache, these are just here so we won't have to calc them often */
float m_flEnemyDist;
weapontype_t m_wtWeaponType;
vector m_vecLastPOI;
void(void) bot;

View File

@ -16,7 +16,6 @@
void SV_SendChat(entity sender, string msg, entity eEnt, float fType);
botstate_t
bot::GetState(void)
{
@ -57,6 +56,7 @@ bot::RouteClear(void)
m_iNodes = 0;
m_flNodeGiveup = 0.0f;
memfree(m_pRoute);
print(sprintf("%s cleared his route.\n", netname));
}
void
@ -180,8 +180,8 @@ void
bot::CheckRoute(void)
{
float flDist;
vector evenpos;
float rad;
vector vecEndPos;
float flRadius;
if (!m_iNodes) {
return;
@ -189,17 +189,24 @@ bot::CheckRoute(void)
/* level out position/node stuff */
if (m_iCurNode < 0) {
evenpos = m_vecLastNode - origin;
rad = 128; /* destination is not a node, therefore has a virtual radius */
vecEndPos = m_vecLastNode;
flRadius = 128; /* destination is not a node, therefore has a virtual radius */
} else {
evenpos = m_pRoute[m_iCurNode].m_vecDest - origin;
rad = m_pRoute[m_iCurNode].m_flRadius;
vecEndPos = m_pRoute[m_iCurNode].m_vecDest;
flRadius = m_pRoute[m_iCurNode].m_flRadius;
}
flDist = floor(vlen(evenpos));
/* we need to have a sensible radius */
if (flRadius <= 16)
flRadius = 16.0f;
/* we only check if we've moved anywhere on the X/Y axis */
flDist = floor(vlen([vecEndPos[0],vecEndPos[1],origin[2]] - origin));
// print(sprintf("%s node dist: %d; radius: %d\n", netname, flDist, rad));
/* we're inside the radius */
if (flDist <= rad) {
if (flDist <= flRadius) {
dprint(sprintf("^2bot::^3CheckRoute^7: " \
"%s reached node\n", this.targetname));
m_iCurNode--;
@ -207,28 +214,32 @@ bot::CheckRoute(void)
/* if we're inside an actual node (not a virtual one */
if (m_iCurNode >= 0) {
/* if a node is flagged as jumpy, jump! */
if (Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_JUMP)
input_buttons |= INPUT_BUTTON2;
if (Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_JUMP) {
//input_buttons |= INPUT_BUTTON2;
velocity = Route_GetJumpVelocity(origin, m_pRoute[m_iCurNode].m_vecDest, gravity);
}
/* find the nearest usable item (func_button) and use them */
if (Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_USER)
UseButton();
}
#if 0
/* we've still traveling and from this node we may be able to walk
* directly to our end-destination */
if (m_iCurNode > -1) {
tracebox(origin, mins, maxs, m_vecLastNode, MOVE_NORMAL, this);
tracebox(origin, mins, maxs, vecEndPos, MOVE_NORMAL, this);
/* can we walk directly to our target destination? */
if (trace_fraction == 1.0) {
dprint("^2bot::^3CheckRoute^7: " \
print("^2bot::^3CheckRoute^7: " \
"Walking directly to last node\n");
m_iCurNode = -1;
}
}
#endif
} else { /* we're not near the node quite yet */
traceline(origin, m_pRoute[m_iCurNode].m_vecDest, MOVE_NORMAL, this);
traceline(origin, vecEndPos, MOVE_NORMAL, this);
/* we can't trace against our next node... that should never happen */
if (trace_fraction != 1.0f) {
@ -248,10 +259,14 @@ bot::CheckRoute(void)
/* after one second, also give up the route */
if (m_flNodeGiveup >= 1.0f || m_iCurNode <= BOTROUTE_END) {
print("taking too long! giving up!\n");
RouteClear();
} else if (m_flNodeGiveup >= 0.5f) {
/* attempt a jump after half a second */
input_buttons |= INPUT_BUTTON2;
/* don't bother if it's too high (we're aiming at air... */
if ((vecEndPos[2] - 32) < origin[2])
input_buttons |= INPUT_BUTTON2;
} else {
/* entire way-link needs to be crouched. that's the law of the land */
if (Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_CROUCH)
@ -406,37 +421,54 @@ bot::RunAI(void)
float shouldwalk = 0;
if (m_wtWeaponType == WPNTYPE_RANGED) {
/* walk _directly_ towards the enemy if we're less than 512 units away */
if (m_eTarget && enemyvisible && m_flEnemyDist < 1024) {
aimpos = m_eTarget.origin;
other = world;
if (m_eTarget) {
tracebox(origin, m_eTarget.origin, mins, maxs, MOVE_OTHERONLY, this);
/* walk _directly_ towards the enemy if we're less than 512 units away */
if (trace_fraction >= 1.0 && m_eTarget && enemyvisible && m_eTarget.health < 50 && m_flEnemyDist < 512) {
aimpos = m_eTarget.origin;
goroute = 1;
} else {
goroute = 1;
}
} else {
goroute = 1;
}
/* we should probably walk we're distant enough to be more accurate */
if ((m_eTarget && enemyvisible && m_flEnemyDist > 512))
if ((m_eTarget && enemyvisible && m_flEnemyDist < 512))
shouldwalk = 1;
} else if (m_wtWeaponType == WPNTYPE_CLOSE) {
/* move directly towards the enemy if we're 256 units away */
if (m_eTarget && enemyvisible && m_flEnemyDist < 256) {
/* we are far away, inch closer */
aimpos = m_eTarget.origin;
printf("going to target\n");
} else {
goroute = 1;
}
} else if (m_wtWeaponType == WPNTYPE_THROW) {
if ((m_eTarget && enemyvisible && !enemydistant) && m_flEnemyDist < 512) {
aimpos = m_eTarget.origin;
printf("going to target\n");
} else {
goroute = 1;
}
} else {
goroute = 1;
}
if (goroute) {
if (m_iCurNode <= BOTROUTE_DESTINATION)
if (m_iCurNode <= BOTROUTE_DESTINATION) {
aimpos = m_vecLastNode;
else
printf("going to last node\n");
} else {
aimpos = m_pRoute[m_iCurNode].m_vecDest;
printf("going to next node\n");
}
} else {
RouteClear();
}
/* now we'll set the movevalues relative to the input_angle */
@ -449,11 +481,13 @@ bot::RunAI(void)
input_movevalues = [v_forward * vecDirection, v_right * vecDirection, v_up * vecDirection];
input_movevalues[2] = 0;
#if 0
/* duck and stand still when our enemy is far away */
if (m_eTarget && enemyvisible && vlen(aimpos-origin) > 512) {
input_buttons |= INPUT_BUTTON8;
input_movevalues = [0,0,0];
#if 1
/* duck and stand still when our enemy seems strong */
if (m_eTarget && enemyvisible && m_eTarget.health >= 75) {
if (m_wtWeaponType == WPNTYPE_RANGED) {
input_buttons |= INPUT_BUTTON8;
input_movevalues = [0,0,0];
}
}
#endif
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -19,3 +19,4 @@ vector Route_SelectDestination( bot target );
void Bot_RouteCB( entity ent, vector dest, int numnodes, nodeslist_t *nodelist );
int Route_GetNodeFlags(nodeslist_t *node);
vector Route_GetJumpVelocity(vector frompos, vector topos, float gravitymod);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2022 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -38,7 +38,31 @@ Route_RoundDistance(float flDist)
/* returns a botinfo point that's nearest to us */
entity
Route_SelectNearest(float type, vector org)
Route_SelectFarthest(float type, vector org, optional vector lastpoi = [0,0,0])
{
entity temp;
int bestrange = 0;
int range;
entity dest = __NULL__;
for (temp = world; (temp = findfloat(temp, ::botinfo, type));) {
range = vlen(temp.origin - org);
if (lastpoi == temp.origin)
continue;
if ((range > bestrange) && (temp.solid != SOLID_NOT)) {
bestrange = range;
dest = temp;
}
}
return dest;
}
/* returns a botinfo point that's nearest to us */
entity
Route_SelectNearest(float type, vector org, optional vector lastpoi = [0,0,0])
{
entity temp;
int bestrange = COST_INFINITE;
@ -48,6 +72,9 @@ Route_SelectNearest(float type, vector org)
for (temp = world; (temp = findfloat(temp, ::botinfo, type));) {
range = vlen(temp.origin - org);
if (lastpoi == temp.origin)
continue;
if ((range < bestrange) && (temp.solid != SOLID_NOT)) {
bestrange = range;
dest = temp;
@ -129,6 +156,10 @@ Route_SelectRandomSpot(void)
{
static entity eLastSpot;
eLastSpot = findfloat(eLastSpot, ::botinfo, BOTINFO_SPAWNPOINT);
if (!eLastSpot)
return (Route_SelectRandomSpot());
return (eLastSpot);
}
@ -140,11 +171,12 @@ Bot_RouteCB(entity ent, vector dest, int numnodes, nodeslist_t *nodelist)
b.m_iCurNode = numnodes - 1;
b.m_pRoute = nodelist;
b.m_vecLastNode = dest;
b.m_flNodeGiveup = 0.0f;
//dprint("Bot: Route calculated.\n");
//dprint(sprintf("Bot: # of nodes: %i\n", bot.m_iNodes) );
//dprint(sprintf("Bot: # current node: %i\n", bot.m_iCurNode) );
//dprint(sprintf("Bot: # endpos: %v\n", dest));
print("Bot: Route calculated.\n");
print(sprintf("Bot: # of nodes: %i\n", b.m_iNodes) );
print(sprintf("Bot: # current node: %i\n", b.m_iCurNode) );
print(sprintf("Bot: # endpos: %v\n", dest));
}
vector
@ -154,7 +186,6 @@ Route_SelectDestination(bot target)
rules = (CGameRules)g_grMode;
entity dest = world;
if (rules.IsTeamPlay()) {
/* we have the goal item, so capture it */
@ -171,8 +202,10 @@ Route_SelectDestination(bot target)
dest = Route_SelectNearestEnemyTeam(BOTINFO_TEAM_GOALITEM, target.origin, target.team);
}
if (dest)
if (dest) {
target.m_vecLastPOI = dest.origin;
return dest.origin + [0,0,32];
}
print(sprintf("%s can't figure out where to go for the goal\n", target.netname));
}
@ -180,25 +213,66 @@ Route_SelectDestination(bot target)
/* if we're low on health, look for health items */
if (target.health < 50) {
print(sprintf("%s going for health\n", target.netname));
dest = Route_SelectNearest(BOTINFO_HEALTH, target.origin);
if (dest)
dest = Route_SelectNearest(BOTINFO_HEALTH, target.origin, target.m_vecLastPOI);
if (dest) {
target.m_vecLastPOI = dest.origin;
return dest.origin + [0,0,32];
}
print(sprintf("%s can't figure out where to go for health\n", target.netname));
}
/* armor is always a good idea to have */
if (random() < 0.25)
if (target.armor < 50) {
print(sprintf("%s going for armor\n", target.netname));
dest = Route_SelectNearest(BOTINFO_ARMOR, target.origin);
dest = Route_SelectNearest(BOTINFO_ARMOR, target.origin, target.m_vecLastPOI);
if (dest)
if (dest) {
target.m_vecLastPOI = dest.origin;
return dest.origin + [0,0,32];
}
print(sprintf("%s can't figure out where to go for armor\n", target.netname));
}
/* go for ammo, or weapon */
if (random() < 0.25)
if (!dest) {
print(sprintf("%s going for ammo/weapon\n", target.netname));
if (random() < 0.5)
dest = Route_SelectFarthest(BOTINFO_WEAPON, target.origin, target.m_vecLastPOI);
else
dest = Route_SelectFarthest(BOTINFO_AMMO, target.origin, target.m_vecLastPOI);
if (dest) {
target.m_vecLastPOI = dest.origin;
return dest.origin + [0,0,32];
}
print(sprintf("%s can't figure out where to go for ammo/weapon\n", target.netname));
}
if (random() < 0.25)
if (!dest) {
static entity but;
but = find(but, ::classname, "func_button");
if (but)
return but.absmin + (0.5 * (but.absmax - but.absmin));
}
if (random() < 0.25)
if (!dest) {
static entity trig;
trig = find(trig, ::classname, "trigger_multiple");
if (trig)
return trig.absmin + (0.5 * (trig.absmax - trig.absmin));
}
/* if all else fails... select a random spot */
print(sprintf("%s found nothing, going for random PoI\n", target.netname));
dest = Route_SelectRandomSpot();
@ -217,3 +291,44 @@ Route_GetNodeFlags(nodeslist_t *node)
else
return fl;
}
/* Get's a velocity vector with which we can successfully jump from one place to another */
vector
Route_GetJumpVelocity(vector vecFrom, vector vecTo, float flGravMod)
{
#if 0
float flHeight, flGravity, flTime, flDistance, flDir;
vector vecJump = [0,0,0];
if (flGravMod <= 0.0)
flGravMod = 1.0f;
flGravity = serverkeyfloat("phy_gravity") * flGravMod;
flHeight = vecTo[2] - vecFrom[2];
if (flHeight <= 0)
flHeight = vlen(vecTo - vecFrom) / 2;
flTime = sqrt(flHeight / (flGravity * 0.5f));
if (flTime <= 0) {
return [0,0,0];
}
vecJump = vecTo - vecFrom;
vecJump[2] = 0;
flDistance = vlen(normalize(vecJump));
flDir = flDistance / flTime;
vecJump *= flDir;
vecJump[2] = bound(240, flTime * flGravity, 512);
print(sprintf("jumping from %v to %v at %v\n", vecFrom, vecTo, vecJump));
#else
vector vecJump = [0,0,0];
float flDist = vlen(vecTo - vecFrom);
makevectors(vectoangles(vecTo - vecFrom));
vecJump = v_forward * flDist;
vecJump[2] = 280;
#endif
return vecJump;
}