Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
api.qh File Reference
Include dependency graph for api.qh:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

bool bot_aim (entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity, bool shot_accurate)
void bot_aim_reset (entity this)
void bot_clientconnect (entity this)
void bot_clientdisconnect (entity this)
void bot_cmdhelp (string scmd)
void bot_endgame ()
bool bot_fixcount (bool multiple_per_frame)
void bot_list_commands ()
void bot_queuecommand (entity bot, string cmdstring)
void bot_relinkplayerlist ()
void bot_resetqueues ()
void bot_serverframe ()
bool bot_shouldattack (entity this, entity e)
void bot_think (entity this)
entity find_bot_by_name (string name)
entity find_bot_by_number (float number)
 float (entity player, entity item) bot_pickupevalfunc
vector get_closer_dest (entity ent, vector org)
void havocbot_goalrating_enemyplayers (entity this, float ratingscale, vector org, float sradius)
bool havocbot_goalrating_item_pickable_check_players (entity this, vector org, entity item, vector item_org)
void havocbot_goalrating_items (entity this, float ratingscale, vector org, float sradius)
void havocbot_goalrating_waypoints (entity this, float ratingscale, vector org, float sradius)
void navigation_dynamicgoal_init (entity this, bool initially_static)
void navigation_dynamicgoal_set (entity this, entity dropper)
void navigation_dynamicgoal_unset (entity this)
entity navigation_findnearestwaypoint (entity ent, float walkfromwp)
void navigation_goalrating_end (entity this)
void navigation_goalrating_start (entity this)
bool navigation_goalrating_timeout (entity this)
bool navigation_goalrating_timeout_can_be_anticipated (entity this)
void navigation_goalrating_timeout_expire (entity this, float seconds)
void navigation_goalrating_timeout_extend_if_needed (entity this, float seconds)
void navigation_goalrating_timeout_force (entity this)
void navigation_goalrating_timeout_set (entity this)
void navigation_markroutes (entity this, entity fixed_source_waypoint)
void navigation_markroutes_inverted (entity fixed_source_waypoint)
void navigation_routerating (entity this, entity e, float f, float rangebias)
void set_tracewalk_dest (entity ent, vector org, bool fix_player_dest)
vector set_tracewalk_dest_2 (entity ent, vector org)
 STATIC_INIT (botapi)
bool tracewalk (entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode)
 void (entity this) havocbot_role
void waypoint_getSymmetricalAxis_cmd (entity caller, bool save, int arg_idx)
void waypoint_getSymmetricalOrigin_cmd (entity caller, bool save, int arg_idx)
void waypoint_lock (entity pl)
void waypoint_remove (entity wp)
void waypoint_remove_fromeditor (entity pl)
void waypoint_saveall ()
void waypoint_schedulerelink (entity wp)
void waypoint_schedulerelinkall ()
entity waypoint_spawn (vector m1, vector m2, float f)
void waypoint_spawn_fromeditor (entity pl, bool at_crosshair, bool is_jump_wp, bool is_crouch_wp, bool is_support_wp)
void waypoint_spawnforitem (entity e)
void waypoint_spawnforitem_force (entity e, vector org)
void waypoint_spawnforteleporter (entity e, vector destination, float timetaken, entity tracetest_ent)
void waypoint_spawnforteleporter_wz (entity e, entity tracetest_ent)
void waypoint_start_hardwiredlink (entity pl, bool at_crosshair)
void waypoint_unreachable (entity pl)

Variables

bool autocvar_g_waypoints_for_items
float bot_attack
entity bot_basewaypoint
float bot_custom_weapon
float bot_dodge
float bot_dodgerating
float bot_forced_team
float bot_moveskill
float bot_pickup
float bot_tracewalk_time
bool bot_waypoints_for_items
float bot_weapons_close [REGISTRY_MAX(Weapons)]
float bot_weapons_far [REGISTRY_MAX(Weapons)]
float bot_weapons_mid [REGISTRY_MAX(Weapons)]
int bots_would_leave
 how many bots would leave so humans can replace them
string cleanname
int currentbots
IntrusiveList g_bot_dodge
IntrusiveList g_bot_targets
IntrusiveList g_waypoints
float goalentity_lock_timeout
vector havocbot_middlepoint
float havocbot_middlepoint_radius
float havocbot_role_timeout
float havocbot_symmetry_axis_m
float havocbot_symmetry_axis_q
float havocbot_symmetry_origin_order
entity ignoregoal
float ignoregoaltime
float isbot
vector lastteleport_origin
float lastteleporttime
bool navigation_dynamicgoal
float navigation_hasgoals
entity nearestwaypoint
float nearestwaypointtimeout
int player_count
float skill
float speed
const int WAYPOINTFLAG_CROUCH = BIT(12)
const int WAYPOINTFLAG_CUSTOM_JP = BIT(13)
const int WAYPOINTFLAG_DEAD_END = BIT(16)
const int WAYPOINTFLAG_GENERATED = BIT(23)
const int WAYPOINTFLAG_ITEM = BIT(22)
const int WAYPOINTFLAG_JUMP = BIT(14)
const int WAYPOINTFLAG_LADDER = BIT(15)
const int WAYPOINTFLAG_NORELINK__DEPRECATED = BIT(20)
const int WAYPOINTFLAG_PERSONAL = BIT(19)
const int WAYPOINTFLAG_PROTECTED = BIT(18)
const int WAYPOINTFLAG_SUPPORT = BIT(11)
const int WAYPOINTFLAG_TELEPORT = BIT(21)
const int WAYPOINTFLAG_USEFUL = BIT(17)
entity wp00
float wp00mincost
entity wp01
float wp01mincost
entity wp02
float wp02mincost
entity wp03
float wp03mincost
entity wp04
float wp04mincost
entity wp05
float wp05mincost
entity wp06
float wp06mincost
entity wp07
float wp07mincost
entity wp08
float wp08mincost
entity wp09
float wp09mincost
entity wp10
float wp10mincost
entity wp11
float wp11mincost
entity wp12
float wp12mincost
entity wp13
float wp13mincost
entity wp14
float wp14mincost
entity wp15
float wp15mincost
entity wp16
float wp16mincost
entity wp17
float wp17mincost
entity wp18
float wp18mincost
entity wp19
float wp19mincost
entity wp20
float wp20mincost
entity wp21
float wp21mincost
entity wp22
float wp22mincost
entity wp23
float wp23mincost
entity wp24
float wp24mincost
entity wp25
float wp25mincost
entity wp26
float wp26mincost
entity wp27
float wp27mincost
entity wp28
float wp28mincost
entity wp29
float wp29mincost
entity wp30
float wp30mincost
entity wp31
float wp31mincost
float wpconsidered
float wpcost
const int WPFLAGMASK_NORELINK = (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER | WAYPOINTFLAG_JUMP | WAYPOINTFLAG_CUSTOM_JP | WAYPOINTFLAG_SUPPORT)
int wpflags
entity wphw00
entity wphw01
entity wphw02
entity wphw03
entity wphw04
entity wphw05
entity wphw06
entity wphw07

Function Documentation

◆ bot_aim()

bool bot_aim ( entity this,
.entity weaponentity,
float shotspeed,
float shotspeedupward,
float maxshottime,
float applygravity,
bool shot_accurate )

References entity(), name, number, org, and vector.

◆ bot_aim_reset()

void bot_aim_reset ( entity this)

Definition at line 134 of file aim.qc.

135{
136 this.bot_mouseaim = this.v_angle;
137 this.bot_olddesiredang = this.v_angle;
138 this.bot_aimdir_executed = true;
139 this.bot_badaimtime = 0;
140 this.bot_aimthinktime = time;
141 this.bot_prevaimtime = time;
142 this.bot_1st_order_aimfilter = '0 0 0';
143 this.bot_2nd_order_aimfilter = '0 0 0';
144 this.bot_3th_order_aimfilter = '0 0 0';
145 this.bot_4th_order_aimfilter = '0 0 0';
146 this.bot_5th_order_aimfilter = '0 0 0';
147 this.bot_firetimer = 0;
148}
vector bot_4th_order_aimfilter
Definition aim.qh:25
vector bot_mouseaim
Definition aim.qh:20
float bot_prevaimtime
Definition aim.qh:16
vector bot_olddesiredang
Definition aim.qh:27
vector bot_3th_order_aimfilter
Definition aim.qh:24
float bot_aimthinktime
Definition aim.qh:15
vector bot_1st_order_aimfilter
Definition aim.qh:22
bool bot_aimdir_executed
Definition aim.qh:13
float bot_badaimtime
Definition aim.qh:14
float bot_firetimer
Definition aim.qh:17
vector bot_5th_order_aimfilter
Definition aim.qh:26
vector bot_2nd_order_aimfilter
Definition aim.qh:23
vector v_angle
Definition player.qh:237
float time

References bot_1st_order_aimfilter, bot_2nd_order_aimfilter, bot_3th_order_aimfilter, bot_4th_order_aimfilter, bot_5th_order_aimfilter, bot_aimdir_executed, bot_aimthinktime, bot_badaimtime, bot_firetimer, bot_mouseaim, bot_olddesiredang, bot_prevaimtime, entity(), time, and v_angle.

Referenced by MUTATOR_HOOKFUNCTION(), ons_Teleport(), PutPlayerInServer(), TeleportPlayer(), and WarpZone_TeleportPlayer().

◆ bot_clientconnect()

void bot_clientconnect ( entity this)

Definition at line 469 of file bot.qc.

470{
471 if (!IS_BOT_CLIENT(this)) return;
473 this.bot_nextthink = time - random();
474 this.isbot = true;
475 this.createdtime = this.bot_nextthink;
476
477 if(!this.bot_config_loaded) // This is needed so team overrider doesn't break between matches
478 {
481 }
482
483 havocbot_setupbot(this);
484}
float isbot
Definition api.qh:49
void bot_setclientfields(entity this)
Definition bot.qc:39
void bot_setnameandstuff(entity this)
Definition bot.qc:163
float createdtime
Definition bot.qh:61
float bot_config_loaded
Definition bot.qh:74
float bot_nextthink
Definition bot.qh:59
float bot_preferredcolors
Definition bot.qh:62
clientcolors
Definition ent_cs.qc:147
void havocbot_setupbot(entity this)
Definition havocbot.qc:1764
float random(void)
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition utils.qh:15

◆ bot_clientdisconnect()

void bot_clientdisconnect ( entity this)

Definition at line 454 of file bot.qc.

455{
456 if (!IS_BOT_CLIENT(this))
457 return;
458 bot_clearqueue(this);
459 strfree(this.cleanname);
463 if(this.bot_cmd_current)
464 delete(this.bot_cmd_current);
465 if(bot_waypoint_queue_owner == this)
467}
string cleanname
Definition api.qh:45
string netname_freeme
Definition bot.qh:55
string playermodel_freeme
Definition bot.qh:56
string playerskin_freeme
Definition bot.qh:57
void bot_clearqueue(entity bot)
Definition scripting.qc:21
entity bot_waypoint_queue_owner
Definition navigation.qh:85
#define NULL
Definition post.qh:14
entity bot_cmd_current
Definition scripting.qh:60
#define strfree(this)
Definition string.qh:59

◆ bot_cmdhelp()

void bot_cmdhelp ( string scmd)

Definition at line 331 of file scripting.qc.

332{
333 int i, ntype;
334 string stype;
335
338
339 for(i=1;i<BOT_CMD_COUNTER;++i)
340 {
341 if(bot_cmd_string[i]!=scmd)
342 continue;
343
344 ntype = bot_cmd_parm_type[i];
345
346 switch(ntype)
347 {
349 stype = "float";
350 break;
352 stype = "string";
353 break;
355 stype = "vector";
356 break;
357 default:
358 stype = "none";
359 break;
360 }
361
362 string desc = "";
363 switch(i)
364 {
365 case BOT_CMD_PAUSE:
366 desc = "Stops the bot completely. Any command other than 'continue' will be ignored.";
367 break;
368 case BOT_CMD_CONTINUE:
369 desc = "Disable paused status";
370 break;
371 case BOT_CMD_WAIT:
372 desc = "Pause command parsing and bot ai for N seconds. Pressed key will remain pressed";
373 break;
375 desc = "Pause command parsing and bot ai until time is N from the last barrier. Pressed key will remain pressed";
376 break;
377 case BOT_CMD_BARRIER:
378 desc = "Waits till all bots that have a command queue reach this command. Pressed key will remain pressed";
379 break;
380 case BOT_CMD_TURN:
381 desc = "Look to the right or left N degrees. For turning to the left use positive numbers.";
382 break;
383 case BOT_CMD_MOVETO:
384 desc = "Walk to an specific coordinate on the map. Usage: moveto \'x y z\'";
385 break;
387 desc = "Walk to the specific target on the map";
388 break;
390 desc = "Resets the goal stack";
391 break;
392 case BOT_CMD_CC:
393 desc = "Execute client command. Examples: cc say something; cc god; cc name newnickname; cc kill;";
394 break;
395 case BOT_CMD_IF:
396 desc = "Perform simple conditional execution.\n"
397 "Syntax: \n"
398 " sv_cmd .. if \"condition\"\n"
399 " sv_cmd .. <instruction if true>\n"
400 " sv_cmd .. <instruction if true>\n"
401 " sv_cmd .. else\n"
402 " sv_cmd .. <instruction if false>\n"
403 " sv_cmd .. <instruction if false>\n"
404 " sv_cmd .. fi\n"
405 "Conditions: a=b, a>b, a<b, a\t\t(spaces not allowed)\n"
406 " Values in conditions can be numbers, cvars in the form cvar.cvar_string or special fields\n"
407 "Fields: health, speed, flagcarrier\n"
408 "Examples: if health>50; if health>cvar.g_balance_laser_primary_damage; if flagcarrier;";
409 break;
410 case BOT_CMD_RESETAIM:
411 desc = "Points the aim to the coordinates x,y 0,0";
412 break;
413 case BOT_CMD_AIM:
414 desc = "Move the aim x/y (horizontal/vertical) degrees relatives to the bot\n"
415 "There is a 3rd optional parameter telling in how many seconds the aim has to reach the new position\n"
416 "Examples: aim \"90 0\" // Turn 90 degrees inmediately (positive numbers move to the left/up)\n"
417 " aim \"0 90 2\" // Will gradually look to the sky in the next two seconds";
418 break;
420 desc = "Points the aim to given target";
421 break;
422 case BOT_CMD_PRESSKEY:
423 desc = "Press one of the following keys: forward, backward, left, right, jump, crouch, attack1, attack2, use"
424 "Multiple keys can be pressed at time (with many presskey calls) and it will remain pressed until the command \"releasekey\" is called"
425 "Note: The script will not return the control to the bot ai until all keys are released";
426 break;
428 desc = "Release previoulsy used keys. Use the parameter \"all\" to release all keys";
429 break;
430 case BOT_CMD_SOUND:
431 desc = "play sound file at bot location";
432 break;
434 desc = "verify the state of the weapon entity";
435 break;
436 default:
437 desc = "This command has no description yet.";
438 break;
439 }
440 LOG_HELP("Command: ", bot_cmd_string[i], "\nParameter: <", stype, ">", "\nDescription: ", desc);
441 }
442}
#define LOG_HELP(...)
Definition log.qh:85
void bot_commands_init()
Definition scripting.qc:157
const int BOT_CMD_AIMTARGET
Definition scripting.qh:32
const int BOT_CMD_AIM
Definition scripting.qh:25
const int BOT_CMD_PARAMETER_FLOAT
Definition scripting.qh:50
const int BOT_CMD_CC
Definition scripting.qh:20
const int BOT_CMD_PRESSKEY
Definition scripting.qh:26
const int BOT_CMD_WAIT_UNTIL
Definition scripting.qh:30
const int BOT_CMD_IF
Definition scripting.qh:21
const int BOT_CMD_DEBUG_ASSERT_CANFIRE
Definition scripting.qh:36
string bot_cmd_string[BOT_CMD_COUNTER]
Definition scripting.qh:56
const int BOT_CMD_SOUND
Definition scripting.qh:35
const int BOT_CMD_RELEASEKEY
Definition scripting.qh:27
const int BOT_CMD_MOVETOTARGET
Definition scripting.qh:31
const int BOT_CMD_PAUSE
Definition scripting.qh:14
const int BOT_CMD_CONTINUE
Definition scripting.qh:15
const int BOT_CMD_MOVETO
Definition scripting.qh:18
const int BOT_CMD_PARAMETER_VECTOR
Definition scripting.qh:52
const int BOT_CMD_COUNTER
Definition scripting.qh:41
const int BOT_CMD_PARAMETER_STRING
Definition scripting.qh:51
const int BOT_CMD_BARRIER
Definition scripting.qh:33
const int BOT_CMD_WAIT
Definition scripting.qh:16
const int BOT_CMD_TURN
Definition scripting.qh:17
int bot_cmd_parm_type[BOT_CMD_COUNTER]
Definition scripting.qh:55
const int BOT_CMD_RESETGOAL
Definition scripting.qh:19
const int BOT_CMD_RESETAIM
Definition scripting.qh:24
float bot_cmds_initialized
Definition scripting.qh:54

References BOT_CMD_AIM, BOT_CMD_AIMTARGET, BOT_CMD_BARRIER, BOT_CMD_CC, BOT_CMD_CONTINUE, BOT_CMD_COUNTER, BOT_CMD_DEBUG_ASSERT_CANFIRE, BOT_CMD_IF, BOT_CMD_MOVETO, BOT_CMD_MOVETOTARGET, BOT_CMD_PARAMETER_FLOAT, BOT_CMD_PARAMETER_STRING, BOT_CMD_PARAMETER_VECTOR, bot_cmd_parm_type, BOT_CMD_PAUSE, BOT_CMD_PRESSKEY, BOT_CMD_RELEASEKEY, BOT_CMD_RESETAIM, BOT_CMD_RESETGOAL, BOT_CMD_SOUND, bot_cmd_string, BOT_CMD_TURN, BOT_CMD_WAIT, BOT_CMD_WAIT_UNTIL, bot_cmds_initialized, bot_commands_init(), and LOG_HELP.

Referenced by GameCommand_bot_cmd().

◆ bot_endgame()

void bot_endgame ( )

Definition at line 412 of file bot.qc.

413{
415 entity e = bot_list;
416 while (e)
417 {
418 setcolor(e, e.bot_preferredcolors);
419 e = e.nextbot;
420 }
421 // if dynamic waypoints are ever implemented, save them here
422}
void bot_relinkplayerlist()
Definition bot.qc:424
entity bot_list
Definition bot.qh:50
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
#define setcolor
Definition pre.qh:11

References bot_list, bot_relinkplayerlist(), entity(), and setcolor.

Referenced by Shutdown().

◆ bot_fixcount()

bool bot_fixcount ( bool multiple_per_frame)

Definition at line 623 of file bot.qc.

624{
625 int activerealplayers = 0;
626 int realplayers = 0;
627 if (MUTATOR_CALLHOOK(Bot_FixCount, activerealplayers, realplayers)) {
628 activerealplayers = M_ARGV(0, int);
629 realplayers = M_ARGV(1, int);
630 } else {
632 if(IS_PLAYER(it))
633 ++activerealplayers;
634 ++realplayers;
635 });
636 }
637
638 int bots;
639 // But don't remove bots immediately on level change, as the real players
640 // usually haven't rejoined yet
643 bots = min(ceil(fabs(autocvar_bot_vs_human) * activerealplayers), maxclients - realplayers);
644 else if ((realplayers || autocvar_bot_join_empty || (currentbots > 0 && time < 5)))
645 {
646 int minplayers = max(0, floor(autocvar_minplayers));
647 if (teamplay)
649 int minbots = max(0, floor(autocvar_bot_number));
650
651 // add bots to reach minplayers if needed
652 bots = max(minbots, minplayers - activerealplayers);
653 // cap bots to the max players allowed by the server
654 int player_limit = GetPlayerLimit();
655 if(player_limit)
656 bots = min(bots, max(player_limit - activerealplayers, 0));
657 bots = min(bots, maxclients - realplayers);
658
659 bots_would_leave = max(0, bots - minbots);
660 }
661 else
662 {
663 // if there are no players, remove bots
664 bots = 0;
665 }
666
667 // only add one bot per frame to avoid utter chaos
669 {
670 while (currentbots < bots)
671 {
672 if (bot_spawn() == NULL)
673 {
674 bprint("Can not add bot, server full.\n");
675 return false;
676 }
677 if (!multiple_per_frame)
678 {
679 break;
680 }
681 }
682 while (currentbots > bots && bots >= 0)
684 }
685
686 return true;
687}
int bots_would_leave
how many bots would leave so humans can replace them
Definition api.qh:101
int currentbots
Definition api.qh:104
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
entity bot_spawn()
Definition bot.qc:45
void bot_removenewest()
Definition bot.qc:533
float botframe_nextthink
Definition bot.qh:80
#define M_ARGV(x, type)
Definition events.qh:17
#define IS_PLAYER(s)
Definition player.qh:243
float maxclients
bool autocvar_bot_join_empty
Definition cvars.qh:49
int autocvar_bot_number
Definition cvars.qh:64
int autocvar_minplayers
Definition cvars.qh:68
int autocvar_minplayers_per_team
Definition cvars.qh:69
int autocvar_bot_vs_human
Definition cvars.qh:67
float ceil(float f)
void bprint(string text,...)
float min(float f,...)
float fabs(float f)
float floor(float f)
float max(float f,...)
#define AVAILABLE_TEAMS
int GetPlayerLimit()
Definition client.qc:2127
bool teamplay
Definition teams.qh:59
#define IS_REAL_CLIENT(v)
Definition utils.qh:17
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50

References autocvar_bot_join_empty, autocvar_bot_number, autocvar_bot_vs_human, autocvar_minplayers, autocvar_minplayers_per_team, AVAILABLE_TEAMS, bot_removenewest(), bot_spawn(), botframe_nextthink, bots_would_leave, bprint(), ceil(), currentbots, fabs(), floor(), FOREACH_CLIENT, GetPlayerLimit(), IS_PLAYER, IS_REAL_CLIENT, M_ARGV, max(), maxclients, min(), MUTATOR_CALLHOOK, NULL, teamplay, and time.

Referenced by GameCommand_bot_cmd(), and GameCommand_setbots().

◆ bot_list_commands()

void bot_list_commands ( )

Definition at line 444 of file scripting.qc.

445{
446 int i;
447 string ptype;
448
451
452 LOG_HELP("Bot commands:");
453
454 for(i=1;i<BOT_CMD_COUNTER;++i)
455 {
456 switch(bot_cmd_parm_type[i])
457 {
459 ptype = "float";
460 break;
462 ptype = "string";
463 break;
465 ptype = "vector";
466 break;
467 default:
468 ptype = "none";
469 break;
470 }
471 if (ptype != "none")
472 LOG_HELP(" ^2", bot_cmd_string[i]," ^7<", ptype, ">");
473 else
474 LOG_HELP(" ^2", bot_cmd_string[i]);
475 }
476 LOG_HELP("For help about a specific command, type bot_cmd help <command>");
477}

References BOT_CMD_COUNTER, BOT_CMD_PARAMETER_FLOAT, BOT_CMD_PARAMETER_STRING, BOT_CMD_PARAMETER_VECTOR, bot_cmd_parm_type, bot_cmd_string, bot_cmds_initialized, bot_commands_init(), and LOG_HELP.

Referenced by GameCommand_bot_cmd().

◆ bot_queuecommand()

void bot_queuecommand ( entity bot,
string cmdstring )

Definition at line 30 of file scripting.qc.

31{
32 if(!bot.bot_cmdqueuebuf_allocated)
33 {
34 bot.bot_cmdqueuebuf = buf_create();
35 bot.bot_cmdqueuebuf_allocated = true;
36 bot.bot_cmdqueuebuf_start = 0;
37 bot.bot_cmdqueuebuf_end = 0;
38 }
39
40 bufstr_set(bot.bot_cmdqueuebuf, bot.bot_cmdqueuebuf_end, cmdstring);
41
42 // if the command was a "sound" command, precache the sound NOW
43 // this prevents lagging!
44 {
45 float sp;
46 string parm;
47 string cmdstr;
48
49 sp = strstrofs(cmdstring, " ", 0);
50 if(sp >= 0)
51 {
52 parm = substring(cmdstring, sp + 1, -1);
53 cmdstr = substring(cmdstring, 0, sp);
54 if(cmdstr == "sound")
55 {
56 // find the LAST word
57 for (;;)
58 {
59 sp = strstrofs(parm, " ", 0);
60 if(sp < 0)
61 break;
62 parm = substring(parm, sp + 1, -1);
63 }
64 precache_sound(parm);
65 }
66 }
67 }
68
69 bot.bot_cmdqueuebuf_end += 1;
70}
#define strstrofs
#define buf_create
string substring(string s, float start, float length)
string precache_sound(string sample)

References buf_create, entity(), precache_sound(), strstrofs, and substring().

Referenced by GameCommand_bot_cmd().

◆ bot_relinkplayerlist()

void bot_relinkplayerlist ( )

Definition at line 424 of file bot.qc.

425{
426 player_count = 0;
427 currentbots = 0;
428 bot_list = NULL;
429
430 entity prevbot = NULL;
431 FOREACH_CLIENT(true,
432 {
433 ++player_count;
434
435 if(IS_BOT_CLIENT(it))
436 {
437 if (!IS_OBSERVER(it) && !bot_ispaused(it))
438 {
439 if(prevbot)
440 prevbot.nextbot = it;
441 else
442 bot_list = it;
443 prevbot = it;
444 }
445 ++currentbots;
446 }
447 });
448 if(prevbot)
449 prevbot.nextbot = NULL;
452}
int player_count
Definition api.qh:103
entity bot_strategytoken
Definition bot.qh:77
float bot_strategytoken_taken
Definition bot.qh:76
bool bot_ispaused(entity this)
#define IS_OBSERVER(v)
Definition utils.qh:11

References bot_ispaused(), bot_list, bot_strategytoken, bot_strategytoken_taken, currentbots, entity(), FOREACH_CLIENT, IS_BOT_CLIENT, IS_OBSERVER, NULL, and player_count.

Referenced by bot_cmd_continue(), bot_cmd_pause(), ClientConnect(), ClientDisconnect(), MUTATOR_HOOKFUNCTION(), PutClientInServer(), and PutObserverInServer().

◆ bot_resetqueues()

void bot_resetqueues ( )

Definition at line 1165 of file scripting.qc.

1166{
1167 FOREACH_CLIENT(it.isbot, {
1168 it.bot_cmd_execution_index = 0;
1169 bot_clearqueue(it);
1170 // also, cancel all barriers
1171 it.bot_barrier = 0;
1172 for(int i = 0; i < it.bot_places_count; ++i)
1173 {
1174 strfree(it.(bot_placenames[i]));
1175 }
1176 it.bot_places_count = 0;
1177 });
1178
1180}
float bot_barriertime
Definition scripting.qh:68

References FOREACH_CLIENT.

Referenced by GameCommand_bot_cmd().

◆ bot_serverframe()

void bot_serverframe ( )

Definition at line 689 of file bot.qc.

690{
692 {
693 // after the end of the match all bots stay unless all human players disconnect
694 int realplayers = 0;
695 FOREACH_CLIENT(IS_REAL_CLIENT(it), { ++realplayers; });
696 if (!realplayers)
697 {
698 FOREACH_CLIENT(IS_BOT_CLIENT(it), { dropclient(it); });
699 currentbots = 0;
700 }
701 return;
702 }
703
704 if (game_stopped)
705 return;
706
707 // Added 0.5 to avoid possible addition + immediate removal of bots that would make them appear as
708 // spectators in the scoreboard and never go away. This issue happens at time 2 if map is changed
709 // with the gotomap command, minplayers is > 1 and human clients join as players very soon
710 // either intentionally or automatically (sv_spectate 0)
711 // A working workaround for this bug was implemented in commit fbd145044, see entcs_attach
712 if (time < 2.5)
713 {
714 currentbots = -1;
715 return;
716 }
717
718 if (currentbots == -1)
719 {
720 // count bots already in the server from the previous match
721 currentbots = 0;
723 }
724
725 if(autocvar_skill != skill)
726 {
727 float wpcost_update = false;
729 wpcost_update = true;
731 wpcost_update = true;
732
734 if (wpcost_update)
736 }
737
740
742 {
743 float a;
745 if(a)
746 autoskill(a);
748 }
749
751 {
752 if(!bot_fixcount(false))
754 }
755
757 {
759 localcmd("quit\n");
760 }
761
764 {
766 {
769 }
770 else
771 {
772 // TODO: Make this check cleaner
773 IL_EACH(g_waypoints, time - it.nextthink > 10,
774 {
775 waypoint_save_links();
776 break;
777 });
778 }
779 }
780 else
781 {
785 }
786
787 if (bot_list)
788 {
789 // cycle the goal token from one bot to the next each frame
790 // (this prevents them from all doing spawnfunc_waypoint searches on the same
791 // frame, which causes choppy framerates)
793 {
794 // give goal token to the first bot without goals; if all bots don't have
795 // any goal (or are dead/frozen) simply give it to the next one
797 entity bot_strategytoken_save = bot_strategytoken;
798 while (true)
799 {
804
806 && !bot_strategytoken.goalcurrent)
807 break;
808
809 if (!bot_strategytoken_save) // break loop if all the bots are dead or frozen
810 break;
811 if (bot_strategytoken == bot_strategytoken_save)
812 bot_strategytoken_save = NULL; // looped through all the bots
813 }
814 }
815
817 {
818 float interval;
820 if (botframe_nextdangertime < time - interval * 1.5)
824 }
825 }
826
829
832
833 if (currentbots > 0)
835}
float skill
Definition api.qh:35
IntrusiveList g_waypoints
Definition api.qh:148
bool bot_fixcount(bool multiple_per_frame)
Definition bot.qc:623
void bot_custom_weapon_priority_setup()
Definition bot.qc:351
void autoskill(float factor)
Definition bot.qc:569
void bot_calculate_stepheightvec()
Definition bot.qc:615
float autoskill_nextthink
Definition bot.qh:25
float botframe_spawnedwaypoints
Definition bot.qh:79
float botframe_nextdangertime
Definition bot.qh:81
#define IS_DEAD(s)
Definition player.qh:245
float game_stopped
Definition stats.qh:81
const float MOVE_NOMONSTERS
const float MOVE_NORMAL
bool autocvar_bot_navigation_ignoreplayers
Definition cvars.qh:50
float autocvar_skill_auto
Definition cvars.qh:62
int autocvar_g_waypointeditor_auto
Definition cvars.qh:60
bool autocvar_waypoint_benchmark
Definition cvars.qh:63
float autocvar_bot_ai_dangerdetectioninterval
Definition cvars.qh:30
float autocvar_bot_ai_bunnyhop_skilloffset
Definition cvars.qh:19
float autocvar_bot_ai_dangerdetectionupdates
Definition cvars.qh:31
#define autocvar_skill
Definition cvars.qh:61
bool intermission_running
#define IL_EACH(this, cond, body)
#define STAT(...)
Definition stats.qh:82
void localcmd(string command,...)
void botframe_updatedangerousobjects(float maxupdate)
float bot_navigation_movemode
Definition navigation.qh:7
bool waypoint_load_links()
void waypoint_updatecost_foralllinks()
Definition waypoints.qc:971
float waypoint_loadall()
void waypoint_load_hardwiredlinks()
void botframe_showwaypointlinks()
void botframe_autowaypoints()
bool waypointeditor_enabled
Definition waypoints.qh:3
float botframe_cachedwaypointlinks
Definition waypoints.qh:24
float botframe_loadedforcedlinks
Definition waypoints.qh:23

References autocvar_bot_ai_bunnyhop_skilloffset, autocvar_bot_ai_dangerdetectioninterval, autocvar_bot_ai_dangerdetectionupdates, autocvar_bot_navigation_ignoreplayers, autocvar_g_waypointeditor_auto, autocvar_skill, autocvar_skill_auto, autocvar_waypoint_benchmark, autoskill(), autoskill_nextthink, bot_calculate_stepheightvec(), bot_custom_weapon_priority_setup(), bot_fixcount(), bot_list, bot_navigation_movemode, bot_strategytoken, bot_strategytoken_taken, botframe_autowaypoints(), botframe_cachedwaypointlinks, botframe_loadedforcedlinks, botframe_nextdangertime, botframe_nextthink, botframe_showwaypointlinks(), botframe_spawnedwaypoints, botframe_updatedangerousobjects(), currentbots, entity(), FOREACH_CLIENT, g_waypoints, game_stopped, IL_EACH, intermission_running, IS_BOT_CLIENT, IS_DEAD, IS_REAL_CLIENT, localcmd(), MOVE_NOMONSTERS, MOVE_NORMAL, NULL, skill, STAT, time, waypoint_load_hardwiredlinks(), waypoint_load_links(), waypoint_loadall(), waypoint_updatecost_foralllinks(), and waypointeditor_enabled.

Referenced by StartFrame().

◆ bot_shouldattack()

bool bot_shouldattack ( entity this,
entity e )

Definition at line 97 of file aim.qc.

98{
99 if (targ.team == this.team)
100 {
101 if (targ == this)
102 return false;
103 if (teamplay)
104 if (targ.team != 0)
105 return false;
106 }
107
108 if(teamplay)
109 {
110 if(targ.team==0)
111 return false;
112 }
113 else if (autocvar_bot_ignore_bots && IS_BOT_CLIENT(targ))
114 return false;
115
116 if (!targ.takedamage)
117 return false;
118 if (IS_DEAD(targ))
119 return false;
121 return false;
122 if(targ.flags & FL_NOTARGET)
123 return false;
124 if(targ.alpha <= 0.1 && targ.alpha != 0)
125 return false; // invisible via alpha
126
127 if(MUTATOR_CALLHOOK(BotShouldAttack, this, targ))
128 return false;
129
130 return true;
131}
#define PHYS_INPUT_BUTTON_CHAT(s)
Definition player.qh:159
const int FL_NOTARGET
Definition constants.qh:76
bool autocvar_bot_typefrag
Definition cvars.qh:58
bool autocvar_bot_ignore_bots
Definition cvars.qh:48

References autocvar_bot_ignore_bots, autocvar_bot_typefrag, entity(), FL_NOTARGET, IS_BOT_CLIENT, IS_DEAD, MUTATOR_CALLHOOK, PHYS_INPUT_BUTTON_CHAT, and teamplay.

Referenced by havocbot_chooseenemy(), and havocbot_goalrating_enemyplayers().

◆ bot_think()

void bot_think ( entity this)

Definition at line 62 of file bot.qc.

