23 if(!bot.bot_cmdqueuebuf_allocated)
25 buf_del(bot.bot_cmdqueuebuf);
26 bot.bot_cmdqueuebuf_allocated =
false;
27 LOG_TRACE(
"bot ", bot.netname,
" queue cleared");
32 if(!bot.bot_cmdqueuebuf_allocated)
35 bot.bot_cmdqueuebuf_allocated =
true;
36 bot.bot_cmdqueuebuf_start = 0;
37 bot.bot_cmdqueuebuf_end = 0;
40 bufstr_set(bot.bot_cmdqueuebuf, bot.bot_cmdqueuebuf_end, cmdstring);
69 bot.bot_cmdqueuebuf_end += 1;
74 if(!bot.bot_cmdqueuebuf_allocated)
75 error(
"dequeuecommand but no queue allocated");
76 if(idx < bot.bot_cmdqueuebuf_start)
77 error(
"dequeueing a command in the past");
78 if(idx >= bot.bot_cmdqueuebuf_end)
79 error(
"dequeueing a command in the future");
80 bufstr_set(bot.bot_cmdqueuebuf, idx,
"");
81 if(idx == bot.bot_cmdqueuebuf_start)
82 bot.bot_cmdqueuebuf_start += 1;
83 if(bot.bot_cmdqueuebuf_start >= bot.bot_cmdqueuebuf_end)
89 if(!bot.bot_cmdqueuebuf_allocated)
90 error(
"readcommand but no queue allocated");
91 if(idx < bot.bot_cmdqueuebuf_start)
92 error(
"reading a command in the past");
93 if(idx >= bot.bot_cmdqueuebuf_end)
94 error(
"reading a command in the future");
95 return bufstr_get(bot.bot_cmdqueuebuf, idx);
141 this.bot_places_count += 1;
149 LOG_INFO(
"invalid place ", placename);
298 LOG_INFO(
"ERROR: A parameter is required for this command");
306 switch(cmd_parm_type)
317 LOG_INFOF(
"ERROR: expected vector type \'x y z\', got %s", parm);
327 LOG_INFO(
"ERROR: No such command '", cmdstring,
"'");
366 desc =
"Stops the bot completely. Any command other than 'continue' will be ignored.";
369 desc =
"Disable paused status";
372 desc =
"Pause command parsing and bot ai for N seconds. Pressed key will remain pressed";
375 desc =
"Pause command parsing and bot ai until time is N from the last barrier. Pressed key will remain pressed";
378 desc =
"Waits till all bots that have a command queue reach this command. Pressed key will remain pressed";
381 desc =
"Look to the right or left N degrees. For turning to the left use positive numbers.";
384 desc =
"Walk to an specific coordinate on the map. Usage: moveto \'x y z\'";
387 desc =
"Walk to the specific target on the map";
390 desc =
"Resets the goal stack";
393 desc =
"Execute client command. Examples: cc \"say something\"; cc god; cc \"name newnickname\"; cc kill;";
396 desc =
"Perform simple conditional execution.\n" 398 " sv_cmd .. if \"condition\"\n" 399 " sv_cmd .. <instruction if true>\n" 400 " sv_cmd .. <instruction if true>\n" 402 " sv_cmd .. <instruction if false>\n" 403 " sv_cmd .. <instruction if false>\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;";
411 desc =
"Points the aim to the coordinates x,y 0,0";
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";
420 desc =
"Points the aim to given target";
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";
428 desc =
"Release previoulsy used keys. Use the parameter \"all\" to release all keys";
431 desc =
"play sound file at bot location";
434 desc =
"verify the state of the weapon entity";
437 desc =
"This command has no description yet.";
476 LOG_HELP(
"For help about a specific command, type bot_cmd help <command>");
490 CS(
this).impulse =
bot_cmd.bot_cmd_parm_float;
545 if(it.bot_cmdqueuebuf_allocated)
546 if(it.bot_barrier != 1)
547 return CMD_STATUS_EXECUTING;
575 float id =
bot_cmd.bot_cmd_parm_float;
580 bool success =
false;
585 if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
591 this.(weaponentity).m_switchweapon =
REGISTRY_GET(Weapons,
id);
631 LOG_INFO(
"ERROR: Unable to convert the expression '", expr,
"' into a numeric value");
637 string expr, val_a, val_b;
643 LOG_INFO(
"ERROR: Only one conditional block can be processed at time");
651 expr =
bot_cmd.bot_cmd_parm_string;
753 parms =
bot_cmd.bot_cmd_parm_string;
757 if(tokens<2||tokens>3)
760 step = (tokens == 3) ?
stof(
argv(2)) : 0;
773 this.bot_cmd_aim_end_z = 0;
793 parms =
bot_cmd.bot_cmd_parm_string;
801 v = e.origin + (e.mins + e.maxs) * 0.5;
806 this.v_angle_x = -this.
v_angle.x;
810 if(tokens<1||tokens>2)
842 CS(
this).movement =
'0 0 0';
855 CS(
this).movement_x = autocvar_sv_maxspeed;
857 CS(
this).movement_x = -autocvar_sv_maxspeed;
860 CS(
this).movement_y = autocvar_sv_maxspeed;
862 CS(
this).movement_y = -autocvar_sv_maxspeed;
987 key =
bot_cmd.bot_cmd_parm_string;
998 key =
bot_cmd.bot_cmd_parm_string;
1019 CS(
this).movement =
'0 0 0';
1029 return this.cmd_moveto(
this,
bot_cmd.bot_cmd_parm_vector);
1038 return this.cmd_moveto(
this, e.origin + (e.mins + e.maxs) * 0.5);
1043 return this.cmd_resetgoal(
this);
1050 f =
bot_cmd.bot_cmd_parm_string;
1060 sample =
argv(n - 1);
1069 _sound(
this, chan, sample, vol, atten);
1077 float f =
bot_cmd.bot_cmd_parm_float;
1086 LOG_INFO(
"Bot ", this.
netname,
" using ", this.(weaponentity).weaponname,
" wants to fire, inhibited by weaponentity state");
1094 LOG_INFO(
"Bot ", this.
netname,
" using ", this.(weaponentity).weaponname,
" wants to fire, inhibited by ATTACK_FINISHED (",
ftos(
ATTACK_FINISHED(
this, weaponentity) -
time),
" seconds left)");
1102 LOG_INFO(
"Bot ", this.
netname,
" using ", this.(weaponentity).weaponname,
" wants to fire, bot still has an active tuba note");
1110 LOG_INFO(
"Bot ", this.
netname,
" using ", this.(weaponentity).weaponname,
" thinks it has fired, but apparently did not; ATTACK_FINISHED says ",
ftos(
ATTACK_FINISHED(
this, weaponentity) -
time),
" seconds left");
1141 if(
bot_cmd.bot_cmd_index !=
this.bot_cmd_execution_index ||
this.bot_cmd_execution_index == 0)
1168 it.bot_cmd_execution_index = 0;
1172 for(int i = 0; i < it.bot_places_count; ++i)
1174 strfree(it.(bot_placenames[i]));
1176 it.bot_places_count = 0;
1186 float status, ispressingkey;
1206 LOG_INFO(
"WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.");
1231 return ispressingkey;
1328 parms =
bot_cmd.bot_cmd_parm_string;
string bot_cmd_string[BOT_CMD_COUNTER]
#define PHYS_INPUT_BUTTON_ATCK2(s)
#define PHYS_INPUT_BUTTON_JUMP(s)
#define PHYS_INPUT_BUTTON_CHAT(s)
#define PHYS_INPUT_BUTTON_CROUCH(s)
float bot_cmd_aim_endtime
string bot_readcommand(entity bot, float idx)
const int CMD_CONDITION_false_BLOCK
#define PHYS_INPUT_BUTTON_DRAG(s)
float bot_cmd_continue(entity this)
const int BOT_CMD_MOVETOTARGET
#define PHYS_INPUT_BUTTON_HOOK(s)
spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 spree_inf s1 s2 s3loc s2 s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2loc s1 s2 f1 f1points s1 s2
float bot_decodecommand(string cmdstring)
float bot_cmd_impulse(entity this)
entity find_bot_by_number(float number)
const int BOT_CMD_KEY_NONE
bool bot_havecommand(entity this, int idx)
void bot_relinkplayerlist()
float bot_cmd_resetaim(entity this)
float bot_execute_commands_once(entity this)
const int BOT_CMD_AIMTARGET
float bot_cmd_sound(entity this)
bool autocvar_g_debug_bot_commands
const int BOT_CMD_KEY_RIGHT
int bot_cmd_parm_type[BOT_CMD_COUNTER]
int bot_execute_commands(entity this)
#define BOT_EXEC_STATUS_WAITING
int bot_cmd_condition_status
void bot_command_executed(entity this, bool rm)
float bot_cmd_moveto(entity this)
#define BOT_EXEC_STATUS_PAUSED
#define REGISTRY_GET(id, i)
ClientState CS(Client this)
#define FOREACH_CLIENT(cond, body)
float bot_cmd_wait_until(entity this)
const int BOT_CMD_KEY_ATTACK1
float bot_cmd_else(entity this)
float bot_cmd_eval(entity this, string expr)
float bot_cmd_barrier(entity this)
const int BOT_CMD_RESETAIM
float bot_cmd_cc(entity this)
const int BOT_CMD_CONTINUE
const int CMD_CONDITION_NONE
const int BOT_CMD_KEY_ATTACK2
const int WS_READY
idle frame
float bot_cmd_aim(entity this)
void bot_queuecommand(entity bot, string cmdstring)
float bot_cmdqueuebuf_start
float bot_cmd_releasekey(entity this)
float bot_cmd_aimtarget(entity this)
const int BOT_CMD_KEY_JUMP
const int BOT_CMD_KEY_USE
const int BOT_CMD_KEY_BACKWARD
const int BOT_CMD_KEY_HOOK
float bot_cmd_debug_assert_canfire(entity this)
#define CMD_STATUS_FINISHED
float bot_cmd_select_weapon(entity this)
float bot_cmd_execution_index
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
float bot_cmd_fi(entity this)
const int BOT_CMD_PRESSKEY
void SV_ParseClientCommand(entity this, string command)
float bot_cmd_movetotarget(entity this)
string bot_placenames[MAX_BOT_PLACES]
float bot_cmd_keypress_handler(entity this, string key, float enabled)
const int CMD_CONDITION_false
void bot_clearqueue(entity bot)
float bot_cmd_wait(entity this)
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
const int MAX_WEAPONSLOTS
float bot_cmd_pause(entity this)
#define PHYS_INPUT_BUTTON_USE(s)
float bot_cmd_aim_begintime
entity bot_places[MAX_BOT_PLACES]
const int CMD_CONDITION_true
#define CMD_STATUS_EXECUTING
entity bot_getplace(entity this, string placename)
#define PHYS_INPUT_BUTTON_ATCK(s)
float bot_cmd_resetgoal(entity this)
const int BOT_CMD_DEBUG_ASSERT_CANFIRE
const int BOT_CMD_CONSOLE
const int BOT_CMD_PARAMETER_VECTOR
const int BOT_CMD_RESETGOAL
const int BOT_CMD_WAIT_UNTIL
vector(float skel, float bonenum) _skel_get_boneabs_hidden
const int BOT_CMD_KEY_FORWARD
const int BOT_CMD_IMPULSE
const int CMD_CONDITION_true_BLOCK
const int BOT_CMD_COUNTER
float bot_cmd_turn(entity this)
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
const int BOT_CMD_RELEASEKEY
bool bot_presskeys(entity this)
const int BOT_CMD_PARAMETER_NONE
float bot_cmdqueuebuf_end
#define _sound(e, c, s, v, a)
float bot_cmd_presskey(entity this)
#define tokenizebyseparator
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
entity weaponentities[MAX_WEAPONSLOTS]
#define new_pure(class)
purely logical entities (.origin doesn't work)
entity find_bot_by_name(string name)
float bot_cmd_if(entity this)
#define ATTACK_FINISHED(ent, w)
void bot_setcurrentcommand(entity this)
bool bot_ispaused(entity this)
const int BOT_CMD_BARRIER
const int BOT_CMD_KEY_CROUCH
float bot_cmdqueuebuf_allocated
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
const int BOT_CMD_PARAMETER_FLOAT
void bot_dequeuecommand(entity bot, float idx)
const int BOT_CMD_SELECTWEAPON
const int BOT_CMD_KEY_LEFT
const int BOT_CMD_KEY_CHAT
float bot_cmds_initialized
void bot_cmdhelp(string scmd)
const int BOT_CMD_PARAMETER_STRING