BotLib: for goals and goalitem route search, use WorldSpaceCenter() and not their origin to deal with brush triggers and non-existant origins properly
This commit is contained in:
parent
900cf43bd0
commit
ab9d66b2e4
4 changed files with 116 additions and 116 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
* Copyright (c) 2016-2023 Vera Visions LLC.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -69,11 +69,10 @@ bot::BrainThink(int enemyvisible, int enemydistant)
|
||||||
void
|
void
|
||||||
bot::UseButton(void)
|
bot::UseButton(void)
|
||||||
{
|
{
|
||||||
#if 1
|
float bestDist;
|
||||||
float best;
|
func_button bestButton = __NULL__;
|
||||||
func_button best_button = __NULL__;
|
|
||||||
|
|
||||||
best = COST_INFINITE;
|
bestDist = COST_INFINITE;
|
||||||
for (entity e = world; (e = find(e, ::classname, "func_button"));) {
|
for (entity e = world; (e = find(e, ::classname, "func_button"));) {
|
||||||
float dist;
|
float dist;
|
||||||
vector pos;
|
vector pos;
|
||||||
|
@ -82,54 +81,36 @@ bot::UseButton(void)
|
||||||
pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
|
pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
|
||||||
dist = vlen(origin - pos);
|
dist = vlen(origin - pos);
|
||||||
|
|
||||||
if (dist < best) {
|
if (dist < bestDist) {
|
||||||
best = dist;
|
bestDist = dist;
|
||||||
best_button = (func_button)e;
|
bestButton = (func_button)e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_button == __NULL__)
|
if (bestButton == __NULL__) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
best_button.Trigger(this, TRIG_TOGGLE);
|
|
||||||
sound(this, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE);
|
|
||||||
#else
|
|
||||||
float best;
|
|
||||||
vector foo;
|
|
||||||
|
|
||||||
best = COST_INFINITE;
|
|
||||||
for (entity e = world; (e = find(e, ::classname, "func_button"));) {
|
|
||||||
float dist;
|
|
||||||
vector pos;
|
|
||||||
pos[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
|
|
||||||
pos[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
|
|
||||||
pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
|
|
||||||
dist = vlen(origin - pos);
|
|
||||||
|
|
||||||
if (dist < best) {
|
|
||||||
best = dist;
|
|
||||||
foo = pos;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v_angle = vectoangles(origin - foo);
|
bestButton.Trigger(this, TRIG_TOGGLE);
|
||||||
Player_UseDown();
|
sound(this, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bot::SeeThink(void)
|
bot::SeeThink(void)
|
||||||
{
|
{
|
||||||
CGameRules rules = (CGameRules)g_grMode;
|
NSGameRules rules = (NSGameRules)g_grMode;
|
||||||
|
|
||||||
/*if (m_eTarget)
|
/*if (m_eTarget)
|
||||||
return; */
|
return; */
|
||||||
|
|
||||||
if (m_flSeeTime > time)
|
if (m_flSeeTime > time) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (autocvar_bot_pacifist)
|
/* DEVELOPER CVAR: don't attack */
|
||||||
|
if (autocvar_bot_dont_shoot) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* reaction time, in a way */
|
/* reaction time, in a way */
|
||||||
switch (cvar("bot_skill")) {
|
switch (cvar("bot_skill")) {
|
||||||
|
@ -158,7 +139,7 @@ bot::SeeThink(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* ain't go hurt our brothers and sisters */
|
/* ain't go hurt our brothers and sisters */
|
||||||
if (rules.IsTeamplay() == TRUE)
|
if (rules.IsTeamplay() == true)
|
||||||
if (team == w.team)
|
if (team == w.team)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -274,7 +255,7 @@ bot::CheckRoute(void)
|
||||||
input_buttons |= INPUT_BUTTON2;
|
input_buttons |= INPUT_BUTTON2;
|
||||||
} else {
|
} else {
|
||||||
/* entire way-link needs to be crouched. that's the law of the land */
|
/* entire way-link needs to be crouched. that's the law of the land */
|
||||||
if (Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_CROUCH)
|
if (Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_CROUCH || autocvar_bot_crouch)
|
||||||
input_buttons |= INPUT_BUTTON8;
|
input_buttons |= INPUT_BUTTON8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,8 +269,8 @@ bot::CreateObjective(void)
|
||||||
void
|
void
|
||||||
bot::RunAI(void)
|
bot::RunAI(void)
|
||||||
{
|
{
|
||||||
vector aimdir, aimpos;
|
vector aimDir, aimPos;
|
||||||
int enemyvisible, enemydistant;
|
bool enemyVisible, enemyDistant;
|
||||||
float flLerp;
|
float flLerp;
|
||||||
|
|
||||||
/* reset input frame */
|
/* reset input frame */
|
||||||
|
@ -298,15 +279,15 @@ bot::RunAI(void)
|
||||||
input_angles = [0,0,0];
|
input_angles = [0,0,0];
|
||||||
|
|
||||||
/* attempt to respawn when dead */
|
/* attempt to respawn when dead */
|
||||||
if (health <= 0) {
|
if (IsDead() == true) {
|
||||||
RouteClear();
|
RouteClear();
|
||||||
WeaponAttack();
|
WeaponAttack();
|
||||||
SetEnemy(__NULL__);
|
SetEnemy(__NULL__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* freeze the bot */
|
/* DEVELOPER CVAR: freeze the bot */
|
||||||
if (autocvar_bot_wait)
|
if (autocvar_bot_stop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* create our first route */
|
/* create our first route */
|
||||||
|
@ -335,66 +316,67 @@ bot::RunAI(void)
|
||||||
m_flEnemyDist = -1;
|
m_flEnemyDist = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enemyvisible = FALSE;
|
enemyVisible = false;
|
||||||
enemydistant = FALSE;
|
enemyDistant = false;
|
||||||
|
|
||||||
if (m_eTarget != __NULL__) {
|
if (m_eTarget != __NULL__) {
|
||||||
traceline(origin + view_ofs, m_eTarget.origin, TRUE, this);
|
traceline(GetEyePos(), m_eTarget.origin, MOVE_NORMAL, this);
|
||||||
|
|
||||||
/* is it 'visible'? can we 'see' them? */
|
/* is it 'visible'? can we 'see' them? */
|
||||||
enemyvisible = (trace_ent == m_eTarget || trace_fraction == 1.0f);
|
enemyVisible = (trace_ent == m_eTarget || trace_fraction == 1.0f);
|
||||||
|
|
||||||
/* if they're distant, remember that */
|
/* if they're distant, remember that */
|
||||||
if (m_flEnemyDist > 1024) {
|
if (m_flEnemyDist > 1024.0f) {
|
||||||
enemydistant = TRUE;
|
enemyDistant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* attack if visible! */
|
/* attack if visible! */
|
||||||
if (enemyvisible) {
|
if (enemyVisible == true) {
|
||||||
WeaponAttack();
|
WeaponAttack();
|
||||||
}
|
}
|
||||||
} else if (m_flForceWeaponAttack > time)
|
} else if (m_flForceWeaponAttack > time) {
|
||||||
WeaponAttack();
|
WeaponAttack();
|
||||||
|
}
|
||||||
|
|
||||||
BrainThink(enemyvisible, enemydistant);
|
BrainThink(enemyVisible, enemyDistant);
|
||||||
CheckRoute();
|
CheckRoute();
|
||||||
|
|
||||||
aimpos = [0,0,0];
|
aimPos = [0,0,0];
|
||||||
|
|
||||||
/* if we've got a path (we always should) move the bot */
|
/* if we've got a path (we always should) move the bot */
|
||||||
if (m_iNodes) {
|
if (m_iNodes) {
|
||||||
float goroute = 0;
|
bool goRoute = false;
|
||||||
vector vecNewAngles;
|
vector vecNewAngles;
|
||||||
vector vecDirection;
|
vector vecDirection;
|
||||||
|
|
||||||
/* no enemy, or it isn't visible... then stare at nodes! */
|
/* no enemy, or it isn't visible... then stare at nodes! */
|
||||||
if (!m_eTarget || !enemyvisible) {
|
if (!m_eTarget || enemyVisible == false) {
|
||||||
/* aim at the next node */
|
/* aim at the next node */
|
||||||
if (m_iCurNode == BOTROUTE_DESTINATION)
|
if (m_iCurNode == BOTROUTE_DESTINATION)
|
||||||
aimpos = m_vecLastNode;
|
aimPos = m_vecLastNode;
|
||||||
else {
|
else {
|
||||||
if (m_iCurNode > 0 && !(Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_AIM))
|
if (m_iCurNode > 0 && !(Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_AIM))
|
||||||
aimpos = m_pRoute[m_iCurNode - 1].dest;
|
aimPos = m_pRoute[m_iCurNode - 1].dest;
|
||||||
else
|
else
|
||||||
aimpos = m_pRoute[m_iCurNode].dest;
|
aimPos = m_pRoute[m_iCurNode].dest;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* aim towards the enemy */
|
/* aim towards the enemy */
|
||||||
aimpos = m_eTarget.origin;
|
aimPos = m_eTarget.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* force bot to fire at a position if desired */
|
/* force bot to fire at a position if desired */
|
||||||
if (m_flForceWeaponAttack > time)
|
if (m_flForceWeaponAttack > time)
|
||||||
aimpos = m_vecForceWeaponAttackPos;
|
aimPos = m_vecForceWeaponAttackPos;
|
||||||
|
|
||||||
/* aim ahead if aimpos is somehow invalid */
|
/* aim ahead if aimPos is somehow invalid */
|
||||||
if (aimpos == [0,0,0]) {
|
if (aimPos == [0,0,0]) {
|
||||||
makevectors(angles);
|
makevectors(angles);
|
||||||
aimpos = origin + v_forward * 128;
|
aimPos = origin + v_forward * 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* lerping speed, faster when we've got a target */
|
/* lerping speed, faster when we've got a target */
|
||||||
if (m_eTarget && enemyvisible)
|
if (m_eTarget && enemyVisible == true)
|
||||||
flLerp = bound(0.0f, frametime * 45, 1.0f);
|
flLerp = bound(0.0f, frametime * 45, 1.0f);
|
||||||
else
|
else
|
||||||
flLerp = bound(0.0f, frametime * 30, 1.0f);
|
flLerp = bound(0.0f, frametime * 30, 1.0f);
|
||||||
|
@ -403,9 +385,9 @@ bot::RunAI(void)
|
||||||
makevectors(v_angle);
|
makevectors(v_angle);
|
||||||
vecNewAngles = v_forward;
|
vecNewAngles = v_forward;
|
||||||
|
|
||||||
/* aimdir = new final angle */
|
/* aimDir = new final angle */
|
||||||
aimdir = vectoangles(aimpos - origin);
|
aimDir = vectoangles(aimPos - origin);
|
||||||
makevectors(aimdir);
|
makevectors(aimDir);
|
||||||
|
|
||||||
/* slowly lerp towards the final angle */
|
/* slowly lerp towards the final angle */
|
||||||
vecNewAngles[0] = Math_Lerp(vecNewAngles[0], v_forward[0], flLerp);
|
vecNewAngles[0] = Math_Lerp(vecNewAngles[0], v_forward[0], flLerp);
|
||||||
|
@ -422,53 +404,53 @@ bot::RunAI(void)
|
||||||
angles[2] = Math_FixDelta(v_angle[2]);
|
angles[2] = Math_FixDelta(v_angle[2]);
|
||||||
input_angles = v_angle;
|
input_angles = v_angle;
|
||||||
|
|
||||||
float shouldwalk = 0;
|
bool shouldWalk = autocvar_bot_walk;
|
||||||
|
|
||||||
if (m_wtWeaponType == WPNTYPE_RANGED) {
|
if (m_wtWeaponType == WPNTYPE_RANGED) {
|
||||||
other = world;
|
|
||||||
|
|
||||||
if (m_eTarget) {
|
if (m_eTarget) {
|
||||||
|
other = world;
|
||||||
tracebox(origin, m_eTarget.origin, mins, maxs, MOVE_OTHERONLY, this);
|
tracebox(origin, m_eTarget.origin, mins, maxs, MOVE_OTHERONLY, this);
|
||||||
|
|
||||||
/* walk _directly_ towards the enemy if we're less than 512 units away */
|
/* 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) {
|
if (trace_fraction >= 1.0 && m_eTarget && enemyVisible && m_eTarget.health < 50 && m_flEnemyDist < 512) {
|
||||||
aimpos = m_eTarget.origin;
|
aimPos = m_eTarget.origin;
|
||||||
goroute = 1;
|
goRoute = true;
|
||||||
} else {
|
} else {
|
||||||
goroute = 1;
|
goRoute = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
goroute = 1;
|
goRoute = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we should probably walk we're distant enough to be more accurate */
|
/* 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;
|
shouldWalk = true;
|
||||||
} else if (m_wtWeaponType == WPNTYPE_CLOSE) {
|
} else if (m_wtWeaponType == WPNTYPE_CLOSE) {
|
||||||
/* move directly towards the enemy if we're 256 units away */
|
/* move directly towards the enemy if we're 256 units away */
|
||||||
if (m_eTarget && enemyvisible && m_flEnemyDist < 256) {
|
if (m_eTarget && enemyVisible && m_flEnemyDist < 256) {
|
||||||
/* we are far away, inch closer */
|
/* we are far away, inch closer */
|
||||||
aimpos = m_eTarget.origin;
|
aimPos = m_eTarget.origin;
|
||||||
//printf("going to target\n");
|
//printf("going to target\n");
|
||||||
} else {
|
} else {
|
||||||
goroute = 1;
|
goRoute = true;
|
||||||
}
|
}
|
||||||
} else if (m_wtWeaponType == WPNTYPE_THROW) {
|
} else if (m_wtWeaponType == WPNTYPE_THROW) {
|
||||||
if ((m_eTarget && enemyvisible && !enemydistant) && m_flEnemyDist < 512) {
|
if ((m_eTarget && enemyVisible && !enemyDistant) && m_flEnemyDist < 512) {
|
||||||
aimpos = m_eTarget.origin;
|
aimPos = m_eTarget.origin;
|
||||||
//printf("going to target\n");
|
//printf("going to target\n");
|
||||||
} else {
|
} else {
|
||||||
goroute = 1;
|
goRoute = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
goroute = 1;
|
goRoute = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (goroute) {
|
if (goRoute) {
|
||||||
if (m_iCurNode <= BOTROUTE_DESTINATION) {
|
if (m_iCurNode <= BOTROUTE_DESTINATION) {
|
||||||
aimpos = m_vecLastNode;
|
aimPos = m_vecLastNode;
|
||||||
//printf("going to last node\n");
|
//printf("going to last node\n");
|
||||||
} else {
|
} else {
|
||||||
aimpos = m_pRoute[m_iCurNode].dest;
|
aimPos = m_pRoute[m_iCurNode].dest;
|
||||||
//printf("going to next node\n");
|
//printf("going to next node\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -476,7 +458,7 @@ bot::RunAI(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if there's a breakable in the way... */
|
/* if there's a breakable in the way... */
|
||||||
traceline(origin, aimpos, MOVE_NORMAL, this);
|
traceline(origin, aimPos, MOVE_NORMAL, this);
|
||||||
|
|
||||||
/* Hackish: If there's a func_breakable in the way... */
|
/* Hackish: If there's a func_breakable in the way... */
|
||||||
if (trace_ent.classname == "func_breakable") {
|
if (trace_ent.classname == "func_breakable") {
|
||||||
|
@ -485,10 +467,10 @@ bot::RunAI(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now we'll set the movevalues relative to the input_angle */
|
/* now we'll set the movevalues relative to the input_angle */
|
||||||
if ((m_iCurNode >= 0 && Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_WALK) || shouldwalk)
|
if ((m_iCurNode >= 0 && Route_GetNodeFlags(&m_pRoute[m_iCurNode]) & LF_WALK) || shouldWalk)
|
||||||
vecDirection = normalize(aimpos - origin) * GetWalkSpeed();
|
vecDirection = normalize(aimPos - origin) * GetWalkSpeed();
|
||||||
else
|
else
|
||||||
vecDirection = normalize(aimpos - origin) * GetRunSpeed();
|
vecDirection = normalize(aimPos - origin) * GetRunSpeed();
|
||||||
|
|
||||||
makevectors(input_angles);
|
makevectors(input_angles);
|
||||||
input_movevalues = [v_forward * vecDirection, v_right * vecDirection, v_up * vecDirection];
|
input_movevalues = [v_forward * vecDirection, v_right * vecDirection, v_up * vecDirection];
|
||||||
|
@ -496,7 +478,7 @@ bot::RunAI(void)
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* duck and stand still when our enemy seems strong */
|
/* duck and stand still when our enemy seems strong */
|
||||||
if (m_eTarget && enemyvisible && m_eTarget.health >= 75) {
|
if (m_eTarget && enemyVisible && m_eTarget.health >= 75) {
|
||||||
if (m_wtWeaponType == WPNTYPE_RANGED) {
|
if (m_wtWeaponType == WPNTYPE_RANGED) {
|
||||||
input_buttons |= INPUT_BUTTON8;
|
input_buttons |= INPUT_BUTTON8;
|
||||||
input_movevalues = [0,0,0];
|
input_movevalues = [0,0,0];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
* Copyright (c) 2016-2023 Vera Visions LLC.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -17,7 +17,7 @@
|
||||||
void
|
void
|
||||||
bot::Pain(void)
|
bot::Pain(void)
|
||||||
{
|
{
|
||||||
CGameRules rules = g_grMode;
|
NSGameRules rules = g_grMode;
|
||||||
|
|
||||||
super::Pain();
|
super::Pain();
|
||||||
|
|
||||||
|
@ -33,11 +33,13 @@ bot::Pain(void)
|
||||||
float enemydist = vlen(origin - m_eTarget.origin);
|
float enemydist = vlen(origin - m_eTarget.origin);
|
||||||
float newdist = vlen(origin - g_dmg_eAttacker.origin);
|
float newdist = vlen(origin - g_dmg_eAttacker.origin);
|
||||||
|
|
||||||
if (m_eTarget)
|
if (m_eTarget) {
|
||||||
if (newdist < enemydist)
|
if (newdist < enemydist) {
|
||||||
SetEnemy(g_dmg_eAttacker);
|
SetEnemy(g_dmg_eAttacker);
|
||||||
else
|
}
|
||||||
|
} else {
|
||||||
SetEnemy(g_dmg_eAttacker);
|
SetEnemy(g_dmg_eAttacker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,10 +48,11 @@ bot::SetEnemy(entity en)
|
||||||
{
|
{
|
||||||
m_eTarget = en;
|
m_eTarget = en;
|
||||||
|
|
||||||
if (m_eTarget)
|
if (m_eTarget) {
|
||||||
m_flEnemyDist = vlen(origin - m_eTarget.origin);
|
m_flEnemyDist = vlen(origin - m_eTarget.origin);
|
||||||
else
|
} else {
|
||||||
m_flEnemyDist = -1;
|
m_flEnemyDist = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -59,9 +62,11 @@ bot::WeaponThink(void)
|
||||||
|
|
||||||
/* clip empty, but the whole weapon isn't */
|
/* clip empty, but the whole weapon isn't */
|
||||||
if (r == 0 && a_ammo1 <= 0) {
|
if (r == 0 && a_ammo1 <= 0) {
|
||||||
|
/* stop fire, tap reload */
|
||||||
input_buttons &= ~INPUT_BUTTON0;
|
input_buttons &= ~INPUT_BUTTON0;
|
||||||
input_buttons |= INPUT_BUTTON4;
|
input_buttons |= INPUT_BUTTON4;
|
||||||
} else if (r == 1) {
|
} else if (r == 1) {
|
||||||
|
/* if empty, switch to the next best weapon */
|
||||||
Weapons_SwitchBest(this, activeweapon);
|
Weapons_SwitchBest(this, activeweapon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,27 +76,27 @@ bot::WeaponThink(void)
|
||||||
void
|
void
|
||||||
bot::WeaponAttack(void)
|
bot::WeaponAttack(void)
|
||||||
{
|
{
|
||||||
int should_attack = 0;
|
bool shouldAttack = false;
|
||||||
|
|
||||||
/* only attack when the type's suggested distance makes sense to */
|
/* only attack when the type's suggested distance makes sense to */
|
||||||
if (m_wtWeaponType == WPNTYPE_RANGED) {
|
if (m_wtWeaponType == WPNTYPE_RANGED) {
|
||||||
if (m_flEnemyDist <= 1024)
|
if (m_flEnemyDist <= 1024)
|
||||||
should_attack = 1;
|
shouldAttack = true;
|
||||||
} else if (m_wtWeaponType == WPNTYPE_THROW) {
|
} else if (m_wtWeaponType == WPNTYPE_THROW) {
|
||||||
if (m_flEnemyDist <= 512)
|
if (m_flEnemyDist <= 512)
|
||||||
should_attack = 1;
|
shouldAttack = true;
|
||||||
} else if (m_wtWeaponType == WPNTYPE_CLOSE) {
|
} else if (m_wtWeaponType == WPNTYPE_CLOSE) {
|
||||||
if (m_flEnemyDist <= 128)
|
if (m_flEnemyDist <= 128)
|
||||||
should_attack = 1;
|
shouldAttack = true;
|
||||||
} else {
|
} else {
|
||||||
if (m_flEnemyDist <= 1024)
|
if (m_flEnemyDist <= 1024)
|
||||||
should_attack = 1;
|
shouldAttack = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_flForceWeaponAttack > time)
|
if (m_flForceWeaponAttack > time)
|
||||||
should_attack = 1;
|
shouldAttack = true;
|
||||||
|
|
||||||
if (should_attack && m_flAttackTime < time) {
|
if (shouldAttack && m_flAttackTime < time) {
|
||||||
if (!m_iAttackMode) {
|
if (!m_iAttackMode) {
|
||||||
input_buttons |= INPUT_BUTTON0;
|
input_buttons |= INPUT_BUTTON0;
|
||||||
}
|
}
|
||||||
|
@ -136,7 +141,7 @@ var float g_botalert_timer;
|
||||||
void
|
void
|
||||||
BotLib_Alert(vector pos, float radius, float t)
|
BotLib_Alert(vector pos, float radius, float t)
|
||||||
{
|
{
|
||||||
CGameRules rules = g_grMode;
|
NSGameRules rules = g_grMode;
|
||||||
|
|
||||||
/* sometimes many alert-sounds happen at once... we don't really want
|
/* sometimes many alert-sounds happen at once... we don't really want
|
||||||
* that */
|
* that */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2022 Vera Visions LLC.
|
* Copyright (c) 2016-2023 Vera Visions LLC.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -14,13 +14,22 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var int autocvar_bot_pacifist = FALSE;
|
|
||||||
var int autocvar_bot_wait = FALSE;
|
|
||||||
var int autocvar_bot_aimless = FALSE;
|
var int autocvar_bot_aimless = FALSE;
|
||||||
|
|
||||||
var int autocvar_nav_linksize = 256;
|
var int autocvar_nav_linksize = 256;
|
||||||
var int autocvar_nav_radius = 8;
|
var int autocvar_nav_radius = 8;
|
||||||
|
|
||||||
|
var bool autocvar_bot_crouch = false;
|
||||||
|
var bool autocvar_bot_walk = false;
|
||||||
|
var bool autocvar_bot_stop = false;
|
||||||
|
var bool autocvar_bot_dont_shoot = false;
|
||||||
|
|
||||||
|
var bool autocvar_bot_join_after_player = false;
|
||||||
|
var float autocvar_bot_join_delay = 0.0f;
|
||||||
|
var int autocvar_bot_quota = 0i;
|
||||||
|
var string autocvar_bot_quota_mode = "normal";
|
||||||
|
var string autocvar_bot_chatter = "normal";
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
BOTSKILL_EASY = 1,
|
BOTSKILL_EASY = 1,
|
||||||
|
@ -28,6 +37,6 @@ typedef enum
|
||||||
BOTSKILL_HARD
|
BOTSKILL_HARD
|
||||||
} botskill_t;
|
} botskill_t;
|
||||||
|
|
||||||
var botskill_t autocvar_bot_skill = 2;
|
var botskill_t autocvar_bot_skill = BOTSKILL_MEDIUM;
|
||||||
|
|
||||||
var string autocvar_bot_prefix = "";
|
var string autocvar_bot_prefix = "";
|
||||||
|
|
|
@ -94,10 +94,11 @@ Route_SelectNearestTeam(float type, vector org, float tt)
|
||||||
entity dest = __NULL__;
|
entity dest = __NULL__;
|
||||||
|
|
||||||
for (temp = world; (temp = findfloat(temp, ::botinfo, type));) {
|
for (temp = world; (temp = findfloat(temp, ::botinfo, type));) {
|
||||||
|
NSEntity tempEnt = (NSEntity)temp;
|
||||||
if (temp.team != tt)
|
if (temp.team != tt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
range = vlen(temp.origin - org);
|
range = vlen(tempEnt.WorldSpaceCenter() - org);
|
||||||
|
|
||||||
if ((range < bestrange) && (temp.solid != SOLID_NOT)) {
|
if ((range < bestrange) && (temp.solid != SOLID_NOT)) {
|
||||||
bestrange = range;
|
bestrange = range;
|
||||||
|
@ -118,10 +119,11 @@ Route_SelectNearestEnemyTeam(float type, vector org, float tt)
|
||||||
entity dest = __NULL__;
|
entity dest = __NULL__;
|
||||||
|
|
||||||
for (temp = world; (temp = findfloat(temp, ::botinfo, type));) {
|
for (temp = world; (temp = findfloat(temp, ::botinfo, type));) {
|
||||||
|
NSEntity tempEnt = (NSEntity)temp;
|
||||||
if (temp.team == tt)
|
if (temp.team == tt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
range = vlen(temp.origin - org);
|
range = vlen(tempEnt.WorldSpaceCenter() - org);
|
||||||
|
|
||||||
if ((range < bestrange) && (temp.solid != SOLID_NOT)) {
|
if ((range < bestrange) && (temp.solid != SOLID_NOT)) {
|
||||||
bestrange = range;
|
bestrange = range;
|
||||||
|
@ -169,7 +171,7 @@ Route_SelectDestination(bot target)
|
||||||
CGameRules rules;
|
CGameRules rules;
|
||||||
rules = (CGameRules)g_grMode;
|
rules = (CGameRules)g_grMode;
|
||||||
|
|
||||||
entity dest = world;
|
NSEntity dest = __NULL__;
|
||||||
|
|
||||||
if (rules.IsTeamplay()) {
|
if (rules.IsTeamplay()) {
|
||||||
/* we have the goal item, so capture it */
|
/* we have the goal item, so capture it */
|
||||||
|
@ -187,10 +189,12 @@ Route_SelectDestination(bot target)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dest != __NULL__) {
|
if (dest != __NULL__) {
|
||||||
target.m_vecLastPOI = dest.origin;
|
target.m_vecLastPOI = dest.WorldSpaceCenter();
|
||||||
return dest.origin + [0,0,32];
|
return dest.WorldSpaceCenter() + [0,0,32];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* by now, they need something else to do involving goal items probably */
|
||||||
|
|
||||||
print(sprintf("%s can't figure out where to go for the goal\n", target.netname));
|
print(sprintf("%s can't figure out where to go for the goal\n", target.netname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +204,7 @@ Route_SelectDestination(bot target)
|
||||||
dest = Route_SelectNearest(BOTINFO_HEALTH, target.origin, target.m_vecLastPOI);
|
dest = Route_SelectNearest(BOTINFO_HEALTH, target.origin, target.m_vecLastPOI);
|
||||||
|
|
||||||
if (dest != __NULL__) {
|
if (dest != __NULL__) {
|
||||||
target.m_vecLastPOI = dest.origin;
|
target.m_vecLastPOI = dest.WorldSpaceCenter();
|
||||||
return dest.origin + [0,0,32];
|
return dest.origin + [0,0,32];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue