FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != e && IS_SPEC(it) && it.enemy == e, LAMBDA(it.clientdata.SendFlags = 1));
}
-.string netname_previous;
-
void SetSpectatee(entity this, entity spectatee);
void SetSpectatee_status(entity this, int spectatee_num);
if (this.killcount != FRAGS_SPECTATOR)
{
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, this.netname);
- if(!gameover)
+ 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);
accuracy_resend(this);
- this.spectatortime = time;
+ CS(this).spectatortime = time;
if(this.bot_attack)
IL_REMOVE(g_bot_targets, this);
this.bot_attack = false;
this.items = 0;
this.weapons = '0 0 0';
+ this.dual_weapons = '0 0 0';
this.drawonlytoclient = this;
this.weaponmodel = "";
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- if(!this.weaponentities[slot])
- continue; // first load
- this.weaponentities[slot].hook_time = 0;
- this.weaponentities[slot].weaponname = "";
this.weaponentities[slot] = NULL;
}
this.exteriorweaponentity = NULL;
this.oldvelocity = this.velocity;
this.fire_endtime = -1;
this.event_damage = func_null;
+
+ for(int slot = 0; slot < MAX_AXH; ++slot)
+ {
+ entity axh = this.(AuxiliaryXhair[slot]);
+ this.(AuxiliaryXhair[slot]) = NULL;
+
+ if(axh.owner == this && axh != NULL && !wasfreed(axh))
+ delete(axh);
+ }
}
int player_getspecies(entity this)
{
if(teamplay)
{
- string s = Static_Team_ColorName_Lower(player.team);
- if (s != "neutral")
+ switch(player.team)
{
- defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s));
- defaultskin = cvar(strcat("sv_defaultplayerskin_", s));
+ case NUM_TEAM_1: defaultmodel = autocvar_sv_defaultplayermodel_red; defaultskin = autocvar_sv_defaultplayerskin_red; break;
+ case NUM_TEAM_2: defaultmodel = autocvar_sv_defaultplayermodel_blue; defaultskin = autocvar_sv_defaultplayerskin_blue; break;
+ case NUM_TEAM_3: defaultmodel = autocvar_sv_defaultplayermodel_yellow; defaultskin = autocvar_sv_defaultplayerskin_yellow; break;
+ case NUM_TEAM_4: defaultmodel = autocvar_sv_defaultplayermodel_pink; defaultskin = autocvar_sv_defaultplayerskin_pink; break;
}
}
{
if(teamplay)
{
- string s = Static_Team_ColorName_Lower(player.team);
- if (s != "neutral")
- defaultskin = cvar(strcat("sv_defaultplayerskin_", s));
+ switch(player.team)
+ {
+ case NUM_TEAM_1: defaultskin = autocvar_sv_defaultplayerskin_red; break;
+ case NUM_TEAM_2: defaultskin = autocvar_sv_defaultplayerskin_blue; break;
+ case NUM_TEAM_3: defaultskin = autocvar_sv_defaultplayerskin_yellow; break;
+ case NUM_TEAM_4: defaultskin = autocvar_sv_defaultplayerskin_pink; break;
+ }
}
if(!defaultskin)
setcolor(player, stof(autocvar_sv_defaultplayercolors));
}
-
-/** Called when a client spawns in the server */
-void PutClientInServer(entity this)
+void PutPlayerInServer(entity this)
{
- if (IS_BOT_CLIENT(this)) {
- TRANSMUTE(Player, this);
- } else if (IS_REAL_CLIENT(this)) {
- msg_entity = this;
- WriteByte(MSG_ONE, SVC_SETVIEW);
- WriteEntity(MSG_ONE, this);
- }
- if (gameover) {
- TRANSMUTE(Observer, this);
+ if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
+
+ PlayerState_attach(this);
+ accuracy_resend(this);
+
+ if (this.team < 0)
+ JoinBestTeam(this, false, true);
+
+ entity spot = SelectSpawnPoint(this, false);
+ if (!spot) {
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
+ return; // spawn failed
}
- SetSpectatee(this, NULL);
+ TRANSMUTE(Player, this);
- // reset player keys
- this.itemkeys = 0;
+ this.wasplayer = true;
+ this.iscreature = true;
+ this.teleportable = TELEPORT_NORMAL;
+ if(!this.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, this);
+ this.damagedbycontents = true;
+ set_movetype(this, MOVETYPE_WALK);
+ this.solid = SOLID_SLIDEBOX;
+ this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
+ if (autocvar_g_playerclip_collisions)
+ this.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
+ if (IS_BOT_CLIENT(this) && autocvar_g_botclip_collisions)
+ this.dphitcontentsmask |= DPCONTENTS_BOTCLIP;
+ this.frags = FRAGS_PLAYER;
+ if (INDEPENDENT_PLAYERS) MAKE_INDEPENDENT_PLAYER(this);
+ this.flags = FL_CLIENT | FL_PICKUPITEMS;
+ if (autocvar__notarget)
+ this.flags |= FL_NOTARGET;
+ this.takedamage = DAMAGE_AIM;
+ this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
+ this.dmg = 2; // WTF
+
+ if (warmup_stage) {
+ this.ammo_shells = warmup_start_ammo_shells;
+ this.ammo_nails = warmup_start_ammo_nails;
+ this.ammo_rockets = warmup_start_ammo_rockets;
+ this.ammo_cells = warmup_start_ammo_cells;
+ this.ammo_plasma = warmup_start_ammo_plasma;
+ this.ammo_fuel = warmup_start_ammo_fuel;
+ this.health = warmup_start_health;
+ this.armorvalue = warmup_start_armorvalue;
+ this.weapons = WARMUP_START_WEAPONS;
+ } else {
+ this.ammo_shells = start_ammo_shells;
+ this.ammo_nails = start_ammo_nails;
+ this.ammo_rockets = start_ammo_rockets;
+ this.ammo_cells = start_ammo_cells;
+ this.ammo_plasma = start_ammo_plasma;
+ this.ammo_fuel = start_ammo_fuel;
+ this.health = start_health;
+ this.armorvalue = start_armorvalue;
+ this.weapons = start_weapons;
+ }
+ SetSpectatee_status(this, 0);
+
+ this.dual_weapons = '0 0 0';
+
+ this.superweapons_finished = (this.weapons & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
+
+ this.items = start_items;
+
+ this.spawnshieldtime = time + autocvar_g_spawnshieldtime;
+ this.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn;
+ this.pauserothealth_finished = time + autocvar_g_balance_pause_health_rot_spawn;
+ this.pauserotfuel_finished = time + autocvar_g_balance_pause_fuel_rot_spawn;
+ this.pauseregen_finished = time + autocvar_g_balance_pause_health_regen_spawn;
+ // extend the pause of rotting if client was reset at the beginning of the countdown
+ if (!autocvar_sv_ready_restart_after_countdown && time < game_starttime) { // TODO why is this cvar NOTted?
+ float f = game_starttime - time;
+ this.spawnshieldtime += f;
+ this.pauserotarmor_finished += f;
+ this.pauserothealth_finished += f;
+ this.pauseregen_finished += f;
+ }
+ this.damageforcescale = 2;
+ this.death_time = 0;
+ this.respawn_flags = 0;
+ this.respawn_time = 0;
+ this.stat_respawn_time = 0;
+ this.scale = 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.nextthink = 0;
+ this.dmg_team = 0;
+ this.ballistics_density = autocvar_g_ballistics_density_player;
- MUTATOR_CALLHOOK(PutClientInServer, this);
+ this.deadflag = DEAD_NO;
- if (IS_OBSERVER(this)) {
- PutObserverInServer(this);
- } else if (IS_PLAYER(this)) {
- if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
+ this.angles = spot.angles;
+ this.angles_z = 0; // never spawn tilted even if the spot says to
+ if (IS_BOT_CLIENT(this))
+ this.v_angle = this.angles;
+ this.fixangle = true; // turn this way immediately
+ this.oldvelocity = this.velocity = '0 0 0';
+ this.avelocity = '0 0 0';
+ this.punchangle = '0 0 0';
+ this.punchvector = '0 0 0';
- PlayerState_attach(this);
- accuracy_resend(this);
+ this.strength_finished = 0;
+ this.invincible_finished = 0;
+ this.fire_endtime = -1;
+ this.revive_progress = 0;
+ this.revival_time = 0;
+ this.air_finished = time + 12;
- if (this.team < 0)
- JoinBestTeam(this, false, true);
+ entity spawnevent = new_pure(spawnevent);
+ spawnevent.owner = this;
+ Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
- entity spot = SelectSpawnPoint(this, false);
- if (!spot) {
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
- return; // spawn failed
- }
+ // Cut off any still running player sounds.
+ stopsound(this, CH_PLAYER_SINGLE);
- TRANSMUTE(Player, this);
+ this.model = "";
+ FixPlayermodel(this);
+ this.drawonlytoclient = NULL;
- this.wasplayer = true;
- this.iscreature = true;
- this.teleportable = TELEPORT_NORMAL;
- if(!this.damagedbycontents)
- IL_PUSH(g_damagedbycontents, this);
- this.damagedbycontents = true;
- set_movetype(this, MOVETYPE_WALK);
- this.solid = SOLID_SLIDEBOX;
- this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
- if (autocvar_g_playerclip_collisions)
- this.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
- if (IS_BOT_CLIENT(this) && autocvar_g_botclip_collisions)
- this.dphitcontentsmask |= DPCONTENTS_BOTCLIP;
- this.frags = FRAGS_PLAYER;
- if (INDEPENDENT_PLAYERS) MAKE_INDEPENDENT_PLAYER(this);
- this.flags = FL_CLIENT | FL_PICKUPITEMS;
- if (autocvar__notarget)
- this.flags |= FL_NOTARGET;
- this.takedamage = DAMAGE_AIM;
- this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
- this.dmg = 2; // WTF
-
- if (warmup_stage) {
- this.ammo_shells = warmup_start_ammo_shells;
- this.ammo_nails = warmup_start_ammo_nails;
- this.ammo_rockets = warmup_start_ammo_rockets;
- this.ammo_cells = warmup_start_ammo_cells;
- this.ammo_plasma = warmup_start_ammo_plasma;
- this.ammo_fuel = warmup_start_ammo_fuel;
- this.health = warmup_start_health;
- this.armorvalue = warmup_start_armorvalue;
- this.weapons = WARMUP_START_WEAPONS;
- } else {
- this.ammo_shells = start_ammo_shells;
- this.ammo_nails = start_ammo_nails;
- this.ammo_rockets = start_ammo_rockets;
- this.ammo_cells = start_ammo_cells;
- this.ammo_plasma = start_ammo_plasma;
- this.ammo_fuel = start_ammo_fuel;
- this.health = start_health;
- this.armorvalue = start_armorvalue;
- this.weapons = start_weapons;
- }
- SetSpectatee_status(this, 0);
-
- this.superweapons_finished = (this.weapons & WEPSET_SUPERWEAPONS) ? time + autocvar_g_balance_superweapons_time : 0;
-
- this.items = start_items;
-
- this.spawnshieldtime = time + autocvar_g_spawnshieldtime;
- this.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn;
- this.pauserothealth_finished = time + autocvar_g_balance_pause_health_rot_spawn;
- this.pauserotfuel_finished = time + autocvar_g_balance_pause_fuel_rot_spawn;
- this.pauseregen_finished = time + autocvar_g_balance_pause_health_regen_spawn;
- // extend the pause of rotting if client was reset at the beginning of the countdown
- if (!autocvar_sv_ready_restart_after_countdown && time < game_starttime) { // TODO why is this cvar NOTted?
- float f = game_starttime - time;
- this.spawnshieldtime += f;
- this.pauserotarmor_finished += f;
- this.pauserothealth_finished += f;
- this.pauseregen_finished += f;
- }
- this.damageforcescale = 2;
- this.death_time = 0;
- this.respawn_flags = 0;
- this.respawn_time = 0;
- this.stat_respawn_time = 0;
- this.scale = 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.nextthink = 0;
- this.dmg_team = 0;
- this.ballistics_density = autocvar_g_ballistics_density_player;
-
- this.deadflag = DEAD_NO;
-
- this.angles = spot.angles;
- this.angles_z = 0; // never spawn tilted even if the spot says to
- if (IS_BOT_CLIENT(this))
- this.v_angle = this.angles;
- this.fixangle = true; // turn this way immediately
- this.oldvelocity = this.velocity = '0 0 0';
- this.avelocity = '0 0 0';
- this.punchangle = '0 0 0';
- this.punchvector = '0 0 0';
-
- this.strength_finished = 0;
- this.invincible_finished = 0;
- this.fire_endtime = -1;
- this.revive_progress = 0;
- this.revival_time = 0;
- this.air_finished = time + 12;
-
- entity spawnevent = new_pure(spawnevent);
- spawnevent.owner = this;
- Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
-
- // Cut off any still running player sounds.
- stopsound(this, CH_PLAYER_SINGLE);
-
- this.model = "";
- FixPlayermodel(this);
- this.drawonlytoclient = NULL;
-
- this.viewloc = NULL;
-
- this.crouch = false;
- this.view_ofs = STAT(PL_VIEW_OFS, this);
- setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
- 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.oldorigin = this.origin;
- this.prevorigin = this.origin;
- this.lastteleporttime = time; // prevent insane speeds due to changing origin
- if(this.conveyor)
- IL_REMOVE(g_conveyed, this);
- this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
- this.hud = HUD_NORMAL;
-
- this.event_damage = PlayerDamage;
-
- if(!this.bot_attack)
- IL_PUSH(g_bot_targets, this);
- this.bot_attack = true;
- this.monster_attack = true;
-
- PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_JUMP(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false;
-
- if (this.killcount == FRAGS_SPECTATOR) {
- PlayerScore_Clear(this);
- this.killcount = 0;
- }
+ this.viewloc = NULL;
- for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- CL_SpawnWeaponentity(this, weaponentity);
- }
- this.alpha = default_player_alpha;
- this.colormod = '1 1 1' * autocvar_g_player_brightness;
- this.exteriorweaponentity.alpha = default_weapon_alpha;
+ this.crouch = false;
+ this.view_ofs = STAT(PL_VIEW_OFS, this);
+ setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
+ 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.oldorigin = this.origin;
+ this.prevorigin = this.origin;
+ this.lastteleporttime = time; // prevent insane speeds due to changing origin
+ if(this.conveyor)
+ IL_REMOVE(g_conveyed, this);
+ this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
+ this.hud = HUD_NORMAL;
+
+ this.event_damage = PlayerDamage;
+
+ if(!this.bot_attack)
+ IL_PUSH(g_bot_targets, this);
+ this.bot_attack = true;
+ if(!this.monster_attack)
+ IL_PUSH(g_monster_targets, this);
+ this.monster_attack = true;
+ navigation_dynamicgoal_init(this, false);
+
+ PHYS_INPUT_BUTTON_ATCK(this) = PHYS_INPUT_BUTTON_JUMP(this) = PHYS_INPUT_BUTTON_ATCK2(this) = false;
+
+ if (this.killcount == FRAGS_SPECTATOR) {
+ PlayerScore_Clear(this);
+ this.killcount = 0;
+ }
+
+ 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;
+ this.exteriorweaponentity.alpha = default_weapon_alpha;
- this.speedrunning = false;
+ this.speedrunning = false;
- target_voicescript_clear(this);
+ target_voicescript_clear(this);
- // reset fields the weapons may use
- FOREACH(Weapons, true, LAMBDA(
- it.wr_resetplayer(it, this);
+ // reset fields the weapons may use
+ FOREACH(Weapons, true, LAMBDA(
+ it.wr_resetplayer(it, this);
// reload all reloadable weapons
- if (it.spawnflags & WEP_FLAG_RELOADABLE) {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo;
- }
+ if (it.spawnflags & WEP_FLAG_RELOADABLE) {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo;
}
- ));
-
- {
- string s = spot.target;
- spot.target = string_null;
- SUB_UseTargets(spot, this, NULL);
- spot.target = s;
}
+ ));
- Unfreeze(this);
+ {
+ string s = spot.target;
+ spot.target = string_null;
+ SUB_UseTargets(spot, this, NULL);
+ spot.target = s;
+ }
- MUTATOR_CALLHOOK(PlayerSpawn, this, spot);
+ Unfreeze(this);
- if (autocvar_spawn_debug)
- {
- sprint(this, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
- delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
- }
+ MUTATOR_CALLHOOK(PlayerSpawn, this, spot);
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(slot == 0)
- this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
- else
- this.(weaponentity).m_switchweapon = WEP_Null;
- this.(weaponentity).m_weapon = WEP_Null;
- this.(weaponentity).weaponname = "";
- this.(weaponentity).m_switchingweapon = WEP_Null;
- this.(weaponentity).cnt = -1;
- }
+ if (autocvar_spawn_debug)
+ {
+ sprint(this, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
+ delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
+ }
+
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(slot == 0 || autocvar_g_weaponswitch_debug == 1)
+ this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+ else
+ this.(weaponentity).m_switchweapon = WEP_Null;
+ this.(weaponentity).m_weapon = WEP_Null;
+ this.(weaponentity).weaponname = "";
+ this.(weaponentity).m_switchingweapon = WEP_Null;
+ this.(weaponentity).cnt = -1;
+ }
+
+ MUTATOR_CALLHOOK(PlayerWeaponSelect, this);
+
+ if (!warmup_stage && !this.alivetime)
+ this.alivetime = time;
+
+ antilag_clear(this, CS(this));
+}
+
+/** Called when a client spawns in the server */
+void PutClientInServer(entity this)
+{
+ if (IS_BOT_CLIENT(this)) {
+ TRANSMUTE(Player, this);
+ } else if (IS_REAL_CLIENT(this)) {
+ msg_entity = this;
+ WriteByte(MSG_ONE, SVC_SETVIEW);
+ WriteEntity(MSG_ONE, this);
+ }
+ if (game_stopped)
+ TRANSMUTE(Observer, this);
- if (!warmup_stage && !this.alivetime)
- this.alivetime = time;
+ SetSpectatee(this, NULL);
+
+ // reset player keys
+ this.itemkeys = 0;
+
+ MUTATOR_CALLHOOK(PutClientInServer, this);
- antilag_clear(this, CS(this));
+ if (IS_OBSERVER(this)) {
+ PutObserverInServer(this);
+ } else if (IS_PLAYER(this)) {
+ PutPlayerInServer(this);
}
}
void SetChangeParms (entity this)
{
// save parms for level change
- parm1 = this.parm_idlesince - time;
+ parm1 = CS(this).parm_idlesince - time;
MUTATOR_CALLHOOK(SetChangeParms);
}
void DecodeLevelParms(entity this)
{
// load parms
- this.parm_idlesince = parm1;
- if (this.parm_idlesince == -(86400 * 366))
- this.parm_idlesince = time;
+ CS(this).parm_idlesince = parm1;
+ if (CS(this).parm_idlesince == -(86400 * 366))
+ CS(this).parm_idlesince = time;
// whatever happens, allow 60 seconds of idling directly after connect for map loading
- this.parm_idlesince = max(this.parm_idlesince, time - sv_maxidle + 60);
+ CS(this).parm_idlesince = max(CS(this).parm_idlesince, time - sv_maxidle + 60);
MUTATOR_CALLHOOK(DecodeLevelParms);
}
.float clientkill_nexttime;
void ClientKill_Now_TeamChange(entity this)
{
- if(this.killindicator_teamchange == -1)
+ if(CS(this).killindicator_teamchange == -1)
{
JoinBestTeam( this, false, true );
}
- else if(this.killindicator_teamchange == -2)
+ else if(CS(this).killindicator_teamchange == -2)
{
if(blockSpectators)
Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
PutObserverInServer(this);
}
else
- SV_ChangeTeam(this, this.killindicator_teamchange - 1);
- this.killindicator_teamchange = 0;
+ SV_ChangeTeam(this, CS(this).killindicator_teamchange - 1);
+ CS(this).killindicator_teamchange = 0;
}
void ClientKill_Now(entity this)
if(this.vehicle)
{
vehicles_exit(this.vehicle, VHEF_RELEASE);
- if(!this.killindicator_teamchange)
+ if(!CS(this).killindicator_teamchange)
{
this.vehicle_health = -1;
Damage(this, this, this, 1 , DEATH_KILL.m_id, this.origin, '0 0 0');
this.killindicator = NULL;
- if(this.killindicator_teamchange)
+ if(CS(this).killindicator_teamchange)
ClientKill_Now_TeamChange(this);
if(!IS_SPEC(this) && !IS_OBSERVER(this))
}
void KillIndicator_Think(entity this)
{
- if (gameover)
+ if (game_stopped)
{
this.owner.killindicator = NULL;
delete(this);
ClientKill_Now(this.owner);
return;
}
- else if(g_cts && this.health == 1) // health == 1 means that it's silent
+ else if(this.health == 1) // health == 1 means that it's silent
{
this.nextthink = time + 1;
this.cnt -= 1;
float killtime;
float starttime;
- if (gameover)
+ if (game_stopped)
return;
killtime = autocvar_g_balance_kill_delay;
- if(g_race_qualifying || g_cts)
- killtime = 0;
-
if(MUTATOR_CALLHOOK(ClientKill, this, killtime))
return;
+ killtime = M_ARGV(1, float);
- this.killindicator_teamchange = targetteam;
+ CS(this).killindicator_teamchange = targetteam;
if(!this.killindicator)
{
void ClientKill (entity this)
{
- if(gameover) return;
+ if(game_stopped) return;
if(this.player_blocked) return;
if(STAT(FROZEN, this)) return;
if(autocvar_sv_gentle)
stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
+ stuffcmd(e, sprintf("\ncl_jumpspeedcap_min \"%s\"\n", autocvar_sv_jumpspeedcap_min));
+ stuffcmd(e, sprintf("\ncl_jumpspeedcap_max \"%s\"\n", autocvar_sv_jumpspeedcap_max));
+
MUTATOR_CALLHOOK(FixClientCvars, e);
}
-float PlayerInIDList(entity p, string idlist)
+bool findinlist_abbrev(string tofind, string list)
{
- float n, i;
- string s;
+ // this function allows abbreviated strings!
+ FOREACH_WORD(list, it == substring(tofind, 0, strlen(it)),
+ {
+ return true;
+ });
+
+ return false;
+}
+bool PlayerInIPList(entity p, string iplist)
+{
+ // some safety checks (never allow local?)
+ if(p.netaddress == "local" || p.netaddress == "" || !IS_REAL_CLIENT(p))
+ return false;
+
+ return findinlist_abbrev(p.netaddress, iplist);
+}
+
+bool PlayerInIDList(entity p, string idlist)
+{
// NOTE: we do NOT check crypto_idfp_signed here, an unsigned ID is fine too for this
- if (!p.crypto_idfp)
- return 0;
+ if(!p.crypto_idfp)
+ return false;
- // this function allows abbreviated player IDs too!
- n = tokenize_console(idlist);
- for(i = 0; i < n; ++i)
- {
- s = argv(i);
- if(s == substring(p.crypto_idfp, 0, strlen(s)))
- return 1;
- }
+ return findinlist_abbrev(p.crypto_idfp, idlist);
+}
- return 0;
+bool PlayerInList(entity player, string list)
+{
+ return PlayerInIDList(player, list) || PlayerInIPList(player, list);
}
#ifdef DP_EXT_PRECONNECT
#ifdef WATERMARK
Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_WATERMARK, WATERMARK);
#endif
- this.version_nagtime = time + 10 + random() * 10;
TRANSMUTE(Client, this);
+ CS(this).version_nagtime = time + 10 + random() * 10;
// identify the right forced team
if (autocvar_g_campaign)
}
}
}
- 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 if (PlayerInList(this, autocvar_g_forced_team_red)) this.team_forced = NUM_TEAM_1;
+ else if (PlayerInList(this, autocvar_g_forced_team_blue)) this.team_forced = NUM_TEAM_2;
+ else if (PlayerInList(this, autocvar_g_forced_team_yellow)) this.team_forced = NUM_TEAM_3;
+ else if (PlayerInList(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;
if (IS_BOT_CLIENT(this)) PlayerStats_GameReport_AddPlayer(this);
if (autocvar_sv_eventlog)
- GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", this.netname));
+ GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false)));
LogTeamchange(this.playerid, this.team, 1);
this.just_joined = true; // stop spamming the eventlog with additional lines when the client connects
- this.netname_previous = strzone(this.netname);
+ CS(this).netname_previous = strzone(this.netname);
if(teamplay && IS_PLAYER(this))
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_CONNECT_TEAM), this.netname);
bot_relinkplayerlist();
- this.spectatortime = time;
+ CS(this).spectatortime = time;
if (blockSpectators)
{
Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
}
- this.jointime = time;
- this.allowed_timeouts = autocvar_sv_timeout_number;
+ CS(this).jointime = time;
+ CS(this).allowed_timeouts = autocvar_sv_timeout_number;
if (IS_REAL_CLIENT(this))
{
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 (!g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
+ if(!MUTATOR_CALLHOOK(HideTeamNagger, this))
send_CSQC_teamnagger();
CSQCMODEL_AUTOINIT(this);
sv_notice_join(this);
// update physics stats (players can spawn before physics runs)
+ STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed;
+ MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this); // do it BEFORE the function so we can modify highspeed!
Physics_UpdateStats(this, PHYS_HIGHSPEED(this));
IL_EACH(g_initforplayer, it.init_for_player, {
{
if (!autocvar_g_campaign && !IS_PLAYER(this))
{
- this.motd_actived_time = -1;
+ CS(this).motd_actived_time = -1;
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this));
}
}
PlayerStats_GameReport_FinalizePlayer(this);
if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
- if (this.active_minigame) part_minigame(this);
+ if (CS(this).active_minigame) part_minigame(this);
if (IS_PLAYER(this)) Send_Effect(EFFECT_SPAWN_NEUTRAL, this.origin, '0 0 0', 1);
if (autocvar_sv_eventlog)
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname);
- SetSpectatee(this, NULL);
+ if(IS_SPEC(this))
+ SetSpectatee(this, NULL);
MUTATOR_CALLHOOK(ClientDisconnect, this);
+ if (CS(this).netname_previous) strunzone(CS(this).netname_previous); // needs to be before the CS entity is removed!
ClientState_detach(this);
Portal_ClearAll(this);
bot_relinkplayerlist();
- if (this.netname_previous) strunzone(this.netname_previous);
if (this.clientstatus) strunzone(this.clientstatus);
if (this.weaponorder_byimpulse) strunzone(this.weaponorder_byimpulse);
if (this.personal) delete(this.personal);
if ( !IS_DEAD(this.owner) && IS_PLAYER(this.owner) )
{
- if ( this.owner.active_minigame )
+ if ( CS(this.owner).active_minigame )
this.mdl = "models/sprites/minigame_busy.iqm";
else if (PHYS_INPUT_BUTTON_CHAT(this.owner))
this.mdl = "models/misc/chatbubble.spr";
// 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) && !gameover)
+ if((this.items & IT_USING_JETPACK) && !IS_DEAD(this) && !game_stopped)
this.modelflags |= MF_ROCKET;
else
this.modelflags &= ~MF_ROCKET;
if (time < this.strength_finished)
{
this.items = this.items | ITEM_Strength.m_itemid;
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_STRENGTH, this.netname);
+ if(!g_cts)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_STRENGTH, this.netname);
Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_STRENGTH);
}
}
if (time < this.invincible_finished)
{
this.items = this.items | ITEM_Shield.m_itemid;
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_SHIELD, this.netname);
+ if(!g_cts)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_SHIELD, this.netname);
Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_SHIELD);
}
}
if (time < this.superweapons_finished || (this.items & IT_UNLIMITED_SUPERWEAPONS))
{
this.items = this.items | IT_SUPERWEAPON;
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_PICKUP, this.netname);
+ if(!g_cts)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_SUPERWEAPON_PICKUP, this.netname);
Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_SUPERWEAPON_PICKUP);
}
else
{
MUTATOR_CALLHOOK(GetPressedKeys, this);
int keys = STAT(PRESSED_KEYS, this);
- 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_FORWARD, CS(this).movement.x > 0);
+ keys = BITSET(keys, KEY_BACKWARD, CS(this).movement.x < 0);
+ keys = BITSET(keys, KEY_RIGHT, CS(this).movement.y > 0);
+ keys = BITSET(keys, KEY_LEFT, CS(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; // store for other users
+ CS(this).pressedkeys = keys; // store for other users
STAT(PRESSED_KEYS, this) = keys;
}
this.clip_size = spectatee.clip_size;
this.effects = spectatee.effects & EFMASK_CHEAP; // eat performance
this.health = spectatee.health;
- this.impulse = 0;
+ CS(this).impulse = 0;
this.items = spectatee.items;
this.last_pickup = spectatee.last_pickup;
this.hit_time = spectatee.hit_time;
this.strength_finished = spectatee.strength_finished;
this.invincible_finished = spectatee.invincible_finished;
+ this.superweapons_finished = spectatee.superweapons_finished;
STAT(PRESSED_KEYS, this) = STAT(PRESSED_KEYS, spectatee);
this.weapons = spectatee.weapons;
+ this.dual_weapons = spectatee.dual_weapons;
this.vortex_charge = spectatee.vortex_charge;
this.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
this.hagar_load = spectatee.hagar_load;
this.(weaponentity) = spectatee.(weaponentity);
}
+ for(int slot = 0; slot < MAX_AXH; ++slot)
+ {
+ this.(AuxiliaryXhair[slot]) = spectatee.(AuxiliaryXhair[slot]);
+ }
+
anticheat_spectatecopy(this, spectatee);
this.hud = spectatee.hud;
if(spectatee.vehicle)
void SetSpectatee(entity this, entity spectatee)
{
+ if(IS_BOT_CLIENT(this))
+ return; // bots abuse .enemy, this code is useless to them
+
entity old_spectatee = this.enemy;
this.enemy = spectatee;
PutClientInServer(this);
+ if(IS_PLAYER(this))
if(teamplay && this.team != -1)
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
else
if(!this.caplayer)
if(IS_REAL_CLIENT(this))
{
- if( time > (this.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
+ if( time > (CS(this).spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
dropclient(this);
}
void PrintWelcomeMessage(entity this)
{
- if(this.motd_actived_time == 0)
+ if(CS(this).motd_actived_time == 0)
{
if (autocvar_g_campaign) {
if ((IS_PLAYER(this) && PHYS_INPUT_BUTTON_INFO(this)) || (!IS_PLAYER(this))) {
- this.motd_actived_time = time;
+ CS(this).motd_actived_time = time;
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, campaign_message);
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this)) {
- this.motd_actived_time = time;
+ CS(this).motd_actived_time = time;
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOTD, getwelcomemessage(this));
}
}
}
- else if(this.motd_actived_time > 0) // showing MOTD or campaign message
+ else if(CS(this).motd_actived_time > 0) // showing MOTD or campaign message
{
if (autocvar_g_campaign) {
if (PHYS_INPUT_BUTTON_INFO(this))
- this.motd_actived_time = time;
- else if ((time - this.motd_actived_time > 2) && IS_PLAYER(this)) { // hide it some seconds after BUTTON_INFO has been released
- this.motd_actived_time = 0;
+ 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);
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this))
- this.motd_actived_time = time;
- else if (time - this.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
- this.motd_actived_time = 0;
+ CS(this).motd_actived_time = time;
+ else if (time - CS(this).motd_actived_time > 2) { // 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);
}
}
}
- else //if(this.motd_actived_time < 0) // just connected, motd is active
+ else //if(CS(this).motd_actived_time < 0) // just connected, motd is active
{
if(PHYS_INPUT_BUTTON_INFO(this)) // BUTTON_INFO hides initial MOTD
- this.motd_actived_time = -2; // wait until BUTTON_INFO gets released
- else if(this.motd_actived_time == -2 || IS_PLAYER(this) || IS_SPEC(this))
+ CS(this).motd_actived_time = -2; // wait until BUTTON_INFO gets released
+ else if(CS(this).motd_actived_time == -2 || IS_PLAYER(this) || IS_SPEC(this))
{
// instanctly hide MOTD
- this.motd_actived_time = 0;
+ CS(this).motd_actived_time = 0;
Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
}
return true;
}
+.int items_added;
+bool PlayerThink(entity this)
+{
+ CheckRules_Player(this);
+
+ if (game_stopped || intermission_running) {
+ this.modelflags &= ~MF_ROCKET;
+ if(intermission_running)
+ IntermissionThink(this);
+ return false;
+ }
+
+ if (timeout_status == TIMEOUT_ACTIVE) {
+ // 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;
+ this.fixangle = true;
+ }
+
+ if (frametime) player_powerups(this);
+
+ if (IS_DEAD(this)) {
+ if (this.personal && g_race_qualifying) {
+ if (time > this.respawn_time) {
+ STAT(RESPAWN_TIME, this) = this.respawn_time = time + 1; // only retry once a second
+ respawn(this);
+ CS(this).impulse = CHIMPULSE_SPEEDRUN.impulse;
+ }
+ } else {
+ if (frametime) player_anim(this);
+
+ if (this.respawn_flags & RESPAWN_DENY)
+ {
+ STAT(RESPAWN_TIME, this) = 0;
+ return false;
+ }
+
+ bool button_pressed = (PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this));
+
+ switch(this.deadflag)
+ {
+ case DEAD_DYING:
+ {
+ if ((this.respawn_flags & RESPAWN_FORCE) && !(this.respawn_time < this.respawn_time_max))
+ this.deadflag = DEAD_RESPAWNING;
+ else if (!button_pressed || (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE)))
+ this.deadflag = DEAD_DEAD;
+ break;
+ }
+ case DEAD_DEAD:
+ {
+ if (button_pressed)
+ this.deadflag = DEAD_RESPAWNABLE;
+ else if (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE))
+ this.deadflag = DEAD_RESPAWNING;
+ break;
+ }
+ case DEAD_RESPAWNABLE:
+ {
+ if (!button_pressed || (this.respawn_flags & RESPAWN_FORCE))
+ this.deadflag = DEAD_RESPAWNING;
+ break;
+ }
+ case DEAD_RESPAWNING:
+ {
+ if (time > this.respawn_time)
+ {
+ this.respawn_time = time + 1; // only retry once a second
+ this.respawn_time_max = this.respawn_time;
+ respawn(this);
+ }
+ break;
+ }
+ }
+
+ ShowRespawnCountdown(this);
+
+ if (this.respawn_flags & RESPAWN_SILENT)
+ STAT(RESPAWN_TIME, this) = 0;
+ else if ((this.respawn_flags & RESPAWN_FORCE) && this.respawn_time < this.respawn_time_max)
+ {
+ if (time < this.respawn_time)
+ STAT(RESPAWN_TIME, this) = this.respawn_time;
+ else if (this.deadflag != DEAD_RESPAWNING)
+ STAT(RESPAWN_TIME, this) = -this.respawn_time_max;
+ }
+ else
+ STAT(RESPAWN_TIME, this) = this.respawn_time;
+ }
+
+ // if respawning, invert stat_respawn_time to indicate this, the client translates it
+ if (this.deadflag == DEAD_RESPAWNING && STAT(RESPAWN_TIME, this) > 0)
+ STAT(RESPAWN_TIME, this) *= -1;
+
+ return false;
+ }
+
+ this.prevorigin = this.origin;
+
+ bool have_hook = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).hook.state)
+ {
+ have_hook = true;
+ break;
+ }
+ }
+ bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+ if (have_hook) {
+ do_crouch = false;
+ } else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
+ do_crouch = false;
+ } else if (this.vehicle) {
+ do_crouch = false;
+ } else if (STAT(FROZEN, this)) {
+ do_crouch = false;
+ }
+
+ if (do_crouch) {
+ if (!this.crouch) {
+ this.crouch = true;
+ this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
+ setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
+ // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
+ }
+ } else if (this.crouch) {
+ tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
+ if (!trace_startsolid) {
+ this.crouch = false;
+ this.view_ofs = STAT(PL_VIEW_OFS, this);
+ setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
+ }
+ }
+
+ FixPlayermodel(this);
+
+ // 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_WeaponFrame(this, weaponentity);
+
+ if(slot == 0)
+ {
+ this.clip_load = this.(weaponentity).clip_load;
+ this.clip_size = this.(weaponentity).clip_size;
+ }
+ }
+
+ this.items_added = 0;
+ if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_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)
+ {
+ .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);
+
+ // secret status
+ secrets_setstatus(this);
+
+ // monsters status
+ monsters_setstatus(this);
+
+ this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
+
+ return true;
+}
+
void ObserverThink(entity this)
{
- if ( this.impulse )
+ if ( CS(this).impulse )
{
- MinigameImpulse(this, this.impulse);
- this.impulse = 0;
+ MinigameImpulse(this, CS(this).impulse);
+ CS(this).impulse = 0;
}
if (this.flags & FL_JUMPRELEASED) {
void SpectatorThink(entity this)
{
- if ( this.impulse )
+ if ( CS(this).impulse )
{
- if(MinigameImpulse(this, this.impulse))
- this.impulse = 0;
+ if(MinigameImpulse(this, CS(this).impulse))
+ CS(this).impulse = 0;
- if (this.impulse == IMP_weapon_drop.impulse)
+ if (CS(this).impulse == IMP_weapon_drop.impulse)
{
STAT(CAMERA_SPECTATOR, this) = (STAT(CAMERA_SPECTATOR, this) + 1) % 3;
- this.impulse = 0;
+ CS(this).impulse = 0;
return;
}
}
if (PHYS_INPUT_BUTTON_JUMP(this) && joinAllowed(this)) {
this.flags &= ~FL_JUMPRELEASED;
this.flags |= FL_SPAWNING;
- } else if(PHYS_INPUT_BUTTON_ATCK(this) || this.impulse == 10 || this.impulse == 15 || this.impulse == 18 || (this.impulse >= 200 && this.impulse <= 209)) {
+ } 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)) {
this.flags &= ~FL_JUMPRELEASED;
if(SpectateNext(this)) {
TRANSMUTE(Spectator, this);
TRANSMUTE(Observer, this);
PutClientInServer(this);
}
- this.impulse = 0;
- } else if(this.impulse == 12 || this.impulse == 16 || this.impulse == 19 || (this.impulse >= 220 && this.impulse <= 229)) {
+ 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);
TRANSMUTE(Observer, this);
PutClientInServer(this);
}
- this.impulse = 0;
+ CS(this).impulse = 0;
} else if (PHYS_INPUT_BUTTON_ATCK2(this)) {
this.flags &= ~FL_JUMPRELEASED;
TRANSMUTE(Observer, this);
if(this.vehicle)
{
- if(!gameover)
+ if(!game_stopped)
{
vehicles_exit(this.vehicle, VHEF_NORMAL);
return;
{
if(!STAT(FROZEN, this))
if(!IS_DEAD(this))
- if(!gameover)
+ if(!game_stopped)
{
entity head, closest_target = NULL;
head = WarpZone_FindRadius(this.origin, autocvar_g_vehicles_enter_radius, true);
Called every frame for each client before the physics are run
=============
*/
-.float usekeypressed;
.float last_vehiclecheck;
-.int items_added;
void PlayerPreThink (entity this)
{
WarpZone_PlayerPhysics_FixVAngle(this);
this.netname = strzone(sprintf("Player#%d", this.playerid));
// stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe?
}
- if (this.netname != this.netname_previous) {
+ if (this.netname != CS(this).netname_previous) {
if (autocvar_sv_eventlog) {
- GameLogEcho(strcat(":name:", ftos(this.playerid), ":", this.netname));
+ GameLogEcho(strcat(":name:", ftos(this.playerid), ":", playername(this, false)));
}
- if (this.netname_previous) strunzone(this.netname_previous);
- this.netname_previous = strzone(this.netname);
+ if (CS(this).netname_previous) strunzone(CS(this).netname_previous);
+ CS(this).netname_previous = strzone(this.netname);
}
// version nagging
- if (this.version_nagtime && this.cvar_g_xonoticversion && time > this.version_nagtime) {
- this.version_nagtime = 0;
+ if (CS(this).version_nagtime && this.cvar_g_xonoticversion && time > CS(this).version_nagtime) {
+ CS(this).version_nagtime = 0;
if (strstrofs(this.cvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(this.cvar_g_xonoticversion, "autobuild", 0) >= 0) {
// git client
} else if (strstrofs(autocvar_g_xonoticversion, "git", 0) >= 0 || strstrofs(autocvar_g_xonoticversion, "autobuild", 0) >= 0) {
MUTATOR_CALLHOOK(PlayerPreThink, this);
- if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !gameover && !this.vehicle)
+ if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !game_stopped && !this.vehicle)
if(IS_PLAYER(this) && !STAT(FROZEN, this) && !IS_DEAD(this))
{
FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_vehicles_enter_radius, IS_VEHICLE(it),
if(!this.cvar_cl_newusekeysupported) // FIXME remove this - it was a stupid idea to begin with, we can JUST use the button
{
- if(PHYS_INPUT_BUTTON_USE(this) && !this.usekeypressed)
+ if(PHYS_INPUT_BUTTON_USE(this) && !CS(this).usekeypressed)
PlayerUseKey(this);
- this.usekeypressed = PHYS_INPUT_BUTTON_USE(this);
+ CS(this).usekeypressed = PHYS_INPUT_BUTTON_USE(this);
}
if (IS_REAL_CLIENT(this))
PrintWelcomeMessage(this);
if (IS_PLAYER(this)) {
- CheckRules_Player(this);
-
- if (gameover || intermission_running) {
- if(intermission_running)
- IntermissionThink(this);
- return;
- }
-
- if (timeout_status == TIMEOUT_ACTIVE) {
- // 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;
- this.fixangle = true;
- }
-
- if (frametime) player_powerups(this);
-
- if (IS_DEAD(this)) {
- if (this.personal && g_race_qualifying) {
- if (time > this.respawn_time) {
- STAT(RESPAWN_TIME, this) = this.respawn_time = time + 1; // only retry once a second
- respawn(this);
- this.impulse = CHIMPULSE_SPEEDRUN.impulse;
- }
- } else {
- if (frametime) player_anim(this);
- bool button_pressed = (PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this));
-
- switch(this.deadflag)
- {
- case DEAD_DYING:
- {
- if ((this.respawn_flags & RESPAWN_FORCE) && !(this.respawn_time < this.respawn_time_max))
- this.deadflag = DEAD_RESPAWNING;
- else if (!button_pressed || (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE)))
- this.deadflag = DEAD_DEAD;
- break;
- }
- case DEAD_DEAD:
- {
- if (button_pressed)
- this.deadflag = DEAD_RESPAWNABLE;
- else if (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE))
- this.deadflag = DEAD_RESPAWNING;
- break;
- }
- case DEAD_RESPAWNABLE:
- {
- if (!button_pressed || (this.respawn_flags & RESPAWN_FORCE))
- this.deadflag = DEAD_RESPAWNING;
- break;
- }
- case DEAD_RESPAWNING:
- {
- if (time > this.respawn_time)
- {
- this.respawn_time = time + 1; // only retry once a second
- this.respawn_time_max = this.respawn_time;
- respawn(this);
- }
- break;
- }
- }
-
- ShowRespawnCountdown(this);
-
- if (this.respawn_flags & RESPAWN_SILENT)
- STAT(RESPAWN_TIME, this) = 0;
- else if ((this.respawn_flags & RESPAWN_FORCE) && this.respawn_time < this.respawn_time_max)
- {
- if (time < this.respawn_time)
- STAT(RESPAWN_TIME, this) = this.respawn_time;
- else if (this.deadflag != DEAD_RESPAWNING)
- STAT(RESPAWN_TIME, this) = -this.respawn_time_max;
- }
- else
- STAT(RESPAWN_TIME, this) = this.respawn_time;
- }
-
- // if respawning, invert stat_respawn_time to indicate this, the client translates it
- if (this.deadflag == DEAD_RESPAWNING && STAT(RESPAWN_TIME, this) > 0)
- STAT(RESPAWN_TIME, this) *= -1;
-
+ if(!PlayerThink(this))
return;
- }
-
- this.prevorigin = this.origin;
-
- bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
- if (this.hook.state) {
- do_crouch = false;
- } else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
- do_crouch = false;
- } else if (this.vehicle) {
- do_crouch = false;
- } else if (STAT(FROZEN, this)) {
- do_crouch = false;
- }
-
- if (do_crouch) {
- if (!this.crouch) {
- this.crouch = true;
- this.view_ofs = STAT(PL_CROUCH_VIEW_OFS, this);
- setsize(this, STAT(PL_CROUCH_MIN, this), STAT(PL_CROUCH_MAX, this));
- // setanim(this, this.anim_duck, false, true, true); // this anim is BROKEN anyway
- }
- } else if (this.crouch) {
- tracebox(this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), this.origin, false, this);
- if (!trace_startsolid) {
- this.crouch = false;
- this.view_ofs = STAT(PL_VIEW_OFS, this);
- setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
- }
- }
-
- FixPlayermodel(this);
-
- // 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_WeaponFrame(this, weaponentity);
-
- if(slot == 0)
- {
- this.clip_load = this.(weaponentity).clip_load;
- this.clip_size = this.(weaponentity).clip_size;
- }
- }
-
- this.items_added = 0;
- if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_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)
- {
- .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);
-
- // secret status
- secrets_setstatus(this);
-
- // monsters status
- monsters_setstatus(this);
-
- this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
}
- else if (gameover || intermission_running) {
+ else if (game_stopped || intermission_running) {
if(intermission_running)
IntermissionThink(this);
return;
SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed);
}
- if (this.teamkill_soundtime && time > this.teamkill_soundtime)
+ if (CS(this).teamkill_soundtime && time > CS(this).teamkill_soundtime)
{
- this.teamkill_soundtime = 0;
+ CS(this).teamkill_soundtime = 0;
- entity e = this.teamkill_soundsource;
+ entity e = CS(this).teamkill_soundsource;
entity oldpusher = e.pusher;
e.pusher = this;
PlayerSound(e, playersound_teamshoot, CH_VOICE, VOL_BASEVOICE, VOICETYPE_LASTATTACKER_ONLY);
e.pusher = oldpusher;
}
- if (this.taunt_soundtime && time > this.taunt_soundtime) {
- this.taunt_soundtime = 0;
+ if (CS(this).taunt_soundtime && time > CS(this).taunt_soundtime) {
+ CS(this).taunt_soundtime = 0;
PlayerSound(this, playersound_taunt, CH_VOICE, VOL_BASEVOICE, VOICETYPE_AUTOTAUNT);
}
if(!this.move_qcphysics)
return;
- if(!frametime && !this.pm_frametime)
+ if(!frametime && !CS(this).pm_frametime)
return;
- Movetype_Physics_NoMatchTicrate(this, this.pm_frametime, true);
+ Movetype_Physics_NoMatchTicrate(this, CS(this).pm_frametime, true);
- this.pm_frametime = 0;
+ CS(this).pm_frametime = 0;
}
/*
Called every frame for each client after the physics are run
=============
*/
-.float idlekick_lasttimeleft;
void PlayerPostThink (entity this)
{
Player_Physics(this);
if (sv_maxidle_slots > 0 && (maxclients - totalClients) > sv_maxidle_slots)
{ /* do nothing */ }
- else if (time - this.parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
+ else if (time - CS(this).parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
{
- if (this.idlekick_lasttimeleft)
+ if (CS(this).idlekick_lasttimeleft)
{
- this.idlekick_lasttimeleft = 0;
+ CS(this).idlekick_lasttimeleft = 0;
Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_IDLING);
}
}
else
{
- float timeleft = ceil(sv_maxidle - (time - this.parm_idlesince));
+ float timeleft = ceil(sv_maxidle - (time - CS(this).parm_idlesince));
if (timeleft == min(10, sv_maxidle - 1)) { // - 1 to support sv_maxidle <= 10
- if (!this.idlekick_lasttimeleft)
+ if (!CS(this).idlekick_lasttimeleft)
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
}
if (timeleft <= 0) {
return;
}
else if (timeleft <= 10) {
- if (timeleft != this.idlekick_lasttimeleft) {
+ if (timeleft != CS(this).idlekick_lasttimeleft) {
Send_Notification(NOTIF_ONE, this, MSG_ANNCE, Announcer_PickNumber(CNT_IDLE, timeleft));
}
- this.idlekick_lasttimeleft = timeleft;
+ CS(this).idlekick_lasttimeleft = timeleft;
}
}
}
CheatFrame(this);
//CheckPlayerJump();
- if (gameover)
+ if (game_stopped)
{
this.solid = SOLID_NOT;
this.takedamage = DAMAGE_NO;
DrownPlayer(this);
CheckRules_Player(this);
UpdateChatBubble(this);
- if (this.impulse) ImpulseCommands(this);
- if (gameover)
+ if (CS(this).impulse) ImpulseCommands(this);
+ if (game_stopped)
{
CSQCMODEL_AUTOUPDATE(this);
return;
CSQCMODEL_AUTOUPDATE(this);
}
+
+// hack to copy the button fields from the client entity to the Client State
+void PM_UpdateButtons(entity this, entity store)
+{
+ if(this.impulse)
+ store.impulse = this.impulse;
+ this.impulse = 0;
+
+ store.button0 = this.button0;
+ store.button2 = this.button2;
+ store.button3 = this.button3;
+ store.button4 = this.button4;
+ store.button5 = this.button5;
+ store.button6 = this.button6;
+ store.button7 = this.button7;
+ store.button8 = this.button8;
+ store.button9 = this.button9;
+ store.button10 = this.button10;
+ store.button11 = this.button11;
+ store.button12 = this.button12;
+ store.button13 = this.button13;
+ store.button14 = this.button14;
+ store.button15 = this.button15;
+ store.button16 = this.button16;
+ store.buttonuse = this.buttonuse;
+ store.buttonchat = this.buttonchat;
+
+ store.cursor_active = this.cursor_active;
+ store.cursor_screen = this.cursor_screen;
+ store.cursor_trace_start = this.cursor_trace_start;
+ store.cursor_trace_endpos = this.cursor_trace_endpos;
+ store.cursor_trace_ent = this.cursor_trace_ent;
+
+ store.ping = this.ping;
+ store.ping_packetloss = this.ping_packetloss;
+ store.ping_movementloss = this.ping_movementloss;
+
+ store.v_angle = this.v_angle;
+ store.movement = this.movement;
+}