63{
64 if (this.bot_nextthink > time)
65 return;
66
67 this.flags &= ~FL_GODMODE;
69 this.flags |= FL_GODMODE;
70
71 // if bot skill is high enough don't limit their think frequency
72 if (SUPERBOT)
73 this.bot_nextthink = max(time, this.bot_nextthink) + 0.005;
74 else
75 this.bot_nextthink = max(time, this.bot_nextthink) + max(0.01, autocvar_bot_ai_thinkinterval * min(14 / (skill + this.bot_aiskill + 14), 1));
76
78 {
79 CS(this).movement = '0 0 0';
80 this.bot_nextthink = time + 0.5;
81 return;
82 }
83
84 if (this.fixangle)
85 {
86 this.v_angle = this.angles;
87 this.v_angle_z = 0;
88 this.fixangle = false;
89 }
90
91 this.dmg_take = 0;
92 this.dmg_save = 0;
93 this.dmg_inflictor = NULL;
94
95 // if bot skill is high enough don't assign latency to them
96 if (SUPERBOT)
97 CS(this).ping = 0;
98 else
99 {
100 // calculate an aiming latency based on the skill setting
101 // (simulated network latency + naturally delayed reflexes)
102 //this.ping = 0.7 - bound(0, 0.05 * skill, 0.5); // moved the reflexes to bot_aimdir (under the name 'think')
103 // minimum ping 20+10 random
104 CS(this).ping = bound(0,0.07 - bound(0, (skill + this.bot_pingskill) * 0.005,0.05)+random()*0.01,0.65); // Now holds real lag to server, and higher skill players take a less laggy server
105 // skill 10 = ping 0.2 (adrenaline)
106 // skill 0 = ping 0.7 (slightly drunk)
107 }
108
109 // clear buttons
110 PHYS_INPUT_BUTTON_ATCK(this) = false;
111 // keep jump button pressed for a short while, useful with ramp jumps
112 PHYS_INPUT_BUTTON_JUMP(this) = (!IS_DEAD(this) && time < this.bot_jump_time + 0.2);
113 PHYS_INPUT_BUTTON_ATCK2(this) = false;
114 PHYS_INPUT_BUTTON_ZOOM(this) = false;
115 PHYS_INPUT_BUTTON_CROUCH(this) = false;
116 PHYS_INPUT_BUTTON_HOOK(this) = false;
117 PHYS_INPUT_BUTTON_INFO(this) = false;
118 PHYS_INPUT_BUTTON_DRAG(this) = false;
119 PHYS_INPUT_BUTTON_CHAT(this) = false;
120 PHYS_INPUT_BUTTON_USE(this) = false;
121
122 if (time < game_starttime)
123 {
124 // block the bot during the countdown to game start
125 CS(this).movement = '0 0 0';
126 return;
127 }
128
129 // if dead, just wait until we can respawn
130 if (IS_DEAD(this) || IS_OBSERVER(this))
131 {
132 if (bot_waypoint_queue_owner == this)
134 this.aistatus = 0;
135 CS(this).movement = '0 0 0';
136 if (IS_OBSERVER(this))
137 return;
138 if (IS_DEAD(this))
139 {
142 // jump must not be pressed for at least one frame in order for
143 // PlayerThink to detect the key down event
144 if (this.deadflag == DEAD_DYING)
145 PHYS_INPUT_BUTTON_JUMP(this) = false;
146 else if (this.deadflag == DEAD_DEAD)
147 PHYS_INPUT_BUTTON_JUMP(this) = true; // press jump to respawn
148 }
149 }
150 else if(this.aistatus & AI_STATUS_STUCK)
151 navigation_unstuck(this);
152
153 if (warmup_stage && !this.ready)
154 {
155 this.ready = true;
156 ReadyCount(); // this must be delayed until the bot has spawned
157 }
158
159 // now call the current bot AI (havocbot for example)
160 this.bot_ai(this);
161}
void navigation_goalrating_timeout_force(entity this)
Definition navigation.qc:29
bool navigation_goalrating_timeout(entity this)
Definition navigation.qc:44
float bot_aiskill
Definition bot.qh:42
int aistatus
Definition bot.qh:20
float bot_pingskill
Definition bot.qh:31
#define SUPERBOT
Definition bot.qh:23
float bot_jump_time
Definition bot.qh:71
const int AI_STATUS_STUCK
Definition bot.qh:17
bool ready
Definition main.qh:88
bool warmup_stage
Definition main.qh:120
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition player.qh:154
#define PHYS_INPUT_BUTTON_JUMP(s)
Definition player.qh:151
#define PHYS_INPUT_BUTTON_HOOK(s)
Definition player.qh:155
#define PHYS_INPUT_BUTTON_INFO(s)
Definition player.qh:156
#define PHYS_INPUT_BUTTON_USE(s)
Definition player.qh:158
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition player.qh:150
#define PHYS_INPUT_BUTTON_ZOOM(s)
Definition player.qh:153
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:152
#define PHYS_INPUT_BUTTON_DRAG(s)
Definition player.qh:157
float game_starttime
Definition stats.qh:82
const int FL_GODMODE
Definition constants.qh:75
float flags
float autocvar_bot_ai_thinkinterval
Definition cvars.qh:41
bool autocvar_bot_god
Definition cvars.qh:47
ent angles
Definition ent_cs.qc:121
bool autocvar_g_campaign
Definition menu.qc:747
float bound(float min, float value, float max)
void navigation_unstuck(entity this)
float DEAD_DYING
Definition progsdefs.qc:275
float fixangle
Definition progsdefs.qc:160
float deadflag
Definition progsdefs.qc:149
float dmg_save
Definition progsdefs.qc:199
float DEAD_DEAD
Definition progsdefs.qc:276
entity dmg_inflictor
Definition progsdefs.qc:200
bool campaign_bots_may_start
campaign mode: bots shall spawn but wait for the player to spawn before they do anything in other gam...
Definition campaign.qh:26
void ReadyCount()
Definition vote.qc:553
ClientState CS(Client this)
Definition state.qh:47
float dmg_take
Definition view.qh:123

References AI_STATUS_STUCK, aistatus, angles, autocvar_bot_ai_thinkinterval, autocvar_bot_god, autocvar_g_campaign, bot_aiskill, bot_jump_time, bot_nextthink, bot_pingskill, bot_waypoint_queue_owner, bound(), campaign_bots_may_start, CS(), DEAD_DEAD, DEAD_DYING, deadflag, dmg_inflictor, dmg_save, dmg_take, entity(), fixangle, FL_GODMODE, flags, game_starttime, IS_DEAD, IS_OBSERVER, IS_PLAYER, max(), min(), navigation_goalrating_timeout(), navigation_goalrating_timeout_force(), navigation_unstuck(), NULL, PHYS_INPUT_BUTTON_ATCK, PHYS_INPUT_BUTTON_ATCK2, PHYS_INPUT_BUTTON_CHAT, PHYS_INPUT_BUTTON_CROUCH, PHYS_INPUT_BUTTON_DRAG, PHYS_INPUT_BUTTON_HOOK, PHYS_INPUT_BUTTON_INFO, PHYS_INPUT_BUTTON_JUMP, PHYS_INPUT_BUTTON_USE, PHYS_INPUT_BUTTON_ZOOM, random(), ready, ReadyCount(), skill, SUPERBOT, time, v_angle, and warmup_stage.

Referenced by sys_phys_ai().

◆ find_bot_by_name()

entity find_bot_by_name ( string name)

Definition at line 235 of file scripting.qc.

236{
237 FOREACH_CLIENT(IS_BOT_CLIENT(it) && it.netname == name,
238 {
239 return it;
240 });
241
242 return NULL;
243}
string name
Definition menu.qh:30

References entity(), FOREACH_CLIENT, IS_BOT_CLIENT, name, and NULL.

Referenced by GameCommand_bot_cmd().

◆ find_bot_by_number()

entity find_bot_by_number ( float number)

Definition at line 246 of file scripting.qc.

247{
248 entity bot;
249 float c = 0;
250
251 if(!number)
252 return NULL;
253
254 bot = findchainflags(flags, FL_CLIENT); // TODO: doesn't findchainflags loop backwards through entities?
255 while (bot)
256 {
257 if(IS_BOT_CLIENT(bot))
258 {
259 if(++c==number)
260 return bot;
261 }
262 bot = bot.chain;
263 }
264
265 return NULL;
266}
const int FL_CLIENT
Definition constants.qh:72
entity findchainflags(.float field, float match)
int int number
Definition impulse.qc:89

References entity(), findchainflags(), FL_CLIENT, flags, IS_BOT_CLIENT, NULL, and number.

Referenced by GameCommand_bot_cmd().

◆ float()

float ( entity player,
entity item )

References entity().

◆ get_closer_dest()

vector get_closer_dest ( entity ent,
vector org )

Definition at line 104 of file navigation.qc.

105{
106 vector dest = '0 0 0';
107 if ((ent.classname != "waypoint") || ent.wpisbox)
108 {
109 vector wm1 = ent.origin + ent.mins;
110 vector wm2 = ent.origin + ent.maxs;
111 dest.x = bound(wm1.x, org.x, wm2.x);
112 dest.y = bound(wm1.y, org.y, wm2.y);
113 dest.z = bound(wm1.z, org.z, wm2.z);
114 }
115 else
116 dest = ent.origin;
117 return dest;
118}
vector dest
Definition jumppads.qh:54
vector
Definition self.qh:92
vector org
Definition self.qh:92

References bound(), dest, entity(), org, and vector.

Referenced by havocbot_ai(), havocbot_bunnyhop(), havocbot_moveto(), and havocbot_movetogoal().

◆ havocbot_goalrating_enemyplayers()

void havocbot_goalrating_enemyplayers ( entity this,
float ratingscale,
vector org,
float sradius )

Definition at line 176 of file roles.qc.

177{
179 return;
180
181 // don't chase players if we're under water
183 return;
184
185 ratingscale = ratingscale * 0.0001;
186
187 FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), {
188 // TODO: Merge this logic with the bot_shouldattack function
189 if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius))
190 continue;
191 if(vdist(vec2(it.velocity), >, autocvar_sv_maxspeed * 2))
192 continue;
193
194 // rate only visible enemies
195 /*
196 traceline(this.origin + this.view_ofs, it.origin, MOVE_NOMONSTERS, this);
197 if (trace_fraction < 1 || trace_ent != it)
198 continue;
199 */
200
201 float t = ((GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR)) - (GetResource(it, RES_HEALTH) + GetResource(it, RES_ARMOR))) / 150;
202 t = bound(0, 1 + t, 3);
203 if (skill > 3)
204 {
205 if (time < StatusEffects_gettime(STATUSEFFECT_Strength, this) - 1) t += 0.5;
206 if (time < StatusEffects_gettime(STATUSEFFECT_Strength, it) - 1) t -= 0.5;
207 if (time < StatusEffects_gettime(STATUSEFFECT_Shield, this) - 1) t += 0.2;
208 if (time < StatusEffects_gettime(STATUSEFFECT_Shield, it) - 1) t -= 0.4;
209 }
210 t += max(0, 8 - skill) * 0.05; // less skilled bots attack more mindlessly
211 ratingscale *= t;
212 if (ratingscale > 0)
213 navigation_routerating(this, it, ratingscale * BOT_RATING_ENEMY, 2000);
214 });
215}
void navigation_routerating(entity this, entity e, float f, float rangebias)
bool bot_shouldattack(entity this, entity e)
Definition aim.qc:97
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
float autocvar_sv_maxspeed
Definition player.qh:53
float waterlevel
Definition player.qh:226
bool autocvar_bot_nofire
Definition cvars.qh:51
RES_ARMOR
Definition ent_cs.qc:130
const int WATERLEVEL_WETFEET
Definition movetypes.qh:12
const float BOT_RATING_ENEMY
Definition roles.qh:3
float StatusEffects_gettime(StatusEffect this, entity actor)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
#define vec2(...)
Definition vector.qh:90

Referenced by havocbot_role_generic().

◆ havocbot_goalrating_item_pickable_check_players()

bool havocbot_goalrating_item_pickable_check_players ( entity this,
vector org,
entity item,
vector item_org )

Definition at line 60 of file roles.qc.

61{
62 if(!teamplay)
63 return true;
64
65 // these variables hold squared distances in order to optimize code
66 float friend_dist2 = FLOAT_MAX;
67 float enemy_dist2 = FLOAT_MAX;
68 float dist2;
69
70 FOREACH_CLIENT(IS_PLAYER(it) && it != this && !(IS_DEAD(it) || STAT(FROZEN, it)),
71 {
72 if (it.team == this.team)
73 {
74 if (!IS_REAL_CLIENT(it))
75 continue;
76
77 dist2 = vlen2(it.origin - item_org);
78 if (dist2 > friend_dist2)
79 continue;
80
82 {
83 friend_dist2 = dist2;
84 continue;
85 }
86 }
87 else
88 {
89 // If enemy only track distances
90 // TODO: track only if visible ?
91 dist2 = vlen2(it.origin - item_org);
92 if (dist2 < enemy_dist2)
93 enemy_dist2 = dist2;
94 }
95 });
96
97 // Rate the item only if no one needs it, or if an enemy is closer to it
98 dist2 = vlen2(item_org - org);
99 if ((enemy_dist2 < friend_dist2 && dist2 < enemy_dist2)
100 || (friend_dist2 > autocvar_bot_ai_friends_aware_pickup_radius ** 2)
101 || (dist2 < friend_dist2 && dist2 < 200 ** 2))
102 return true;
103 return false;
104};
float autocvar_bot_ai_friends_aware_pickup_radius
Definition cvars.qh:35
const float FLOAT_MAX
Definition float.qh:3
bool havocbot_goalrating_item_can_be_left_to_teammate(entity this, entity player, entity item)
Definition roles.qc:45
#define vlen2(v)
Definition vector.qh:4

References autocvar_bot_ai_friends_aware_pickup_radius, entity(), FLOAT_MAX, FOREACH_CLIENT, havocbot_goalrating_item_can_be_left_to_teammate(), IS_DEAD, IS_PLAYER, IS_REAL_CLIENT, org, STAT, teamplay, vector, and vlen2.

Referenced by havocbot_goalrating_items(), and navigation_goalrating_timeout_can_be_anticipated().

◆ havocbot_goalrating_items()

void havocbot_goalrating_items ( entity this,
float ratingscale,
vector org,
float sradius )

Definition at line 106 of file roles.qc.

107{
108 ratingscale = ratingscale * 0.0001;
109
110 IL_EACH(g_items, it.bot_pickup,
111 {
112 // ignore if bot already rated this item with a higher ratingscale
113 // NOTE: this code assumes each bot rates items in a different frame
114 if(it.bot_ratingscale_time == time && ratingscale < it.bot_ratingscale)
115 continue;
116
117 if(!it.solid)
118 {
119 if(!autocvar_bot_ai_timeitems)
120 continue;
121 if(!it.scheduledrespawntime)
122 continue;
123 if(it.respawntime < max(11, autocvar_bot_ai_timeitems_minrespawndelay))
124 continue;
125 if(it.respawntimejitter && !it.itemdef.instanceOfPowerup)
126 continue;
127
128 float t = 0;
129 if(it.itemdef.instanceOfPowerup)
130 t = bound(0, skill / 10, 1) * 6;
131 else if(skill >= 9)
132 t = 4;
133
134 if(time < it.scheduledrespawntime - t)
135 continue;
136
137 it.bot_pickup_respawning = true;
138 }
139 vector o = (it.absmin + it.absmax) * 0.5;
140 if(vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
141 continue;
142
143 // Check if the item can be picked up safely
144 if(ITEM_IS_LOOT(it))
145 {
146 if(!IS_ONGROUND(it))
147 continue;
148 traceline(o, o + '0 0 -1500', true, NULL);
149
150 if(IN_LAVA(trace_endpos + '0 0 1'))
151 continue;
152
153 // this tracebox_hits_trigger_hurt call isn't needed:
154 // dropped weapons are removed as soon as they fall on a trigger_hurt
155 // and can't be rated while they are in the air
156 //if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
157 // continue;
158 }
159 else
160 {
161 if(IN_LAVA(it.origin + (it.mins + it.maxs) * 0.5))
162 continue;
163 }
164
166 continue;
167
168 it.bot_ratingscale_time = time;
169 it.bot_ratingscale = ratingscale;
170 float rating = it.bot_pickupevalfunc(this, it);
171 if(rating > 0)
172 navigation_routerating(this, it, rating * ratingscale, 2000);
173 });
174}
entity ignoregoal
Definition api.qh:99
float ignoregoaltime
Definition api.qh:98
#define IN_LAVA(pos)
Definition bot.qh:84
vector trace_endpos
#define ITEM_IS_LOOT(item)
Returns whether the item is loot.
Definition spawning.qh:39
#define IS_ONGROUND(s)
Definition movetypes.qh:16
bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, entity item, vector item_org)
Definition roles.qc:60
IntrusiveList g_items
Definition items.qh:125

Referenced by havocbot_role_generic().

◆ havocbot_goalrating_waypoints()

void havocbot_goalrating_waypoints ( entity this,
float ratingscale,
vector org,
float sradius )

Definition at line 16 of file roles.qc.

17{
18 // rate waypoints only if there's no alternative goal
20 return;
21
22 float f;
23 float range = 500;
24 sradius = max(range, (0.5 + random() * 0.5) * sradius);
25 while(sradius > 100)
26 {
27 IL_EACH(g_waypoints, vdist(it.origin - org, <, sradius)
28 && vdist(it.origin - org, >, max(100, sradius - range))
29 && !(it.wpflags & WAYPOINTFLAG_TELEPORT),
30 {
31 if(vdist(it.origin - this.wp_goal_prev0.origin, <, range * 1.5))
32 f = 0.1;
33 else if(vdist(it.origin - this.wp_goal_prev1.origin, <, range * 1.5))
34 f = 0.1;
35 else
36 f = 0.5 + random() * 0.5;
37 navigation_routerating(this, it, ratingscale * f, 2000);
38 });
40 break;
41 sradius -= range;
42 }
43};
const int WAYPOINTFLAG_TELEPORT
Definition api.qh:13
entity navigation_bestgoal
Definition navigation.qh:15

References entity(), g_waypoints, IL_EACH, max(), navigation_bestgoal, org, random(), vdist, vector, and WAYPOINTFLAG_TELEPORT.

Referenced by havocbot_role_dom(), havocbot_role_ft_freeing(), havocbot_role_ft_offense(), havocbot_role_generic(), havocbot_role_ka_carrier(), and havocbot_role_tka_carrier().

◆ navigation_dynamicgoal_init()

void navigation_dynamicgoal_init ( entity this,
bool initially_static )

Definition at line 77 of file navigation.qc.

78{
79 this.navigation_dynamicgoal = true;
81 if(initially_static)
82 this.nearestwaypointtimeout = -1;
83 else
85}
entity bot_basewaypoint
Definition api.qh:106
float nearestwaypointtimeout
Definition api.qh:53
entity nearestwaypoint
Definition api.qh:54
bool navigation_dynamicgoal
Definition api.qh:107

References bot_basewaypoint, entity(), navigation_dynamicgoal, nearestwaypoint, nearestwaypointtimeout, and time.

Referenced by ctf_DelayedFlagSetup(), ka_SpawnBalls(), kh_Key_Spawn(), PutPlayerInServer(), tka_SpawnBalls(), and W_ThrowNewWeapon().

◆ navigation_dynamicgoal_set()

void navigation_dynamicgoal_set ( entity this,
entity dropper )

Definition at line 87 of file navigation.qc.

88{
90 if (dropper && dropper.nearestwaypointtimeout && dropper.nearestwaypointtimeout < time + 2)
91 this.nearestwaypoint = dropper.nearestwaypoint;
92 if (this.nearestwaypoint)
93 this.nearestwaypointtimeout += 2;
94}

References entity(), nearestwaypoint, nearestwaypointtimeout, and time.

Referenced by ctf_Handle_Throw(), ka_DropEvent(), ka_RespawnBall(), kh_Key_Detach(), tka_DropEvent(), and tka_RespawnBall().

◆ navigation_dynamicgoal_unset()

void navigation_dynamicgoal_unset ( entity this)

◆ navigation_findnearestwaypoint()

entity navigation_findnearestwaypoint ( entity ent,
float walkfromwp )

Definition at line 1012 of file navigation.qc.

1013{
1014 entity wp = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, NULL);
1016 {
1017 entity wp2 = navigation_findnearestwaypoint_withdist_except(ent, walkfromwp, 1050, wp);
1018 if (wp && !wp2)
1019 wp.wpflags |= WAYPOINTFLAG_PROTECTED;
1020 }
1021 return wp;
1022}
const int WAYPOINTFLAG_PROTECTED
Definition api.qh:16
entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfromwp, float bestdist, entity except)

