.float campcheck_nextcheck;
.float campcheck_traveled_distance;
+.vector campcheck_prevorigin;
+
MUTATOR_HOOKFUNCTION(campcheck, PlayerDies)
{
entity frag_target = M_ARGV(2, entity);
MUTATOR_HOOKFUNCTION(campcheck, PlayerPreThink)
{
entity player = M_ARGV(0, entity);
+ bool checked = false;
- if(!game_stopped)
- if(!warmup_stage) // don't consider it camping during warmup?
- if(time >= game_starttime)
+ if(autocvar_g_campcheck_interval)
+ if(!game_stopped && !warmup_stage && time >= game_starttime)
if(IS_PLAYER(player))
- if(IS_REAL_CLIENT(player)) // bots may camp, but that's no reason to constantly kill them
if(!IS_DEAD(player))
- if(!forbidWeaponUse(player))
if(!STAT(FROZEN, player))
if(!PHYS_INPUT_BUTTON_CHAT(player))
- if(autocvar_g_campcheck_interval)
+ if(IS_REAL_CLIENT(player)) // bots may camp, but that's no reason to constantly kill them
+ if(!forbidWeaponUse(player))
{
- vector dist;
-
// calculate player movement (in 2 dimensions only, so jumping on one spot doesn't count as movement)
- dist = player.prevorigin - player.origin;
- dist.z = 0;
+ vector dist = vec2(player.campcheck_prevorigin - player.origin);
player.campcheck_traveled_distance += fabs(vlen(dist));
if((autocvar_g_campaign && !campaign_bots_may_start) || (time < game_starttime) || (round_handler_IsActive() && !round_handler_IsRoundStarted()))
player.campcheck_traveled_distance = 0;
}
- return;
+ checked = true;
}
- player.campcheck_nextcheck = time + autocvar_g_campcheck_interval; // one of the above checks failed, so keep the timer up to date
+ if(!checked)
+ player.campcheck_nextcheck = time + autocvar_g_campcheck_interval; // one of the above checks failed, so keep the timer up to date
+
+ player.campcheck_prevorigin = player.origin;
+}
+
+MUTATOR_HOOKFUNCTION(campcheck, CopyBody)
+{
+ entity player = M_ARGV(0, entity);
+ entity clone = M_ARGV(1, entity);
+
+ clone.campcheck_prevorigin = player.campcheck_prevorigin;
}
MUTATOR_HOOKFUNCTION(campcheck, PlayerSpawn)
if (IS_SPEC(e)) e = e.enemy;
sf = 0;
- if (e.race_completed) sf |= 1; // forced scoreboard
+ if (CS(e).race_completed) sf |= 1; // forced scoreboard
if (CS(to).spectatee_status) sf |= 2; // spectator ent number follows
if (CS(e).zoomstate) sf |= 4; // zoomed
if (autocvar_sv_showspectators) sf |= 16; // show spectators
{
entity spot = SelectSpawnPoint(this, true);
if (!spot) LOG_FATAL("No spawnpoints for observers?!?");
- this.angles = spot.angles;
- this.angles_z = 0;
+ this.angles = vec2(spot.angles);
this.fixangle = true;
// offset it so that the spectator spawns higher off the ground, looks better this way
setorigin(this, spot.origin + STAT(PL_VIEW_OFS, this));
- this.prevorigin = this.origin;
if (IS_REAL_CLIENT(this))
{
msg_entity = this;
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);
return false;
}
- this.prevorigin = this.origin;
-
bool have_hook = false;
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
ATTRIB(Client, spectatee_status, int, this.spectatee_status);
ATTRIB(Client, zoomstate, bool, this.zoomstate);
ATTRIB(Client, just_joined, bool, this.just_joined);
+ ATTRIB(Client, race_completed, bool, this.race_completed);
METHOD(Client, m_unwind, bool(Client this));
.float ammo_fuel;
-.vector prevorigin;
-
//flood fields
.float nickspamtime; // time of last nick change
.float nickspamcount;
setorigin(targ, spot.origin + '0 0 1' * (1 - targ.mins.z - 24));
// don't reset back to last position, even if new position is stuck in solid
targ.oldorigin = targ.origin;
- targ.prevorigin = targ.origin;
Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
}
c = 0;
FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
++n;
- if(it.race_completed)
+ if(CS(it).race_completed)
++c;
));
if(n && (n == c))
//clone.weapon = this.weapon;
setorigin(clone, this.origin);
setsize(clone, this.mins, this.maxs);
- clone.prevorigin = this.origin;
clone.reset = SUB_Remove;
clone._ps = this._ps;
if(tvalid)
if(cp == race_timed_checkpoint) // finish line
- if (!e.race_completed)
+ if (!CS(e).race_completed)
{
float s;
if(g_race_qualifying)
if(race_completing)
{
- e.race_completed = 1;
+ CS(e).race_completed = 1;
MAKE_INDEPENDENT_PLAYER(e);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_FINISHED, e.netname);
ClientData_Touch(e);
void race_AbandonRaceCheck(entity p)
{
- if(race_completing && !p.race_completed)
+ if(race_completing && !CS(p).race_completed)
{
- p.race_completed = 1;
+ CS(p).race_completed = 1;
MAKE_INDEPENDENT_PLAYER(p);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_RACE_ABANDONED, p.netname);
ClientData_Touch(p);
float l;
l = PlayerScore_Add(e, SP_RACE_LAPS, 0);
- if(e.race_completed)
+ if(CS(e).race_completed)
return l; // not fractional
vector o0, o1;