X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Fscripting.qc;h=f975f74e56743ec7472ff04c8488e8f890fe7888;hp=3f53d2b9f23456677bc33676d22f06f658ef0634;hb=0f6c4bee8db75b0aded48382af1c2693b19624de;hpb=e32f518af0bfa21335fe0de1320e33ef78551bcb diff --git a/qcsrc/server/bot/default/scripting.qc b/qcsrc/server/bot/default/scripting.qc index 3f53d2b9f..f975f74e5 100644 --- a/qcsrc/server/bot/default/scripting.qc +++ b/qcsrc/server/bot/default/scripting.qc @@ -1,5 +1,15 @@ #include "scripting.qh" +#include "cvars.qh" + +#include +#include +#include + +#include "bot.qh" + +.int state; + .float bot_cmdqueuebuf_allocated; .float bot_cmdqueuebuf; .float bot_cmdqueuebuf_start; @@ -11,7 +21,7 @@ void bot_clearqueue(entity bot) return; buf_del(bot.bot_cmdqueuebuf); bot.bot_cmdqueuebuf_allocated = false; - LOG_TRACE("bot ", bot.netname, " queue cleared\n"); + LOG_TRACE("bot ", bot.netname, " queue cleared"); } void bot_queuecommand(entity bot, string cmdstring) @@ -82,33 +92,33 @@ string bot_readcommand(entity bot, float idx) return bufstr_get(bot.bot_cmdqueuebuf, idx); } -float bot_havecommand(entity bot, float idx) +bool bot_havecommand(entity this, int idx) { - if(!bot.bot_cmdqueuebuf_allocated) - return 0; - if(idx < bot.bot_cmdqueuebuf_start) - return 0; - if(idx >= bot.bot_cmdqueuebuf_end) - return 0; - return 1; + if(!this.bot_cmdqueuebuf_allocated) + return false; + if(idx < this.bot_cmdqueuebuf_start) + return false; + if(idx >= this.bot_cmdqueuebuf_end) + return false; + return true; } 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 bot_getplace(entity this, string placename) +{ entity e; if(substring(placename, 0, 1) == "@") { int i, p; placename = substring(placename, 1, -1); string s, s2; - for(i = 0; i < self.bot_places_count; ++i) - if(self.(bot_placenames[i]) == placename) - return self.(bot_places[i]); - // now: i == self.bot_places_count + for(i = 0; i < this.bot_places_count; ++i) + if(this.(bot_placenames[i]) == placename) + return this.(bot_places[i]); + // now: i == this.bot_places_count s = s2 = cvar_string(placename); p = strstrofs(s2, " ", 0); if(p >= 0) @@ -118,20 +128,20 @@ entity bot_getplace(string placename) cvar_set(placename, strcat(substring(s2, p+1, -1), " ", s)); //print("places: ", placename, " := ", cvar_string(placename), "\n"); } - e = find(world, targetname, s); + e = find(NULL, targetname, s); if(!e) LOG_INFO("invalid place ", s, "\n"); if(i < MAX_BOT_PLACES) { - self.(bot_placenames[i]) = strzone(placename); - self.(bot_places[i]) = e; - self.bot_places_count += 1; + this.(bot_placenames[i]) = strzone(placename); + this.(bot_places[i]) = e; + this.bot_places_count += 1; } return e; } else { - e = find(world, targetname, placename); + e = find(NULL, targetname, placename); if(!e) LOG_INFO("invalid place ", placename, "\n"); return e; @@ -221,19 +231,12 @@ void bot_commands_init() // Returns first bot with matching name entity find_bot_by_name(string name) { - entity bot; - - bot = findchainflags(flags, FL_CLIENT); - while (bot) + FOREACH_CLIENT(IS_BOT_CLIENT(it) && it.netname == name, { - if(IS_BOT_CLIENT(bot)) - if(bot.netname==name) - return bot; - - bot = bot.chain; - } + return it; + }); - return world; + return NULL; } // Returns a bot by number on list @@ -243,9 +246,9 @@ entity find_bot_by_number(float number) float c = 0; if(!number) - return world; + return NULL; - bot = findchainflags(flags, FL_CLIENT); + bot = findchainflags(flags, FL_CLIENT); // TODO: doesn't findchainflags loop backwards through entities? while (bot) { if(IS_BOT_CLIENT(bot)) @@ -256,7 +259,7 @@ entity find_bot_by_number(float number) bot = bot.chain; } - return world; + return NULL; } float bot_decodecommand(string cmdstring) @@ -469,113 +472,120 @@ void bot_list_commands() // Commands code .int bot_exec_status; -void SV_ParseClientCommand(string s); -float bot_cmd_cc() +float bot_cmd_cc(entity this) { - SV_ParseClientCommand(bot_cmd.bot_cmd_parm_string); + SV_ParseClientCommand(this, bot_cmd.bot_cmd_parm_string); return CMD_STATUS_FINISHED; } -float bot_cmd_impulse() -{SELFPARAM(); - self.impulse = bot_cmd.bot_cmd_parm_float; +float bot_cmd_impulse(entity this) +{ + this.impulse = bot_cmd.bot_cmd_parm_float; return CMD_STATUS_FINISHED; } -float bot_cmd_continue() -{SELFPARAM(); - self.bot_exec_status &= ~BOT_EXEC_STATUS_PAUSED; +float bot_cmd_continue(entity this) +{ + bot_relinkplayerlist(); + this.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) +float bot_cmd_wait(entity this) +{ + if(this.bot_exec_status & BOT_EXEC_STATUS_WAITING) { - if(time>=self.bot_cmd_wait_time) + if(time>=this.bot_cmd_wait_time) { - self.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING; + this.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING; return CMD_STATUS_FINISHED; } else return CMD_STATUS_EXECUTING; } - self.bot_cmd_wait_time = time + bot_cmd.bot_cmd_parm_float; - self.bot_exec_status |= BOT_EXEC_STATUS_WAITING; + this.bot_cmd_wait_time = time + bot_cmd.bot_cmd_parm_float; + this.bot_exec_status |= BOT_EXEC_STATUS_WAITING; return CMD_STATUS_EXECUTING; } -float bot_cmd_wait_until() -{SELFPARAM(); +float bot_cmd_wait_until(entity this) +{ if(time < bot_cmd.bot_cmd_parm_float + bot_barriertime) { - self.bot_exec_status |= BOT_EXEC_STATUS_WAITING; + this.bot_exec_status |= BOT_EXEC_STATUS_WAITING; return CMD_STATUS_EXECUTING; } - self.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING; + this.bot_exec_status &= ~BOT_EXEC_STATUS_WAITING; return CMD_STATUS_FINISHED; } -float bot_cmd_barrier() -{SELFPARAM(); - entity cl; - +float bot_cmd_barrier(entity this) +{ // 0 = no barrier, 1 = waiting, 2 = waiting finished - if(self.bot_barrier == 0) // initialization + if(this.bot_barrier == 0) // initialization { - self.bot_barrier = 1; + this.bot_barrier = 1; - //self.colormod = '4 4 0'; + //this.colormod = '4 4 0'; } - if(self.bot_barrier == 1) // find other bots + if(this.bot_barrier == 1) // find other bots { - FOR_EACH_CLIENT(cl) if(cl.isbot) - { - if(cl.bot_cmdqueuebuf_allocated) - if(cl.bot_barrier != 1) - return CMD_STATUS_EXECUTING; // not all are at the barrier yet - } + FOREACH_CLIENT(it.isbot, LAMBDA( + if(it.bot_cmdqueuebuf_allocated) + if(it.bot_barrier != 1) + return CMD_STATUS_EXECUTING; // not all are at the barrier yet + )); // all bots hit the barrier! - FOR_EACH_CLIENT(cl) if(cl.isbot) - { - cl.bot_barrier = 2; // acknowledge barrier - } + + // acknowledge barrier + FOREACH_CLIENT(it.isbot, LAMBDA(it.bot_barrier = 2)); bot_barriertime = time; } // if we get here, the barrier is finished // so end it... - self.bot_barrier = 0; - //self.colormod = '0 0 0'; + this.bot_barrier = 0; + //this.colormod = '0 0 0'; return CMD_STATUS_FINISHED; } -float bot_cmd_turn() -{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; +float bot_cmd_turn(entity this) +{ + this.v_angle_y = this.v_angle.y + bot_cmd.bot_cmd_parm_float; + this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360; return CMD_STATUS_FINISHED; } -float bot_cmd_select_weapon() -{SELFPARAM(); - float id; - - id = bot_cmd.bot_cmd_parm_float; +float bot_cmd_select_weapon(entity this) +{ + float id = bot_cmd.bot_cmd_parm_float; if(id < WEP_FIRST || id > WEP_LAST) return CMD_STATUS_ERROR; - if(client_hasweapon(self, id, true, false)) - self.switchweapon = id; - else + bool success = false; + + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(this.(weaponentity).m_weapon == WEP_Null && slot != 0) + continue; + + if(client_hasweapon(this, Weapons_from(id), weaponentity, true, false)) + { + success = true; + this.(weaponentity).m_switchweapon = Weapons_from(id); + } + } + + if(!success) return CMD_STATUS_ERROR; return CMD_STATUS_FINISHED; @@ -589,49 +599,45 @@ 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(); +float bot_cmd_eval(entity this, string expr) +{ // Search for numbers - if(strstrofs("0123456789", substring(expr, 0, 1), 0) >= 0) - { + if(IS_DIGIT(substring(expr, 0, 1))) return stof(expr); - } // Search for cvars if(substring(expr, 0, 5)=="cvar.") - { return cvar(substring(expr, 5, strlen(expr))); - } // Search for fields switch(expr) { case "health": - return self.health; + return this.health; case "speed": - return vlen(self.velocity); + return vlen(this.velocity); case "flagcarrier": - return ((self.flagcarried!=world)); + return ((this.flagcarried!=NULL)); } LOG_INFO(strcat("ERROR: Unable to convert the expression '",expr,"' into a numeric value\n")); return 0; } -float bot_cmd_if() -{SELFPARAM(); +float bot_cmd_if(entity this) +{ string expr, val_a, val_b; float cmpofs; - if(self.bot_cmd_condition_status != CMD_CONDITION_NONE) + if(this.bot_cmd_condition_status != CMD_CONDITION_NONE) { // Only one "if" block is allowed at time LOG_INFO("ERROR: Only one conditional block can be processed at time"); - bot_clearqueue(self); + bot_clearqueue(this); return CMD_STATUS_ERROR; } - self.bot_cmd_condition_status |= CMD_CONDITION_true_BLOCK; + this.bot_cmd_condition_status |= CMD_CONDITION_true_BLOCK; // search for operators expr = bot_cmd.bot_cmd_parm_string; @@ -643,10 +649,10 @@ float bot_cmd_if() val_a = substring(expr,0,cmpofs); 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; + if(bot_cmd_eval(this, val_a)==bot_cmd_eval(this, val_b)) + this.bot_cmd_condition_status |= CMD_CONDITION_true; else - self.bot_cmd_condition_status |= CMD_CONDITION_false; + this.bot_cmd_condition_status |= CMD_CONDITION_false; return CMD_STATUS_FINISHED; } @@ -658,10 +664,10 @@ float bot_cmd_if() val_a = substring(expr,0,cmpofs); 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; + if(bot_cmd_eval(this, val_a)>bot_cmd_eval(this, val_b)) + this.bot_cmd_condition_status |= CMD_CONDITION_true; else - self.bot_cmd_condition_status |= CMD_CONDITION_false; + this.bot_cmd_condition_status |= CMD_CONDITION_false; return CMD_STATUS_FINISHED; } @@ -673,38 +679,38 @@ float bot_cmd_if() val_a = substring(expr,0,cmpofs); val_b = substring(expr,cmpofs+1,strlen(expr)); - if(bot_cmd_eval(val_a)=self.bot_cmd_aim_endtime) + if(time>=this.bot_cmd_aim_endtime) { - self.bot_cmd_aim_endtime = 0; + this.bot_cmd_aim_endtime = 0; return CMD_STATUS_FINISHED; } else @@ -747,28 +753,28 @@ float bot_cmd_aim() if(step == 0) { - self.v_angle_x -= stof(argv(1)); - self.v_angle_y += stof(argv(0)); + this.v_angle_x -= stof(argv(1)); + this.v_angle_y += stof(argv(0)); return CMD_STATUS_FINISHED; } - self.bot_cmd_aim_begin = self.v_angle; + this.bot_cmd_aim_begin = this.v_angle; - self.bot_cmd_aim_end_x = self.v_angle.x - stof(argv(1)); - self.bot_cmd_aim_end_y = self.v_angle.y + stof(argv(0)); - self.bot_cmd_aim_end_z = 0; + this.bot_cmd_aim_end_x = this.v_angle.x - stof(argv(1)); + this.bot_cmd_aim_end_y = this.v_angle.y + stof(argv(0)); + this.bot_cmd_aim_end_z = 0; - self.bot_cmd_aim_begintime = time; - self.bot_cmd_aim_endtime = time + step; + this.bot_cmd_aim_begintime = time; + this.bot_cmd_aim_endtime = time + step; return CMD_STATUS_EXECUTING; } -float bot_cmd_aimtarget() -{SELFPARAM(); - if(self.bot_cmd_aim_endtime) +float bot_cmd_aimtarget(entity this) +{ + if(this.bot_cmd_aim_endtime) { - return bot_cmd_aim(); + return bot_cmd_aim(this); } entity e; @@ -780,7 +786,7 @@ float bot_cmd_aimtarget() tokens = tokenizebyseparator(parms, " "); - e = bot_getplace(argv(0)); + e = bot_getplace(this, argv(0)); if(!e) return CMD_STATUS_ERROR; @@ -788,8 +794,8 @@ float bot_cmd_aimtarget() if(tokens==1) { - self.v_angle = vectoangles(v - (self.origin + self.view_ofs)); - self.v_angle_x = -self.v_angle.x; + this.v_angle = vectoangles(v - (this.origin + this.view_ofs)); + this.v_angle_x = -this.v_angle.x; return CMD_STATUS_FINISHED; } @@ -798,12 +804,12 @@ float bot_cmd_aimtarget() step = stof(argv(1)); - self.bot_cmd_aim_begin = self.v_angle; - self.bot_cmd_aim_end = vectoangles(v - (self.origin + self.view_ofs)); - self.bot_cmd_aim_end_x = -self.bot_cmd_aim_end.x; + this.bot_cmd_aim_begin = this.v_angle; + this.bot_cmd_aim_end = vectoangles(v - (this.origin + this.view_ofs)); + this.bot_cmd_aim_end_x = -this.bot_cmd_aim_end.x; - self.bot_cmd_aim_begintime = time; - self.bot_cmd_aim_endtime = time + step; + this.bot_cmd_aim_begintime = time; + this.bot_cmd_aim_endtime = time + step; return CMD_STATUS_EXECUTING; } @@ -811,153 +817,153 @@ float bot_cmd_aimtarget() .int bot_cmd_keys; const int BOT_CMD_KEY_NONE = 0; -const int BOT_CMD_KEY_FORWARD = 1; -const int BOT_CMD_KEY_BACKWARD = 2; -const int BOT_CMD_KEY_RIGHT = 4; -const int BOT_CMD_KEY_LEFT = 8; -const int BOT_CMD_KEY_JUMP = 16; -const int BOT_CMD_KEY_ATTACK1 = 32; -const int BOT_CMD_KEY_ATTACK2 = 64; -const int BOT_CMD_KEY_USE = 128; -const int BOT_CMD_KEY_HOOK = 256; -const int BOT_CMD_KEY_CROUCH = 512; -const int BOT_CMD_KEY_CHAT = 1024; - -float bot_presskeys() -{SELFPARAM(); - self.movement = '0 0 0'; - self.BUTTON_JUMP = false; - self.BUTTON_CROUCH = false; - self.BUTTON_ATCK = false; - self.BUTTON_ATCK2 = false; - self.BUTTON_USE = false; - self.BUTTON_HOOK = false; - self.BUTTON_CHAT = false; - - if(self.bot_cmd_keys == BOT_CMD_KEY_NONE) +const int BOT_CMD_KEY_FORWARD = BIT(0); +const int BOT_CMD_KEY_BACKWARD = BIT(1); +const int BOT_CMD_KEY_RIGHT = BIT(2); +const int BOT_CMD_KEY_LEFT = BIT(3); +const int BOT_CMD_KEY_JUMP = BIT(4); +const int BOT_CMD_KEY_ATTACK1 = BIT(5); +const int BOT_CMD_KEY_ATTACK2 = BIT(6); +const int BOT_CMD_KEY_USE = BIT(7); +const int BOT_CMD_KEY_HOOK = BIT(8); +const int BOT_CMD_KEY_CROUCH = BIT(9); +const int BOT_CMD_KEY_CHAT = BIT(10); + +bool bot_presskeys(entity this) +{ + this.movement = '0 0 0'; + PHYS_INPUT_BUTTON_JUMP(this) = false; + PHYS_INPUT_BUTTON_CROUCH(this) = false; + PHYS_INPUT_BUTTON_ATCK(this) = false; + PHYS_INPUT_BUTTON_ATCK2(this) = false; + PHYS_INPUT_BUTTON_USE(this) = false; + PHYS_INPUT_BUTTON_HOOK(this) = false; + PHYS_INPUT_BUTTON_CHAT(this) = false; + + if(this.bot_cmd_keys == BOT_CMD_KEY_NONE) return false; - if(self.bot_cmd_keys & BOT_CMD_KEY_FORWARD) - self.movement_x = autocvar_sv_maxspeed; - else if(self.bot_cmd_keys & BOT_CMD_KEY_BACKWARD) - self.movement_x = -autocvar_sv_maxspeed; + if(this.bot_cmd_keys & BOT_CMD_KEY_FORWARD) + this.movement_x = autocvar_sv_maxspeed; + else if(this.bot_cmd_keys & BOT_CMD_KEY_BACKWARD) + this.movement_x = -autocvar_sv_maxspeed; - if(self.bot_cmd_keys & BOT_CMD_KEY_RIGHT) - self.movement_y = autocvar_sv_maxspeed; - else if(self.bot_cmd_keys & BOT_CMD_KEY_LEFT) - self.movement_y = -autocvar_sv_maxspeed; + if(this.bot_cmd_keys & BOT_CMD_KEY_RIGHT) + this.movement_y = autocvar_sv_maxspeed; + else if(this.bot_cmd_keys & BOT_CMD_KEY_LEFT) + this.movement_y = -autocvar_sv_maxspeed; - if(self.bot_cmd_keys & BOT_CMD_KEY_JUMP) - self.BUTTON_JUMP = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_JUMP) + PHYS_INPUT_BUTTON_JUMP(this) = true; - if(self.bot_cmd_keys & BOT_CMD_KEY_CROUCH) - self.BUTTON_CROUCH = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_CROUCH) + PHYS_INPUT_BUTTON_CROUCH(this) = true; - if(self.bot_cmd_keys & BOT_CMD_KEY_ATTACK1) - self.BUTTON_ATCK = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_ATTACK1) + PHYS_INPUT_BUTTON_ATCK(this) = true; - if(self.bot_cmd_keys & BOT_CMD_KEY_ATTACK2) - self.BUTTON_ATCK2 = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_ATTACK2) + PHYS_INPUT_BUTTON_ATCK2(this) = true; - if(self.bot_cmd_keys & BOT_CMD_KEY_USE) - self.BUTTON_USE = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_USE) + PHYS_INPUT_BUTTON_USE(this) = true; - if(self.bot_cmd_keys & BOT_CMD_KEY_HOOK) - self.BUTTON_HOOK = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_HOOK) + PHYS_INPUT_BUTTON_HOOK(this) = true; - if(self.bot_cmd_keys & BOT_CMD_KEY_CHAT) - self.BUTTON_CHAT = true; + if(this.bot_cmd_keys & BOT_CMD_KEY_CHAT) + PHYS_INPUT_BUTTON_CHAT(this) = true; return true; } -float bot_cmd_keypress_handler(string key, float enabled) -{SELFPARAM(); +float bot_cmd_keypress_handler(entity this, string key, float enabled) +{ switch(key) { case "all": if(enabled) - self.bot_cmd_keys = power2of(20) - 1; // >:) + this.bot_cmd_keys = power2of(20) - 1; // >:) else - self.bot_cmd_keys = BOT_CMD_KEY_NONE; + this.bot_cmd_keys = BOT_CMD_KEY_NONE; case "forward": if(enabled) { - self.bot_cmd_keys |= BOT_CMD_KEY_FORWARD; - self.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD; + this.bot_cmd_keys |= BOT_CMD_KEY_FORWARD; + this.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD; } else - self.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD; + this.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD; break; case "backward": if(enabled) { - self.bot_cmd_keys |= BOT_CMD_KEY_BACKWARD; - self.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD; + this.bot_cmd_keys |= BOT_CMD_KEY_BACKWARD; + this.bot_cmd_keys &= ~BOT_CMD_KEY_FORWARD; } else - self.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD; + this.bot_cmd_keys &= ~BOT_CMD_KEY_BACKWARD; break; case "left": if(enabled) { - self.bot_cmd_keys |= BOT_CMD_KEY_LEFT; - self.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT; + this.bot_cmd_keys |= BOT_CMD_KEY_LEFT; + this.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT; } else - self.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT; + this.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT; break; case "right": if(enabled) { - self.bot_cmd_keys |= BOT_CMD_KEY_RIGHT; - self.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT; + this.bot_cmd_keys |= BOT_CMD_KEY_RIGHT; + this.bot_cmd_keys &= ~BOT_CMD_KEY_LEFT; } else - self.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT; + this.bot_cmd_keys &= ~BOT_CMD_KEY_RIGHT; break; case "jump": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_JUMP; + this.bot_cmd_keys |= BOT_CMD_KEY_JUMP; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_JUMP; + this.bot_cmd_keys &= ~BOT_CMD_KEY_JUMP; break; case "crouch": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_CROUCH; + this.bot_cmd_keys |= BOT_CMD_KEY_CROUCH; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_CROUCH; + this.bot_cmd_keys &= ~BOT_CMD_KEY_CROUCH; break; case "attack1": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_ATTACK1; + this.bot_cmd_keys |= BOT_CMD_KEY_ATTACK1; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK1; + this.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK1; break; case "attack2": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_ATTACK2; + this.bot_cmd_keys |= BOT_CMD_KEY_ATTACK2; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK2; + this.bot_cmd_keys &= ~BOT_CMD_KEY_ATTACK2; break; case "use": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_USE; + this.bot_cmd_keys |= BOT_CMD_KEY_USE; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_USE; + this.bot_cmd_keys &= ~BOT_CMD_KEY_USE; break; case "hook": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_HOOK; + this.bot_cmd_keys |= BOT_CMD_KEY_HOOK; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_HOOK; + this.bot_cmd_keys &= ~BOT_CMD_KEY_HOOK; break; case "chat": if(enabled) - self.bot_cmd_keys |= BOT_CMD_KEY_CHAT; + this.bot_cmd_keys |= BOT_CMD_KEY_CHAT; else - self.bot_cmd_keys &= ~BOT_CMD_KEY_CHAT; + this.bot_cmd_keys &= ~BOT_CMD_KEY_CHAT; break; default: break; @@ -966,67 +972,67 @@ float bot_cmd_keypress_handler(string key, float enabled) return CMD_STATUS_FINISHED; } -float bot_cmd_presskey() +float bot_cmd_presskey(entity this) { string key; key = bot_cmd.bot_cmd_parm_string; - bot_cmd_keypress_handler(key,true); + bot_cmd_keypress_handler(this, key,true); return CMD_STATUS_FINISHED; } -float bot_cmd_releasekey() +float bot_cmd_releasekey(entity this) { string key; key = bot_cmd.bot_cmd_parm_string; - return bot_cmd_keypress_handler(key,false); + return bot_cmd_keypress_handler(this, key,false); } -float bot_cmd_pause() -{SELFPARAM(); - self.button1 = 0; - self.button8 = 0; - self.BUTTON_USE = 0; - self.BUTTON_ATCK = 0; - self.BUTTON_JUMP = 0; - self.BUTTON_HOOK = 0; - self.BUTTON_CHAT = 0; - self.BUTTON_ATCK2 = 0; - self.BUTTON_CROUCH = 0; - - self.movement = '0 0 0'; - self.bot_cmd_keys = BOT_CMD_KEY_NONE; - - self.bot_exec_status |= BOT_EXEC_STATUS_PAUSED; +float bot_cmd_pause(entity this) +{ + PHYS_INPUT_BUTTON_DRAG(this) = false; + PHYS_INPUT_BUTTON_USE(this) = false; + PHYS_INPUT_BUTTON_ATCK(this) = false; + PHYS_INPUT_BUTTON_JUMP(this) = false; + PHYS_INPUT_BUTTON_HOOK(this) = false; + PHYS_INPUT_BUTTON_CHAT(this) = false; + PHYS_INPUT_BUTTON_ATCK2(this) = false; + PHYS_INPUT_BUTTON_CROUCH(this) = false; + + this.movement = '0 0 0'; + this.bot_cmd_keys = BOT_CMD_KEY_NONE; + + bot_clear(this); + this.bot_exec_status |= BOT_EXEC_STATUS_PAUSED; return CMD_STATUS_FINISHED; } -float bot_cmd_moveto() -{SELFPARAM(); - return self.cmd_moveto(bot_cmd.bot_cmd_parm_vector); +float bot_cmd_moveto(entity this) +{ + return this.cmd_moveto(this, bot_cmd.bot_cmd_parm_vector); } -float bot_cmd_movetotarget() -{SELFPARAM(); +float bot_cmd_movetotarget(entity this) +{ entity e; - e = bot_getplace(bot_cmd.bot_cmd_parm_string); + e = bot_getplace(this, bot_cmd.bot_cmd_parm_string); if(!e) return CMD_STATUS_ERROR; - return self.cmd_moveto(e.origin + (e.mins + e.maxs) * 0.5); + return this.cmd_moveto(this, e.origin + (e.mins + e.maxs) * 0.5); } -float bot_cmd_resetgoal() -{SELFPARAM(); - return self.cmd_resetgoal(); +float bot_cmd_resetgoal(entity this) +{ + return this.cmd_resetgoal(this); } -float bot_cmd_sound() -{SELFPARAM(); +float bot_cmd_sound(entity this) +{ string f; f = bot_cmd.bot_cmd_parm_string; @@ -1047,47 +1053,48 @@ float bot_cmd_sound() atten = stof(argv(2)); precache_sound(f); - _sound(self, chan, sample, vol, atten); + _sound(this, chan, sample, vol, atten); return CMD_STATUS_FINISHED; } .entity tuba_note; -float bot_cmd_debug_assert_canfire() -{SELFPARAM(); - float f; - f = bot_cmd.bot_cmd_parm_float; +float bot_cmd_debug_assert_canfire(entity this) +{ + float f = bot_cmd.bot_cmd_parm_float; - if(self.weaponentity.state != WS_READY) + int slot = 0; // TODO: unhardcode? + .entity weaponentity = weaponentities[slot]; + if(this.(weaponentity).state != WS_READY) { if(f) { - self.colormod = '0 8 8'; - LOG_INFO("Bot ", self.netname, " using ", self.weaponname, " wants to fire, inhibited by weaponentity state\n"); + this.colormod = '0 8 8'; + LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by weaponentity state\n"); } } - else if(ATTACK_FINISHED(self) > time) + else if(ATTACK_FINISHED(this, slot) > time) { if(f) { - self.colormod = '8 0 8'; - LOG_INFO("Bot ", self.netname, " using ", self.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(self) - time), " seconds left)\n"); + this.colormod = '8 0 8'; + LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n"); } } - else if(self.tuba_note) + else if(this.(weaponentity).tuba_note) { if(f) { - self.colormod = '8 0 0'; - LOG_INFO("Bot ", self.netname, " using ", self.weaponname, " wants to fire, bot still has an active tuba note\n"); + this.colormod = '8 0 0'; + LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, bot still has an active tuba note\n"); } } else { if(!f) { - self.colormod = '8 8 0'; - 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"); + this.colormod = '8 8 0'; + LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n"); } } @@ -1096,118 +1103,112 @@ float bot_cmd_debug_assert_canfire() // -void bot_command_executed(float rm) -{SELFPARAM(); +void bot_command_executed(entity this, bool rm) +{ entity cmd; cmd = bot_cmd; if(rm) - bot_dequeuecommand(self, self.bot_cmd_execution_index); + bot_dequeuecommand(this, this.bot_cmd_execution_index); - self.bot_cmd_execution_index++; + this.bot_cmd_execution_index++; } -void bot_setcurrentcommand() -{SELFPARAM(); - bot_cmd = world; +void bot_setcurrentcommand(entity this) +{ + bot_cmd = NULL; - if(!self.bot_cmd_current) + if(!this.bot_cmd_current) { - self.bot_cmd_current = spawn(); - self.bot_cmd_current.classname = "bot_cmd"; - self.bot_cmd_current.is_bot_cmd = 1; + this.bot_cmd_current = new_pure(bot_cmd); } - bot_cmd = self.bot_cmd_current; - if(bot_cmd.bot_cmd_index != self.bot_cmd_execution_index || self.bot_cmd_execution_index == 0) + bot_cmd = this.bot_cmd_current; + if(bot_cmd.bot_cmd_index != this.bot_cmd_execution_index || this.bot_cmd_execution_index == 0) { - if(bot_havecommand(self, self.bot_cmd_execution_index)) + if(bot_havecommand(this, this.bot_cmd_execution_index)) { string cmdstring; - cmdstring = bot_readcommand(self, self.bot_cmd_execution_index); + cmdstring = bot_readcommand(this, this.bot_cmd_execution_index); if(bot_decodecommand(cmdstring)) { - bot_cmd.owner = self; - bot_cmd.bot_cmd_index = self.bot_cmd_execution_index; + bot_cmd.owner = this; + bot_cmd.bot_cmd_index = this.bot_cmd_execution_index; } else { // Invalid command, remove from queue - bot_cmd = world; - bot_dequeuecommand(self, self.bot_cmd_execution_index); - self.bot_cmd_execution_index++; + bot_cmd = NULL; + bot_dequeuecommand(this, this.bot_cmd_execution_index); + this.bot_cmd_execution_index++; } } else - bot_cmd = world; + bot_cmd = NULL; } } void bot_resetqueues() { - entity cl; - - FOR_EACH_CLIENT(cl) if(cl.isbot) - { - cl.bot_cmd_execution_index = 0; - bot_clearqueue(cl); + FOREACH_CLIENT(it.isbot, LAMBDA( + it.bot_cmd_execution_index = 0; + bot_clearqueue(it); // also, cancel all barriers - cl.bot_barrier = 0; - for(int i = 0; i < cl.bot_places_count; ++i) + it.bot_barrier = 0; + for(int i = 0; i < it.bot_places_count; ++i) { - strunzone(cl.(bot_placenames[i])); - cl.(bot_placenames[i]) = string_null; + strunzone(it.(bot_placenames[i])); + it.(bot_placenames[i]) = string_null; } - cl.bot_places_count = 0; - } + it.bot_places_count = 0; + )); bot_barriertime = time; } -bool autocvar_g_debug_bot_commands; - // 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 bot_execute_commands_once(entity this) +{ float status, ispressingkey; // Find command - bot_setcurrentcommand(); - - // if we have no bot command, better return - // old logic kept pressing previously pressed keys, but that has problems - // (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; + bot_setcurrentcommand(this); // Ignore all commands except continue when the bot is paused - if(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED) - if(bot_cmd.bot_cmd_type!=BOT_CMD_CONTINUE) + if(!(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED)) + { + // if we have no bot command, better return + // old logic kept pressing previously pressed keys, but that has problems + // (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 0; + } + else if(bot_cmd.bot_cmd_type != BOT_CMD_CONTINUE) { if(bot_cmd.bot_cmd_type!=BOT_CMD_NULL) { - bot_command_executed(true); + bot_command_executed(this, true); LOG_INFO( "WARNING: Commands are ignored while the bot is paused. Use the command 'continue' instead.\n"); } return 1; } // Keep pressing keys raised by the "presskey" command - ispressingkey = !!bot_presskeys(); + ispressingkey = boolean(bot_presskeys(this)); // 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(this.bot_cmd_condition_status & CMD_CONDITION_true && this.bot_cmd_condition_status & CMD_CONDITION_false_BLOCK) { - bot_command_executed(true); + bot_command_executed(this, true); return -1; } - else if(self.bot_cmd_condition_status & CMD_CONDITION_false && self.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK) + else if(this.bot_cmd_condition_status & CMD_CONDITION_false && this.bot_cmd_condition_status & CMD_CONDITION_true_BLOCK) { - bot_command_executed(true); + bot_command_executed(this, true); return -1; } @@ -1218,74 +1219,74 @@ float bot_execute_commands_once() return ispressingkey; //break; case BOT_CMD_PAUSE: - status = bot_cmd_pause(); + status = bot_cmd_pause(this); break; case BOT_CMD_CONTINUE: - status = bot_cmd_continue(); + status = bot_cmd_continue(this); break; case BOT_CMD_WAIT: - status = bot_cmd_wait(); + status = bot_cmd_wait(this); break; case BOT_CMD_WAIT_UNTIL: - status = bot_cmd_wait_until(); + status = bot_cmd_wait_until(this); break; case BOT_CMD_TURN: - status = bot_cmd_turn(); + status = bot_cmd_turn(this); break; case BOT_CMD_MOVETO: - status = bot_cmd_moveto(); + status = bot_cmd_moveto(this); break; case BOT_CMD_MOVETOTARGET: - status = bot_cmd_movetotarget(); + status = bot_cmd_movetotarget(this); break; case BOT_CMD_RESETGOAL: - status = bot_cmd_resetgoal(); + status = bot_cmd_resetgoal(this); break; case BOT_CMD_CC: - status = bot_cmd_cc(); + status = bot_cmd_cc(this); break; case BOT_CMD_IF: - status = bot_cmd_if(); + status = bot_cmd_if(this); break; case BOT_CMD_ELSE: - status = bot_cmd_else(); + status = bot_cmd_else(this); break; case BOT_CMD_FI: - status = bot_cmd_fi(); + status = bot_cmd_fi(this); break; case BOT_CMD_RESETAIM: - status = bot_cmd_resetaim(); + status = bot_cmd_resetaim(this); break; case BOT_CMD_AIM: - status = bot_cmd_aim(); + status = bot_cmd_aim(this); break; case BOT_CMD_AIMTARGET: - status = bot_cmd_aimtarget(); + status = bot_cmd_aimtarget(this); break; case BOT_CMD_PRESSKEY: - status = bot_cmd_presskey(); + status = bot_cmd_presskey(this); break; case BOT_CMD_RELEASEKEY: - status = bot_cmd_releasekey(); + status = bot_cmd_releasekey(this); break; case BOT_CMD_SELECTWEAPON: - status = bot_cmd_select_weapon(); + status = bot_cmd_select_weapon(this); break; case BOT_CMD_IMPULSE: - status = bot_cmd_impulse(); + status = bot_cmd_impulse(this); break; case BOT_CMD_BARRIER: - status = bot_cmd_barrier(); + status = bot_cmd_barrier(this); break; case BOT_CMD_CONSOLE: localcmd(strcat(bot_cmd.bot_cmd_parm_string, "\n")); status = CMD_STATUS_FINISHED; break; case BOT_CMD_SOUND: - status = bot_cmd_sound(); + status = bot_cmd_sound(this); break; case BOT_CMD_DEBUG_ASSERT_CANFIRE: - status = bot_cmd_debug_assert_canfire(); + status = bot_cmd_debug_assert_canfire(this); break; default: LOG_INFO(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n")); @@ -1321,10 +1322,10 @@ float bot_execute_commands_once() parms = ""; break; } - clientcommand(self,strcat("say ^7", bot_cmd_string[bot_cmd.bot_cmd_type]," ",parms,"\n")); + clientcommand(this,strcat("say ^7", bot_cmd_string[bot_cmd.bot_cmd_type]," ",parms,"\n")); } - bot_command_executed(true); + bot_command_executed(this, true); } if(status == CMD_STATUS_FINISHED) @@ -1334,12 +1335,12 @@ float bot_execute_commands_once() } // This function should be (the only) called directly from the bot ai loop -float bot_execute_commands() +int bot_execute_commands(entity this) { - float f; + int f; do { - f = bot_execute_commands_once(); + f = bot_execute_commands_once(this); } while(f < 0); return f;