-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include "../dpdefs/progsdefs.qh"
- #include "../dpdefs/dpextensions.qh"
- #include "../warpzonelib/util_server.qh"
- #include "../common/constants.qh"
- #include "../common/teams.qh"
- #include "../common/triggers/subs.qh"
- #include "../common/util.qh"
- #include "autocvars.qh"
- #include "constants.qh"
- #include "defs.qh"
- #include "mutators/mutators_include.qh"
- #include "spawnpoints.qh"
- #include "race.qh"
-#endif
-
-float SpawnPoint_Send(entity to, int sf)
+#include "spawnpoints.qh"
+
+#include "mutators/all.qh"
+#include "g_world.qh"
+#include "race.qh"
+#include "../common/constants.qh"
+#include "../common/teams.qh"
+#include "../common/triggers/subs.qh"
+#include "../common/util.qh"
+#include "../lib/warpzone/common.qh"
+#include "../lib/warpzone/util_server.qh"
+
+bool SpawnPoint_Send(entity this, entity to, int sf)
{
- WriteByte(MSG_ENTITY, ENT_CLIENT_SPAWNPOINT);
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_SPAWNPOINT);
- WriteByte(MSG_ENTITY, self.team);
- WriteShort(MSG_ENTITY, self.origin.x);
- WriteShort(MSG_ENTITY, self.origin.y);
- WriteShort(MSG_ENTITY, self.origin.z);
+ WriteByte(MSG_ENTITY, this.team);
+ WriteCoord(MSG_ENTITY, this.origin.x);
+ WriteCoord(MSG_ENTITY, this.origin.y);
+ WriteCoord(MSG_ENTITY, this.origin.z);
return true;
}
-float SpawnEvent_Send(entity to, int sf)
+bool SpawnEvent_Send(entity this, entity to, int sf)
{
float send;
- WriteByte(MSG_ENTITY, ENT_CLIENT_SPAWNEVENT);
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_SPAWNEVENT);
if(autocvar_g_spawn_alloweffects)
{
- WriteByte(MSG_ENTITY, num_for_edict(self.owner));
- WriteShort(MSG_ENTITY, self.owner.origin.x);
- WriteShort(MSG_ENTITY, self.owner.origin.y);
- WriteShort(MSG_ENTITY, self.owner.origin.z);
+ WriteByte(MSG_ENTITY, etof(this.owner));
+ WriteCoord(MSG_ENTITY, this.owner.origin.x);
+ WriteCoord(MSG_ENTITY, this.owner.origin.y);
+ WriteCoord(MSG_ENTITY, this.owner.origin.z);
send = true;
}
- else if((to == self.owner) || (IS_SPEC(to) && (to.enemy == self.owner)) )
+ else if((to == this.owner) || (IS_SPEC(to) && (to.enemy == this.owner)) )
{
WriteByte(MSG_ENTITY, 0);
send = true;
return send;
}
-void spawnpoint_use()
+.vector spawnpoint_prevorigin;
+void spawnpoint_think(entity this)
+{
+ this.nextthink = time + 0.1;
+ if(this.origin != this.spawnpoint_prevorigin)
+ {
+ this.spawnpoint_prevorigin = this.origin;
+ this.SendFlags |= 1;
+ }
+}
+
+void spawnpoint_use(entity this, entity actor, entity trigger)
{
if(teamplay)
if(have_team_spawns > 0)
{
- self.team = activator.team;
+ this.team = actor.team;
some_spawn_has_been_used = 1;
}
- print("spawnpoint was used!\n");
+ //LOG_INFO("spawnpoint was used!\n");
}
-void relocate_spawnpoint()
+void relocate_spawnpoint(entity this)
{
// nudge off the floor
- setorigin(self, self.origin + '0 0 1');
+ setorigin(this, this.origin + '0 0 1');
- tracebox(self.origin, PL_MIN_CONST, PL_MAX_CONST, self.origin, true, self);
+ tracebox(this.origin, PL_MIN_CONST, PL_MAX_CONST, this.origin, true, this);
if (trace_startsolid)
{
vector o;
- o = self.origin;
- self.mins = PL_MIN_CONST;
- self.maxs = PL_MAX_CONST;
- if (!move_out_of_solid(self))
- objerror("could not get out of solid at all!");
- print("^1NOTE: this map needs FIXING. Spawnpoint at ", vtos(o - '0 0 1'));
- print(" needs to be moved out of solid, e.g. by '", ftos(self.origin.x - o.x));
- print(" ", ftos(self.origin.y - o.y));
- print(" ", ftos(self.origin.z - o.z), "'\n");
+ o = this.origin;
+ this.mins = PL_MIN_CONST;
+ this.maxs = PL_MAX_CONST;
+ if (!move_out_of_solid(this))
+ objerror(this, "could not get out of solid at all!");
+ LOG_INFO("^1NOTE: this map needs FIXING. Spawnpoint at ", vtos(o - '0 0 1'));
+ LOG_INFO(" needs to be moved out of solid, e.g. by '", ftos(this.origin.x - o.x));
+ LOG_INFO(" ", ftos(this.origin.y - o.y));
+ LOG_INFO(" ", ftos(this.origin.z - o.z), "'\n");
if (autocvar_g_spawnpoints_auto_move_out_of_solid)
{
if (!spawnpoint_nag)
- print("\{1}^1NOTE: this map needs FIXING (it contains spawnpoints in solid, see server log)\n");
+ LOG_INFO("\{1}^1NOTE: this map needs FIXING (it contains spawnpoints in solid, see server log)\n");
spawnpoint_nag = 1;
}
else
{
- setorigin(self, o);
- self.mins = self.maxs = '0 0 0';
- objerror("player spawn point in solid, mapper sucks!\n");
+ setorigin(this, o);
+ this.mins = this.maxs = '0 0 0';
+ objerror(this, "player spawn point in solid, mapper sucks!\n");
return;
}
}
- self.use = spawnpoint_use;
- self.team_saved = self.team;
- if (!self.cnt)
- self.cnt = 1;
+ this.use = spawnpoint_use;
+ setthink(this, spawnpoint_think);
+ this.nextthink = time + 0.5 + random() * 2; // shouldn't need it for a little second
+ this.team_saved = this.team;
+ if (!this.cnt)
+ this.cnt = 1;
if (have_team_spawns != 0)
- if (self.team)
+ if (this.team)
have_team_spawns = 1;
- have_team_spawns_forteam[self.team] = 1;
+ have_team_spawns_forteam[this.team] = 1;
if (autocvar_r_showbboxes)
{
// show where spawnpoints point at too
- makevectors(self.angles);
- entity e;
- e = spawn();
- e.classname = "info_player_foo";
- setorigin(e, self.origin + v_forward * 24);
+ makevectors(this.angles);
+ entity e = new(info_player_foo);
+ setorigin(e, this.origin + v_forward * 24);
setsize(e, '-8 -8 -8', '8 8 8');
e.solid = SOLID_TRIGGER;
}
!(
( // if this passes, there is a DM spawn on a team match
teamplay
- && (self.team != NUM_TEAM_1)
- && (self.team != NUM_TEAM_2)
- && (self.team != NUM_TEAM_3)
- && (self.team != NUM_TEAM_4)
+ && (this.team != NUM_TEAM_1)
+ && (this.team != NUM_TEAM_2)
+ && (this.team != NUM_TEAM_3)
+ && (this.team != NUM_TEAM_4)
)
||
( // if this passes, there is a team spawn on a DM match
!teamplay
&&
(
- (self.team == NUM_TEAM_1)
- || (self.team == NUM_TEAM_2)
- || (self.team == NUM_TEAM_3)
- || (self.team == NUM_TEAM_4)
+ (this.team == NUM_TEAM_1)
+ || (this.team == NUM_TEAM_2)
+ || (this.team == NUM_TEAM_3)
+ || (this.team == NUM_TEAM_4)
)
)
)
||
autocvar_g_spawn_useallspawns
)
- { Net_LinkEntity(self, false, 0, SpawnPoint_Send); }
+ { Net_LinkEntity(this, false, 0, SpawnPoint_Send); }
+}
+
+spawnfunc(info_player_survivor)
+{
+ spawnfunc_info_player_deathmatch(this);
+}
+
+spawnfunc(info_player_start)
+{
+ spawnfunc_info_player_deathmatch(this);
}
-void spawnfunc_info_player_survivor (void)
+spawnfunc(info_player_deathmatch)
{
- spawnfunc_info_player_deathmatch();
+ this.classname = "info_player_deathmatch";
+ relocate_spawnpoint(this);
}
-void spawnfunc_info_player_start (void)
+/*QUAKED spawnfunc_info_player_team1 (1 0 0) (-16 -16 -24) (16 16 24)
+Starting point for a player in team one (Red).
+Keys: "angle" viewing angle when spawning. */
+spawnfunc(info_player_team1)
{
- spawnfunc_info_player_deathmatch();
+ this.team = NUM_TEAM_1; // red
+ spawnfunc_info_player_deathmatch(this);
}
-void spawnfunc_info_player_deathmatch (void)
+
+/*QUAKED spawnfunc_info_player_team2 (1 0 0) (-16 -16 -24) (16 16 24)
+Starting point for a player in team two (Blue).
+Keys: "angle" viewing angle when spawning. */
+spawnfunc(info_player_team2)
{
- self.classname = "info_player_deathmatch";
- relocate_spawnpoint();
+ this.team = NUM_TEAM_2; // blue
+ spawnfunc_info_player_deathmatch(this);
+}
+
+/*QUAKED spawnfunc_info_player_team3 (1 0 0) (-16 -16 -24) (16 16 24)
+Starting point for a player in team three (Yellow).
+Keys: "angle" viewing angle when spawning. */
+spawnfunc(info_player_team3)
+{
+ this.team = NUM_TEAM_3; // yellow
+ spawnfunc_info_player_deathmatch(this);
+}
+
+
+/*QUAKED spawnfunc_info_player_team4 (1 0 0) (-16 -16 -24) (16 16 24)
+Starting point for a player in team four (Purple).
+Keys: "angle" viewing angle when spawning. */
+spawnfunc(info_player_team4)
+{
+ this.team = NUM_TEAM_4; // purple
+ spawnfunc_info_player_deathmatch(this);
}
// Returns:
// _x: prio (-1 if unusable)
// _y: weight
-vector Spawn_Score(entity spot, float mindist, float teamcheck)
+vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck)
{
float shortest, thisdist;
float prio;
- entity player;
prio = 0;
if(spot.target == "")
return '-1 0 0';
- if(IS_REAL_CLIENT(self))
+ if(IS_REAL_CLIENT(this))
{
if(spot.restriction == 1)
return '-1 0 0';
}
shortest = vlen(world.maxs - world.mins);
- FOR_EACH_PLAYER(player) if (player != self)
- {
- thisdist = vlen(player.origin - spot.origin);
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, LAMBDA(
+ thisdist = vlen(it.origin - spot.origin);
if (thisdist < shortest)
shortest = thisdist;
- }
+ ));
if(shortest > mindist)
prio += SPAWN_PRIO_GOOD_DISTANCE;
- spawn_score = prio * '1 0 0' + shortest * '0 1 0';
- spawn_spot = spot;
+ vector spawn_score = prio * '1 0 0' + shortest * '0 1 0';
// filter out spots for assault
- if(spot.target != "") {
- entity ent;
- float found;
-
- found = 0;
- for(ent = world; (ent = find(ent, targetname, spot.target)); )
+ if(spot.target != "")
+ {
+ int found = 0;
+ for(entity targ = findchain(targetname, spot.target); targ; targ = targ.chain)
{
++found;
- if(ent.spawn_evalfunc)
+ if(targ.spawn_evalfunc)
{
- entity oldself = self;
- self = ent;
- spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
- self = oldself;
+ spawn_score = targ.spawn_evalfunc(targ, this, spot, spawn_score);
if(spawn_score.x < 0)
return spawn_score;
}
if(!found)
{
- dprint("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
+ LOG_TRACE("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target, "\n");
return '-1 0 0';
}
}
- MUTATOR_CALLHOOK(Spawn_Score);
+ MUTATOR_CALLHOOK(Spawn_Score, this, spot, spawn_score);
+ spawn_score = M_ARGV(2, vector);
return spawn_score;
}
-void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck)
+void Spawn_ScoreAll(entity this, entity firstspot, float mindist, float teamcheck)
{
entity spot;
for(spot = firstspot; spot; spot = spot.chain)
- spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck);
+ spot.spawnpoint_score = Spawn_Score(this, spot, mindist, teamcheck);
}
-entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck)
+entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck)
{
entity spot, spotlist, spotlistend;
- spotlist = world;
- spotlistend = world;
+ spotlist = NULL;
+ spotlistend = NULL;
- Spawn_ScoreAll(firstspot, mindist, teamcheck);
+ Spawn_ScoreAll(this, firstspot, mindist, teamcheck);
for(spot = firstspot; spot; spot = spot.chain)
{
}
}
if(spotlistend)
- spotlistend.chain = world;
+ spotlistend.chain = NULL;
return spotlist;
}
Finds a point to respawn
=============
*/
-entity SelectSpawnPoint (float anypoint)
+entity SelectSpawnPoint(entity this, bool anypoint)
{
float teamcheck;
entity spot, firstspot;
- spot = find (world, classname, "testplayerstart");
+ spot = find (NULL, classname, "testplayerstart");
if (spot)
return spot;
teamcheck = -1;
else if(have_team_spawns > 0)
{
- if(have_team_spawns_forteam[self.team] == 0)
+ if(have_team_spawns_forteam[this.team] == 0)
{
// we request a spawn for a team, and we have team
// spawns, but that team has no spawns?
teamcheck = -1;
}
else
- teamcheck = self.team; // MUST be team
+ teamcheck = this.team; // MUST be team
}
else if(have_team_spawns == 0 && have_team_spawns_forteam[0])
teamcheck = 0; // MUST be noteam
}
else
{
- firstspot = Spawn_FilterOutBadSpots(firstspot, 100, teamcheck);
+ firstspot = Spawn_FilterOutBadSpots(this, firstspot, 100, teamcheck);
// there is 50/50 chance of choosing a random spot or the furthest spot
// (this means that roughly every other spawn will be furthest, so you
else
{
if(some_spawn_has_been_used)
- return world; // team can't spawn any more, because of actions of other team
+ return NULL; // team can't spawn any more, because of actions of other team
else
error("Cannot find a spawn point - please fix the map!");
}