References autocvar_g_waypointeditor_auto, entity(), navigation_findnearestwaypoint_withdist_except(), NULL, and WAYPOINTFLAG_PROTECTED.

Referenced by waypoint_remove_fromeditor(), and waypoint_unreachable().

◆ navigation_goalrating_end()

void navigation_goalrating_end ( entity this)

Definition at line 1846 of file navigation.qc.

1847{
1848 if(this.aistatus & AI_STATUS_STUCK)
1849 return;
1850
1851 entity wp = this.goalstack31; // save to wp as this.goalstack31 is set by navigation_routetogoal
1852 this.goalstack31 = NULL;
1853
1855 LOG_DEBUG("best goal ", navigation_bestgoal.classname);
1856
1857 if (wp && this.goalcurrent == wp)
1858 navigation_poproute(this);
1859
1860 // If the bot got stuck then try to reach the farthest waypoint
1861 if (!this.goalentity)
1862 {
1864 {
1865 LOG_DEBUG(this.netname, " cannot walk to any goal");
1866 this.aistatus |= AI_STATUS_STUCK;
1867 }
1868 this.goalentity_shouldbefrozen = false;
1869 }
1870 else
1871 this.goalentity_shouldbefrozen = boolean(STAT(FROZEN, this.goalentity));
1872}
#define boolean(value)
Definition bool.qh:9
string netname
Definition powerups.qc:20
vector origin
bool autocvar_bot_wander_enable
Definition cvars.qh:57
#define LOG_DEBUG(...)
Definition log.qh:80
entity goalentity
Definition viewloc.qh:16
bool navigation_routetogoal(entity this, entity e, vector startposition)
void navigation_poproute(entity this)
bool goalentity_shouldbefrozen
Definition navigation.qh:36
entity goalcurrent
Definition navigation.qh:19
entity goalstack31
Definition navigation.qh:26

References AI_STATUS_STUCK, aistatus, autocvar_bot_wander_enable, boolean, entity(), goalcurrent, goalentity, goalentity_shouldbefrozen, goalstack31, LOG_DEBUG, navigation_bestgoal, navigation_poproute(), navigation_routetogoal(), netname, NULL, origin, and STAT.

Referenced by havocbot_moveto_refresh_route(), havocbot_role_ast_defense(), havocbot_role_ast_offense(), havocbot_role_ctf_carrier(), havocbot_role_ctf_defense(), havocbot_role_ctf_escort(), havocbot_role_ctf_middle(), havocbot_role_ctf_offense(), havocbot_role_ctf_retriever(), havocbot_role_cts(), havocbot_role_dom(), havocbot_role_ft_freeing(), havocbot_role_ft_offense(), havocbot_role_generic(), havocbot_role_ka_carrier(), havocbot_role_ka_collector(), havocbot_role_kh_carrier(), havocbot_role_kh_defense(), havocbot_role_kh_freelancer(), havocbot_role_kh_offense(), havocbot_role_ons_offense(), havocbot_role_race(), havocbot_role_tka_carrier(), and havocbot_role_tka_collector().

◆ navigation_goalrating_start()

void navigation_goalrating_start ( entity this)

Definition at line 1831 of file navigation.qc.

1832{
1833 if(this.aistatus & AI_STATUS_STUCK)
1834 return;
1835
1841 navigation_markroutes(this, wp);
1842 this.goalstack31 = wp; // temporarly save the really close waypoint
1843}
entity navigation_get_really_close_waypoint(entity this)
void navigation_markroutes(entity this, entity fixed_source_waypoint)
void navigation_clearroute(entity this)
entity navigation_jetpack_goal
Definition navigation.qh:77
float navigation_bestrating
Definition navigation.qh:6

References AI_STATUS_STUCK, aistatus, entity(), goalstack31, navigation_bestgoal, navigation_bestrating, navigation_clearroute(), navigation_get_really_close_waypoint(), navigation_jetpack_goal, navigation_markroutes(), and NULL.

Referenced by havocbot_moveto_refresh_route(), havocbot_role_ast_defense(), havocbot_role_ast_offense(), havocbot_role_ctf_carrier(), havocbot_role_ctf_defense(), havocbot_role_ctf_escort(), havocbot_role_ctf_middle(), havocbot_role_ctf_offense(), havocbot_role_ctf_retriever(), havocbot_role_cts(), havocbot_role_dom(), havocbot_role_ft_freeing(), havocbot_role_ft_offense(), havocbot_role_generic(), havocbot_role_ka_carrier(), havocbot_role_ka_collector(), havocbot_role_kh_carrier(), havocbot_role_kh_defense(), havocbot_role_kh_freelancer(), havocbot_role_kh_offense(), havocbot_role_ons_offense(), havocbot_role_race(), havocbot_role_tka_carrier(), and havocbot_role_tka_collector().

◆ navigation_goalrating_timeout()

◆ navigation_goalrating_timeout_can_be_anticipated()

bool navigation_goalrating_timeout_can_be_anticipated ( entity this)

Definition at line 56 of file navigation.qc.

57{
58 vector gco = (this.goalentity.absmin + this.goalentity.absmax) * 0.5;
59 if (vdist(gco - this.origin, >, autocvar_sv_maxspeed * 1.5)
60 && time > this.bot_strategytime - (IS_MOVABLE(this.goalentity) ? 3 : 2))
61 {
62 return true;
63 }
64
65 if (this.goalentity.bot_pickup && time > this.bot_strategytime - 5)
66 {
68 {
69 this.ignoregoal = this.goalentity;
71 return true;
72 }
73 }
74 return false;
75}
bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, entity item, vector item_org)
Definition roles.qc:60
float autocvar_bot_ai_ignoregoal_timeout
Definition cvars.qh:36
#define IS_MOVABLE(v)
Definition utils.qh:25

References autocvar_bot_ai_ignoregoal_timeout, autocvar_sv_maxspeed, bot_strategytime, entity(), goalentity, havocbot_goalrating_item_pickable_check_players(), ignoregoal, ignoregoaltime, IS_MOVABLE, origin, time, vdist, and vector.

Referenced by havocbot_movetogoal().

◆ navigation_goalrating_timeout_expire()

void navigation_goalrating_timeout_expire ( entity this,
float seconds )

◆ navigation_goalrating_timeout_extend_if_needed()

void navigation_goalrating_timeout_extend_if_needed ( entity this,
float seconds )

Definition at line 50 of file navigation.qc.

51{
52 this.bot_strategytime = max(this.bot_strategytime, time + seconds);
53}

References bot_strategytime, entity(), max(), and time.

◆ navigation_goalrating_timeout_force()

void navigation_goalrating_timeout_force ( entity this)

Definition at line 29 of file navigation.qc.

30{
32}
void navigation_goalrating_timeout_expire(entity this, float seconds)
Definition navigation.qc:36

References entity(), and navigation_goalrating_timeout_expire().

Referenced by bot_think(), havocbot_ai(), havocbot_chooserole(), havocbot_movetogoal(), havocbot_role_ctf_retriever(), and havocbot_role_ctf_setrole().

◆ navigation_goalrating_timeout_set()

◆ navigation_markroutes()

void navigation_markroutes ( entity this,
entity fixed_source_waypoint )

Definition at line 1082 of file navigation.qc.

1083{
1084 float cost, cost2;
1085 vector p;
1086
1087 IL_EACH(g_waypoints, true,
1088 {
1089 it.wpconsidered = false;
1090 it.wpnearestpoint = '0 0 0';
1091 it.wpcost = 10000000;
1092 it.wpfire = 0;
1093 it.enemy = NULL;
1094 });
1095
1096 if(fixed_source_waypoint)
1097 {
1098 fixed_source_waypoint.wpconsidered = true;
1099 fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
1100 fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg;
1101 fixed_source_waypoint.wpfire = 1;
1102 fixed_source_waypoint.enemy = NULL;
1103 }
1104 else
1105 {
1106 // try a short range search for the nearest waypoints, and expand the search repeatedly if none are found
1107 // as this search is expensive we will use lower values if the bot is on the air
1108 float increment, maxdistance;
1109 if(IS_ONGROUND(this))
1110 {
1111 increment = 750;
1112 maxdistance = 50000;
1113 }
1114 else
1115 {
1116 increment = 500;
1117 maxdistance = 1500;
1118 }
1119
1120 for(int j = increment; !navigation_markroutes_nearestwaypoints(this, j) && j < maxdistance; j += increment);
1121 }
1122
1123 bool searching = true;
1124 while (searching)
1125 {
1126 searching = false;
1127 IL_EACH(g_waypoints, it.wpfire,
1128 {
1129 searching = true;
1130 it.wpfire = 0;
1131 cost = it.wpcost;
1132 p = it.wpnearestpoint;
1133 entity wp;
1134 wp = it.wp00;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp00mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1135 wp = it.wp01;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp01mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1136 wp = it.wp02;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp02mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1137 wp = it.wp03;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp03mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1138 wp = it.wp04;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp04mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1139 wp = it.wp05;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp05mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1140 wp = it.wp06;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp06mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1141 wp = it.wp07;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp07mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1142 wp = it.wp08;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp08mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1143 wp = it.wp09;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp09mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1144 wp = it.wp10;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp10mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1145 wp = it.wp11;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp11mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1146 wp = it.wp12;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp12mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1147 wp = it.wp13;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp13mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1148 wp = it.wp14;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp14mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1149 wp = it.wp15;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp15mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1150 wp = it.wp16;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp16mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1151 wp = it.wp17;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp17mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1152 wp = it.wp18;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp18mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1153 wp = it.wp19;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp19mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1154 wp = it.wp20;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp20mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1155 wp = it.wp21;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp21mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1156 wp = it.wp22;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp22mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1157 wp = it.wp23;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp23mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1158 wp = it.wp24;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp24mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1159 wp = it.wp25;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp25mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1160 wp = it.wp26;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp26mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1161 wp = it.wp27;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp27mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1162 wp = it.wp28;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp28mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1163 wp = it.wp29;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp29mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1164 wp = it.wp30;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp30mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1165 wp = it.wp31;if (wp){cost2 = cost + wp.dmg;if (wp.wpcost > cost2 + it.wp31mincost) navigation_markroutes_checkwaypoint(it, wp, cost2, p);
1166 }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
1167 });
1168 }
1169}
float navigation_markroutes_nearestwaypoints(entity this, float maxdist)

References entity(), g_waypoints, IL_EACH, IS_ONGROUND, navigation_markroutes_nearestwaypoints(), NULL, and vector.

Referenced by waypoint_unreachable().

◆ navigation_markroutes_inverted()

void navigation_markroutes_inverted ( entity fixed_source_waypoint)

Definition at line 1172 of file navigation.qc.

1173{
1174 float cost, cost2;
1175 vector p;
1176 IL_EACH(g_waypoints, true,
1177 {
1178 it.wpconsidered = false;
1179 it.wpnearestpoint = '0 0 0';
1180 it.wpcost = 10000000;
1181 it.wpfire = 0;
1182 it.enemy = NULL;
1183 });
1184
1185 if(fixed_source_waypoint)
1186 {
1187 fixed_source_waypoint.wpconsidered = true;
1188 fixed_source_waypoint.wpnearestpoint = fixed_source_waypoint.origin + 0.5 * (fixed_source_waypoint.mins + fixed_source_waypoint.maxs);
1189 fixed_source_waypoint.wpcost = fixed_source_waypoint.dmg; // the cost to get from X to fixed_source_waypoint
1190 fixed_source_waypoint.wpfire = 1;
1191 fixed_source_waypoint.enemy = NULL;
1192 }
1193 else
1194 {
1195 error("need to start with a waypoint\n");
1196 }
1197
1198 bool searching = true;
1199 while (searching)
1200 {
1201 searching = false;
1202 IL_EACH(g_waypoints, it.wpfire,
1203 {
1204 searching = true;
1205 it.wpfire = 0;
1206 cost = it.wpcost; // cost to walk from it to home
1207 p = it.wpnearestpoint;
1208 entity wp = it;
1209 IL_EACH(g_waypoints, it != wp,
1210 {
1211 if(!waypoint_islinked(it, wp))
1212 continue;
1213 cost2 = cost + it.dmg;
1214 navigation_markroutes_checkwaypoint(wp, it, cost2, p);
1215 });
1216 });
1217 }
1218}
#define error
Definition pre.qh:6

References entity(), error, g_waypoints, IL_EACH, NULL, and vector.

Referenced by waypoint_unreachable().

◆ navigation_routerating()

void navigation_routerating ( entity this,
entity e,
float f,
float rangebias )

Definition at line 1221 of file navigation.qc.

1222{
1223 if (!e || e.blacklisted) { return; }
1224
1225 rangebias = waypoint_getlinearcost(rangebias);
1227
1228 if (IS_PLAYER(e))
1229 {
1230 bool rate_wps = false;
1231 if (e.watertype < CONTENT_WATER || (e.waterlevel > WATERLEVEL_WETFEET && !STAT(FROZEN, e))
1232 || (e.flags & FL_PARTIALGROUND))
1233 {
1234 rate_wps = true;
1235 }
1236
1237 if(!IS_ONGROUND(e))
1238 {
1239 traceline(e.origin, e.origin + '0 0 -1500', true, NULL);
1240 int t = pointcontents(trace_endpos + '0 0 1');
1241 if(t != CONTENT_SOLID )
1242 {
1243 if(t == CONTENT_WATER || t == CONTENT_SLIME || t == CONTENT_LAVA)
1244 rate_wps = true;
1245 else if(tracebox_hits_trigger_hurt(e.origin, e.mins, e.maxs, trace_endpos))
1246 return;
1247 }
1248 }
1249
1250 if(rate_wps)
1251 {
1252 entity theEnemy = e;
1253 entity best_wp = NULL;
1254 float best_dist = FLOAT_MAX;
1256 && vdist(it.origin - theEnemy.origin, <, 500)
1257 && vdist(it.origin - this.origin, >, 100)
1258 && vdist(it.origin - this.origin, <, 10000),
1259 {
1260 float dist = vlen2(it.origin - theEnemy.origin);
1261 if (dist < best_dist)
1262 {
1263 best_wp = it;
1264 best_dist = dist;
1265 }
1266 });
1267 if (!best_wp)
1268 return;
1269 e = best_wp;
1270 }
1271 }
1272
1273 vector goal_org = (e.absmin + e.absmax) * 0.5;
1274
1275 //print("routerating ", etos(e), " = ", ftos(f), " - ", ftos(rangebias), "\n");
1276
1277 // Evaluate path using jetpack
1278 if(this.items & IT_JETPACK)
1281 {
1282 vector pointa, pointb;
1283
1284 LOG_DEBUG("jetpack ai: evaluating path for ", e.classname);
1285
1286 // Point A
1287 traceline(this.origin, this.origin + '0 0 65535', MOVE_NORMAL, this);
1288 pointa = trace_endpos - '0 0 1';
1289
1290 // Point B
1291 traceline(goal_org, goal_org + '0 0 65535', MOVE_NORMAL, e);
1292 pointb = trace_endpos - '0 0 1';
1293
1294 // Can I see these two points from the sky?
1295 traceline(pointa, pointb, MOVE_NORMAL, this);
1296
1297 if(trace_fraction==1)
1298 {
1299 LOG_DEBUG("jetpack ai: can bridge these two points");
1300
1301 // Lower the altitude of these points as much as possible
1302 float zdistance, xydistance, cost, t, fuel;
1303 vector down, npa, npb;
1304
1305 down = '0 0 -1' * (STAT(PL_MAX, this).z - STAT(PL_MIN, this).z) * 10;
1306
1307 do{
1308 npa = pointa + down;
1309 npb = pointb + down;
1310
1311 if(npa.z<=this.absmax.z)
1312 break;
1313
1314 if(npb.z<=e.absmax.z)
1315 break;
1316
1317 traceline(npa, npb, MOVE_NORMAL, this);
1318 if(trace_fraction==1)
1319 {
1320 pointa = npa;
1321 pointb = npb;
1322 }
1323 }
1324 while(trace_fraction == 1);
1325
1326
1327 // Rough estimation of fuel consumption
1328 // (ignores acceleration and current xyz velocity)
1329 xydistance = vlen(pointa - pointb);
1330 zdistance = fabs(pointa.z - this.origin.z);
1331
1332 t = zdistance / autocvar_g_jetpack_maxspeed_up;
1333 t += xydistance / autocvar_g_jetpack_maxspeed_side;
1334 fuel = t * autocvar_g_jetpack_fuel * 0.8;
1335
1336 LOG_DEBUG("jetpack ai: required fuel ", ftos(fuel), ", have ", ftos(GetResource(this, RES_FUEL)));
1337
1338 // enough fuel ?
1339 if(GetResource(this, RES_FUEL) > fuel || (this.items & IT_UNLIMITED_AMMO))
1340 {
1341 // Estimate cost
1342 // (as onground costs calculation is mostly based on distances, here we do the same establishing some relationship
1343 // - between air and ground speeds)
1344
1347 cost *= 1.5;
1348
1349 // Compare against other goals
1350 f = f * rangebias / (rangebias + cost);
1351
1352 if (navigation_bestrating < f)
1353 {
1354 LOG_DEBUG("jetpack path: added goal ", e.classname, " (with rating ", ftos(f), ")");
1357 this.navigation_jetpack_goal = e;
1358 this.navigation_jetpack_point = pointb;
1359 }
1360 return;
1361 }
1362 }
1363 }
1364
1365 entity nwp;
1366 //te_wizspike(e.origin);
1367 //bprint(etos(e));
1368 //bprint("\n");
1369 // update the cached spawnfunc_waypoint link on a dynamic item entity
1370 if(e.classname == "waypoint" && !(e.wpflags & WAYPOINTFLAG_PERSONAL))
1371 {
1372 nwp = e;
1373 }
1374 else
1375 {
1376 if(waypointeditor_enabled && e.nearestwaypointtimeout >= 0 && time > e.nearestwaypointtimeout)
1377 e.nearestwaypoint = NULL;
1378
1379 if ((!e.nearestwaypoint || e.navigation_dynamicgoal)
1380 && e.nearestwaypointtimeout >= 0 && time > e.nearestwaypointtimeout)
1381 {
1382 if(IS_BOT_CLIENT(e) && e.goalcurrent && e.goalcurrent.classname == "waypoint")
1383 e.nearestwaypoint = nwp = e.goalcurrent;
1384 else
1385 e.nearestwaypoint = nwp = navigation_findnearestwaypoint(e, true);
1386 if(!nwp)
1387 {
1388 LOG_DEBUG("FAILED to find a nearest waypoint to '", e.classname, "' #", etos(e));
1389
1390 if(!e.navigation_dynamicgoal)
1391 e.blacklisted = true;
1392
1393 if(e.blacklisted)
1394 {
1395 LOG_DEBUG("The entity '", e.classname, "' is going to be excluded from path finding during this match");
1396 return;
1397 }
1398 }
1399
1400 if(e.navigation_dynamicgoal)
1401 e.nearestwaypointtimeout = time + 2;
1402 else if(waypointeditor_enabled)
1403 e.nearestwaypointtimeout = time + 3 + random() * 2;
1404 }
1405 nwp = e.nearestwaypoint;
1406 }
1407
1408 if (nwp && nwp.wpcost < 10000000)
1409 {
1410 //te_wizspike(nwp.wpnearestpoint);
1411 float nwptoitem_cost = 0;
1412 if(nwp.wpflags & WAYPOINTFLAG_TELEPORT)
1413 nwptoitem_cost = nwp.wp00mincost;
1414 else
1415 nwptoitem_cost = waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, nwp, e);
1416 float cost = nwp.wpcost + nwptoitem_cost;
1417 LOG_DEBUG("checking ^5", e.classname, "^7 with base rating ^xf04", ftos(f), "^7 and rangebias ^xf40", ftos(rangebias));
1418 f = f * rangebias / (rangebias + cost);
1419 LOG_DEBUG(" ^5", e.classname, "^7 with cost ^6", ftos(cost), "^7 and final rating ^2", ftos(f));
1420 if (navigation_bestrating < f)
1421 {
1422 LOG_DEBUG(" ground path: ^3added goal ^5", e.classname);
1425 }
1426 }
1427}
const int WAYPOINTFLAG_PERSONAL
Definition api.qh:15
const int IT_JETPACK
Definition item.qh:26
const int IT_UNLIMITED_AMMO
Definition item.qh:23
int items
Definition player.qh:227
int autocvar_g_jetpack_fuel
Definition stats.qh:298
float autocvar_g_jetpack_maxspeed_up
Definition stats.qh:300
float autocvar_g_jetpack_maxspeed_side
Definition stats.qh:299
const int FL_PARTIALGROUND
Definition constants.qh:79
const float CONTENT_SOLID
const float CONTENT_WATER
float trace_fraction
const float CONTENT_LAVA
const float CONTENT_SLIME
float autocvar_bot_ai_navigation_jetpack_mindistance
Definition cvars.qh:40
float autocvar_bot_ai_navigation_jetpack
Definition cvars.qh:39
bool tracebox_hits_trigger_hurt(vector start, vector e_min, vector e_max, vector end)
Definition hurt.qc:79
float vlen(vector v)
string ftos(float f)
string etos(entity e)
entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
vector navigation_jetpack_point
Definition navigation.qh:78
float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent)
float waypoint_getlinearcost(float dist)

