#include "campaign.qh"
#include "command/common.qh"
-#include "bot/bot.qh"
-#include "bot/navigation.qh"
+#include "bot/api.qh"
#include "../common/ent_cs.qh"
#include <common/state.qh>
STATIC_METHOD(Client, Add, void(Client this, int _team))
{
- WITHSELF(this, ClientConnect());
+ ClientConnect(this);
TRANSMUTE(Player, this);
this.frame = 12; // 7
this.team = _team;
- WITHSELF(this, PutClientInServer());
+ PutClientInServer(this);
}
void PutObserverInServer(entity this);
-void ClientDisconnect();
STATIC_METHOD(Client, Remove, void(Client this))
{
TRANSMUTE(Observer, this);
- WITHSELF(this, PutClientInServer());
- WITHSELF(this, ClientDisconnect());
+ PutClientInServer(this);
+ ClientDisconnect(this);
}
void send_CSQC_teamnagger() {
WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
+int CountSpectators(entity player, entity to)
+{
+ if(!player) { return 0; } // not sure how, but best to be safe
+
+ int spec_count = 0;
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
+ {
+ spec_count++;
+ });
+
+ return spec_count;
+}
+
+void WriteSpectators(entity player, entity to)
+{
+ if(!player) { return; } // not sure how, but best to be safe
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
+ {
+ WriteByte(MSG_ENTITY, num_for_edict(it));
+ });
+}
+
bool ClientData_Send(entity this, entity to, int sf)
{
assert(to == this.owner, return false);
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 (autocvar_sv_showspectators) sf |= 16; // show spectators
WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
WriteByte(MSG_ENTITY, sf);
WriteAngle(MSG_ENTITY, e.v_angle.x);
WriteAngle(MSG_ENTITY, e.v_angle.y);
}
+
+ if(sf & 16)
+ {
+ float specs = CountSpectators(e, to);
+ WriteByte(MSG_ENTITY, specs);
+ WriteSpectators(e, to);
+ }
+
return true;
}
void ClientData_Detach(entity this)
{
- remove(this.clientdata);
+ delete(this.clientdata);
this.clientdata = NULL;
}
// needed for player sounds
this.model = "";
FixPlayermodel(this);
- }
+ }
setmodel(this, MDL_Null);
setsize(this, STAT(PL_CROUCH_MIN, NULL), STAT(PL_CROUCH_MAX, NULL));
this.view_ofs = '0 0 0';
RemoveGrapplingHook(this);
Portal_ClearAll(this);
Unfreeze(this);
+ SetSpectatee(this, NULL);
if (this.alivetime)
{
this.health = FRAGS_SPECTATOR;
this.takedamage = DAMAGE_NO;
this.solid = SOLID_NOT;
- this.movetype = MOVETYPE_FLY_WORLDONLY; // user preference is controlled by playerprethink
+ set_movetype(this, MOVETYPE_FLY_WORLDONLY); // user preference is controlled by playerprethink
this.flags = FL_CLIENT | FL_NOTARGET;
this.armorvalue = 666;
this.effects = 0;
this.oldvelocity = this.velocity;
this.fire_endtime = -1;
this.event_damage = func_null;
+
+ STAT(ACTIVEWEAPON, this) = WEP_Null.m_id;
+ STAT(SWITCHINGWEAPON, this) = WEP_Null.m_id;
+ STAT(SWITCHWEAPON, this) = WEP_Null.m_id;
}
int player_getspecies(entity this)
/** Called when a client spawns in the server */
-void PutClientInServer()
-{ENGINE_EVENT();
+void PutClientInServer(entity this)
+{
if (IS_BOT_CLIENT(this)) {
TRANSMUTE(Player, this);
} else if (IS_REAL_CLIENT(this)) {
if (IS_OBSERVER(this)) {
PutObserverInServer(this);
} else if (IS_PLAYER(this)) {
+ if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
+
PlayerState_attach(this);
accuracy_resend(this);
this.iscreature = true;
this.teleportable = TELEPORT_NORMAL;
this.damagedbycontents = true;
- this.movetype = MOVETYPE_WALK;
+ set_movetype(this, MOVETYPE_WALK);
this.solid = SOLID_SLIDEBOX;
this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID;
if (autocvar_g_playerclip_collisions)
if (autocvar_spawn_debug)
{
sprint(this, strcat("spawnpoint origin: ", vtos(spot.origin), "\n"));
- remove(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
+ delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
}
PS(this).m_switchweapon = w_getbestweapon(this);
SetChangeParms
=============
*/
-void SetChangeParms ()
-{ENGINE_EVENT();
+void SetChangeParms (entity this)
+{
// save parms for level change
parm1 = this.parm_idlesince - time;
PutObserverInServer(this);
}
else
- WITHSELF(this, SV_ChangeTeam(this.killindicator_teamchange - 1));
+ SV_ChangeTeam(this, this.killindicator_teamchange - 1);
this.killindicator_teamchange = 0;
}
}
if(this.killindicator && !wasfreed(this.killindicator))
- remove(this.killindicator);
+ delete(this.killindicator);
this.killindicator = NULL;
if(this.killindicator_teamchange)
ClientKill_Now_TeamChange(this);
- if(IS_PLAYER(this))
+ if(!IS_SPEC(this) && !IS_OBSERVER(this))
Damage(this, this, this, 100000, DEATH_KILL.m_id, this.origin, '0 0 0');
// now I am sure the player IS dead
if (gameover)
{
this.owner.killindicator = NULL;
- remove(this);
+ delete(this);
return;
}
if (this.owner.alpha < 0 && !this.owner.vehicle)
{
this.owner.killindicator = NULL;
- remove(this);
+ delete(this);
return;
}
{
float killtime;
float starttime;
- entity e;
if (gameover)
return;
this.killindicator.count = bound(0, ceil(killtime), 10);
//sprint(this, strcat("^1You'll be dead in ", ftos(this.killindicator.cnt), " seconds\n"));
- for(e = NULL; (e = find(e, classname, "body")) != NULL; )
+ FOREACH_ENTITY_ENT(enemy, this,
{
- if(e.enemy != this)
+ if(it.classname != "body")
continue;
- e.killindicator = spawn();
- e.killindicator.owner = e;
- e.killindicator.scale = 0.5;
- setattachment(e.killindicator, e, "");
- setorigin(e.killindicator, '0 0 52');
- setthink(e.killindicator, KillIndicator_Think);
- e.killindicator.nextthink = starttime + (e.lip) * 0.05;
- clientkilltime = max(clientkilltime, e.killindicator.nextthink + 0.05);
- e.killindicator.cnt = ceil(killtime);
- }
+ it.killindicator = spawn();
+ it.killindicator.owner = it;
+ it.killindicator.scale = 0.5;
+ setattachment(it.killindicator, it, "");
+ setorigin(it.killindicator, '0 0 52');
+ setthink(it.killindicator, KillIndicator_Think);
+ it.killindicator.nextthink = starttime + (it.lip) * 0.05;
+ //clientkilltime = max(clientkilltime, it.killindicator.nextthink + 0.05);
+ it.killindicator.cnt = ceil(killtime);
+ });
this.lip = 0;
}
}
}
-void ClientKill ()
-{ENGINE_EVENT();
+void ClientKill (entity this)
+{
if(gameover) return;
if(this.player_blocked) return;
if(STAT(FROZEN, this)) return;
Called when a client connects to the server
=============
*/
-void ClientConnect()
-{ENGINE_EVENT();
+void ClientConnect(entity this)
+{
if (Ban_MaybeEnforceBanOnce(this)) return;
assert(!IS_CLIENT(this), return);
this.flags |= FL_CLIENT;
if (!sv_foginterval && world.fog != "")
stuffcmd(this, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
- if (autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)))
+ 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
send_CSQC_teamnagger();
*/
.entity chatbubbleentity;
void ReadyCount();
-void ClientDisconnect()
-{ENGINE_EVENT();
+void ClientDisconnect(entity this)
+{
assert(IS_CLIENT(this), return);
PlayerStats_GameReport_FinalizePlayer(this);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_DISCONNECT, this.netname);
+ SetSpectatee(this, NULL);
+
MUTATOR_CALLHOOK(ClientDisconnect, this);
ClientState_detach(this);
this.flags &= ~FL_CLIENT;
- if (this.chatbubbleentity) remove(this.chatbubbleentity);
- if (this.killindicator) remove(this.killindicator);
+ if (this.chatbubbleentity) delete(this.chatbubbleentity);
+ if (this.killindicator) delete(this.killindicator);
WaypointSprite_PlayerGone(this);
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) remove(this.personal);
+ if (this.personal) delete(this.personal);
this.playerid = 0;
ReadyCount();
{
if(this.owner) // but why can that ever be NULL?
this.owner.chatbubbleentity = NULL;
- remove(this);
+ delete(this);
return;
}
{
this.solid = SOLID_NOT;
this.takedamage = DAMAGE_NO;
- this.movetype = MOVETYPE_FLY;
+ set_movetype(this, MOVETYPE_FLY);
this.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
this.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
this.effects |= CSQCMODEL_EF_RESPAWNGHOST;
CopyBody(this, 1);
this.effects |= EF_NODRAW; // prevent another CopyBody
- WITHSELF(this, PutClientInServer());
+ PutClientInServer(this);
}
void play_countdown(entity this, float finished, Sound samp)
this.angles = spectatee.v_angle;
STAT(FROZEN, this) = STAT(FROZEN, spectatee);
this.revive_progress = spectatee.revive_progress;
- if(!PHYS_INPUT_BUTTON_USE(this))
+ if(!PHYS_INPUT_BUTTON_USE(this) && STAT(CAMERA_SPECTATOR, this) != 2)
this.fixangle = true;
setorigin(this, spectatee.origin);
setsize(this, spectatee.mins, spectatee.maxs);
this.hud = spectatee.hud;
if(spectatee.vehicle)
{
- this.fixangle = false;
+ this.angles = spectatee.v_angle;
+
+ //this.fixangle = false;
//this.velocity = spectatee.vehicle.velocity;
this.vehicle_health = spectatee.vehicle_health;
this.vehicle_shield = spectatee.vehicle_shield;
this.vehicle_reload1 = spectatee.vehicle_reload1;
this.vehicle_reload2 = spectatee.vehicle_reload2;
- msg_entity = this;
+ //msg_entity = this;
- WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
- WriteAngle(MSG_ONE, spectatee.v_angle.x);
- WriteAngle(MSG_ONE, spectatee.v_angle.y);
- WriteAngle(MSG_ONE, spectatee.v_angle.z);
+ // WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+ //WriteAngle(MSG_ONE, spectatee.v_angle.x);
+ // WriteAngle(MSG_ONE, spectatee.v_angle.y);
+ // WriteAngle(MSG_ONE, spectatee.v_angle.z);
//WriteByte (MSG_ONE, SVC_SETVIEW);
// WriteEntity(MSG_ONE, this);
if(!IS_PLAYER(this.enemy))
return false;
+ ClientData_Touch(this.enemy);
+
msg_entity = this;
WriteByte(MSG_ONE, SVC_SETVIEW);
WriteEntity(MSG_ONE, this.enemy);
- this.movetype = MOVETYPE_NONE;
+ set_movetype(this, MOVETYPE_NONE);
accuracy_resend(this);
if(!SpectateUpdate(this))
// WEAPONTODO
// these are required to fix the spectator bug with arc
- if(old_spectatee && old_spectatee.arc_beam) { old_spectatee.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
- if(this.enemy && this.enemy.arc_beam) { this.enemy.arc_beam.SendFlags |= ARC_SF_SETTINGS; }
+ if(old_spectatee)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(old_spectatee.(weaponentity).arc_beam)
+ old_spectatee.(weaponentity).arc_beam.SendFlags |= ARC_SF_SETTINGS;
+ }
+ }
+ if(this.enemy)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.enemy.(weaponentity).arc_beam)
+ this.enemy.(weaponentity).arc_beam.SendFlags |= ARC_SF_SETTINGS;
+ }
+ }
+
+ // needed to update spectator list
+ if(old_spectatee) { ClientData_Touch(old_spectatee); }
}
bool Spectate(entity this, entity pl)
bool SpectateNext(entity this)
{
- other = find(this.enemy, classname, STR_PLAYER);
+ entity ent = find(this.enemy, classname, STR_PLAYER);
- if (MUTATOR_CALLHOOK(SpectateNext, this, other))
- other = M_ARGV(1, entity);
- else if (!other)
- other = find(other, classname, STR_PLAYER);
+ if (MUTATOR_CALLHOOK(SpectateNext, this, ent))
+ ent = M_ARGV(1, entity);
+ else if (!ent)
+ ent = find(ent, classname, STR_PLAYER);
- if(other) { SetSpectatee(this, other); }
+ if(ent) { SetSpectatee(this, ent); }
return SpectateSet(this);
}
bool SpectatePrev(entity this)
{
// NOTE: chain order is from the highest to the lower entnum (unlike find)
- other = findchain(classname, STR_PLAYER);
- if (!other) // no player
+ entity ent = findchain(classname, STR_PLAYER);
+ if (!ent) // no player
return false;
- entity first = other;
+ entity first = ent;
// skip players until current spectated player
if(this.enemy)
- while(other && other != this.enemy)
- other = other.chain;
+ while(ent && ent != this.enemy)
+ ent = ent.chain;
- switch (MUTATOR_CALLHOOK(SpectatePrev, this, other, first))
+ switch (MUTATOR_CALLHOOK(SpectatePrev, this, ent, first))
{
case MUT_SPECPREV_FOUND:
- other = M_ARGV(1, entity);
+ ent = M_ARGV(1, entity);
break;
case MUT_SPECPREV_RETURN:
- other = M_ARGV(1, entity);
return true;
case MUT_SPECPREV_CONTINUE:
default:
{
- if(other.chain)
- other = other.chain;
+ if(ent.chain)
+ ent = ent.chain;
else
- other = first;
+ ent = first;
break;
}
}
- SetSpectatee(this, other);
+ SetSpectatee(this, ent);
return SpectateSet(this);
}
{
TRANSMUTE(Player, this);
+ SetSpectatee(this, NULL);
+
if(autocvar_g_campaign || autocvar_g_balance_teams)
{ JoinBestTeam(this, false, true); }
Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_PREVENT_JOIN);
- WITHSELF(this, PutClientInServer());
+ PutClientInServer(this);
if(IS_PLAYER(this)) { Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && this.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), this.netname); }
}
MinigameImpulse(this, this.impulse);
this.impulse = 0;
}
- float prefered_movetype;
if (this.flags & FL_JUMPRELEASED) {
if (PHYS_INPUT_BUTTON_JUMP(this) && !this.version_mismatch) {
this.flags &= ~FL_JUMPRELEASED;
TRANSMUTE(Spectator, this);
}
} else {
- prefered_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? this.cvar_cl_clippedspectating : !this.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
- if (this.movetype != prefered_movetype)
- this.movetype = prefered_movetype;
+ int preferred_movetype = ((!PHYS_INPUT_BUTTON_USE(this) ? this.cvar_cl_clippedspectating : !this.cvar_cl_clippedspectating) ? MOVETYPE_FLY_WORLDONLY : MOVETYPE_NOCLIP);
+ set_movetype(this, preferred_movetype);
}
} else {
if (!(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this))) {
{
if(MinigameImpulse(this, this.impulse))
this.impulse = 0;
+
+ if (this.impulse == IMP_weapon_drop.impulse)
+ {
+ STAT(CAMERA_SPECTATOR, this) = (STAT(CAMERA_SPECTATOR, this) + 1) % 3;
+ this.impulse = 0;
+ return;
+ }
}
if (this.flags & FL_JUMPRELEASED) {
if (PHYS_INPUT_BUTTON_JUMP(this) && !this.version_mismatch) {
TRANSMUTE(Spectator, this);
} else {
TRANSMUTE(Observer, this);
- WITHSELF(this, PutClientInServer());
+ PutClientInServer(this);
}
this.impulse = 0;
} else if(this.impulse == 12 || this.impulse == 16 || this.impulse == 19 || (this.impulse >= 220 && this.impulse <= 229)) {
TRANSMUTE(Spectator, this);
} else {
TRANSMUTE(Observer, this);
- WITHSELF(this, PutClientInServer());
+ PutClientInServer(this);
}
this.impulse = 0;
} else if (PHYS_INPUT_BUTTON_ATCK2(this)) {
this.flags &= ~FL_JUMPRELEASED;
TRANSMUTE(Observer, this);
- WITHSELF(this, PutClientInServer());
+ PutClientInServer(this);
} else {
if(!SpectateUpdate(this))
PutObserverInServer(this);
while(head) // find the closest acceptable target to enter
{
- if(head.vehicle_flags & VHF_ISVEHICLE)
+ if(IS_VEHICLE(head))
if(!IS_DEAD(head))
if(!head.owner || ((head.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(head.owner, this)))
if(head.takedamage != DAMAGE_NO)
.float usekeypressed;
.float last_vehiclecheck;
.int items_added;
-void PlayerPreThink ()
-{ENGINE_EVENT();
+void PlayerPreThink (entity this)
+{
WarpZone_PlayerPhysics_FixVAngle(this);
STAT(GAMESTARTTIME, this) = game_starttime;
if(autocvar_g_vehicles_enter && (time > this.last_vehiclecheck) && !gameover && !this.vehicle)
if(IS_PLAYER(this) && !STAT(FROZEN, this) && !IS_DEAD(this))
{
- FOREACH_ENTITY_FLAGS(vehicle_flags, VHF_ISVEHICLE,
+ FOREACH_ENTITY_RADIUS(this.origin, autocvar_g_vehicles_enter_radius, IS_VEHICLE(it),
{
if(!IS_DEAD(it) && it.takedamage != DAMAGE_NO)
- if(vdist(it.origin - this.origin, <, autocvar_g_vehicles_enter_radius))
if((it.vehicle_flags & VHF_MULTISLOT) && SAME_TEAM(it.owner, this))
{
Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_GUNNER);
{
if(!it.team || SAME_TEAM(this, it))
Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER);
- }
- else if(autocvar_g_vehicles_steal)
- {
- Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_STEAL);
+ else if(autocvar_g_vehicles_steal)
+ Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_VEHICLE_ENTER_STEAL);
}
});
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));
- if (this.deadflag == DEAD_DYING) {
- if ((this.respawn_flags & RESPAWN_FORCE) && !(this.respawn_time < this.respawn_time_max)) {
- this.deadflag = DEAD_RESPAWNING;
- } else if (!button_pressed) {
- this.deadflag = DEAD_DEAD;
- }
- } else if (this.deadflag == 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;
- }
- } else if (this.deadflag == DEAD_RESPAWNABLE) {
- if (!button_pressed) {
- this.deadflag = DEAD_RESPAWNING;
- }
- } else if (this.deadflag == 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);
+ 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 || (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;
}
}
this.prevorigin = this.origin;
bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
- .entity weaponentity = weaponentities[0]; // TODO: unhardcode
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;
- } else if ((PS(this).m_weapon == WEP_SHOTGUN || PS(this).m_weapon == WEP_SHOCKWAVE) && this.(weaponentity).wframe == WFRAME_FIRE2 && time < this.(weaponentity).weapon_nextthink) {
- // WEAPONTODO: predict
- do_crouch = false;
}
if (do_crouch) {
{
this.items &= ~this.items_added;
- W_WeaponFrame(this);
+ //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ //{
+ //.entity weaponentity = weaponentities[slot];
+ //W_WeaponFrame(this, weaponentity);
+ //}
+ .entity weaponentity = weaponentities[0]; // TODO
+ W_WeaponFrame(this, weaponentity);
this.items_added = 0;
if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
entity e = this.teamkill_soundsource;
entity oldpusher = e.pusher;
e.pusher = this;
- PlayerSound(e, playersound_teamshoot, CH_VOICE, VOICETYPE_LASTATTACKER_ONLY);
+ 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;
- PlayerSound(this, playersound_taunt, CH_VOICE, VOICETYPE_AUTOTAUNT);
+ PlayerSound(this, playersound_taunt, CH_VOICE, VOL_BASEVOICE, VOICETYPE_AUTOTAUNT);
}
target_voicescript_next(this);
if(IS_DEAD(this))
return;
- if (this.waterlevel != WATERLEVEL_SUBMERGED)
+ if (this.waterlevel != WATERLEVEL_SUBMERGED || this.vehicle)
{
if(this.air_finished < time)
- PlayerSound(this, playersound_gasp, CH_PLAYER, VOICETYPE_PLAYERSOUND);
+ PlayerSound(this, playersound_gasp, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
this.air_finished = time + autocvar_g_balance_contents_drowndelay;
this.dmg = 2;
}
}
}
+.bool move_qcphysics;
+
+void Player_Physics(entity this)
+{
+ set_movetype(this, ((this.move_qcphysics) ? MOVETYPE_NONE : this.move_movetype));
+
+ if(!this.move_qcphysics)
+ return;
+
+ int mt = this.move_movetype;
+
+ if(mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH || mt == MOVETYPE_PHYSICS)
+ {
+ this.move_qcphysics = false;
+ set_movetype(this, mt);
+ return;
+ }
+
+ if(!frametime && !this.pm_frametime)
+ return;
+
+ Movetype_Physics_NoMatchTicrate(this, this.pm_frametime, true);
+
+ this.pm_frametime = 0;
+}
+
/*
=============
PlayerPostThink
=============
*/
.float idlekick_lasttimeleft;
-void PlayerPostThink ()
-{ENGINE_EVENT();
+void PlayerPostThink (entity this)
+{
+ Player_Physics(this);
+
if (sv_maxidle > 0)
if (frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
if (IS_REAL_CLIENT(this))
if (IS_PLAYER(this) || sv_maxidle_spectatorsareidle)
{
- if (time - this.parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
+ int totalClients = 0;
+ if(sv_maxidle_slots > 0)
+ {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) || sv_maxidle_slots_countbots,
+ {
+ ++totalClients;
+ });
+ }
+
+ 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
{
if (this.idlekick_lasttimeleft)
{