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