References CONTENT_LAVA, CONTENT_SLIME, CONTENT_SOLID, CONTENT_WATER, entity(), FL_PARTIALGROUND, FLOAT_MAX, g_waypoints, IL_EACH, IS_ONGROUND, IS_PLAYER, NULL, STAT, trace_endpos, tracebox_hits_trigger_hurt(), vdist, WATERLEVEL_WETFEET, waypoint_getlinearcost(), and WAYPOINTFLAG_TELEPORT.

Referenced by havocbot_goalrating_ctf_droppedflags(), havocbot_goalrating_ctf_enemybase(), havocbot_goalrating_ctf_enemyflag(), havocbot_goalrating_ctf_ourbase(), havocbot_goalrating_ctf_ourstolenflag(), havocbot_goalrating_enemyplayers(), havocbot_goalrating_ft_freeplayers(), havocbot_goalrating_items(), havocbot_goalrating_kh(), havocbot_goalrating_ons_controlpoints_attack(), havocbot_goalrating_ons_generator_attack(), havocbot_moveto_refresh_route(), havocbot_role_cts(), and havocbot_role_race().

◆ set_tracewalk_dest()

void set_tracewalk_dest ( entity ent,
vector org,
bool fix_player_dest )

Definition at line 120 of file navigation.qc.

121{
122 if ((ent.classname != "waypoint") || ent.wpisbox)
123 {
124 vector wm1 = ent.origin + ent.mins;
125 vector wm2 = ent.origin + ent.maxs;
126 if (IS_PLAYER(ent) || IS_MONSTER(ent))
127 {
128 // move destination point out of player bbox otherwise tracebox always fails
129 // (if bot_navigation_ignoreplayers is false)
130 wm1 += vec2(PL_MIN_CONST) + '-1 -1 0';
131 wm2 += vec2(PL_MAX_CONST) + '1 1 0';
132 }
133 // set destination point to x and y coords of ent that are closer to org
134 // z coord is set to ent's min height
135 tracewalk_dest.x = bound(wm1.x, org.x, wm2.x);
136 tracewalk_dest.y = bound(wm1.y, org.y, wm2.y);
137 if ((IS_PLAYER(ent) || IS_MONSTER(ent))
138 && org.x == tracewalk_dest.x && org.y == tracewalk_dest.y && org.z > tracewalk_dest.z)
139 {
140 tracewalk_dest.z = wm2.z - PL_MIN_CONST.z;
142 fix_player_dest = false;
143 }
144 else
145 {
146 tracewalk_dest.z = wm1.z;
147 tracewalk_dest_height = wm2.z - wm1.z;
148 }
149 }
150 else
151 {
152 tracewalk_dest = ent.origin;
154 }
155 if (fix_player_dest && IS_PLAYER(ent) && !IS_ONGROUND(ent))
156 {
157 // snap player to the ground
158 if (org.x == tracewalk_dest.x && org.y == tracewalk_dest.y)
159 {
160 // bot is right under the player
161 tracebox(ent.origin, ent.mins, ent.maxs, ent.origin - '0 0 700', MOVE_NORMAL, ent);
164 }
165 else
166 {
167 tracebox(tracewalk_dest, ent.mins, ent.maxs, tracewalk_dest - '0 0 700', MOVE_NORMAL, ent);
169 {
172 }
173 }
174 }
175}
const vector PL_MIN_CONST
Definition constants.qh:56
const vector PL_MAX_CONST
Definition constants.qh:55
float trace_startsolid
vector tracewalk_dest
Definition navigation.qh:66
float tracewalk_dest_height
Definition navigation.qh:67
#define IS_MONSTER(v)
Definition utils.qh:21

References bound(), entity(), IS_MONSTER, IS_ONGROUND, IS_PLAYER, MOVE_NORMAL, org, PL_MAX_CONST, PL_MIN_CONST, trace_endpos, trace_startsolid, tracewalk_dest, tracewalk_dest_height, vec2, and vector.

Referenced by havocbot_movetogoal(), navigation_routetogoal(), navigation_shortenpath(), and navigation_unstuck().

◆ set_tracewalk_dest_2()

vector set_tracewalk_dest_2 ( entity ent,
vector org )

Definition at line 178 of file navigation.qc.

179{
180 vector closer_dest = '0 0 0';
181 if ((ent.classname != "waypoint") || ent.wpisbox)
182 {
183 vector wm1 = ent.origin + ent.mins;
184 vector wm2 = ent.origin + ent.maxs;
185 closer_dest.x = bound(wm1.x, org.x, wm2.x);
186 closer_dest.y = bound(wm1.y, org.y, wm2.y);
187 closer_dest.z = bound(wm1.z, org.z, wm2.z);
188 // set destination point to x and y coords of ent that are closer to org
189 // z coord is set to ent's min height
190 tracewalk_dest.x = closer_dest.x;
191 tracewalk_dest.y = closer_dest.y;
192 tracewalk_dest.z = wm1.z;
193 tracewalk_dest_height = wm2.z - wm1.z; // destination height
194 }
195 else
196 {
197 closer_dest = ent.origin;
198 tracewalk_dest = closer_dest;
200 }
201 return closer_dest;
202}

References bound(), entity(), org, tracewalk_dest, tracewalk_dest_height, and vector.

Referenced by waypoint_think().

◆ STATIC_INIT()

STATIC_INIT ( botapi )

Definition at line 151 of file api.qh.

152{
156}
IntrusiveList g_bot_targets
Definition api.qh:149
IntrusiveList g_bot_dodge
Definition api.qh:150
#define IL_NEW()

References g_bot_dodge, g_bot_targets, g_waypoints, and IL_NEW.

◆ tracewalk()

bool tracewalk ( entity e,
vector start,
vector m1,
vector m2,
vector end,
float end_height,
float movemode )

Definition at line 274 of file navigation.qc.

275{
277 {
279 debugnode(e, start);
280 }
281
282 vector org = start;
283 vector flatdir = end - start;
284 flatdir.z = 0;
285 float flatdist = vlen(flatdir);
286 flatdir = normalize(flatdir);
287 float stepdist = 32;
288 bool ignorehazards = false;
289 int nav_action;
290
291 // Analyze starting point
292 if (IN_LAVA(start))
293 ignorehazards = true;
294
295 tracebox(start, m1, m2, start, MOVE_NOMONSTERS, e);
297 {
298 // Bad start
301
302 //print("tracewalk: ", vtos(start), " is a bad start\n");
303 return false;
304 }
305
306 vector end2 = end;
307 if(end_height)
308 end2.z += end_height;
309
310 vector fixed_end = end;
311 vector move;
312
313 if (flatdist > 0 && WETFEET(org))
314 {
315 if (SUBMERGED(org))
316 nav_action = NAV_SWIM_UNDERWATER;
317 else
318 {
319 // tracebox down by player's height
320 // useful to know if water level is so low that bot can still walk
321 tracebox(org, m1, m2, org - eZ * (m2.z - m1.z), movemode, e);
323 {
325 nav_action = NAV_SWIM_UNDERWATER;
326 }
327 else
328 nav_action = NAV_WALK;
329 }
330 }
331 else
332 nav_action = NAV_WALK;
333
334 // Movement loop
335 while (true)
336 {
337 if (flatdist <= 0)
338 {
339 bool success = true;
340 if (org.z > end2.z + 1)
341 {
342 tracebox(org, m1, m2, end2, movemode, e);
344 if (org.z > end2.z + 1)
345 success = false;
346 }
347 else if (org.z < end.z - 1)
348 {
349 tracebox(org, m1, m2, org - jumpheight_vec, movemode, e);
351 {
353 tracebox(v, m1, m2, end, movemode, e);
354 if(trace_endpos.z >= end.z - 1)
355 {
357 trace_endpos = v;
358 }
359 }
360 else if (trace_endpos.z > org.z - jumpheight_vec.z)
361 tracebox(trace_endpos, m1, m2, trace_endpos + jumpheight_vec, movemode, e);
363 if (org.z < end.z - 1)
364 success = false;
365 }
366
367 if (success)
368 {
369 // Succeeded
371 {
372 debugnode(e, org);
374 }
375
376 //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
377 return true;
378 }
379 }
380
382 debugnode(e, org);
383
384 if (flatdist <= 0)
385 break;
386
387 if (stepdist > flatdist)
388 stepdist = flatdist;
389 if(nav_action == NAV_SWIM_UNDERWATER || (nav_action == NAV_SWIM_ONWATER && org.z > end2.z))
390 {
391 // can't use movement direction here to calculate move because of
392 // precision errors especially when direction has a high enough z value
393 //water_dir = normalize(water_end - org);
394 //move = org + water_dir * stepdist;
395 fixed_end.z = bound(end.z, org.z, end2.z);
396 if (stepdist == flatdist) {
397 move = fixed_end;
398 flatdist = 0;
399 } else {
400 move = org + (fixed_end - org) * (stepdist / flatdist);
401 flatdist = vlen(vec2(fixed_end - move));
402 }
403 }
404 else // horiz. direction
405 {
406 flatdist -= stepdist;
407 move = org + flatdir * stepdist;
408 }
409
410 if(nav_action == NAV_SWIM_ONWATER)
411 {
412 tracebox(org, m1, m2, move, movemode, e); // swim
413
414 // hit something
415 if (trace_fraction < 1)
416 {
417 // stepswim
418 tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
419
420 if (trace_fraction < 1 || trace_startsolid) // can't jump obstacle out of water
421 {
423 if(navigation_checkladders(e, org, m1, m2, end, end2, movemode))
424 {
426 {
427 debugnode(e, org);
429 }
430
431 //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
432 return true;
433 }
434
437
438 return false;
439 //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
440 }
441
442 //succesful stepswim
443
444 if (flatdist <= 0)
445 {
447 continue;
448 }
449
450 if (org.z <= move.z) // going horiz.
451 {
452 tracebox(trace_endpos, m1, m2, move, movemode, e);
454 nav_action = NAV_WALK;
455 continue;
456 }
457 }
458
459 if (org.z <= move.z) // going horiz.
460 {
462 nav_action = NAV_SWIM_ONWATER;
463 }
464 else // going down
465 {
467 if (SUBMERGED(org))
468 nav_action = NAV_SWIM_UNDERWATER;
469 else
470 nav_action = NAV_SWIM_ONWATER;
471 }
472 }
473 else if(nav_action == NAV_SWIM_UNDERWATER)
474 {
475 if (move.z >= org.z) // swimming upwards or horiz.
476 {
477 tracebox(org, m1, m2, move, movemode, e); // swim
478
479 bool stepswum = false;
480
481 // hit something
482 if (trace_fraction < 1)
483 {
484 // stepswim
485 vector stepswim_move = move + stepheightvec;
486 if (flatdist > 0 && stepswim_move.z > end2.z + stepheightvec.z) // don't allow stepswim to go higher than destination
487 stepswim_move.z = end2.z;
488
489 tracebox(org + stepheightvec, m1, m2, stepswim_move, movemode, e);
490
491 // hit something
493 {
496
497 //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
498 return false;
499 }
500
501 if (trace_fraction < 1)
502 {
503 float org_z_prev = org.z;
504 RESURFACE_LIMITED(org, end2.z);
505 if(org.z == org_z_prev)
506 {
509
510 //print("tracewalk: ", vtos(start), " can't reach ", vtos(end), "\n");
511 return false;
512 }
513 if(SUBMERGED(org))
514 nav_action = NAV_SWIM_UNDERWATER;
515 else
516 nav_action = NAV_SWIM_ONWATER;
517
518 // we didn't advance horiz. in this step, flatdist decrease should be reverted
519 // but we can't do it properly right now... apply this workaround instead
520 if (flatdist <= 0)
521 flatdist = 1;
522
523 continue;
524 }
525
526 //succesful stepswim
527
528 if (flatdist <= 0)
529 {
531 continue;
532 }
533
534 stepswum = true;
535 }
536
537 if (!WETFEET(trace_endpos))
538 {
539 tracebox(trace_endpos, m1, m2, trace_endpos - eZ * (stepdist + (m2.z - m1.z)), movemode, e);
540 // if stepswum we'll land on the obstacle, avoid the SUBMERGED check
541 if (!stepswum && SUBMERGED(trace_endpos))
542 {
545 nav_action = NAV_SWIM_ONWATER;
546 continue;
547 }
548
549 // not submerged
551 nav_action = NAV_WALK;
552 continue;
553 }
554
555 // wetfeet
557 nav_action = NAV_SWIM_UNDERWATER;
558 continue;
559 }
560 else //if (move.z < org.z) // swimming downwards
561 {
562 tracebox(org, m1, m2, move, movemode, e); // swim
563
564 // hit something
565 if (trace_fraction < 1)
566 {
567 // stepswim
568 tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
569
570 // hit something
571 if (trace_fraction < 1 || trace_startsolid) // can't jump obstacle out of water
572 {
575
576 //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
577 return false;
578 }
579
580 //succesful stepswim
581
582 if (flatdist <= 0)
583 {
585 continue;
586 }
587
588 if (trace_endpos.z > org.z && !SUBMERGED(trace_endpos))
589 {
590 // stepswim caused upwards direction
591 tracebox(trace_endpos, m1, m2, trace_endpos - stepheightvec, movemode, e);
593 {
595 nav_action = NAV_WALK;
596 continue;
597 }
598 }
599 }
600
602 nav_action = NAV_SWIM_UNDERWATER;
603 continue;
604 }
605 }
606 else if(nav_action == NAV_WALK)
607 {
608 // walk
609 tracebox(org, m1, m2, move, movemode, e);
610
613
614 // hit something
615 if (trace_fraction < 1)
616 {
617 // check if we can walk over this obstacle, possibly by jumpstepping
618 tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
620 {
621 if (trace_startsolid) // hit ceiling above org
622 {
623 // reduce stepwalk height
624 tracebox(org, m1, m2, org + stepheightvec, movemode, e);
625 tracebox(trace_endpos, m1, m2, move + eZ * (trace_endpos.z - move.z), movemode, e);
626 }
627 else //if (trace_fraction < 1)
628 {
629 tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e);
630 if (trace_startsolid) // hit ceiling above org
631 {
632 // reduce jumpstepwalk height
633 tracebox(org, m1, m2, org + jumpstepheightvec, movemode, e);
634 tracebox(trace_endpos, m1, m2, move + eZ * (trace_endpos.z - move.z), movemode, e);
635 }
636 }
637
638 if (trace_fraction < 1)
639 {
641 v.z = org.z + jumpheight_vec.z;
642 if(navigation_checkladders(e, v, m1, m2, end, end2, movemode))
643 {
645 {
646 debugnode(e, v);
648 }
649
650 //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
651 return true;
652 }
653
656
657 traceline( org, move, movemode, e);
658
659 if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
660 {
661 vector nextmove;
662 move = trace_endpos;
663 while(trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
664 {
665 nextmove = move + (flatdir * stepdist);
666 traceline( move, nextmove, movemode, e);
667 move = nextmove;
668 }
669 flatdist = vlen(vec2(end - move));
670 }
671 else
672 {
675
676 //print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
677 //te_explosion(trace_endpos);
678 //print(ftos(e.dphitcontentsmask), "\n");
679 return false; // failed
680 }
681 }
682 else
683 move = trace_endpos;
684 }
685 else
686 move = trace_endpos;
687 }
688 else
689 move = trace_endpos;
690
691 // trace down from stepheight as far as possible and move there,
692 // if this starts in solid we try again without the stepup, and
693 // if that also fails we assume it is a wall
694 // (this is the same logic as the Quake walkmove function used)
695 tracebox(move, m1, m2, move + '0 0 -65536', movemode, e);
696
698
699 if (!ignorehazards)
700 {
701 if (IN_LAVA(org))
702 {
704 {
707 }
708
709 //print("tracewalk: ", vtos(start), " hits a hazard when trying to reach ", vtos(end), "\n");
710 return false;
711 }
712 }
713
714 if (flatdist <= 0)
715 {
716 if(move.z >= end2.z && org.z < end2.z)
717 org.z = end2.z;
718 continue;
719 }
720
721 if(org.z > move.z - 1 || !SUBMERGED(org))
722 {
723 nav_action = NAV_WALK;
724 continue;
725 }
726
727 // ended up submerged while walking
729 debugnode(e, org);
730
731 RESURFACE_LIMITED(org, move.z);
732 nav_action = NAV_SWIM_ONWATER;
733 continue;
734 }
735 }
736
737 //print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n");
738
739 // moved but didn't arrive at the intended destination
742
743 return false;
744}
#define WETFEET(pos)
Definition bot.qh:87
#define SUBMERGED(pos)
Definition bot.qh:86
entity trace_ent
bool autocvar_bot_debug_tracewalk
Definition cvars.qh:55
vector normalize(vector v)
#define NAV_SWIM_ONWATER
void debugnodestatus(vector position, float status)
bool navigation_checkladders(entity e, vector org, vector m1, vector m2, vector end, vector end2, int movemode)
void debugnode(entity this, vector node)
#define NAV_SWIM_UNDERWATER
#define NAV_WALK
#define RESURFACE_LIMITED(org, lim)
void debugresetnodes()
const float DEBUG_NODE_SUCCESS
Definition navigation.qh:80
const float DEBUG_NODE_WARNING
Definition navigation.qh:81
vector jumpstepheightvec
Definition navigation.qh:10
vector stepheightvec
Definition navigation.qh:11
vector jumpheight_vec
Definition navigation.qh:12
const float DEBUG_NODE_FAIL
Definition navigation.qh:82
const vector eZ
Definition vector.qh:46

