]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Weapons: store switchweapon as direct weapon reference
authorTimePath <andrew.hardaker1995@gmail.com>
Sat, 12 Dec 2015 08:04:10 +0000 (19:04 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sat, 12 Dec 2015 08:04:10 +0000 (19:04 +1100)
41 files changed:
qcsrc/Makefile
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/mutators/mutator/buffs/buffs.qc
qcsrc/common/mutators/mutator/nix/nix.qc
qcsrc/common/mutators/mutator/overkill/hmg.qc
qcsrc/common/mutators/mutator/overkill/overkill.qc
qcsrc/common/mutators/mutator/pinata/pinata.qc
qcsrc/common/state.qh [new file with mode: 0644]
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/vehicle/bumblebee.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/lib/macro.qh
qcsrc/lib/stats.qh
qcsrc/server/_all.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/bot/scripting.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_impulse.qc
qcsrc/server/cl_player.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/playerdemo.qc
qcsrc/server/t_items.qc
qcsrc/server/weapons/hitplot.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/selection.qh
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/weaponsystem.qc

index b49ebbe04268a71edbb53e7180c5e8c12bfd22f7..d332a0413789e72e4f4201c0203fef10d0519069 100644 (file)
@@ -2,6 +2,7 @@ SCM := $(shell if [ -d .svn ]; then echo svn; elif [ -d ../.git ]; then echo git
 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)
 
@@ -22,7 +23,7 @@ QCCFLAGS ?= \
        -fftepp -flno -futf8 -fno-bail-on-werror -fftepp-predefs \
        -frelaxed-switch -freturn-assignments \
        $(QCCFLAGS_WATERMARK) \
-       -DNDEBUG=1 \
+       -DNDEBUG=$(NDEBUG) \
        $(QCCFLAGS_FEATURES) \
        $(QCCFLAGS_EXTRA)
 
index 2206df7c695d00ae25f493fbdd9f4eadeacf6121..0d56d37155b0359113d2e096e83619c6568a722d 100644 (file)
@@ -180,12 +180,12 @@ void GiveBall(entity plyr, entity ball)
        }
 
        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);
 }
@@ -971,8 +971,8 @@ MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
                                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';
                        }
index 1c9e3a2177b9f3c07f5822392e0232d4d88ba6e7..37a0573dcf56accbd31d630f2cd280ee842b864e 100644 (file)
@@ -880,7 +880,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
        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)
@@ -902,7 +902,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
                        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)
index 68f4dfaa875236a01d1203d0377852720af3dbed..9043a8399d407c5ce633e75cbf25bf1864ef881d 100644 (file)
@@ -69,7 +69,7 @@ REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"
                        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);
                }
        }
 
@@ -210,10 +210,10 @@ void NIX_GiveCurrentWeapon()
                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);
                }
index e78e9110a70baa56ddf36004fbb89a60a6fa83fb..28b1715e18cd23e348753815ff26e960821716c7 100644 (file)
@@ -65,7 +65,7 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
        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;
        }
index 4ad190d258f439bf44e0319c458aa88418711929..952537e31f979bf5227847abe07d3cb3fdf7c9f0 100644 (file)
@@ -146,7 +146,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDies)
        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;
 }
@@ -186,7 +186,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
 
        if(self.ok_lastwep)
        {
-               self.switchweapon = self.ok_lastwep;
+               PS(self).m_switchweapon = Weapons_from(self.ok_lastwep);
                self.ok_lastwep = 0;
        }
 
@@ -224,7 +224,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
        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;
index 99c1321c1aaa37062f84830272978a5efdaea0fc..d5cbb7fdaeb75b5833aba3266cde6810b2ec6293 100644 (file)
@@ -5,7 +5,7 @@ MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
 {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');
 
diff --git a/qcsrc/common/state.qh b/qcsrc/common/state.qh
new file mode 100644 (file)
index 0000000..84bb946
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * 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;
+}
index 2940b95653399d1c382e0af785055887a9664033..97a6b467ca5e6f3b6e0c82749c3ecf5710dd3b64 100644 (file)
@@ -877,7 +877,7 @@ void vehicles_exit(bool eject)
                _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;
 
