]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/havocbot/havocbot.qc
Merge branch 'master' into mirceakitsune/hud_postprocessing
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / havocbot / havocbot.qc
index 7463cfc6f0e9362f5bcdea43dddfb84b832ad7fa..7c2f986346677e73b2cefc533cf45651ebd18cf0 100644 (file)
@@ -2,6 +2,8 @@
 #include "role_ctf.qc"
 #include "role_onslaught.qc"
 #include "role_keyhunt.qc"
+#include "role_freezetag.qc"
+#include "role_keepaway.qc"
 #include "roles.qc"
 
 void havocbot_ai()
@@ -146,27 +148,26 @@ void havocbot_ai()
        }
        havocbot_movetogoal();
 
-       // if the bot is not attacking, go through all weapons that aren't fully loaded and reload them to keep them ready
+       // if the bot is not attacking, consider reloading weapons
        if not(self.aistatus & AI_STATUS_ATTACKING)
        {
                float i;
                entity e;
 
                // we are currently holding a weapon that's not fully loaded, reload it
-               if(skill > 2.5) // bots can only reload held weapons on purpose past this skill
-               if(self.clip_load < self.clip_size && self.weapon)
+               if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
+               if(self.clip_load < self.clip_size)
                        self.impulse = 20; // "press" the reload button, not sure if this is done right
 
                // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
                // the code above executes next frame, starting the reloading then
                if(skill >= 5) // bots can only look for unloaded weapons past this skill
                if(self.clip_load >= 0) // only if we're not reloading a weapon already
-               if not(self.clip_load < self.clip_size && self.weapon) // we're already holding a weapon we can reload, don't look for another
                {
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                        {
                                e = get_weaponinfo(i);
-                               if(self.weapon_load[i] < cvar(strcat("g_balance_", e.netname, "_reload_ammo")))
+                               if ((e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < cvar(strcat("g_balance_", e.netname, "_reload_ammo"))))
                                        self.switchweapon = i;
                        }
                }
@@ -260,7 +261,7 @@ void havocbot_bunnyhop(vector dir)
        // Don't jump when using some weapons
        /*
        if(self.aistatus & AI_STATUS_ATTACKING)
-       if(self.weapon == WEP_SNIPERRIFLE)
+       if(self.weapon == WEP_RIFLE)
                return;
 
        if(self.goalcurrent.classname == "player")
@@ -417,10 +418,11 @@ void havocbot_movetogoal()
        if(self.goalcurrent==self.navigation_jetpack_goal)
        if(self.ammo_fuel)
        {
-               #ifdef DEBUG_BOT_GOALSTACK
+               if(autocvar_bot_debug_goalstack)
+               {
                        debuggoalstack();
                        te_wizspike(self.navigation_jetpack_point);
-               #endif
+               }
 
                // Take off
                if not(self.aistatus & AI_STATUS_JETPACK_FLYING)
@@ -654,9 +656,8 @@ void havocbot_movetogoal()
                return;
        }
 
-#ifdef DEBUG_BOT_GOALSTACK
-       debuggoalstack();
-#endif
+       if(autocvar_bot_debug_goalstack)
+               debuggoalstack();
 
        m1 = self.goalcurrent.origin + self.goalcurrent.mins;
        m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
@@ -919,7 +920,7 @@ void havocbot_chooseenemy()
 
                // I want to do a second scan if no enemy was found or I don't have weapons
                // TODO: Perform the scan when using the rifle (requires changes on the rifle code)
-               if(best || self.weapons) // || self.weapon == WEP_SNIPERRIFLE
+               if(best || self.weapons) // || self.weapon == WEP_RIFLE
                        break;
                if(i)
                        break;
@@ -940,6 +941,31 @@ void havocbot_chooseenemy()
        self.havocbot_stickenemy = TRUE;
 };
 
+float havocbot_chooseweapon_checkreload(float new_weapon)
+{
+       // bots under this skill cannot find unloaded weapons to reload idly when not in combat,
+       // so skip this for them, or they'll never get to reload their weapons at all.
+       // this also allows bots under this skill to be more stupid, and reload more often during combat :)
+       if(skill < 5)
+               return FALSE;
+
+       // if this weapon is scheduled for reloading, don't switch to it during combat
+       if (self.weapon_load[new_weapon] < 0)
+       {
+               local float i, other_weapon_available;
+               for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               {
+                       // if we are out of ammo for all other weapons, it's an emergency to switch to anything else
+                       if (weapon_action(i, WR_CHECKAMMO1) + weapon_action(i, WR_CHECKAMMO2))
+                               other_weapon_available = TRUE;
+               }
+               if(other_weapon_available)
+                       return TRUE;
+       }
+
+       return FALSE;
+}
+
 void havocbot_chooseweapon()
 {
        local float i;
@@ -1004,8 +1030,9 @@ void havocbot_chooseweapon()
                if ( distance > bot_distance_far ) {
                        for(i=0; i < WEP_COUNT && bot_weapons_far[i] != -1 ; ++i){
                                w = bot_weapons_far[i];
-                               if ( client_hasweapon(self, w, TRUE, FALSE) ){
-                                       if ( self.weapon == w && combo)
+                               if ( client_hasweapon(self, w, TRUE, FALSE) )
+                               {
+                                       if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
                                                continue;
                                        self.switchweapon = w;
                                        return;
@@ -1017,8 +1044,9 @@ void havocbot_chooseweapon()
                if ( distance > bot_distance_close) {
                        for(i=0; i < WEP_COUNT && bot_weapons_mid[i] != -1 ; ++i){
                                w = bot_weapons_mid[i];
-                               if ( client_hasweapon(self, w, TRUE, FALSE) ){
-                                       if ( self.weapon == w && combo)
+                               if ( client_hasweapon(self, w, TRUE, FALSE) )
+                               {
+                                       if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
                                                continue;
                                        self.switchweapon = w;
                                        return;
@@ -1029,8 +1057,9 @@ void havocbot_chooseweapon()
                // Choose weapons for close distance
                for(i=0; i < WEP_COUNT && bot_weapons_close[i] != -1 ; ++i){
                        w = bot_weapons_close[i];
-                       if ( client_hasweapon(self, w, TRUE, FALSE) ){
-                               if ( self.weapon == w && combo)
+                       if ( client_hasweapon(self, w, TRUE, FALSE) )
+                       {
+                               if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
                                        continue;
                                self.switchweapon = w;
                                return;
@@ -1112,9 +1141,8 @@ float havocbot_moveto(vector pos)
                        }
                }
 
-               #ifdef DEBUG_BOT_GOALSTACK
+               if(autocvar_bot_debug_goalstack)
                        debuggoalstack();
-               #endif
 
                // Heading
                local vector dir = self.goalcurrent.origin - (self.origin + self.view_ofs);