1 // NOTE: New commands should be added here. Do not forget to update BOT_CMD_COUNTER
\r
2 #define BOT_CMD_NULL 0
\r
3 #define BOT_CMD_PAUSE 1
\r
4 #define BOT_CMD_CONTINUE 2
\r
5 #define BOT_CMD_WAIT 3
\r
6 #define BOT_CMD_TURN 4
\r
7 #define BOT_CMD_MOVETO 5
\r
8 #define BOT_CMD_RESETGOAL 6
\r
11 #define BOT_CMD_ELSE 9
12 #define BOT_CMD_FI 10
\r
13 #define BOT_CMD_RESETAIM 11
\r
14 #define BOT_CMD_AIM 12
15 #define BOT_CMD_PRESSKEY 13
16 #define BOT_CMD_RELEASEKEY 14
17 #define BOT_CMD_SELECTWEAPON 15
\r
18 #define BOT_CMD_IMPULSE 16
\r
19 #define BOT_CMD_COUNTER 17
\r
21 // NOTE: Following commands should be implemented on the bot ai
\r
22 .float(vector) cmd_moveto;
\r
23 .float() cmd_resetgoal;
\r
26 #define BOT_CMD_PARAMETER_NONE 0
\r
27 #define BOT_CMD_PARAMETER_FLOAT 1
\r
28 #define BOT_CMD_PARAMETER_STRING 2
\r
29 #define BOT_CMD_PARAMETER_VECTOR 3
\r
31 float bot_cmds_initialized;
32 float bot_cmd_parm_type[BOT_CMD_COUNTER];
33 string bot_cmd_string[BOT_CMD_COUNTER];
35 // Bots command queue
\r
37 #define BOT_CMD_QUEUE_SIZE 150
\r
39 .float bot_cmd[BOT_CMD_QUEUE_SIZE];
\r
40 .float bot_cmd_parm_float[BOT_CMD_QUEUE_SIZE];
41 .string bot_cmd_parm_string[BOT_CMD_QUEUE_SIZE];
\r
42 .vector bot_cmd_parm_vector[BOT_CMD_QUEUE_SIZE];
\r
44 .float bot_cmd_execution_index;
\r
45 .float bot_cmd_queue_index;
\r
47 // Initialize global commands list
\r
48 // NOTE: New commands should be initialized here
\r
49 void bot_commands_init()
\r
51 bot_cmd_string[BOT_CMD_NULL] = "";
\r
52 bot_cmd_parm_type[BOT_CMD_NULL] = BOT_CMD_PARAMETER_NONE;
\r
54 bot_cmd_string[BOT_CMD_PAUSE] = "pause";
\r
55 bot_cmd_parm_type[BOT_CMD_PAUSE] = BOT_CMD_PARAMETER_NONE;
\r
57 bot_cmd_string[BOT_CMD_CONTINUE] = "continue";
\r
58 bot_cmd_parm_type[BOT_CMD_CONTINUE] = BOT_CMD_PARAMETER_NONE;
\r
60 bot_cmd_string[BOT_CMD_WAIT] = "wait";
\r
61 bot_cmd_parm_type[BOT_CMD_WAIT] = BOT_CMD_PARAMETER_FLOAT;
\r
63 bot_cmd_string[BOT_CMD_TURN] = "turn";
\r
64 bot_cmd_parm_type[BOT_CMD_TURN] = BOT_CMD_PARAMETER_FLOAT;
\r
66 bot_cmd_string[BOT_CMD_MOVETO] = "moveto";
\r
67 bot_cmd_parm_type[BOT_CMD_MOVETO] = BOT_CMD_PARAMETER_VECTOR;
\r
69 bot_cmd_string[BOT_CMD_RESETGOAL] = "resetgoal";
\r
70 bot_cmd_parm_type[BOT_CMD_RESETGOAL] = BOT_CMD_PARAMETER_NONE;
\r
72 bot_cmd_string[BOT_CMD_CC] = "cc";
\r
73 bot_cmd_parm_type[BOT_CMD_CC] = BOT_CMD_PARAMETER_STRING;
\r
75 bot_cmd_string[BOT_CMD_IF] = "if";
\r
76 bot_cmd_parm_type[BOT_CMD_IF] = BOT_CMD_PARAMETER_STRING;
\r
78 bot_cmd_string[BOT_CMD_ELSE] = "else";
\r
79 bot_cmd_parm_type[BOT_CMD_ELSE] = BOT_CMD_PARAMETER_NONE;
\r
81 bot_cmd_string[BOT_CMD_FI] = "fi";
\r
82 bot_cmd_parm_type[BOT_CMD_FI] = BOT_CMD_PARAMETER_NONE;
\r
84 bot_cmd_string[BOT_CMD_RESETAIM] = "resetaim";
\r
85 bot_cmd_parm_type[BOT_CMD_RESETAIM] = BOT_CMD_PARAMETER_NONE;
\r
87 bot_cmd_string[BOT_CMD_AIM] = "aim";
\r
88 bot_cmd_parm_type[BOT_CMD_AIM] = BOT_CMD_PARAMETER_STRING;
\r
90 bot_cmd_string[BOT_CMD_PRESSKEY] = "presskey";
91 bot_cmd_parm_type[BOT_CMD_PRESSKEY] = BOT_CMD_PARAMETER_STRING;
93 bot_cmd_string[BOT_CMD_RELEASEKEY] = "releasekey";
94 bot_cmd_parm_type[BOT_CMD_RELEASEKEY] = BOT_CMD_PARAMETER_STRING;
96 bot_cmd_string[BOT_CMD_SELECTWEAPON] = "selectweapon";
97 bot_cmd_parm_type[BOT_CMD_SELECTWEAPON] = BOT_CMD_PARAMETER_FLOAT;
99 bot_cmd_string[BOT_CMD_IMPULSE] = "impulse";
\r
100 bot_cmd_parm_type[BOT_CMD_IMPULSE] = BOT_CMD_PARAMETER_FLOAT;
\r
102 bot_cmds_initialized = TRUE;
\r
105 // Returns first bot with matching name
\r
106 entity find_bot_by_name(string name)
\r
110 bot = findchainflags(flags, FL_CLIENT);
\r
113 if(clienttype(bot) == CLIENTTYPE_BOT)
\r
114 if(bot.netname==name)
\r
123 // Returns a bot by number on list
\r
124 entity find_bot_by_number(float number)
\r
129 bot = findchainflags(flags, FL_CLIENT);
\r
132 if(clienttype(bot) == CLIENTTYPE_BOT)
\r
143 void bot_clearqueue()
\r
145 self.(bot_cmd[0]) = BOT_CMD_NULL;
\r
146 self.bot_cmd_queue_index = 0;
\r
147 self.bot_cmd_execution_index = 0;
\r
150 void bot_queuecommand(entity bot, string cmd, string parm)
\r
152 local float queue_index, cmd_parm_type, i;
\r
157 if(!bot_cmds_initialized)
\r
158 bot_commands_init();
\r
160 queue_index = bot.bot_cmd_queue_index;
162 if(bot.bot_cmd[queue_index]!=BOT_CMD_NULL)
164 print( strcat("WARNING: Command queue of length (",ftos(BOT_CMD_QUEUE_SIZE),") is full. Command ignored.\n"));
168 for(i=1;i<BOT_CMD_COUNTER;++i)
\r
170 if(bot_cmd_string[i]!=cmd)
\r
173 cmd_parm_type = bot_cmd_parm_type[i];
\r
175 if(cmd_parm_type!=BOT_CMD_PARAMETER_NONE&&parm=="")
\r
177 print("ERROR: Invalid parameters count\n");
\r
181 // Load command into queue
182 bot.(bot_cmd[queue_index]) = i;
184 // Load parameters into queue
\r
185 switch(cmd_parm_type)
\r
187 case BOT_CMD_PARAMETER_FLOAT:
\r
188 bot.(bot_cmd_parm_float[queue_index]) = stof(parm);
\r
190 case BOT_CMD_PARAMETER_STRING:
\r
191 bot.(bot_cmd_parm_string[queue_index]) = strzone(parm);
\r
193 case BOT_CMD_PARAMETER_VECTOR:
\r
194 bot.(bot_cmd_parm_vector[queue_index]) = stov(parm);
\r
200 // Move the queue index to the next position
201 if(queue_index==BOT_CMD_QUEUE_SIZE-1)
202 bot.bot_cmd_queue_index = queue_index = 0;
204 bot.bot_cmd_queue_index += 1;
208 print("ERROR: No such command");
\r
211 float bot_cmd_getparm_float()
\r
213 local float index = self.bot_cmd_execution_index;
\r
214 return self.bot_cmd_parm_float[index];
\r
217 string bot_cmd_getparm_string()
\r
219 local float index = self.bot_cmd_execution_index;
\r
220 return self.bot_cmd_parm_string[index];
\r
223 vector bot_cmd_getparm_vector()
\r
225 local float index = self.bot_cmd_execution_index;
\r
226 return self.bot_cmd_parm_vector[index];
\r
229 void bot_cmdhelp(string scmd)
\r
231 local float i, index, ntype;
\r
232 local string stype;
\r
234 if(!bot_cmds_initialized)
\r
235 bot_commands_init();
\r
237 for(i=1;i<BOT_CMD_COUNTER;++i)
\r
239 if(bot_cmd_string[i]!=scmd)
\r
242 ntype = bot_cmd_parm_type[i];
\r
246 case BOT_CMD_PARAMETER_FLOAT:
\r
247 stype = "float number";
\r
249 case BOT_CMD_PARAMETER_STRING:
\r
252 case BOT_CMD_PARAMETER_VECTOR:
\r
260 print(strcat("Command: ",bot_cmd_string[i],"\nParameter: <",stype,"> \n"));
\r
262 print("Description: ");
\r
265 case BOT_CMD_PAUSE:
\r
266 print("Stops the bot completely. Any command other than 'continue' will be ignored.");
\r
268 case BOT_CMD_CONTINUE:
\r
269 print("Disable paused status");
\r
272 print("Pause command parsing and bot ai for N seconds. Pressed key will remain pressed");
\r
275 print("Look to the right or left N degrees. For turning to the left use positive numbers.");
\r
277 case BOT_CMD_MOVETO:
\r
279 case BOT_CMD_RESETGOAL:
\r
282 print("Execute client command. Examples: cc \"say something\"; cc god; cc \"name newnickname\"; cc kill;");
\r
285 print("Perform simple conditional execution.\n");
\r
286 print("Syntax: \n");
\r
287 print(" sv_cmd .. if \"condition\"\n");
\r
288 print(" sv_cmd .. <instruction if true>\n");
\r
289 print(" sv_cmd .. <instruction if true>\n");
\r
290 print(" sv_cmd .. else\n");
\r
291 print(" sv_cmd .. <instruction if false>\n");
\r
292 print(" sv_cmd .. <instruction if false>\n");
\r
293 print(" sv_cmd .. fi\n");
\r
294 print("Conditions: a=b, a>b, a<b, a\t\t(spaces not allowed)\n");
\r
295 print(" Values in conditions can be numbers, cvars in the form cvar.cvar_string or special fields\n");
\r
296 print("Fields: health, speed, flagcarrier\n");
\r
297 print("Examples: if health>50; if health>cvar.g_balance_laser_primary_damage; if flagcarrier;");
299 case BOT_CMD_RESETAIM:
\r
300 print("Points the aim to the coordinates x,y 0,0");
\r
303 print("Move the aim x/y (horizontal/vertical) degrees relatives to the bot\n");
\r
304 print("There is a 3rd optional parameter telling in how many seconds the aim has to reach the new position\n");
\r
305 print("Examples: aim \"90 0\" // Turn 90 degrees inmediately (positive numbers move to the left/up)\n");
\r
306 print(" aim \"0 90 2\" // Will gradually look to the sky in the next two seconds");
\r
308 case BOT_CMD_PRESSKEY:
309 print("Press one of the following keys: forward, backward, left, right, jump, crouch, attack1, attack2, use\n");
310 print("Multiple keys can be pressed at time (with many presskey calls) and it will remain pressed until the command \"releasekey\" is called");
311 print("Note: The script will not return the control to the bot ai until all keys are released");
313 case BOT_CMD_RELEASEKEY:
314 print("Release previoulsy used keys. Use the parameter \"all\" to release all keys");
317 print("This command has no description yet.");
324 void bot_list_commands()
\r
327 local string ptype;
\r
329 if(!bot_cmds_initialized)
332 print("List of all available commands:\n");
333 print(" Command\t\t\t\tParameter Type\n");
\r
335 for(i=1;i<BOT_CMD_COUNTER;++i)
\r
337 switch(bot_cmd_parm_type[i])
\r
339 case BOT_CMD_PARAMETER_FLOAT:
\r
340 ptype = "float number";
\r
342 case BOT_CMD_PARAMETER_STRING:
\r
345 case BOT_CMD_PARAMETER_VECTOR:
\r
352 print(strcat(" ",bot_cmd_string[i],"\t\t\t\t<",ptype,"> \n"));
\r
357 .float bot_exec_status;
\r
359 #define BOT_EXEC_STATUS_IDLE 0
\r
360 #define BOT_EXEC_STATUS_PAUSED 1
\r
361 #define BOT_EXEC_STATUS_WAITING 2
\r
363 #define CMD_STATUS_EXECUTING 0
\r
364 #define CMD_STATUS_FINISHED 1
\r
365 #define CMD_STATUS_ERROR 2
\r
367 float bot_cmd_raw()
\r
369 clientcommand(self,bot_cmd_getparm_string());
\r
370 return CMD_STATUS_FINISHED;
\r
373 float bot_cmd_impulse()
\r
375 self.impulse = bot_cmd_getparm_float();
\r
376 return CMD_STATUS_FINISHED;
\r
379 float bot_cmd_continue()
\r
381 self.bot_exec_status &~= BOT_EXEC_STATUS_PAUSED;
\r
382 return CMD_STATUS_FINISHED;
\r
385 .float bot_cmd_wait_time;
\r
386 float bot_cmd_wait()
\r
388 if(self.bot_exec_status & BOT_EXEC_STATUS_WAITING)
\r
390 if(time>=self.bot_cmd_wait_time)
\r
392 self.bot_exec_status &~= BOT_EXEC_STATUS_WAITING;
\r
393 return CMD_STATUS_FINISHED;
\r
396 return CMD_STATUS_EXECUTING;
\r
399 self.bot_cmd_wait_time = time + bot_cmd_getparm_float();
\r
400 self.bot_exec_status |= BOT_EXEC_STATUS_WAITING;
\r
401 return CMD_STATUS_EXECUTING;
\r
404 float bot_cmd_turn()
\r
406 self.v_angle_y = self.v_angle_y + bot_cmd_getparm_float();
407 self.v_angle_y = self.v_angle_y - floor(self.v_angle_y / 360) * 360;
\r
408 return CMD_STATUS_FINISHED;
\r
411 float bot_cmd_select_weapon()
415 id = bot_cmd_getparm_float();
417 if(id < WEP_FIRST || id > WEP_LAST)
418 return CMD_STATUS_ERROR;
420 if(client_hasweapon(self, id, TRUE, FALSE))
421 self.switchweapon = id;
423 return CMD_STATUS_FINISHED;
426 .float bot_cmd_condition_status;
\r
428 #define CMD_CONDITION_NONE 0
\r
429 #define CMD_CONDITION_TRUE 1
\r
430 #define CMD_CONDITION_FALSE 2
\r
431 #define CMD_CONDITION_TRUE_BLOCK 4
\r
432 #define CMD_CONDITION_FALSE_BLOCK 8
\r
434 float bot_cmd_eval(string expr)
436 // Search for numbers
437 if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0)
443 if(substring(expr, 0, 5)=="cvar.")
445 return cvar(substring(expr, 5, strlen(expr)));
454 return vlen(self.velocity);
456 return ((self.flagcarried!=world));
459 print(strcat("ERROR: Can not convert the expression '",expr,"' into a numeric value\n"));
\r
465 local string expr, val_a, val_b;
\r
468 if(self.bot_cmd_condition_status != CMD_CONDITION_NONE)
\r
470 // Only one "if" block is allowed at time
\r
471 print("ERROR: Only one conditional block can be processed at time");
\r
473 return CMD_STATUS_ERROR;
\r
476 self.bot_cmd_condition_status |= CMD_CONDITION_TRUE_BLOCK;
\r
478 // search for operators
\r
479 expr = bot_cmd_getparm_string();
\r
481 cmpofs = strstrofs(expr,"=",0);
\r
485 val_a = substring(expr,0,cmpofs);
\r
486 val_b = substring(expr,cmpofs+1,strlen(expr));
488 if(bot_cmd_eval(val_a)==bot_cmd_eval(val_b))
\r
489 self.bot_cmd_condition_status |= CMD_CONDITION_TRUE;
\r
491 self.bot_cmd_condition_status |= CMD_CONDITION_FALSE;
\r
493 return CMD_STATUS_FINISHED;
\r
496 cmpofs = strstrofs(expr,">",0);
\r
500 val_a = substring(expr,0,cmpofs);
\r
501 val_b = substring(expr,cmpofs+1,strlen(expr));
\r
503 if(bot_cmd_eval(val_a)>bot_cmd_eval(val_b))
\r
504 self.bot_cmd_condition_status |= CMD_CONDITION_TRUE;
\r
506 self.bot_cmd_condition_status |= CMD_CONDITION_FALSE;
\r
508 return CMD_STATUS_FINISHED;
\r
511 cmpofs = strstrofs(expr,"<",0);
\r
515 val_a = substring(expr,0,cmpofs);
\r
516 val_b = substring(expr,cmpofs+1,strlen(expr));
\r
518 if(bot_cmd_eval(val_a)<bot_cmd_eval(val_b))
\r
519 self.bot_cmd_condition_status |= CMD_CONDITION_TRUE;
\r
521 self.bot_cmd_condition_status |= CMD_CONDITION_FALSE;
\r
523 return CMD_STATUS_FINISHED;
\r
527 if(bot_cmd_eval(expr))
\r
528 self.bot_cmd_condition_status |= CMD_CONDITION_TRUE;
\r
530 self.bot_cmd_condition_status |= CMD_CONDITION_FALSE;
\r
532 return CMD_STATUS_FINISHED;
535 float bot_cmd_else()
\r
537 self.bot_cmd_condition_status &~= CMD_CONDITION_TRUE_BLOCK;
\r
538 self.bot_cmd_condition_status |= CMD_CONDITION_FALSE_BLOCK;
\r
539 return CMD_STATUS_FINISHED;
\r
544 self.bot_cmd_condition_status = CMD_CONDITION_NONE;
\r
545 return CMD_STATUS_FINISHED;
\r
548 float bot_cmd_resetaim()
\r
550 self.v_angle = '0 0 0';
\r
551 return CMD_STATUS_FINISHED;
\r
554 .float bot_cmd_aim_begintime;
\r
555 .float bot_cmd_aim_endtime;
\r
556 .vector bot_cmd_aim_begin;
\r
557 .vector bot_cmd_aim_end;
\r
559 float bot_cmd_aim()
\r
561 // Current direction
\r
562 if(self.bot_cmd_aim_endtime)
\r
564 local float progress;
\r
566 progress = min(1 - (self.bot_cmd_aim_endtime - time) / (self.bot_cmd_aim_endtime - self.bot_cmd_aim_begintime),1);
567 self.v_angle = self.bot_cmd_aim_begin + ((self.bot_cmd_aim_end - self.bot_cmd_aim_begin) * progress);
\r
569 if(time>=self.bot_cmd_aim_endtime)
\r
571 self.bot_cmd_aim_endtime = 0;
\r
572 return CMD_STATUS_FINISHED;
\r
575 return CMD_STATUS_EXECUTING;
\r
578 // New aiming direction
\r
579 local string parms;
\r
580 local float tokens, step;
\r
582 parms = bot_cmd_getparm_string();
\r
584 tokens = tokenizebyseparator(parms, " ");
588 self.v_angle_x -= stof(argv(1));
589 self.v_angle_y += stof(argv(0));
590 return CMD_STATUS_FINISHED;
593 if(tokens<1||tokens>3)
\r
594 return CMD_STATUS_ERROR;
\r
596 step = stof(argv(2));
598 self.bot_cmd_aim_begin = self.v_angle;
600 self.bot_cmd_aim_end_x = self.v_angle_x - stof(argv(1));
\r
601 self.bot_cmd_aim_end_y = self.v_angle_y + stof(argv(0));
\r
602 self.bot_cmd_aim_end_z = 0;
\r
604 self.bot_cmd_aim_begintime = time;
\r
605 self.bot_cmd_aim_endtime = time + step;
\r
607 return CMD_STATUS_EXECUTING;
\r
612 #define BOT_CMD_KEY_NONE 0
613 #define BOT_CMD_KEY_FORWARD 1
614 #define BOT_CMD_KEY_BACKWARD 2
615 #define BOT_CMD_KEY_RIGHT 4
616 #define BOT_CMD_KEY_LEFT 8
617 #define BOT_CMD_KEY_JUMP 16
618 #define BOT_CMD_KEY_ATTACK1 32
619 #define BOT_CMD_KEY_ATTACK2 64
620 #define BOT_CMD_KEY_USE 128
621 #define BOT_CMD_KEY_HOOK 256
622 #define BOT_CMD_KEY_CROUCH 512
624 float bot_presskeys()
626 self.movement = '0 0 0';
628 if(self.bot_cmd_keys == BOT_CMD_KEY_NONE)
631 if(self.bot_cmd_keys & BOT_CMD_KEY_FORWARD)
632 self.movement_x = cvar("sv_maxspeed");
633 else if(self.bot_cmd_keys & BOT_CMD_KEY_BACKWARD)
634 self.movement_x = -cvar("sv_maxspeed");
636 if(self.bot_cmd_keys & BOT_CMD_KEY_RIGHT)
637 self.movement_y = cvar("sv_maxspeed");
638 else if(self.bot_cmd_keys & BOT_CMD_KEY_LEFT)
639 self.movement_y = -cvar("sv_maxspeed");
641 if(self.bot_cmd_keys & BOT_CMD_KEY_JUMP)
642 self.BUTTON_JUMP = TRUE;
644 if(self.bot_cmd_keys & BOT_CMD_KEY_CROUCH)
645 self.BUTTON_CROUCH = TRUE;
647 if(self.bot_cmd_keys & BOT_CMD_KEY_ATTACK1)
648 self.BUTTON_ATCK = TRUE;
650 if(self.bot_cmd_keys & BOT_CMD_KEY_ATTACK2)
651 self.BUTTON_ATCK2 = TRUE;
653 if(self.bot_cmd_keys & BOT_CMD_KEY_USE)
654 self.BUTTON_USE = TRUE;
660 float bot_cmd_keypress_handler(string key, float enabled)
666 self.bot_cmd_keys = power2of(20) - 1; // >:)
668 self.bot_cmd_keys = BOT_CMD_KEY_NONE;
\r
672 self.bot_cmd_keys |= BOT_CMD_KEY_FORWARD;
673 self.bot_cmd_keys &~= BOT_CMD_KEY_BACKWARD;
676 self.bot_cmd_keys &~= BOT_CMD_KEY_FORWARD;
681 self.bot_cmd_keys |= BOT_CMD_KEY_BACKWARD;
682 self.bot_cmd_keys &~= BOT_CMD_KEY_FORWARD;
685 self.bot_cmd_keys &~= BOT_CMD_KEY_BACKWARD;
690 self.bot_cmd_keys |= BOT_CMD_KEY_LEFT;
691 self.bot_cmd_keys &~= BOT_CMD_KEY_RIGHT;
694 self.bot_cmd_keys &~= BOT_CMD_KEY_LEFT;
699 self.bot_cmd_keys |= BOT_CMD_KEY_RIGHT;
700 self.bot_cmd_keys &~= BOT_CMD_KEY_LEFT;
703 self.bot_cmd_keys &~= BOT_CMD_KEY_RIGHT;
707 self.bot_cmd_keys |= BOT_CMD_KEY_JUMP;
709 self.bot_cmd_keys &~= BOT_CMD_KEY_JUMP;
713 self.bot_cmd_keys |= BOT_CMD_KEY_CROUCH;
715 self.bot_cmd_keys &~= BOT_CMD_KEY_CROUCH;
719 self.bot_cmd_keys |= BOT_CMD_KEY_ATTACK1;
721 self.bot_cmd_keys &~= BOT_CMD_KEY_ATTACK1;
725 self.bot_cmd_keys |= BOT_CMD_KEY_ATTACK2;
727 self.bot_cmd_keys &~= BOT_CMD_KEY_ATTACK2;
731 self.bot_cmd_keys |= BOT_CMD_KEY_USE;
733 self.bot_cmd_keys &~= BOT_CMD_KEY_USE;
739 return CMD_STATUS_FINISHED;
742 float bot_cmd_presskey()
746 key = bot_cmd_getparm_string();
748 bot_cmd_keypress_handler(key,TRUE);
750 return CMD_STATUS_FINISHED;
753 float bot_cmd_releasekey()
757 key = bot_cmd_getparm_string();
759 return bot_cmd_keypress_handler(key,FALSE);
762 float bot_cmd_pause()
767 self.BUTTON_ATCK = 0;
768 self.BUTTON_JUMP = 0;
769 self.BUTTON_HOOK = 0;
770 self.BUTTON_CHAT = 0;
771 self.BUTTON_ATCK2 = 0;
772 self.BUTTON_CROUCH = 0;
774 self.movement = '0 0 0';
775 self.bot_cmd_keys = BOT_CMD_KEY_NONE;
777 self.bot_exec_status = self.bot_exec_status | BOT_EXEC_STATUS_PAUSED;
778 return CMD_STATUS_FINISHED;
781 void bot_command_executed()
784 index = self.bot_cmd_execution_index;
786 self.(bot_cmd[index])=BOT_CMD_NULL;
788 if(index==BOT_CMD_QUEUE_SIZE-1)
789 self.bot_cmd_execution_index = 0;
791 self.bot_cmd_execution_index += 1;
794 // This function should be (the only) called directly from the bot ai loop
\r
795 // It maps commands to functions and deal with complex interactions between commands and execution states
\r
796 // NOTE: Of course you need to include your command here too :)
\r
797 float bot_execute_commands()
\r
799 local float cmd, status, index, ispressingkey;
\r
801 index = self.bot_cmd_execution_index;
\r
803 // Keep pressing keys raised by the "presskey" command
804 ispressingkey = bot_presskeys();
806 // Ignore all commands except continue when the bot is paused
\r
807 if(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED)
\r
808 if(self.bot_cmd[index]!=BOT_CMD_CONTINUE)
\r
810 if(self.bot_cmd[index]!=BOT_CMD_NULL)
\r
812 bot_command_executed();
813 print( "WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.\n");
\r
819 if not(self.bot_cmd[index]==BOT_CMD_FI||self.bot_cmd[index]==BOT_CMD_ELSE)
\r
820 if(self.bot_cmd_condition_status & CMD_CONDITION_TRUE && self.bot_cmd_condition_status & CMD_CONDITION_FALSE_BLOCK)
\r
822 bot_command_executed();
\r
825 else if(self.bot_cmd_condition_status & CMD_CONDITION_FALSE && self.bot_cmd_condition_status & CMD_CONDITION_TRUE_BLOCK)
\r
827 bot_command_executed();
\r
831 // Map commands to functions
832 cmd = self.bot_cmd[index];
\r
836 return ispressingkey;
838 case BOT_CMD_PAUSE:
\r
839 status = bot_cmd_pause();
\r
841 case BOT_CMD_CONTINUE:
\r
842 status = bot_cmd_continue();
\r
845 status = bot_cmd_wait();
\r
848 status = bot_cmd_turn();
\r
850 case BOT_CMD_MOVETO:
\r
851 // status = bot.bot_cmd_moveto();
\r
852 status = CMD_STATUS_FINISHED;
\r
854 case BOT_CMD_RESETGOAL:
855 // status = bot.cmd_resetgoal();
\r
856 status = CMD_STATUS_FINISHED;
\r
859 status = bot_cmd_raw();
\r
862 status = bot_cmd_if();
\r
865 status = bot_cmd_else();
\r
868 status = bot_cmd_fi();
\r
870 case BOT_CMD_RESETAIM:
\r
871 status = bot_cmd_resetaim();
\r
874 status = bot_cmd_aim();
\r
876 case BOT_CMD_PRESSKEY:
877 status = bot_cmd_presskey();
879 case BOT_CMD_RELEASEKEY:
880 status = bot_cmd_releasekey();
882 case BOT_CMD_SELECTWEAPON:
883 status = bot_cmd_select_weapon();
885 case BOT_CMD_IMPULSE:
\r
886 status = bot_cmd_impulse();
\r
889 print(strcat("ERROR: Invalid command on queue with id '",ftos(cmd),"'\n"));
890 self.(bot_cmd[index]) = BOT_CMD_NULL;
\r
894 if (status==CMD_STATUS_ERROR)
895 print(strcat("ERROR: The command '",bot_cmd_string[cmd],"' returned an error status\n"));
897 // Move execution pointer
898 if not(status==CMD_STATUS_EXECUTING)
900 if(cvar("g_debug_bot_commands"))
904 switch(bot_cmd_parm_type[cmd])
906 case BOT_CMD_PARAMETER_FLOAT:
907 parms = ftos(bot_cmd_getparm_float());
909 case BOT_CMD_PARAMETER_STRING:
910 parms = bot_cmd_getparm_string();
912 case BOT_CMD_PARAMETER_VECTOR:
913 parms = vtos(bot_cmd_getparm_vector());
919 clientcommand(self,strcat("say ^7", bot_cmd_string[cmd]," ",parms,"\n"));
922 bot_command_executed();