References autocvar_bot_debug_tracewalk, bound(), DEBUG_NODE_FAIL, DEBUG_NODE_SUCCESS, DEBUG_NODE_WARNING, debugnode(), debugnodestatus(), debugresetnodes(), entity(), eZ, IN_LAVA, jumpheight_vec, jumpstepheightvec, MOVE_NOMONSTERS, NAV_SWIM_ONWATER, NAV_SWIM_UNDERWATER, NAV_WALK, navigation_checkladders(), normalize(), org, RESURFACE_LIMITED, stepheightvec, SUBMERGED, trace_endpos, trace_ent, trace_fraction, trace_startsolid, vec2, vector, vlen(), and WETFEET.

Referenced by GameCommand_trace(), havocbot_movetogoal(), navigation_routetogoal(), and waypoint_think().

◆ void()

void ( entity this)

References entity().

◆ waypoint_getSymmetricalAxis_cmd()

void waypoint_getSymmetricalAxis_cmd ( entity caller,
bool save,
int arg_idx )

Definition at line 137 of file waypoints.qc.

138{
139 vector v1 = stov(argv(arg_idx++));
140 vector v2 = stov(argv(arg_idx++));
141 vector mid = (v1 + v2) * 0.5;
142
143 float diffy = (v2.y - v1.y);
144 float diffx = (v2.x - v1.x);
145 if (v1.y == v2.y)
146 diffy = 0.000001;
147 if (v1.x == v2.x)
148 diffx = 0.000001;
149 float m = - diffx / diffy;
150 float q = - m * mid.x + mid.y;
151 if (fabs(m) <= 0.000001) m = 0;
152 if (fabs(q) <= 0.000001) q = 0;
153
154 string axis_str = strcat(ftos(m), " ", ftos(q));
155 if (save)
156 cvar_set("g_waypointeditor_symmetrical_axis", axis_str);
157 axis_str = strcat("\"", axis_str, "\"");
158 sprint(caller, strcat("Axis of symmetry based on input points: ", axis_str, "\n"));
159 if (save)
160 sprint(caller, sprintf(" ^3saved to %s\n", "g_waypointeditor_symmetrical_axis"));
161 if (save)
162 {
163 cvar_set("g_waypointeditor_symmetrical", "-2");
164 sprint(caller, strcat("g_waypointeditor_symmetrical", " has been set to ",
165 cvar_string("g_waypointeditor_symmetrical"), "\n"));
166 }
167}
void cvar_set(string name, string value)
void sprint(float clientnum, string text,...)
vector stov(string s)
const string cvar_string(string name)
string argv(float n)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))

References argv(), cvar_set(), cvar_string(), entity(), fabs(), ftos(), sprint(), stov(), strcat(), and vector.

Referenced by ClientCommand_wpeditor().

◆ waypoint_getSymmetricalOrigin_cmd()

void waypoint_getSymmetricalOrigin_cmd ( entity caller,
bool save,
int arg_idx )

Definition at line 169 of file waypoints.qc.

170{
171 vector org = '0 0 0';
172 int ctf_flags = 0;
173 for (int i = 0; i < 6; ++i)
174 {
175 if (argv(arg_idx + i) != "")
176 ctf_flags++;
177 }
178 if (ctf_flags < 2)
179 {
180 ctf_flags = 0;
182 if (argv(arg_idx) != "")
183 sprint(caller, "WARNING: Ignoring single input point\n");
185 {
186 sprint(caller, "Origin of symmetry can't be automatically determined\n");
187 return;
188 }
189 }
190 else
191 {
192 vector v1, v2, v3, v4, v5, v6;
193 // TODO: Consider inlining this away after https://github.com/graphitemaster/gmqcc/issues/210.
194 float r_ctf_flags = 1 / ctf_flags;
195 for (int i = 1; i <= ctf_flags; ++i)
196 {
197 if (i == 1) { v1 = stov(argv(arg_idx++)); org = v1 * r_ctf_flags; }
198 else if (i == 2) { v2 = stov(argv(arg_idx++)); org += v2 * r_ctf_flags; }
199 else if (i == 3) { v3 = stov(argv(arg_idx++)); org += v3 * r_ctf_flags; }
200 else if (i == 4) { v4 = stov(argv(arg_idx++)); org += v4 * r_ctf_flags; }
201 else if (i == 5) { v5 = stov(argv(arg_idx++)); org += v5 * r_ctf_flags; }
202 else if (i == 6) { v6 = stov(argv(arg_idx++)); org += v6 * r_ctf_flags; }
203 }
204 }
205
206 if (fabs(org.x) <= 0.000001) org.x = 0;
207 if (fabs(org.y) <= 0.000001) org.y = 0;
208 string org_str = strcat(ftos(org.x), " ", ftos(org.y));
209 if (save)
210 {
211 cvar_set("g_waypointeditor_symmetrical_origin", org_str);
212 cvar_set("g_waypointeditor_symmetrical_order", ftos(ctf_flags));
213 }
214 org_str = strcat("\"", org_str, "\"");
215
216 if (ctf_flags < 2)
217 sprint(caller, strcat("Origin of symmetry based on flag positions: ", org_str, "\n"));
218 else
219 sprint(caller, strcat("Origin of symmetry based on input points: ", org_str, "\n"));
220 if (save)
221 sprint(caller, sprintf(" ^3saved to %s\n", "g_waypointeditor_symmetrical_origin"));
222
223 if (ctf_flags < 2)
224 sprint(caller, "Order of symmetry: 0 (autodetected)\n");
225 else
226 sprint(caller, strcat("Order of symmetry: ", ftos(ctf_flags), "\n"));
227 if (save)
228 sprint(caller, sprintf(" ^3saved to %s\n", "g_waypointeditor_symmetrical_order"));
229
230 if (save)
231 {
232 if (ctf_flags < 2)
233 cvar_set("g_waypointeditor_symmetrical", "0");
234 else
235 cvar_set("g_waypointeditor_symmetrical", "-1");
236 sprint(caller, strcat("g_waypointeditor_symmetrical", " has been set to ",
237 cvar_string("g_waypointeditor_symmetrical"), "\n"));
238 }
239}
vector havocbot_middlepoint
Definition api.qh:91
float havocbot_middlepoint_radius
Definition api.qh:92

References argv(), cvar_set(), cvar_string(), entity(), fabs(), ftos(), havocbot_middlepoint, havocbot_middlepoint_radius, org, sprint(), stov(), strcat(), vec2, and vector.

Referenced by ClientCommand_wpeditor().

◆ waypoint_lock()

void waypoint_lock ( entity pl)

Definition at line 270 of file waypoints.qc.

271{
273 pl.wp_locked = trace_ent;
274}
void crosshair_trace_waypoints(entity pl)

References crosshair_trace_waypoints(), entity(), and trace_ent.

Referenced by ClientCommand_wpeditor().

◆ waypoint_remove()

void waypoint_remove ( entity wp)

Definition at line 819 of file waypoints.qc.

820{
821 IL_EACH(g_waypoints, it != wp,
822 {
823 if (it.SUPPORT_WP == wp)
824 {
825 it.SUPPORT_WP = NULL;
826 waypoint_schedulerelink(it); // restore incoming links
827 }
828 if (waypoint_islinked(it, wp))
829 {
830 if (waypoint_is_hardwiredlink(it, wp))
832 waypoint_removelink(it, wp);
833 }
834 });
835 delete(wp);
836}
void waypoint_unmark_hardwiredlink(entity wp_from, entity wp_to)
Definition waypoints.qc:318
bool waypoint_is_hardwiredlink(entity wp_from, entity wp_to)
Definition waypoints.qc:283
bool waypoint_islinked(entity from, entity to)
Definition waypoints.qc:966
void waypoint_schedulerelink(entity wp)
void waypoint_removelink(entity from, entity to)
Definition waypoints.qc:905

References entity(), g_waypoints, IL_EACH, NULL, waypoint_is_hardwiredlink(), waypoint_islinked(), waypoint_removelink(), waypoint_schedulerelink(), and waypoint_unmark_hardwiredlink().

Referenced by havocbot_moveto().

◆ waypoint_remove_fromeditor()

void waypoint_remove_fromeditor ( entity pl)

Definition at line 838 of file waypoints.qc.

