]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Improve autoswitching options in CTS k9er/cts-autoswitch 1398/head
authorotta8634 <k9wolf@pm.me>
Sat, 21 Dec 2024 15:50:54 +0000 (23:50 +0800)
committerotta8634 <k9wolf@pm.me>
Sat, 21 Dec 2024 15:50:54 +0000 (23:50 +0800)
Removed cl_cts_noautoswitch and replaced it with cl_autoswitch_cts which has 3 options:
- 0 (default): fallsback to the cl_autoswitch behavior. This may seem unnecessary, but it can be useful on some maps, manually editing the weapon priority list to choose when you autoswitch and when you don't.
- 1: always autoswitch to the new weapon.
- 2: never autoswitch to the new weapon.
These options are of course only used in CTS, in other gamemodes (including Race) the cvar is ignored and cl_autoswitch is used.
Also made the new cvar apply to cases where a trigger gives a player a weapon in CTS, which for some reason it didn't apply to before.
Added a bit of documentation to affected functions.
The new cvar name is easier to find and more intuitive in my opinion.

commands.cfg
qcsrc/common/replicate.qh
qcsrc/server/client.qh
qcsrc/server/items/items.qc
xonotic-client.cfg

index ae8719a0f5edd5743fa2a93093caac31d5a82c56..0165d8f89f93658fef2ce74835d79927b6fe5d70 100644 (file)
@@ -178,7 +178,7 @@ alias menu_showteamselect team_selection_show
 set sv_clientcommand_antispam_time 1 "Amount of seconds after a command before another command can be called again without being considered spam. (Use -1 for no antispam limit)"
 set sv_clientcommand_antispam_count 8 "Amount of commands considered spam before commands are rejected."
 seta sv_status_privacy 1 "hide IP addresses from \"status\" and \"who\" replies shown to clients"
-seta cl_autoswitch 1 "automatically switch to newly picked up weapons if they are better than what you are carrying"
+seta cl_autoswitch 1 "automatically switch to newly picked up weapons if they are better than what you are carrying (NOTE: see also cl_autoswitch_cts)"
 
 // commented out commands are really only intended for internal use, or already have declaration in the engine
 alias autoswitch           "qc_cmd_cmd    autoswitch           ${* ?}" // Whether or not to switch automatically when getting a better weapon
index 6c66771f8aab4a812e50b9030385a3d688c19651..3f4a9ffc0ad60a9f1c9e65e40f18e09f1ddead63 100644 (file)
@@ -6,7 +6,7 @@
 REPLICATE_INIT(bool, cvar_cl_autoswitch);
 REPLICATE_INIT(int, cvar_cl_autoscreenshot);
 REPLICATE_INIT(bool, cvar_cl_clippedspectating);
-REPLICATE_INIT(bool, cvar_cl_cts_noautoswitch);
+REPLICATE_INIT(int, cvar_cl_autoswitch_cts);
 REPLICATE_INIT(vector, cvar_cl_handicap);
 REPLICATE_INIT(float, cvar_cl_handicap_damage_given);
 REPLICATE_INIT(float, cvar_cl_handicap_damage_taken);
@@ -15,7 +15,7 @@ REPLICATE_INIT(string, cvar_g_xonoticversion);
 REPLICATE(cvar_cl_autoswitch, bool, "cl_autoswitch");
 REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
 REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating");
-REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
+REPLICATE(cvar_cl_autoswitch_cts, int, "cl_autoswitch_cts");
 REPLICATE(cvar_cl_handicap, vector, "cl_handicap");
 REPLICATE(cvar_cl_handicap_damage_given, float, "cl_handicap_damage_given");
 REPLICATE(cvar_cl_handicap_damage_taken, float, "cl_handicap_damage_taken");
index cd3c162baf9778a789f98319183f6bccbcb10494..5aa2a42ac5fc25e745b84fa4e71636352a030649 100644 (file)
@@ -228,7 +228,7 @@ CLASS(Client, Object)
     ATTRIB(Client, cvar_cl_accuracy_data_receive, bool, this.cvar_cl_accuracy_data_receive);
     ATTRIBARRAY(Client, cvar_cl_weaponpriorities, string, 10);
     ATTRIB(Client, cvar_cl_weaponpriority, string, this.cvar_cl_weaponpriority);
-    ATTRIB(Client, cvar_cl_cts_noautoswitch, bool, this.cvar_cl_cts_noautoswitch);
+    ATTRIB(Client, cvar_cl_autoswitch_cts, int, this.cvar_cl_autoswitch_cts);
     ATTRIB(Client, cvar_cl_weapon_switch_reload, bool, this.cvar_cl_weapon_switch_reload);
     ATTRIB(Client, cvar_cl_weapon_switch_fallback_to_impulse, bool, this.cvar_cl_weapon_switch_fallback_to_impulse);
 #endif
