From c00654aeb21fc3e47e182b73206e7d27a24208a4 Mon Sep 17 00:00:00 2001
From: Mario <mario.mario@y7mail.com>
Date: Tue, 10 Sep 2013 09:31:50 +1000
Subject: [PATCH] Move overkill's spawn system into a separate mutator

---
 mutators.cfg                                 |  10 ++
 qcsrc/server/autocvars.qh                    |   5 +
 qcsrc/server/miscfunctions.qc                |   1 +
 qcsrc/server/mutators/mutator_spawnsystem.qc | 112 +++++++++++++++++++
 qcsrc/server/mutators/mutators.qh            |   1 +
 qcsrc/server/progs.src                       |   1 +
 6 files changed, 130 insertions(+)
 create mode 100644 qcsrc/server/mutators/mutator_spawnsystem.qc

diff --git a/mutators.cfg b/mutators.cfg
index e88fbc0afc..415d48ce6f 100644
--- a/mutators.cfg
+++ b/mutators.cfg
@@ -156,3 +156,13 @@ set g_campcheck 0 "damages campers every few seconds"
 set g_campcheck_interval 10
 set g_campcheck_damage 100
 set g_campcheck_distance 1800
+
+
+// ==============
+//  spawn system
+// ==============
+set g_spawnsystem 0 "spawn at teammates in teamplay modes"
+set g_spawnsystem_delay 2.5 "how long to wait before its OK to spawn at a player after someone just spawned at this player"
+set g_spawnsystem_delay_death 0 "how long to wait before its OK to spawn at a player after death"
+set g_spawnsystem_check_health 1 "only allow spawn at this player if their health is full"
+set g_spawnsystem_closetodeath 1 "spawn as close to death location as possible"
diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh
index 711d914360..b372af6dfc 100644
--- a/qcsrc/server/autocvars.qh
+++ b/qcsrc/server/autocvars.qh
@@ -1255,3 +1255,8 @@ float autocvar_g_campcheck_damage;
 float autocvar_g_campcheck_distance;
 float autocvar_g_campcheck_interval;
 float autocvar_g_jump_grunt;
+float autocvar_g_spawnsystem;
+float autocvar_g_spawnsystem_delay;
+float autocvar_g_spawnsystem_delay_death;
+float autocvar_g_spawnsystem_check_health;
+float autocvar_g_spawnsystem_closetodeath;
diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc
index 6a2458000f..cdd1caed64 100644
--- a/qcsrc/server/miscfunctions.qc
+++ b/qcsrc/server/miscfunctions.qc
@@ -924,6 +924,7 @@ void readlevelcvars(void)
 	CHECK_MUTATOR_ADD("g_nades", mutator_nades, 1);
 	CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1);
 	CHECK_MUTATOR_ADD("g_campcheck", mutator_campcheck, 1);
+	CHECK_MUTATOR_ADD("g_spawnsystem", mutator_spawnsystem, teamplay);
 	
 	#undef CHECK_MUTATOR_ADD
 	
