if (navigation_goalrating_timeout(this))
{
navigation_goalrating_start(this);
- havocbot_goalrating_enemyplayers(this, 20000, this.origin, 650);
+ havocbot_goalrating_enemyplayers(this, 10000, this.origin, 650);
if(!havocbot_goalrating_ons_generator_attack(this, 20000))
havocbot_goalrating_ons_controlpoints_attack(this, 20000);
havocbot_goalrating_ons_offenseitems(this, 10000, this.origin, 10000);
navigation_shortenpath(this);
+ bool goalcurrent_can_be_removed = false;
if (IS_MOVABLE(this.goalcurrent))
{
- if (IS_DEAD(this.goalcurrent))
+ // if is movable => not frozen
+ if (IS_DEAD(this.goalcurrent) || (this.goalentity_shouldbefrozen && this.goalentity == this.goalcurrent))
{
+ goalcurrent_can_be_removed = true;
+ // don't remove if not visible
if (checkpvs(this.origin + this.view_ofs, this.goalcurrent))
{
navigation_goalrating_timeout_force(this);
{
if (this.goalcurrent)
{
- if (IS_MOVABLE(this.goalcurrent) && IS_DEAD(this.goalcurrent))
+ if (goalcurrent_can_be_removed)
{
// remove even if not visible
navigation_goalrating_timeout_force(this);
float enemy_distance = FLOAT_MAX;
float dist;
- FOREACH_CLIENT(IS_PLAYER(it) && it != this && !IS_DEAD(it),
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this && !(IS_DEAD(it) || STAT(FROZEN, it)),
{
if (it.team == this.team)
{
{
float rating;
vector o;
- ratingscale = ratingscale * 0.0001; // items are rated around 10000 already
+ ratingscale = ratingscale * 0.0001;
IL_EACH(g_items, it.bot_pickup,
{
// NOTE: this code assumes each bot rates items in a different frame
if(it.bot_ratingscale_time == time && ratingscale < it.bot_ratingscale)
continue;
- it.bot_ratingscale_time = time;
- it.bot_ratingscale = ratingscale;
if(!it.solid)
{
if(!havocbot_goalrating_item_pickable_check_players(this, org, it, o))
continue;
+ it.bot_ratingscale_time = time;
+ it.bot_ratingscale = ratingscale;
rating = it.bot_pickupevalfunc(this, it);
if(rating > 0)
navigation_routerating(this, it, rating * ratingscale, 2000);
if(this.waterlevel>WATERLEVEL_WETFEET)
return;
- ratingscale = ratingscale * 0.00005; // enemies are rated around 20000 already
+ ratingscale = ratingscale * 0.0001;
float t;
FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), {
{
navigation_goalrating_start(this);
havocbot_goalrating_items(this, 10000, this.origin, 10000);
- havocbot_goalrating_enemyplayers(this, 20000, this.origin, 10000);
+ havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
navigation_goalrating_end(this);
this.goalcurrent_distance_z = FLOAT_MAX;
this.goalcurrent_distance_time = 0;
this.goalentity_lock_timeout = 0;
+ this.goalentity_shouldbefrozen = false;
this.goalentity = NULL;
this.goalcurrent = NULL;
this.goalstack01 = NULL;
nwp = e.nearestwaypoint;
}
- LOG_DEBUG("-- checking ", e.classname, " (with cost ", ftos(nwp.wpcost), ")");
if (nwp && nwp.wpcost < 10000000)
{
//te_wizspike(nwp.wpnearestpoint);
else
nwptoitem_cost = waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, nwp, e);
float cost = nwp.wpcost + nwptoitem_cost;
- LOG_DEBUG(e.classname, " ", ftos(f), "/(1+", ftos(cost), "/", ftos(rangebias), ") = ");
+ LOG_DEBUG("checking ^5", e.classname, "^7 with base rating ^xf04", ftos(f), "^7 and rangebias ^xf40", ftos(rangebias));
f = f * rangebias / (rangebias + cost);
- LOG_DEBUG("considering ", e.classname, " (with rating ", ftos(f), ")");
+ LOG_DEBUG(" ^5", e.classname, "^7 with cost ^6", ftos(cost), "^7 and final rating ^2", ftos(f));
if (navigation_bestrating < f)
{
- LOG_DEBUG("ground path: added goal ", e.classname, " (with rating ", ftos(f), ")");
+ LOG_DEBUG(" ground path: ^3added goal ^5", e.classname);
navigation_bestrating = f;
navigation_bestgoal = e;
}
this.aistatus |= AI_STATUS_STUCK;
}
}
+ this.goalentity_shouldbefrozen = boolean(STAT(FROZEN, this.goalentity));
}
void botframe_updatedangerousobjects(float maxupdate)
.float goalcurrent_distance_time;
.float goalentity_lock_timeout;
+.bool goalentity_shouldbefrozen;
.entity nearestwaypoint;
.float nearestwaypointtimeout;
if (navigation_goalrating_timeout(this))
{
navigation_goalrating_start(this);
- havocbot_goalrating_enemyplayers(this, 20000, this.origin, 650);
+ havocbot_goalrating_enemyplayers(this, 10000, this.origin, 650);
havocbot_goalrating_ast_targets(this, 20000);
havocbot_goalrating_items(this, 15000, this.origin, 10000);
navigation_goalrating_end(this);
if (navigation_goalrating_timeout(this))
{
navigation_goalrating_start(this);
- havocbot_goalrating_enemyplayers(this, 20000, this.origin, 3000);
+ havocbot_goalrating_enemyplayers(this, 10000, this.origin, 3000);
havocbot_goalrating_ast_targets(this, 20000);
havocbot_goalrating_items(this, 15000, this.origin, 10000);
navigation_goalrating_end(this);
void havocbot_goalrating_ctf_enemybase(entity this, float ratingscale)
{
+ // disabled because we always spawn waypoints for flags with waypoint_spawnforitem_force
+ /*
if (!bot_waypoints_for_items)
{
havocbot_goalrating_ctf_enemyflag(this, ratingscale);
return;
}
-
+ */
entity head;
head = havocbot_ctf_find_enemy_flag(this);
if (it.health || it.armorvalue)
if (vdist(it.origin - org, <, sradius))
{
- // get the value of the item
float t = it.bot_pickupevalfunc(this, it) * 0.0001;
if (t > 0)
navigation_routerating(this, it, t * ratingscale, 500);
havocbot_role_ctf_setrole(this, HAVOCBOT_CTF_ROLE_MIDDLE);
}
+bool havocbot_ctf_is_basewaypoint(entity item)
+{
+ if (item.classname != "waypoint")
+ return false;
+
+ entity head = ctf_worldflaglist;
+ while (head)
+ {
+ if (item == head.bot_basewaypoint)
+ return true;
+ head = head.ctf_worldflagnext;
+ }
+ return false;
+}
+
void havocbot_role_ctf_carrier(entity this)
{
if(IS_DEAD(this))
navigation_goalrating_timeout_set(this);
- entity head = ctf_worldflaglist;
- while (head)
- {
- if (this.goalentity == head.bot_basewaypoint)
- {
- this.goalentity_lock_timeout = time + 5;
- break;
- }
- head = head.ctf_worldflagnext;
- }
+ entity goal = this.goalentity;
+ if (havocbot_ctf_is_basewaypoint(goal) && vdist(goal.origin - this.origin, <, 100))
+ this.goalentity_lock_timeout = time + ((this.bot_aimtarg) ? 2 : 3);
- if (this.goalentity)
+ if (goal)
this.havocbot_cantfindflag = time + 10;
else if (time > this.havocbot_cantfindflag)
{
this.havocbot_role_timeout = 0;
return;
}
+ if (ef.ctf_status == FLAG_DROPPED)
+ {
+ navigation_goalrating_timeout_expire(this, 1);
+ return;
+ }
// If the flag carrier reached the base switch to defense
mf = havocbot_ctf_find_flag(this);
havocbot_goalrating_ctf_ourstolenflag(this, 50000);
havocbot_goalrating_ctf_droppedflags(this, 30000, this.origin, 10000);
- havocbot_goalrating_enemyplayers(this, 10000, org, havocbot_middlepoint_radius * 0.5);
+ havocbot_goalrating_enemyplayers(this, 5000, org, havocbot_middlepoint_radius * 0.5);
havocbot_goalrating_items(this, 5000, org, havocbot_middlepoint_radius * 0.5);
havocbot_goalrating_items(this, 2500, this.origin, 10000);
havocbot_goalrating_ctf_enemybase(this, 2500);
navigation_goalrating_end(this);
+ entity goal = this.goalentity;
+ if (havocbot_ctf_is_basewaypoint(goal) && vdist(goal.origin - this.origin, <, 100))
+ this.goalentity_lock_timeout = time + 2;
+
navigation_goalrating_timeout_set(this);
}
}
havocbot_goalrating_ctf_ourstolenflag(this, 20000);
havocbot_goalrating_ctf_droppedflags(this, 20000, org, havocbot_middlepoint_radius);
- havocbot_goalrating_enemyplayers(this, 15000, org, havocbot_middlepoint_radius);
+ havocbot_goalrating_enemyplayers(this, 7500, org, havocbot_middlepoint_radius);
havocbot_goalrating_items(this, 10000, org, havocbot_middlepoint_radius);
havocbot_goalrating_items(this, 5000, this.origin, 10000);
navigation_goalrating_start(this);
havocbot_goalrating_controlpoints(this, 10000, this.origin, 15000);
havocbot_goalrating_items(this, 8000, this.origin, 8000);
- //havocbot_goalrating_enemyplayers(this, 3000, this.origin, 2000);
+ //havocbot_goalrating_enemyplayers(this, 1500, this.origin, 2000);
havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
navigation_goalrating_end(this);
{
navigation_goalrating_start(this);
havocbot_goalrating_items(this, 10000, this.origin, 10000);
- havocbot_goalrating_enemyplayers(this, 20000, this.origin, 10000);
+ havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
havocbot_goalrating_freeplayers(this, 9000, this.origin, 10000);
havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
navigation_goalrating_end(this);
{
navigation_goalrating_start(this);
havocbot_goalrating_items(this, 8000, this.origin, 10000);
- havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
+ havocbot_goalrating_enemyplayers(this, 5000, this.origin, 10000);
havocbot_goalrating_freeplayers(this, 20000, this.origin, 10000);
havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
navigation_goalrating_end(this);
{
navigation_goalrating_start(this);
havocbot_goalrating_items(this, 10000, this.origin, 10000);
- havocbot_goalrating_enemyplayers(this, 20000, this.origin, 10000);
+ havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
navigation_goalrating_end(this);
{
navigation_goalrating_start(this);
havocbot_goalrating_items(this, 10000, this.origin, 10000);
- havocbot_goalrating_enemyplayers(this, 1000, this.origin, 10000);
+ havocbot_goalrating_enemyplayers(this, 500, this.origin, 10000);
havocbot_goalrating_ball(this, 20000, this.origin);
navigation_goalrating_end(this);
navigation_goalrating_start(this);
if(kh_Key_AllOwnedByWhichTeam() == this.team)
- havocbot_goalrating_kh(this, 10, 0.1, 0.1); // bring home
+ havocbot_goalrating_kh(this, 10, 0.1, 0.05); // bring home
else
- havocbot_goalrating_kh(this, 4, 4, 1); // play defensively
+ havocbot_goalrating_kh(this, 4, 4, 0.5); // play defensively
navigation_goalrating_end(this);
key_owner_team = kh_Key_AllOwnedByWhichTeam();
if(key_owner_team == this.team)
- havocbot_goalrating_kh(this, 10, 0.1, 0.1); // defend key carriers
+ havocbot_goalrating_kh(this, 10, 0.1, 0.05); // defend key carriers
else if(key_owner_team == -1)
- havocbot_goalrating_kh(this, 4, 1, 0.1); // play defensively
+ havocbot_goalrating_kh(this, 4, 1, 0.05); // play defensively
else
- havocbot_goalrating_kh(this, 0.1, 0.1, 10); // ATTACK ANYWAY
+ havocbot_goalrating_kh(this, 0.1, 0.1, 5); // ATTACK ANYWAY
navigation_goalrating_end(this);
key_owner_team = kh_Key_AllOwnedByWhichTeam();
if(key_owner_team == this.team)
- havocbot_goalrating_kh(this, 10, 0.1, 0.1); // defend anyway
+ havocbot_goalrating_kh(this, 10, 0.1, 0.05); // defend anyway
else if(key_owner_team == -1)
- havocbot_goalrating_kh(this, 0.1, 1, 4); // play offensively
+ havocbot_goalrating_kh(this, 0.1, 1, 2); // play offensively
else
- havocbot_goalrating_kh(this, 0.1, 0.1, 10); // ATTACK! EMERGENCY!
+ havocbot_goalrating_kh(this, 0.1, 0.1, 5); // ATTACK! EMERGENCY!
navigation_goalrating_end(this);
int key_owner_team = kh_Key_AllOwnedByWhichTeam();
if(key_owner_team == this.team)
- havocbot_goalrating_kh(this, 10, 0.1, 0.1); // defend anyway
+ havocbot_goalrating_kh(this, 10, 0.1, 0.05); // defend anyway
else if(key_owner_team == -1)
- havocbot_goalrating_kh(this, 1, 10, 4); // prefer dropped keys
+ havocbot_goalrating_kh(this, 1, 10, 2); // prefer dropped keys
else
- havocbot_goalrating_kh(this, 0.1, 0.1, 10); // ATTACK ANYWAY
+ havocbot_goalrating_kh(this, 0.1, 0.1, 5); // ATTACK ANYWAY
navigation_goalrating_end(this);
set g_hitplots 0 "when set to 1, hitplots are stored by the server to provide a means of proving that a triggerbot was used"
set g_hitplots_individuals "" "the individuals, by IP, that should have their hitplots recorded"
+// set it to 1 to "fix bot moveto command and routing... now all bots can get to their seats" (Nexuiz repo, commit 2c9873e6)
set bot_navigation_ignoreplayers 0 // FIXME remove this once the issue is solved
set bot_sound_monopoly 0 "when enabled, only bots can make any noise"