@@ -1063,7 +1063,7 @@ void vehicles_enter(entity pl, entity veh)
        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;
 
index 244b4e2f6126e7fbabf9ca5533b4e24405618332..f279e9e2a27f90e701a5fcf97ac13731f53c6e6e 100644 (file)
@@ -261,7 +261,7 @@ void bumblebee_gunner_exit(int _exitflag)
        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);
@@ -330,7 +330,7 @@ bool bumblebee_gunner_enter()
 
        RemoveGrapplingHook(player);
 
-       gunner.switchweapon = player.switchweapon;
+       gunner.m_switchweapon = PS(player).m_switchweapon;
        gunner.vehicle_exit = bumblebee_gunner_exit;
        gunner.vehicle_hudmodel.viewmodelforclient = player;
 
index 9c2305126f307795270d869ce1d2d88fc770d8c1..d817c2e1a23d93702497d54b2db43789f1a8d555 100644 (file)
@@ -88,7 +88,7 @@ float spiderbot_frame()
 
        player.BUTTON_ZOOM        = 0;
        player.BUTTON_CROUCH    = 0;
-       player.switchweapon      = 0;
+       PS(player).m_switchweapon = WEP_Null;
        player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
 
 
index 9bf60e94ab438dd62cdbce7d4e29cad94c96f8df..4c8ede6dcc6286c6e8a583faf26280f1e0df5778 100644 (file)
@@ -332,7 +332,6 @@ STATIC_INIT(register_weapons_done)
 
 //.int weapon; // current weapon
 #ifdef SVQC
-.int switchweapon = _STAT(SWITCHWEAPON);
 .int switchingweapon = _STAT(SWITCHINGWEAPON);
 #endif
 .string weaponname; // name of .weapon
index 13037eb7d4cdc904014d0866094d2d51dc3fb4f2..11d9115f0fadcf3a19db6690ca2afc69aeb113d6 100644 (file)
@@ -629,7 +629,7 @@ void Arc_Smoke()
        }
 
        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);
index 1063a9c66ef111d167723360fef49fd085499ca1..5ae4dd4b9d8f43a609ec2fe34b994c3c57544577 100644 (file)
@@ -191,7 +191,7 @@ void W_Blaster_Attack(
                                {
                                        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;
                                        }
index eb4dbdd87bf1ac079c8f0fd8c28598ef14bbd4a8..56f9bba810335032411318d317b10a7be91fd6c2 100644 (file)
@@ -626,7 +626,7 @@ void W_Crylink_Attack2(Weapon thiswep)
                                        {
                                                // ran out of ammo!
                                                actor.cnt = WEP_CRYLINK.m_id;
-                                               actor.switchweapon = w_getbestweapon(actor);
+                                               PS(actor).m_switchweapon = w_getbestweapon(actor);
                                        }
                                }
                        }
index 25a823788a69bc4338e3074b1ba7d4694c5f40c6..31701c3194bb75ae3419006beacff63c608ec3f1 100644 (file)
@@ -116,7 +116,7 @@ void W_Devastator_Explode()
                        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);
@@ -196,7 +196,7 @@ void W_Devastator_DoRemoteExplode(.entity weaponentity)
                        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);
@@ -545,7 +545,7 @@ void W_Devastator_Attack(Weapon thiswep)
                                        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;
index cebe69450a00386ea084593587299cc29851126c..260f4b00406dcd9ed5eb62450046c0cc5d88709a 100644 (file)
@@ -163,7 +163,7 @@ void W_HLAC_Attack2()
 // 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;
@@ -174,7 +174,7 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
                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;
                }