diff --git a/qcsrc/server/mutators/mutator_spawnsystem.qc b/qcsrc/server/mutators/mutator_spawnsystem.qc
new file mode 100644
index 0000000000..89455b081d
--- /dev/null
+++ b/qcsrc/server/mutators/mutator_spawnsystem.qc
@@ -0,0 +1,112 @@
+.float spawnsys_timer;
+.vector spawnsys_deathloc;
+
+MUTATOR_HOOKFUNCTION(spawn_PlayerDies)
+{
+	self.spawnsys_deathloc = self.origin;
+	
+	return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(spawn_PlayerSpawn)
+{
+	if(autocvar_g_spawnsystem_delay_death)
+		self.spawnsys_timer = time + autocvar_g_spawnsystem_delay_death;
+
+	if not(autocvar_g_spawnsystem)
+		return FALSE;
+
+	entity team_mate, best_mate = world;
+	vector best_spot = '0 0 0';
+	float pc = 0, best_dist = 0, dist = 0;
+	FOR_EACH_PLAYER(team_mate)
+	{
+		if((autocvar_g_spawnsystem_check_health >= 0 && team_mate.health >= autocvar_g_balance_health_regenstable) || autocvar_g_spawnsystem_check_health == 0)
+		if(team_mate.deadflag == DEAD_NO)
+		if(team_mate.spawnsys_timer < time)
+		if(!IsDifferentTeam(self, team_mate))
+		if(team_mate.freezetag_frozen == 0)
+		if(team_mate != self)
+		{
+			tracebox(team_mate.origin, PL_MIN, PL_MAX, team_mate.origin - '0 0 100', MOVE_WORLDONLY, team_mate);
+			if(trace_fraction != 1.0)
+			if not(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+			{
+				pc = pointcontents(trace_endpos + '0 0 1');
+				if(pc == CONTENT_EMPTY)
+				{
+					if(vlen(team_mate.velocity) > 5)
+						fixedmakevectors(vectoangles(team_mate.velocity));
+					else
+						fixedmakevectors(team_mate.angles);
+
+					for(pc = 0; pc != 5; ++pc) // test 5 diffrent spots close to mate
+					{
+						switch(pc)
+						{
+							case 0:
+								tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin + v_right * 128, MOVE_NORMAL, team_mate);
+								break;
+							case 1:
+								tracebox(team_mate.origin , PL_MIN, PL_MAX,team_mate.origin - v_right * 128 , MOVE_NORMAL, team_mate);
+								break;
+							case 2:
+								tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin + v_right * 64 - v_forward * 64, MOVE_NORMAL, team_mate);
+								break;
+							case 3:
+								tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_right * 64 - v_forward * 64, MOVE_NORMAL, team_mate);
+								break;
+							case 4:
+								tracebox(team_mate.origin , PL_MIN, PL_MAX, team_mate.origin - v_forward * 128, MOVE_NORMAL, team_mate);
+								break;
+						}
+
+						if(trace_fraction == 1.0)
+						{
+							traceline(trace_endpos + '0 0 4', trace_endpos - '0 0 100', MOVE_NORMAL, team_mate);
+							if(trace_fraction != 1.0)
+							{
+								if(autocvar_g_spawnsystem_closetodeath)
+								{
+									dist = vlen(trace_endpos - self.spawnsys_deathloc);
+									if(dist < best_dist || best_dist == 0)
+									{
+										best_dist = dist;
+										best_spot = trace_endpos;
+										best_mate = team_mate;
+									}
+								}
+								else
+								{
+									setorigin(self, trace_endpos);
+									self.angles = team_mate.angles;
+									team_mate.spawnsys_timer = time + autocvar_g_spawnsystem_delay;
+									return 0;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if(autocvar_g_spawnsystem_closetodeath)
+	if(best_dist)
+	{
+		setorigin(self, best_spot);
+		self.angles = best_mate.angles;
+		self.fixangle = TRUE;
+		best_mate.spawnsys_timer = time + autocvar_g_spawnsystem_delay;
+	}
+	
+	return FALSE;
+}
+
+MUTATOR_DEFINITION(mutator_spawnsystem)
+{
+	MUTATOR_HOOK(PlayerDies, spawn_PlayerDies, CBC_ORDER_ANY);
+	MUTATOR_HOOK(PlayerSpawn, spawn_PlayerSpawn, CBC_ORDER_ANY);
+
+	return FALSE;
+}
diff --git a/qcsrc/server/mutators/mutators.qh b/qcsrc/server/mutators/mutators.qh
index e7a95de7ec..eae215c5db 100644
--- a/qcsrc/server/mutators/mutators.qh
+++ b/qcsrc/server/mutators/mutators.qh
@@ -29,5 +29,6 @@ MUTATOR_DECLARATION(mutator_multijump);
 MUTATOR_DECLARATION(mutator_melee_only);
 MUTATOR_DECLARATION(mutator_nades);
 MUTATOR_DECLARATION(mutator_campcheck);
+MUTATOR_DECLARATION(mutator_spawnsystem);
 
 MUTATOR_DECLARATION(sandbox);
diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src
index e9e9a4b8c8..36572711c2 100644
--- a/qcsrc/server/progs.src
+++ b/qcsrc/server/progs.src
@@ -258,6 +258,7 @@ mutators/mutator_multijump.qc
 mutators/mutator_melee_only.qc
 mutators/mutator_nades.qc
 mutators/mutator_campcheck.qc
+mutators/mutator_spawnsystem.qc
 
 ../warpzonelib/anglestransform.qc
 ../warpzonelib/mathlib.qc
-- 
2.39.5