]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/cl_weapons.qc
Merge branch 'master' into terencehill/g_changeteam_banned_fix
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_weapons.qc
index 6de63b9377fd76893498adebe0507247737e3fe1..edf5b1f5e5c697d07087509075ef53edc2af5bd0 100644 (file)
@@ -1,8 +1,6 @@
-void W_Reload()
+void W_TriggerReload()
 {
-       if(self.switchweapon == self.weapon)
-       if(self.weaponentity.state == WS_READY)
-               weapon_action(self.weapon, WR_RELOAD);
+    weapon_action(self.weapon, WR_RELOAD);
 }
 
 // switch between weapons
@@ -17,9 +15,9 @@ void W_SwitchWeapon(float imp)
        }
        else
        {
-               W_Reload();
+               W_TriggerReload();
        }
-};
+}
 
 .float weaponcomplainindex;
 float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
@@ -139,17 +137,26 @@ void W_PreviousWeapon(float list)
                W_CycleWeapon(self.cvar_cl_weaponpriority, +1);
 }
 
+// previously used if exists and has ammo, (second) best otherwise
+void W_LastWeapon()
+{
+       if(client_hasweapon(self, self.cnt, TRUE, FALSE))
+               W_SwitchWeapon(self.cnt);
+       else
+               W_SwitchToOtherWeapon(self);
+}
+
 float w_getbestweapon(entity e)
 {
        return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE);
-};
+}
 
 // generic weapons table
 // TODO should they be macros instead?
 float weapon_action(float wpn, float wrequest)
 {
        return (get_weaponinfo(wpn)).weapon_func(wrequest);
-};
+}
 
 string W_Name(float weaponid)
 {
@@ -199,6 +206,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                self = oldself;
                if(startitem_failed)
                        return string_null;
+               wep.glowmod = own.weaponentity_glowmod;
                wep.think = thrown_wep_think;
                wep.nextthink = time + 0.5;
                return "";
@@ -223,10 +231,18 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                                        wep.ammofield = thisammo;
                                        own.ammofield -= thisammo;
                                        s = strcat(s, " and ", ftos(thisammo), " ", Item_CounterFieldName(j));
+
+                                       // if our weapon is loaded, give its load back to the player
+                                       if(self.(weapon_load[self.weapon]) > 0)
+                                       {
+                                               own.ammofield += self.(weapon_load[self.weapon]);
+                                               self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
+                                       }
                                }
                        }
                        s = substring(s, 5, -1);
                }
+               wep.glowmod = own.weaponentity_glowmod;
                wep.think = thrown_wep_think;
                wep.nextthink = time + 0.5;
                return s;
@@ -236,6 +252,20 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
 float W_IsWeaponThrowable(float w)
 {
        float wb, wa;
+
+       if (!autocvar_g_pickup_items)
+               return 0;
+       if (g_weaponarena)
+               return 0;
+       if (g_lms)
+               return 0;
+       if (g_ca)
+               return 0;
+       if (g_cts)
+               return 0;
+       if (g_nexball && w == WEP_GRENADE_LAUNCHER)
+               return 0;
+
        wb = W_WeaponBit(w);
        if(!wb)
                return 0;
@@ -257,7 +287,7 @@ float W_IsWeaponThrowable(float w)
 // toss current weapon
 void W_ThrowWeapon(vector velo, vector delta, float doreduce)
 {
-       local float w, wb;
+       float w, wb;
        string a;
 
        w = self.weapon;
@@ -265,25 +295,13 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
                return; // just in case
        if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
                return;
-       if (g_weaponarena)
-               return;
-       if (g_lms)
-               return;
-       if (g_nexball && w == WEP_GRENADE_LAUNCHER)
-               return;
-       if (!autocvar_g_pickup_items)
-               return;
-       if (g_ca)
-               return;
-    if (g_cts)
-        return;
        if(!autocvar_g_weapon_throwable)
                return;
        if(autocvar_g_weapon_stay == 1)
                return;
-       if(!W_IsWeaponThrowable(w))
+       if(self.weaponentity.state != WS_READY)
                return;
-       if(self.deadflag == DEAD_NO && self.weaponentity.state != WS_READY)
+       if(!W_IsWeaponThrowable(w))
                return;
 
        wb = W_WeaponBit(w);
@@ -295,14 +313,11 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
        a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
        if not(a)
                return;
-       if(self.health >= 1)
-       {
-               if(a == "")
-                       sprint(self, strcat("You dropped the ^2", W_Name(w), "\n"));
-               else
-                       sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", a, "\n"));
-       }
-};
+       if(a == "")
+               sprint(self, strcat("You dropped the ^2", W_Name(w), "\n"));
+       else
+               sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", a, "\n"));
+}
 
 // Bringed back weapon frame
 void W_WeaponFrame()