index 1b6fe5e3dac56f40a3f26af5f718170cb3076e41..a8a76cfd6e5783056a0760bb401a3586bcb95ff0 100644 (file)
@@ -243,7 +243,7 @@ void W_Hook_Attack2(Weapon thiswep, entity actor)
                                                        {
                                                                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));
                                                        }
                                                }
                                        }
index 7805feda829f579bd17b57cb3775cefbf0a42402..8d49f8d7c2b4ec59e59158ef89dc50c1cc305acc 100644 (file)
@@ -141,7 +141,7 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, .entity weaponentity)
 // 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;
@@ -151,7 +151,7 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit
                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;
                }
@@ -177,7 +177,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
        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;
        }
@@ -269,7 +269,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
                                        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;
                                        }
index 0b069ca89578b87557d7b024f381b3c0bce777cd..a9eee99faa89629d3a92a9807cd54131e43c4ada 100644 (file)
@@ -132,7 +132,7 @@ void W_MineLayer_Explode()
                        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);
        }
@@ -159,7 +159,7 @@ void W_MineLayer_DoRemoteExplode()
                        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);
        }
index 59e254990d0db400d2ef69efed698aff4f7dffc4..77f8cb5f23c5fd36d4d64652437248289c734314 100644 (file)
@@ -95,16 +95,16 @@ void W_Rifle_Attack2()
 .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();
index ae6b736df96e68ab8fc018da9967164dac264beb..039414c7b0909718b536dae613d3f75ad0a42054 100644 (file)
@@ -420,7 +420,7 @@ void W_Seeker_Vollycontroller_Think() // TODO: Merge this with W_Seeker_Attack
        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;
@@ -458,7 +458,7 @@ void W_Seeker_Vollycontroller_Think() // TODO: Merge this with W_Seeker_Attack
 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)
index 7b710b21fffdf311aab1dece3f0363dbf2c46d11..bdc592fed880cae56509ebbbaf2200f1e60c2cdf 100644 (file)
@@ -202,7 +202,7 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
        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;
        }
@@ -216,7 +216,7 @@ void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity
        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;
        }
index adcbe3553b03c9816868a1b0cdc2c40dfaf62c10..1301ca4a4e57be35623bed9efbda0bc98a38d9db 100644 (file)
@@ -10,4 +10,7 @@
     #define MACRO_END } while (0)
 #endif
 
+#define _CAT(a, b) a ## b
+#define CAT(a, b) _CAT(a, b)
+
 #endif
index 0d445817e9118f58212a04ab6f743d199a26873d..d1823a77d7d8078e5dbc0704f7996cce63e55a07 100644 (file)
@@ -26,6 +26,7 @@ typedef vector vectori;
        #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); \
@@ -36,7 +37,8 @@ typedef vector vectori;
                } \
                [[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)
index cbda56873aaa9091b3774b298fc6641954f46b0b..a53ab2435ddb67b3f24735ae6a48eb5b8c08c70c 100644 (file)
@@ -29,6 +29,16 @@ const string STR_OBSERVER = "observer";
 #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"
index 8cb4a31689626b812f9fe6b6ade9d437a1eaf8ea..a0a1d78ee6fc1d0ea181ebe37fb6fffc580b4757 100644 (file)
@@ -175,7 +175,7 @@ void havocbot_ai()
                        {
                                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);
                        }
                }
        }
@@ -617,7 +617,7 @@ void havocbot_movetogoal()
                                        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);
@@ -1014,7 +1014,7 @@ void havocbot_chooseweapon()
        // ;)
        if(g_weaponarena_weapons == WEPSET(TUBA))
        {
-               self.switchweapon = WEP_TUBA.m_id;
+               PS(self).m_switchweapon = WEP_TUBA;
                return;
        }
 
@@ -1027,7 +1027,7 @@ void havocbot_chooseweapon()
                {
                        if(client_hasweapon(self, Weapons_from(i), true, false))
                        {
-                               self.switchweapon = i;
+                               PS(self).m_switchweapon = Weapons_from(i);
                                return;
                        }
                }
