From 9d656e2e2c32a525ff8d5b21c2e465f2eccf9e1d Mon Sep 17 00:00:00 2001
From: Samual Lenks <samual@xonotic.org>
Date: Sat, 7 Dec 2013 23:34:20 -0500
Subject: [PATCH] Remove some files that got left over by merge accidentally

---
 qcsrc/server/cl_weapons.qc        | 537 ----------------------
 qcsrc/server/w_crylink.qc         | 727 ------------------------------
 qcsrc/server/w_grenadelauncher.qc | 414 -----------------
 qcsrc/server/w_minelayer.qc       | 563 -----------------------
 qcsrc/server/w_rocketlauncher.qc  | 491 --------------------
 5 files changed, 2732 deletions(-)
 delete mode 100644 qcsrc/server/cl_weapons.qc
 delete mode 100644 qcsrc/server/w_crylink.qc
 delete mode 100644 qcsrc/server/w_grenadelauncher.qc
 delete mode 100644 qcsrc/server/w_minelayer.qc
 delete mode 100644 qcsrc/server/w_rocketlauncher.qc

diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc
deleted file mode 100644
index 88397a8802..0000000000
--- a/qcsrc/server/cl_weapons.qc
+++ /dev/null
@@ -1,537 +0,0 @@
-void W_TriggerReload()
-{
-    weapon_action(self.weapon, WR_RELOAD);
-}
-
-// switch between weapons
-void W_SwitchWeapon(float imp)
-{
-	if (self.switchweapon != imp)
-	{
-		if (client_hasweapon(self, imp, TRUE, TRUE))
-			W_SwitchWeapon_Force(self, imp);
-		else
-			self.selectweapon = imp; // update selectweapon ANYWAY
-	}
-	else
-	{
-		W_TriggerReload();
-	}
-}
-
-.float weaponcomplainindex;
-float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
-{
-	// We cannot tokenize in this function, as GiveItems calls this
-	// function. Thus we must use car/cdr.
-	float weaponwant, first_valid, prev_valid, switchtonext, switchtolast, c;
-	string rest;
-	switchtonext = switchtolast = 0;
-	first_valid = prev_valid = 0;
-	float weaponcur;
-
-	if(skipmissing || pl.selectweapon == 0)
-		weaponcur = pl.switchweapon;
-	else
-		weaponcur = pl.selectweapon;
-
-	if(dir == 0)
-		switchtonext = 1;
-
-	c = 0;
-
-	rest = weaponorder;
-	while(rest != "")
-	{
-		weaponwant = stof(car(rest)); rest = cdr(rest);
-		if(imp >= 0)
-			if((get_weaponinfo(weaponwant)).impulse != imp)
-				continue;
-
-		++c;
-
-		if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE))
-		{
-			if(switchtonext)
-				return weaponwant;
-			if(!first_valid)
-				first_valid = weaponwant;
-			if(weaponwant == weaponcur)
-			{
-				if(dir >= 0)
-					switchtonext = 1;
-				else if(prev_valid)
-					return prev_valid;
-				else
-					switchtolast = 1;
-			}
-			prev_valid = weaponwant;
-		}
-	}
-	if(first_valid)
-	{
-		if(switchtolast)
-			return prev_valid;
-		else
-			return first_valid;
-	}
-	// complain (but only for one weapon on the button that has been pressed)
-	if(complain)
-	{
-		self.weaponcomplainindex += 1;
-		c = mod(self.weaponcomplainindex, c) + 1;
-		rest = weaponorder;
-		while(rest != "")
-		{
-			weaponwant = stof(car(rest)); rest = cdr(rest);
-			if(imp >= 0)
-				if((get_weaponinfo(weaponwant)).impulse != imp)
-					continue;
-
-			--c;
-			if(c == 0)
-			{
-				client_hasweapon(pl, weaponwant, TRUE, TRUE);
-				break;
-			}
-		}
-	}
-	return 0;
-}
-
-void W_CycleWeapon(string weaponorder, float dir)
-{
-	float w;
-	w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE);
-	if(w > 0)
-		W_SwitchWeapon(w);
-}
-
-void W_NextWeaponOnImpulse(float imp)
-{
-	float w;
-	w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
-	if(w > 0)
-		W_SwitchWeapon(w);
-}
-
-// next weapon
-void W_NextWeapon(float list)
-{
-	if(list == 0)
-		W_CycleWeapon(weaponorder_byid, -1);
-	else if(list == 1)
-		W_CycleWeapon(self.weaponorder_byimpulse, -1);
-	else if(list == 2)
-		W_CycleWeapon(self.cvar_cl_weaponpriority, -1);
-}
-
-// prev weapon
-void W_PreviousWeapon(float list)
-{
-	if(list == 0)
-		W_CycleWeapon(weaponorder_byid, +1);
-	else if(list == 1)
-		W_CycleWeapon(self.weaponorder_byimpulse, +1);
-	else if(list == 2)
-		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);
-}
-
-.float savenextthink;
-void thrown_wep_think()
-{
-	self.owner = world;
-	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
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
-{
-	entity oldself, wep;
-	float wa, thisammo, i, j;
-	string s;
-	var .float ammofield;
-
-	wep = spawn();
-
-	setorigin(wep, org);
-	wep.classname = "droppedweapon";
-	wep.velocity = velo;
-	wep.owner = wep.enemy = own;
-	wep.flags |= FL_TOSSED;
-	wep.colormap = own.colormap;
-
-	if(WepSet_FromWeapon(wpn) & WEPSET_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(WepSet_FromWeapon(i) & WEPSET_SUPERWEAPONS)
-					if(own.weapons & WepSet_FromWeapon(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 == 0)
-	{
-		oldself = self;
-		self = wep;
-		weapon_defaultspawnfunc(wpn);
-		self = oldself;
-		if(startitem_failed)
-			return string_null;
-		wep.glowmod = own.weaponentity_glowmod;
-		wep.think = thrown_wep_think;
-		wep.savenextthink = wep.nextthink;
-		wep.nextthink = min(wep.nextthink, time + 0.5);
-		wep.pickup_anyway = TRUE; // these are ALWAYS pickable
-		return "";
-	}
-	else
-	{
-		s = "";
-		oldself = self;
-		self = wep;
-		weapon_defaultspawnfunc(wpn);
-		self = oldself;
-		if(startitem_failed)
-			return string_null;
-		if(doreduce && g_weapon_stay == 2)
-		{
-			for(i = 0, j = 1; i < 24; ++i, j *= 2)
-			{
-				if(wa & j)
-				{
-					ammofield = Item_CounterField(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
-					}
-
-					wep.ammofield = 0;
-				}
-			}
-		}
-		else if(doreduce)
-		{
-			for(i = 0, j = 1; i < 24; ++i, j *= 2)
-			{
-				if(wa & j)
-				{
-					ammofield = Item_CounterField(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
-					}
-
-					thisammo = min(own.ammofield, wep.ammofield);
-					wep.ammofield = thisammo;
-					own.ammofield -= thisammo;
-					s = strcat(s, " and ", ftos(thisammo), " ", Item_CounterFieldName(j));
-				}
-			}
-			s = substring(s, 5, -1);
-		}
-		wep.glowmod = own.weaponentity_glowmod;
-		wep.think = thrown_wep_think;
-		wep.savenextthink = wep.nextthink;
-		wep.nextthink = min(wep.nextthink, time + 0.5);
-		wep.pickup_anyway = TRUE; // these are ALWAYS pickable
-
-		return s;
-	}
-}
-
-float W_IsWeaponThrowable(float w)
-{
-	float wa;
-
-	if (!autocvar_g_pickup_items)
-		return 0;
-	if (g_weaponarena)
-		return 0;
-	if (g_cts)
-		return 0;
-	if (g_nexball && w == WEP_GRENADE_LAUNCHER)
-		return 0;
-    if(w == 0)
-        return 0;
-
-	wa = W_AmmoItemCode(w);
-	if(start_weapons & WepSet_FromWeapon(w))
-	{
-		// 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;
-	}
-
-	return 1;
-}
-
-// toss current weapon
-void W_ThrowWeapon(vector velo, vector delta, float doreduce)
-{
-	float w;
-	string a;
-
-	w = self.weapon;
-	if (w == 0)
-		return; // just in case
-	if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
-		return;
-	if(!autocvar_g_weapon_throwable)
-		return;
-	if(self.weaponentity.state != WS_READY)
-		return;
-	if(!W_IsWeaponThrowable(w))
-		return;
-
-	if(!(self.weapons & WepSet_FromWeapon(w)))
-		return;
-	self.weapons &= ~WepSet_FromWeapon(w);
-
-	W_SwitchWeapon_Force(self, w_getbestweapon(self));
-	a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
-
-	if (!a) return;
-	Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_WEAPON_DROP, a, w);
-}
-
-float forbidWeaponUse()
-{
-	if(time < game_starttime && !autocvar_sv_ready_restart_after_countdown)
-		return 1;
-	if(round_handler_IsActive() && !round_handler_IsRoundStarted())
-		return 1;
-	if(self.player_blocked)
-		return 1;
-	if(self.freezetag_frozen)
-		return 1;
-	return 0;
-}
-
-void W_WeaponFrame()
-{
-	vector fo, ri, up;
-
-	if (frametime)
-		self.weapon_frametime = frametime;
-
-	if (!self.weaponentity || self.health < 1)
-		return; // Dead player can't use weapons and injure impulse commands
-
-	if(forbidWeaponUse())
-	if(self.weaponentity.state != WS_CLEAR)
-	{
-		w_ready();
-		return;
-	}
-
-	if(!self.switchweapon)
-	{
-		self.weapon = 0;
-		self.switchingweapon = 0;
-		self.weaponentity.state = WS_CLEAR;
-		self.weaponname = "";
-		self.items &= ~IT_AMMO;
-		return;
-	}
-
-	makevectors(self.v_angle);
-	fo = v_forward; // save them in case the weapon think functions change it
-	ri = v_right;
-	up = v_up;
-
-	// Change weapon
-	if (self.weapon != self.switchweapon)
-	{
-		if (self.weaponentity.state == WS_CLEAR)
-		{
-			// end switching!
-			self.switchingweapon = self.switchweapon;
-
-			entity newwep = get_weaponinfo(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
-			if(newwep.spawnflags & WEP_FLAG_RELOADABLE && cvar(strcat("g_balance_", newwep.netname, "_reload_ammo"))) // prevent accessing undefined cvars
-			{
-				self.clip_load = self.(weapon_load[self.switchweapon]);
-				self.clip_size = cvar(strcat("g_balance_", newwep.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, cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)), w_ready);
-			//print(sprintf("W_WeaponFrame(): cvar: %s, value: %f\n", sprintf("g_balance_%s_switchdelay_raise", newwep.netname), cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname))));
-			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;
-
-			entity oldwep = get_weaponinfo(self.weapon);
-
-#ifndef INDEPENDENT_ATTACK_FINISHED
-			if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5)
-			{
-#endif
-			sound (self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTEN_NORM);
-			self.weaponentity.state = WS_DROP;
-			// set up weapon switch think in the future, and start drop anim
-			weapon_thinkf(WFRAME_DONTCHANGE, cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)), w_clear);
-			//print(sprintf("W_WeaponFrame(): cvar: %s, value: %f\n", sprintf("g_balance_%s_switchdelay_drop", oldwep.netname), cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname))));
-			weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, PLAYER_WEAPONSELECTION_RANGE);
-#ifndef INDEPENDENT_ATTACK_FINISHED
-			}
-#endif
-		}
-	}
-
-	// LordHavoc: network timing test code
-	//if (self.button0)
-	//	print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(self)), " >= ", ftos(self.weapon_nextthink), "\n");
-
-	float w;
-	w = self.weapon;
-
-	// 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
-	float c;
-	c = 0;
-	while (c < W_TICSPERFRAME)
-	{
-		c = c + 1;
-		if(w && !(self.weapons & WepSet_FromWeapon(w)))
-		{
-			if(self.weapon == self.switchweapon)
-				W_SwitchWeapon_Force(self, w_getbestweapon(self));
-			w = 0;
-		}
-
-		v_forward = fo;
-		v_right = ri;
-		v_up = up;
-
-		if(w)
-			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)
-			{
-				v_forward = fo;
-				v_right = ri;
-				v_up = up;
-				self.weapon_think();
-			}
-			else
-				bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n");
-		}
-	}
-
-	// don't let attack_finished fall behind when not firing (must be after weapon_setup calls!)
-	//if (ATTACK_FINISHED(self) < time)
-	//	ATTACK_FINISHED(self) = time;
-
-	//if (self.weapon_nextthink < time)
-	//	self.weapon_nextthink = time;
-
-	// update currentammo incase it has changed
-#if 0
-	if (self.items & IT_CELLS)
-		self.currentammo = self.ammo_cells;
-	else if (self.items & IT_ROCKETS)
-		self.currentammo = self.ammo_rockets;
-	else if (self.items & IT_NAILS)
-		self.currentammo = self.ammo_nails;
-	else if (self.items & IT_SHELLS)
-		self.currentammo = self.ammo_shells;
-	else
-		self.currentammo = 1;
-#endif
-}
-
-string W_Apply_Weaponreplace(string in)
-{
-	float n = tokenize_console(in);
-	string out = "";
-	float i;
-	for(i = 0; i < n; ++i)
-	{
-		string s = argv(i);
-		string r = cvar_string(strcat("g_weaponreplace_", s));
-		if(r == "")
-			out = strcat(out, " ", s);
-		else if(r != "0")
-			out = strcat(out, " ", r);
-	}
-	return substring(out, 1, -1);
-}
diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc
deleted file mode 100644
index f7ad7583d1..0000000000
--- a/qcsrc/server/w_crylink.qc
+++ /dev/null
@@ -1,727 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ CRYLINK,
-/* function  */ w_crylink,
-/* ammotype  */ IT_CELLS,
-/* impulse   */ 6,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* model     */ "crylink",
-/* shortname */ "crylink",
-/* fullname  */ _("Crylink")
-);
-#else
-#ifdef SVQC
-.float gravity;
-.float crylink_waitrelease;
-.entity crylink_lastgroup;
-
-.entity queuenext;
-.entity queueprev;
-
-void W_Crylink_CheckLinks(entity e)
-{
-	float i;
-	entity p;
-
-	if(e == world)
-		error("W_Crylink_CheckLinks: entity is world");
-	if(e.classname != "spike" || wasfreed(e))
-		error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e)));
-
-	p = e;
-	for(i = 0; i < 1000; ++i)
-	{
-		if(p.queuenext.queueprev != p || p.queueprev.queuenext != p)
-			error("W_Crylink_CheckLinks: queue is inconsistent");
-		p = p.queuenext;
-		if(p == e)
-			break;
-	}
-	if(i >= 1000)
-		error("W_Crylink_CheckLinks: infinite chain");
-}
-
-void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next)
-{
-	W_Crylink_CheckLinks(next);
-	if(me == own.crylink_lastgroup)
-		own.crylink_lastgroup = ((me == next) ? world : next);
-	prev.queuenext = next;
-	next.queueprev = prev;
-	me.classname = "spike_oktoremove";
-	if(me != next)
-		W_Crylink_CheckLinks(next);
-}
-
-void W_Crylink_Dequeue(entity e)
-{
-	W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext);
-}
-
-void W_Crylink_Reset(void)
-{
-	W_Crylink_Dequeue(self);
-	remove(self);
-}
-
-// force projectile to explode
-void W_Crylink_LinkExplode (entity e, entity e2)
-{
-	float a;
-
-	if(e == e2)
-		return;
-
-	a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
-
-	if(e == e.realowner.crylink_lastgroup)
-		e.realowner.crylink_lastgroup = world;
-
-	if(e.projectiledeathtype & HITTYPE_SECONDARY)
-		RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other);
-	else
-		RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other);
-
-	W_Crylink_LinkExplode(e.queuenext, e2);
-
-	e.classname = "spike_oktoremove";
-	remove (e);
-}
-
-// adjust towards center
-// returns the origin where they will meet... and the time till the meeting is
-// stored in w_crylink_linkjoin_time.
-// could possibly network this origin and time, and display a special particle
-// effect when projectiles meet there :P
-// jspeed: joining speed (calculate this as join spread * initial speed)
-float w_crylink_linkjoin_time;
-vector W_Crylink_LinkJoin(entity e, float jspeed)
-{
-	vector avg_origin, avg_velocity;
-	vector targ_origin;
-	float avg_dist, n;
-	entity p;
-
-	// FIXME remove this debug code
-	W_Crylink_CheckLinks(e);
-
-	w_crylink_linkjoin_time = 0;
-
-	avg_origin = e.origin;
-	avg_velocity = e.velocity;
-	n = 1;
-	for(p = e; (p = p.queuenext) != e; )
-	{
-		avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin);
-		avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity);
-		++n;
-	}
-	avg_origin *= (1.0 / n);
-	avg_velocity *= (1.0 / n);
-
-	if(n < 2)
-		return avg_origin; // nothing to do
-
-	// yes, mathematically we can do this in ONE step, but beware of 32bit floats...
-	avg_dist = pow(vlen(e.origin - avg_origin), 2);
-	for(p = e; (p = p.queuenext) != e; )
-		avg_dist += pow(vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin), 2);
-	avg_dist *= (1.0 / n);
-	avg_dist = sqrt(avg_dist);
-
-	if(avg_dist == 0)
-		return avg_origin; // no change needed
-
-	if(jspeed == 0)
-	{
-		e.velocity = avg_velocity;
-		UpdateCSQCProjectile(e);
-		for(p = e; (p = p.queuenext) != e; )
-		{
-			p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity);
-			UpdateCSQCProjectile(p);
-		}
-		targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE
-	}
-	else
-	{
-			w_crylink_linkjoin_time = avg_dist / jspeed;
-		targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity;
-
-		e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time);
-		UpdateCSQCProjectile(e);
-		for(p = e; (p = p.queuenext) != e; )
-		{
-			p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time));
-			UpdateCSQCProjectile(p);
-		}
-
-		// analysis:
-		//   jspeed -> +infinity:
-		//      w_crylink_linkjoin_time -> +0
-		//      targ_origin -> avg_origin
-		//      p->velocity -> HUEG towards center
-		//   jspeed -> 0:
-		//      w_crylink_linkjoin_time -> +/- infinity
-		//      targ_origin -> avg_velocity * +/- infinity
-		//      p->velocity -> avg_velocity
-		//   jspeed -> -infinity:
-		//      w_crylink_linkjoin_time -> -0
-		//      targ_origin -> avg_origin
-		//      p->velocity -> HUEG away from center
-	}
-
-	W_Crylink_CheckLinks(e);
-
-	return targ_origin;
-}
-
-void W_Crylink_LinkJoinEffect_Think()
-{
-	// is there at least 2 projectiles very close?
-	entity e, p;
-	float n;
-	e = self.owner.crylink_lastgroup;
-	n = 0;
-	if(e)
-	{
-		if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime)
-			++n;
-		for(p = e; (p = p.queuenext) != e; )
-		{
-			if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime)
-				++n;
-		}
-		if(n >= 2)
-		{
-			if(e.projectiledeathtype & HITTYPE_SECONDARY)
-			{
-				if(autocvar_g_balance_crylink_secondary_joinexplode)
-				{
-					n = n / autocvar_g_balance_crylink_secondary_shots;
-					RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_joinexplode_damage * n,
-									autocvar_g_balance_crylink_secondary_joinexplode_edgedamage * n,
-									autocvar_g_balance_crylink_secondary_joinexplode_radius * n, e.realowner,
-									autocvar_g_balance_crylink_secondary_joinexplode_force * n, e.projectiledeathtype, other);
-
-					pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
-				}
-			}
-			else
-			{
-				if(autocvar_g_balance_crylink_primary_joinexplode)
-				{
-					n = n / autocvar_g_balance_crylink_primary_shots;
-					RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_joinexplode_damage * n,
-									autocvar_g_balance_crylink_primary_joinexplode_edgedamage * n,
-									autocvar_g_balance_crylink_primary_joinexplode_radius * n, e.realowner,
-									autocvar_g_balance_crylink_primary_joinexplode_force * n, e.projectiledeathtype, other);
-
-					pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
-				}
-			}
-		}
-	}
-	remove(self);
-}
-
-float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
-{
-	entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE);
-	float hit_friendly = 0;
-	float hit_enemy = 0;
-
-	while(head)
-	{
-		if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO))
-		{
-			if(SAME_TEAM(head, projectile.realowner))
-				++hit_friendly;
-			else
-				++hit_enemy;
-		}
-
-		head = head.chain;
-	}
-
-	return (hit_enemy ? FALSE : hit_friendly);
-}
-
-// NO bounce protection, as bounces are limited!
-void W_Crylink_Touch (void)
-{
-	float finalhit;
-	float f;
-	PROJECTILE_TOUCH;
-
-	float a;
-	a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1);
-
-	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
-	if(finalhit)
-		f = 1;
-	else
-		f = autocvar_g_balance_crylink_primary_bouncedamagefactor;
-	if(a)
-		f *= a;
-
-	float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other);
-
-	if(totaldamage && ((autocvar_g_balance_crylink_primary_linkexplode == 2) || ((autocvar_g_balance_crylink_primary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_primary_radius))))
-	{
-		if(self == self.realowner.crylink_lastgroup)
-			self.realowner.crylink_lastgroup = world;
-		W_Crylink_LinkExplode(self.queuenext, self);
-		self.classname = "spike_oktoremove";
-		remove (self);
-		return;
-	}
-	else if(finalhit)
-	{
-		// just unlink
-		W_Crylink_Dequeue(self);
-		remove(self);
-		return;
-	}
-	self.cnt = self.cnt - 1;
-	self.angles = vectoangles(self.velocity);
-	self.owner = world;
-	self.projectiledeathtype |= HITTYPE_BOUNCE;
-	// commented out as it causes a little hitch...
-	//if(proj.cnt == 0)
-	//	CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE);
-}
-
-void W_Crylink_Touch2 (void)
-{
-	float finalhit;
-	float f;
-	PROJECTILE_TOUCH;
-
-	float a;
-	a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1);
-
-	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
-	if(finalhit)
-		f = 1;
-	else
-		f = autocvar_g_balance_crylink_secondary_bouncedamagefactor;
-	if(a)
-		f *= a;
-
-	float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other);
-
-	if(totaldamage && ((autocvar_g_balance_crylink_secondary_linkexplode == 2) || ((autocvar_g_balance_crylink_secondary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_secondary_radius))))
-	{
-		if(self == self.realowner.crylink_lastgroup)
-			self.realowner.crylink_lastgroup = world;
-		W_Crylink_LinkExplode(self.queuenext, self);
-		self.classname = "spike_oktoremove";
-		remove (self);
-		return;
-	}
-	else if(finalhit)
-	{
-		// just unlink
-		W_Crylink_Dequeue(self);
-		remove(self);
-		return;
-	}
-	self.cnt = self.cnt - 1;
-	self.angles = vectoangles(self.velocity);
-	self.owner = world;
-	self.projectiledeathtype |= HITTYPE_BOUNCE;
-	// commented out as it causes a little hitch...
-	//if(proj.cnt == 0)
-	//	CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE);
-}
-
-void W_Crylink_Fadethink (void)
-{
-	W_Crylink_Dequeue(self);
-	remove(self);
-}
-
-void W_Crylink_Attack (void)
-{
-	float counter, shots;
-	entity proj, prevproj, firstproj;
-	vector s;
-	vector forward, right, up;
-	float maxdmg;
-
-	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_reload_ammo);
-
-	maxdmg = autocvar_g_balance_crylink_primary_damage*autocvar_g_balance_crylink_primary_shots;
-	maxdmg *= 1 + autocvar_g_balance_crylink_primary_bouncedamagefactor * autocvar_g_balance_crylink_primary_bounces;
-	if(autocvar_g_balance_crylink_primary_joinexplode)
-		maxdmg += autocvar_g_balance_crylink_primary_joinexplode_damage;
-
-	W_SetupShot (self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg);
-	forward = v_forward;
-	right = v_right;
-	up = v_up;
-
-	shots = autocvar_g_balance_crylink_primary_shots;
-	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
-	proj = prevproj = firstproj = world;
-	for(counter = 0; counter < shots; ++counter)
-	{
-		proj = spawn ();
-		proj.reset = W_Crylink_Reset;
-		proj.realowner = proj.owner = self;
-		proj.classname = "spike";
-		proj.bot_dodge = TRUE;
-		proj.bot_dodgerating = autocvar_g_balance_crylink_primary_damage;
-		if(shots == 1) {
-			proj.queuenext = proj;
-			proj.queueprev = proj;
-		}
-		else if(counter == 0) { // first projectile, store in firstproj for now
-			firstproj = proj;
-		}
-		else if(counter == shots - 1) { // last projectile, link up with first projectile
-			prevproj.queuenext = proj;
-			firstproj.queueprev = proj;
-			proj.queuenext = firstproj;
-			proj.queueprev = prevproj;
-		}
-		else { // else link up with previous projectile
-			prevproj.queuenext = proj;
-			proj.queueprev = prevproj;
-		}
-
-		prevproj = proj;
-
-		proj.movetype = MOVETYPE_BOUNCEMISSILE;
-		PROJECTILE_MAKETRIGGER(proj);
-		proj.projectiledeathtype = WEP_CRYLINK;
-		//proj.gravity = 0.001;
-
-		setorigin (proj, w_shotorg);
-		setsize(proj, '0 0 0', '0 0 0');
-
-
-		s = '0 0 0';
-		if (counter == 0)
-			s = '0 0 0';
-		else
-		{
-			makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
-			s_y = v_forward_x;
-			s_z = v_forward_y;
-		}
-		s = s * autocvar_g_balance_crylink_primary_spread * g_weaponspreadfactor;
-		W_SetupProjectileVelocityEx(proj, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_crylink_primary_speed, 0, 0, 0, FALSE);
-		proj.touch = W_Crylink_Touch;
-
-		proj.think = W_Crylink_Fadethink;
-		if(counter == 0)
-		{
-			proj.fade_time = time + autocvar_g_balance_crylink_primary_middle_lifetime;
-			proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_middle_fadetime;
-			proj.nextthink = time + autocvar_g_balance_crylink_primary_middle_lifetime + autocvar_g_balance_crylink_primary_middle_fadetime;
-		}
-		else
-		{
-			proj.fade_time = time + autocvar_g_balance_crylink_primary_other_lifetime;
-			proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_other_fadetime;
-			proj.nextthink = time + autocvar_g_balance_crylink_primary_other_lifetime + autocvar_g_balance_crylink_primary_other_fadetime;
-		}
-		proj.teleport_time = time + autocvar_g_balance_crylink_primary_joindelay;
-		proj.cnt = autocvar_g_balance_crylink_primary_bounces;
-		//proj.scale = 1 + 1 * proj.cnt;
-
-		proj.angles = vectoangles (proj.velocity);
-
-		//proj.glow_size = 20;
-
-		proj.flags = FL_PROJECTILE;
-    proj.missile_flags = MIF_SPLASH;
-
-		CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
-
-		other = proj; MUTATOR_CALLHOOK(EditProjectile);
-	}
-	if(autocvar_g_balance_crylink_primary_joinspread != 0)
-	{
-		self.crylink_lastgroup = proj;
-		W_Crylink_CheckLinks(proj);
-		self.crylink_waitrelease = 1;
-	}
-}
-
-void W_Crylink_Attack2 (void)
-{
-	float counter, shots;
-	entity proj, prevproj, firstproj;
-	vector s;
-	vector forward, right, up;
-	float maxdmg;
-
-	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo);
-
-	maxdmg = autocvar_g_balance_crylink_secondary_damage*autocvar_g_balance_crylink_secondary_shots;
-	maxdmg *= 1 + autocvar_g_balance_crylink_secondary_bouncedamagefactor * autocvar_g_balance_crylink_secondary_bounces;
-	if(autocvar_g_balance_crylink_secondary_joinexplode)
-		maxdmg += autocvar_g_balance_crylink_secondary_joinexplode_damage;
-
-	W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg);
-	forward = v_forward;
-	right = v_right;
-	up = v_up;
-
-	shots = autocvar_g_balance_crylink_secondary_shots;
-	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
-	proj = prevproj = firstproj = world;
-	for(counter = 0; counter < shots; ++counter)
-	{
-		proj = spawn ();
-		proj.reset = W_Crylink_Reset;
-		proj.realowner = proj.owner = self;
-		proj.classname = "spike";
-		proj.bot_dodge = TRUE;
-		proj.bot_dodgerating = autocvar_g_balance_crylink_secondary_damage;
-		if(shots == 1) {
-			proj.queuenext = proj;
-			proj.queueprev = proj;
-		}
-		else if(counter == 0) { // first projectile, store in firstproj for now
-			firstproj = proj;
-		}
-		else if(counter == shots - 1) { // last projectile, link up with first projectile
-			prevproj.queuenext = proj;
-			firstproj.queueprev = proj;
-			proj.queuenext = firstproj;
-			proj.queueprev = prevproj;
-		}
-		else { // else link up with previous projectile
-			prevproj.queuenext = proj;
-			proj.queueprev = prevproj;
-		}
-
-		prevproj = proj;
-
-		proj.movetype = MOVETYPE_BOUNCEMISSILE;
-		PROJECTILE_MAKETRIGGER(proj);
-		proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY;
-		//proj.gravity = 0.001;
-
-		setorigin (proj, w_shotorg);
-		setsize(proj, '0 0 0', '0 0 0');
-
-		if(autocvar_g_balance_crylink_secondary_spreadtype == 1)
-		{
-			s = '0 0 0';
-			if (counter == 0)
-				s = '0 0 0';
-			else
-			{
-				makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
-				s_y = v_forward_x;
-				s_z = v_forward_y;
-			}
-			s = s * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor;
-			s = w_shotdir + right * s_y + up * s_z;
-		}
-		else
-		{
-			s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor);
-		}
-
-		W_SetupProjectileVelocityEx(proj, s, v_up, autocvar_g_balance_crylink_secondary_speed, 0, 0, 0, FALSE);
-		proj.touch = W_Crylink_Touch2;
-		proj.think = W_Crylink_Fadethink;
-		if(counter == (shots - 1) / 2)
-		{
-			proj.fade_time = time + autocvar_g_balance_crylink_secondary_middle_lifetime;
-			proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_middle_fadetime;
-			proj.nextthink = time + autocvar_g_balance_crylink_secondary_middle_lifetime + autocvar_g_balance_crylink_secondary_middle_fadetime;
-		}
-		else
-		{
-			proj.fade_time = time + autocvar_g_balance_crylink_secondary_line_lifetime;
-			proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_line_fadetime;
-			proj.nextthink = time + autocvar_g_balance_crylink_secondary_line_lifetime + autocvar_g_balance_crylink_secondary_line_fadetime;
-		}
-		proj.teleport_time = time + autocvar_g_balance_crylink_secondary_joindelay;
-		proj.cnt = autocvar_g_balance_crylink_secondary_bounces;
-		//proj.scale = 1 + 1 * proj.cnt;
-
-		proj.angles = vectoangles (proj.velocity);
-
-		//proj.glow_size = 20;
-
-		proj.flags = FL_PROJECTILE;
-        proj.missile_flags = MIF_SPLASH;
-
-		CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
-
-		other = proj; MUTATOR_CALLHOOK(EditProjectile);
-	}
-	if(autocvar_g_balance_crylink_secondary_joinspread != 0)
-	{
-		self.crylink_lastgroup = proj;
-		W_Crylink_CheckLinks(proj);
-		self.crylink_waitrelease = 2;
-	}
-}
-
-void spawnfunc_weapon_crylink (void)
-{
-	weapon_defaultspawnfunc(WEP_CRYLINK);
-}
-
-float w_crylink(float req)
-{
-	float ammo_amount;
-	if (req == WR_AIM)
-	{
-		if (random() < 0.10)
-			self.BUTTON_ATCK = bot_aim(autocvar_g_balance_crylink_primary_speed, 0, autocvar_g_balance_crylink_primary_middle_lifetime, FALSE);
-		else
-			self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_crylink_secondary_speed, 0, autocvar_g_balance_crylink_secondary_middle_lifetime, FALSE);
-	}
-	else if (req == WR_THINK)
-	{
-		if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)) // forced reload
-			weapon_action(self.weapon, WR_RELOAD);
-
-		if (self.BUTTON_ATCK)
-		{
-			if (self.crylink_waitrelease != 1)
-			if (weapon_prepareattack(0, autocvar_g_balance_crylink_primary_refire))
-			{
-				W_Crylink_Attack();
-				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_crylink_primary_animtime, w_ready);
-			}
-		}
-
-		if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary)
-		{
-			if (self.crylink_waitrelease != 2)
-			if (weapon_prepareattack(1, autocvar_g_balance_crylink_secondary_refire))
-			{
-				W_Crylink_Attack2();
-				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_crylink_secondary_animtime, w_ready);
-			}
-		}
-
-		if ((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2))
-		{
-			if (!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time)
-			{
-				// fired and released now!
-				if(self.crylink_lastgroup)
-				{
-					vector pos;
-					entity linkjoineffect;
-
-					if(self.crylink_waitrelease == 1)
-					{
-						pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_primary_joinspread * autocvar_g_balance_crylink_primary_speed);
-
-					}
-					else
-					{
-						pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_secondary_joinspread * autocvar_g_balance_crylink_secondary_speed);
-					}
-
-					linkjoineffect = spawn();
-					linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
-					linkjoineffect.classname = "linkjoineffect";
-					linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
-					linkjoineffect.owner = self;
-					setorigin(linkjoineffect, pos);
-				}
-				self.crylink_waitrelease = 0;
-				if(!w_crylink(WR_CHECKAMMO1) && !w_crylink(WR_CHECKAMMO2))
-				if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-				{
-					// ran out of ammo!
-					self.cnt = WEP_CRYLINK;
-					self.switchweapon = w_getbestweapon(self);
-				}
-			}
-		}
-	}
-	else if (req == WR_PRECACHE)
-	{
-		precache_model ("models/weapons/g_crylink.md3");
-		precache_model ("models/weapons/v_crylink.md3");
-		precache_model ("models/weapons/h_crylink.iqm");
-		precache_sound ("weapons/crylink_fire.wav");
-		precache_sound ("weapons/crylink_fire2.wav");
-		precache_sound ("weapons/crylink_linkjoin.wav");
-		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
-	}
-	else if (req == WR_SETUP)
-	{
-		weapon_setup(WEP_CRYLINK);
-		self.current_ammo = ammo_cells;
-	}
-	else if (req == WR_CHECKAMMO1)
-	{
-		// don't "run out of ammo" and switch weapons while waiting for release
-		if(self.crylink_lastgroup && self.crylink_waitrelease)
-			return TRUE;
-
-		ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo;
-		ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo;
-		return ammo_amount;
-	}
-	else if (req == WR_CHECKAMMO2)
-	{
-		// don't "run out of ammo" and switch weapons while waiting for release
-		if(self.crylink_lastgroup && self.crylink_waitrelease)
-			return TRUE;
-
-		ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo;
-		ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo;
-		return ammo_amount;
-	}
-	else if (req == WR_RELOAD)
-	{
-		W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav");
-	}
-	else if (req == WR_SUICIDEMESSAGE)
-	{
-		return WEAPON_CRYLINK_SUICIDE;
-	}
-	else if (req == WR_KILLMESSAGE)
-	{
-		return WEAPON_CRYLINK_MURDER;
-	}
-	return TRUE;
-}
-#endif
-#ifdef CSQC
-float w_crylink(float req)
-{
-	if(req == WR_IMPACTEFFECT)
-	{
-		vector org2;
-		org2 = w_org + w_backoff * 2;
-		if(w_deathtype & HITTYPE_SECONDARY)
-		{
-			pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTEN_NORM);
-		}
-		else
-		{
-			pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTEN_NORM);
-		}
-	}
-	else if(req == WR_PRECACHE)
-	{
-		precache_sound("weapons/crylink_impact2.wav");
-		precache_sound("weapons/crylink_impact.wav");
-	}
-	return TRUE;
-}
-#endif
-#endif
diff --git a/qcsrc/server/w_grenadelauncher.qc b/qcsrc/server/w_grenadelauncher.qc
deleted file mode 100644
index 17144d3a53..0000000000
--- a/qcsrc/server/w_grenadelauncher.qc
+++ /dev/null
@@ -1,414 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ GRENADE_LAUNCHER,
-/* function  */ w_glauncher,
-/* ammotype  */ IT_ROCKETS,
-/* impulse   */ 4,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* model     */ "gl",
-/* shortname */ "grenadelauncher",
-/* fullname  */ _("Mortar")
-);
-#else
-#ifdef SVQC
-.float gl_detonate_later;
-.float gl_bouncecnt;
-
-void W_Grenade_Explode (void)
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	if(self.movetype == MOVETYPE_NONE)
-		self.velocity = self.oldvelocity;
-
-	RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other);
-
-	remove (self);
-}
-
-void W_Grenade_Explode2 (void)
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	if(self.movetype == MOVETYPE_NONE)
-		self.velocity = self.oldvelocity;
-
-	RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other);
-
-	remove (self);
-}
-
-void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if (self.health <= 0)
-		return;
-
-	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt
-
-	self.health = self.health - damage;
-
-	if (self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, self.use);
-}
-
-void W_Grenade_Think1 (void)
-{
-	self.nextthink = time;
-	if (time > self.cnt)
-	{
-		other = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		W_Grenade_Explode ();
-		return;
-	}
-	if(self.gl_detonate_later && self.gl_bouncecnt >= autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt)
-		W_Grenade_Explode();
-}
-
-void W_Grenade_Touch1 (void)
-{
-	PROJECTILE_TOUCH;
-	if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_primary_type == 0) // always explode when hitting a player, or if normal mortar projectile
-	{
-		self.use ();
-	}
-	else if (autocvar_g_balance_grenadelauncher_primary_type == 1) // bounce
-	{
-		float r;
-		r = random() * 6;
-		if(r < 1)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 2)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 3)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 4)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 5)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM);
-		else
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM);
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		self.gl_bouncecnt += 1;
-	}
-	else if(autocvar_g_balance_grenadelauncher_primary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
-	{
-		spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM);
-
-		// let it stick whereever it is
-		self.oldvelocity = self.velocity;
-		self.velocity = '0 0 0';
-		self.movetype = MOVETYPE_NONE; // also disables gravity
-		self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
-		UpdateCSQCProjectile(self);
-
-		// do not respond to any more touches
-		self.solid = SOLID_NOT;
-
-		self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_primary_lifetime_stick);
-	}
-}
-
-void W_Grenade_Touch2 (void)
-{
-	PROJECTILE_TOUCH;
-	if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_secondary_type == 0) // always explode when hitting a player, or if normal mortar projectile
-	{
-		self.use ();
-	}
-	else if (autocvar_g_balance_grenadelauncher_secondary_type == 1) // bounce
-	{
-		float r;
-		r = random() * 6;
-		if(r < 1)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 2)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 3)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 4)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM);
-		else if(r < 5)
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM);
-		else
-			spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM);
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		self.gl_bouncecnt += 1;
-
-		if (autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce && self.gl_bouncecnt == 1)
-			self.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce;
-
-	}
-	else if(autocvar_g_balance_grenadelauncher_secondary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
-	{
-		spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM);
-
-		// let it stick whereever it is
-		self.oldvelocity = self.velocity;
-		self.velocity = '0 0 0';
-		self.movetype = MOVETYPE_NONE; // also disables gravity
-		self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
-		UpdateCSQCProjectile(self);
-
-		// do not respond to any more touches
-		self.solid = SOLID_NOT;
-
-		self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_secondary_lifetime_stick);
-	}
-}
-
-void W_Grenade_Attack (void)
-{
-	entity gren;
-
-	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo);
-
-	W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_primary_damage);
-	w_shotdir = v_forward; // no TrueAim for grenades please
-
-	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	gren = spawn ();
-	gren.owner = gren.realowner = self;
-	gren.classname = "grenade";
-	gren.bot_dodge = TRUE;
-	gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_primary_damage;
-	gren.movetype = MOVETYPE_BOUNCE;
-	gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor;
-	gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop;
-	PROJECTILE_MAKETRIGGER(gren);
-	gren.projectiledeathtype = WEP_GRENADE_LAUNCHER;
-	setorigin(gren, w_shotorg);
-	setsize(gren, '-3 -3 -3', '3 3 3');
-
-	gren.cnt = time + autocvar_g_balance_grenadelauncher_primary_lifetime;
-	gren.nextthink = time;
-	gren.think = W_Grenade_Think1;
-	gren.use = W_Grenade_Explode;
-	gren.touch = W_Grenade_Touch1;
-
-	gren.takedamage = DAMAGE_YES;
-	gren.health = autocvar_g_balance_grenadelauncher_primary_health;
-	gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale;
-	gren.event_damage = W_Grenade_Damage;
-	gren.damagedbycontents = TRUE;
-	gren.missile_flags = MIF_SPLASH | MIF_ARC;
-	W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
-
-	gren.angles = vectoangles (gren.velocity);
-	gren.flags = FL_PROJECTILE;
-
-	if(autocvar_g_balance_grenadelauncher_primary_type == 0 || autocvar_g_balance_grenadelauncher_primary_type == 2)
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
-	else
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
-
-	other = gren; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_Grenade_Attack2 (void)
-{
-	entity gren;
-
-	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_secondary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo);
-
-	W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_secondary_damage);
-	w_shotdir = v_forward; // no TrueAim for grenades please
-
-	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	gren = spawn ();
-	gren.owner = gren.realowner = self;
-	gren.classname = "grenade";
-	gren.bot_dodge = TRUE;
-	gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_secondary_damage;
-	gren.movetype = MOVETYPE_BOUNCE;
-	gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor;
-	gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop;
-	PROJECTILE_MAKETRIGGER(gren);
-	gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY;
-	setorigin(gren, w_shotorg);
-	setsize(gren, '-3 -3 -3', '3 3 3');
-
-	gren.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime;
-	gren.think = adaptor_think2use_hittype_splash;
-	gren.use = W_Grenade_Explode2;
-	gren.touch = W_Grenade_Touch2;
-
-	gren.takedamage = DAMAGE_YES;
-	gren.health = autocvar_g_balance_grenadelauncher_secondary_health;
-	gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale;
-	gren.event_damage = W_Grenade_Damage;
-	gren.damagedbycontents = TRUE;
-	gren.missile_flags = MIF_SPLASH | MIF_ARC;
-	W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary);
-
-	gren.angles = vectoangles (gren.velocity);
-	gren.flags = FL_PROJECTILE;
-
-	if(autocvar_g_balance_grenadelauncher_secondary_type == 0 || autocvar_g_balance_grenadelauncher_secondary_type == 2)
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
-	else
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
-
-	other = gren; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void spawnfunc_weapon_grenadelauncher (void)
-{
-	weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER);
-}
-
-.float bot_secondary_grenademooth;
-float w_glauncher(float req)
-{
-	entity nade;
-	float nadefound;
-	float ammo_amount;
-
-	if (req == WR_AIM)
-	{
-		self.BUTTON_ATCK = FALSE;
-		self.BUTTON_ATCK2 = FALSE;
-		if (self.bot_secondary_grenademooth == 0)
-		{
-			if(bot_aim(autocvar_g_balance_grenadelauncher_primary_speed, autocvar_g_balance_grenadelauncher_primary_speed_up, autocvar_g_balance_grenadelauncher_primary_lifetime, TRUE))
-			{
-				self.BUTTON_ATCK = TRUE;
-				if(random() < 0.01) self.bot_secondary_grenademooth = 1;
-			}
-		}
-		else
-		{
-			if(bot_aim(autocvar_g_balance_grenadelauncher_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_grenadelauncher_secondary_lifetime, TRUE))
-			{
-				self.BUTTON_ATCK2 = TRUE;
-				if(random() < 0.02) self.bot_secondary_grenademooth = 0;
-			}
-		}
-	}
-	else if (req == WR_THINK)
-	{
-		if(autocvar_g_balance_grenadelauncher_reload_ammo && self.clip_load < min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)) // forced reload
-			weapon_action(self.weapon, WR_RELOAD);
-		else if (self.BUTTON_ATCK)
-		{
-			if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire))
-			{
-				W_Grenade_Attack();
-				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready);
-			}
-		}
-		else if (self.BUTTON_ATCK2)
-		{
-			if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary"))
-			{
-				nadefound = 0;
-				for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self)
-				{
-					if(!nade.gl_detonate_later)
-					{
-						nade.gl_detonate_later = TRUE;
-						nadefound = 1;
-					}
-				}
-				if(nadefound)
-					sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM);
-			}
-			else if (weapon_prepareattack(1, autocvar_g_balance_grenadelauncher_secondary_refire))
-			{
-				W_Grenade_Attack2();
-				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_grenadelauncher_secondary_animtime, w_ready);
-			}
-		}
-	}
-	else if (req == WR_PRECACHE)
-	{
-		precache_model ("models/weapons/g_gl.md3");
-		precache_model ("models/weapons/v_gl.md3");
-		precache_model ("models/weapons/h_gl.iqm");
-		precache_sound ("weapons/grenade_bounce1.wav");
-		precache_sound ("weapons/grenade_bounce2.wav");
-		precache_sound ("weapons/grenade_bounce3.wav");
-		precache_sound ("weapons/grenade_bounce4.wav");
-		precache_sound ("weapons/grenade_bounce5.wav");
-		precache_sound ("weapons/grenade_bounce6.wav");
-		precache_sound ("weapons/grenade_stick.wav");
-		precache_sound ("weapons/grenade_fire.wav");
-		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
-	}
-	else if (req == WR_SETUP)
-	{
-		weapon_setup(WEP_GRENADE_LAUNCHER);
-		self.current_ammo = ammo_rockets;
-	}
-	else if (req == WR_CHECKAMMO1)
-	{
-		ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo;
-		ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_primary_ammo;
-		return ammo_amount;
-	}
-	else if (req == WR_CHECKAMMO2)
-	{
-		ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo;
-		ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_secondary_ammo;
-		return ammo_amount;
-	}
-	else if (req == WR_RELOAD)
-	{
-		W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav");
-	}
-	else if (req == WR_SUICIDEMESSAGE)
-	{
-		if(w_deathtype & HITTYPE_SECONDARY)
-			return WEAPON_MORTAR_SUICIDE_BOUNCE;
-		else
-			return WEAPON_MORTAR_SUICIDE_EXPLODE;
-	}
-	else if (req == WR_KILLMESSAGE)
-	{
-		if(w_deathtype & HITTYPE_SECONDARY)
-			return WEAPON_MORTAR_MURDER_BOUNCE;
-		else
-			return WEAPON_MORTAR_MURDER_EXPLODE;
-	}
-	return TRUE;
-}
-#endif
-#ifdef CSQC
-float w_glauncher(float req)
-{
-	if(req == WR_IMPACTEFFECT)
-	{
-		vector org2;
-		org2 = w_org + w_backoff * 12;
-		pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
-		if(!w_issilent)
-			sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
-	}
-	else if(req == WR_PRECACHE)
-	{
-		precache_sound("weapons/grenade_impact.wav");
-	}
-	return TRUE;
-}
-#endif
-#endif
diff --git a/qcsrc/server/w_minelayer.qc b/qcsrc/server/w_minelayer.qc
deleted file mode 100644
index 5d88df8b25..0000000000
--- a/qcsrc/server/w_minelayer.qc
+++ /dev/null
@@ -1,563 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ MINE_LAYER,
-/* function  */ w_minelayer,
-/* ammotype  */ IT_ROCKETS,
-/* impulse   */ 4,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* model     */ "minelayer",
-/* shortname */ "minelayer",
-/* fullname  */ _("Mine Layer")
-);
-#else
-#ifdef SVQC
-void W_Mine_Think (void);
-.float minelayer_detonate, mine_explodeanyway;
-.float mine_time;
-.vector mine_orientation;
-
-void spawnfunc_weapon_minelayer (void)
-{
-	weapon_defaultspawnfunc(WEP_MINE_LAYER);
-}
-
-void W_Mine_Stick (entity to)
-{
-	spamsound (self, CH_SHOTS, "weapons/mine_stick.wav", VOL_BASE, ATTEN_NORM);
-
-	// in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
-
-	entity newmine;
-	newmine = spawn();
-	newmine.classname = self.classname;
-
-	newmine.bot_dodge = self.bot_dodge;
-	newmine.bot_dodgerating = self.bot_dodgerating;
-
-	newmine.owner = self.owner;
-	newmine.realowner = self.realowner;
-	setsize(newmine, '-4 -4 -4', '4 4 4');
-	setorigin(newmine, self.origin);
-	setmodel(newmine, "models/mine.md3");
-	newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
-
-	newmine.mine_orientation = -trace_plane_normal;
-
-	newmine.takedamage = self.takedamage;
-	newmine.damageforcescale = self.damageforcescale;
-	newmine.health = self.health;
-	newmine.event_damage = self.event_damage;
-	newmine.spawnshieldtime = self.spawnshieldtime;
-	newmine.damagedbycontents = TRUE;
-
-	newmine.movetype = MOVETYPE_NONE; // lock the mine in place
-	newmine.projectiledeathtype = self.projectiledeathtype;
-
-	newmine.mine_time = self.mine_time;
-
-	newmine.touch = func_null;
-	newmine.think = W_Mine_Think;
-	newmine.nextthink = time;
-	newmine.cnt = self.cnt;
-	newmine.flags = self.flags;
-
-	remove(self);
-	self = newmine;
-
-	if(to)
-		SetMovetypeFollow(self, to);
-}
-
-void W_Mine_Explode ()
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other);
-
-	if (self.realowner.weapon == WEP_MINE_LAYER)
-	{
-		entity oldself;
-		oldself = self;
-		self = self.realowner;
-		if (!weapon_action(WEP_MINE_LAYER, WR_CHECKAMMO1))
-		{
-			self.cnt = WEP_MINE_LAYER;
-			ATTACK_FINISHED(self) = time;
-			self.switchweapon = w_getbestweapon(self);
-		}
-		self = oldself;
-	}
-	self.realowner.minelayer_mines -= 1;
-	remove (self);
-}
-
-void W_Mine_DoRemoteExplode ()
-{
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
-		self.velocity = self.mine_orientation; // particle fx and decals need .velocity
-
-	RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world);
-
-	if (self.realowner.weapon == WEP_MINE_LAYER)
-	{
-		entity oldself;
-		oldself = self;
-		self = self.realowner;
-		if (!weapon_action(WEP_MINE_LAYER, WR_CHECKAMMO1))
-		{
-			self.cnt = WEP_MINE_LAYER;
-			ATTACK_FINISHED(self) = time;
-			self.switchweapon = w_getbestweapon(self);
-		}
-		self = oldself;
-	}
-	self.realowner.minelayer_mines -= 1;
-	remove (self);
-}
-
-void W_Mine_RemoteExplode ()
-{
-	if(self.realowner.deadflag == DEAD_NO)
-		if((self.spawnshieldtime >= 0)
-			? (time >= self.spawnshieldtime) // timer
-			: (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_minelayer_remote_radius) // safety device
-		)
-		{
-			W_Mine_DoRemoteExplode();
-		}
-}
-
-void W_Mine_ProximityExplode ()
-{
-	// make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
-	if(autocvar_g_balance_minelayer_protection && self.mine_explodeanyway == 0)
-	{
-		entity head;
-		head = findradius(self.origin, autocvar_g_balance_minelayer_radius);
-		while(head)
-		{
-			if(head == self.realowner || SAME_TEAM(head, self.realowner))
-				return;
-			head = head.chain;
-		}
-	}
-
-	self.mine_time = 0;
-	W_Mine_Explode();
-}
-
-float W_Mine_Count(entity e)
-{
-	float minecount = 0;
-	entity mine;
-	for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
-		minecount += 1;
-
-	return minecount;
-}
-
-void W_Mine_Think (void)
-{
-	entity head;
-
-	self.nextthink = time;
-
-	if(self.movetype == MOVETYPE_FOLLOW)
-	{
-		if(LostMovetypeFollow(self))
-		{
-			UnsetMovetypeFollow(self);
-			self.movetype = MOVETYPE_NONE;
-		}
-	}
-
-	// our lifetime has expired, it's time to die - mine_time just allows us to play a sound for this
-	// TODO: replace this mine_trigger.wav sound with a real countdown
-	if ((time > self.cnt) && (!self.mine_time))
-	{
-		if(autocvar_g_balance_minelayer_lifetime_countdown > 0)
-			spamsound (self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTEN_NORM);
-		self.mine_time = time + autocvar_g_balance_minelayer_lifetime_countdown;
-		self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near.
-	}
-
-	// a player's mines shall explode if he disconnects or dies
-	// TODO: Do this on team change too -- Samual: But isn't a player killed when they switch teams?
-	if(!IS_PLAYER(self.realowner) || self.realowner.deadflag != DEAD_NO)
-	{
-		other = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		W_Mine_Explode();
-		return;
-	}
-
-	// set the mine for detonation when a foe gets close enough
-	head = findradius(self.origin, autocvar_g_balance_minelayer_proximityradius);
-	while(head)
-	{
-		if(IS_PLAYER(head) && head.deadflag == DEAD_NO)
-		if(head != self.realowner && DIFF_TEAM(head, self.realowner)) // don't trigger for team mates
-		if(!self.mine_time)
-		{
-			spamsound (self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTEN_NORM);
-			self.mine_time = time + autocvar_g_balance_minelayer_time;
-		}
-		head = head.chain;
-	}
-
-	// explode if it's time to
-	if(self.mine_time && time >= self.mine_time)
-	{
-		W_Mine_ProximityExplode();
-		return;
-	}
-
-	// remote detonation
-	if (self.realowner.weapon == WEP_MINE_LAYER)
-	if (self.realowner.deadflag == DEAD_NO)
-	if (self.minelayer_detonate)
-		W_Mine_RemoteExplode();
-}
-
-void W_Mine_Touch (void)
-{
-	if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
-		return; // we're already a stuck mine, why do we get called? TODO does this even happen?
-
-	if(WarpZone_Projectile_Touch())
-	{
-		if(wasfreed(self))
-			self.realowner.minelayer_mines -= 1;
-		return;
-	}
-
-	if(other && IS_PLAYER(other) && other.deadflag == DEAD_NO)
-	{
-		// hit a player
-		// don't stick
-	}
-	else
-	{
-		W_Mine_Stick(other);
-	}
-}
-
-void W_Mine_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if (self.health <= 0)
-		return;
-
-	float is_from_enemy = (inflictor.realowner != self.realowner);
-
-	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_from_enemy ? 1 : -1)))
-		return; // g_projectiles_damage says to halt
-
-	self.health = self.health - damage;
-	self.angles = vectoangles(self.velocity);
-
-	if (self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, W_Mine_Explode);
-}
-
-void W_Mine_Attack (void)
-{
-	entity mine;
-	entity flash;
-
-	// scan how many mines we placed, and return if we reached our limit
-	if(autocvar_g_balance_minelayer_limit)
-	{
-		if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit)
-		{
-			// the refire delay keeps this message from being spammed
-			sprint(self, strcat("minelayer: You cannot place more than ^2", ftos(autocvar_g_balance_minelayer_limit), " ^7mines at a time\n") );
-			play2(self, "weapons/unavailable.wav");
-			return;
-		}
-	}
-
-	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo);
-
-	W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CH_WEAPON_A, autocvar_g_balance_minelayer_damage);
-	pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	mine = WarpZone_RefSys_SpawnSameRefSys(self);
-	mine.owner = mine.realowner = self;
-	if(autocvar_g_balance_minelayer_detonatedelay >= 0)
-		mine.spawnshieldtime = time + autocvar_g_balance_minelayer_detonatedelay;
-	else
-		mine.spawnshieldtime = -1;
-	mine.classname = "mine";
-	mine.bot_dodge = TRUE;
-	mine.bot_dodgerating = autocvar_g_balance_minelayer_damage * 2; // * 2 because it can detonate inflight which makes it even more dangerous
-
-	mine.takedamage = DAMAGE_YES;
-	mine.damageforcescale = autocvar_g_balance_minelayer_damageforcescale;
-	mine.health = autocvar_g_balance_minelayer_health;
-	mine.event_damage = W_Mine_Damage;
-	mine.damagedbycontents = TRUE;
-
-	mine.movetype = MOVETYPE_TOSS;
-	PROJECTILE_MAKETRIGGER(mine);
-	mine.projectiledeathtype = WEP_MINE_LAYER;
-	setsize (mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
-
-	setorigin (mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point
-	W_SetupProjectileVelocity(mine, autocvar_g_balance_minelayer_speed, 0);
-	mine.angles = vectoangles (mine.velocity);
-
-	mine.touch = W_Mine_Touch;
-	mine.think = W_Mine_Think;
-	mine.nextthink = time;
-	mine.cnt = time + (autocvar_g_balance_minelayer_lifetime - autocvar_g_balance_minelayer_lifetime_countdown);
-	mine.flags = FL_PROJECTILE;
-	mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY;
-
-	CSQCProjectile(mine, TRUE, PROJECTILE_MINE, TRUE);
-
-	// muzzle flash for 1st person view
-	flash = spawn ();
-	setmodel (flash, "models/flash.md3"); // precision set below
-	SUB_SetFade (flash, time, 0.1);
-	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-	W_AttachToShotorg(flash, '5 0 0');
-
-	// common properties
-
-	other = mine; MUTATOR_CALLHOOK(EditProjectile);
-
-	self.minelayer_mines = W_Mine_Count(self);
-}
-
-float W_PlacedMines(float detonate)
-{
-	entity mine;
-	float minfound = 0;
-
-	for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self)
-	{
-		if(detonate)
-		{
-			if(!mine.minelayer_detonate)
-			{
-				mine.minelayer_detonate = TRUE;
-				minfound = 1;
-			}
-		}
-		else
-			minfound = 1;
-	}
-	return minfound;
-}
-
-float w_minelayer(float req)
-{
-	entity mine;
-	float ammo_amount;
-
-	if (req == WR_AIM)
-	{
-		// aim and decide to fire if appropriate
-		if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit)
-			self.BUTTON_ATCK = FALSE;
-		else
-			self.BUTTON_ATCK = bot_aim(autocvar_g_balance_minelayer_speed, 0, autocvar_g_balance_minelayer_lifetime, FALSE);
-		if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
-		{
-			// decide whether to detonate mines
-			entity targetlist, targ;
-			float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
-			float selfdamage, teamdamage, enemydamage;
-			edgedamage = autocvar_g_balance_minelayer_edgedamage;
-			coredamage = autocvar_g_balance_minelayer_damage;
-			edgeradius = autocvar_g_balance_minelayer_radius;
-			recipricoledgeradius = 1 / edgeradius;
-			selfdamage = 0;
-			teamdamage = 0;
-			enemydamage = 0;
-			targetlist = findchainfloat(bot_attack, TRUE);
-			mine = find(world, classname, "mine");
-			while (mine)
-			{
-				if (mine.realowner != self)
-				{
-					mine = find(mine, classname, "mine");
-					continue;
-				}
-				targ = targetlist;
-				while (targ)
-				{
-					d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - mine.origin);
-					d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
-					// count potential damage according to type of target
-					if (targ == self)
-						selfdamage = selfdamage + d;
-					else if (targ.team == self.team && teamplay)
-						teamdamage = teamdamage + d;
-					else if (bot_shouldattack(targ))
-						enemydamage = enemydamage + d;
-					targ = targ.chain;
-				}
-				mine = find(mine, classname, "mine");
-			}
-			float desirabledamage;
-			desirabledamage = enemydamage;
-			if (time > self.invincible_finished && time > self.spawnshieldtime)
-				desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
-			if (teamplay && self.team)
-				desirabledamage = desirabledamage - teamdamage;
-
-			mine = find(world, classname, "mine");
-			while (mine)
-			{
-				if (mine.realowner != self)
-				{
-					mine = find(mine, classname, "mine");
-					continue;
-				}
-				makevectors(mine.v_angle);
-				targ = targetlist;
-				if (skill > 9) // normal players only do this for the target they are tracking
-				{
-					targ = targetlist;
-					while (targ)
-					{
-						if (
-							(v_forward * normalize(mine.origin - targ.origin)< 0.1)
-							&& desirabledamage > 0.1*coredamage
-						)self.BUTTON_ATCK2 = TRUE;
-						targ = targ.chain;
-					}
-				}else{
-					float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
-					//As the distance gets larger, a correct detonation gets near imposible
-					//Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player
-					if(v_forward * normalize(mine.origin - self.enemy.origin)< 0.1)
-						if(IS_PLAYER(self.enemy))
-							if(desirabledamage >= 0.1*coredamage)
-								if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
-									self.BUTTON_ATCK2 = TRUE;
-				//	dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
-				}
-
-				mine = find(mine, classname, "mine");
-			}
-			// if we would be doing at X percent of the core damage, detonate it
-			// but don't fire a new shot at the same time!
-			if (desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
-				self.BUTTON_ATCK2 = TRUE;
-			if ((skill > 6.5) && (selfdamage > self.health))
-				self.BUTTON_ATCK2 = FALSE;
-			//if(self.BUTTON_ATCK2 == TRUE)
-			//	dprint(ftos(desirabledamage),"\n");
-			if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
-		}
-	}
-	else if (req == WR_THINK)
-	{
-		if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < autocvar_g_balance_minelayer_ammo) // forced reload
-		{
-			// not if we're holding the minelayer without enough ammo, but can detonate existing mines
-			if (!(W_PlacedMines(FALSE) && self.ammo_rockets < autocvar_g_balance_minelayer_ammo))
-				weapon_action(self.weapon, WR_RELOAD);
-		}
-		else if (self.BUTTON_ATCK)
-		{
-			if(weapon_prepareattack(0, autocvar_g_balance_minelayer_refire))
-			{
-				W_Mine_Attack();
-				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_minelayer_animtime, w_ready);
-			}
-		}
-
-		if (self.BUTTON_ATCK2)
-		{
-			if(W_PlacedMines(TRUE))
-				sound (self, CH_WEAPON_B, "weapons/mine_det.wav", VOL_BASE, ATTEN_NORM);
-		}
-	}
-	else if (req == WR_PRECACHE)
-	{
-		precache_model ("models/flash.md3");
-		precache_model ("models/mine.md3");
-		precache_model ("models/weapons/g_minelayer.md3");
-		precache_model ("models/weapons/v_minelayer.md3");
-		precache_model ("models/weapons/h_minelayer.iqm");
-		precache_sound ("weapons/mine_det.wav");
-		precache_sound ("weapons/mine_fire.wav");
-		precache_sound ("weapons/mine_stick.wav");
-		precache_sound ("weapons/mine_trigger.wav");
-		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
-	}
-	else if (req == WR_SETUP)
-	{
-		weapon_setup(WEP_MINE_LAYER);
-		self.current_ammo = ammo_rockets;
-	}
-	else if (req == WR_CHECKAMMO1)
-	{
-		// don't switch while placing a mine
-		if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
-		{
-			ammo_amount = self.ammo_rockets >= autocvar_g_balance_minelayer_ammo;
-			ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= autocvar_g_balance_minelayer_ammo;
-			return ammo_amount;
-		}
-	}
-	else if (req == WR_CHECKAMMO2)
-	{
-		if (W_PlacedMines(FALSE))
-			return TRUE;
-		else
-			return FALSE;
-	}
-	else if (req == WR_RESETPLAYER)
-	{
-		self.minelayer_mines = 0;
-	}
-	else if (req == WR_RELOAD)
-	{
-		W_Reload(autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo, autocvar_g_balance_minelayer_reload_time, "weapons/reload.wav");
-	}
-	else if (req == WR_SUICIDEMESSAGE)
-	{
-		return WEAPON_MINELAYER_SUICIDE;
-	}
-	else if (req == WR_KILLMESSAGE)
-	{
-		return WEAPON_MINELAYER_MURDER;
-	}
-	return TRUE;
-}
-#endif
-#ifdef CSQC
-float w_minelayer(float req)
-{
-	if(req == WR_IMPACTEFFECT)
-	{
-		vector org2;
-		org2 = w_org + w_backoff * 12;
-		pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
-		if(!w_issilent)
-			sound(self, CH_SHOTS, "weapons/mine_exp.wav", VOL_BASE, ATTEN_NORM);
-	}
-	else if(req == WR_PRECACHE)
-	{
-		precache_sound("weapons/mine_exp.wav");
-	}
-	return TRUE;
-}
-#endif
-#endif
diff --git a/qcsrc/server/w_rocketlauncher.qc b/qcsrc/server/w_rocketlauncher.qc
deleted file mode 100644
index 6cd8929f6f..0000000000
--- a/qcsrc/server/w_rocketlauncher.qc
+++ /dev/null
@@ -1,491 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ ROCKET_LAUNCHER,
-/* function  */ w_rlauncher,
-/* ammotype  */ IT_ROCKETS,
-/* impulse   */ 9,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* model     */ "rl",
-/* shortname */ "rocketlauncher",
-/* fullname  */ _("Rocket Launcher")
-);
-#else
-#ifdef SVQC
-.float rl_release;
-.float rl_detonate_later;
-
-void W_Rocket_Unregister()
-{
-	if(self.realowner && self.realowner.lastrocket == self)
-	{
-		self.realowner.lastrocket = world;
-		// self.realowner.rl_release = 1;
-	}
-}
-
-void W_Rocket_Explode ()
-{
-	W_Rocket_Unregister();
-
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other);
-
-	if (self.realowner.weapon == WEP_ROCKET_LAUNCHER)
-	{
-		if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
-		{
-			self.realowner.cnt = WEP_ROCKET_LAUNCHER;
-			ATTACK_FINISHED(self.realowner) = time;
-			self.realowner.switchweapon = w_getbestweapon(self.realowner);
-		}
-	}
-	remove (self);
-}
-
-void W_Rocket_DoRemoteExplode ()
-{
-	W_Rocket_Unregister();
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world);
-
-	if (self.realowner.weapon == WEP_ROCKET_LAUNCHER)
-	{
-		if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
-		{
-			self.realowner.cnt = WEP_ROCKET_LAUNCHER;
-			ATTACK_FINISHED(self.realowner) = time;
-			self.realowner.switchweapon = w_getbestweapon(self.realowner);
-		}
-	}
-	remove (self);
-}
-
-void W_Rocket_RemoteExplode()
-{
-	if(self.realowner.deadflag == DEAD_NO)
-	if(self.realowner.lastrocket)
-	{
-		if((self.spawnshieldtime >= 0)
-			? (time >= self.spawnshieldtime) // timer
-			: (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_rocketlauncher_remote_radius) // safety device
-		)
-		{
-			W_Rocket_DoRemoteExplode();
-		}
-	}
-}
-
-vector rocket_steerto(vector thisdir, vector goaldir, float maxturn_cos)
-{
-	if(thisdir * goaldir > maxturn_cos)
-		return goaldir;
-	if(thisdir * goaldir < -0.9998) // less than 1 degree and opposite
-		return thisdir; // refuse to guide (better than letting a numerical error happen)
-	float f, m2;
-	vector v;
-	// solve:
-	//   g = normalize(thisdir + goaldir * X)
-	//   thisdir * g = maxturn
-	//
-	//   gg = thisdir + goaldir * X
-	//   (thisdir * gg)^2 = maxturn^2 * (gg * gg)
-	//
-	//   (1 + (thisdir * goaldir) * X)^2 = maxturn^2 * (1 + X*X + 2 * X * thisdir * goaldir)
-	f = thisdir * goaldir;
-	//   (1 + f * X)^2 = maxturn^2 * (1 + X*X + 2 * X * f)
-	//   0 = (m^2 - f^2) * x^2 + (2 * f * (m^2 - 1)) * x + (m^2 - 1)
-	m2 = maxturn_cos * maxturn_cos;
-	v = solve_quadratic(m2 - f * f, 2 * f * (m2 - 1), m2 - 1);
-	return normalize(thisdir + goaldir * v_y); // the larger solution!
-}
-// assume thisdir == -goaldir:
-//   f == -1
-//   v = solve_qadratic(m2 - 1, -2 * (m2 - 1), m2 - 1)
-//   (m2 - 1) x^2 - 2 * (m2 - 1) * x + (m2 - 1) = 0
-//   x^2 - 2 * x + 1 = 0
-//   (x - 1)^2 = 0
-//   x = 1
-//   normalize(thisdir + goaldir)
-//   normalize(0)
-
-void W_Rocket_Think (void)
-{
-	vector desireddir, olddir, newdir, desiredorigin, goal;
-#if 0
-	float cosminang, cosmaxang, cosang;
-#endif
-	float velspeed, f;
-	self.nextthink = time;
-	if (time > self.cnt)
-	{
-		other = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		W_Rocket_Explode ();
-		return;
-	}
-
-	// accelerate
-	makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
-	velspeed = autocvar_g_balance_rocketlauncher_speed * g_weaponspeedfactor - (self.velocity * v_forward);
-	if (velspeed > 0)
-		self.velocity = self.velocity + v_forward * min(autocvar_g_balance_rocketlauncher_speedaccel * g_weaponspeedfactor * frametime, velspeed);
-
-	// laser guided, or remote detonation
-	if (self.realowner.weapon == WEP_ROCKET_LAUNCHER)
-	{
-		if(self == self.realowner.lastrocket)
-		if (!self.realowner.rl_release)
-		if (!self.BUTTON_ATCK2)
-		if(autocvar_g_balance_rocketlauncher_guiderate)
-		if(time > self.pushltime)
-		if(self.realowner.deadflag == DEAD_NO)
-		{
-			f = autocvar_g_balance_rocketlauncher_guideratedelay;
-			if(f)
-				f = bound(0, (time - self.pushltime) / f, 1);
-			else
-				f = 1;
-
-			velspeed = vlen(self.velocity);
-
-			makevectors(self.realowner.v_angle);
-			desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward);
-			desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs);
-			olddir = normalize(self.velocity);
-
-			// now it gets tricky... we want to move like some curve to approximate the target direction
-			// but we are limiting the rate at which we can turn!
-			goal = desiredorigin + ((self.origin - desiredorigin) * desireddir + autocvar_g_balance_rocketlauncher_guidegoal) * desireddir;
-			newdir = rocket_steerto(olddir, normalize(goal - self.origin), cos(autocvar_g_balance_rocketlauncher_guiderate * f * frametime * DEG2RAD));
-
-			self.velocity = newdir * velspeed;
-			self.angles = vectoangles(self.velocity);
-
-			if(!self.count)
-			{
-				pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1);
-				// TODO add a better sound here
-				sound (self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTEN_NORM);
-				self.count = 1;
-			}
-		}
-
-		if(self.rl_detonate_later)
-			W_Rocket_RemoteExplode();
-	}
-
-	if(self.csqcprojectile_clientanimate == 0)
-		UpdateCSQCProjectile(self);
-}
-
-void W_Rocket_Touch (void)
-{
-	if(WarpZone_Projectile_Touch())
-	{
-		if(wasfreed(self))
-			W_Rocket_Unregister();
-		return;
-	}
-	W_Rocket_Unregister();
-	W_Rocket_Explode ();
-}
-
-void W_Rocket_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if (self.health <= 0)
-		return;
-
-	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt
-
-	self.health = self.health - damage;
-	self.angles = vectoangles(self.velocity);
-
-	if (self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, W_Rocket_Explode);
-}
-
-void W_Rocket_Attack (void)
-{
-	entity missile;
-	entity flash;
-
-	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo);
-
-	W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_balance_rocketlauncher_damage);
-	pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = WarpZone_RefSys_SpawnSameRefSys(self);
-	missile.owner = missile.realowner = self;
-	self.lastrocket = missile;
-	if(autocvar_g_balance_rocketlauncher_detonatedelay >= 0)
-		missile.spawnshieldtime = time + autocvar_g_balance_rocketlauncher_detonatedelay;
-	else
-		missile.spawnshieldtime = -1;
-	missile.pushltime = time + autocvar_g_balance_rocketlauncher_guidedelay;
-	missile.classname = "rocket";
-	missile.bot_dodge = TRUE;
-	missile.bot_dodgerating = autocvar_g_balance_rocketlauncher_damage * 2; // * 2 because it can be detonated inflight which makes it even more dangerous
-
-	missile.takedamage = DAMAGE_YES;
-	missile.damageforcescale = autocvar_g_balance_rocketlauncher_damageforcescale;
-	missile.health = autocvar_g_balance_rocketlauncher_health;
-	missile.event_damage = W_Rocket_Damage;
-	missile.damagedbycontents = TRUE;
-
-	missile.movetype = MOVETYPE_FLY;
-	PROJECTILE_MAKETRIGGER(missile);
-	missile.projectiledeathtype = WEP_ROCKET_LAUNCHER;
-	setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
-	setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
-	W_SetupProjectileVelocity(missile, autocvar_g_balance_rocketlauncher_speedstart, 0);
-	missile.angles = vectoangles (missile.velocity);
-
-	missile.touch = W_Rocket_Touch;
-	missile.think = W_Rocket_Think;
-	missile.nextthink = time;
-	missile.cnt = time + autocvar_g_balance_rocketlauncher_lifetime;
-	missile.flags = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH;
-
-	CSQCProjectile(missile, autocvar_g_balance_rocketlauncher_guiderate == 0 && autocvar_g_balance_rocketlauncher_speedaccel == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound
-
-	// muzzle flash for 1st person view
-	flash = spawn ();
-	setmodel (flash, "models/flash.md3"); // precision set below
-	SUB_SetFade (flash, time, 0.1);
-	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-	W_AttachToShotorg(flash, '5 0 0');
-
-	// common properties
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void spawnfunc_weapon_rocketlauncher (void); // defined in t_items.qc
-
-float w_rlauncher(float req)
-{
-	entity rock;
-	float rockfound;
-	float ammo_amount;
-
-	if (req == WR_AIM)
-	{
-		// aim and decide to fire if appropriate
-		self.BUTTON_ATCK = bot_aim(autocvar_g_balance_rocketlauncher_speed, 0, autocvar_g_balance_rocketlauncher_lifetime, FALSE);
-		if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
-		{
-			// decide whether to detonate rockets
-			entity missile, targetlist, targ;
-			float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
-			float selfdamage, teamdamage, enemydamage;
-			edgedamage = autocvar_g_balance_rocketlauncher_edgedamage;
-			coredamage = autocvar_g_balance_rocketlauncher_damage;
-			edgeradius = autocvar_g_balance_rocketlauncher_radius;
-			recipricoledgeradius = 1 / edgeradius;
-			selfdamage = 0;
-			teamdamage = 0;
-			enemydamage = 0;
-			targetlist = findchainfloat(bot_attack, TRUE);
-			missile = find(world, classname, "rocket");
-			while (missile)
-			{
-				if (missile.realowner != self)
-				{
-					missile = find(missile, classname, "rocket");
-					continue;
-				}
-				targ = targetlist;
-				while (targ)
-				{
-					d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.origin);
-					d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
-					// count potential damage according to type of target
-					if (targ == self)
-						selfdamage = selfdamage + d;
-					else if (targ.team == self.team && teamplay)
-						teamdamage = teamdamage + d;
-					else if (bot_shouldattack(targ))
-						enemydamage = enemydamage + d;
-					targ = targ.chain;
-				}
-				missile = find(missile, classname, "rocket");
-			}
-			float desirabledamage;
-			desirabledamage = enemydamage;
-			if (time > self.invincible_finished && time > self.spawnshieldtime)
-				desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
-			if (teamplay && self.team)
-				desirabledamage = desirabledamage - teamdamage;
-
-			missile = find(world, classname, "rocket");
-			while (missile)
-			{
-				if (missile.realowner != self)
-				{
-					missile = find(missile, classname, "rocket");
-					continue;
-				}
-				makevectors(missile.v_angle);
-				targ = targetlist;
-				if (skill > 9) // normal players only do this for the target they are tracking
-				{
-					targ = targetlist;
-					while (targ)
-					{
-						if (
-							(v_forward * normalize(missile.origin - targ.origin)< 0.1)
-							&& desirabledamage > 0.1*coredamage
-						)self.BUTTON_ATCK2 = TRUE;
-						targ = targ.chain;
-					}
-				}else{
-					float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
-					//As the distance gets larger, a correct detonation gets near imposible
-					//Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player
-					if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1)
-						if(IS_PLAYER(self.enemy))
-							if(desirabledamage >= 0.1*coredamage)
-								if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
-									self.BUTTON_ATCK2 = TRUE;
-				//	dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
-				}
-
-				missile = find(missile, classname, "rocket");
-			}
-			// if we would be doing at X percent of the core damage, detonate it
-			// but don't fire a new shot at the same time!
-			if (desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
-				self.BUTTON_ATCK2 = TRUE;
-			if ((skill > 6.5) && (selfdamage > self.health))
-				self.BUTTON_ATCK2 = FALSE;
-			//if(self.BUTTON_ATCK2 == TRUE)
-			//	dprint(ftos(desirabledamage),"\n");
-			if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
-		}
-	}
-	else if (req == WR_THINK)
-	{
-		if(autocvar_g_balance_rocketlauncher_reload_ammo && self.clip_load < autocvar_g_balance_rocketlauncher_ammo) // forced reload
-			weapon_action(self.weapon, WR_RELOAD);
-		else
-		{
-			if (self.BUTTON_ATCK)
-			{
-				if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop)
-				if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire))
-				{
-					W_Rocket_Attack();
-					weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready);
-					self.rl_release = 0;
-				}
-			}
-			else
-				self.rl_release = 1;
-
-			if (self.BUTTON_ATCK2)
-			{
-				rockfound = 0;
-				for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
-				{
-					if(!rock.rl_detonate_later)
-					{
-						rock.rl_detonate_later = TRUE;
-						rockfound = 1;
-					}
-				}
-				if(rockfound)
-					sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM);
-			}
-		}
-	}
-	else if (req == WR_PRECACHE)
-	{
-		precache_model ("models/flash.md3");
-		precache_model ("models/weapons/g_rl.md3");
-		precache_model ("models/weapons/v_rl.md3");
-		precache_model ("models/weapons/h_rl.iqm");
-		precache_sound ("weapons/rocket_det.wav");
-		precache_sound ("weapons/rocket_fire.wav");
-		precache_sound ("weapons/rocket_mode.wav");
-		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
-	}
-	else if (req == WR_SETUP)
-	{
-		weapon_setup(WEP_ROCKET_LAUNCHER);
-		self.current_ammo = ammo_rockets;
-		self.rl_release = 1;
-	}
-	else if (req == WR_CHECKAMMO1)
-	{
-		// don't switch while guiding a missile
-		if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER)
-		{
-			ammo_amount = FALSE;
-			if(autocvar_g_balance_rocketlauncher_reload_ammo)
-			{
-				if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo)
-					ammo_amount = TRUE;
-			}
-			else if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
-				ammo_amount = TRUE;
-			return !ammo_amount;
-		}
-	}
-	else if (req == WR_CHECKAMMO2)
-		return FALSE;
-	else if (req == WR_RESETPLAYER)
-	{
-		self.rl_release = 0;
-	}
-	else if (req == WR_RELOAD)
-	{
-		W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav");
-	}
-	else if (req == WR_SUICIDEMESSAGE)
-	{
-		return WEAPON_ROCKETLAUNCHER_SUICIDE;
-	}
-	else if (req == WR_KILLMESSAGE)
-	{
-		if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
-			return WEAPON_ROCKETLAUNCHER_MURDER_SPLASH;
-		else
-			return WEAPON_ROCKETLAUNCHER_MURDER_DIRECT;
-	}
-	return TRUE;
-}
-#endif
-#ifdef CSQC
-float w_rlauncher(float req)
-{
-	if(req == WR_IMPACTEFFECT)
-	{
-		vector org2;
-		org2 = w_org + w_backoff * 12;
-		pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
-		if(!w_issilent)
-			sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
-	}
-	else if(req == WR_PRECACHE)
-	{
-		precache_sound("weapons/rocket_impact.wav");
-	}
-	return TRUE;
-}
-#endif
-#endif
-- 
2.39.5