r3718 - in trunk/data: . qcsrc/server

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Fri Jun 27 07:58:49 EDT 2008


Author: div0
Date: 2008-06-27 07:58:47 -0400 (Fri, 27 Jun 2008)
New Revision: 3718

Modified:
   trunk/data/defaultNexuiz.cfg
   trunk/data/qcsrc/server/cl_client.qc
   trunk/data/qcsrc/server/miscfunctions.qc
   trunk/data/qcsrc/server/sv_main.qc
Log:
cleanup of spawn code;
g_spawn_furthest cvar: 0 means always spawn randomly, 1 means always spawn far away, 0.5 is default


Modified: trunk/data/defaultNexuiz.cfg
===================================================================
--- trunk/data/defaultNexuiz.cfg	2008-06-27 09:47:41 UTC (rev 3717)
+++ trunk/data/defaultNexuiz.cfg	2008-06-27 11:58:47 UTC (rev 3718)
@@ -314,6 +314,8 @@
 seta g_runematch_point_limit -1
 seta g_keyhunt_point_limit -1
 
+// 50% of the spawns shall be far away from any players
+set g_spawn_furthest 0.5
 // respawn delay
 set g_respawn_delay 2
 set g_respawn_waves 0

Modified: trunk/data/qcsrc/server/cl_client.qc
===================================================================
--- trunk/data/qcsrc/server/cl_client.qc	2008-06-27 09:47:41 UTC (rev 3717)
+++ trunk/data/qcsrc/server/cl_client.qc	2008-06-27 11:58:47 UTC (rev 3718)
@@ -27,116 +27,108 @@
 	}
 };
 
