#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 FixPlayermodel(entity player);
void PutObserverInServer()
-{SELFPARAM();
+{
+ SELFPARAM();
+ PlayerState_detach(this);
entity spot;
self.hud = HUD_NORMAL;
setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // 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 = "";
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
if (IS_OBSERVER(this)) {
PutObserverInServer();
} else if (IS_PLAYER(this)) {
+ PlayerState_attach(this);
accuracy_resend(this);
if (this.team < 0)
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) {
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?
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);
else
WriteString(channel, "");
WriteByte(channel, self.count * 255.0); // g_balance_armor_blockpercent
- WriteCoord(channel, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO
- WriteCoord(channel, self.bouncestop); // g_balance_mortar_bouncestop
- WriteCoord(channel, self.ebouncefactor); // g_balance_mortar_bouncefactor
- WriteCoord(channel, self.ebouncestop); // g_balance_mortar_bouncestop
- WriteByte(channel, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO
- WriteByte(channel, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO
WriteByte(channel, serverflags); // client has to know if it should zoom or not
- WriteByte(channel, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO
- WriteByte(channel, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO
WriteCoord(channel, autocvar_g_trueaim_minrange);
- WriteByte(channel, WEP_CVAR(porto, secondary)); // WEAPONTODO
-
- MUTATOR_CALLHOOK(Ent_Init);
}
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()
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)
{
GameLogEcho(sprintf(":connect:%d:%d:%s",
self.playerid,
- num_for_edict(self),
+ etof(self),
((IS_REAL_CLIENT(self)) ? self.netaddress : "bot")
));
}
*/
void DecodeLevelParms ();
void ClientConnect ()
-{SELFPARAM();
+{
+ SELFPARAM();
+ ClientState_attach(this);
float t;
if(IS_CLIENT(self))
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(self)) { PlayerStats_PlayerBasic_CheckUpdate(self); }
PlayerScore_Attach(self);
ClientData_Attach();
PlayerStats_GameReport_AddPlayer(self);
if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(num_for_edict(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname));
+ GameLogEcho(strcat(":join:", ftos(self.playerid), ":", ftos(etof(self)), ":", ((IS_REAL_CLIENT(self)) ? self.netaddress : "bot"), ":", self.netname));
LogTeamchange(self.playerid, self.team, 1);
else
stuffcmd(self, "set _teams_available 0\n");
- attach_entcs(self);
+ entcs_attach(self);
bot_relinkplayerlist();
Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
- if(autocvar_g_bugrigs || (g_weaponarena_weapons == WEPSET(TUBA)))
+ if(g_weaponarena_weapons == WEPSET(TUBA))
stuffcmd(self, "cl_cmd settemp chase_active 1\n");
}
self.model_randomizer = random();
if(IS_REAL_CLIENT(self))
- sv_notice_join();
+ sv_notice_join(self);
for (entity e = world; (e = findfloat(e, init_for_player_needed, 1)); ) {
WITH(entity, self, e, e.init_for_player(this));
.entity chatbubbleentity;
void ReadyCount();
void ClientDisconnect ()
-{SELFPARAM();
+{
+ 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)));
{
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, 1, DEATH_ROT.m_id, self.origin, '0 0 0');
}
if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
======================
*/
-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;
return false;
}
- SpectateCopy(self.enemy);
+ SpectateCopy(this, this.enemy);
return true;
}
{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)
{
* 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;
}
/**
{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) {
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();
}
// WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY
// It cannot be predicted by the engine!
.entity weaponentity = weaponentities[0]; // TODO: unhardcode
- if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && self.(weaponentity).wframe == WFRAME_FIRE2 && time < self.(weaponentity).weapon_nextthink)
+ 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));
}
}
}
// 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(this.deadflag != DEAD_NO)
+ 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
//CheckPlayerJump();
if(IS_PLAYER(self)) {
+ DrownPlayer(self);
CheckRules_Player();
UpdateChatBubble();
if (self.impulse)
- ImpulseCommands();
+ ImpulseCommands(self);
if (intermission_running)
return; // intermission or finale
GetPressedKeys();