#include "anticheat.qh"
#include "cl_impulse.qh"
#include "cl_player.qh"
-#include "ent_cs.qh"
#include "ipban.qh"
#include "miscfunctions.qh"
#include "portals.qh"
#include "bot/bot.qh"
#include "bot/navigation.qh"
-#include "../common/vehicles/all.qh"
+#include "../common/ent_cs.qh"
+#include "../common/state.qh"
+
#include "../common/triggers/teleporters.qh"
+#include "../common/vehicles/all.qh"
+
#include "weapons/hitplot.qh"
#include "weapons/weaponsystem.qh"
#include "../common/net_notice.qh"
-#include "../common/physics.qh"
+#include "../common/physics/player.qh"
#include "../common/items/all.qc"
void send_CSQC_teamnagger() {
- WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
+ WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
bool ClientData_Send(entity this, entity to, int sf)
{
- if(to != self.owner)
- {
- error("wtf");
- return false;
- }
-
- entity e;
+ assert(to == this.owner, return false);
- e = to;
- if(IS_SPEC(to))
- e = to.enemy;
+ entity e = to;
+ if (IS_SPEC(e)) e = e.enemy;
sf = 0;
+ if (e.race_completed) sf |= 1; // forced scoreboard
+ if (to.spectatee_status) sf |= 2; // spectator ent number follows
+ if (e.zoomstate) sf |= 4; // zoomed
+ if (e.porto_v_angle_held) sf |= 8; // angles held
- if(e.race_completed)
- sf |= 1; // forced scoreboard
- if(to.spectatee_status)
- sf |= 2; // spectator ent number follows
- if(e.zoomstate)
- sf |= 4; // zoomed
- if(e.porto_v_angle_held)
- sf |= 8; // angles held
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
WriteByte(MSG_ENTITY, sf);
- if(sf & 2)
+ if (sf & 2)
+ {
WriteByte(MSG_ENTITY, to.spectatee_status);
-
- if(sf & 8)
+ }
+ if (sf & 8)
{
WriteAngle(MSG_ENTITY, e.v_angle.x);
WriteAngle(MSG_ENTITY, e.v_angle.y);
}
-
return true;
}
-void ClientData_Attach()
-{SELFPARAM();
- Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send);
- self.clientdata.drawonlytoclient = self;
- self.clientdata.owner = self;
+void ClientData_Attach(entity this)
+{
+ Net_LinkEntity(this.clientdata = new(clientdata), false, 0, ClientData_Send);
+ make_pure(this.clientdata);
+ self.clientdata.drawonlytoclient = this;
+ self.clientdata.owner = this;
}
-void ClientData_Detach()
-{SELFPARAM();
- remove(self.clientdata);
- self.clientdata = world;
+void ClientData_Detach(entity this)
+{
+ remove(this.clientdata);
+ self.clientdata = NULL;
}
void ClientData_Touch(entity e)
e.clientdata.SendFlags = 1;
// make it spectatable
- entity e2;
- FOR_EACH_REALCLIENT(e2)
- {
- if(e2 != e)
- if(IS_SPEC(e2))
- if(e2.enemy == e)
- e2.clientdata.SendFlags = 1;
- }
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != e && IS_SPEC(it) && it.enemy == e, LAMBDA(it.clientdata.SendFlags = 1));
}
.string netname_previous;
precache_model(modelname);
_setmodel(e, modelname);
player_setupanimsformodel();
- UpdatePlayerSounds();
}
/*
*/
void FixPlayermodel(entity player);
void PutObserverInServer()
-{SELFPARAM();
+{
+ SELFPARAM();
+ PlayerState_detach(this);
entity spot;
self.hud = HUD_NORMAL;
if(self.vehicle)
vehicles_exit(VHEF_RELEASE);
- WaypointSprite_PlayerDead();
+ WaypointSprite_PlayerDead(self);
if(!mutator_returnvalue) // mutator prevents resetting teams
self.team = -1; // move this as it is needed to log the player spectating in eventlog
self.crouch = false;
self.revival_time = 0;
- setorigin (self, (spot.origin + PL_VIEW_OFS)); // offset it so that the spectator spawns higher off the ground, looks better this way
+ setorigin (self, (spot.origin + STAT(PL_VIEW_OFS, NULL))); // offset it so that the spectator spawns higher off the ground, looks better this way
self.prevorigin = self.origin;
self.items = 0;
self.weapons = '0 0 0';
setmodel(self, MDL_Null);
self.drawonlytoclient = self;
- setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
+ setsize (self, STAT(PL_CROUCH_MIN, NULL), STAT(PL_CROUCH_MAX, NULL)); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
self.view_ofs = '0 0 0'; // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
- self.weapon = 0;
+ PS(self).m_weapon = WEP_Null;
self.weaponname = "";
- self.switchingweapon = 0;
+ PS(self).m_switchingweapon = WEP_Null;
self.weaponmodel = "";
- self.weaponentity = world;
+ for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ self.weaponentities[slot] = NULL;
+ }
self.exteriorweaponentity = world;
self.killcount = FRAGS_SPECTATOR;
self.velocity = '0 0 0';
self.event_damage = func_null;
}
+int player_getspecies(entity this)
+{
+ get_model_parameters(this.model, this.skin);
+ int s = get_model_parameters_species;
+ get_model_parameters(string_null, 0);
+ if (s < 0) return SPECIES_HUMAN;
+ return s;
+}
+
.float model_randomizer;
void FixPlayermodel(entity player)
{
if(chmdl || oldskin != player.skin) // model or skin has changed
{
- player.species = player_getspecies(); // update species
- UpdatePlayerSounds(); // update skin sounds
+ player.species = player_getspecies(player); // update species
}
if(!teamplay)
if (IS_OBSERVER(this)) {
PutObserverInServer();
} else if (IS_PLAYER(this)) {
+ PlayerState_attach(this);
accuracy_resend(this);
if (this.team < 0)
this.revival_time = 0;
this.air_finished = time + 12;
- entity spawnevent = spawn();
+ entity spawnevent = new(spawnevent);
+ make_pure(spawnevent);
spawnevent.owner = this;
Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
this.drawonlytoclient = NULL;
this.crouch = false;
- this.view_ofs = PL_VIEW_OFS;
- setsize(this, PL_MIN, PL_MAX);
+ this.view_ofs = STAT(PL_VIEW_OFS, NULL);
+ setsize(this, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL));
this.spawnorigin = spot.origin;
setorigin(this, spot.origin + '0 0 1' * (1 - this.mins.z - 24));
// don't reset back to last position, even if new position is stuck in solid
this.bot_attack = true;
this.monster_attack = true;
- this.spider_slowness = 0;
-
this.BUTTON_ATCK = this.BUTTON_JUMP = this.BUTTON_ATCK2 = false;
if (this.killcount == FRAGS_SPECTATOR) {
this.killcount = 0;
}
- CL_SpawnWeaponentity(this);
+ for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ CL_SpawnWeaponentity(this, weaponentities[slot]);
+ }
this.alpha = default_player_alpha;
this.colormod = '1 1 1' * autocvar_g_player_brightness;
this.exteriorweaponentity.alpha = default_weapon_alpha;
remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
}
- this.switchweapon = w_getbestweapon(this);
+ PS(this).m_switchweapon = w_getbestweapon(this);
this.cnt = -1; // W_LastWeapon will not complain
- this.weapon = 0;
+ PS(this).m_weapon = WEP_Null;
this.weaponname = "";
- this.switchingweapon = 0;
+ PS(this).m_switchingweapon = WEP_Null;
if (!warmup_stage && !this.alivetime)
this.alivetime = time;
}
}
+void ClientInit_misc();
+
.float ebouncefactor, ebouncestop; // electro's values
// TODO do we need all these fields, or should we stop autodetecting runtime
// changes and just have a console command to update this?
bool ClientInit_SendEntity(entity this, entity to, int sf)
{
- WriteByte(MSG_ENTITY, ENT_CLIENT_INIT);
- WriteByte(MSG_ENTITY, g_nexball_meter_period * 32);
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[0]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[1]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[2]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[3]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[0]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[1]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[2]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[3]));
+ WriteHeader(MSG_ENTITY, _ENT_CLIENT_INIT);
+ return = true;
+ msg_entity = to;
+ // MSG_INIT replacement
+ // TODO: make easier to use
+ Registry_send_all();
+ W_PROP_reload(MSG_ONE, to);
+ ClientInit_misc();
+ MUTATOR_CALLHOOK(Ent_Init);
+}
+void ClientInit_misc()
+{
+ int channel = MSG_ONE;
+ WriteHeader(channel, ENT_CLIENT_INIT);
+ WriteByte(channel, g_nexball_meter_period * 32);
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[0]));
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[1]));
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[2]));
+ WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[3]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[0]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[1]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[2]));
+ WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[3]));
if(sv_foginterval && world.fog != "")
- WriteString(MSG_ENTITY, world.fog);
+ WriteString(channel, world.fog);
else
- WriteString(MSG_ENTITY, "");
- WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent
- WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO
- WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_mortar_bouncestop
- WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_mortar_bouncefactor
- WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_mortar_bouncestop
- WriteByte(MSG_ENTITY, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO
- WriteByte(MSG_ENTITY, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO
- WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
- WriteByte(MSG_ENTITY, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO
- WriteByte(MSG_ENTITY, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO
- WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
- WriteByte(MSG_ENTITY, WEP_CVAR(porto, secondary)); // WEAPONTODO
- return true;
+ WriteString(channel, "");
+ WriteByte(channel, self.count * 255.0); // g_balance_armor_blockpercent
+ WriteByte(channel, serverflags); // client has to know if it should zoom or not
+ WriteCoord(channel, autocvar_g_trueaim_minrange);
}
void ClientInit_CheckUpdate()
self.count = autocvar_g_balance_armor_blockpercent;
self.SendFlags |= 1;
}
- if(self.bouncefactor != autocvar_g_balance_mortar_bouncefactor) // WEAPONTODO
- {
- self.bouncefactor = autocvar_g_balance_mortar_bouncefactor;
- self.SendFlags |= 1;
- }
- if(self.bouncestop != autocvar_g_balance_mortar_bouncestop)
- {
- self.bouncestop = autocvar_g_balance_mortar_bouncestop;
- self.SendFlags |= 1;
- }
- if(self.ebouncefactor != autocvar_g_balance_electro_secondary_bouncefactor)
- {
- self.ebouncefactor = autocvar_g_balance_electro_secondary_bouncefactor;
- self.SendFlags |= 1;
- }
- if(self.ebouncestop != autocvar_g_balance_electro_secondary_bouncestop)
- {
- self.ebouncestop = autocvar_g_balance_electro_secondary_bouncestop;
- self.SendFlags |= 1;
- }
}
void ClientInit_Spawn()
{SELFPARAM();
- entity e = spawn();
- e.classname = "clientinit";
+
+ entity e = new(clientinit);
+ make_pure(e);
e.think = ClientInit_CheckUpdate;
Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
SetNewParms
=============
*/
-void SetNewParms (void)
+void SetNewParms ()
{
// initialize parms for a new player
parm1 = -(86400 * 366);
SetChangeParms
=============
*/
-void SetChangeParms (void)
+void SetChangeParms ()
{SELFPARAM();
// save parms for level change
parm1 = self.parm_idlesince - time;
DecodeLevelParms
=============
*/
-void DecodeLevelParms (void)
-{SELFPARAM();
+void DecodeLevelParms(entity this)
+{
// load parms
- self.parm_idlesince = parm1;
- if(self.parm_idlesince == -(86400 * 366))
- self.parm_idlesince = time;
+ this.parm_idlesince = parm1;
+ if (this.parm_idlesince == -(86400 * 366))
+ this.parm_idlesince = time;
// whatever happens, allow 60 seconds of idling directly after connect for map loading
- self.parm_idlesince = max(self.parm_idlesince, time - sv_maxidle + 60);
+ this.parm_idlesince = max(this.parm_idlesince, time - sv_maxidle + 60);
MUTATOR_CALLHOOK(DecodeLevelParms);
}
*/
.float clientkill_nexttime;
-void ClientKill_Now_TeamChange()
-{SELFPARAM();
- if(self.killindicator_teamchange == -1)
+void ClientKill_Now_TeamChange(entity this)
+{
+ if(this.killindicator_teamchange == -1)
{
- JoinBestTeam( self, false, true );
+ JoinBestTeam( this, false, true );
}
- else if(self.killindicator_teamchange == -2)
+ else if(this.killindicator_teamchange == -2)
{
if(blockSpectators)
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
- PutObserverInServer();
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
+ WITH(entity, self, this, PutObserverInServer());
}
else
- SV_ChangeTeam(self.killindicator_teamchange - 1);
- self.killindicator_teamchange = 0;
+ WITH(entity, self, this, SV_ChangeTeam(this.killindicator_teamchange - 1));
+ this.killindicator_teamchange = 0;
}
void ClientKill_Now()
self.killindicator = world;
if(self.killindicator_teamchange)
- ClientKill_Now_TeamChange();
+ ClientKill_Now_TeamChange(self);
if(IS_PLAYER(self))
Damage(self, self, self, 100000, DEATH_KILL.m_id, self.origin, '0 0 0');
if(!self.killindicator)
{
- if(self.deadflag == DEAD_NO)
+ if(!IS_DEAD(self))
{
killtime = max(killtime, self.clientkill_nexttime - time);
self.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
}
- if(killtime <= 0 || !IS_PLAYER(self) || self.deadflag != DEAD_NO)
+ if(killtime <= 0 || !IS_PLAYER(self) || IS_DEAD(self))
{
ClientKill_Now();
}
}
-void ClientKill (void)
+void ClientKill ()
{SELFPARAM();
if(gameover) return;
if(self.player_blocked) return;
- if(self.frozen) return;
+ if(STAT(FROZEN, self)) return;
ClientKill_TeamChange(0);
}
stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
if(autocvar_sv_gentle)
stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
+
+ MUTATOR_CALLHOOK(FixClientCvars, e);
}
float PlayerInIDList(entity p, string idlist)
Called once (not at each match start) when a client begins a connection to the server
=============
*/
-void ClientPreConnect (void)
+void ClientPreConnect ()
{SELFPARAM();
if(autocvar_sv_eventlog)
{
GameLogEcho(sprintf(":connect:%d:%d:%s",
self.playerid,
- num_for_edict(self),
+ etof(self),
((IS_REAL_CLIENT(self)) ? self.netaddress : "bot")
));
}
}
#endif
-/*
+/**
=============
ClientConnect
Called when a client connects to the server
=============
*/
-void DecodeLevelParms (void);
-void ClientConnect (void)
-{SELFPARAM();
- float t;
-
- if(IS_CLIENT(self))
- {
- LOG_INFO("Warning: ClientConnect, but already connected!\n");
- return;
- }
-
- if(Ban_MaybeEnforceBanOnce(self))
- return;
-
- DecodeLevelParms();
+void ClientConnect()
+{
+ SELFPARAM();
+ if (Ban_MaybeEnforceBanOnce(this)) return;
+ assert(!IS_CLIENT(this), return);
+ assert(player_count >= 0, player_count = 0);
+ this.classname = "player_joining";
+ this.flags = FL_CLIENT;
#ifdef WATERMARK
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_WATERMARK, WATERMARK);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_WATERMARK, WATERMARK);
#endif
+ this.version_nagtime = time + 10 + random() * 10;
- self.classname = "player_joining";
-
- self.flags = FL_CLIENT;
- self.version_nagtime = time + 10 + random() * 10;
-
- if(player_count<0)
- {
- LOG_TRACE("BUG player count is lower than zero, this cannot happen!\n");
- player_count = 0;
- }
-
- if(IS_REAL_CLIENT(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); }
+ // TODO: xonstat elo.txt support, until then just 404s
+ if (false && IS_REAL_CLIENT(this)) { PlayerStats_PlayerBasic_CheckUpdate(this); }
- PlayerScore_Attach(self);
- ClientData_Attach();
- accuracy_init(self);
- Inventory_new(self);
+ ClientState_attach(this);
+ // TODO: fold all of these into ClientState
+ DecodeLevelParms(this);
+ PlayerScore_Attach(this);
+ ClientData_Attach(this);
+ accuracy_init(this);
+ Inventory_new(this);
+ playerdemo_init(this);
+ anticheat_init(this);
+ entcs_attach(this);
+ W_HitPlotOpen(this);
- bot_clientconnect();
-
- playerdemo_init();
-
- anticheat_init();
+ bot_clientconnect(this);
// identify the right forced team
- if(autocvar_g_campaign)
+ if (autocvar_g_campaign)
{
- if(IS_REAL_CLIENT(self)) // only players, not bots
+ if (IS_REAL_CLIENT(this)) // only players, not bots
{
- switch(autocvar_g_campaign_forceteam)
+ switch (autocvar_g_campaign_forceteam)
{
- case 1: self.team_forced = NUM_TEAM_1; break;
- case 2: self.team_forced = NUM_TEAM_2; break;
- case 3: self.team_forced = NUM_TEAM_3; break;
- case 4: self.team_forced = NUM_TEAM_4; break;
- default: self.team_forced = 0;
+ case 1: this.team_forced = NUM_TEAM_1; break;
+ case 2: this.team_forced = NUM_TEAM_2; break;
+ case 3: this.team_forced = NUM_TEAM_3; break;
+ case 4: this.team_forced = NUM_TEAM_4; break;
+ default: this.team_forced = 0;
}
}
}
- else if(PlayerInIDList(self, autocvar_g_forced_team_red))
- self.team_forced = NUM_TEAM_1;
- else if(PlayerInIDList(self, autocvar_g_forced_team_blue))
- self.team_forced = NUM_TEAM_2;
- else if(PlayerInIDList(self, autocvar_g_forced_team_yellow))
- self.team_forced = NUM_TEAM_3;
- else if(PlayerInIDList(self, autocvar_g_forced_team_pink))
- self.team_forced = NUM_TEAM_4;
- else if(autocvar_g_forced_team_otherwise == "red")
- self.team_forced = NUM_TEAM_1;
- else if(autocvar_g_forced_team_otherwise == "blue")
- self.team_forced = NUM_TEAM_2;
- else if(autocvar_g_forced_team_otherwise == "yellow")
- self.team_forced = NUM_TEAM_3;
- else if(autocvar_g_forced_team_otherwise == "pink")
- self.team_forced = NUM_TEAM_4;
- else if(autocvar_g_forced_team_otherwise == "spectate")
- self.team_forced = -1;
- else if(autocvar_g_forced_team_otherwise == "spectator")
- self.team_forced = -1;
- else
- self.team_forced = 0;
-
- if(!teamplay)
- if(self.team_forced > 0)
- self.team_forced = 0;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_red)) this.team_forced = NUM_TEAM_1;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_blue)) this.team_forced = NUM_TEAM_2;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_yellow)) this.team_forced = NUM_TEAM_3;
+ else if (PlayerInIDList(this, autocvar_g_forced_team_pink)) this.team_forced = NUM_TEAM_4;
+ else switch (autocvar_g_forced_team_otherwise)
+ {
+ default: this.team_forced = 0; break;
+ case "red": this.team_forced = NUM_TEAM_1; break;
+ case "blue": this.team_forced = NUM_TEAM_2; break;
+ case "yellow": this.team_forced = NUM_TEAM_3; break;
+ case "pink": this.team_forced = NUM_TEAM_4; break;
+ case "spectate":
+ case "spectator":
+ this.team_forced = -1;
+ break;
+ }
+ if (!teamplay && this.team_forced > 0) this.team_forced = 0;
- JoinBestTeam(self, false, false); // if the team number is valid, keep it
+ JoinBestTeam(this, false, false); // if the team number is valid, keep it
- if((autocvar_sv_spectate == 1) || autocvar_g_campaign || self.team_forced < 0) {
- self.classname = STR_OBSERVER;
+ if (autocvar_sv_spectate || autocvar_g_campaign || this.team_forced < 0) {
+ this.classname = STR_OBSERVER;
} else {
- if(teamplay)
+ if (!teamplay || autocvar_g_balance_teams)
{
- if(autocvar_g_balance_teams)
- {
- self.classname = STR_PLAYER;
- campaign_bots_may_start = 1;
- }
- else
- {
- self.classname = STR_OBSERVER; // do it anyway
- }
+ this.classname = STR_PLAYER;
+ campaign_bots_may_start = 1;
}
else
{
- self.classname = STR_PLAYER;
- campaign_bots_may_start = 1;
+ this.classname = STR_OBSERVER; // do it anyway
}
}
- self.playerid = (playerid_last = playerid_last + 1);
-
- PlayerStats_GameReport_AddEvent(sprintf("kills-%d", self.playerid));
+ this.playerid = ++playerid_last;
- if(IS_BOT_CLIENT(self))
- PlayerStats_GameReport_AddPlayer(self);
+ PlayerStats_GameReport_AddEvent(sprintf("kills-%d", this.playerid));
- if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname));
+ // always track bots, don't ask for cl_allow_uidtracking
+ if (IS_BOT_CLIENT(this)) PlayerStats_GameReport_AddPlayer(this);
- LogTeamchange(self.playerid, self.team, 1);
+ if (autocvar_sv_eventlog)
+ GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", this.netname));
- self.just_joined = true; // stop spamming the eventlog with additional lines when the client connects
+ LogTeamchange(this.playerid, this.team, 1);
- self.netname_previous = strzone(self.netname);
+ this.just_joined = true; // stop spamming the eventlog with additional lines when the client connects
- if(IS_PLAYER(self) && teamplay)
- Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(self, INFO_JOIN_CONNECT_TEAM_), self.netname);
- else
- Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_CONNECT, self.netname);
+ this.netname_previous = strzone(this.netname);
- stuffcmd(self, strcat(clientstuff, "\n"));
- stuffcmd(self, "cl_particles_reloadeffects\n"); // TODO do we still need this?
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && IS_PLAYER(this)) ? APP_TEAM_ENT_4(this, INFO_JOIN_CONNECT_TEAM_) : INFO_JOIN_CONNECT), this.netname);
- FixClientCvars(self);
+ stuffcmd(this, clientstuff, "\n");
+ stuffcmd(this, "cl_particles_reloadeffects\n"); // TODO do we still need this?
- // spawnfunc_waypoint sprites
- WaypointSprite_InitClient(self);
+ FixClientCvars(this);
- // Wazat's grappling hook
- SetGrappleHookBindings();
+ // Grappling hook
+ stuffcmd(this, "alias +hook +button6\n");
+ stuffcmd(this, "alias -hook -button6\n");
// Jetpack binds
- stuffcmd(self, "alias +jetpack +button10\n");
- stuffcmd(self, "alias -jetpack -button10\n");
+ stuffcmd(this, "alias +jetpack +button10\n");
+ stuffcmd(this, "alias -jetpack -button10\n");
// get version info from player
- stuffcmd(self, "cmd clientversion $gameversion\n");
+ stuffcmd(this, "cmd clientversion $gameversion\n");
// get other cvars from player
GetCvars(0);
// notify about available teams
- if(teamplay)
+ if (teamplay)
{
- CheckAllowedTeams(self);
- t = 0; if(c1 >= 0) t |= 1; if(c2 >= 0) t |= 2; if(c3 >= 0) t |= 4; if(c4 >= 0) t |= 8;
- stuffcmd(self, strcat("set _teams_available ", ftos(t), "\n"));
+ CheckAllowedTeams(this);
+ int t = 0;
+ if (c1 >= 0) t |= BIT(0);
+ if (c2 >= 0) t |= BIT(1);
+ if (c3 >= 0) t |= BIT(2);
+ if (c4 >= 0) t |= BIT(3);
+ stuffcmd(this, sprintf("set _teams_available %d\n", t));
}
else
- stuffcmd(self, "set _teams_available 0\n");
-
- attach_entcs(self);
+ {
+ stuffcmd(this, "set _teams_available 0\n");
+ }
bot_relinkplayerlist();
- self.spectatortime = time;
- if(blockSpectators)
+ this.spectatortime = time;
+ if (blockSpectators)
{
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
}
- self.jointime = time;
- self.allowed_timeouts = autocvar_sv_timeout_number;
+ this.jointime = time;
+ this.allowed_timeouts = autocvar_sv_timeout_number;
- if(IS_REAL_CLIENT(self))
+ if (IS_REAL_CLIENT(this))
{
- if(!autocvar_g_campaign)
+ if (!autocvar_g_campaign)
{
- self.motd_actived_time = -1;
- Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
+ this.motd_actived_time = -1;
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
- if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
- stuffcmd(self, "cl_cmd settemp chase_active 1\n");
+ if (g_weaponarena_weapons == WEPSET(TUBA))
+ stuffcmd(this, "cl_cmd settemp chase_active 1\n");
}
- if(!sv_foginterval && world.fog != "")
- stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
-
- W_HitPlotOpen(self);
-
- if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
- send_CSQC_teamnagger();
+ if (!sv_foginterval && world.fog != "")
+ stuffcmd(this, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
- CheatInitClient();
+ if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)))
+ if (!g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
+ send_CSQC_teamnagger();
- CSQCMODEL_AUTOINIT(self);
+ CSQCMODEL_AUTOINIT(this);
- self.model_randomizer = random();
+ this.model_randomizer = random();
- if(IS_REAL_CLIENT(self))
- sv_notice_join();
+ if (IS_REAL_CLIENT(this))
+ sv_notice_join(this);
- for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
- WITH(entity, self, e, e.init_for_player(this));
- }
+ FOREACH_ENTITY_FLOAT(init_for_player_needed, true, {
+ WITH(entity, self, it, it.init_for_player(it));
+ });
- MUTATOR_CALLHOOK(ClientConnect, self);
+ MUTATOR_CALLHOOK(ClientConnect, this);
}
/*
=============
*/
.entity chatbubbleentity;
void ReadyCount();
-void ClientDisconnect (void)
-{SELFPARAM();
+void ClientDisconnect ()
+{
+ SELFPARAM();
+ ClientState_detach(this);
if(self.vehicle)
vehicles_exit(VHEF_RELEASE);
bot_clientdisconnect();
- detach_entcs(self);
+ entcs_detach(self);
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":part:", ftos(self.playerid)));
accuracy_free(self);
Inventory_delete(self);
- ClientData_Detach();
+ ClientData_Detach(this);
PlayerScore_Detach(self);
if(self.netname_previous)
if(self.weaponorder_byimpulse)
strunzone(self.weaponorder_byimpulse);
- ClearPlayerSounds();
-
if(self.personal)
remove(self.personal);
self.mdl = "";
- if ( !self.owner.deadflag && IS_PLAYER(self.owner) )
+ if ( !IS_DEAD(self.owner) && IS_PLAYER(self.owner) )
{
if ( self.owner.active_minigame )
self.mdl = "models/sprites/minigame_busy.iqm";
// spawn a chatbubble entity if needed
if (!self.chatbubbleentity)
{
- self.chatbubbleentity = spawn();
+ self.chatbubbleentity = new(chatbubbleentity);
self.chatbubbleentity.owner = self;
self.chatbubbleentity.exteriormodeltoclient = self;
self.chatbubbleentity.think = ChatBubbleThink;
else self.colormod = '1 1 1';
}*/
-void respawn(void)
+void respawn()
{SELFPARAM();
if(self.alpha >= 0 && autocvar_g_respawn_ghosts)
{
SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
}
- CopyBody(1);
+ CopyBody(self, 1);
self.effects |= EF_NODRAW; // prevent another CopyBody
PutClientInServer();
_sound (self, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
}
-void player_powerups (void)
+void player_powerups ()
{SELFPARAM();
// add a way to see what the items were BEFORE all of these checks for the mutator hook
int items_prev = self.items;
- if((self.items & IT_USING_JETPACK) && !self.deadflag && !gameover)
+ if((self.items & IT_USING_JETPACK) && !IS_DEAD(self) && !gameover)
self.modelflags |= MF_ROCKET;
else
self.modelflags &= ~MF_ROCKET;
self.effects &= ~(EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
- if((self.alpha < 0 || self.deadflag) && !self.vehicle) // don't apply the flags if the player is gibbed
+ if((self.alpha < 0 || IS_DEAD(self)) && !self.vehicle) // don't apply the flags if the player is gibbed
return;
Fire_ApplyDamage(self);
return current;
}
-void player_regen (void)
+void player_regen ()
{SELFPARAM();
float max_mod, regen_mod, rot_mod, limit_mod;
max_mod = regen_mod = rot_mod = limit_mod = 1;
regen_health_stable = autocvar_g_balance_health_regenstable;
regen_health_rotstable = autocvar_g_balance_health_rotstable;
if(!MUTATOR_CALLHOOK(PlayerRegen))
- if(!self.frozen)
+ if(!STAT(FROZEN, self))
{
float mina, maxa, limith, limita;
maxa = autocvar_g_balance_armor_rotstable;
{
if(self.vehicle)
vehicles_exit(VHEF_RELEASE);
- self.event_damage(self, self, 1, DEATH_ROT.m_id, self.origin, '0 0 0');
+ if(self.event_damage)
+ self.event_damage(self, self, self, 1, DEATH_ROT.m_id, self.origin, '0 0 0');
}
if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
}
void GetPressedKeys()
-{SELFPARAM();
+{
+ SELFPARAM();
MUTATOR_CALLHOOK(GetPressedKeys);
- #define X(var,bit,flag) (flag ? var |= bit : var &= ~bit)
- X(self.pressedkeys, KEY_FORWARD, self.movement_x > 0);
- X(self.pressedkeys, KEY_BACKWARD, self.movement_x < 0);
- X(self.pressedkeys, KEY_RIGHT, self.movement_y > 0);
- X(self.pressedkeys, KEY_LEFT, self.movement_y < 0);
-
- X(self.pressedkeys, KEY_JUMP, PHYS_INPUT_BUTTON_JUMP(self));
- X(self.pressedkeys, KEY_CROUCH, PHYS_INPUT_BUTTON_CROUCH(self));
- X(self.pressedkeys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(self));
- X(self.pressedkeys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(self));
- #undef X
+ int keys = this.pressedkeys;
+ keys = BITSET(keys, KEY_FORWARD, this.movement.x > 0);
+ keys = BITSET(keys, KEY_BACKWARD, this.movement.x < 0);
+ keys = BITSET(keys, KEY_RIGHT, this.movement.y > 0);
+ keys = BITSET(keys, KEY_LEFT, this.movement.y < 0);
+
+ keys = BITSET(keys, KEY_JUMP, PHYS_INPUT_BUTTON_JUMP(this));
+ keys = BITSET(keys, KEY_CROUCH, PHYS_INPUT_BUTTON_CROUCH(this));
+ keys = BITSET(keys, KEY_ATCK, PHYS_INPUT_BUTTON_ATCK(this));
+ keys = BITSET(keys, KEY_ATCK2, PHYS_INPUT_BUTTON_ATCK2(this));
+ this.pressedkeys = keys;
}
/*
======================
*/
-void SpectateCopy(entity spectatee)
-{SELFPARAM();
+void SpectateCopy(entity this, entity spectatee)
+{
MUTATOR_CALLHOOK(SpectateCopy, spectatee, self);
self.armortype = spectatee.armortype;
self.armorvalue = spectatee.armorvalue;
self.invincible_finished = spectatee.invincible_finished;
self.pressedkeys = spectatee.pressedkeys;
self.weapons = spectatee.weapons;
- self.switchweapon = spectatee.switchweapon;
- self.switchingweapon = spectatee.switchingweapon;
- self.weapon = spectatee.weapon;
+ PS(self).m_switchweapon = PS(spectatee).m_switchweapon;
+ PS(self).m_switchingweapon = PS(spectatee).m_switchingweapon;
+ PS(self).m_weapon = PS(spectatee).m_weapon;
self.vortex_charge = spectatee.vortex_charge;
self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
self.hagar_load = spectatee.hagar_load;
self.dmg_inflictor = spectatee.dmg_inflictor;
self.v_angle = spectatee.v_angle;
self.angles = spectatee.v_angle;
- self.frozen = spectatee.frozen;
+ STAT(FROZEN, self) = STAT(FROZEN, spectatee);
self.revive_progress = spectatee.revive_progress;
if(!self.BUTTON_USE)
self.fixangle = true;
return false;
}
- SpectateCopy(self.enemy);
+ SpectateCopy(this, this.enemy);
return true;
}
bool SpectateNext()
{SELFPARAM();
- other = find(self.enemy, classname, "player");
-
- bool mutator_returnvalue = MUTATOR_CALLHOOK(SpectateNext, self, other);
- other = spec_player;
+ other = find(self.enemy, classname, STR_PLAYER);
- if(!mutator_returnvalue && !other)
- other = find(other, classname, "player");
+ if (MUTATOR_CALLHOOK(SpectateNext, self, other))
+ other = spec_player;
+ else if (!other)
+ other = find(other, classname, STR_PLAYER);
if(other) { SetSpectatee(self, other); }
bool SpectatePrev()
{SELFPARAM();
// NOTE: chain order is from the highest to the lower entnum (unlike find)
- other = findchain(classname, "player");
+ other = findchain(classname, STR_PLAYER);
if (!other) // no player
return false;
while(other && other != self.enemy)
other = other.chain;
- int mutator_returnvalue = MUTATOR_CALLHOOK(SpectatePrev, self, other, first);
- other = spec_player;
-
- switch(mutator_returnvalue)
+ switch (MUTATOR_CALLHOOK(SpectatePrev, self, other, first))
{
- case MUT_SPECPREV_FOUND: break;
- case MUT_SPECPREV_RETURN: return true;
+ case MUT_SPECPREV_FOUND:
+ other = spec_player;
+ break;
+ case MUT_SPECPREV_RETURN:
+ other = spec_player;
+ return true;
case MUT_SPECPREV_CONTINUE:
default:
{
void ShowRespawnCountdown()
{SELFPARAM();
float number;
- if(self.deadflag == DEAD_NO) // just respawned?
+ if(!IS_DEAD(self)) // just respawned?
return;
else
{
{SELFPARAM();
if(self.caplayer)
return;
- if(nJoinAllowed(self))
+ if(nJoinAllowed(self, self))
{
if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0)
{
self.classname = STR_PLAYER;
- nades_RemoveBonus(self);
if(autocvar_g_campaign || autocvar_g_balance_teams)
{ JoinBestTeam(self, false, true); }
PutClientInServer();
- if(IS_PLAYER(self)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_PLAY, self.netname); }
+ if(IS_PLAYER(self)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, ((teamplay) ? APP_TEAM_ENT_4(this, INFO_JOIN_PLAY_TEAM_) : INFO_JOIN_PLAY), self.netname); }
}
else
stuffcmd(self, "menu_showteamselect\n");
* it checks whether the number of currently playing players exceeds g_maxplayers.
* @return int number of free slots for players, 0 if none
*/
-float nJoinAllowed(entity ignore)
-{SELFPARAM();
+bool nJoinAllowed(entity this, entity ignore)
+{
if(!ignore)
// this is called that way when checking if anyone may be able to join (to build qcstatus)
// so report 0 free slots if restricted
{
if(autocvar_g_forced_team_otherwise == "spectate")
- return 0;
+ return false;
if(autocvar_g_forced_team_otherwise == "spectator")
- return 0;
+ return false;
}
- if(self.team_forced < 0)
- return 0; // forced spectators can never join
+ if(this.team_forced < 0)
+ return false; // forced spectators can never join
// TODO simplify this
- entity e;
- float totalClients = 0;
- FOR_EACH_CLIENT(e)
- if(e != ignore)
- totalClients += 1;
+ int totalClients = 0;
+ int currentlyPlaying = 0;
+ FOREACH_CLIENT(true, LAMBDA(
+ if(it != ignore)
+ ++totalClients;
+ if(IS_REAL_CLIENT(it))
+ if(IS_PLAYER(it) || it.caplayer)
+ ++currentlyPlaying;
+ ));
if (!autocvar_g_maxplayers)
return maxclients - totalClients;
- float currentlyPlaying = 0;
- FOR_EACH_REALCLIENT(e)
- if(IS_PLAYER(e) || e.caplayer)
- currentlyPlaying += 1;
-
if(currentlyPlaying < autocvar_g_maxplayers)
return min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
- return 0;
+ return false;
}
/**
{
if(self.BUTTON_INFO) // BUTTON_INFO hides initial MOTD
self.motd_actived_time = -2; // wait until BUTTON_INFO gets released
- else if(self.motd_actived_time == -2 || IS_PLAYER(self))
+ else if(self.motd_actived_time == -2 || IS_PLAYER(self) || IS_SPEC(self))
{
// instanctly hide MOTD
self.motd_actived_time = 0;
{SELFPARAM();
if ( self.impulse )
{
- MinigameImpulse(self.impulse);
+ MinigameImpulse(self, self.impulse);
self.impulse = 0;
}
float prefered_movetype;
{SELFPARAM();
if ( self.impulse )
{
- if(MinigameImpulse(self.impulse))
+ if(MinigameImpulse(self, self.impulse))
self.impulse = 0;
}
if (self.flags & FL_JUMPRELEASED) {
}
else if(autocvar_g_vehicles_enter)
{
- if(!self.frozen)
- if(self.deadflag == DEAD_NO)
+ if(!STAT(FROZEN, self))
+ if(!IS_DEAD(self))
if(!gameover)
{
entity head, closest_target = world;
- head = WarpZone_FindRadius(self.origin, autocvar_g_vehicles_enter_radius, TRUE);
+ head = WarpZone_FindRadius(self.origin, autocvar_g_vehicles_enter_radius, true);
while(head) // find the closest acceptable target to enter
{
if(head.vehicle_flags & VHF_ISVEHICLE)
- if(head.deadflag == DEAD_NO)
+ if(!IS_DEAD(head))
if(!head.owner || ((head.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(head.owner, self)))
if(head.takedamage != DAMAGE_NO)
{
MUTATOR_CALLHOOK(PlayerUseKey);
}
-float isInvisibleString(string s)
-{
- float i, n, c;
- s = strdecolorize(s);
- for((i = 0), (n = strlen(s)); i < n; ++i)
- {
- c = str2chr(s, i);
- switch(c)
- {
- case 0:
- case 32: // space
- break;
- case 192: // charmap space
- if (!autocvar_utf8_enable)
- break;
- return false;
- case 160: // space in unicode fonts
- case 0xE000 + 192: // utf8 charmap space
- if (autocvar_utf8_enable)
- break;
- default:
- return false;
- }
- }
- return true;
-}
/*
=============
void() nexball_setstatus;
.float last_vehiclecheck;
.int items_added;
-void PlayerPreThink (void)
+void PlayerPreThink ()
{SELFPARAM();
WarpZone_PlayerPhysics_FixVAngle();
self.max_armorvalue = 0;
}
- if(self.frozen == 2)
+ if(STAT(FROZEN, self) == 2)
{
self.revive_progress = bound(0, self.revive_progress + frametime * self.revive_speed, 1);
self.health = max(1, self.revive_progress * start_health);
if(self.revive_progress >= 1)
Unfreeze(self);
}
- else if(self.frozen == 3)
+ else if(STAT(FROZEN, self) == 3)
{
self.revive_progress = bound(0, self.revive_progress - frametime * self.revive_speed, 1);
self.health = max(0, autocvar_g_nades_ice_health + (start_health-autocvar_g_nades_ice_health) * self.revive_progress );
{
if(self.vehicle)
vehicles_exit(VHEF_RELEASE);
- self.event_damage(self, self.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, self.origin, '0 0 0');
+ self.event_damage(self, self, self.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, self.origin, '0 0 0');
}
else if ( self.revive_progress <= 0 )
Unfreeze(self);
if(time > self.last_vehiclecheck)
if(IS_PLAYER(self))
if(!gameover)
- if(!self.frozen)
+ if(!STAT(FROZEN, self))
if(!self.vehicle)
- if(self.deadflag == DEAD_NO)
+ if(!IS_DEAD(self))
{
entity veh;
for(veh = world; (veh = findflags(veh, vehicle_flags, VHF_ISVEHICLE)); )
if(vlen(veh.origin - self.origin) < autocvar_g_vehicles_enter_radius)
- if(veh.deadflag == DEAD_NO)
+ if(!IS_DEAD(veh))
if(veh.takedamage != DAMAGE_NO)
if((veh.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(veh.owner, self))
Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_VEHICLE_ENTER_GUNNER);
if(frametime)
{
- if(self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge))
- {
- self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-
- if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
- {
- self.weaponentity_glowmod_x = self.weaponentity_glowmod.x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_y = self.weaponentity_glowmod.y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- self.weaponentity_glowmod_z = self.weaponentity_glowmod.z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
- }
- }
- else
- self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, true) * 2;
-
player_powerups();
}
- if (self.deadflag != DEAD_NO)
+ if (IS_DEAD(self))
{
if(self.personal && g_race_qualifying)
{
do_crouch = 0;
if(self.vehicle)
do_crouch = 0;
- if(self.frozen)
+ if(STAT(FROZEN, self))
do_crouch = 0;
// WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY
// It cannot be predicted by the engine!
- if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
+ .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+ if((PS(self).m_weapon == WEP_SHOCKWAVE || PS(self).m_weapon == WEP_SHOTGUN) && self.(weaponentity).wframe == WFRAME_FIRE2 && time < self.(weaponentity).weapon_nextthink)
do_crouch = 0;
if (do_crouch)
if (!self.crouch)
{
self.crouch = true;
- self.view_ofs = self.stat_pl_crouch_view_ofs;
- setsize (self, self.stat_pl_crouch_min, self.stat_pl_crouch_max);
+ self.view_ofs = STAT(PL_CROUCH_VIEW_OFS, self);
+ setsize (self, STAT(PL_CROUCH_MIN, self), STAT(PL_CROUCH_MAX, self));
// setanim(self, self.anim_duck, false, true, true); // this anim is BROKEN anyway
}
}
{
if (self.crouch)
{
- tracebox(self.origin, self.stat_pl_min, self.stat_pl_max, self.origin, false, self);
+ tracebox(self.origin, STAT(PL_MIN, self), STAT(PL_MAX, self), self.origin, false, self);
if (!trace_startsolid)
{
self.crouch = false;
- self.view_ofs = self.stat_pl_view_ofs;
- setsize (self, self.stat_pl_min, self.stat_pl_max);
+ self.view_ofs = STAT(PL_VIEW_OFS, self);
+ setsize (self, STAT(PL_MIN, self), STAT(PL_MAX, self));
}
}
}
secrets_setstatus();
// monsters status
- monsters_setstatus();
+ monsters_setstatus(self);
self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
// WEAPONTODO: Add weapon request for this
if(!zoomstate_set)
- SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX.m_id) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE.m_id && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO
+ SetZoomState(
+ self.BUTTON_ZOOM
+ || self.BUTTON_ZOOMSCRIPT
+ || (self.BUTTON_ATCK2 && PS(self).m_weapon == WEP_VORTEX)
+ || (self.BUTTON_ATCK2 && PS(self).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
+ ); // WEAPONTODO
float oldspectatee_status;
oldspectatee_status = self.spectatee_status;
if(IS_SPEC(self))
- self.spectatee_status = num_for_edict(self.enemy);
+ self.spectatee_status = etof(self.enemy);
else if(IS_OBSERVER(self))
- self.spectatee_status = num_for_edict(self);
+ self.spectatee_status = etof(self);
else
self.spectatee_status = 0;
if(self.spectatee_status != oldspectatee_status)
{
ClientData_Touch(self);
+ if(g_race || g_cts)
+ race_InitSpectator();
}
if(self.teamkill_soundtime)
{
self.teamkill_soundtime = 0;
- setself(self.teamkill_soundsource);
- entity oldpusher = self.pusher;
- self.pusher = this;
-
- PlayerSound(playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
-
- self.pusher = oldpusher;
- setself(this);
+ entity e = self.teamkill_soundsource;
+ entity oldpusher = e.pusher;
+ e.pusher = this;
+ PlayerSound(e, playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
+ e.pusher = oldpusher;
}
if(self.taunt_soundtime)
if(time > self.taunt_soundtime)
{
self.taunt_soundtime = 0;
- PlayerSound(playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
+ PlayerSound(self, playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
}
target_voicescript_next(self);
// WEAPONTODO: Move into weaponsystem somehow
// if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
- if(!self.weapon)
+ if (PS(self).m_weapon == WEP_Null)
self.clip_load = self.clip_size = 0;
}
+void DrownPlayer(entity this)
+{
+ if(IS_DEAD(this))
+ return;
+
+ if (this.waterlevel != WATERLEVEL_SUBMERGED)
+ {
+ if(this.air_finished < time)
+ PlayerSound(this, playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ this.air_finished = time + autocvar_g_balance_contents_drowndelay;
+ this.dmg = 2;
+ }
+ else if (this.air_finished < time)
+ { // drown!
+ if (this.pain_finished < time)
+ {
+ Damage (this, world, world, autocvar_g_balance_contents_playerdamage_drowning * autocvar_g_balance_contents_damagerate, DEATH_DROWN.m_id, this.origin, '0 0 0');
+ this.pain_finished = time + 0.5;
+ }
+ }
+}
+
/*
=============
PlayerPostThink
=============
*/
.float idlekick_lasttimeleft;
-void PlayerPostThink (void)
+void PlayerPostThink ()
{SELFPARAM();
if(sv_maxidle > 0 && frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
if(IS_REAL_CLIENT(self))
//CheckPlayerJump();
if(IS_PLAYER(self)) {
+ DrownPlayer(self);
CheckRules_Player();
UpdateChatBubble();
if (self.impulse)
- ImpulseCommands();
+ ImpulseCommands(self);
if (intermission_running)
return; // intermission or finale
GetPressedKeys();