@@ -315,7 +330,7 @@ void W_WeaponFrame()
        if(((arena_roundbased || g_ca || g_freezetag) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown))
                return;
 
-       if(g_freezetag && self.freezetag_frozen == 1)
+       if(self.freezetag_frozen == 1)
                return;
 
        if (!self.weaponentity || self.health < 1)
@@ -324,6 +339,7 @@ void W_WeaponFrame()
        if(!self.switchweapon)
        {
                self.weapon = 0;
+               self.switchingweapon = 0;
                self.weaponentity.state = WS_CLEAR;
                self.weaponname = "";
                self.items &~= IT_AMMO;
@@ -340,22 +356,44 @@ void W_WeaponFrame()
        {
                if (self.weaponentity.state == WS_CLEAR)
                {
-                       setanim(self, self.anim_draw, FALSE, TRUE, TRUE);
+                       // end switching!
+                       self.switchingweapon = self.switchweapon;
+
+                       //setanim(self, self.anim_draw, FALSE, TRUE, TRUE);
                        self.weaponentity.state = WS_RAISE;
                        weapon_action(self.switchweapon, WR_SETUP);
+
+                       // set our clip load to the load of the weapon we switched to, if it's reloadable
+                       entity e;
+                       e = get_weaponinfo(self.switchweapon);
+                       if(e.spawnflags & WEP_FLAG_RELOADABLE && cvar(strcat("g_balance_", e.netname, "_reload_ammo"))) // prevent accessing undefined cvars
+                       {
+                               self.clip_load = self.(weapon_load[self.switchweapon]);
+                               self.clip_size = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
+                       }
+                       else
+                               self.clip_load = self.clip_size = 0;
+
                        // VorteX: add player model weapon select frame here
                        // setcustomframe(PlayerWeaponRaise);
                        weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_weaponswitchdelay, w_ready);
                        weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, '0 0 0');
                }
+               else if (self.weaponentity.state == WS_DROP)
+               {
+                       // in dropping phase we can switch at any time
+                       self.switchingweapon = self.switchweapon;
+               }
                else if (self.weaponentity.state == WS_READY)
                {
+                       // start switching!
+                       self.switchingweapon = self.switchweapon;
+
 #ifndef INDEPENDENT_ATTACK_FINISHED
                        if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5)
                        {
 #endif
-                       // UGLY WORKAROUND: play this on CHAN_WEAPON2 so it can't cut off fire sounds
-                       sound (self, CHAN_WEAPON2, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM);
+                       sound (self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM);
                        self.weaponentity.state = WS_DROP;
                        // set up weapon switch think in the future, and start drop anim
                        weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_weaponswitchdelay, w_clear);
@@ -376,24 +414,27 @@ void W_WeaponFrame()
        // call the think code which may fire the weapon
        // and do so multiple times to resolve framerate dependency issues if the
        // server framerate is very low and the weapon fire rate very high
-       local float c;
+       float c;
        c = 0;
        while (c < W_TICSPERFRAME)
        {
                c = c + 1;
                if(wb && ((self.weapons & wb) == 0))
                {
-                       W_SwitchWeapon_Force(self, w_getbestweapon(self));
+                       if(self.weapon == self.switchweapon)
+                               W_SwitchWeapon_Force(self, w_getbestweapon(self));
                        wb = 0;
                }
+
+               v_forward = fo;
+               v_right = ri;
+               v_up = up;
+
                if(wb)
-               {
-                       v_forward = fo;
-                       v_right = ri;
-                       v_up = up;
-                       self.weaponentity_glowmod = '0 0 0'; // reset glowmod, weapon think function only *might* set it
                        weapon_action(self.weapon, WR_THINK);
-               }
+               else
+                       weapon_action(self.weapon, WR_GONETHINK);
+
                if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink)
                {
                        if(self.weapon_think)
@@ -428,4 +469,4 @@ void W_WeaponFrame()
        else
                self.currentammo = 1;
 #endif
-};
+}