PERL ?= perl
QCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"'
QCC ?= gmqcc
+NDEBUG ?= 1
QCCVERSIONFILE := qccversion.$(shell (cd server && $(QCC) --version) > qccversion.txt && git hash-object qccversion.txt)
-fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
-frelaxed-switch -freturn-assignments \
$(QCCFLAGS_WATERMARK) \
- -DNDEBUG=1 \
+ -DNDEBUG=$(NDEBUG) \
$(QCCFLAGS_FEATURES) \
$(QCCFLAGS_EXTRA)
}
plyr.(weaponentity).weapons = plyr.weapons;
- plyr.(weaponentity).switchweapon = plyr.weapon;
+ plyr.(weaponentity).m_switchweapon = Weapons_from(plyr.weapon);
plyr.weapons = WEPSET(NEXBALL);
setself(plyr);
Weapon w = WEP_NEXBALL;
w.wr_resetplayer(w);
- plyr.switchweapon = WEP_NEXBALL.m_id;
+ PS(plyr).m_switchweapon = WEP_NEXBALL;
W_SwitchWeapon(WEP_NEXBALL);
setself(this);
}
self.weapons = self.(weaponentity).weapons;
Weapon w = WEP_NEXBALL;
w.wr_resetplayer(w);
- self.switchweapon = self.(weaponentity).switchweapon;
- W_SwitchWeapon(Weapons_from(self.switchweapon));
+ PS(self).m_switchweapon = self.(weaponentity).m_switchweapon;
+ W_SwitchWeapon(PS(self).m_switchweapon);
self.(weaponentity).weapons = '0 0 0';
}
if(self.buffs & BUFF_AMMO.m_itemid)
if(self.clip_size)
- self.clip_load = self.(weapon_load[self.switchweapon]) = self.clip_size;
+ self.clip_load = self.(weapon_load[PS(self).m_switchweapon.m_id]) = self.clip_size;
if((self.buffs & BUFF_INVISIBLE.m_itemid) && (self.oldbuffs & BUFF_INVISIBLE.m_itemid))
if(self.alpha != autocvar_g_buffs_invisible_alpha)
if(self.clip_load)
self.buff_ammo_prev_clipload = self.clip_load;
- self.clip_load = self.(weapon_load[self.switchweapon]) = self.clip_size;
+ self.clip_load = self.(weapon_load[PS(self).m_switchweapon.m_id]) = self.clip_size;
}
BUFF_ONREM(BUFF_AMMO)
e.ammo_fuel = start_ammo_fuel;
e.weapons = start_weapons;
if(!client_hasweapon(e, Weapons_from(e.weapon), true, false))
- e.switchweapon = w_getbestweapon(self);
+ PS(e).m_switchweapon = w_getbestweapon(self);
}
}
self.weapons |= WEPSET(BLASTER);
self.weapons |= e.m_wepset;
- if(self.switchweapon != nix_weapon)
- if(!client_hasweapon(self, Weapons_from(self.switchweapon), true, false))
+ Weapon w = Weapons_from(nix_weapon);
+ if(PS(self).m_switchweapon != w)
+ if(!client_hasweapon(self, PS(self).m_switchweapon, true, false))
{
- Weapon w = Weapons_from(nix_weapon);
if(client_hasweapon(self, w, true, false))
W_SwitchWeapon(w);
}
if(!thiswep.wr_checkammo1(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
e.velocity = '0 0 200' + normalize(targ.origin - self.origin) * 500;
SUB_SetFade(e, time + 5, 1);
- this.ok_lastwep = this.switchweapon;
+ this.ok_lastwep = PS(this).m_switchweapon.m_id;
return false;
}
if(self.ok_lastwep)
{
- self.switchweapon = self.ok_lastwep;
+ PS(self).m_switchweapon = Weapons_from(self.ok_lastwep);
self.ok_lastwep = 0;
}
if(self.ok_use_ammocharge)
if(!ok_CheckWeaponCharge(self, self.weapon))
{
- if(autocvar_g_overkill_ammo_charge_notice && time > self.ok_notice_time && self.BUTTON_ATCK && IS_REAL_CLIENT(self) && self.weapon == self.switchweapon)
+ if(autocvar_g_overkill_ammo_charge_notice && time > self.ok_notice_time && self.BUTTON_ATCK && IS_REAL_CLIENT(self) && self.weapon == PS(self).m_switchweapon.m_id)
{
//Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERKILL_CHARGE);
self.ok_notice_time = time + 2;
{SELFPARAM();
for(int j = WEP_FIRST; j <= WEP_LAST; ++j)
if(self.weapons & WepSet_FromWeapon(Weapons_from(j)))
- if(self.switchweapon != j)
+ if(PS(self).m_switchweapon.m_id != j)
if(W_IsWeaponThrowable(j))
W_ThrowNewWeapon(self, j, false, self.origin + (self.mins + self.maxs) * 0.5, randomvec() * 175 + '0 0 325');
--- /dev/null
+/**
+ * Purpose: common client state, usable on client and server
+ * Client: singleton representing the viewed player
+ * Server: instance per client
+ */
+CLASS(ClientState, Object)
+ ATTRIB(ClientState, m_client, entity, NULL)
+ CONSTRUCTOR(ClientState, entity client)
+ {
+ CONSTRUCT(ClientState);
+ this.m_client = client;
+ }
+ENDCLASS(ClientState)
+
+.ClientState _cs;
+
+#if NDEBUG
+#define CS(this) (this._cs)
+#else
+ClientState CS(entity this) { assert(IS_CLIENT(this)); assert(this._cs); return this._cs; }
+#endif
+
+void ClientState_attach(entity this)
+{
+ this._cs = NEW(ClientState, this);
+}
+
+void ClientState_detach(entity this)
+{
+ remove(CS(this));
+ this._cs = NULL;
+}
+
+
+
+/**
+ * Purpose: common player state, usable on client and server
+ * Client: singleton representing the viewed player
+ * Server: instance per client, clients decoupled from players
+ */
+CLASS(PlayerState, Object)
+ ATTRIB(PlayerState, m_client, entity, NULL)
+ CONSTRUCTOR(PlayerState, entity client)
+ {
+ CONSTRUCT(PlayerState);
+ this.m_client = client;
+ }
+ ATTRIB(PlayerState, m_switchingweapon, Weapon, Weapons_from(-1))
+ ATTRIB(PlayerState, m_switchweapon, Weapon, Weapons_from(-1))
+ ATTRIB(PlayerState, m_weapon, Weapon, Weapons_from(-1))
+ METHOD(PlayerState, ps_push, void(PlayerState this))
+ {
+ STAT(SWITCHWEAPON, this.m_client) = this.m_switchweapon.m_id;
+ }
+ENDCLASS(PlayerState)
+
+.PlayerState _ps;
+#if NDEBUG
+#define PS(this) (this._ps)
+#else
+PlayerState PS(entity this) { assert(IS_CLIENT(this)); return this._ps; }
+#endif
+
+void PlayerState_attach(entity this)
+{
+ LOG_INFO("Attached\n");
+ this._ps = NEW(PlayerState, this);
+}
+
+void PlayerState_detach(entity this)
+{
+ if (!PS(this)) return; // initial connect
+ remove(PS(this));
+ this._ps = NULL;
+}
_player.view_ofs = PL_VIEW_OFS;
_player.event_damage = PlayerDamage;
_player.hud = HUD_NORMAL;
- _player.switchweapon = _vehicle.switchweapon;
+ PS(_player).m_switchweapon = _vehicle.m_switchweapon;
_player.last_vehiclecheck = time + 3;
_player.vehicle_enter_delay = time + 2;
veh.colormap = pl.colormap;
if(veh.tur_head)
veh.tur_head.colormap = pl.colormap;
- veh.switchweapon = pl.switchweapon;
+ veh.m_switchweapon = PS(pl).m_switchweapon;
pl.hud = veh.vehicleid;
pl.PlayerPhysplug = veh.PlayerPhysplug;
player.event_damage = PlayerDamage;
player.hud = HUD_NORMAL;
player.teleportable = TELEPORT_NORMAL;
- player.switchweapon = gunner.switchweapon;
+ PS(player).m_switchweapon = gunner.m_switchweapon;
player.vehicle_enter_delay = time + 2;
fixedmakevectors(vehic.angles);
RemoveGrapplingHook(player);
- gunner.switchweapon = player.switchweapon;
+ gunner.m_switchweapon = PS(player).m_switchweapon;
gunner.vehicle_exit = bumblebee_gunner_exit;
gunner.vehicle_hudmodel.viewmodelforclient = player;
player.BUTTON_ZOOM = 0;
player.BUTTON_CROUCH = 0;
- player.switchweapon = 0;
+ PS(player).m_switchweapon = WEP_Null;
player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
//.int weapon; // current weapon
#ifdef SVQC
-.int switchweapon = _STAT(SWITCHWEAPON);
.int switchingweapon = _STAT(SWITCHINGWEAPON);
#endif
.string weaponname; // name of .weapon
}
if ( self.arc_smoke_sound && ( self.arc_overheat <= time ||
- !( self.BUTTON_ATCK || self.BUTTON_ATCK2 ) ) || self.switchweapon != WEP_ARC.m_id )
+ !( self.BUTTON_ATCK || self.BUTTON_ATCK2 ) ) || PS(self).m_switchweapon != WEP_ARC )
{
self.arc_smoke_sound = 0;
sound(self, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
{
case 0: // switch to last used weapon
{
- if(actor.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
+ if(PS(actor).m_switchweapon == WEP_BLASTER) // don't do this if already switching
W_LastWeapon();
break;
}
{
// ran out of ammo!
actor.cnt = WEP_CRYLINK.m_id;
- actor.switchweapon = w_getbestweapon(actor);
+ PS(actor).m_switchweapon = w_getbestweapon(actor);
}
}
}
self.realowner.cnt = WEP_DEVASTATOR.m_id;
int slot = 0; // TODO: unhardcode
ATTACK_FINISHED(self.realowner, slot) = time;
- self.realowner.switchweapon = w_getbestweapon(self.realowner);
+ PS(self.realowner).m_switchweapon = w_getbestweapon(self.realowner);
}
}
remove(self);
self.realowner.cnt = WEP_DEVASTATOR.m_id;
int slot = weaponslot(weaponentity);
ATTACK_FINISHED(self.realowner, slot) = time;
- self.realowner.switchweapon = w_getbestweapon(self.realowner);
+ PS(self.realowner).m_switchweapon = w_getbestweapon(self.realowner);
}
}
remove(self);
actor.rl_release = 1;
if(fire & 2)
- if(actor.switchweapon == WEP_DEVASTATOR.m_id)
+ if(PS(actor).m_switchweapon == WEP_DEVASTATOR)
{
entity rock;
bool rockfound = false;
// weapon frames
void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- if(actor.weapon != actor.switchweapon) // abort immediately if switching
+ if(actor.weapon != PS(actor).m_switchweapon.m_id) // abort immediately if switching
{
w_ready(thiswep, actor, weaponentity, fire);
return;
if(!thiswep.wr_checkammo1(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
{
actor.ammo_fuel = 0;
actor.hook_state |= HOOK_REMOVING;
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
}
}
}
// weapon frames
void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- if(actor.weapon != actor.switchweapon) // abort immediately if switching
+ if(actor.weapon != PS(actor).m_switchweapon.m_id) // abort immediately if switching
{
w_ready(thiswep, actor, weaponentity, fire);
return;
if(!thiswep.wr_checkammo2(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
if(!thiswep.wr_checkammo1(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
if(!thiswep.wr_checkammo2(thiswep))
if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
self.cnt = WEP_MINE_LAYER.m_id;
int slot = 0; // TODO: unhardcode
ATTACK_FINISHED(self, slot) = time;
- self.switchweapon = w_getbestweapon(self);
+ PS(self).m_switchweapon = w_getbestweapon(self);
}
setself(this);
}
self.cnt = WEP_MINE_LAYER.m_id;
int slot = 0; // TODO: unhardcode
ATTACK_FINISHED(self, slot) = time;
- self.switchweapon = w_getbestweapon(self);
+ PS(self).m_switchweapon = w_getbestweapon(self);
}
setself(this);
}
.float rifle_bullethail_refire;
void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- float r, sw, af;
+ float r, af;
- sw = actor.switchweapon; // make it not detect weapon changes as reason to abort firing
+ Weapon sw = PS(actor).m_switchweapon; // make it not detect weapon changes as reason to abort firing
int slot = weaponslot(weaponentity);
af = ATTACK_FINISHED(actor, slot);
- actor.switchweapon = actor.weapon;
+ PS(actor).m_switchweapon = Weapons_from(actor.weapon);
ATTACK_FINISHED(actor, slot) = time;
r = weapon_prepareattack(thiswep, actor, weaponentity, actor.rifle_bullethail_frame == WFRAME_FIRE2, actor.rifle_bullethail_refire);
- if(actor.switchweapon == actor.weapon)
- actor.switchweapon = sw;
+ if(PS(actor).m_switchweapon.m_id == actor.weapon)
+ PS(actor).m_switchweapon = sw;
if(r)
{
actor.rifle_bullethail_attackfunc();
entity oldenemy;
self.cnt = self.cnt - 1;
- if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id))
+ if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (PS(self.realowner).m_switchweapon != WEP_SEEKER))
{
remove(self);
return;
void W_Seeker_Tracker_Think()
{SELFPARAM();
// commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
- if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id)
+ if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (PS(self.realowner).m_switchweapon != WEP_SEEKER)
|| (time > self.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime)))
{
if(self)
if (!thiswep.wr_checkammo2(thiswep))
if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
if (!thiswep.wr_checkammo2(thiswep))
if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
{
- W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w_ready(thiswep, actor, weaponentity, fire);
return;
}
#define MACRO_END } while (0)
#endif
+#define _CAT(a, b) a ## b
+#define CAT(a, b) _CAT(a, b)
+
#endif
#define _STAT(id) g_stat_##id
#define REGISTER_STAT_2(id, T) \
T _STAT(id); \
+ T CAT(_STAT(id), _prev); \
REGISTER(Stats, STAT_##id, m_id, new(stat)) \
{ \
make_pure(this); \
} \
[[accumulate]] void stats_get() \
{ \
- _STAT(id) = getstat_##T(STAT_##id.m_id); \
+ T it = getstat_##T(STAT_##id.m_id); \
+ if (it != CAT(_STAT(id), _prev)) _STAT(id) = it; \
}
#define REGISTER_STAT_3(x, T, expr) REGISTER_STAT(x, T)
#elif defined(SVQC)
#define FOR_EACH_OBSERVER(v) FOR_EACH_CLIENT(v) if (IS_OBSERVER(v))
#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if (IS_PLAYER(v))
+#define FOREACH_CLIENT(cond, body) \
+ MACRO_BEGIN { \
+ int i = 0; \
+ for (entity it = NULL; (it = nextent(it)) && (num_for_edict(it) <= maxclients); ++i) \
+ { \
+ if (!IS_CLIENT(it)) continue; \
+ if (cond) { LAMBDA(body) } \
+ } \
+ } MACRO_END
+
#define FOR_EACH_MONSTER(v) for (v = world; (v = findflags(v, flags, FL_MONSTER)) != world; )
#include "../common/effects/all.qh"
{
entity e = Weapons_from(i);
if ((self.weapons & (e.m_wepset)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
- self.switchweapon = i;
+ PS(self).m_switchweapon = Weapons_from(i);
}
}
}
return;
}
- self.switchweapon = WEP_DEVASTATOR.m_id;
+ PS(self).m_switchweapon = WEP_DEVASTATOR;
self.v_angle_x = 90;
self.BUTTON_ATCK = true;
self.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
// ;)
if(g_weaponarena_weapons == WEPSET(TUBA))
{
- self.switchweapon = WEP_TUBA.m_id;
+ PS(self).m_switchweapon = WEP_TUBA;
return;
}
{
if(client_hasweapon(self, Weapons_from(i), true, false))
{
- self.switchweapon = i;
+ PS(self).m_switchweapon = Weapons_from(i);
return;
}
}
{
if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
continue;
- self.switchweapon = w;
+ PS(self).m_switchweapon = Weapons_from(w);
return;
}
}
{
if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
continue;
- self.switchweapon = w;
+ PS(self).m_switchweapon = Weapons_from(w);
return;
}
}
{
if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
continue;
- self.switchweapon = w;
+ PS(self).m_switchweapon = Weapons_from(w);
return;
}
}
return CMD_STATUS_ERROR;
if(client_hasweapon(self, Weapons_from(id), true, false))
- self.switchweapon = id;
+ PS(self).m_switchweapon = Weapons_from(id);
else
return CMD_STATUS_ERROR;
#include "bot/navigation.qh"
#include "../common/ent_cs.qh"
-#include "../common/vehicles/all.qh"
+#include "../common/state.qh"
+
#include "../common/triggers/teleporters.qh"
+#include "../common/vehicles/all.qh"
+
#include "weapons/hitplot.qh"
#include "weapons/weaponsystem.qh"
*/
void FixPlayermodel(entity player);
void PutObserverInServer()
-{SELFPARAM();
+{
+ SELFPARAM();
+ PlayerState_detach(this);
entity spot;
self.hud = HUD_NORMAL;
if (IS_OBSERVER(this)) {
PutObserverInServer();
} else if (IS_PLAYER(this)) {
+ PlayerState_attach(this);
accuracy_resend(this);
if (this.team < 0)
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;
this.weaponname = "";
*/
void DecodeLevelParms ();
void ClientConnect ()
-{SELFPARAM();
+{
+ SELFPARAM();
+ ClientState_attach(this);
float t;
if(IS_CLIENT(self))
.entity chatbubbleentity;
void ReadyCount();
void ClientDisconnect ()
-{SELFPARAM();
+{
+ SELFPARAM();
+ ClientState_detach(this);
if(self.vehicle)
vehicles_exit(VHEF_RELEASE);
self.invincible_finished = spectatee.invincible_finished;
self.pressedkeys = spectatee.pressedkeys;
self.weapons = spectatee.weapons;
- self.switchweapon = spectatee.switchweapon;
+ PS(self).m_switchweapon = PS(spectatee).m_switchweapon;
self.switchingweapon = spectatee.switchingweapon;
self.weapon = spectatee.weapon;
self.vortex_charge = spectatee.vortex_charge;
{
if (this.vehicle) return;
if (this.deadflag != DEAD_NO) return;
- W_SwitchWeapon(Weapons_from(w_getbestweapon(this)));
+ W_SwitchWeapon(w_getbestweapon(this));
}
IMPULSE(weapon_drop)
// clear waypoints
WaypointSprite_PlayerDead();
// throw a weapon
- SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, self.switchweapon);
+ SpawnThrownWeapon (self.origin + (self.mins + self.maxs) * 0.5, PS(self).m_switchweapon.m_id);
// become fully visible
self.alpha = default_player_alpha;
// after a frag, choose another random weapon set
if (!(attacker.weapons & WepSet_FromWeapon(Weapons_from(attacker.weapon))))
- W_SwitchWeapon_Force(attacker, Weapons_from(w_getbestweapon(attacker)));
+ W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
}
// FIXME fix the mess this is (we have REAL points now!)
setself(e_);
antilag_record(e_, altime);
}
+ FOREACH_CLIENT(PS(it), PS(it).ps_push(PS(it)));
}
case "l": replacement = NearestLocation(self.origin); break;
case "y": replacement = NearestLocation(cursor); break;
case "d": replacement = NearestLocation(self.death_origin); break;
- case "w": replacement = WEP_NAME(((!self.weapon) ? (!self.switchweapon ? self.cnt : self.switchweapon) : self.weapon)); break;
+ case "w": replacement = WEP_NAME(((!self.weapon) ? (!PS(self).m_switchweapon.m_id ? self.cnt : PS(self).m_switchweapon.m_id) : self.weapon)); break;
case "W": replacement = ammoitems; break;
case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
case "s": replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1')); break;
self.weaponorder_byimpulse = strzone(W_FixWeaponOrder_BuildImpulseList(o));
return o;
}
-void GetCvars(float f)
+
+/**
+ * @param f -1: cleanup, 0: request, 1: receive
+ */
+void GetCvars(int f)
{SELFPARAM();
string s = string_null;
if (f > 0)
{
if (s == "cl_weaponpriority")
- self.switchweapon = w_getbestweapon(self);
+ if (PS(self)) PS(self).m_switchweapon = w_getbestweapon(self);
if (s == "cl_allow_uidtracking")
PlayerStats_GameReport_AddPlayer(self);
}
PLAYERDEMO_FIELD(func,string,playerskin) \
PLAYERDEMO_FIELD(func,float,frame) \
PLAYERDEMO_FIELD(func,float,effects) \
- PLAYERDEMO_FIELD(func,float,switchweapon) \
+ /* PLAYERDEMO_FIELD(func,float,switchweapon) */ \
PLAYERDEMO_FIELD(func,float,BUTTON_ATCK) \
PLAYERDEMO_FIELD(func,float,BUTTON_ATCK2) \
PLAYERDEMO_FIELD(func,float,BUTTON_CROUCH) \
// if the player is using their best weapon before items are given, they
// probably want to switch to an even better weapon after items are given
if (player.autoswitch)
- if (player.switchweapon == w_getbestweapon(player))
+ if (PS(player).m_switchweapon == w_getbestweapon(player))
_switchweapon = true;
- if (!(player.weapons & WepSet_FromWeapon(Weapons_from(player.switchweapon))))
+ if (!(player.weapons & WepSet_FromWeapon(PS(player).m_switchweapon)))
_switchweapon = true;
pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
}
if (_switchweapon)
- if (player.switchweapon != w_getbestweapon(player))
- W_SwitchWeapon_Force(player, Weapons_from(w_getbestweapon(player)));
+ if (PS(player).m_switchweapon != w_getbestweapon(player))
+ W_SwitchWeapon_Force(player, w_getbestweapon(player));
return 1;
}
_switchweapon = false;
if (e.autoswitch)
- if (e.switchweapon == w_getbestweapon(e))
+ if (PS(e).m_switchweapon == w_getbestweapon(e))
_switchweapon = true;
e.strength_finished = max(0, e.strength_finished - time);
else
e.superweapons_finished += time;
- if (!(e.weapons & WepSet_FromWeapon(Weapons_from(e.switchweapon))))
+ if (!(e.weapons & WepSet_FromWeapon(PS(e).m_switchweapon)))
_switchweapon = true;
if(_switchweapon)
- W_SwitchWeapon_Force(e, Weapons_from(w_getbestweapon(e)));
+ W_SwitchWeapon_Force(e, w_getbestweapon(e));
return got;
}
antilag_takeback(trace_ent, time - lag);
hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos);
antilag_restore(trace_ent);
- fputs(player.hitplotfh, strcat(ftos(hitplot.x), " ", ftos(hitplot.y), " ", ftos(hitplot.z), " ", ftos(player.switchweapon), "\n"));
+ fputs(player.hitplotfh, strcat(ftos(hitplot.x), " ", ftos(hitplot.y), " ", ftos(hitplot.z), " ", ftos(PS(player).m_switchweapon.m_id), "\n"));
//print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n"));
}
}
entity wep;
if(skipmissing || pl.selectweapon == 0)
- weaponcur = pl.switchweapon;
+ weaponcur = PS(pl).m_switchweapon.m_id;
else
weaponcur = pl.selectweapon;
void W_SwitchWeapon_Force(entity e, Weapon wep)
{
- int w = wep.m_id;
- e.cnt = e.switchweapon;
- e.switchweapon = w;
- e.selectweapon = w;
+ e.cnt = PS(e).m_switchweapon.m_id;
+ PS(e).m_switchweapon = wep;
+ e.selectweapon = wep.m_id;
}
// perform weapon to attack (weaponstate and attack_finished check is here)
void W_SwitchToOtherWeapon(entity pl)
{
// hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
- int ww;
+ Weapon ww;
WepSet set = WepSet_FromWeapon(Weapons_from(pl.weapon));
if(pl.weapons & set)
{
else
ww = w_getbestweapon(pl);
if(ww)
- W_SwitchWeapon_Force(pl, Weapons_from(ww));
+ W_SwitchWeapon_Force(pl, ww);
}
void W_SwitchWeapon(Weapon w)
{SELFPARAM();
- int imp = w.m_id;
- if (self.switchweapon != imp)
+ if (PS(self).m_switchweapon != w)
{
if (client_hasweapon(self, w, true, true))
W_SwitchWeapon_Force(self, w);
else
- self.selectweapon = imp; // update selectweapon ANYWAY
+ self.selectweapon = w.m_id; // update selectweapon ANYWAY
}
else if(!forbidWeaponUse(self)) {
w.wr_reload(w);
.int weaponcomplainindex;
float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing);
-#define w_getbestweapon(ent) W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true)
+#define w_getbestweapon(ent) Weapons_from(W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true))
void W_SwitchWeapon_Force(entity e, Weapon w);
if(!(self.weapons & set)) return;
self.weapons &= ~set;
- W_SwitchWeapon_Force(self, Weapons_from(w_getbestweapon(self)));
+ W_SwitchWeapon_Force(self, w_getbestweapon(self));
string a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
if(!a) return;
if (thiswep == WEP_SHOTGUN)
if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false; // no clicking, just allow
- if (thiswep == Weapons_from(actor.switchweapon) && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+ if (thiswep == PS(actor).m_switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
{
sound(actor, CH_WEAPON_A, SND_DRYFIRE, VOL_BASE, ATTEN_NORM);
actor.prevdryfire = time;
return false;
// do not even think about shooting if switching
- if (actor.switchweapon != actor.weapon) return false;
+ if (PS(actor).m_switchweapon.m_id != actor.weapon) return false;
if (attacktime >= 0)
{
}
}
- if (actor.switchweapon == 0)
+ if (PS(actor).m_switchweapon.m_id == 0)
{
actor.weapon = 0;
actor.switchingweapon = 0;
vector up = v_up;
// Change weapon
- if (actor.weapon != actor.switchweapon)
+ if (actor.weapon != PS(actor).m_switchweapon.m_id)
{
switch (this.state)
{
case WS_CLEAR:
{
// end switching!
- actor.switchingweapon = actor.switchweapon;
- entity newwep = Weapons_from(actor.switchweapon);
+ Weapon newwep = PS(actor).m_switchweapon;
+ actor.switchingweapon = newwep.m_id;
// the two weapon entities will notice this has changed and update their models
- actor.weapon = actor.switchweapon;
+ actor.weapon = newwep.m_id;
actor.weaponname = newwep.mdl;
actor.bulletcounter = 0;
actor.ammo_field = newwep.ammo_field;
// set our clip load to the load of the weapon we switched to, if it's reloadable
if ((newwep.spawnflags & WEP_FLAG_RELOADABLE) && newwep.reloading_ammo) // prevent accessing undefined cvars
{
- actor.clip_load = actor.(weapon_load[actor.switchweapon]);
+ actor.clip_load = actor.(weapon_load[PS(actor).m_switchweapon.m_id]);
actor.clip_size = newwep.reloading_ammo;
}
else
case WS_DROP:
{
// in dropping phase we can switch at any time
- actor.switchingweapon = actor.switchweapon;
+ actor.switchingweapon = PS(actor).m_switchweapon.m_id;
break;
}
case WS_READY:
{
// start switching!
- actor.switchingweapon = actor.switchweapon;
+ actor.switchingweapon = PS(actor).m_switchweapon.m_id;
entity oldwep = Weapons_from(actor.weapon);
// set up weapon switch think in the future, and start drop anim
{
if (w && !(actor.weapons & WepSet_FromWeapon(Weapons_from(w))))
{
- if (actor.weapon == actor.switchweapon) W_SwitchWeapon_Force(actor, Weapons_from(w_getbestweapon(actor)));
+ if (actor.weapon == PS(actor).m_switchweapon.m_id) W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
w = 0;
}
}
else
{
- if (key_pressed && actor.switchweapon != WEP_HOOK.m_id && !actor.hook_switchweapon)
+ if (key_pressed && PS(actor).m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
W_SwitchWeapon(WEP_HOOK);
actor.hook_switchweapon = key_pressed;
Weapon h = WEP_HOOK;