X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fscripting.qc;h=72951cd6628b36e574d77b98abac0b2bfd2d6a0b;hp=f984f29b6b4facf819418946c15c6bfd8152d639;hb=96e1acc3050bcb718e2f06702e5b88a60459a015;hpb=451c0fbf5473c6acc88bafaa0e9c14e5afd3764e diff --git a/qcsrc/server/bot/scripting.qc b/qcsrc/server/bot/scripting.qc index f984f29b6..72951cd66 100644 --- a/qcsrc/server/bot/scripting.qc +++ b/qcsrc/server/bot/scripting.qc @@ -1,3 +1,8 @@ +#include "scripting.qh" +#include "../_all.qh" + +#include "bot.qh" + .float bot_cmdqueuebuf_allocated; .float bot_cmdqueuebuf; .float bot_cmdqueuebuf_start; @@ -8,8 +13,8 @@ void bot_clearqueue(entity bot) if(!bot.bot_cmdqueuebuf_allocated) return; buf_del(bot.bot_cmdqueuebuf); - bot.bot_cmdqueuebuf_allocated = FALSE; - dprint("bot ", bot.netname, " queue cleared\n"); + bot.bot_cmdqueuebuf_allocated = false; + LOG_TRACE("bot ", bot.netname, " queue cleared\n"); } void bot_queuecommand(entity bot, string cmdstring) @@ -17,7 +22,7 @@ void bot_queuecommand(entity bot, string cmdstring) if(!bot.bot_cmdqueuebuf_allocated) { bot.bot_cmdqueuebuf = buf_create(); - bot.bot_cmdqueuebuf_allocated = TRUE; + bot.bot_cmdqueuebuf_allocated = true; bot.bot_cmdqueuebuf_start = 0; bot.bot_cmdqueuebuf_end = 0; } @@ -39,7 +44,7 @@ void bot_queuecommand(entity bot, string cmdstring) if(cmdstr == "sound") { // find the LAST word - for(;;) + for (;;) { sp = strstrofs(parm, " ", 0); if(sp < 0) @@ -91,16 +96,16 @@ float bot_havecommand(entity bot, float idx) return 1; } -#define MAX_BOT_PLACES 4 +const int MAX_BOT_PLACES = 4; .float bot_places_count; .entity bot_places[MAX_BOT_PLACES]; .string bot_placenames[MAX_BOT_PLACES]; entity bot_getplace(string placename) -{ +{SELFPARAM(); entity e; if(substring(placename, 0, 1) == "@") { - float i, p; + int i, p; placename = substring(placename, 1, -1); string s, s2; for(i = 0; i < self.bot_places_count; ++i) @@ -118,7 +123,7 @@ entity bot_getplace(string placename) } e = find(world, targetname, s); if(!e) - print("invalid place ", s, "\n"); + LOG_INFO("invalid place ", s, "\n"); if(i < MAX_BOT_PLACES) { self.(bot_placenames[i]) = strzone(placename); @@ -131,74 +136,12 @@ entity bot_getplace(string placename) { e = find(world, targetname, placename); if(!e) - print("invalid place ", placename, "\n"); + LOG_INFO("invalid place ", placename, "\n"); return e; } } -// NOTE: New commands should be added here. Do not forget to update BOT_CMD_COUNTER -#define BOT_CMD_NULL 0 -#define BOT_CMD_PAUSE 1 -#define BOT_CMD_CONTINUE 2 -#define BOT_CMD_WAIT 3 -#define BOT_CMD_TURN 4 -#define BOT_CMD_MOVETO 5 -#define BOT_CMD_RESETGOAL 6 // Not implemented yet -#define BOT_CMD_CC 7 -#define BOT_CMD_IF 8 -#define BOT_CMD_ELSE 9 -#define BOT_CMD_FI 10 -#define BOT_CMD_RESETAIM 11 -#define BOT_CMD_AIM 12 -#define BOT_CMD_PRESSKEY 13 -#define BOT_CMD_RELEASEKEY 14 -#define BOT_CMD_SELECTWEAPON 15 -#define BOT_CMD_IMPULSE 16 -#define BOT_CMD_WAIT_UNTIL 17 -#define BOT_CMD_MOVETOTARGET 18 -#define BOT_CMD_AIMTARGET 19 -#define BOT_CMD_BARRIER 20 -#define BOT_CMD_CONSOLE 21 -#define BOT_CMD_SOUND 22 -#define BOT_CMD_DEBUG_ASSERT_CANFIRE 23 -#define BOT_CMD_WHILE 24 // TODO: Not implemented yet -#define BOT_CMD_WEND 25 // TODO: Not implemented yet -#define BOT_CMD_CHASE 26 // TODO: Not implemented yet - -#define BOT_CMD_COUNTER 24 // Update this value if you add/remove a command - -// NOTE: Following commands should be implemented on the bot ai -// If a new command should be handled by the target ai(s) please declare it here -.float(vector) cmd_moveto; -.float() cmd_resetgoal; - -// -#define BOT_CMD_PARAMETER_NONE 0 -#define BOT_CMD_PARAMETER_FLOAT 1 -#define BOT_CMD_PARAMETER_STRING 2 -#define BOT_CMD_PARAMETER_VECTOR 3 - -float bot_cmds_initialized; -float bot_cmd_parm_type[BOT_CMD_COUNTER]; -string bot_cmd_string[BOT_CMD_COUNTER]; - -// Bots command queue -entity bot_cmd; // global current command -.entity bot_cmd_current; // current command of this bot - -.float is_bot_cmd; // Tells if the entity is a bot command -.float bot_cmd_index; // Position of the command in the queue -.float bot_cmd_type; // If of command (see the BOT_CMD_* defines) -.float bot_cmd_parm_float; // Field to store a float parameter -.string bot_cmd_parm_string; // Field to store a string parameter -.vector bot_cmd_parm_vector; // Field to store a vector parameter - -float bot_barriertime; -.float bot_barrier; - -.float bot_cmd_execution_index; // Position in the queue of the command to be executed - // Initialize global commands list // NOTE: New commands should be initialized here void bot_commands_init() @@ -275,7 +218,7 @@ void bot_commands_init() bot_cmd_string[BOT_CMD_DEBUG_ASSERT_CANFIRE] = "debug_assert_canfire"; bot_cmd_parm_type[BOT_CMD_DEBUG_ASSERT_CANFIRE] = BOT_CMD_PARAMETER_FLOAT; - bot_cmds_initialized = TRUE; + bot_cmds_initialized = true; } // Returns first bot with matching name @@ -321,7 +264,7 @@ entity find_bot_by_number(float number) float bot_decodecommand(string cmdstring) { - float cmd_parm_type, i; + float cmd_parm_type; float sp; string parm; @@ -339,6 +282,7 @@ float bot_decodecommand(string cmdstring) if(!bot_cmds_initialized) bot_commands_init(); + int i; for(i=1;i \n")); + LOG_INFO(strcat("Command: ",bot_cmd_string[i],"\nParameter: <",stype,"> \n")); - print("Description: "); + LOG_INFO("Description: "); switch(i) { case BOT_CMD_PAUSE: - print("Stops the bot completely. Any command other than 'continue' will be ignored."); + LOG_INFO("Stops the bot completely. Any command other than 'continue' will be ignored."); break; case BOT_CMD_CONTINUE: - print("Disable paused status"); + LOG_INFO("Disable paused status"); break; case BOT_CMD_WAIT: - print("Pause command parsing and bot ai for N seconds. Pressed key will remain pressed"); + LOG_INFO("Pause command parsing and bot ai for N seconds. Pressed key will remain pressed"); break; case BOT_CMD_WAIT_UNTIL: - print("Pause command parsing and bot ai until time is N from the last barrier. Pressed key will remain pressed"); + LOG_INFO("Pause command parsing and bot ai until time is N from the last barrier. Pressed key will remain pressed"); break; case BOT_CMD_BARRIER: - print("Waits till all bots that have a command queue reach this command. Pressed key will remain pressed"); + LOG_INFO("Waits till all bots that have a command queue reach this command. Pressed key will remain pressed"); break; case BOT_CMD_TURN: - print("Look to the right or left N degrees. For turning to the left use positive numbers."); + LOG_INFO("Look to the right or left N degrees. For turning to the left use positive numbers."); break; case BOT_CMD_MOVETO: - print("Walk to an specific coordinate on the map. Usage: moveto \"x y z\""); + LOG_INFO("Walk to an specific coordinate on the map. Usage: moveto \"x y z\""); break; case BOT_CMD_MOVETOTARGET: - print("Walk to the specific target on the map"); + LOG_INFO("Walk to the specific target on the map"); break; case BOT_CMD_RESETGOAL: - print("Resets the goal stack"); + LOG_INFO("Resets the goal stack"); break; case BOT_CMD_CC: - print("Execute client command. Examples: cc \"say something\"; cc god; cc \"name newnickname\"; cc kill;"); + LOG_INFO("Execute client command. Examples: cc \"say something\"; cc god; cc \"name newnickname\"; cc kill;"); break; case BOT_CMD_IF: - print("Perform simple conditional execution.\n"); - print("Syntax: \n"); - print(" sv_cmd .. if \"condition\"\n"); - print(" sv_cmd .. \n"); - print(" sv_cmd .. \n"); - print(" sv_cmd .. else\n"); - print(" sv_cmd .. \n"); - print(" sv_cmd .. \n"); - print(" sv_cmd .. fi\n"); - print("Conditions: a=b, a>b, a50; if health>cvar.g_balance_laser_primary_damage; if flagcarrier;"); + LOG_INFO("Perform simple conditional execution.\n"); + LOG_INFO("Syntax: \n"); + LOG_INFO(" sv_cmd .. if \"condition\"\n"); + LOG_INFO(" sv_cmd .. \n"); + LOG_INFO(" sv_cmd .. \n"); + LOG_INFO(" sv_cmd .. else\n"); + LOG_INFO(" sv_cmd .. \n"); + LOG_INFO(" sv_cmd .. \n"); + LOG_INFO(" sv_cmd .. fi\n"); + LOG_INFO("Conditions: a=b, a>b, a50; if health>cvar.g_balance_laser_primary_damage; if flagcarrier;"); break; case BOT_CMD_RESETAIM: - print("Points the aim to the coordinates x,y 0,0"); + LOG_INFO("Points the aim to the coordinates x,y 0,0"); break; case BOT_CMD_AIM: - print("Move the aim x/y (horizontal/vertical) degrees relatives to the bot\n"); - print("There is a 3rd optional parameter telling in how many seconds the aim has to reach the new position\n"); - print("Examples: aim \"90 0\" // Turn 90 degrees inmediately (positive numbers move to the left/up)\n"); - print(" aim \"0 90 2\" // Will gradually look to the sky in the next two seconds"); + LOG_INFO("Move the aim x/y (horizontal/vertical) degrees relatives to the bot\n"); + LOG_INFO("There is a 3rd optional parameter telling in how many seconds the aim has to reach the new position\n"); + LOG_INFO("Examples: aim \"90 0\" // Turn 90 degrees inmediately (positive numbers move to the left/up)\n"); + LOG_INFO(" aim \"0 90 2\" // Will gradually look to the sky in the next two seconds"); break; case BOT_CMD_AIMTARGET: - print("Points the aim to given target"); + LOG_INFO("Points the aim to given target"); break; case BOT_CMD_PRESSKEY: - print("Press one of the following keys: forward, backward, left, right, jump, crouch, attack1, attack2, use\n"); - print("Multiple keys can be pressed at time (with many presskey calls) and it will remain pressed until the command \"releasekey\" is called"); - print("Note: The script will not return the control to the bot ai until all keys are released"); + LOG_INFO("Press one of the following keys: forward, backward, left, right, jump, crouch, attack1, attack2, use\n"); + LOG_INFO("Multiple keys can be pressed at time (with many presskey calls) and it will remain pressed until the command \"releasekey\" is called"); + LOG_INFO("Note: The script will not return the control to the bot ai until all keys are released"); break; case BOT_CMD_RELEASEKEY: - print("Release previoulsy used keys. Use the parameter \"all\" to release all keys"); + LOG_INFO("Release previoulsy used keys. Use the parameter \"all\" to release all keys"); break; case BOT_CMD_SOUND: - print("play sound file at bot location"); + LOG_INFO("play sound file at bot location"); break; case BOT_CMD_DEBUG_ASSERT_CANFIRE: - print("verify the state of the weapon entity"); + LOG_INFO("verify the state of the weapon entity"); break; default: - print("This command has no description yet."); + LOG_INFO("This command has no description yet."); break; } - print("\n"); + LOG_INFO("\n"); } } void bot_list_commands() { - float i; + int i; string ptype; if(!bot_cmds_initialized) bot_commands_init(); - print("List of all available commands:\n"); - print(" Command - Parameter Type\n"); + LOG_INFO("List of all available commands:\n"); + LOG_INFO(" Command - Parameter Type\n"); for(i=1;i \n")); + LOG_INFO(strcat(" ",bot_cmd_string[i]," - <",ptype,"> \n")); } } // Commands code -.float bot_exec_status; - -#define BOT_EXEC_STATUS_IDLE 0 -#define BOT_EXEC_STATUS_PAUSED 1 -#define BOT_EXEC_STATUS_WAITING 2 - -#define CMD_STATUS_EXECUTING 0 -#define CMD_STATUS_FINISHED 1 -#define CMD_STATUS_ERROR 2 +.int bot_exec_status; void SV_ParseClientCommand(string s); float bot_cmd_cc() @@ -544,20 +480,20 @@ float bot_cmd_cc() } float bot_cmd_impulse() -{ +{SELFPARAM(); self.impulse = bot_cmd.bot_cmd_parm_float; return CMD_STATUS_FINISHED; } float bot_cmd_continue() -{ +{SELFPARAM(); self.bot_exec_status &= ~BOT_EXEC_STATUS_PAUSED; return CMD_STATUS_FINISHED; } .float bot_cmd_wait_time; float bot_cmd_wait() -{ +{SELFPARAM(); if(self.bot_exec_status & BOT_EXEC_STATUS_WAITING) { if(time>=self.bot_cmd_wait_time) @@ -575,7 +511,7 @@ float bot_cmd_wait() } float bot_cmd_wait_until() -{ +{SELFPARAM(); if(time < bot_cmd.bot_cmd_parm_float + bot_barriertime) { self.bot_exec_status |= BOT_EXEC_STATUS_WAITING; @@ -586,7 +522,7 @@ float bot_cmd_wait_until() } float bot_cmd_barrier() -{ +{SELFPARAM(); entity cl; // 0 = no barrier, 1 = waiting, 2 = waiting finished @@ -625,14 +561,14 @@ float bot_cmd_barrier() } float bot_cmd_turn() -{ - self.v_angle_y = self.v_angle_y + bot_cmd.bot_cmd_parm_float; - self.v_angle_y = self.v_angle_y - floor(self.v_angle_y / 360) * 360; +{SELFPARAM(); + self.v_angle_y = self.v_angle.y + bot_cmd.bot_cmd_parm_float; + self.v_angle_y = self.v_angle.y - floor(self.v_angle.y / 360) * 360; return CMD_STATUS_FINISHED; } float bot_cmd_select_weapon() -{ +{SELFPARAM(); float id; id = bot_cmd.bot_cmd_parm_float; @@ -640,7 +576,7 @@ float bot_cmd_select_weapon() if(id < WEP_FIRST || id > WEP_LAST) return CMD_STATUS_ERROR; - if(client_hasweapon(self, id, TRUE, FALSE)) + if(client_hasweapon(self, id, true, false)) self.switchweapon = id; else return CMD_STATUS_ERROR; @@ -648,16 +584,16 @@ float bot_cmd_select_weapon() return CMD_STATUS_FINISHED; } -.float bot_cmd_condition_status; +.int bot_cmd_condition_status; -#define CMD_CONDITION_NONE 0 -#define CMD_CONDITION_TRUE 1 -#define CMD_CONDITION_FALSE 2 -#define CMD_CONDITION_TRUE_BLOCK 4 -#define CMD_CONDITION_FALSE_BLOCK 8 +const int CMD_CONDITION_NONE = 0; +const int CMD_CONDITION_true = 1; +const int CMD_CONDITION_false = 2; +const int CMD_CONDITION_true_BLOCK = 4; +const int CMD_CONDITION_false_BLOCK = 8; float bot_cmd_eval(string expr) -{ +{SELFPARAM(); // Search for numbers if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0) { @@ -681,24 +617,24 @@ float bot_cmd_eval(string expr) return ((self.flagcarried!=world)); } - print(strcat("ERROR: Unable to convert the expression '",expr,"' into a numeric value\n")); + LOG_INFO(strcat("ERROR: Unable to convert the expression '",expr,"' into a numeric value\n")); return 0; } float bot_cmd_if() -{ +{SELFPARAM(); string expr, val_a, val_b; float cmpofs; if(self.bot_cmd_condition_status != CMD_CONDITION_NONE) { // Only one "if" block is allowed at time - print("ERROR: Only one conditional block can be processed at time"); + LOG_INFO("ERROR: Only one conditional block can be processed at time"); bot_clearqueue(self); return CMD_STATUS_ERROR; } - self.bot_cmd_condition_status |= CMD_CONDITION_TRUE_BLOCK; + self.bot_cmd_condition_status |= CMD_CONDITION_true_BLOCK; // search for operators expr = bot_cmd.bot_cmd_parm_string; @@ -711,9 +647,9 @@ float bot_cmd_if() val_b = substring(expr,cmpofs+1,strlen(expr)); if(bot_cmd_eval(val_a)==bot_cmd_eval(val_b)) - self.bot_cmd_condition_status |= CMD_CONDITION_TRUE; + self.bot_cmd_condition_status |= CMD_CONDITION_true; else - self.bot_cmd_condition_status |= CMD_CONDITION_FALSE; + self.bot_cmd_condition_status |= CMD_CONDITION_false; return CMD_STATUS_FINISHED; } @@ -726,9 +662,9 @@ float bot_cmd_if() val_b = substring(expr,cmpofs+1,strlen(expr)); if(bot_cmd_eval(val_a)>bot_cmd_eval(val_b)) - self.bot_cmd_condition_status |= CMD_CONDITION_TRUE; + self.bot_cmd_condition_status |= CMD_CONDITION_true; else - self.bot_cmd_condition_status |= CMD_CONDITION_FALSE; + self.bot_cmd_condition_status |= CMD_CONDITION_false; return CMD_STATUS_FINISHED; } @@ -741,36 +677,36 @@ float bot_cmd_if() val_b = substring(expr,cmpofs+1,strlen(expr)); if(bot_cmd_eval(val_a) time) @@ -1138,7 +1074,7 @@ float bot_cmd_debug_assert_canfire() if(f) { self.colormod = '8 0 8'; - print("Bot ", self.netname, " using ", self.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(self) - time), " seconds left)\n"); + LOG_INFO("Bot ", self.netname, " using ", self.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(self) - time), " seconds left)\n"); } } else if(self.tuba_note) @@ -1146,7 +1082,7 @@ float bot_cmd_debug_assert_canfire() if(f) { self.colormod = '8 0 0'; - print("Bot ", self.netname, " using ", self.weaponname, " wants to fire, bot still has an active tuba note\n"); + LOG_INFO("Bot ", self.netname, " using ", self.weaponname, " wants to fire, bot still has an active tuba note\n"); } } else @@ -1154,7 +1090,7 @@ float bot_cmd_debug_assert_canfire() if(!f) { self.colormod = '8 8 0'; - print("Bot ", self.netname, " using ", self.weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(self) - time), " seconds left\n"); + LOG_INFO("Bot ", self.netname, " using ", self.weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(self) - time), " seconds left\n"); } } @@ -1164,7 +1100,7 @@ float bot_cmd_debug_assert_canfire() // void bot_command_executed(float rm) -{ +{SELFPARAM(); entity cmd; cmd = bot_cmd; @@ -1176,7 +1112,7 @@ void bot_command_executed(float rm) } void bot_setcurrentcommand() -{ +{SELFPARAM(); bot_cmd = world; if(!self.bot_cmd_current) @@ -1214,7 +1150,6 @@ void bot_setcurrentcommand() void bot_resetqueues() { entity cl; - float i; FOR_EACH_CLIENT(cl) if(cl.isbot) { @@ -1222,7 +1157,7 @@ void bot_resetqueues() bot_clearqueue(cl); // also, cancel all barriers cl.bot_barrier = 0; - for(i = 0; i < cl.bot_places_count; ++i) + for(int i = 0; i < cl.bot_places_count; ++i) { strunzone(cl.(bot_placenames[i])); cl.(bot_placenames[i]) = string_null; @@ -1236,7 +1171,7 @@ void bot_resetqueues() // Here we map commands to functions and deal with complex interactions between commands and execution states // NOTE: Of course you need to include your commands here too :) float bot_execute_commands_once() -{ +{SELFPARAM(); float status, ispressingkey; // Find command @@ -1247,7 +1182,7 @@ float bot_execute_commands_once() // (namely, it means you cannot make a bot "normal" ever again) // to keep a bot walking for a while, use the "wait" bot command if(bot_cmd == world) - return FALSE; + return false; // Ignore all commands except continue when the bot is paused if(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED) @@ -1255,8 +1190,8 @@ float bot_execute_commands_once() { if(bot_cmd.bot_cmd_type!=BOT_CMD_NULL) { - bot_command_executed(TRUE); - print( "WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.\n"); + bot_command_executed(true); + LOG_INFO( "WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.\n"); } return 1; } @@ -1266,14 +1201,14 @@ float bot_execute_commands_once() // Handle conditions if (!(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE)) - if(self.bot_cmd_condition_status & CMD_CONDITION_TRUE && self.bot_cmd_condition_status & CMD_CONDITION_FALSE_BLOCK) + if(self.bot_cmd_condition_status & CMD_CONDITION_true && self.bot_cmd_condition_status & CMD_CONDITION_false_BLOCK) { - bot_command_executed(TRUE); + bot_command_executed(true); return -1; } - else if(self.bot_cmd_condition_status & CMD_CONDITION_FALSE && self.bot_cmd_condition_status & CMD_CONDITION_TRUE_BLOCK) + else if(self.bot_cmd_condition_status & CMD_CONDITION_false && self.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK) { - bot_command_executed(TRUE); + bot_command_executed(true); return -1; } @@ -1354,12 +1289,12 @@ float bot_execute_commands_once() status = bot_cmd_debug_assert_canfire(); break; default: - print(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n")); + LOG_INFO(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n")); return 0; } if (status==CMD_STATUS_ERROR) - print(strcat("ERROR: The command '",bot_cmd_string[bot_cmd.bot_cmd_type],"' returned an error status\n")); + LOG_INFO(strcat("ERROR: The command '",bot_cmd_string[bot_cmd.bot_cmd_type],"' returned an error status\n")); // Move execution pointer if(status==CMD_STATUS_EXECUTING) @@ -1390,7 +1325,7 @@ float bot_execute_commands_once() clientcommand(self,strcat("say ^7", bot_cmd_string[bot_cmd.bot_cmd_type]," ",parms,"\n")); } - bot_command_executed(TRUE); + bot_command_executed(true); } if(status == CMD_STATUS_FINISHED)