From: Rudolf Polzer <divverent@alientrap.org>
Date: Mon, 16 Jan 2012 11:53:24 +0000 (+0100)
Subject: allow throwing superweapons
X-Git-Tag: xonotic-v0.6.0~157^2~9
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=9c2ce91100ccb6e1b272488411744bf1fe4d4277;p=xonotic%2Fxonotic-data.pk3dir.git

allow throwing superweapons
---

diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc
index 8b3b5e5968..73d610b6c6 100644
--- a/qcsrc/server/cl_weapons.qc
+++ b/qcsrc/server/cl_weapons.qc
@@ -173,11 +173,17 @@ float W_AmmoItemCode(float wpn)
 	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
@@ -197,6 +203,33 @@ 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(self.items & IT_UNLIMITED_SUPERWEAPONS)
+		{
+			wep.superweapons_finished = time + autocvar_g_balance_superweapons_time;
+		}
+		else
+		{
+			float superweapons = 0;
+			for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+				if(self.weapons & WEPBIT_SUPERWEAPONS & W_WeaponBit(i))
+					++superweapons;
+			if(superweapons <= 1)
+			{
+				wep.superweapons_finished = self.superweapons_finished;
+				self.superweapons_finished = 0;
+			}
+			else
+			{
+				float timeleft = self.superweapons_finished - time;
+				float weptimeleft = timeleft / superweapons;
+				wep.superweapons_finished = time + weptimeleft;
+				self.superweapons_finished -= weptimeleft;
+			}
+		}
+	}
+
 	wa = W_AmmoItemCode(wpn);
 	if(wa == 0)
 	{
@@ -208,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
@@ -262,7 +297,8 @@ 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;
 	}
@@ -288,9 +324,6 @@ float W_IsWeaponThrowable(float w)
 	wb = W_WeaponBit(w);
 	if(!wb)
 		return 0;
-	if(!g_minstagib)
-		if(wb & WEPBIT_SUPERWEAPONS) // can't throw a superweapon, they don't work
-			return 0;
 	wa = W_AmmoItemCode(w);
 	if(start_weapons & wb)
 	{
diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc
index 11688ae36a..dcc5c15c88 100644
--- a/qcsrc/server/t_items.qc
+++ b/qcsrc/server/t_items.qc
@@ -168,7 +168,7 @@ void Item_Show (entity e, float mode)
 		e.spawnshieldtime = 1;
 	}
 
-	if (e.strength_finished || e.invincible_finished)
+	if (e.items & (IT_STRENGTH | IT_INVINCIBLE))
 		e.effects |= EF_ADDITIVE | EF_FULLBRIGHT;
 	if (autocvar_g_nodepthtestitems)
 		e.effects |= EF_NODEPTHTEST;
@@ -510,8 +510,24 @@ void Item_Touch (void)
 	if (self.owner == other)
 		return;
 
+	if (self.classname == "droppedweapon")
+	{
+		self.strength_finished = max(0, self.strength_finished - time);
+		self.invincible_finished = max(0, self.invincible_finished - time);
+		self.superweapons_finished = max(0, self.superweapons_finished - time);
+	}
+
 	if(!Item_GiveTo(self, other))
-		return;
+	{
+		if (self.classname == "droppedweapon")
+		{
+			// undo what we did above
+			self.strength_finished += time;
+			self.invincible_finished += time;
+			self.superweapons_finished += time;
+			return;
+		}
+	}
 
 	other.last_pickup = time;
 
@@ -546,11 +562,15 @@ void Item_Reset()
 {
 	Item_Show(self, !self.state);
 	setorigin (self, self.origin);
-	self.think = SUB_Null;
-	self.nextthink = 0;
 
-	if((self.flags & FL_POWERUP) | (self.weapons & WEPBIT_SUPERWEAPONS)) // do not spawn powerups initially!
-		Item_ScheduleInitialRespawn(self);
+	if(self.classname != "droppedweapon")
+	{
+		self.think = SUB_Null;
+		self.nextthink = 0;
+
+		if((self.flags & FL_POWERUP) | (self.weapons & WEPBIT_SUPERWEAPONS)) // do not spawn powerups initially!
+			Item_ScheduleInitialRespawn(self);
+	}
 }
 
 void Item_FindTeam()
@@ -654,7 +674,7 @@ float weapon_pickupevalfunc(entity player, entity item)
 
 float commodity_pickupevalfunc(entity player, entity item)
 {
-	float c, i, need_shells, need_nails, need_rockets, need_cells;
+	float c, i, need_shells, need_nails, need_rockets, need_cells, need_fuel;
 	entity wi;
 	c = 0;
 
@@ -674,6 +694,8 @@ float commodity_pickupevalfunc(entity player, entity item)
 			need_rockets = TRUE;
 		else if(wi.items & IT_CELLS)
 			need_cells = TRUE;
+		else if(wi.items & IT_FUEL)
+			need_cells = TRUE;
 	}
 
 	// TODO: figure out if the player even has the weapon this ammo is for?
@@ -695,6 +717,10 @@ float commodity_pickupevalfunc(entity player, entity item)
 	if (item.ammo_cells)
 	if (player.ammo_cells < g_pickup_cells_max)
 		c = c + max(0, 1 - player.ammo_cells / g_pickup_cells_max);
+	if (need_fuel)
+	if (item.ammo_fuel)
+	if (player.ammo_fuel < g_pickup_fuel_max)
+		c = c + max(0, 1 - player.ammo_fuel / g_pickup_fuel_max);
 	if (item.armorvalue)
 	if (player.armorvalue < item.max_armorvalue)
 		c = c + max(0, 1 - player.armorvalue / item.max_armorvalue);
@@ -721,9 +747,28 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 		self.reset = SUB_Remove;
 		// it's a dropped weapon
 		self.movetype = MOVETYPE_TOSS;
+
 		// Savage: remove thrown items after a certain period of time ("garbage collection")
 		self.think = RemoveItem;
 		self.nextthink = time + 60;
+
+		if(self.strength_finished || self.invincible_finished || self.superweapons_finished)
+		/*
+		if(self.items == 0)
+		if(self.weapons == (self.weapons & WEPBIT_SUPERWEAPONS)) // only superweapons
+		if(self.ammo_nails == 0)
+		if(self.ammo_cells == 0)
+		if(self.ammo_rockets == 0)
+		if(self.ammo_shells == 0)
+		if(self.ammo_fuel == 0)
+		if(self.health == 0)
+		if(self.armorvalue == 0)
+		*/
+		{
+			// if item is worthless after a timer, have it expire then
+			self.nextthink = max(self.strength_finished, self.invincible_finished, self.superweapons_finished);
+		}
+
 		// don't drop if in a NODROP zone (such as lava)
 		traceline(self.origin, self.origin, MOVE_NORMAL, self);
 		if (trace_dpstartcontents & DPCONTENTS_NODROP)
@@ -856,7 +901,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 		self.colormap = 1024; // color shirt=0 pants=0 grey
 	}
 
-	Item_Show(self, 1);
 	self.state = 0;
 	if(self.team)
 	{