X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_weapons.qc;h=fac0d73aa2cbf09b30f36ed949e7bb97a9d26085;hb=e52c92b8ba22924be19d8458fb1dd0cb7cfe11c7;hp=afe3088d431cd40507f61ce543442da20f80fa8c;hpb=db3d8b68f0aff3f1304428e9d60836b4a8013a5a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc index afe3088d4..fac0d73aa 100644 --- a/qcsrc/server/cl_weapons.qc +++ b/qcsrc/server/cl_weapons.qc @@ -17,7 +17,7 @@ void W_SwitchWeapon(float imp) { W_TriggerReload(); } -}; +} .float weaponcomplainindex; float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing) @@ -137,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) { @@ -161,14 +170,20 @@ float W_WeaponBit(float wpn) float W_AmmoItemCode(float wpn) { - return (get_weaponinfo(wpn)).items; + return (get_weaponinfo(wpn)).items & IT_AMMO; } +.float savenextthink; void thrown_wep_think() { - self.solid = SOLID_TRIGGER; self.owner = world; - SUB_SetFade(self, time + 20, 1); + float timeleft = self.savenextthink - time; + if(timeleft > 1) + SUB_SetFade(self, self.savenextthink - 1, 1); + else if(timeleft > 0) + SUB_SetFade(self, time, timeleft); + else + SUB_VanishOrRemove(self); } // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count @@ -188,8 +203,35 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto wep.flags |= FL_TOSSED; wep.colormap = own.colormap; + if(W_WeaponBit(wpn) & WEPBIT_SUPERWEAPONS) + { + if(own.items & IT_UNLIMITED_SUPERWEAPONS) + { + wep.superweapons_finished = time + autocvar_g_balance_superweapons_time; + } + else + { + float superweapons = 1; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + if(own.weapons & WEPBIT_SUPERWEAPONS & W_WeaponBit(i)) + ++superweapons; + if(superweapons <= 1) + { + wep.superweapons_finished = own.superweapons_finished; + own.superweapons_finished = 0; + } + else + { + float timeleft = own.superweapons_finished - time; + float weptimeleft = timeleft / superweapons; + wep.superweapons_finished = time + weptimeleft; + own.superweapons_finished -= weptimeleft; + } + } + } + wa = W_AmmoItemCode(wpn); - if(wa == IT_SUPERWEAPON || wa == 0) + if(wa == 0) { oldself = self; self = wep; @@ -199,7 +241,9 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto return string_null; wep.glowmod = own.weaponentity_glowmod; wep.think = thrown_wep_think; - wep.nextthink = time + 0.5; + wep.savenextthink = wep.nextthink; + wep.nextthink = min(wep.nextthink, time + 0.5); + wep.pickup_anyway = TRUE; // these are ALWAYS pickable return ""; } else @@ -211,7 +255,25 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto self = oldself; if(startitem_failed) return string_null; - if(doreduce) + if(doreduce && g_weapon_stay == 2) + { + for(i = 0, j = 1; i < 24; ++i, j *= 2) + { + if(wa & j) + { + ammofield = Item_CounterField(j); + wep.ammofield = 0; + + // 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 + } + } + } + } + else if(doreduce) { for(i = 0, j = 1; i < 24; ++i, j *= 2) { @@ -224,10 +286,10 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto 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) + 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 + own.ammofield += self.(weapon_load[self.weapon]); + self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading } } } @@ -235,7 +297,9 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto } wep.glowmod = own.weaponentity_glowmod; wep.think = thrown_wep_think; - wep.nextthink = time + 0.5; + wep.savenextthink = wep.nextthink; + wep.nextthink = min(wep.nextthink, time + 0.5); + wep.pickup_anyway = TRUE; // these are ALWAYS pickable return s; } } @@ -254,7 +318,7 @@ float W_IsWeaponThrowable(float w) return 0; if (g_cts) return 0; - if (g_nexball && w == WEP_GRENADE_LAUNCHER) + if (g_nexball && w == WEP_PORTO) return 0; wb = W_WeaponBit(w); @@ -263,11 +327,9 @@ float W_IsWeaponThrowable(float w) wa = W_AmmoItemCode(w); if(start_weapons & wb) { - if(wa == IT_SUPERWEAPON && start_items & IT_UNLIMITED_SUPERWEAPONS) - return 0; - if(wa != IT_SUPERWEAPON && start_items & IT_UNLIMITED_WEAPON_AMMO) - return 0; // start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo) + if(start_items & IT_UNLIMITED_WEAPON_AMMO) + return 0; if(wa == 0) return 0; } @@ -278,7 +340,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; @@ -288,8 +350,6 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce) return; if(!autocvar_g_weapon_throwable) return; - if(autocvar_g_weapon_stay == 1) - return; if(self.weaponentity.state != WS_READY) return; if(!W_IsWeaponThrowable(w)) @@ -308,7 +368,7 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce) 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() @@ -359,7 +419,7 @@ void W_WeaponFrame() 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_load = self.(weapon_load[self.switchweapon]); self.clip_size = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); } else @@ -405,14 +465,15 @@ 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; } @@ -459,4 +520,4 @@ void W_WeaponFrame() else self.currentammo = 1; #endif -}; +}