void race_SendRankings(float pos, float prevpos, float del, float msg);
void send_CSQC_teamnagger() {
- WriteByte(0, SVC_TEMPENTITY);
- WriteByte(0, TE_CSQC_TEAMNAGGER);
-}
-
-void send_CSQC_cr_maxbullets(entity e) {
- msg_entity = e;
- WriteByte(MSG_ONE, SVC_TEMPENTITY);
- WriteByte(MSG_ONE, TE_CSQC_CR_MAXBULLETS);
- WriteByte(MSG_ONE, autocvar_g_balance_campingrifle_magazinecapacity);
+ WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
void Announce(string snd) {
self.frags = FRAGS_SPECTATOR;
}
-float RestrictSkin(float s)
-{
- if(!teams_matter)
- return s;
- if(s == 6)
- return 6;
- return mod(s, 3);
-}
-
void FixPlayermodel()
{
local string defaultmodel;
}
oldskin = self.skinindex;
- self.skinindex = RestrictSkin(stof(self.playerskin));
+ self.skinindex = stof(self.playerskin);
}
if(chmdl || oldskin != self.skinindex)
self.cnt = self.switchweapon;
self.weapon = 0;
+ self.wish_reload = 0;
+
if(!self.alivetime)
self.alivetime = time;
} else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
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_sniperrifle_magazinecapacity); // rifle max bullets
+ WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
return TRUE;
}
void ClientKill_Now()
{
+ remove(self.killindicator);
+ self.killindicator = world;
+
if(self.killindicator_teamchange)
ClientKill_Now_TeamChange();
// in any case:
Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
- if(self.killindicator)
- {
- dprint("Cleaned up after a leaked kill indicator.\n");
- remove(self.killindicator);
- self.killindicator = world;
- }
+ // now I am sure the player IS dead
}
void KillIndicator_Think()
{
if(g_race_qualifying || g_cts)
killtime = 0;
+ if(g_cts && self.killindicator && self.killindicator.health == 1) // self.killindicator.health == 1 means that the kill indicator was spawned by CTS_ClientKill
+ {
+ remove(self.killindicator);
+ self.killindicator = world;
+
+ ClientKill_Now(); // allow instant kill in this case
+ return;
+ }
+
self.killindicator_teamchange = targetteam;
if(!self.killindicator)
self.killindicator.nextthink = time + (self.lip) * 0.05;
self.killindicator.cnt = ceil(killtime);
self.killindicator.count = bound(0, ceil(killtime), 10);
- sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n"));
+ //sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n"));
for(e = world; (e = find(e, classname, "body")) != world; )
{
{
// do nothing
}
- else if(g_freezetag && self.freezetag_frozen == 1)
+ else if(self.freezetag_frozen)
{
// do nothing
}
ClientKill_TeamChange(0);
}
-void CTS_ClientKill (entity e) // silent version of ClientKill
+void CTS_ClientKill (entity e) // silent version of ClientKill, used when player finishes a CTS run. Useful to prevent cheating by running back to the start line and starting out with more speed
{
e.killindicator = spawn();
e.killindicator.owner = e;
else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca
send_CSQC_teamnagger();
- send_CSQC_cr_maxbullets(self);
-
CheatInitClient();
PlayerStats_AddPlayer(self);
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;
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;
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;
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));