@@ -1075,7 +1075,7 @@ void havocbot_chooseweapon()
                                {
                                        if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
                                                continue;
-                                       self.switchweapon = w;
+                                       PS(self).m_switchweapon = Weapons_from(w);
                                        return;
                                }
                        }
@@ -1089,7 +1089,7 @@ void havocbot_chooseweapon()
                                {
                                        if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
                                                continue;
-                                       self.switchweapon = w;
+                                       PS(self).m_switchweapon = Weapons_from(w);
                                        return;
                                }
                        }
@@ -1102,7 +1102,7 @@ void havocbot_chooseweapon()
                        {
                                if ((self.weapon == w && combo) || havocbot_chooseweapon_checkreload(w))
                                        continue;
-                               self.switchweapon = w;
+                               PS(self).m_switchweapon = Weapons_from(w);
                                return;
                        }
                }
index 96f7af3a1715f1702ec022aedc8baaf0122e6da3..4f14d2f3bb40cf875812664a9738108e9720117a 100644 (file)
@@ -576,7 +576,7 @@ float bot_cmd_select_weapon()
                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;
 
index ad5b5fc9e2562f41b9326aa0f7041a7175abe793..fddaa09cbd422b87acb0258832f1f3bdcb89aaa8 100644 (file)
 #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"
 
@@ -186,7 +189,9 @@ putting a client as observer in the server
 */
 void FixPlayermodel(entity player);
 void PutObserverInServer()
-{SELFPARAM();
+{
+       SELFPARAM();
+       PlayerState_detach(this);
        entity  spot;
     self.hud = HUD_NORMAL;
 
@@ -438,6 +443,7 @@ void PutClientInServer()
        if (IS_OBSERVER(this)) {
                PutObserverInServer();
        } else if (IS_PLAYER(this)) {
+               PlayerState_attach(this);
                accuracy_resend(this);
 
                if (this.team < 0)
@@ -617,7 +623,7 @@ void PutClientInServer()
                        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 = "";
@@ -997,7 +1003,9 @@ Called when a client connects to the server
 */
 void DecodeLevelParms ();
 void ClientConnect ()
-{SELFPARAM();
+{
+       SELFPARAM();
+       ClientState_attach(this);
        float t;
 
        if(IS_CLIENT(self))
@@ -1216,7 +1224,9 @@ Called when a client disconnects from the server
 .entity chatbubbleentity;
 void ReadyCount();
 void ClientDisconnect ()
-{SELFPARAM();
+{
+       SELFPARAM();
+       ClientState_detach(this);
        if(self.vehicle)
            vehicles_exit(VHEF_RELEASE);
 
@@ -1670,7 +1680,7 @@ void SpectateCopy(entity this, entity spectatee)
        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;
index 6598039dc7e85c695edfd5d8693c5bff0baad7d2..1787d540fa1c10612d7de96b8665319ddccd8a54 100644 (file)
@@ -202,7 +202,7 @@ IMPULSE(weapon_best)
 {
        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)
index d7ce1f66aedd85785d6f95b62416b4456e37f66f..f496cf5be8fbec37399dcc9382ec79f51c330032 100644 (file)
@@ -573,7 +573,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, int deathtyp
                // 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;
index 0e23d0828bcab192ddcb421af3834058b8ede882..dfabd9d3dc9758b24fbbe9b0a843c581685bfe4c 100644 (file)
@@ -96,7 +96,7 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 
                // 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!)
index 854282f3dd5cce00d2342b765c5cc5187c36573f..b2570784b5a2cc6b96e3f361dfd2cd8628c7697d 100644 (file)
@@ -1992,6 +1992,7 @@ void EndFrame()
                setself(e_);
                antilag_record(e_, altime);
        }
+       FOREACH_CLIENT(PS(it), PS(it).ps_push(PS(it)));
 }
 
 
index 07dd423dcde4d8c0cac9916aa5642d580a254f2e..bed49addd7c30dbf9d393b96a80370179b8a1444 100644 (file)
@@ -262,7 +262,7 @@ string formatmessage(string msg)
                        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;
@@ -374,7 +374,11 @@ string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
        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;
 
@@ -423,7 +427,7 @@ void GetCvars(float f)
        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);
        }
index 5ca2c1ca99d4450c11ad86b526f23cfaa869ec74..5273a65a7f1062c32548c34874578fdb50fa059d 100644 (file)
@@ -58,7 +58,7 @@ void playerdemo_open_write(string f)
        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) \
index d78194eb46f8ab0f0fbe855cc280adb23f736489..2511c69dcad69696cf46686ded6ac3692cdd1871 100644 (file)
@@ -642,10 +642,10 @@ float Item_GiveTo(entity item, entity player)
        // 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);
@@ -715,8 +715,8 @@ float Item_GiveTo(entity item, entity player)
        }
 
        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;
 }