839{
841 {
842 LOG_INFOF("^1Editing waypoints with a higher version number (%f) is not allowed.\n"
843 "Update Xonotic to make them editable.", waypoint_version_loaded);
844 return;
845 }
846
848
849 int ctf_flags = havocbot_symmetry_origin_order;
850 bool sym = ((autocvar_g_waypointeditor_symmetrical > 0 && ctf_flags >= 2)
854 if (sym && ctf_flags < 2)
855 ctf_flags = 2;
856 int wp_num = ctf_flags;
857
858 LABEL(remove_wp);
859 if (!e) return;
860
861 if (e.wpflags & WAYPOINTFLAG_GENERATED)
862 {
865 return;
866 }
867
869 {
870 LOG_INFO("Can't remove a waypoint with hardwired links, remove links with \"wpeditor hardwire\" first\n");
871 return;
872 }
873
874 entity wp_sym = NULL;
875 if (sym)
876 {
877 vector org = waypoint_getSymmetricalPoint(e.origin, ctf_flags);
878 FOREACH_ENTITY_CLASS("waypoint", !(it.wpflags & WAYPOINTFLAG_GENERATED), {
879 if(vdist(org - it.origin, <, 3))
880 {
881 wp_sym = it;
882 break;
883 }
884 });
885 }
886
887 bprint(strcat("Waypoint removed at ", vtos(e.origin), "\n"));
888 te_explosion(e.origin);
890
891 if (sym && wp_sym)
892 {
893 e = wp_sym;
894 if(wp_num > 2)
895 wp_num--;
896 else
897 sym = false;
898 goto remove_wp;
899 }
900
903}
entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
float havocbot_symmetry_origin_order
Definition api.qh:95
const int WAYPOINTFLAG_GENERATED
Definition api.qh:11
#define LABEL(id)
Definition compiler.qh:34
#define FOREACH_ENTITY_CLASS(class, cond, body)
Definition iter.qh:189
#define LOG_INFO(...)
Definition log.qh:65
#define LOG_INFOF(...)
Definition log.qh:66
string vtos(vector v)
bool waypoint_has_hardwiredlinks(entity wp)
Definition waypoints.qc:276
vector waypoint_getSymmetricalPoint(vector org, int ctf_flags)
Definition waypoints.qc:241
void waypoint_clear_start_wp_globals(entity pl, bool warn)
Definition waypoints.qc:521
bool start_wp_is_spawned
Definition waypoints.qc:516
void waypoint_remove(entity wp)
Definition waypoints.qc:819
float waypoint_version_loaded
Definition waypoints.qh:16
const float WAYPOINT_VERSION
Definition waypoints.qh:15
bool autocvar_g_waypointeditor_symmetrical
Definition waypoints.qh:6
int autocvar_g_waypointeditor_symmetrical_order
Definition waypoints.qh:9

References autocvar_g_waypointeditor_symmetrical, autocvar_g_waypointeditor_symmetrical_order, entity(), FOREACH_ENTITY_CLASS, havocbot_symmetry_origin_order, LABEL, LOG_INFO, LOG_INFOF, navigation_findnearestwaypoint(), NULL, org, start_wp_is_spawned, vector, waypoint_clear_start_wp_globals(), waypoint_getSymmetricalPoint(), waypoint_has_hardwiredlinks(), WAYPOINT_VERSION, waypoint_version_loaded, and WAYPOINTFLAG_GENERATED.

Referenced by ClientCommand_wpeditor().

◆ waypoint_saveall()

void waypoint_saveall ( )

Definition at line 1755 of file waypoints.qc.

1756{
1758 {
1759 LOG_INFOF("^1Overwriting waypoints with a higher version number (%f) is not allowed.\n"
1760 "Update Xonotic to make them editable.", waypoint_version_loaded);
1761 return;
1762 }
1763 string gt_ext = GET_GAMETYPE_EXTENSION();
1764
1765 string filename = sprintf("maps/%s.waypoints", strcat(mapname, gt_ext));
1766 int file = fopen(filename, FILE_WRITE);
1767 if (file < 0)
1768 {
1769 waypoint_save_links(); // save anyway?
1771
1772 LOG_INFOF("waypoint links: save to %s failed", filename);
1773 return;
1774 }
1775
1777 string sym_str = ftos(sym);
1778 if (sym == -1 || (sym == 1 && autocvar_g_waypointeditor_symmetrical_order >= 2))
1779 {
1780 if (sym == 1)
1781 {
1782 sym_str = cons(sym_str, "-");
1783 sym_str = cons(sym_str, "-");
1784 }
1785 else
1786 {
1789 }
1792 }
1794 {
1797 }
1798
1799 // a group of 3 comments doesn't break compatibility with older Xonotic versions
1800 // (they are read as a waypoint with origin '0 0 0' and flag 0 though)
1801 fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n"));
1802 fputs(file, strcat("//", "WAYPOINT_SYMMETRY ", sym_str, "\n"));
1803
1804 strcpy(waypoint_time, strftime(true, "%Y-%m-%d %H:%M:%S"));
1805 fputs(file, strcat("//", "WAYPOINT_TIME ", waypoint_time, "\n"));
1806 //fputs(file, strcat("//", "\n"));
1807 //fputs(file, strcat("//", "\n"));
1808 //fputs(file, strcat("//", "\n"));
1809
1810 int c = 0;
1811 IL_EACH(g_waypoints, true,
1812 {
1813 if(it.wpflags & WAYPOINTFLAG_GENERATED)
1814 continue;
1815
1816 string s;
1817 // NOTE: vtos rounds vector components to 1 decimal place
1818 s = strcat(vtos(it.origin + it.mins), "\n");
1819 s = strcat(s, vtos(it.origin + it.maxs));
1820 s = strcat(s, "\n");
1821 s = strcat(s, ftos(it.wpflags));
1822 s = strcat(s, "\n");
1823 fputs(file, s);
1824 c++;
1825 });
1826 fclose(file);
1829
1831
1833 LOG_INFOF("saved %d waypoints to %s", c, filename);
1834}
string mapname
const float FILE_WRITE
void fclose(float fhandle)
void fputs(float fhandle, string s)
float fopen(string filename, float mode)
ERASEABLE string ftos_decimals(float number, int decimals)
converts a number to a string with the indicated number of decimals
Definition string.qh:469
#define strcpy(this, s)
Definition string.qh:52
ERASEABLE string cons(string a, string b)
Definition string.qh:276
#define GET_GAMETYPE_EXTENSION()
void waypoint_save_hardwiredlinks()
void waypoint_save_links()
vector autocvar_g_waypointeditor_symmetrical_axis
Definition waypoints.qh:10
vector autocvar_g_waypointeditor_symmetrical_origin
Definition waypoints.qh:8
string waypoint_time
Definition waypoints.qh:17

References autocvar_g_waypointeditor_symmetrical, autocvar_g_waypointeditor_symmetrical_axis, autocvar_g_waypointeditor_symmetrical_order, autocvar_g_waypointeditor_symmetrical_origin, botframe_loadedforcedlinks, cons(), fclose(), FILE_WRITE, fopen(), fputs(), ftos(), ftos_decimals(), g_waypoints, GET_GAMETYPE_EXTENSION, IL_EACH, LOG_INFOF, mapname, strcat(), strcpy, vtos(), waypoint_save_hardwiredlinks(), waypoint_save_links(), waypoint_time, WAYPOINT_VERSION, waypoint_version_loaded, and WAYPOINTFLAG_GENERATED.

Referenced by ClientCommand_wpeditor().

◆ waypoint_schedulerelink()

void waypoint_schedulerelink ( entity wp)

Definition at line 1273 of file waypoints.qc.

1274{
1275 if (wp == NULL)
1276 return;
1277
1279 wp.wpisbox = vdist(wp.size, >, 0);
1280 wp.enemy = NULL;
1281 if (!(wp.wpflags & WAYPOINTFLAG_PERSONAL))
1282 wp.owner = NULL;
1283 if (!(wp.wpflags & WPFLAGMASK_NORELINK))
1285 // schedule an actual relink on next frame
1287 wp.nextthink = time;
1288 wp.effects = EF_LOWPRECISION;
1289}
const int WPFLAGMASK_NORELINK
Definition api.qh:29
float EF_LOWPRECISION
#define setthink(e, f)
void waypoint_clearlinks(entity wp)
void waypoint_think(entity this)
void waypoint_setupmodel(entity wp)
Definition waypoints.qc:362

References EF_LOWPRECISION, entity(), NULL, setthink, time, vdist, waypoint_clearlinks(), waypoint_setupmodel(), waypoint_think(), WAYPOINTFLAG_PERSONAL, and WPFLAGMASK_NORELINK.

◆ waypoint_schedulerelinkall()

void waypoint_schedulerelinkall ( )

Definition at line 1304 of file waypoints.qc.

1305{
1307 IL_EACH(g_waypoints, true,
1308 {
1310 });
1312}
float relink_total
Definition waypoints.qh:20
float relink_lengthculled
Definition waypoints.qh:20
float relink_walkculled
Definition waypoints.qh:20
float relink_pvsculled
Definition waypoints.qh:20

References g_waypoints, IL_EACH, relink_lengthculled, relink_pvsculled, relink_total, relink_walkculled, waypoint_load_hardwiredlinks(), and waypoint_schedulerelink().

Referenced by ClientCommand_wpeditor().

◆ waypoint_spawn()

entity waypoint_spawn ( vector m1,
vector m2,
float f )

Definition at line 433 of file waypoints.qc.

434{
435 if(!(f & (WAYPOINTFLAG_PERSONAL | WAYPOINTFLAG_GENERATED)) && m1 == m2)
436 {
437 entity wp_found = waypoint_get(m1, m2);
438 if (wp_found)
439 return wp_found;
440 }
441 // spawn only one destination waypoint for teleports teleporting player to the exact same spot
442 // otherwise links loaded from file would be applied only to the first destination
443 // waypoint since link format doesn't specify waypoint entities but just positions
444 if((f & WAYPOINTFLAG_GENERATED) && !(f & (WPFLAGMASK_NORELINK | WAYPOINTFLAG_PERSONAL)) && m1 == m2)
445 {
446 IL_EACH(g_waypoints, boxesoverlap(m1, m2, it.absmin, it.absmax),
447 {
448 return it;
449 });
450 }
451
452 entity w = new(waypoint);
455 w.wpflags = f;
456 w.solid = SOLID_TRIGGER;
457 w.createdtime = time;
458 setorigin(w, (m1 + m2) * 0.5);
459 setsize(w, m1 - w.origin, m2 - w.origin);
460 if (w.size)
461 w.wpisbox = true;
462
463 if(!w.wpisbox)
464 {
465 if (f & WAYPOINTFLAG_CROUCH)
466 setsize(w, PL_CROUCH_MIN_CONST - '1 1 0', PL_CROUCH_MAX_CONST + '1 1 0');
467 else
468 setsize(w, PL_MIN_CONST - '1 1 0', PL_MAX_CONST + '1 1 0');
469 if(!move_out_of_solid(w))
470 {
471 if(!(f & WAYPOINTFLAG_GENERATED))
472 {
473 LOG_TRACE("Killed a waypoint that was stuck in solid at ", vtos(w.origin));
474 delete(w);
475 return NULL;
476 }
477 else
478 {
479 if(autocvar_developer > 0)
480 {
481 LOG_INFO("A generated waypoint is stuck in solid at ", vtos(w.origin));
482 backtrace("Waypoint stuck");
483 }
484 }
485 }
486 setsize(w, '0 0 0', '0 0 0');
487 }
488
490 //waypoint_schedulerelink(w);
491
493
494 return w;
495}
const int WAYPOINTFLAG_CROUCH
Definition api.qh:22
const vector PL_CROUCH_MIN_CONST
Definition constants.qh:58
const vector PL_CROUCH_MAX_CONST
Definition constants.qh:57
float DPCONTENTS_BOTCLIP
const float SOLID_TRIGGER
float DPCONTENTS_SOLID
float DPCONTENTS_BODY
float DPCONTENTS_PLAYERCLIP
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define move_out_of_solid(e)
Definition common.qh:110
noref int autocvar_developer
Definition log.qh:96
#define LOG_TRACE(...)
Definition log.qh:76
#define backtrace(msg)
Definition log.qh:99
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
Definition vector.qh:73
entity waypoint_get(vector m1, vector m2)
Definition waypoints.qc:420

References autocvar_developer, backtrace, boxesoverlap(), DPCONTENTS_BODY, DPCONTENTS_BOTCLIP, DPCONTENTS_PLAYERCLIP, DPCONTENTS_SOLID, entity(), g_waypoints, IL_EACH, IL_PUSH(), LOG_INFO, LOG_TRACE, move_out_of_solid, NULL, PL_CROUCH_MAX_CONST, PL_CROUCH_MIN_CONST, PL_MAX_CONST, PL_MIN_CONST, SOLID_TRIGGER, time, vector, vtos(), waypoint_clearlinks(), waypoint_get(), waypoint_setupmodel(), WAYPOINTFLAG_CROUCH, WAYPOINTFLAG_GENERATED, WAYPOINTFLAG_PERSONAL, and WPFLAGMASK_NORELINK.

Referenced by botframe_autowaypoints_createwp().

◆ waypoint_spawn_fromeditor()

void waypoint_spawn_fromeditor ( entity pl,
bool at_crosshair,
bool is_jump_wp,
bool is_crouch_wp,
bool is_support_wp )

Definition at line 568 of file waypoints.qc.

569{
571 {
572 LOG_INFOF("^1Editing waypoints with a higher version number (%f) is not allowed.\n"
573 "Update Xonotic to make them editable.", waypoint_version_loaded);
574 return;
575 }
576
577 entity e = NULL, jp = NULL;
578 vector org = pl.origin;
579 if (at_crosshair)
580 {
583 if (!trace_ent)
584 org.z -= PL_MIN_CONST.z;
586 IL_EACH(g_jumppads, boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax),
587 {
588 jp = it;
589 break;
590 });
591 if (!jp && !start_wp_is_spawned && trace_ent)
592 {
593 if (trace_ent.wpflags & (WAYPOINTFLAG_JUMP))
594 is_jump_wp = true;
595 else if (trace_ent.wpflags & (WAYPOINTFLAG_SUPPORT))
596 is_support_wp = true;
597 }
598 }
599 if (jp || is_jump_wp || is_support_wp)
600 {
602 start_wp_is_spawned = false;
603 LOG_INFO("^xf80Spawning start waypoint...\n");
604 }
605 int ctf_flags = havocbot_symmetry_origin_order;
606 bool sym = ((autocvar_g_waypointeditor_symmetrical > 0 && ctf_flags >= 2)
610 if (sym && ctf_flags < 2)
611 ctf_flags = 2;
612 int wp_num = ctf_flags;
613
614 if(!PHYS_INPUT_BUTTON_CROUCH(pl) && !at_crosshair && !is_jump_wp && !is_support_wp)
615 {
616 // snap waypoint to item's origin if close enough
617 IL_EACH(g_items, true,
618 {
619 vector item_org = (it.absmin + it.absmax) * 0.5;
620 item_org.z = it.absmin.z - PL_MIN_CONST.z;
621 if (vlen(item_org - org) < 20)
622 {
623 org = item_org;
624 break;
625 }
626 });
627 }
628
629 vector start_org = '0 0 0';
631 {
633 LOG_INFO("^xf80Spawning destination waypoint...\n");
634 start_org = start_wp_origin;
635 }
636
637 // save org as it can be modified spawning symmetrycal waypoints
638 vector initial_origin = '0 0 0';
639 bool initial_origin_is_set = false;
640
641 LABEL(add_wp);
642
643 if (jp)
644 {
645 e = NULL;
647 && boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax),
648 {
649 e = it; break;
650 });
651 if (!e)
652 e = waypoint_spawn(jp.absmin - PL_MAX_CONST, jp.absmax - PL_MIN_CONST, WAYPOINTFLAG_TELEPORT);
653 if (!pl.wp_locked)
654 pl.wp_locked = e;
655 }
656 else if (is_jump_wp || is_support_wp)
657 {
658 int type_flag = (is_jump_wp) ? WAYPOINTFLAG_JUMP : WAYPOINTFLAG_SUPPORT;
659
660 entity wp_found = waypoint_get(org, org);
661 if (wp_found && !(wp_found.wpflags & type_flag))
662 {
663 LOG_INFOF("Error: can't spawn a %s waypoint over an existent waypoint of a different type\n", (is_jump_wp) ? "Jump" : "Support");
664 return;
665 }
666 e = waypoint_spawn(org, org, type_flag);
667 if (!pl.wp_locked)
668 pl.wp_locked = e;
669 }
670 else
671 e = waypoint_spawn(org, org, (is_crouch_wp) ? WAYPOINTFLAG_CROUCH : 0);
672 if(!e)
673 {
674 LOG_INFOF("Couldn't spawn waypoint at %v\n", org);
677 return;
678 }
679
680 if (!initial_origin_is_set)
681 {
682 initial_origin = e.origin;
683 initial_origin_is_set = true;
684 }
685
686 entity start_wp = NULL;
688 {
690 && boxesoverlap(start_org, start_org, it.absmin, it.absmax),
691 {
692 start_wp = it; break;
693 });
694 if(!start_wp)
695 {
696 // should not happen
697 LOG_INFOF("Couldn't find start waypoint at %v\n", start_org);
699 return;
700 }
702 {
703 if (waypoint_is_hardwiredlink(start_wp, e))
704 {
706 waypoint_removelink(start_wp, e);
707 string s = strcat(vtos(start_wp.origin), "*", vtos(e.origin));
708 LOG_INFOF("^x80fRemoved hardwired link %s.\n", s);
709 }
710 else
711 {
712 if (e.createdtime == time)
713 {
714 LOG_INFO("Error: hardwired links can be created only between 2 existing (and unconnected) waypoints.\n");
717 waypoint_spawn_fromeditor(pl, at_crosshair, is_jump_wp, is_crouch_wp, is_support_wp);
718 return;
719 }
720 if (start_wp == e)
721 {
722 LOG_INFO("Error: start and destination waypoints coincide.\n");
724 return;
725 }
726 if (waypoint_islinked(start_wp, e))
727 {
728 LOG_INFO("Error: waypoints are already linked.\n");
730 return;
731 }
732 waypoint_addlink(start_wp, e);
733 waypoint_mark_hardwiredlink(start_wp, e);
734 string s = strcat(vtos(start_wp.origin), "*", vtos(e.origin));
735 LOG_INFOF("^x80fAdded hardwired link %s.\n", s);
736 }
737 }
738 else
739 {
741 {
742 if (e.SUPPORT_WP)
743 {
744 LOG_INFOF("Waypoint %v has already a support waypoint, delete it first.\n", e.origin);
746 return;
747 }
748 // clear all links to e
749 IL_EACH(g_waypoints, it != e,
750 {
751 if (waypoint_islinked(it, e) && !waypoint_is_hardwiredlink(it, e))
752 waypoint_removelink(it, e);
753 });
754 }
755 waypoint_addlink(start_wp, e);
756 }
757 }
758
759 if (!(jp || is_jump_wp || is_support_wp || start_wp_is_hardwired))
761
762 string wp_type_str = waypoint_get_type_name(e);
763
764 bprint(strcat(wp_type_str, "^7 spawned at ", vtos(e.origin), "\n"));
765
767 {
768 pl.wp_locked = NULL;
770 waypoint_schedulerelink(start_wp);
771 if (start_wp.wpflags & WAYPOINTFLAG_TELEPORT)
772 {
773 if (start_wp.wp00_original == start_wp.wp00)
774 start_wp.wpflags &= ~WAYPOINTFLAG_CUSTOM_JP;
775 else
776 start_wp.wpflags |= WAYPOINTFLAG_CUSTOM_JP;
777 }
778 }
779
780 if (sym)
781 {
783 if (jp)
784 {
785 IL_EACH(g_jumppads, boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax),
786 {
787 jp = it; break;
788 });
789 }
791 start_org = waypoint_getSymmetricalPoint(start_org, ctf_flags);
792 if (vdist(org - pl.origin, >, 32))
793 {
794 if(wp_num > 2)
795 wp_num--;
796 else
797 sym = false;
798 goto add_wp;
799 }
800 }
801 if (jp || is_jump_wp || is_support_wp)
802 {
804 {
805 // we've just created a custom jumppad waypoint
806 // the next one created by the user will be the destination waypoint
807 start_wp_is_spawned = true;
808 start_wp_origin = initial_origin;
809 if (is_support_wp)
810 start_wp_is_support = true;
811 }
812 }
813 else if (start_wp_is_spawned)
814 {
816 }
817}
const int WAYPOINTFLAG_CUSTOM_JP
Definition api.qh:21
const int WAYPOINTFLAG_SUPPORT
Definition api.qh:23
const int WAYPOINTFLAG_JUMP
Definition api.qh:20
IntrusiveList g_jumppads
Definition jumppads.qh:18
bool start_wp_is_support
Definition waypoints.qc:519
string waypoint_get_type_name(entity wp)
Definition waypoints.qc:397
void waypoint_addlink(entity from, entity to)
bool start_wp_is_hardwired
Definition waypoints.qc:518
entity waypoint_spawn(vector m1, vector m2, float f)
Definition waypoints.qc:433
vector start_wp_origin
Definition waypoints.qc:517
void waypoint_mark_hardwiredlink(entity wp_from, entity wp_to)
Definition waypoints.qc:301
void waypoint_spawn_fromeditor(entity pl, bool at_crosshair, bool is_jump_wp, bool is_crouch_wp, bool is_support_wp)
Definition waypoints.qc:568

References autocvar_g_waypointeditor_symmetrical, autocvar_g_waypointeditor_symmetrical_order, boxesoverlap(), bprint(), crosshair_trace_waypoints(), entity(), g_items, g_jumppads, g_waypoints, havocbot_symmetry_origin_order, IL_EACH, LABEL, LOG_INFO, LOG_INFOF, NULL, org, PHYS_INPUT_BUTTON_CROUCH, PL_MAX_CONST, PL_MIN_CONST, start_wp_is_hardwired, start_wp_is_spawned, start_wp_is_support, start_wp_origin, strcat(), time, trace_endpos, trace_ent, vdist, vector, vlen(), vtos(), waypoint_addlink(), waypoint_clear_start_wp_globals(), waypoint_get(), waypoint_get_type_name(), waypoint_getSymmetricalPoint(), waypoint_is_hardwiredlink(), waypoint_islinked(), waypoint_mark_hardwiredlink(), waypoint_remove(), waypoint_removelink(), waypoint_schedulerelink(), waypoint_spawn(), waypoint_spawn_fromeditor(), waypoint_unmark_hardwiredlink(), WAYPOINT_VERSION, waypoint_version_loaded, WAYPOINTFLAG_CROUCH, WAYPOINTFLAG_CUSTOM_JP, WAYPOINTFLAG_JUMP, WAYPOINTFLAG_SUPPORT, WAYPOINTFLAG_TELEPORT, and WPFLAGMASK_NORELINK.

Referenced by ClientCommand_wpeditor().

◆ waypoint_spawnforitem()

void waypoint_spawnforitem ( entity e)

Definition at line 2002 of file waypoints.qc.

2003{
2005 return;
2006
2007 waypoint_spawnforitem_force(e, e.origin);
2008}
bool bot_waypoints_for_items
Definition api.qh:9
void waypoint_spawnforitem_force(entity e, vector org)

References bot_waypoints_for_items, entity(), and waypoint_spawnforitem_force().

Referenced by dom_controlpoint_setup(), and StartItem().

◆ waypoint_spawnforitem_force()

void waypoint_spawnforitem_force ( entity e,
vector org )

Definition at line 1973 of file waypoints.qc.

1974{
1975 // Fix the waypoint altitude if necessary
1977
1978 // don't spawn an item spawnfunc_waypoint if it already exists
1979 IL_EACH(g_waypoints, true,
1980 {
1981 if(it.wpisbox)
1982 {
1983 if(boxesoverlap(org, org, it.absmin, it.absmax))
1984 {
1985 e.nearestwaypoint = it;
1986 return;
1987 }
1988 }
1989 else
1990 {
1991 if(vdist(it.origin - org, <, 16))
1992 {
1993 e.nearestwaypoint = it;
1994 return;
1995 }
1996 }
1997 });
1998
2000}
const int WAYPOINTFLAG_ITEM
Definition api.qh:12
#define waypoint_fixorigin(position, tracetest_ent)

References boxesoverlap(), entity(), g_waypoints, IL_EACH, NULL, org, vdist, vector, waypoint_fixorigin, waypoint_spawn(), WAYPOINTFLAG_GENERATED, and WAYPOINTFLAG_ITEM.

Referenced by ctf_DelayedFlagSetup(), ons_DelayedGeneratorSetup(), spawnfunc(), and target_checkpoint_setup().

◆ waypoint_spawnforteleporter()

void waypoint_spawnforteleporter ( entity e,
vector destination,
float timetaken,
entity tracetest_ent )

Definition at line 2064 of file waypoints.qc.

2065{
2066 destination = waypoint_fixorigin(destination, tracetest_ent);
2067 waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT, e.absmin - PL_MAX_CONST, e.absmax - PL_MIN_CONST, destination, destination, timetaken);
2068}
void waypoint_spawnforteleporter_boxes(entity e, int teleport_flag, vector org1, vector org2, vector destination1, vector destination2, float timetaken)

References entity(), PL_MAX_CONST, PL_MIN_CONST, vector, waypoint_fixorigin, waypoint_spawnforteleporter_boxes(), and WAYPOINTFLAG_TELEPORT.

Referenced by teleport_findtarget(), and trigger_push_test().

◆ waypoint_spawnforteleporter_wz()

void waypoint_spawnforteleporter_wz ( entity e,
entity tracetest_ent )

Definition at line 2026 of file waypoints.qc.

2027{
2028 float src_angle = e.warpzone_angles.x;
2029 while (src_angle < -180) src_angle += 360;
2030 while (src_angle > 180) src_angle -= 360;
2031
2032 float dest_angle = e.enemy.warpzone_angles.x;
2033 while (dest_angle < -180) dest_angle += 360;
2034 while (dest_angle > 180) dest_angle -= 360;
2035
2036 // no waypoints for warpzones pointing upwards, they can't be used by the bots
2037 if (src_angle == -90 || dest_angle == -90)
2038 return;
2039
2040 makevectors(e.warpzone_angles);
2041 vector src = (e.absmin + e.absmax) * 0.5;
2042 src += ((e.warpzone_origin - src) * v_forward) * v_forward + 16 * v_right;
2043 vector down_dir_src = -v_up;
2044
2045 makevectors(e.enemy.warpzone_angles);
2046 vector dest = (e.enemy.absmin + e.enemy.absmax) * 0.5;
2047 dest += ((e.enemy.warpzone_origin - dest) * v_forward) * v_forward - 16 * v_right;
2048 vector down_dir_dest = -v_up;
2049
2050 int extra_flag = 0;
2051 // don't snap to the ground waypoints for source warpzones pointing downwards
2052 if (src_angle != 90)
2053 {
2054 src = waypoint_fixorigin_down_dir(src, tracetest_ent, down_dir_src);
2055 dest = waypoint_fixorigin_down_dir(dest, tracetest_ent, down_dir_dest);
2056 // oblique warpzones need a jump otherwise bots gets stuck
2057 if (src_angle != 0)
2058 extra_flag = WAYPOINTFLAG_JUMP;
2059 }
2060
2061 waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT | extra_flag, src, src, dest, dest, 0);
2062}
vector v_up
vector v_right
vector v_forward
#define makevectors
Definition post.qh:21
vector waypoint_fixorigin_down_dir(vector position, entity tracetest_ent, vector down_dir)