+// Returns:
+//   -1 if a spawn can't be used
+//   otherwise, a weight of the spawnpoint
+float Spawn_Score(entity spot, entity playerlist, float teamcheck)
+{
+	float shortest, thisdist;
+	entity player;
+
+	// filter out spots for the wrong team
+	if(teamcheck)
+	if(spot.team != teamcheck)
+		return -1;
+
+	// filter out spots for assault
+	if(spot.target != "") {
+		local entity ent;
+		ent = find(world, targetname, spot.target);
+		while(ent) {
+			if(ent.classname == "target_objective")
+				if(ent.health < 0 || ent.health >= ASSAULT_VALUE_INACTIVE)
+					return -1;
+			ent = find(ent, targetname, spot.target);
+		}
+	}
+
+	player = playerlist;
+	shortest = vlen(world.maxs - world.mins);
+	for(player = playerlist; player; player = player.chain)
+		if (player != self)
+		{
+			thisdist = vlen(player.origin - spot.origin);
+			if (thisdist < shortest)
+				shortest = thisdist;
+		}
+	return shortest;
+}
+
 float spawn_allbad;
 float spawn_allgood;
 entity Spawn_FilterOutBadSpots(entity firstspot, entity playerlist, float mindist, float teamcheck)
 {
-	local entity spot, player, nextspot, previousspot, newfirstspot;
-	local float pcount;
-	spot = firstspot;
-	newfirstspot = world;
-	previousspot = world;
+	local entity spot, spotlist, spotlistend;
 	spawn_allgood = TRUE;
 	spawn_allbad = TRUE;
-	while (spot)
-	{
-		nextspot = spot.chain;
-		// count team mismatches as bad spots
 
-		local float spotactive;
-		spotactive = 1;
+	spotlist = world;
+	spotlistend = world;
 
-		// filter out spots for assault
-		if(spot.target != "") {
-			local entity ent;
-			ent = find(world, targetname, spot.target);
-			while(ent) {
-				if(ent.classname == "target_objective")
-					if(ent.health < 0 || ent.health >= ASSAULT_VALUE_INACTIVE)
-						spotactive = 0;
-				ent = find(ent, targetname, spot.target);
+	for(spot = firstspot; spot; spot = spot.chain)
+	{
+		spot.frags = Spawn_Score(spot, playerlist, teamcheck);
+
+		if(cvar("spawn_debugview"))
+		{
+			setmodel(spot, "models/runematch/rune.mdl");
+			if(spot.frags < mindist)
+			{
+				spot.colormod = '1 0 0';
+				spot.scale = 1;
 			}
+			else
+			{
+				spot.colormod = '0 1 0';
+				spot.scale = spot.frags / mindist;
+			}
 		}
 
-		if ((!teamcheck || spot.team == teamcheck) && spotactive > 0)
+		if(spot.frags >= 0) // spawning allowed here
 		{
-			pcount = 0;
-			player = playerlist;
-			while (player)
+			if(spot.frags < mindist)
 			{
-				if (player != self)
-				if (vlen(player.origin - spot.origin) < mindist)
-					pcount = pcount + 1;
-				player = player.chain;
+				// too short distance
+				spawn_allgood = FALSE;
 			}
-			if (!pcount)
+			else 
 			{
+				// perfect
 				spawn_allbad = FALSE;
-				if (newfirstspot)
-					previousspot.chain = spot;
-				else
-					newfirstspot = spot;
-				previousspot = spot;
-				spot.chain = world;
+
+				if(spotlistend)
+					spotlistend.chain = spot;
+				spotlistend = spot;
+				if(!spotlist)
+					spotlist = spot;
 			}
-			else
-				spawn_allgood = FALSE;
 		}
-		spot = nextspot;
 	}
-	// if we couldn't find ANY good points, return world
-	return newfirstspot;
+
+	return spotlist;
 }
 
-entity Spawn_RandomPoint(entity firstspot)
+entity Spawn_WeightedPoint(entity firstspot, float lower, float upper, float exponent)
 {
+	// weight of a point: bound(lower, mindisttoplayer, upper)^exponent
+	// multiplied by spot.cnt (useful if you distribute many spawnpoints in a small area)
 	local entity spot;
-	local float numspots;
-	// count number of spots
-	numspots = 0;
-	spot = firstspot;
-	while (spot)
-	{
-		numspots = numspots + 1;
-		spot = spot.chain;
-	}
-	// pick a random one
-	numspots = numspots * random();
-	spot = firstspot;
-	while (spot.chain && numspots >= 1)
-	{
-		numspots = numspots - 1;
-		spot = spot.chain;
-	}
-	return spot;
-}
 
-entity Spawn_FurthestPoint(entity firstspot, entity playerlist)
-{
-	local entity best, spot, player;
-	local float bestrating, rating;
-	best = world;
-	bestrating = -1000000;
-	spot = firstspot;
-	while (spot)
-	{
-		rating = 1000000000;
-		player = playerlist;
-		while (player)
-		{
-			if (player != self)
-				rating = min(rating, vlen(player.origin - spot.origin));
-			player = player.chain;
-		}
-		rating = rating + random() * 16;
-		if (bestrating < rating)
-		{
-			best = spot;
-			bestrating = rating;
-		}
-		spot = spot.chain;
-	}
-	return best;
+	RandomSelection_Init();
+	for(spot = firstspot; spot; spot = spot.chain)
+		RandomSelection_Add(spot, 0, pow(bound(lower, spot.frags, upper), exponent) * spot.cnt);
+
+	return RandomSelection_chosen_ent;
 }
 
 /*
@@ -180,13 +172,18 @@
 		firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 800, teamcheck);
 		if(firstspot_new)
 			firstspot = firstspot_new;
-		spot = Spawn_RandomPoint(firstspot);
+		spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
 	}
-	else if (random() > 0.5 || spawn_allbad || spawn_allgood)
-		spot = Spawn_RandomPoint(firstspot);
+	else if (random() > cvar("g_spawn_furthest"))
+		spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
 	else
-		spot = Spawn_FurthestPoint(firstspot, playerlist);
+		spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint
 
+	if(cvar("spawn_debugview"))
+	{
+		print("spot mindistance: ", ftos(spot.frags), "\n");
+	}
+
 	if (!spot)
 	{
 		if(cvar("spawn_debug"))

Modified: trunk/data/qcsrc/server/miscfunctions.qc
===================================================================
--- trunk/data/qcsrc/server/miscfunctions.qc	2008-06-27 09:47:41 UTC (rev 3717)
+++ trunk/data/qcsrc/server/miscfunctions.qc	2008-06-27 11:58:47 UTC (rev 3718)
@@ -2,6 +2,25 @@
 void() spawnpoint_use;
 string ColoredTeamName(float t);
 
+float RandomSelection_totalweight;
+entity RandomSelection_chosen_ent;
+float RandomSelection_chosen_float;
+void RandomSelection_Init()
+{
+	RandomSelection_totalweight = 0;
+	RandomSelection_chosen_ent = world;
+	RandomSelection_chosen_float = 0;
+}
+void RandomSelection_Add(entity e, float f, float weight)
+{
+	RandomSelection_totalweight += weight;
+	if(random() * RandomSelection_totalweight <= weight)
+	{
+		RandomSelection_chosen_ent = e;
+		RandomSelection_chosen_float = f;
+	}
+}
+
 float DistributeEvenly_amount;
 float DistributeEvenly_totalweight;
 void DistributeEvenly_Init(float amount, float totalweight)
@@ -195,6 +214,8 @@
 
 	self.use = spawnpoint_use;
 	self.team_saved = self.team;
+	if(!self.cnt)
+		self.cnt = 1;
 
 	if(g_ctf || g_assault || g_onslaught || g_domination)
 	if(self.team)

Modified: trunk/data/qcsrc/server/sv_main.qc
===================================================================
--- trunk/data/qcsrc/server/sv_main.qc	2008-06-27 09:47:41 UTC (rev 3717)
+++ trunk/data/qcsrc/server/sv_main.qc	2008-06-27 11:58:47 UTC (rev 3718)
@@ -146,6 +146,7 @@
 */
 void RuneMatchGivePoints();
 float RedirectionThink();
+entity SelectSpawnPoint (float anypoint);
 void StartFrame (void)
 {
 	dprint_load(); // load dprint status from cvar
@@ -174,4 +175,9 @@
 
 	RuneMatchGivePoints();
 	bot_serverframe();
+
+	if(cvar("spawn_debugview"))
+	{
+		SelectSpawnPoint(0);
+	}
 }




More information about the nexuiz-commits mailing list