@@ -1627,7 +1627,7 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        _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);
@@ -1813,10 +1813,10 @@ float GiveItems(entity e, float beginarg, float endarg)
        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;
 }
index ec48c6d3cea09c19bb6498cc9f1c47691c7aad4c..9846443647a921fa99e3effbc1cf669383c1be42 100644 (file)
@@ -71,7 +71,7 @@ void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright,
                        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"));
                }
        }
index 737ddc8adcbf8e2c25ad3e14a1644f9bde97d450..9a2c9fd2bd7b08ab9077968e52d6512b820f45e1 100644 (file)
@@ -123,7 +123,7 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
        entity wep;
 
        if(skipmissing || pl.selectweapon == 0)
-               weaponcur = pl.switchweapon;
+               weaponcur = PS(pl).m_switchweapon.m_id;
        else
                weaponcur = pl.selectweapon;
 
@@ -225,17 +225,16 @@ float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, floa
 
 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)
        {
@@ -246,18 +245,17 @@ void W_SwitchToOtherWeapon(entity pl)
        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);
index 07d8383b11b3a922a0636bd49d1a76175802b780..18e3f5a1c99cb1d62dd03f0656930b36d88ee84e 100644 (file)
@@ -10,7 +10,7 @@ bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain);
 .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);
 
index 829b6ed62e772fc250c0847bd84dc6b5fcd26308..652ec92005aba884ea26c3955b42644fb33a6726 100644 (file)
@@ -182,7 +182,7 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
        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;
index f5f279dff00a9d9d30134dadfbb8ba8848b7117d..0124fa9f5cb08611376e57958fb7ebe573030093 100644 (file)
@@ -222,7 +222,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
        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;
@@ -269,7 +269,7 @@ bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponenti
                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)
        {
@@ -429,7 +429,7 @@ void W_WeaponFrame(entity actor)
                }
        }
 
-       if (actor.switchweapon == 0)
+       if (PS(actor).m_switchweapon.m_id == 0)
        {
                actor.weapon = 0;
                actor.switchingweapon = 0;
@@ -445,7 +445,7 @@ void W_WeaponFrame(entity actor)
        vector up = v_up;
 
        // Change weapon
-       if (actor.weapon != actor.switchweapon)
+       if (actor.weapon != PS(actor).m_switchweapon.m_id)
        {
                switch (this.state)
                {
@@ -458,11 +458,11 @@ void W_WeaponFrame(entity actor)
                        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;
@@ -472,7 +472,7 @@ void W_WeaponFrame(entity actor)
                                // 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
@@ -486,13 +486,13 @@ void W_WeaponFrame(entity actor)
                        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
@@ -520,7 +520,7 @@ void W_WeaponFrame(entity actor)
        {
                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;
                }
 
@@ -538,7 +538,7 @@ void W_WeaponFrame(entity actor)
                        }
                        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;