References dest, entity(), makevectors, v_forward, v_right, v_up, vector, waypoint_fixorigin_down_dir(), waypoint_spawnforteleporter_boxes(), WAYPOINTFLAG_JUMP, and WAYPOINTFLAG_TELEPORT.

Referenced by WarpZone_PostInitialize_Callback().

◆ waypoint_start_hardwiredlink()

void waypoint_start_hardwiredlink ( entity pl,
bool at_crosshair )

Definition at line 532 of file waypoints.qc.

533{
534 entity wp = pl.nearestwaypoint;
535 if (at_crosshair)
536 {
538 wp = trace_ent;
539 }
540 string err = "";
542 err = "can't hardwire while in the process of creating a special link";
543 else if (!wp)
544 {
545 if (at_crosshair)
546 err = "couldn't find any waypoint at crosshair";
547 else
548 err = "couldn't find any waypoint nearby";
549 }
550 else if (wp.wpflags & WPFLAGMASK_NORELINK)
551 err = "can't hardwire a waypoint with special links";
552
553 if (err == "")
554 {
556 start_wp_is_spawned = true;
557 start_wp_origin = wp.origin;
558 pl.wp_locked = wp;
559 LOG_INFOF("^x80fWaypoint %s marked as hardwired link origin.\n", vtos(wp.origin));
560 }
561 else
562 {
563 start_wp_is_hardwired = false;
564 LOG_INFO("Error: ", err, "\n");
565 }
566}
entity err
Definition promise.qc:44

References crosshair_trace_waypoints(), entity(), err, LOG_INFO, LOG_INFOF, start_wp_is_hardwired, start_wp_is_spawned, start_wp_origin, trace_ent, vtos(), and WPFLAGMASK_NORELINK.

Referenced by ClientCommand_wpeditor().

◆ waypoint_unreachable()

void waypoint_unreachable ( entity pl)

Definition at line 28 of file waypoints.qc.

29{
30 IL_EACH(g_waypoints, true,
31 {
32 it.colormod = '0.5 0.5 0.5';
33 it.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
34 });
35
37 if(!e2)
38 {
39 LOG_INFO("Can't find any waypoint nearby\n");
40 return;
41 }
42
44
45 int j = 0;
46 int m = 0;
47 IL_EACH(g_waypoints, it.wpcost >= 10000000,
48 {
49 LOG_INFO("unreachable: ", etos(it), " ", vtos(it.origin), "\n");
50 it.colormod_z = 8;
51 it.effects |= EF_NODEPTHTEST | EF_BLUE;
52 j++;
53 m++;
54 });
55 if (j) LOG_INFOF("%d waypoints cannot be reached from here in any way (marked with blue light)\n", j);
57
58 j = 0;
59 IL_EACH(g_waypoints, it.wpcost >= 10000000,
60 {
61 LOG_INFO("cannot reach me: ", etos(it), " ", vtos(it.origin), "\n");
62 it.colormod_x = 8;
63 if (!(it.effects & EF_NODEPTHTEST)) // not already reported before
64 m++;
65 it.effects |= EF_NODEPTHTEST | EF_RED;
66 j++;
67 });
68 if (j) LOG_INFOF("%d waypoints cannot walk to here in any way (marked with red light)\n", j);
69 if (m) LOG_INFOF("%d waypoints have been marked total\n", m);
70
71 j = 0;
73 {
74 if (navigation_findnearestwaypoint(it, false))
75 {
76 if(it.spawnpointmodel)
77 {
78 delete(it.spawnpointmodel);
79 it.spawnpointmodel = NULL;
80 }
81 }
82 else
83 {
84 if(!it.spawnpointmodel)
85 {
86 tracebox(it.origin, PL_MIN_CONST, PL_MAX_CONST, it.origin - '0 0 512', MOVE_NOMONSTERS, NULL);
87 entity e = new(spawnpointmodel);
89 setorigin(e, org);
90 e.solid = SOLID_TRIGGER;
91 it.spawnpointmodel = e;
92 }
93 LOG_INFO("spawn without waypoint: ", etos(it), " ", vtos(it.origin), "\n");
94 it.spawnpointmodel.effects |= EF_NODEPTHTEST;
95 _setmodel(it.spawnpointmodel, pl.model);
96 it.spawnpointmodel.frame = ANIM_idle.m_id;
97 it.spawnpointmodel.skin = pl.skin;
98 it.spawnpointmodel.colormap = 1024 + 68;
99 it.spawnpointmodel.glowmod = '1 0 0';
100 it.spawnpointmodel.angles = it.angles;
101 setsize(it.spawnpointmodel, PL_MIN_CONST, PL_MAX_CONST);
102 j++;
103 }
104 });
105 if (j) LOG_INFOF("%d spawnpoints have no nearest waypoint (marked by player model)\n", j);
106
107 j = 0;
108 IL_EACH(g_items, true,
109 {
110 it.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
111 it.colormod = '0.5 0.5 0.5';
112 });
113 IL_EACH(g_items, true,
114 {
115 if (navigation_findnearestwaypoint(it, false))
116 continue;
117 LOG_INFO("item without waypoint: ", etos(it), " ", vtos(it.origin), "\n");
118 it.effects |= EF_NODEPTHTEST | EF_RED;
119 it.colormod_x = 8;
120 j++;
121 });
122 if (j) LOG_INFOF("%d items have no nearest waypoint and cannot be walked away from (marked with red light)\n", j);
123
124 j = 0;
125 IL_EACH(g_items, true,
126 {
127 if (navigation_findnearestwaypoint(it, true))
128 continue;
129 LOG_INFO("item without waypoint: ", etos(it), " ", vtos(it.origin), "\n");
130 it.effects |= EF_NODEPTHTEST | EF_BLUE;
131 it.colormod_z = 8;
132 j++;
133 });
134 if (j) LOG_INFOF("%d items have no nearest waypoint and cannot be walked to (marked with blue light)\n", j);
135}
void navigation_markroutes_inverted(entity fixed_source_waypoint)
void navigation_markroutes(entity this, entity fixed_source_waypoint)
const float EF_RED
const float EF_BLUE
const float EF_NODEPTHTEST
IntrusiveList g_spawnpoints
entity spawnpointmodel
Definition waypoints.qc:27

References EF_BLUE, EF_NODEPTHTEST, EF_RED, entity(), etos(), eZ, g_items, g_spawnpoints, g_waypoints, IL_EACH, LOG_INFO, LOG_INFOF, MOVE_NOMONSTERS, navigation_findnearestwaypoint(), navigation_markroutes(), navigation_markroutes_inverted(), NULL, org, PL_MAX_CONST, PL_MIN_CONST, SOLID_TRIGGER, spawnpointmodel, trace_endpos, vector, and vtos().

Referenced by ClientCommand_wpeditor().

Variable Documentation

◆ autocvar_g_waypoints_for_items

bool autocvar_g_waypoints_for_items

Definition at line 8 of file api.qh.

Referenced by spawnfunc().

◆ bot_attack

◆ bot_basewaypoint

entity bot_basewaypoint

◆ bot_custom_weapon

float bot_custom_weapon

Definition at line 31 of file api.qh.

Referenced by bot_custom_weapon_priority_setup(), and havocbot_chooseweapon().

◆ bot_dodge

float bot_dodge

Definition at line 40 of file api.qh.

Referenced by havocbot_dodge(), W_Electro_Orb_Stick(), and W_MineLayer_Stick().

◆ bot_dodgerating

float bot_dodgerating

Definition at line 39 of file api.qh.

Referenced by W_Electro_Orb_Stick(), and W_MineLayer_Stick().

◆ bot_forced_team

float bot_forced_team

Definition at line 41 of file api.qh.

Referenced by bot_setnameandstuff(), and PutPlayerInServer().

◆ bot_moveskill

float bot_moveskill

Definition at line 42 of file api.qh.

Referenced by bot_setnameandstuff(), havocbot_keyboard_movement(), and havocbot_movetogoal().

◆ bot_pickup

float bot_pickup

Definition at line 43 of file api.qh.

Referenced by buff_Init(), func_ladder_init(), and StartItem().

◆ bot_tracewalk_time

float bot_tracewalk_time

Definition at line 37 of file api.qh.

Referenced by havocbot_movetogoal(), and navigation_shortenpath().

◆ bot_waypoints_for_items

bool bot_waypoints_for_items

Definition at line 9 of file api.qh.

Referenced by spawnfunc(), and waypoint_spawnforitem().

◆ bot_weapons_close

float bot_weapons_close[REGISTRY_MAX(Weapons)]

Definition at line 32 of file api.qh.

Referenced by havocbot_chooseweapon().

◆ bot_weapons_far

float bot_weapons_far[REGISTRY_MAX(Weapons)]

Definition at line 33 of file api.qh.

Referenced by havocbot_chooseweapon().

◆ bot_weapons_mid

float bot_weapons_mid[REGISTRY_MAX(Weapons)]

Definition at line 34 of file api.qh.

Referenced by havocbot_chooseweapon().

◆ bots_would_leave

int bots_would_leave

how many bots would leave so humans can replace them

Definition at line 101 of file api.qh.

Referenced by bot_fixcount(), nJoinAllowed(), TeamBalance_AreEqual(), TeamBalance_CompareTeamsInternal(), and TeamBalance_QueuedPlayersTagIn().

◆ cleanname

string cleanname

Definition at line 45 of file api.qh.

Referenced by bot_clientdisconnect(), and bot_setnameandstuff().

◆ currentbots

◆ g_bot_dodge

◆ g_bot_targets

◆ g_waypoints

◆ goalentity_lock_timeout

◆ havocbot_middlepoint

◆ havocbot_middlepoint_radius

◆ havocbot_role_timeout

◆ havocbot_symmetry_axis_m

float havocbot_symmetry_axis_m

Definition at line 93 of file api.qh.

Referenced by havocbot_ctf_calculate_middlepoint(), and waypoint_getSymmetricalPoint().

◆ havocbot_symmetry_axis_q

float havocbot_symmetry_axis_q

Definition at line 94 of file api.qh.

Referenced by havocbot_ctf_calculate_middlepoint(), and waypoint_getSymmetricalPoint().

◆ havocbot_symmetry_origin_order

float havocbot_symmetry_origin_order

◆ ignoregoal

◆ ignoregoaltime

◆ isbot

float isbot

Definition at line 49 of file api.qh.

Referenced by bot_clientconnect().

◆ lastteleport_origin

vector lastteleport_origin

Definition at line 51 of file api.qh.

◆ lastteleporttime

float lastteleporttime

◆ navigation_dynamicgoal

bool navigation_dynamicgoal

Definition at line 107 of file api.qh.

Referenced by navigation_dynamicgoal_init().

◆ navigation_hasgoals

float navigation_hasgoals

Definition at line 52 of file api.qh.

◆ nearestwaypoint

◆ nearestwaypointtimeout

◆ player_count

◆ skill

◆ speed

float speed

Definition at line 55 of file api.qh.

◆ WAYPOINTFLAG_CROUCH

◆ WAYPOINTFLAG_CUSTOM_JP

◆ WAYPOINTFLAG_DEAD_END

const int WAYPOINTFLAG_DEAD_END = BIT(16)

Definition at line 18 of file api.qh.

Referenced by botframe_deleteuselesswaypoints().

◆ WAYPOINTFLAG_GENERATED

◆ WAYPOINTFLAG_ITEM

◆ WAYPOINTFLAG_JUMP

◆ WAYPOINTFLAG_LADDER

const int WAYPOINTFLAG_LADDER = BIT(15)

◆ WAYPOINTFLAG_NORELINK__DEPRECATED

const int WAYPOINTFLAG_NORELINK__DEPRECATED = BIT(20)

Definition at line 28 of file api.qh.

Referenced by waypoint_loadall().

◆ WAYPOINTFLAG_PERSONAL

◆ WAYPOINTFLAG_PROTECTED

const int WAYPOINTFLAG_PROTECTED = BIT(18)

◆ WAYPOINTFLAG_SUPPORT

◆ WAYPOINTFLAG_TELEPORT

◆ WAYPOINTFLAG_USEFUL

const int WAYPOINTFLAG_USEFUL = BIT(17)

Definition at line 17 of file api.qh.

Referenced by botframe_deleteuselesswaypoints().

◆ wp00

entity wp00

Definition at line 56 of file api.qh.

◆ wp00mincost

float wp00mincost

Definition at line 58 of file api.qh.

◆ wp01

entity wp01

Definition at line 56 of file api.qh.

◆ wp01mincost

float wp01mincost

Definition at line 58 of file api.qh.

◆ wp02

entity wp02

Definition at line 56 of file api.qh.

◆ wp02mincost

float wp02mincost

Definition at line 58 of file api.qh.

◆ wp03

entity wp03

Definition at line 56 of file api.qh.

◆ wp03mincost

float wp03mincost

Definition at line 58 of file api.qh.

◆ wp04

entity wp04

Definition at line 56 of file api.qh.

◆ wp04mincost

float wp04mincost

Definition at line 58 of file api.qh.

◆ wp05

entity wp05

Definition at line 56 of file api.qh.

◆ wp05mincost

float wp05mincost

Definition at line 58 of file api.qh.

◆ wp06

entity wp06

Definition at line 56 of file api.qh.

◆ wp06mincost

float wp06mincost

Definition at line 58 of file api.qh.

◆ wp07

entity wp07

Definition at line 56 of file api.qh.

◆ wp07mincost

float wp07mincost

Definition at line 58 of file api.qh.

◆ wp08

entity wp08

Definition at line 56 of file api.qh.

◆ wp08mincost

float wp08mincost

Definition at line 59 of file api.qh.

◆ wp09

entity wp09

Definition at line 56 of file api.qh.

◆ wp09mincost

float wp09mincost

Definition at line 59 of file api.qh.

◆ wp10

entity wp10

Definition at line 56 of file api.qh.

◆ wp10mincost

float wp10mincost

Definition at line 59 of file api.qh.

◆ wp11

entity wp11

Definition at line 56 of file api.qh.

◆ wp11mincost

float wp11mincost

Definition at line 59 of file api.qh.

◆ wp12

entity wp12

Definition at line 56 of file api.qh.

◆ wp12mincost

float wp12mincost

Definition at line 59 of file api.qh.

◆ wp13

entity wp13

Definition at line 56 of file api.qh.

◆ wp13mincost

float wp13mincost

Definition at line 59 of file api.qh.

◆ wp14

entity wp14

Definition at line 56 of file api.qh.

◆ wp14mincost

float wp14mincost

Definition at line 59 of file api.qh.

◆ wp15

entity wp15

Definition at line 56 of file api.qh.

◆ wp15mincost

float wp15mincost

Definition at line 59 of file api.qh.

◆ wp16

entity wp16

Definition at line 57 of file api.qh.

◆ wp16mincost

float wp16mincost

Definition at line 60 of file api.qh.

◆ wp17

entity wp17

Definition at line 57 of file api.qh.

◆ wp17mincost

float wp17mincost

Definition at line 60 of file api.qh.

◆ wp18

entity wp18

Definition at line 57 of file api.qh.

◆ wp18mincost

float wp18mincost

Definition at line 60 of file api.qh.

◆ wp19

entity wp19

Definition at line 57 of file api.qh.

◆ wp19mincost

float wp19mincost

Definition at line 60 of file api.qh.

◆ wp20

entity wp20

Definition at line 57 of file api.qh.

◆ wp20mincost

float wp20mincost

Definition at line 60 of file api.qh.

◆ wp21

entity wp21

Definition at line 57 of file api.qh.

◆ wp21mincost

float wp21mincost

Definition at line 60 of file api.qh.

◆ wp22

entity wp22

Definition at line 57 of file api.qh.

◆ wp22mincost

float wp22mincost

Definition at line 60 of file api.qh.

◆ wp23

entity wp23

Definition at line 57 of file api.qh.

◆ wp23mincost

float wp23mincost

Definition at line 60 of file api.qh.

◆ wp24

entity wp24

Definition at line 57 of file api.qh.

◆ wp24mincost

float wp24mincost

Definition at line 61 of file api.qh.

◆ wp25

entity wp25

Definition at line 57 of file api.qh.

◆ wp25mincost

float wp25mincost

Definition at line 61 of file api.qh.

◆ wp26

entity wp26

Definition at line 57 of file api.qh.

◆ wp26mincost

float wp26mincost

Definition at line 61 of file api.qh.

◆ wp27

entity wp27

Definition at line 57 of file api.qh.

◆ wp27mincost

float wp27mincost

Definition at line 61 of file api.qh.

◆ wp28

entity wp28

Definition at line 57 of file api.qh.

◆ wp28mincost

float wp28mincost

Definition at line 61 of file api.qh.

◆ wp29

entity wp29

Definition at line 57 of file api.qh.

◆ wp29mincost

float wp29mincost

Definition at line 61 of file api.qh.

◆ wp30

entity wp30

Definition at line 57 of file api.qh.

◆ wp30mincost

float wp30mincost

Definition at line 61 of file api.qh.

◆ wp31

entity wp31

Definition at line 57 of file api.qh.

◆ wp31mincost

float wp31mincost

Definition at line 61 of file api.qh.

◆ wpconsidered

float wpconsidered

Definition at line 62 of file api.qh.

◆ wpcost

float wpcost

Definition at line 63 of file api.qh.

◆ WPFLAGMASK_NORELINK

◆ wpflags

int wpflags

Definition at line 64 of file api.qh.

Referenced by waypoint_think().

◆ wphw00

entity wphw00

Definition at line 65 of file api.qh.

◆ wphw01

entity wphw01

Definition at line 65 of file api.qh.

◆ wphw02

entity wphw02

Definition at line 65 of file api.qh.

◆ wphw03

entity wphw03

Definition at line 65 of file api.qh.

◆ wphw04

entity wphw04

Definition at line 65 of file api.qh.

◆ wphw05

entity wphw05

Definition at line 65 of file api.qh.

◆ wphw06

entity wphw06

Definition at line 65 of file api.qh.

◆ wphw07

entity wphw07

Definition at line 65 of file api.qh.