prio = 0;
// filter out spots for the wrong team
- if(teamcheck)
- if(spot.team != teamcheck)
- return '-1 0 0';
+ if(teamcheck >= 0)
+ if(spot.team != teamcheck)
+ return '-1 0 0';
if(race_spawns)
if(spot.target == "")
spotlist = spot;
/*
- if(teamcheck)
+ if(teamcheck >= 0)
if(spot.team != teamcheck)
error("invalid spawn added");
/*
entity e;
- if(teamcheck)
+ if(teamcheck >= 0)
for(e = spotlist; e; e = e.chain)
{
print("seen ", etos(e), "\n");
if (spot)
return spot;
- teamcheck = 0;
-
- if(!anypoint && have_team_spawns > 0)
- teamcheck = self.team;
+ if(anypoint)
+ teamcheck = -1;
+ else if(have_team_spawns > 0)
+ teamcheck = self.team; // MUST be team
+ else if(have_team_spawns == 0 && have_noteam_spawns)
+ 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 list of players
playerlist = findchain(classname, "player");
print("spot mindistance: ", vtos(spot.spawnpoint_score), "\n");
entity e;
- if(teamcheck)
+ if(teamcheck >= 0)
for(e = firstspot; e; e = e.chain)
if(e.team != teamcheck)
error("invalid spawn found");
// reset fields the weapons may use
for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+ {
weapon_action(j, WR_RESETPLAYER);
+ // all weapons must be fully loaded when we spawn
+ entity e;
+ e = get_weaponinfo(j);
+ if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
+ self.weapon_load[j] = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
+ }
+
oldself = self;
self = spot;
activator = oldself;
WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor
WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop
WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not
- WriteByte(MSG_ENTITY, autocvar_g_balance_campingrifle_secondary); // client has to know if it should zoom or not
+ WriteByte(MSG_ENTITY, autocvar_g_balance_sniperrifle_secondary); // client has to know if it should zoom or not
WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
- WriteByte(MSG_ENTITY, autocvar_g_balance_campingrifle_magazinecapacity); // rifle max bullets
+ WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines
+ WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
return TRUE;
}
{
// do nothing
}
- else if(g_freezetag && self.freezetag_frozen == 1)
+ else if(self.freezetag_frozen)
{
// do nothing
}
playerdemo_init();
anticheat_init();
-
+
race_PreSpawnObserver();
//if(g_domination)
void ReadyCount();
void ClientDisconnect (void)
{
+ if(self.vehicle)
+ {
+ entity oldself;
+ oldself = self;
+ self = self.vehicle;
+ self.vehicle_exit(VHEF_RELESE);
+ self = oldself;
+ }
+
if not(self.flags & FL_CLIENT)
{
print("Warning: ClientDisconnect without ClientConnect\n");
{
// add a way to see what the items were BEFORE all of these checks for the mutator hook
olditems = self.items;
-
+
if((self.items & IT_USING_JETPACK) && !self.deadflag)
{
SoundEntity_StartSound(self, CHAN_PLAYER, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
self.modelflags &~= MF_ROCKET;
}
- self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
+ self.effects &~= (EF_DIMLIGHT | EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
if(!self.modelindex || self.deadflag) // don't apply the flags if the player is gibbed
return;
-
+
Fire_ApplyDamage(self);
Fire_ApplyEffect(self);
if (time < self.spawnshieldtime)
self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
}
-
+
MUTATOR_CALLHOOK(PlayerPowerups);
}
self.ammo_nails = spectatee.ammo_nails;
self.ammo_rockets = spectatee.ammo_rockets;
self.ammo_fuel = spectatee.ammo_fuel;
+ self.clip_load = spectatee.clip_load;
+ self.clip_size = spectatee.clip_size;
self.effects = spectatee.effects & EFMASK_CHEAP; // eat performance
self.health = spectatee.health;
self.impulse = 0;
self.items = spectatee.items;
self.last_pickup = spectatee.last_pickup;
+ self.hit_time = spectatee.hit_time;
self.metertime = spectatee.metertime;
self.strength_finished = spectatee.strength_finished;
self.invincible_finished = spectatee.invincible_finished;
self.weapons = spectatee.weapons;
self.switchweapon = spectatee.switchweapon;
self.weapon = spectatee.weapon;
+ self.nex_charge = spectatee.nex_charge;
+ self.nex_chargepool_ammo = spectatee.nex_chargepool_ammo;
+ self.minelayer_mines = spectatee.minelayer_mines;
self.punchangle = spectatee.punchangle;
self.view_ofs = spectatee.view_ofs;
self.v_angle = spectatee.v_angle;
SetZoomState(spectatee.zoomstate);
anticheat_spectatecopy(spectatee);
+
+ //self.vehicle = spectatee.vehicle;
+
+ self.hud = spectatee.hud;
+ if(spectatee.vehicle)
+ {
+ self.vehicle_health = spectatee.vehicle_health;
+ self.vehicle_shield = spectatee.vehicle_shield;
+ self.vehicle_energy = spectatee.vehicle_energy;
+ self.vehicle_ammo1 = spectatee.vehicle_ammo1;
+ self.vehicle_ammo2 = spectatee.vehicle_ammo2;
+ self.vehicle_reload1 = spectatee.vehicle_reload1;
+ self.vehicle_reload2 = spectatee.vehicle_reload2;
+ msg_entity = self;
+ WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+ WriteEntity(MSG_ONE, spectatee.vehicle.vehicle_viewport);
+ }
}
float SpectateUpdate() {
void LeaveSpectatorMode()
{
- if(isJoinAllowed()) {
+ if(nJoinAllowed(1)) {
if(!teams_matter || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) {
self.classname = "player";
* Determines whether the player is allowed to join. This depends on cvar
* g_maxplayers, if it isn't used this function always return TRUE, otherwise
* it checks whether the number of currently playing players exceeds g_maxplayers.
- * @return bool TRUE if the player is allowed to join, false otherwise
+ * @return int number of free slots for players, 0 if none
*/
-float isJoinAllowed() {
+float nJoinAllowed(float includeMe) {
if(self.team_forced < 0)
return FALSE; // forced spectators can never join
+ // TODO simplify this
+ local entity e;
+
+ local float totalClients;
+ FOR_EACH_CLIENT(e)
+ totalClients += 1;
+
if (!autocvar_g_maxplayers)
- return TRUE;
+ return maxclients - totalClients + includeMe;
- local entity e;
local float currentlyPlaying;
- FOR_EACH_REALPLAYER(e) {
- if(e.classname == "player")
- currentlyPlaying += 1;
- }
+ FOR_EACH_REALPLAYER(e)
+ currentlyPlaying += 1;
+
if(currentlyPlaying < autocvar_g_maxplayers)
- return TRUE;
+ return min(maxclients - totalClients + includeMe, autocvar_g_maxplayers - currentlyPlaying);
- return FALSE;
+ return 0;
}
/**
}
if(!zoomstate_set)
- SetZoomState(self.BUTTON_ZOOM || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_CAMPINGRIFLE && autocvar_g_balance_campingrifle_secondary == 0));
+ SetZoomState(self.BUTTON_ZOOM || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_SNIPERRIFLE && autocvar_g_balance_sniperrifle_secondary == 0));
float oldspectatee_status;
oldspectatee_status = self.spectatee_status;
}
target_voicescript_next(self);
+
+ // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
+ if(!self.weapon)
+ self.clip_load = self.clip_size = 0;
}
float isInvisibleString(string s)
if(self.waypointsprite_attachedforcarrier)
WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent));
-
+
if(self.classname == "player" && self.deadflag == DEAD_NO && autocvar_r_showbboxes)
{
if(!self.showheadshotbbox)
playerdemo_write();
- if((g_cts || g_race) && self.cvar_cl_allow_uid2name == 1)
+ if((g_cts || g_race) && self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
{
if(!self.stored_netname)
self.stored_netname = strzone(uid2name(self.crypto_idfp));