}
}
-
-.vector spawnpoint_score;
.string netname_previous;
-void spawnfunc_info_player_survivor (void)
-{
- spawnfunc_info_player_deathmatch();
-}
-
-void spawnfunc_info_player_start (void)
-{
- spawnfunc_info_player_deathmatch();
-}
-
-void spawnfunc_info_player_deathmatch (void)
-{
- self.classname = "info_player_deathmatch";
- relocate_spawnpoint();
-}
-
-void spawnpoint_use()
-{
- if(teamplay)
- if(have_team_spawns > 0)
- {
- self.team = activator.team;
- some_spawn_has_been_used = 1;
- }
-}
-
-// Returns:
-// _x: prio (-1 if unusable)
-// _y: weight
-vector Spawn_Score(entity spot, float mindist, float teamcheck)
-{
- float shortest, thisdist;
- float prio;
- entity player;
-
- prio = 0;
-
- // filter out spots for the wrong team
- if(teamcheck >= 0)
- if(spot.team != teamcheck)
- return '-1 0 0';
-
- if(race_spawns)
- if(spot.target == "")
- return '-1 0 0';
-
- if(clienttype(self) == CLIENTTYPE_REAL)
- {
- if(spot.restriction == 1)
- return '-1 0 0';
- }
- else
- {
- if(spot.restriction == 2)
- return '-1 0 0';
- }
-
- shortest = vlen(world.maxs - world.mins);
- FOR_EACH_PLAYER(player) if (player != self)
- {
- thisdist = vlen(player.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;
-
- // filter out spots for assault
- if(spot.target != "") {
- entity ent;
- float found;
-
- found = 0;
- for(ent = world; (ent = find(ent, targetname, spot.target)); )
- {
- ++found;
- if(ent.spawn_evalfunc)
- {
- entity oldself = self;
- self = ent;
- spawn_score = ent.spawn_evalfunc(oldself, spot, spawn_score);
- self = oldself;
- 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");
- return '-1 0 0';
- }
- }
-
- MUTATOR_CALLHOOK(Spawn_Score);
- return spawn_score;
-}
-
-void Spawn_ScoreAll(entity firstspot, float mindist, float teamcheck)
-{
- entity spot;
- for(spot = firstspot; spot; spot = spot.chain)
- spot.spawnpoint_score = Spawn_Score(spot, mindist, teamcheck);
-}
-
-entity Spawn_FilterOutBadSpots(entity firstspot, float mindist, float teamcheck)
-{
- entity spot, spotlist, spotlistend;
-
- spotlist = world;
- spotlistend = world;
-
- Spawn_ScoreAll(firstspot, mindist, teamcheck);
-
- for(spot = firstspot; spot; spot = spot.chain)
- {
- if(spot.spawnpoint_score_x >= 0) // spawning allowed here
- {
- if(spotlistend)
- spotlistend.chain = spot;
- spotlistend = spot;
- if(!spotlist)
- spotlist = spot;
- }
- }
- if(spotlistend)
- spotlistend.chain = world;
-
- return spotlist;
-}
-
-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)
- entity spot;
-
- RandomSelection_Init();
- for(spot = firstspot; spot; spot = spot.chain)
- RandomSelection_Add(spot, 0, string_null, pow(bound(lower, spot.spawnpoint_score_y, upper), exponent) * spot.cnt, (spot.spawnpoint_score_y >= lower) * 0.5 + spot.spawnpoint_score_x);
-
- return RandomSelection_chosen_ent;
-}
-
-/*
-=============
-SelectSpawnPoint
-
-Finds a point to respawn
-=============
-*/
-entity SelectSpawnPoint (float anypoint)
-{
- float teamcheck;
- entity spot, firstspot;
-
- spot = find (world, classname, "testplayerstart");
- if (spot)
- return spot;
-
- if(anypoint || autocvar_g_spawn_useallspawns)
- teamcheck = -1;
- else if(have_team_spawns > 0)
- {
- if(have_team_spawns_forteam[self.team] == 0)
- {
- // we request a spawn for a team, and we have team
- // spawns, but that team has no spawns?
- if(have_team_spawns_forteam[0])
- // try noteam spawns
- teamcheck = 0;
- else
- // if not, any spawn has to do
- teamcheck = -1;
- }
- else
- teamcheck = self.team; // MUST be team
- }
- else if(have_team_spawns == 0 && have_team_spawns_forteam[0])
- teamcheck = 0; // MUST be noteam
- else
- teamcheck = -1;
- // if we get here, we either require team spawns but have none, or we require non-team spawns and have none; use any spawn then
-
-
- // get the entire list of spots
- firstspot = findchain(classname, "info_player_deathmatch");
- // filter out the bad ones
- // (note this returns the original list if none survived)
- if(anypoint)
- {
- spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
- }
- else
- {
- float mindist;
- if (g_arena && arena_roundbased)
- mindist = 800;
- else
- mindist = 100;
- firstspot = Spawn_FilterOutBadSpots(firstspot, mindist, 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
- // usually won't get fragged at spawn twice in a row)
- if (random() > autocvar_g_spawn_furthest)
- spot = Spawn_WeightedPoint(firstspot, 1, 1, 1);
- else
- spot = Spawn_WeightedPoint(firstspot, 1, 5000, 5); // chooses a far far away spawnpoint
- }
-
- if (!spot)
- {
- if(autocvar_spawn_debug)
- GotoNextMap(0);
- else
- {
- if(some_spawn_has_been_used)
- return world; // team can't spawn any more, because of actions of other team
- else
- error("Cannot find a spawn point - please fix the map!");
- }
- }
-
- return spot;
-}
/*
=============
WriteEntity(MSG_ONE, self);
}
- if(g_lms)
- {
- // Only if the player cannot play at all
- if(PlayerScore_Add(self, SP_LMS_RANK, 0) == 666)
- self.frags = FRAGS_SPECTATOR;
- else
- self.frags = FRAGS_LMS_LOSER;
- }
- else if((g_race && g_race_qualifying) || g_cts)
+ if((g_race && g_race_qualifying) || g_cts)
{
if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
self.frags = FRAGS_LMS_LOSER;
// reset player keys
self.itemkeys = 0;
- // player is dead and becomes observer
- // FIXME fix LMS scoring for new system
- if(g_lms)
- {
- if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0)
- self.classname = "observer";
- }
-
MUTATOR_CALLHOOK(PutClientInServer);
if(gameover)
self.colormod = '1 1 1' * autocvar_g_player_brightness;
self.exteriorweaponentity.alpha = default_weapon_alpha;
- self.lms_nextcheck = time + autocvar_g_lms_campcheck_interval*2;
- self.lms_traveled_distance = 0;
self.speedrunning = FALSE;
race_PostSpawn(spot);
}
+ float SpectateSet()
+ {
+ if(self.enemy.classname != "player")
+ return FALSE;
+ /*if(self.enemy.vehicle)
+ {
+
+ msg_entity = self;
+ WriteByte(MSG_ONE, SVC_SETVIEW);
+ WriteEntity(MSG_ONE, self.enemy);
+ //stuffcmd(self, "set viewsize $tmpviewsize \n");
+
+ self.movetype = MOVETYPE_NONE;
+ accuracy_resend(self);
+ }
+ else
+ {*/
+ msg_entity = self;
+ WriteByte(MSG_ONE, SVC_SETVIEW);
+ WriteEntity(MSG_ONE, self.enemy);
+ //stuffcmd(self, "set viewsize $tmpviewsize \n");
+ self.movetype = MOVETYPE_NONE;
+ accuracy_resend(self);
+
+ if(!SpectateUpdate())
+ PutObserverInServer();
+ //}
+ return TRUE;
+ }
+
+ float Spectate(entity pl)
+ {
+ if(g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
+ if(pl.team != self.team)
+ return 0;
+
+ self.enemy = pl;
+ return SpectateSet();
+ }
+
// Returns next available player to spectate if g_ca_spectate_enemies == 0
entity CA_SpectateNext(entity start) {
if (start.team == self.team) {
return other;
}
- float SpectateNext(entity _prefer) {
-
- if(_prefer)
- other = _prefer;
- else
- other = find(self.enemy, classname, "player");
-
+ float SpectateNext()
+ {
+ other = find(self.enemy, classname, "player");
+
if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer) {
// CA and ca players when spectating enemies is forbidden
other = CA_SpectateNext(other);
if (!other)
other = find(other, classname, "player");
}
-
+
if (other)
self.enemy = other;
- if(self.enemy.classname == "player") {
- /*if(self.enemy.vehicle)
- {
-
- msg_entity = self;
- WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, self.enemy);
- //stuffcmd(self, "set viewsize $tmpviewsize \n");
-
- self.movetype = MOVETYPE_NONE;
- accuracy_resend(self);
- }
- else
- {*/
- msg_entity = self;
- WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, self.enemy);
- //stuffcmd(self, "set viewsize $tmpviewsize \n");
- self.movetype = MOVETYPE_NONE;
- accuracy_resend(self);
-
- if(!SpectateUpdate())
- PutObserverInServer();
- //}
- return 1;
- } else {
- return 0;
+ return SpectateSet();
+ }
+
+ float SpectatePrev()
+ {
+ // NOTE: chain order is from the highest to the lower entnum (unlike find)
+ other = findchain(classname, "player");
+ if not(other) // no player
+ return FALSE;
+
+ entity first = other;
+ // skip players until current spectated player
+ if(self.enemy)
+ while(other && other != self.enemy)
+ other = other.chain;
+
+ if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer)
+ {
+ do { other = other.chain; }
+ while(other && other.team != self.team);
+
+ if not(other)
+ {
+ other = first;
+ while(other.team != self.team)
+ other = other.chain;
+ if(other == self.enemy)
+ return TRUE;
+ }
+ }
+ else
+ {
+ if(other.chain)
+ other = other.chain;
+ else
+ other = first;
}
+ self.enemy = other;
+ return SpectateSet();
}
/*
self.flags |= FL_SPAWNING;
} else if(self.BUTTON_ATCK && !self.version_mismatch) {
self.flags &~= FL_JUMPRELEASED;
- if(SpectateNext(world) == 1) {
+ if(SpectateNext()) {
self.classname = "spectator";
}
} else {
if (self.BUTTON_JUMP && !self.version_mismatch) {
self.flags &~= FL_JUMPRELEASED;
self.flags |= FL_SPAWNING;
- } else if(self.BUTTON_ATCK) {
+ } else if(self.BUTTON_ATCK || self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || self.impulse >= 200 && self.impulse <= 209) {
+ self.flags &~= FL_JUMPRELEASED;
+ if(SpectateNext()) {
+ self.classname = "spectator";
+ } else {
+ self.classname = "observer";
+ PutClientInServer();
+ }
+ self.impulse = 0;
+ } else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || self.impulse >= 220 && self.impulse <= 229) {
self.flags &~= FL_JUMPRELEASED;
- if(SpectateNext(world) == 1) {
+ if(SpectatePrev()) {
self.classname = "spectator";
} else {
self.classname = "observer";
PutClientInServer();
}
+ self.impulse = 0;
} else if (self.BUTTON_ATCK2) {
self.flags &~= FL_JUMPRELEASED;
self.classname = "observer";
}
}
-float spawnpoint_nag;
-void relocate_spawnpoint()
-{
- // nudge off the floor
- setorigin(self, self.origin + '0 0 1');
-
- tracebox(self.origin, PL_MIN, PL_MAX, self.origin, TRUE, self);
- if (trace_startsolid)
- {
- vector o;
- o = self.origin;
- self.mins = PL_MIN;
- self.maxs = PL_MAX;
- 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");
- 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");
- spawnpoint_nag = 1;
- }
- else
- {
- setorigin(self, o);
- self.mins = self.maxs = '0 0 0';
- objerror("player spawn point in solid, mapper sucks!\n");
- return;
- }
- }
-
- self.use = spawnpoint_use;
- self.team_saved = self.team;
- if (!self.cnt)
- self.cnt = 1;
-
- if (have_team_spawns != 0)
- if (self.team)
- have_team_spawns = 1;
- have_team_spawns_forteam[self.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);
- setsize(e, '-8 -8 -8', '8 8 8');
- e.solid = SOLID_TRIGGER;
- }
-}
-
#define strstr strstrofs
/*
// NOTE: DO NOT USE THIS FUNCTION TOO OFTEN.
g_pinata = 0; // incompatible
g_weapon_stay = 0; // incompatible
WEPSET_COPY_AA(start_weapons, g_weaponarena_weapons);
- if(!g_ca)
- start_items |= IT_UNLIMITED_AMMO;
+ start_items |= IT_UNLIMITED_AMMO;
}
else if (g_minstagib)
{
}
else
{
- if(g_ca)
- {
- start_ammo_shells = cvar("g_lms_start_ammo_shells");
- start_ammo_nails = cvar("g_lms_start_ammo_nails");
- start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
- start_ammo_cells = cvar("g_lms_start_ammo_cells");
- start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
- }
- else
- {
- start_ammo_shells = cvar("g_start_ammo_shells");
- start_ammo_nails = cvar("g_start_ammo_nails");
- start_ammo_rockets = cvar("g_start_ammo_rockets");
- start_ammo_cells = cvar("g_start_ammo_cells");
- start_ammo_fuel = cvar("g_start_ammo_fuel");
- }
- }
-
- if (g_ca)
- {
- start_health = cvar("g_lms_start_health");
- start_armorvalue = cvar("g_lms_start_armor");
+ start_ammo_shells = cvar("g_start_ammo_shells");
+ start_ammo_nails = cvar("g_start_ammo_nails");
+ start_ammo_rockets = cvar("g_start_ammo_rockets");
+ start_ammo_cells = cvar("g_start_ammo_cells");
+ start_ammo_fuel = cvar("g_start_ammo_fuel");
}
if (inWarmupStage)