index 6adc4f9b439d88c2fbd97d20adad62d6157db77f..3a791c6344a5836c87af8534ca297773f47e379b 100644 (file)
@@ -529,21 +529,22 @@ bool Item_GiveTo(entity item, entity player)
 {
        // if nothing happens to player, just return without taking the item
        int _switchweapon = 0;
-       // in case the player has autoswitch enabled do the following:
+       // in case the player has cl_autoswitch enabled do the following:
        // if the player is using their best weapon before items are given, they
        // probably want to switch to an even better weapon after items are given
 
-       if(CS_CVAR(player).cvar_cl_autoswitch)
+       bool use_cts_autoswitch = (g_cts && item.itemdef.instanceOfWeaponPickup);
+       if (CS_CVAR(player).cvar_cl_autoswitch && (!use_cts_autoswitch || !CS_CVAR(player).cvar_cl_autoswitch_cts))
        {
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
                        .entity weaponentity = weaponentities[slot];
-                       if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                       if (player.(weaponentity).m_weapon != WEP_Null || slot == 0)
                        {
-                               if(player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
+                               if (player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
                                        _switchweapon |= BIT(slot);
 
-                               if(!(STAT(WEAPONS, player) & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
+                               if (!(STAT(WEAPONS, player) & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
                                        _switchweapon |= BIT(slot);
                        }
                }
@@ -654,26 +655,32 @@ bool Item_GiveTo(entity item, entity player)
        if (!pickedup)
                return false;
 
-       // crude hack to enforce switching weapons
-       if(g_cts && item.itemdef.instanceOfWeaponPickup && !CS_CVAR(player).cvar_cl_cts_noautoswitch)
+       if(use_cts_autoswitch && CS_CVAR(player).cvar_cl_autoswitch_cts != 0)
        {
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               // CTS handling: always switch (1), never switch (2)
+               if(CS_CVAR(player).cvar_cl_autoswitch_cts == 1)
                {
-                       .entity weaponentity = weaponentities[slot];
-                       if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
-                               W_SwitchWeapon_Force(player, REGISTRY_GET(Weapons, item.weapon), weaponentity);
+                       // crude hack to enforce switching weapons
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                                       W_SwitchWeapon_Force(player, REGISTRY_GET(Weapons, item.weapon), weaponentity);
+                       }
                }
-               return true;
        }
-
-       if(_switchweapon)
+       else if(_switchweapon)
        {
+               // non-CTS handling: weaponpriority-based autoswitch
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
                        .entity weaponentity = weaponentities[slot];
                        if(_switchweapon & BIT(slot))
-                       if(player.(weaponentity).m_switchweapon != w_getbestweapon(player, weaponentity))
-                               W_SwitchWeapon_Force(player, w_getbestweapon(player, weaponentity), weaponentity);
+                       {
+                               Weapon best_wep = w_getbestweapon(player, weaponentity);
+                               if(player.(weaponentity).m_switchweapon != best_wep)
+                                       W_SwitchWeapon_Force(player, best_wep, weaponentity);
+                       }
                }
        }
 
@@ -1583,7 +1590,8 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        int _switchweapon = 0;
 
-       if(CS_CVAR(e).cvar_cl_autoswitch)
+       bool use_cts_autoswitch = g_cts;
+       if(CS_CVAR(e).cvar_cl_autoswitch && (!use_cts_autoswitch || !CS_CVAR(e).cvar_cl_autoswitch_cts))
        {
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
@@ -1609,6 +1617,7 @@ float GiveItems(entity e, float beginarg, float endarg)
        PREGIVE_RESOURCE(e, RES_ARMOR);
        PREGIVE_RESOURCE(e, RES_HEALTH);
 
+       Weapon last_wep = WEP_Null;
        for(i = beginarg; i < endarg; ++i)
        {
                cmd = argv(i);
@@ -1717,6 +1726,7 @@ float GiveItems(entity e, float beginarg, float endarg)
                                });
                                FOREACH(Weapons, it != WEP_Null && (cmd == it.netname || cmd == it.m_deprecated_netname), {
                                        got += GiveWeapon(e, it.m_id, op, val);
+                                       last_wep = it;
                                        break;
                                });
                                break;
@@ -1757,24 +1767,35 @@ float GiveItems(entity e, float beginarg, float endarg)
        if(e.statuseffects)
                StatusEffects_update(e);
 
-       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       if(last_wep != WEP_Null && use_cts_autoswitch && CS_CVAR(e).cvar_cl_autoswitch_cts != 0)
        {
-               .entity weaponentity = weaponentities[slot];
-               if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
-               if(!(STAT(WEAPONS, e) & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
-                       _switchweapon |= BIT(slot);
+               // CTS handling: always switch (1), never switch (2)
+               if(CS_CVAR(e).cvar_cl_autoswitch_cts == 1)
+               {
+                       // crude hack to enforce switching weapons
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                                       W_SwitchWeapon_Force(e, last_wep, weaponentity);
+                       }
+               }
        }
-
-       if(_switchweapon)
+       else
        {
+               // non-CTS handling: weaponpriority-based autoswitch
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
                        .entity weaponentity = weaponentities[slot];
+                       if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                       if(!(STAT(WEAPONS, e) & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
+                               _switchweapon |= BIT(slot);
+
                        if(_switchweapon & BIT(slot))
                        {
-                               Weapon wep = w_getbestweapon(e, weaponentity);
-                               if(wep != e.(weaponentity).m_switchweapon)
-                                       W_SwitchWeapon_Force(e, wep, weaponentity);
+                               Weapon best_wep = w_getbestweapon(e, weaponentity);
+                               if(e.(weaponentity).m_switchweapon != best_wep)
+                                       W_SwitchWeapon_Force(e, best_wep, weaponentity);
                        }
                }
        }
index 6668db2b48f1a2a8b41b176ffdeabb17c9105a23..642b97f7620bda1f6bd250d8231c134fff3b5e73 100644 (file)
@@ -720,7 +720,7 @@ seta cl_race_cptimes_namesize 10 "Maximum length of player names in checkpoint m
 seta cl_race_checkpoint_splits_console 1 "Print checkpoint splits to console"
 seta cl_race_checkpoint_splits_hud 1 "Show race checkpoint splits on HUD in infomessages"
 
-seta cl_cts_noautoswitch 0 "Prevent forced switching to new weapons in CTS"
+seta cl_autoswitch_cts 0 "0 = fallback to the behavior of cl_autoswitch, 1 = always autoswitch in CTS, 2 = never autoswitch in CTS"
 
 set cl_stripcolorcodes 0       "experimental feature (notes: strips ALL color codes from messages!)"