#include "client.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include <common/effects/all.qh>
#include "anticheat.qh"
#include "teamplay.qh"
#include "spawnpoints.qh"
#include "resources.qh"
-#include "g_damage.qh"
+#include "damage.qh"
#include "handicap.qh"
-#include "g_hook.qh"
+#include "hook.qh"
+#include <server/intermission.qh>
#include "command/common.qh"
#include "command/vote.qh"
#include "clientkill.qh"
#include "cheats.qh"
-#include "g_world.qh"
+#include "world.qh"
+#include <server/gamelog.qh>
#include "race.qh"
+#include <server/main.qh>
#include "antilag.qh"
#include "campaign.qh"
#include "command/common.qh"
#include "scores_rules.qh"
+#include "weapons/common.qh"
#include "bot/api.qh"
#include <common/effects/qc/globalsound.qh>
#include "../common/mapobjects/func/conveyor.qh"
+#include <common/mapobjects/func/ladder.qh>
#include "../common/mapobjects/teleporters.qh"
#include "../common/mapobjects/target/spawnpoint.qh"
#include <common/mapobjects/trigger/counter.qh>
#include "../common/vehicles/all.qh"
#include "weapons/hitplot.qh"
+#include "weapons/selection.qh"
#include "weapons/weaponsystem.qh"
#include "../common/net_notice.qh"
#include "../common/items/_mod.qh"
+#include <common/gamemodes/gamemode/nexball/sv_nexball.qh>
+
#include "../common/mutators/mutator/waypoints/all.qh"
#include "../common/mutators/mutator/instagib/sv_instagib.qh"
#include <common/gamemodes/_mod.qh>
#include <common/mutators/mutator/overkill/oknex.qh>
+#include <common/weapons/weapon/vortex.qh>
+
+#define CHAT_NOSPECTATORS() ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage))
+
STATIC_METHOD(Client, Add, void(Client this, int _team))
{
ClientConnect(this);
{
if(!player) { return; } // not sure how, but best to be safe
+ int spec_count = 0;
FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
{
+ if(spec_count >= MAX_SPECTATORS)
+ break;
WriteByte(MSG_ENTITY, num_for_edict(it));
+ ++spec_count;
});
}
/** putting a client as observer in the server */
void PutObserverInServer(entity this)
{
- bool mutator_returnvalue = MUTATOR_CALLHOOK(MakePlayerObserver, this);
+ bool mutator_returnvalue = MUTATOR_CALLHOOK(MakePlayerObserver, this);
PlayerState_detach(this);
if (IS_PLAYER(this))
if (vote_called) { VoteCount(false); }
ReadyCount();
}
- }
+ }
- {
- entity spot = SelectSpawnPoint(this, true);
- if (!spot) LOG_FATAL("No spawnpoints for observers?!?");
- this.angles = vec2(spot.angles);
- this.fixangle = true;
- // offset it so that the spectator spawns higher off the ground, looks better this way
- setorigin(this, spot.origin + STAT(PL_VIEW_OFS, this));
- if (IS_REAL_CLIENT(this))
- {
- msg_entity = this;
- WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, this);
- }
- // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
- // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
- if(!autocvar_g_debug_globalsounds)
- {
- // needed for player sounds
- this.model = "";
- FixPlayermodel(this);
- }
- setmodel(this, MDL_Null);
- setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
- this.view_ofs = '0 0 0';
- }
+ entity spot = SelectSpawnPoint(this, true);
+ if (!spot) LOG_FATAL("No spawnpoints for observers?!?");
+ this.angles = vec2(spot.angles);
+ this.fixangle = true;
+ // offset it so that the spectator spawns higher off the ground, looks better this way
+ setorigin(this, spot.origin + STAT(PL_VIEW_OFS, this));
+ if (IS_REAL_CLIENT(this))
+ {
+ msg_entity = this;
+ WriteByte(MSG_ONE, SVC_SETVIEW);
+ WriteEntity(MSG_ONE, this);
+ }
+ // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
+ // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
+ if(!autocvar_g_debug_globalsounds)
+ {
+ // needed for player sounds
+ this.model = "";
+ FixPlayermodel(this);
+ }
+ setmodel(this, MDL_Null);
+ setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
+ this.view_ofs = '0 0 0';
- RemoveGrapplingHooks(this);
+ RemoveGrapplingHooks(this);
Portal_ClearAll(this);
Unfreeze(this, false);
SetSpectatee(this, NULL);
WaypointSprite_PlayerDead(this);
- if (CS(this).killcount != FRAGS_SPECTATOR)
- {
- if(!game_stopped)
- if(autocvar_g_chat_nospectators == 1 || (!warmup_stage && autocvar_g_chat_nospectators == 2))
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
- }
+ if (CS(this).killcount != FRAGS_SPECTATOR && !game_stopped && CHAT_NOSPECTATORS())
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
accuracy_resend(this);
if(this.monster_attack)
IL_REMOVE(g_monster_targets, this);
this.monster_attack = false;
- STAT(HUD, this) = HUD_NORMAL;
+ STAT(HUD, this) = HUD_NORMAL;
TRANSMUTE(Observer, this);
this.iscreature = false;
this.teleportable = TELEPORT_SIMPLE;
this.alpha = 0;
this.scale = 0;
this.fade_time = 0;
- this.pain_frame = 0;
this.pain_finished = 0;
- this.strength_finished = 0;
- this.invincible_finished = 0;
- this.superweapons_finished = 0;
+ STAT(STRENGTH_FINISHED, this) = 0;
+ STAT(INVINCIBLE_FINISHED, this) = 0;
+ STAT(SUPERWEAPONS_FINISHED, this) = 0;
+ STAT(AIR_FINISHED, this) = 0;
//this.dphitcontentsmask = 0;
this.dphitcontentsmask = DPCONTENTS_SOLID;
if (autocvar_g_playerclip_collisions)
setthink(this, func_null);
this.nextthink = 0;
this.deadflag = DEAD_NO;
- this.crouch = false;
+ UNSET_DUCKED(this);
STAT(REVIVE_PROGRESS, this) = 0;
this.revival_time = 0;
this.draggable = drag_undraggable;
PS(this).dual_weapons = '0 0 0';
- this.superweapons_finished = (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
+ STAT(SUPERWEAPONS_FINISHED, this) = (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
this.items = start_items;
this.respawn_flags = 0;
this.respawn_time = 0;
STAT(RESPAWN_TIME, this) = 0;
- this.scale = autocvar_sv_player_scale;
+ bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox;
+ this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale);
this.fade_time = 0;
- this.pain_frame = 0;
this.pain_finished = 0;
this.pushltime = 0;
setthink(this, func_null); // players have no think function
this.punchangle = '0 0 0';
this.punchvector = '0 0 0';
- this.strength_finished = 0;
- this.invincible_finished = 0;
+ STAT(STRENGTH_FINISHED, this) = 0;
+ STAT(INVINCIBLE_FINISHED, this) = 0;
this.fire_endtime = -1;
STAT(REVIVE_PROGRESS, this) = 0;
this.revival_time = 0;
STAT(BUFFS, this) = 0;
STAT(BUFF_TIME, this) = 0;
- this.air_finished = time + 12;
+ STAT(AIR_FINISHED, this) = 0;
this.waterlevel = WATERLEVEL_NONE;
this.watertype = CONTENT_EMPTY;
this.spawnpoint_targ = NULL;
- this.crouch = false;
+ UNSET_DUCKED(this);
this.view_ofs = STAT(PL_VIEW_OFS, this);
setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
this.spawnorigin = spot.origin;
IL_REMOVE(g_conveyed, this);
this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
if(this.swampslug)
- delete(this.swampslug);
- this.in_swamp = false;
+ IL_REMOVE(g_swamped, this);
+ this.swampslug = NULL;
+ this.swamp_interval = 0;
+ if(this.ladder_entity)
+ IL_REMOVE(g_ladderents, this);
+ this.ladder_entity = NULL;
+ IL_EACH(g_counters, it.realowner == this,
+ {
+ delete(it);
+ });
STAT(HUD, this) = HUD_NORMAL;
this.event_damage = PlayerDamage;
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
- entity oldwep = this.(weaponentity);
CL_SpawnWeaponentity(this, weaponentity);
- if(oldwep && oldwep.owner == this)
- this.(weaponentity).m_gunalign = oldwep.m_gunalign;
}
this.alpha = default_player_alpha;
this.colormod = '1 1 1' * autocvar_g_player_brightness;
if (CS(this).impulse) ImpulseCommands(this);
+ W_ResetGunAlign(this, CS(this).cvar_cl_gunalign);
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[2]));
WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[3]));
- if(sv_foginterval && world.fog != "")
+ if(autocvar_sv_foginterval && world.fog != "")
WriteString(channel, world.fog);
else
WriteString(channel, "");
CS(this).parm_idlesince = time;
// whatever happens, allow 60 seconds of idling directly after connect for map loading
- CS(this).parm_idlesince = max(CS(this).parm_idlesince, time - sv_maxidle + 60);
+ CS(this).parm_idlesince = max(CS(this).parm_idlesince, time - autocvar_sv_maxidle + 60);
MUTATOR_CALLHOOK(DecodeLevelParms);
}
modifications = strcat(modifications, ", Low gravity");
if(g_weapon_stay && !g_cts)
modifications = strcat(modifications, ", Weapons stay");
- if(g_jetpack)
+ if(autocvar_g_jetpack)
modifications = strcat(modifications, ", Jet pack");
if(autocvar_g_powerups == 0)
modifications = strcat(modifications, ", No powerups");
modifications = substring(modifications, 2, strlen(modifications) - 2);
string versionmessage = GetClientVersionMessage(this);
- string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
+ string s = strcat(versionmessage, "^8\n^8\nhost is ^9", autocvar_hostname, "^8\n");
+
+ s = strcat(s, "^8\nmatch type is ^1", gamemode_name, "^8\n");
if(modifications != "")
s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
return s;
}
-bool autocvar_sv_qcphysics = false; // TODO this is for testing - remove when qcphysics work
+bool autocvar_sv_qcphysics = true; // TODO this is for testing - remove when qcphysics work
/**
=============
this.flags |= FL_CLIENT;
assert(player_count >= 0, player_count = 0);
-#ifdef WATERMARK
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_WATERMARK, WATERMARK);
-#endif
TRANSMUTE(Client, this);
CS(this).version_nagtime = time + 10 + random() * 10;
CS(this).allowed_timeouts = autocvar_sv_timeout_number;
if (autocvar_sv_eventlog)
- GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false)));
+ GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? GameLog_ProcessIP(this.netaddress) : "bot"), ":", playername(this, false)));
CS(this).just_joined = true; // stop spamming the eventlog with additional lines when the client connects
stuffcmd(this, "cl_cmd settemp chase_active 1\n");
}
- if (!sv_foginterval && world.fog != "")
+ if (!autocvar_sv_foginterval && world.fog != "")
stuffcmd(this, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && AvailableTeams() == 2))
if(IS_SPEC(this))
SetSpectatee(this, NULL);
- MUTATOR_CALLHOOK(ClientDisconnect, this);
+ MUTATOR_CALLHOOK(ClientDisconnect, this);
strfree(CS(this).netname_previous); // needs to be before the CS entity is removed!
strfree(CS(this).weaponorder_byimpulse);
if (this.chatbubbleentity) delete(this.chatbubbleentity);
if (this.killindicator) delete(this.killindicator);
+ IL_EACH(g_counters, it.realowner == this,
+ {
+ delete(it);
+ });
+
WaypointSprite_PlayerGone(this);
bot_relinkplayerlist();
}
}
+void calculate_player_respawn_time(entity this)
+{
+ if(MUTATOR_CALLHOOK(CalculateRespawnTime, this))
+ return;
+
+ float gametype_setting_tmp;
+ float sdelay_max = GAMETYPE_DEFAULTED_SETTING(respawn_delay_max);
+ float sdelay_small = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small);
+ float sdelay_large = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large);
+ float sdelay_small_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small_count);
+ float sdelay_large_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large_count);
+ float waves = GAMETYPE_DEFAULTED_SETTING(respawn_waves);
+
+ float pcount = 1; // Include myself whether or not team is already set right and I'm a "player".
+ if (teamplay)
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
+ if(it.team == this.team)
+ ++pcount;
+ });
+ if (sdelay_small_count == 0)
+ sdelay_small_count = 1;
+ if (sdelay_large_count == 0)
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
+ ++pcount;
+ });
+ if (sdelay_small_count == 0)
+ {
+ if (IS_INDEPENDENT_PLAYER(this))
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_small_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_small_count = 2;
+ }
+ }
+ if (sdelay_large_count == 0)
+ {
+ if (IS_INDEPENDENT_PLAYER(this))
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_large_count = 2;
+ }
+ }
+ }
+
+ float sdelay;
+
+ if (pcount <= sdelay_small_count)
+ sdelay = sdelay_small;
+ else if (pcount >= sdelay_large_count)
+ sdelay = sdelay_large;
+ else // NOTE: this case implies sdelay_large_count > sdelay_small_count.
+ sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count);
+
+ if(waves)
+ this.respawn_time = ceil((time + sdelay) / waves) * waves;
+ else
+ this.respawn_time = time + sdelay;
+
+ if(sdelay < sdelay_max)
+ this.respawn_time_max = time + sdelay_max;
+ else
+ this.respawn_time_max = this.respawn_time;
+
+ if((sdelay + waves >= 5.0) && (this.respawn_time - time > 1.75))
+ this.respawn_countdown = 10; // first number to count down from is 10
+ else
+ this.respawn_countdown = -1; // do not count down
+
+ if(autocvar_g_forced_respawn)
+ this.respawn_flags = this.respawn_flags | RESPAWN_FORCE;
+}
// LordHavoc: this hack will be removed when proper _pants/_shirt layers are
// added to the model skins
void respawn(entity this)
{
- if(this.alpha >= 0 && autocvar_g_respawn_ghosts)
+ bool damagedbycontents_prev = this.damagedbycontents;
+ if(this.alpha >= 0)
{
- this.solid = SOLID_NOT;
- this.takedamage = DAMAGE_NO;
- set_movetype(this, MOVETYPE_FLY);
- this.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
- this.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
- this.effects |= CSQCMODEL_EF_RESPAWNGHOST;
- Send_Effect(EFFECT_RESPAWN_GHOST, this.origin, '0 0 0', 1);
- if(autocvar_g_respawn_ghosts_maxtime)
- SUB_SetFade (this, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
+ if(autocvar_g_respawn_ghosts)
+ {
+ this.solid = SOLID_NOT;
+ this.takedamage = DAMAGE_NO;
+ this.damagedbycontents = false;
+ set_movetype(this, MOVETYPE_FLY);
+ this.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
+ this.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
+ this.effects |= CSQCMODEL_EF_RESPAWNGHOST;
+ this.alpha = min(this.alpha, autocvar_g_respawn_ghosts_alpha);
+ Send_Effect(EFFECT_RESPAWN_GHOST, this.origin, '0 0 0', 1);
+ if(autocvar_g_respawn_ghosts_time > 0)
+ SUB_SetFade(this, time + autocvar_g_respawn_ghosts_time, autocvar_g_respawn_ghosts_fadetime);
+ }
+ else
+ SUB_SetFade (this, time, 1); // fade out the corpse immediately
}
CopyBody(this, 1);
+ this.damagedbycontents = damagedbycontents_prev;
this.effects |= EF_NODRAW; // prevent another CopyBody
PutClientInServer(this);
ERASEABLE
void DebugPrintToChat(entity client, string text)
{
- if (autocvar_developer)
+ if (autocvar_developer > 0)
{
PrintToChat(client, text);
}
ERASEABLE
void DebugPrintToChatAll(string text)
{
- if (autocvar_developer)
+ if (autocvar_developer > 0)
{
PrintToChatAll(text);
}
ERASEABLE
void DebugPrintToChatTeam(int team_num, string text)
{
- if (autocvar_developer)
+ if (autocvar_developer > 0)
{
PrintToChatTeam(team_num, text);
}
void player_powerups(entity this)
{
- // add a way to see what the items were BEFORE all of these checks for the mutator hook
- int items_prev = this.items;
-
if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !game_stopped)
this.modelflags |= MF_ROCKET;
else
this.effects &= ~(EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
+ if (IS_DEAD(this))
+ {
+ if (this.items & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON))
+ {
+ sound(this, CH_INFO, SND_POWEROFF, VOL_BASE, ATTEN_NORM);
+ stopsound(this, CH_TRIGGER_SINGLE); // get rid of the pickup sound
+ this.items &= ~ITEM_Strength.m_itemid;
+ this.items &= ~ITEM_Shield.m_itemid;
+ this.items -= (this.items & IT_SUPERWEAPON);
+ }
+ }
+
if((this.alpha < 0 || IS_DEAD(this)) && !this.vehicle) // don't apply the flags if the player is gibbed
return;
+ // add a way to see what the items were BEFORE all of these checks for the mutator hook
+ int items_prev = this.items;
+
Fire_ApplyDamage(this);
Fire_ApplyEffect(this);
{
if (this.items & ITEM_Strength.m_itemid)
{
- play_countdown(this, this.strength_finished, SND_POWEROFF);
+ play_countdown(this, STAT(STRENGTH_FINISHED, this), SND_POWEROFF);
this.effects = this.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
- if (time > this.strength_finished)
+ if (time > STAT(STRENGTH_FINISHED, this))
{
this.items = this.items - (this.items & ITEM_Strength.m_itemid);
//Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_STRENGTH, this.netname);
}
else
{
- if (time < this.strength_finished)
+ if (time < STAT(STRENGTH_FINISHED, this))
{
this.items = this.items | ITEM_Strength.m_itemid;
if(!g_cts)
}
if (this.items & ITEM_Shield.m_itemid)
{
- play_countdown(this, this.invincible_finished, SND_POWEROFF);
+ play_countdown(this, STAT(INVINCIBLE_FINISHED, this), SND_POWEROFF);
this.effects = this.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
- if (time > this.invincible_finished)
+ if (time > STAT(INVINCIBLE_FINISHED, this))
{
this.items = this.items - (this.items & ITEM_Shield.m_itemid);
//Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_SHIELD, this.netname);
}
else
{
- if (time < this.invincible_finished)
+ if (time < STAT(INVINCIBLE_FINISHED, this))
{
this.items = this.items | ITEM_Shield.m_itemid;
if(!g_cts)
{
if (!(STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
{
- this.superweapons_finished = 0;
+ STAT(SUPERWEAPONS_FINISHED, this) = 0;
this.items = this.items - (this.items & IT_SUPERWEAPON);
//Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_LOST, this.netname);
Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
}
else
{
- play_countdown(this, this.superweapons_finished, SND_POWEROFF);
- if (time > this.superweapons_finished)
+ play_countdown(this, STAT(SUPERWEAPONS_FINISHED, this), SND_POWEROFF);
+ if (time > STAT(SUPERWEAPONS_FINISHED, this))
{
this.items = this.items - (this.items & IT_SUPERWEAPON);
STAT(WEAPONS, this) &= ~WEPSET_SUPERWEAPONS;
}
else if(STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS)
{
- if (time < this.superweapons_finished || (this.items & IT_UNLIMITED_SUPERWEAPONS))
+ if (time < STAT(SUPERWEAPONS_FINISHED, this) || (this.items & IT_UNLIMITED_SUPERWEAPONS))
{
this.items = this.items | IT_SUPERWEAPON;
if(!(this.items & IT_UNLIMITED_SUPERWEAPONS))
}
else
{
- this.superweapons_finished = 0;
+ STAT(SUPERWEAPONS_FINISHED, this) = 0;
STAT(WEAPONS, this) &= ~WEPSET_SUPERWEAPONS;
}
}
else
{
- this.superweapons_finished = 0;
+ STAT(SUPERWEAPONS_FINISHED, this) = 0;
}
}
return max(stable, current + (stable - current) * rotfactor * rotframetime);
}
-float CalcRotRegen(float current, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit)
+void RotRegen(entity this, int res, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit_mod)
{
+ float old = GetResource(this, res);
+ float current = old;
if(current > rotstable)
{
if(rotframetime > 0)
}
}
+ float limit = GetResourceLimit(this, res) * limit_mod;
if(current > limit)
current = limit;
- return current;
+ if (current != old)
+ SetResource(this, res, current);
}
void player_regen(entity this)
if(!mutator_returnvalue)
if(!STAT(FROZEN, this))
{
- float mina, maxa, limith, limita;
- maxa = autocvar_g_balance_armor_rotstable;
- mina = autocvar_g_balance_armor_regenstable;
- limith = GetResourceLimit(this, RES_HEALTH);
- limita = GetResourceLimit(this, RES_ARMOR);
+ float maxa = autocvar_g_balance_armor_rotstable;
+ float mina = autocvar_g_balance_armor_regenstable;
- regen_health_rotstable = regen_health_rotstable * max_mod;
- regen_health_stable = regen_health_stable * max_mod;
- limith = limith * limit_mod;
- limita = limita * limit_mod;
+ RotRegen(this, RES_ARMOR, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear,
+ regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
+ rot_mod * frametime * (time > this.pauserotarmor_finished), limit_mod);
- SetResource(this, RES_ARMOR, CalcRotRegen(GetResource(this, RES_ARMOR), mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear,
- regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
- rot_mod * frametime * (time > this.pauserotarmor_finished), limita));
- SetResource(this, RES_HEALTH, CalcRotRegen(GetResource(this, RES_HEALTH), regen_health_stable, regen_health, regen_health_linear,
- regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable, regen_health_rot, regen_health_rotlinear,
- rot_mod * frametime * (time > this.pauserothealth_finished), limith));
+ RotRegen(this, RES_HEALTH, regen_health_stable * max_mod, regen_health, regen_health_linear,
+ regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable * max_mod, regen_health_rot, regen_health_rotlinear,
+ rot_mod * frametime * (time > this.pauserothealth_finished), limit_mod);
}
// if player rotted to death... die!
this.event_damage(this, this, this, 1, DEATH_ROT.m_id, DMG_NOWEP, this.origin, '0 0 0');
}
- if (!(this.items & IT_UNLIMITED_WEAPON_AMMO))
+ if (!(this.items & IT_UNLIMITED_AMMO))
{
- float minf, maxf, limitf;
+ float maxf = autocvar_g_balance_fuel_rotstable;
+ float minf = autocvar_g_balance_fuel_regenstable;
- maxf = autocvar_g_balance_fuel_rotstable;
- minf = autocvar_g_balance_fuel_regenstable;
- limitf = GetResourceLimit(this, RES_FUEL);
-
- SetResource(this, RES_FUEL, CalcRotRegen(GetResource(this, RES_FUEL), minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear,
- frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
- maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), limitf));
+ RotRegen(this, RES_FUEL, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear,
+ frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
+ maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), 1);
}
}
this.items = spectatee.items;
STAT(LAST_PICKUP, this) = STAT(LAST_PICKUP, spectatee);
STAT(HIT_TIME, this) = STAT(HIT_TIME, spectatee);
- this.strength_finished = spectatee.strength_finished;
- this.invincible_finished = spectatee.invincible_finished;
- this.superweapons_finished = spectatee.superweapons_finished;
+ STAT(STRENGTH_FINISHED, this) = STAT(STRENGTH_FINISHED, spectatee);
+ STAT(INVINCIBLE_FINISHED, this) = STAT(INVINCIBLE_FINISHED, spectatee);
+ STAT(SUPERWEAPONS_FINISHED, this) = STAT(SUPERWEAPONS_FINISHED, spectatee);
+ STAT(AIR_FINISHED, this) = STAT(AIR_FINISHED, spectatee);
STAT(PRESSED_KEYS, this) = STAT(PRESSED_KEYS, spectatee);
STAT(WEAPONS, this) = STAT(WEAPONS, spectatee);
this.punchangle = spectatee.punchangle;
if (CS(this).spectatee_status != oldspectatee_status)
{
+ if (STAT(PRESSED_KEYS, this))
+ {
+ CS(this).pressedkeys = 0;
+ STAT(PRESSED_KEYS, this) = 0;
+ }
ClientData_Touch(this);
if (g_race || g_cts) race_InitSpectator();
}
switch (MUTATOR_CALLHOOK(SpectatePrev, this, ent, first))
{
case MUT_SPECPREV_FOUND:
- ent = M_ARGV(1, entity);
- break;
+ ent = M_ARGV(1, entity);
+ break;
case MUT_SPECPREV_RETURN:
- return true;
+ return true;
case MUT_SPECPREV_CONTINUE:
default:
{
int GetPlayerLimit()
{
+ if(g_duel)
+ return 2; // TODO: this workaround is needed since the mutator hook from duel can't be activated before the gametype is loaded (e.g. switching modes via gametype vote screen)
int player_limit = autocvar_g_maxplayers;
MUTATOR_CALLHOOK(GetPlayerLimit, player_limit);
player_limit = M_ARGV(0, int);
int player_limit = GetPlayerLimit();
- float free_slots = 0;
+ int free_slots = 0;
if (!player_limit)
free_slots = maxclients - totalClients;
- else if(currentlyPlaying < player_limit)
+ else if(player_limit > 0 && currentlyPlaying < player_limit)
free_slots = min(maxclients - totalClients, player_limit - currentlyPlaying);
- static float join_prevent_msg_time = 0;
- if(this && ignore && !free_slots && time > join_prevent_msg_time)
+ static float msg_time = 0;
+ if(this && !this.caplayer && ignore && !free_slots && time > msg_time)
{
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT);
- join_prevent_msg_time = time + 3;
+ msg_time = time + 0.5;
}
return free_slots;
if (autocvar_g_campaign) {
if ((IS_PLAYER(this) && PHYS_INPUT_BUTTON_INFO(this)) || (!IS_PLAYER(this))) {
CS(this).motd_actived_time = time;
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, campaign_message);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_CAMPAIGN_MESSAGE, Campaign_GetMessage(), Campaign_GetLevelNum());
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this)) {
CS(this).motd_actived_time = time;
else if ((time - CS(this).motd_actived_time > 2) && IS_PLAYER(this)) { // hide it some seconds after BUTTON_INFO has been released
CS(this).motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_CAMPAIGN_MESSAGE);
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this))
{
// instantly hide MOTD
CS(this).motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
+ if (autocvar_g_campaign)
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_CAMPAIGN_MESSAGE);
+ else
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
else if (IS_PLAYER(this) || IS_SPEC(this))
{
}
}
-const int MIN_SPEC_TIME = 1;
bool joinAllowed(entity this)
{
if (CS(this).version_mismatch) return false;
return true;
}
-.int items_added;
.string shootfromfixedorigin;
+.bool dualwielding_prev;
bool PlayerThink(entity this)
{
if (game_stopped || intermission_running) {
}
if (timeout_status == TIMEOUT_ACTIVE) {
- // don't allow the player to turn around while game is paused
+ // don't allow the player to turn around while game is paused
// FIXME turn this into CSQC stuff
this.v_angle = this.lastV_angle;
this.angles = this.lastV_angle;
stuffcmd(this, sprintf("\ncl_shootfromfixedorigin \"%s\"\n", autocvar_g_shootfromfixedorigin));
}
+ // reset gun alignment when dual wielding status changes
+ // to ensure guns are always aligned right and left
+ bool dualwielding = W_DualWielding(this);
+ if(this.dualwielding_prev != dualwielding)
+ {
+ W_ResetGunAlign(this, CS(this).cvar_cl_gunalign);
+ this.dualwielding_prev = dualwielding;
+ }
+
// LordHavoc: allow firing on move frames (sub-ticrate), this gives better timing on slow servers
//if(frametime)
{
- this.items &= ~this.items_added;
-
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
W_Vortex_Charge(this, weaponentity, frametime);
W_WeaponFrame(this, weaponentity);
}
-
- this.items_added = 0;
- if ((this.items & ITEM_Jetpack.m_itemid) && ((this.items & ITEM_JetpackRegen.m_itemid) || GetResource(this, RES_FUEL) >= 0.01))
- this.items_added |= IT_FUEL;
-
- this.items |= this.items_added;
}
- player_regen(this);
-
- // WEAPONTODO: Add a weapon request for this
- // rot vortex charge to the charge limit
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ if (frametime)
{
- .entity weaponentity = weaponentities[slot];
- if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time)
- this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
- }
-
- if (frametime) player_anim(this);
+ // WEAPONTODO: Add a weapon request for this
+ // rot vortex charge to the charge limit
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time)
+ this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+ }
- // secret status
- secrets_setstatus(this);
+ player_regen(this);
+ player_anim(this);
+ this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
+ }
- // monsters status
monsters_setstatus(this);
- this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
-
return true;
}
.bool would_spectate;
-void ObserverThink(entity this)
+void ObserverOrSpectatorThink(entity this)
{
+ bool is_spec = IS_SPEC(this);
if ( CS(this).impulse )
{
- MinigameImpulse(this, CS(this).impulse);
- CS(this).impulse = 0;
- }
-
- if (this.flags & FL_JUMPRELEASED) {
- if (PHYS_INPUT_BUTTON_JUMP(this) && joinAllowed(this)) {
- this.flags &= ~FL_JUMPRELEASED;
- this.flags |= FL_SPAWNING;
- } else if(PHYS_INPUT_BUTTON_ATCK(this) && !CS(this).version_mismatch || this.would_spectate) {
- this.flags &= ~FL_JUMPRELEASED;
- if(SpectateNext(this)) {
- TRANSMUTE(Spectator, this);
- }
- } else {
- int preferred_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? CS(this).cvar_cl_clippedspectating : !CS(this).cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
- set_movetype(this, preferred_movetype);
- }
- } else {
- if (!(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this))) {
- this.flags |= FL_JUMPRELEASED;
- if(this.flags & FL_SPAWNING)
- {
- this.flags &= ~FL_SPAWNING;
- Join(this);
- return;
- }
- }
- }
-}
-
-void SpectatorThink(entity this)
-{
- if ( CS(this).impulse )
- {
- if(MinigameImpulse(this, CS(this).impulse))
+ int r = MinigameImpulse(this, CS(this).impulse);
+ if (!is_spec || r)
CS(this).impulse = 0;
- if (CS(this).impulse == IMP_weapon_drop.impulse)
+ if (is_spec && CS(this).impulse == IMP_weapon_drop.impulse)
{
STAT(CAMERA_SPECTATOR, this) = (STAT(CAMERA_SPECTATOR, this) + 1) % 3;
CS(this).impulse = 0;
}
if (this.flags & FL_JUMPRELEASED) {
- if (PHYS_INPUT_BUTTON_JUMP(this) && joinAllowed(this)) {
+ if (PHYS_INPUT_BUTTON_JUMP(this) && (joinAllowed(this) || time < CS(this).jointime + MIN_SPEC_TIME)) {
this.flags &= ~FL_JUMPRELEASED;
this.flags |= FL_SPAWNING;
- } else if(PHYS_INPUT_BUTTON_ATCK(this) || CS(this).impulse == 10 || CS(this).impulse == 15 || CS(this).impulse == 18 || (CS(this).impulse >= 200 && CS(this).impulse <= 209)) {
+ } else if((is_spec && (PHYS_INPUT_BUTTON_ATCK(this) || CS(this).impulse == 10 || CS(this).impulse == 15 || CS(this).impulse == 18 || (CS(this).impulse >= 200 && CS(this).impulse <= 209)))
+ || (!is_spec && ((PHYS_INPUT_BUTTON_ATCK(this) && !CS(this).version_mismatch) || this.would_spectate))) {
this.flags &= ~FL_JUMPRELEASED;
if(SpectateNext(this)) {
TRANSMUTE(Spectator, this);
- } else {
+ } else if (is_spec) {
TRANSMUTE(Observer, this);
PutClientInServer(this);
}
- CS(this).impulse = 0;
- } else if(CS(this).impulse == 12 || CS(this).impulse == 16 || CS(this).impulse == 19 || (CS(this).impulse >= 220 && CS(this).impulse <= 229)) {
- this.flags &= ~FL_JUMPRELEASED;
- if(SpectatePrev(this)) {
- TRANSMUTE(Spectator, this);
- } else {
+ if (is_spec)
+ CS(this).impulse = 0;
+ } else if (is_spec) {
+ if(CS(this).impulse == 12 || CS(this).impulse == 16 || CS(this).impulse == 19 || (CS(this).impulse >= 220 && CS(this).impulse <= 229)) {
+ this.flags &= ~FL_JUMPRELEASED;
+ if(SpectatePrev(this)) {
+ TRANSMUTE(Spectator, this);
+ } else {
+ TRANSMUTE(Observer, this);
+ PutClientInServer(this);
+ }
+ CS(this).impulse = 0;
+ } else if(PHYS_INPUT_BUTTON_ATCK2(this)) {
+ this.would_spectate = false;
+ this.flags &= ~FL_JUMPRELEASED;
TRANSMUTE(Observer, this);
PutClientInServer(this);
- }
- CS(this).impulse = 0;
- } else if (PHYS_INPUT_BUTTON_ATCK2(this)) {
- this.would_spectate = false;
- this.flags &= ~FL_JUMPRELEASED;
- TRANSMUTE(Observer, this);
- PutClientInServer(this);
- } else {
- if(!SpectateUpdate(this))
- {
- if(!SpectateNext(this))
- {
- PutObserverInServer(this);
- this.would_spectate = true;
- }
+ } else if(!SpectateUpdate(this) && !SpectateNext(this)) {
+ PutObserverInServer(this);
+ this.would_spectate = true;
}
}
+ else {
+ int preferred_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? CS(this).cvar_cl_clippedspectating : !CS(this).cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
+ set_movetype(this, preferred_movetype);
+ }
} else {
- if (!(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))) {
+ if ((is_spec && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)))
+ || (!is_spec && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this)))) {
this.flags |= FL_JUMPRELEASED;
if(this.flags & FL_SPAWNING)
{
this.flags &= ~FL_SPAWNING;
- Join(this);
+ if(joinAllowed(this))
+ Join(this);
+ else if(time < CS(this).jointime + MIN_SPEC_TIME)
+ CS(this).autojoin_checked = -1;
return;
}
}
- if(!SpectateUpdate(this))
+ if(is_spec && !SpectateUpdate(this))
PutObserverInServer(this);
}
-
- this.flags |= FL_CLIENT | FL_NOTARGET;
+ if (is_spec)
+ this.flags |= FL_CLIENT | FL_NOTARGET;
}
void PlayerUseKey(entity this)
this.max_armorvalue = 0;
}
- if(IS_PLAYER(this))
+ if (frametime && IS_PLAYER(this))
{
if (STAT(FROZEN, this) == FROZEN_TEMP_REVIVING)
{
STAT(REVIVE_PROGRESS, this) = bound(0, STAT(REVIVE_PROGRESS, this) + frametime * this.revive_speed, 1);
SetResourceExplicit(this, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, this) * start_health));
- this.iceblock.alpha = bound(0.2, 1 - STAT(REVIVE_PROGRESS, this), 1);
+ if (this.iceblock)
+ this.iceblock.alpha = bound(0.2, 1 - STAT(REVIVE_PROGRESS, this), 1);
if (STAT(REVIVE_PROGRESS, this) >= 1)
Unfreeze(this, false);
IntermissionThink(this);
return;
}
- else if (IS_REAL_CLIENT(this) && !CS(this).autojoin_checked && time >= CS(this).jointime + MIN_SPEC_TIME)
+ else if (IS_REAL_CLIENT(this) && CS(this).autojoin_checked <= 0 && time >= CS(this).jointime + MIN_SPEC_TIME)
{
- CS(this).autojoin_checked = true;
+ bool early_join_requested = (CS(this).autojoin_checked < 0);
+ CS(this).autojoin_checked = 1;
// don't do this in ClientConnect
// many things can go wrong if a client is spawned as player on connection
- if (MUTATOR_CALLHOOK(AutoJoinOnConnection, this)
+ if (early_join_requested || MUTATOR_CALLHOOK(AutoJoinOnConnection, this)
|| (!(autocvar_sv_spectate || autocvar_g_campaign || (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR))
&& (!teamplay || autocvar_g_balance_teams)))
{
campaign_bots_may_start = true;
- Join(this);
+ if(joinAllowed(this))
+ Join(this);
return;
}
}
- else if (IS_OBSERVER(this)) {
- ObserverThink(this);
- }
- else if (IS_SPEC(this)) {
- SpectatorThink(this);
+ else if (IS_OBSERVER(this) || IS_SPEC(this)) {
+ ObserverOrSpectatorThink(this);
}
// WEAPONTODO: Add weapon request for this
wep_zoomed += thiswep.wr_zoom(thiswep, this);
}
SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed);
- }
+ }
if (CS(this).teamkill_soundtime && time > CS(this).teamkill_soundtime)
{
void DrownPlayer(entity this)
{
- if(IS_DEAD(this) || game_stopped || time < game_starttime)
+ if(IS_DEAD(this) || game_stopped || time < game_starttime || this.vehicle
+ || STAT(FROZEN, this) || this.watertype != CONTENT_WATER)
+ {
+ STAT(AIR_FINISHED, this) = 0;
return;
+ }
- if (this.waterlevel != WATERLEVEL_SUBMERGED || this.vehicle)
+ if (this.waterlevel != WATERLEVEL_SUBMERGED)
{
- if(this.air_finished < time)
+ if(STAT(AIR_FINISHED, this) && STAT(AIR_FINISHED, this) < time)
PlayerSound(this, playersound_gasp, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
- this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+ STAT(AIR_FINISHED, this) = 0;
}
- else if (this.air_finished < time)
- { // drown!
- if (this.pain_finished < time)
- {
- Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
- this.pain_finished = time + 0.5;
+ else
+ {
+ if (!STAT(AIR_FINISHED, this))
+ STAT(AIR_FINISHED, this) = time + autocvar_g_balance_contents_drowndelay;
+ if (STAT(AIR_FINISHED, this) < time)
+ { // drown!
+ if (this.pain_finished < time)
+ {
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ this.pain_finished = time + 0.5;
+ }
}
}
}
{
Player_Physics(this);
- if (sv_maxidle > 0)
+ if (autocvar_sv_maxidle > 0)
if (frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
if (IS_REAL_CLIENT(this))
- if (IS_PLAYER(this) || sv_maxidle_spectatorsareidle)
+ if (IS_PLAYER(this) || autocvar_sv_maxidle_spectatorsareidle)
{
int totalClients = 0;
- if(sv_maxidle_slots > 0)
+ if(autocvar_sv_maxidle_slots > 0)
{
- FOREACH_CLIENT(IS_REAL_CLIENT(it) || sv_maxidle_slots_countbots,
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_maxidle_slots_countbots,
{
++totalClients;
});
}
- if (sv_maxidle_slots > 0 && (maxclients - totalClients) > sv_maxidle_slots)
+ if (autocvar_sv_maxidle_slots > 0 && (maxclients - totalClients) > autocvar_sv_maxidle_slots)
{ /* do nothing */ }
else if (time - CS(this).parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
{
}
else
{
- float timeleft = ceil(sv_maxidle - (time - CS(this).parm_idlesince));
- if (timeleft == min(10, sv_maxidle - 1)) { // - 1 to support sv_maxidle <= 10
+ float timeleft = ceil(autocvar_sv_maxidle - (time - CS(this).parm_idlesince));
+ if (timeleft == min(10, autocvar_sv_maxidle - 1)) { // - 1 to support sv_maxidle <= 10
if (!CS(this).idlekick_lasttimeleft)
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
}
return;
}
else if (timeleft <= 10) {
- if (timeleft != CS(this).idlekick_lasttimeleft) {
- Send_Notification(NOTIF_ONE, this, MSG_ANNCE, Announcer_PickNumber(CNT_IDLE, timeleft));
- }
+ if (timeleft != CS(this).idlekick_lasttimeleft)
+ Send_Notification(NOTIF_ONE, this, MSG_ANNCE, Announcer_PickNumber(CNT_IDLE, timeleft));
CS(this).idlekick_lasttimeleft = timeleft;
}
}
this.solid = SOLID_NOT;
this.takedamage = DAMAGE_NO;
set_movetype(this, MOVETYPE_NONE);
+ CS(this).teamkill_complain = 0;
+ CS(this).teamkill_soundtime = 0;
+ CS(this).teamkill_soundsource = NULL;
}
if (IS_PLAYER(this)) {
}
GetPressedKeys(this);
}
+ else if (IS_OBSERVER(this) && STAT(PRESSED_KEYS, this))
+ {
+ CS(this).pressedkeys = 0;
+ STAT(PRESSED_KEYS, this) = 0;
+ }
if (this.waypointsprite_attachedforcarrier) {
float hp = healtharmor_maxdamage(GetResource(this, RES_HEALTH), GetResource(this, RES_ARMOR), autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id).x;
var .float flood_field = floodcontrol_chat;
if(floodcontrol && source)
{
- float flood_spl;
- float flood_burst;
- float flood_lmax;
- float lines;
+ float flood_spl, flood_burst, flood_lmax;
if(privatesay)
{
flood_spl = autocvar_g_chat_flood_spl_tell;
{
getWrappedLine_remaining = msgstr;
msgstr = "";
- lines = 0;
+ int lines = 0;
while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
{
msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
sourcecmsgstr = cmsgstr;
}
- if (!privatesay && source && !(IS_PLAYER(source) || source.caplayer))
+ if (!privatesay && source && !(IS_PLAYER(source) || source.caplayer) && !game_stopped
+ && (teamsay || CHAT_NOSPECTATORS()))
{
- if (!game_stopped)
- if (teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage))
- teamsay = -1; // spectators
+ teamsay = -1; // spectators
}
if(flood)
ret = 1;
}
- if (privatesay && source && !(IS_PLAYER(source) || source.caplayer))
+ if (privatesay && source && !(IS_PLAYER(source) || source.caplayer) && !game_stopped
+ && (IS_PLAYER(privatesay) || privatesay.caplayer) && CHAT_NOSPECTATORS())
{
- if (!game_stopped)
- if ((privatesay && (IS_PLAYER(privatesay) || privatesay.caplayer)) && ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage)))
- ret = -1; // just hide the message completely
+ ret = -1; // just hide the message completely
}
MUTATOR_CALLHOOK(ChatMessage, source, ret);
store.ping_movementloss = this.ping_movementloss;
store.v_angle = this.v_angle;
- store.movement = (typing) ? '0 0 0' : this.movement;
+ store.movement = this.movement;
}
NET_HANDLE(fpsreport, bool)