]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/scripting.qc
Merge branch 'master' into Mario/wepent_experimental
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / scripting.qc
index 3f53d2b9f23456677bc33676d22f06f658ef0634..252708a1189f0401c7af68b0ff4ff047759e1950 100644 (file)
@@ -1,5 +1,15 @@
 #include "scripting.qh"
 
+#include "cvars.qh"
+
+#include <common/state.qh>
+#include <common/physics/player.qh>
+#include <common/wepent.qh>
+
+#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,119 @@ 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)
+{
+       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 +598,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 +648,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 +663,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 +678,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)<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;
        }
 
-       if(bot_cmd_eval(expr))
-               self.bot_cmd_condition_status |= CMD_CONDITION_true;
+       if(bot_cmd_eval(this, expr))
+               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;
 }
 
-float bot_cmd_else()
-{SELFPARAM();
-       self.bot_cmd_condition_status &= ~CMD_CONDITION_true_BLOCK;
-       self.bot_cmd_condition_status |= CMD_CONDITION_false_BLOCK;
+float bot_cmd_else(entity this)
+{
+       this.bot_cmd_condition_status &= ~CMD_CONDITION_true_BLOCK;
+       this.bot_cmd_condition_status |= CMD_CONDITION_false_BLOCK;
        return CMD_STATUS_FINISHED;
 }
 
-float bot_cmd_fi()
-{SELFPARAM();
-       self.bot_cmd_condition_status = CMD_CONDITION_NONE;
+float bot_cmd_fi(entity this)
+{
+       this.bot_cmd_condition_status = CMD_CONDITION_NONE;
        return CMD_STATUS_FINISHED;
 }
 
-float bot_cmd_resetaim()
-{SELFPARAM();
-       self.v_angle = '0 0 0';
+float bot_cmd_resetaim(entity this)
+{
+       this.v_angle = '0 0 0';
        return CMD_STATUS_FINISHED;
 }
 
@@ -713,19 +718,19 @@ float bot_cmd_resetaim()
 .vector bot_cmd_aim_begin;
 .vector bot_cmd_aim_end;
 
-float bot_cmd_aim()
-{SELFPARAM();
+float bot_cmd_aim(entity this)
+{
        // Current direction
-       if(self.bot_cmd_aim_endtime)
+       if(this.bot_cmd_aim_endtime)
        {
                float progress;
 
-               progress = min(1 - (self.bot_cmd_aim_endtime - time) / (self.bot_cmd_aim_endtime - self.bot_cmd_aim_begintime),1);
-               self.v_angle = self.bot_cmd_aim_begin + ((self.bot_cmd_aim_end - self.bot_cmd_aim_begin) * progress);
+               progress = min(1 - (this.bot_cmd_aim_endtime - time) / (this.bot_cmd_aim_endtime - this.bot_cmd_aim_begintime),1);
+               this.v_angle = this.bot_cmd_aim_begin + ((this.bot_cmd_aim_end - this.bot_cmd_aim_begin) * progress);
 
-               if(time>=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 +752,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 +785,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 +793,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 +803,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 +816,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 +971,66 @@ 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;
+
+       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 +1051,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 +1101,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 +1217,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 +1320,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 +1333,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;