Add a networked entity to hold weapon state
authorMario <mario@smbclan.net>
Thu, 29 Sep 2016 01:50:28 +0000 (11:50 +1000)
committerMario <mario@smbclan.net>
Thu, 29 Sep 2016 01:50:28 +0000 (11:50 +1000)
74 files changed:
qcsrc/client/_all.qh
qcsrc/client/hud/panel/ammo.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qh
qcsrc/client/view.qc
qcsrc/common/_all.inc
qcsrc/common/_mod.inc
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/monsters/monster.qh
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/monsters/monster/zombie.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
qcsrc/common/mutators/mutator/overkill/hmg.qc
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/mutators/mutator/pinata/sv_pinata.qc
qcsrc/common/state.qc
qcsrc/common/state.qh
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/turrets/turret/machinegun_weapon.qc
qcsrc/common/turrets/turret/plasma.qc
qcsrc/common/turrets/turret/plasma_dual.qc
qcsrc/common/turrets/turret/walker_weapon.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/vehicle/bumblebee.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/weapons/all.qc
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/electro.qc
qcsrc/common/weapons/weapon/hagar.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/mortar.qc
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vortex.qc
qcsrc/common/wepent.qc [new file with mode: 0644]
qcsrc/common/wepent.qh [new file with mode: 0644]
qcsrc/server/bot/default/aim.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/scripting.qc
qcsrc/server/client.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_world.qc
qcsrc/server/impulse.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/player.qc
qcsrc/server/tests.qc
qcsrc/server/weapons/hitplot.qc
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/selection.qh
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/throwing.qh
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/tracing.qh
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh

index 077b5f4..5593af1 100644 (file)
@@ -13,3 +13,4 @@
 #include "miscfunctions.qh"
 
 #include <common/ent_cs.qh>
+#include <common/wepent.qh>
index e299d14..94545ac 100644 (file)
@@ -169,7 +169,9 @@ void HUD_Ammo()
                ammo_size.y = newSize;
        }
 
-       Weapon wep = switchweapon;
+       entity wepent = viewmodels[0]; // TODO: unhardcode
+
+       Weapon wep = wepent.switchweapon;
        int i;
        bool infinite_ammo = (STAT(ITEMS) & IT_UNLIMITED_WEAPON_AMMO);
        row = column = 0;
index db25d53..69fd82c 100644 (file)
@@ -373,10 +373,12 @@ void HUD_Weapons()
                switch_speed = frametime * autocvar_hud_panel_weapons_selection_speed;
        vector radius_size = weapon_size * (autocvar_hud_panel_weapons_selection_radius + 1);
 
-       if(switchweapon == WEP_Null)
+       entity wepent = viewmodels[0]; // TODO: unhardcode
+
+       if(wepent.switchweapon == WEP_Null)
                panel_switchweapon = NULL;
        else if(!panel_switchweapon)
-               panel_switchweapon = switchweapon;
+               panel_switchweapon = wepent.switchweapon;
 
        // draw background behind currently selected weapon
        // do it earlier to make sure bg is drawn behind every weapon icons while it's moving
index 54ed9e2..bbf69d2 100644 (file)
@@ -53,9 +53,6 @@ bool button_zoom;
 bool spectatorbutton_zoom;
 bool button_attack2;
 
-Weapon activeweapon;
-Weapon switchingweapon;
-Weapon switchweapon;
 float current_viewzoom;
 float zoomin_effect;
 float warmup_stage;
index 3134a24..36c0d1b 100644 (file)
@@ -283,7 +283,7 @@ void viewmodel_animate(entity this)
 
 void viewmodel_draw(entity this)
 {
-       if(!activeweapon || !autocvar_r_drawviewmodel)
+       if(!this.activeweapon || !autocvar_r_drawviewmodel)
                return;
        int mask = (intermission || (STAT(HEALTH) <= 0) || autocvar_chase_active) ? 0 : MASK_NORMAL;
        float a = this.alpha;
@@ -292,7 +292,7 @@ void viewmodel_draw(entity this)
        if (invehicle) a = -1;
        else if (wasinvehicle) a = 1;
        wasinvehicle = invehicle;
-       Weapon wep = activeweapon;
+       Weapon wep = this.activeweapon;
        int c = entcs_GetClientColors(current_player);
        vector g = weaponentity_glowmod(wep, NULL, c);
        entity me = CSQCModel_server2csqc(player_localentnum - 1);
@@ -353,9 +353,10 @@ void viewmodel_draw(entity this)
        setorigin(this, this.origin);
 }
 
-entity viewmodel;
+entity viewmodels[MAX_WEAPONSLOTS];
 STATIC_INIT(viewmodel) {
-    viewmodel = new(viewmodel);
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       viewmodels[slot] = new(viewmodel);
 }
 
 void Porto_Draw(entity this);
@@ -371,7 +372,8 @@ const int polyline_length = 16;
 vector polyline[polyline_length];
 void Porto_Draw(entity this)
 {
-       if (activeweapon != WEP_PORTO) return;
+       entity wepent = viewmodels[0]; // TODO: unhardcode
+       if (wepent.activeweapon != WEP_PORTO) return;
        if (spectatee_status) return;
        if (WEP_CVAR(porto, secondary)) return;
        if (intermission == 1) return;
@@ -448,9 +450,11 @@ vector GetCurrentFov(float fov)
                        zoomspeed = 3.5;
 
        zoomdir = button_zoom;
+       entity wepent = viewmodels[0]; // TODO: unhardcode
+
        if(hud == HUD_NORMAL && !spectatee_status)
-       if(switchweapon == activeweapon)
-       if((activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here
+       if(wepent.switchweapon == wepent.activeweapon)
+       if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here
                zoomdir += button_attack2;
        if(spectatee_status > 0 || isdemo())
        {
@@ -631,7 +635,9 @@ float TrueAimCheck()
        ta = trueaim;
        mv = MOVE_NOMONSTERS;
 
-       switch(activeweapon) // WEAPONTODO
+       entity wepent = viewmodels[0]; // TODO: unhardcode
+
+       switch(wepent.activeweapon) // WEAPONTODO
        {
                case WEP_TUBA: // no aim
                case WEP_PORTO: // shoots from eye
@@ -806,9 +812,11 @@ void HitSound()
 {
        // varying sound pitch
 
+       entity wepent = viewmodels[0]; // TODO: unhardcode
+
        static float hitsound_time_prev = 0;
        // HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
-       float arc_hack = activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
+       float arc_hack = wepent.activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
        if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
        {
                if (autocvar_cl_hitsound && unaccounted_damage)
@@ -995,7 +1003,8 @@ void HUD_Crosshair(entity this)
         entity e = WEP_Null;
                if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
                {
-                       e = switchingweapon;
+                       entity wepent = viewmodels[0]; // TODO: unhardcode
+                       e = wepent.switchingweapon;
                        if(e)
                        {
                                if(autocvar_crosshair_per_weapon)
@@ -1153,9 +1162,10 @@ void HUD_Crosshair(entity this)
                                if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
                                        vortex_charge_movingavg = vortex_charge;
 
+                               entity wepent = viewmodels[0]; // TODO: unhardcode
 
                                // handle the values
-                               if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+                               if (autocvar_crosshair_ring && wepent.activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
                                {
                                        if (vortex_chargepool || use_vortex_chargepool) {
                                                use_vortex_chargepool = 1;
@@ -1175,14 +1185,14 @@ void HUD_Crosshair(entity this)
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring_nexgun.tga";
                                }
-                               else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
+                               else if (autocvar_crosshair_ring && wepent.activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
                                {
                                        ring_value = bound(0, STAT(LAYED_MINES) / WEP_CVAR(minelayer, limit), 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
                                        ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if (activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+                               else if (wepent.activeweapon == WEP_HAGAR && STAT(HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
                                {
                                        ring_value = bound(0, STAT(HAGAR_LOAD) / WEP_CVAR_SEC(hagar, load_max), 1);
                                        ring_alpha = autocvar_crosshair_ring_hagar_alpha;
@@ -1205,12 +1215,12 @@ void HUD_Crosshair(entity this)
 
                                        // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
                                        // if a new image for another weapon is added, add the code (and its respective file/value) here
-                                       if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
+                                       if ((wepent.activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
                                                ring_image = "gfx/crosshair_ring_rifle.tga";
                                        else
                                                ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC )
+                               else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && wepent.activeweapon == WEP_ARC )
                                {
                                        ring_value = arc_heat;
                                        ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha +
@@ -1699,7 +1709,8 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        // run viewmodel_draw before updating view_angles to the angles calculated by WarpZone_FixView
        // viewmodel_draw needs to use the view_angles set by the engine on every CSQC_UpdateView call
-       viewmodel_draw(viewmodel);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               viewmodel_draw(viewmodels[slot]);
 
        // Render the Scene
        view_origin = getpropertyvec(VF_ORIGIN);
@@ -1777,18 +1788,12 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
 
-       // currently switching-to weapon (for crosshair)
-       switchingweapon = Weapons_from(STAT(SWITCHINGWEAPON));
-
-       // actually active weapon (for zoom)
-       activeweapon = Weapons_from(STAT(ACTIVEWEAPON));
-
-       switchweapon = Weapons_from(STAT(SWITCHWEAPON));
+       entity wepent = viewmodels[0]; // TODO: unhardcode
 
-       if(last_switchweapon != switchweapon)
+       if(last_switchweapon != wepent.switchweapon)
        {
                weapontime = time;
-               last_switchweapon = switchweapon;
+               last_switchweapon = wepent.switchweapon;
                if(button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
                {
                        localcmd("-zoom\n");
@@ -1801,11 +1806,11 @@ void CSQC_UpdateView(entity this, float w, float h)
                        button_attack2 = false;
                }
        }
-       if(last_activeweapon != activeweapon)
+       if(last_activeweapon != wepent.activeweapon)
        {
-               last_activeweapon = activeweapon;
+               last_activeweapon = wepent.activeweapon;
 
-               e = activeweapon;
+               e = wepent.activeweapon;
                if(e.netname != "")
                        localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
                else
@@ -1937,7 +1942,7 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        if(autocvar_cl_reticle)
        {
-               Weapon wep = activeweapon;
+               Weapon wep = wepent.activeweapon;
                // Draw the aiming reticle for weapons that use it
                // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
                // It must be a persisted float for fading out to work properly (you let go of the zoom button for
index 5177c9d..3117f3e 100644 (file)
@@ -5,6 +5,7 @@ float autocvar_net_connecttimeout = 30;
 #include "animdecide.qc"
 #include "ent_cs.qc"
 #include "net_notice.qc"
+#include "wepent.qc"
 #endif
 
 #include "mapinfo.qc"
index 90edfa6..0ac07a1 100644 (file)
@@ -11,3 +11,4 @@
 #include <common/t_items.qc>
 #include <common/util.qc>
 #include <common/viewloc.qc>
+#include <common/wepent.qc>
index 1d2555e..15f1d26 100644 (file)
@@ -190,12 +190,12 @@ void GiveBall(entity plyr, entity ball)
        }
 
        plyr.(weaponentity).weapons = plyr.weapons;
-       plyr.(weaponentity).m_switchweapon = PS(plyr).m_weapon;
+       plyr.m_switchweapon = plyr.(weaponentity).m_weapon;
        plyr.weapons = WEPSET(NEXBALL);
        Weapon w = WEP_NEXBALL;
        w.wr_resetplayer(w, plyr);
-       PS(plyr).m_switchweapon = WEP_NEXBALL;
-       W_SwitchWeapon(plyr, WEP_NEXBALL);
+       plyr.(weaponentity).m_switchweapon = WEP_NEXBALL;
+       W_SwitchWeapon(plyr, WEP_NEXBALL, weaponentity);
 }
 
 void DropBall(entity ball, vector org, vector vel)
@@ -1000,8 +1000,8 @@ MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
                                player.weapons = player.(weaponentity).weapons;
                                Weapon w = WEP_NEXBALL;
                                w.wr_resetplayer(w, player);
-                               PS(player).m_switchweapon = player.(weaponentity).m_switchweapon;
-                               W_SwitchWeapon(player, PS(player).m_switchweapon);
+                               player.(weaponentity).m_switchweapon = player.m_switchweapon;
+                               W_SwitchWeapon(player, player.(weaponentity).m_switchweapon, weaponentity);
 
                                player.(weaponentity).weapons = '0 0 0';
                        }
@@ -1053,15 +1053,17 @@ MUTATOR_HOOKFUNCTION(nb, PlayerPhysics)
 MUTATOR_HOOKFUNCTION(nb, ForbidThrowCurrentWeapon)
 {
        entity player = M_ARGV(0, entity);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 
-       return PS(player).m_weapon == WEP_NEXBALL;
+       return player.(weaponentity).m_weapon == WEP_NEXBALL;
 }
 
 MUTATOR_HOOKFUNCTION(nb, ForbidDropCurrentWeapon)
 {
        entity player = M_ARGV(0, entity);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 
-       return PS(player).m_weapon == WEP_MORTAR; // TODO: what is this for?
+       return player.(weaponentity).m_weapon == WEP_MORTAR; // TODO: what is this for?
 }
 
 MUTATOR_HOOKFUNCTION(nb, FilterItem)
index babf6e4..8540d5c 100644 (file)
@@ -13,7 +13,7 @@ const int MON_FLAG_RIDE = 4096; // monster can be ridden in special modes
 const int MONSTER_SIZE_QUAKE = 8192;
 
 // entity properties of monsterinfo:
-.bool(int, entity actor, entity targ) monster_attackfunc;
+.bool(int, entity actor, entity targ, .entity weaponentity) monster_attackfunc;
 
 // animations
 .vector anim_blockend;
index 30d0980..a39f0a2 100644 (file)
@@ -323,9 +323,8 @@ void M_Mage_Defend_Shield(entity this)
        this.anim_finished = time + 1;
 }
 
-bool M_Mage_Attack(int attack_type, entity actor, entity targ)
+bool M_Mage_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
 {
-    .entity weaponentity = weaponentities[0];
        switch(attack_type)
        {
                case MONSTER_ATTACK_MELEE:
index 8f84bdc..38de862 100644 (file)
@@ -155,7 +155,7 @@ void M_Shambler_Attack_Lightning(entity this)
 
 .int state;
 
-bool M_Shambler_Attack(int attack_type, entity actor, entity targ)
+bool M_Shambler_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
 {
        switch(attack_type)
        {
index d2cb831..ed589d1 100644 (file)
@@ -169,9 +169,8 @@ void M_Spider_Attack_Web(entity this)
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO, true);
 }
 
-bool M_Spider_Attack(int attack_type, entity actor, entity targ)
+bool M_Spider_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
 {
-    .entity weaponentity = weaponentities[0];
        switch(attack_type)
        {
                Weapon wep = WEP_SPIDER_ATTACK;
index 3fd7ec9..6f2b50e 100644 (file)
@@ -88,9 +88,8 @@ void M_Wyvern_Attack_Fireball_Touch(entity this, entity toucher)
        M_Wyvern_Attack_Fireball_Explode(this);
 }
 
-bool M_Wyvern_Attack(int attack_type, entity actor, entity targ)
+bool M_Wyvern_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
 {
-       .entity weaponentity = weaponentities[0];
        switch(attack_type)
        {
                case MONSTER_ATTACK_MELEE:
index c48c210..edf6d92 100644 (file)
@@ -94,7 +94,7 @@ bool M_Zombie_Defend_Block(entity this)
        return true;
 }
 
-bool M_Zombie_Attack(int attack_type, entity actor, entity targ)
+bool M_Zombie_Attack(int attack_type, entity actor, entity targ, .entity weaponentity)
 {
        switch(attack_type)
        {
index ff1a5d3..c1414bf 100644 (file)
@@ -412,16 +412,18 @@ bool Monster_Attack_Leap(entity this, vector anm, void(entity this, entity touch
        return true;
 }
 
-void Monster_Attack_Check(entity this, entity targ)
+void Monster_Attack_Check(entity this, entity targ, .entity weaponentity)
 {
+       int slot = weaponslot(weaponentity);
+
        if((this == NULL || targ == NULL)
        || (!this.monster_attackfunc)
-       || (time < this.attack_finished_single[0])
+       || (time < this.attack_finished_single[slot])
        ) { return; }
 
        if(vdist(targ.origin - this.origin, <=, this.attack_range))
        {
-               bool attack_success = this.monster_attackfunc(MONSTER_ATTACK_MELEE, this, targ);
+               bool attack_success = this.monster_attackfunc(MONSTER_ATTACK_MELEE, this, targ, weaponentity);
                if(attack_success == 1)
                        Monster_Sound(this, monstersound_melee, 0, false, CH_VOICE);
                else if(attack_success > 0)
@@ -430,7 +432,7 @@ void Monster_Attack_Check(entity this, entity targ)
 
        if(vdist(targ.origin - this.origin, >, this.attack_range))
        {
-               float attack_success = this.monster_attackfunc(MONSTER_ATTACK_RANGED, this, targ);
+               float attack_success = this.monster_attackfunc(MONSTER_ATTACK_RANGED, this, targ, weaponentity);
                if(attack_success == 1)
                        Monster_Sound(this, monstersound_melee, 0, false, CH_VOICE);
                else if(attack_success > 0)
@@ -695,7 +697,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
        // update goal entity if lost
        if(this.target2 && this.goalentity.targetname != this.target2) { this.goalentity = find(NULL, targetname, this.target2); }
 
-       entity targ;
+       entity targ = this.goalentity;
 
        if(STAT(FROZEN, this) == 2)
        {
@@ -781,8 +783,6 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
                }
        }
 
-       targ = this.goalentity;
-
        if (MUTATOR_CALLHOOK(MonsterMove, this, runspeed, walkspeed, targ)
                || gameover
                || this.draggedby != NULL
@@ -895,7 +895,8 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
                this.angles_y += turny;
        }
 
-       Monster_Attack_Check(this, this.enemy);
+       .entity weaponentity = weaponentities[0]; // TODO?
+       Monster_Attack_Check(this, this.enemy, weaponentity);
 }
 
 void Monster_Remove(entity this)
@@ -1037,7 +1038,10 @@ void Monster_Dead(entity this, entity attacker, float gibbed)
        mon.mr_death(mon, this);
 
        if(this.candrop && this.weapon)
-               W_ThrowNewWeapon(this, this.weapon, 0, this.origin, randomvec() * 150 + '0 0 325');
+       {
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+               W_ThrowNewWeapon(this, this.weapon, 0, this.origin, randomvec() * 150 + '0 0 325', weaponentity);
+       }
 }
 
 void Monster_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
index 82fa2d3..0bd8ae9 100644 (file)
@@ -841,9 +841,11 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                });
        }
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        if(player.buffs & BUFF_AMMO.m_itemid)
        if(player.clip_size)
-               player.clip_load = player.(weapon_load[PS(player).m_switchweapon.m_id]) = player.clip_size;
+               player.clip_load = player.(weapon_load[player.(weaponentity).m_switchweapon.m_id]) = player.clip_size;
 
        if((player.buffs & BUFF_INVISIBLE.m_itemid) && (player.oldbuffs & BUFF_INVISIBLE.m_itemid))
        if(player.alpha != autocvar_g_buffs_invisible_alpha)
@@ -872,7 +874,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
                        if(player.clip_load)
                                player.buff_ammo_prev_clipload = player.clip_load;
-                       player.clip_load = player.(weapon_load[PS(player).m_switchweapon.m_id]) = player.clip_size;
+                       player.clip_load = player.(weapon_load[player.(weaponentity).m_switchweapon.m_id]) = player.clip_size;
                }
 
                BUFF_ONREM(BUFF_AMMO)
index 97ed436..9ea34f2 100644 (file)
@@ -63,8 +63,9 @@ REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"
                        it.ammo_rockets = start_ammo_rockets;
                        it.ammo_fuel = start_ammo_fuel;
                        it.weapons = start_weapons;
-                       if(!client_hasweapon(it, PS(it).m_weapon, true, false))
-                               PS(it).m_switchweapon = w_getbestweapon(it);
+                       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+                       if(!client_hasweapon(it, it.(weaponentity).m_weapon, true, false))
+                               it.(weaponentity).m_switchweapon = w_getbestweapon(it);
                });
        }
 
@@ -204,12 +205,13 @@ void NIX_GiveCurrentWeapon(entity this)
                this.weapons |= WEPSET(BLASTER);
        this.weapons |= e.m_wepset;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
     Weapon w = Weapons_from(nix_weapon);
-       if(PS(this).m_switchweapon != w)
-               if(!client_hasweapon(this, PS(this).m_switchweapon, true, false))
+       if(this.(weaponentity).m_switchweapon != w)
+               if(!client_hasweapon(this, this.(weaponentity).m_switchweapon, true, false))
                {
                        if(client_hasweapon(this, w, true, false))
-                               W_SwitchWeapon(this, w);
+                               W_SwitchWeapon(this, w, weaponentity);
                }
 }
 
index 024fdb1..ff9bbf9 100644 (file)
@@ -22,12 +22,12 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
 
        if((!thiswep.wr_checkammo1(thiswep, actor) && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (!(actor.items & IT_SUPERWEAPON) && !(actor.items & IT_UNLIMITED_SUPERWEAPONS)))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
 
-       W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR(hmg, ammo));
+       W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR(hmg, ammo), weaponentity);
 
        W_SetupShot (actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(hmg, damage));
 
@@ -38,7 +38,7 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
        }
 
        float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * actor.misc_bulletcounter), WEP_CVAR(hmg, spread_max));
-       fireBullet(actor, w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
 
        actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
 
index 122bdfc..32d51f9 100644 (file)
@@ -68,7 +68,7 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
        entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(actor);
        entity flash = spawn ();
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(rpc, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(rpc, ammo), weaponentity);
        W_SetupShot_ProjectileSize (actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(rpc, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        PROJECTILE_MAKETRIGGER(missile);
index ea7ed95..20d2ee7 100644 (file)
@@ -46,7 +46,8 @@ MUTATOR_HOOKFUNCTION(ok, W_DecreaseAmmo)
        entity actor = M_ARGV(0, entity);
        if (actor.ok_use_ammocharge)
        {
-               ok_DecreaseCharge(actor, PS(actor).m_weapon.m_id);
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+               ok_DecreaseCharge(actor, actor.(weaponentity).m_weapon.m_id);
                return true;
        }
 }
@@ -152,7 +153,9 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDies)
 
        ok_DropItem(frag_target, targ);
 
-       frag_target.ok_lastwep = PS(frag_target).m_switchweapon.m_id;
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
+       frag_target.ok_lastwep = frag_target.(weaponentity).m_switchweapon.m_id;
 }
 
 MUTATOR_HOOKFUNCTION(ok, MonsterDropItem)
@@ -203,6 +206,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
                return;
 
        entity player = M_ARGV(0, entity);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 
        if(IS_DEAD(player) || !IS_PLAYER(player) || STAT(FROZEN, player))
                return;
@@ -214,11 +218,11 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
                        newwep = WEP_MACHINEGUN;
                if(player.ok_lastwep == WEP_RPC.m_id)
                        newwep = WEP_VORTEX;
-               PS(player).m_switchweapon = newwep;
+               player.(weaponentity).m_switchweapon = newwep;
                player.ok_lastwep = 0;
        }
 
-       ok_IncreaseCharge(player, PS(player).m_weapon.m_id);
+       ok_IncreaseCharge(player, player.(weaponentity).m_weapon.m_id);
 
        if(PHYS_INPUT_BUTTON_ATCK2(player))
        if(!forbidWeaponUse(player) || player.weapon_blocked) // allow if weapon is blocked
@@ -227,11 +231,11 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
                player.jump_interval = time + WEP_CVAR_PRI(blaster, refire) * W_WeaponRateFactor(player);
                makevectors(player.v_angle);
 
-               Weapon oldwep = PS(player).m_weapon;
-               PS(player).m_weapon = WEP_BLASTER;
+               Weapon oldwep = player.(weaponentity).m_weapon;
+               player.(weaponentity).m_weapon = WEP_BLASTER;
                W_Blaster_Attack(
                        player,
-                       weaponentities[0], // TODO: unhardcode
+                       weaponentity,
                        WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                        WEP_CVAR_SEC(vaporizer, shotangle),
                        WEP_CVAR_SEC(vaporizer, damage),
@@ -243,23 +247,23 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
                        WEP_CVAR_SEC(vaporizer, delay),
                        WEP_CVAR_SEC(vaporizer, lifetime)
                );
-               PS(player).m_weapon = oldwep;
+               player.(weaponentity).m_weapon = oldwep;
        }
 
        player.weapon_blocked = false;
 
-       player.ok_ammo_charge = player.ammo_charge[PS(player).m_weapon.m_id];
+       player.ok_ammo_charge = player.ammo_charge[player.(weaponentity).m_weapon.m_id];
 
        if(player.ok_use_ammocharge)
-       if(!ok_CheckWeaponCharge(player, PS(player).m_weapon.m_id))
+       if(!ok_CheckWeaponCharge(player, player.(weaponentity).m_weapon.m_id))
        {
-               if(autocvar_g_overkill_ammo_charge_notice && time > player.ok_notice_time && PHYS_INPUT_BUTTON_ATCK(player) && IS_REAL_CLIENT(player) && PS(player).m_weapon == PS(player).m_switchweapon)
+               if(autocvar_g_overkill_ammo_charge_notice && time > player.ok_notice_time && PHYS_INPUT_BUTTON_ATCK(player) && IS_REAL_CLIENT(player) && player.(weaponentity).m_weapon == player.(weaponentity).m_switchweapon)
                {
                        //Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_OVERKILL_CHARGE);
                        player.ok_notice_time = time + 2;
                        play2(player, SND(DRYFIRE));
                }
-               Weapon wpn = PS(player).m_weapon;
+               Weapon wpn = player.(weaponentity).m_weapon;
                .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                if(player.(weaponentity).state != WS_CLEAR)
                        w_ready(wpn, player, weaponentity, PHYS_INPUT_BUTTON_ATCK(player) | (PHYS_INPUT_BUTTON_ATCK2(player) << 1));
@@ -357,8 +361,9 @@ MUTATOR_HOOKFUNCTION(ok, SpectateCopy)
 {
        entity spectatee = M_ARGV(0, entity);
        entity client = M_ARGV(1, entity);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 
-       client.ammo_charge[PS(client).m_weapon.m_id] = spectatee.ammo_charge[PS(spectatee).m_weapon.m_id];
+       client.ammo_charge[client.(weaponentity).m_weapon.m_id] = spectatee.ammo_charge[spectatee.(weaponentity).m_weapon.m_id];
        client.ok_use_ammocharge = spectatee.ok_use_ammocharge;
 }
 
index bc3887e..387c1c3 100644 (file)
@@ -6,11 +6,13 @@ MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        FOREACH(Weapons, it != WEP_Null, LAMBDA(
                if(frag_target.weapons & WepSet_FromWeapon(it))
-               if(PS(frag_target).m_switchweapon != it)
+               if(frag_target.(weaponentity).m_switchweapon != it)
                if(W_IsWeaponThrowable(frag_target, it.m_id))
-                       W_ThrowNewWeapon(frag_target, it.m_id, false, CENTER_OR_VIEWOFS(frag_target), randomvec() * 175 + '0 0 325');
+                       W_ThrowNewWeapon(frag_target, it.m_id, false, CENTER_OR_VIEWOFS(frag_target), randomvec() * 175 + '0 0 325', weaponentity);
        ));
 
        return true;
index 891461c..882b256 100644 (file)
@@ -17,10 +17,6 @@ void PlayerState_detach(entity this)
        PS(this) = NULL;
 
        if (ps.m_client != this) return;  // don't own state, spectator
-       ps.m_switchweapon = WEP_Null;
-       ps.m_weapon = WEP_Null;
-       ps.m_switchingweapon = WEP_Null;
-       ps.ps_push(ps, this);
        
        FOREACH_CLIENT(PS(it) == ps, { PS(it) = NULL; });
        delete(ps);
index 94b9bc3..850e7ac 100644 (file)
@@ -12,16 +12,6 @@ CLASS(PlayerState, Object)
                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, entity cl))
-       {
-           TC(PlayerState, this);
-               STAT(ACTIVEWEAPON, cl) = this.m_weapon.m_id;
-               STAT(SWITCHINGWEAPON, cl) = this.m_switchingweapon.m_id;
-               STAT(SWITCHWEAPON, cl) = this.m_switchweapon.m_id;
-       }
 ENDCLASS(PlayerState)
 
 .PlayerState _ps;
index e6cc553..5cc278b 100644 (file)
@@ -59,9 +59,7 @@ REGISTER_STAT(KH_KEYS, int)
 REGISTER_STAT(SWITCHWEAPON, int)
 /** weapon currently being switched to (is copied from switchweapon once switch is possible) */
 REGISTER_STAT(SWITCHINGWEAPON, int)
-REGISTER_STAT(WEAPON_NEXTTHINK, float)
 #ifdef SVQC
-SPECTATE_COPYFIELD(_STAT(WEAPON_NEXTTHINK))
 float W_WeaponRateFactor(entity this);
 #endif
 REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor(this))
index f9f89a7..6949035 100644 (file)
@@ -675,6 +675,8 @@ float Item_GiveTo(entity item, entity player)
        float _switchweapon;
        float pickedup;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        // if nothing happens to player, just return without taking the item
        pickedup = false;
        _switchweapon = false;
@@ -682,10 +684,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 (PS(player).m_switchweapon == w_getbestweapon(player))
+       if (player.(weaponentity).m_switchweapon == w_getbestweapon(player))
                _switchweapon = true;
 
-       if (!(player.weapons & WepSet_FromWeapon(PS(player).m_switchweapon)))
+       if (!(player.weapons & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
                _switchweapon = true;
 
        pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
@@ -760,13 +762,13 @@ LABEL(skip)
        // crude hack to enforce switching weapons
        if(g_cts && item.itemdef.instanceOfWeaponPickup)
        {
-               W_SwitchWeapon_Force(player, Weapons_from(item.weapon));
+               W_SwitchWeapon_Force(player, Weapons_from(item.weapon), weaponentity);
                return 1;
        }
 
        if (_switchweapon)
-               if (PS(player).m_switchweapon != w_getbestweapon(player))
-                       W_SwitchWeapon_Force(player, w_getbestweapon(player));
+               if (player.(weaponentity).m_switchweapon != w_getbestweapon(player))
+                       W_SwitchWeapon_Force(player, w_getbestweapon(player), weaponentity);
 
        return 1;
 }
@@ -1653,9 +1655,11 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        got = 0;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        _switchweapon = false;
        if (e.autoswitch)
-               if (PS(e).m_switchweapon == w_getbestweapon(e))
+               if (e.(weaponentity).m_switchweapon == w_getbestweapon(e))
                        _switchweapon = true;
 
        e.strength_finished = max(0, e.strength_finished - time);
@@ -1821,10 +1825,10 @@ float GiveItems(entity e, float beginarg, float endarg)
        else
                e.superweapons_finished += time;
 
-       if (!(e.weapons & WepSet_FromWeapon(PS(e).m_switchweapon)))
+       if (!(e.weapons & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
                _switchweapon = true;
        if(_switchweapon)
-               W_SwitchWeapon_Force(e, w_getbestweapon(e));
+               W_SwitchWeapon_Force(e, w_getbestweapon(e), weaponentity);
 
        return got;
 }
index 44c8d64..c60cd3b 100644 (file)
@@ -19,7 +19,7 @@ METHOD(MachineGunTurretAttack, wr_think, void(entity thiswep, entity actor, .ent
             actor.tur_head = actor;
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, w_ready);
         }
-        fireBullet (actor, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN.m_id, 0);
+        fireBullet (actor, weaponentity, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_MACHINEGUN.m_id, 0);
         W_MachineGun_MuzzleFlash(actor, weaponentity);
         setattachment(actor.(weaponentity).muzzle_flash, actor.tur_head, "tag_fire");
     }
index d161436..ed7d4f1 100644 (file)
@@ -10,7 +10,8 @@ METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this, entity it))
 {
     if(g_instagib)
     {
-        FireRailgunBullet (it, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+        .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+        FireRailgunBullet (it, weaponentity, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
                            800, 0, 0, 0, 0, DEATH_TURRET_PLASMA.m_id);
 
         Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, it.tur_shotorg, it.tur_shotdir_updated * 1000, 1);
index 9e6d80b..b1e7d58 100644 (file)
@@ -9,7 +9,8 @@ spawnfunc(turret_plasma_dual) { if (!turret_initialize(this, TUR_PLASMA_DUAL)) d
 METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret thistur, entity it))
 {
     if (g_instagib) {
-        FireRailgunBullet (it, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
+        .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+        FireRailgunBullet (it, weaponentity, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
                            800, 0, 0, 0, 0, DEATH_TURRET_PLASMA.m_id);
 
 
index 88b18b9..9bcf902 100644 (file)
@@ -18,7 +18,7 @@ METHOD(WalkerTurretAttack, wr_think, void(entity thiswep, entity actor, .entity
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
         }
         sound (actor, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
-        fireBullet (actor, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_WALK_GUN.m_id, 0);
+        fireBullet (actor, weaponentity, actor.tur_shotorg, actor.tur_shotdir_updated, actor.shot_spread, 0, actor.shot_dmg, actor.shot_force, DEATH_TURRET_WALK_GUN.m_id, 0);
         Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, actor.tur_shotorg, actor.tur_shotdir_updated * 1000, 1);
     }
 }
index cd62f07..bcb0631 100644 (file)
@@ -806,7 +806,12 @@ void vehicles_exit(entity vehic, bool eject)
                player.view_ofs         = STAT(PL_VIEW_OFS, NULL);
                player.event_damage     = PlayerDamage;
                player.hud                              = HUD_NORMAL;
-               PS(player).m_switchweapon = vehic.m_switchweapon;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++ slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       player.(weaponentity).m_switchweapon = vehic.(weaponentity).m_switchweapon;
+                       delete(vehic.(weaponentity)); // no longer needed
+               }
                player.last_vehiclecheck = time + 3;
                player.vehicle_enter_delay = time + 2;
 
@@ -976,7 +981,12 @@ void vehicles_enter(entity pl, entity veh)
        veh.colormap            = pl.colormap;
        if(veh.tur_head)
                veh.tur_head.colormap = pl.colormap;
-       veh.m_switchweapon = PS(pl).m_switchweapon;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               veh.(weaponentity) = new(temp_wepent);
+               veh.(weaponentity).m_switchweapon = pl.(weaponentity).m_switchweapon;
+       }
        pl.hud = veh.vehicleid;
        pl.PlayerPhysplug = veh.PlayerPhysplug;
 
index 3f5f404..4f74c86 100644 (file)
@@ -236,7 +236,12 @@ void bumblebee_gunner_exit(entity this, int _exitflag)
        player.event_damage   = PlayerDamage;
        player.hud            = HUD_NORMAL;
        player.teleportable       = TELEPORT_NORMAL;
-       PS(player).m_switchweapon = gunner.m_switchweapon;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               player.(weaponentity).m_switchweapon = gunner.(weaponentity).m_switchweapon;
+               delete(gunner.(weaponentity));
+       }
        player.vehicle_enter_delay = time + 2;
 
        fixedmakevectors(vehic.angles);
@@ -306,7 +311,13 @@ bool bumblebee_gunner_enter(entity this, entity player)
 
        RemoveGrapplingHook(player);
 
-       gunner.m_switchweapon = PS(player).m_switchweapon;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+
+               gunner.(weaponentity) = new(temp_wepent);
+               gunner.(weaponentity).m_switchweapon = player.(weaponentity).m_switchweapon;
+       }
        gunner.vehicle_exit = bumblebee_gunner_exit;
        gunner.vehicle_hudmodel.viewmodelforclient = player;
 
index 347d212..ddbd6e2 100644 (file)
@@ -60,7 +60,11 @@ bool spiderbot_frame(entity this, float dt)
 
        PHYS_INPUT_BUTTON_ZOOM(this) = false;
        PHYS_INPUT_BUTTON_CROUCH(this) = false;
-       PS(this).m_switchweapon = WEP_Null;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               this.(weaponentity).m_switchweapon = WEP_Null;
+       }
        this.vehicle_weapon2mode = vehic.vehicle_weapon2mode;
 
 
@@ -260,7 +264,8 @@ bool spiderbot_frame(entity this, float dt)
                        v_forward = normalize(v_forward);
                        v += v_forward * 50;
 
-                       fireBullet(this, v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
+                       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+                       fireBullet(this, weaponentity, v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
                                autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN.m_id, 0);
 
                        sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
index cf55aa6..1faa1a0 100644 (file)
@@ -557,21 +557,23 @@ NET_HANDLE(wframe, bool isNew)
        a.x = ReadCoord();
     a.y = ReadCoord();
     a.z = ReadCoord();
+    int slot = ReadByte();
        bool restartanim = ReadByte();
-       anim_set(viewmodel, a, !restartanim, restartanim, restartanim);
-       viewmodel.state = ReadByte();
-       viewmodel.weapon_nextthink = ReadFloat();
-       viewmodel.alpha = ReadByte() / 255;
-       switch (viewmodel.state)
+       entity wepent = viewmodels[slot];
+       anim_set(wepent, a, !restartanim, restartanim, restartanim);
+       wepent.state = ReadByte();
+       wepent.weapon_nextthink = ReadFloat();
+       wepent.alpha = ReadByte() / 255;
+       switch (wepent.state)
        {
                case WS_RAISE:
-                       viewmodel.weapon_switchdelay = activeweapon.switchdelay_raise;
+                       wepent.weapon_switchdelay = wepent.activeweapon.switchdelay_raise;
                        break;
                case WS_DROP:
-                       viewmodel.weapon_switchdelay = activeweapon.switchdelay_drop;
+                       wepent.weapon_switchdelay = wepent.activeweapon.switchdelay_drop;
                        break;
         default:
-            viewmodel.weapon_switchdelay = 0;
+            wepent.weapon_switchdelay = 0;
             break;
        }
        return true;
@@ -588,6 +590,7 @@ void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
        WriteCoord(channel, a.x);
        WriteCoord(channel, a.y);
        WriteCoord(channel, a.z);
+       WriteByte(channel, weaponslot(weaponentity.weaponentity_fld));
        WriteByte(channel, restartanim);
        WriteByte(channel, weaponentity.state);
        WriteFloat(channel, weaponentity.weapon_nextthink);
index a61dc0f..5d2e9e2 100644 (file)
@@ -273,7 +273,7 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(arc, bolt_ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(arc, bolt_ammo), weaponentity);
 
        W_SetupShot(actor, weaponentity, false, 2, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR(arc, bolt_damage));
 
@@ -381,7 +381,7 @@ void W_Arc_Beam_Think(entity this)
                if(!(own.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
-                       W_SwitchToOtherWeapon(own);
+                       W_SwitchToOtherWeapon(own, weaponentity);
                }
                delete(this);
                return;
@@ -728,7 +728,7 @@ void Arc_Smoke(entity actor, .entity weaponentity)
        }
 
        if (  actor.arc_smoke_sound && ( actor.arc_overheat <= time ||
-               !( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) ) ) || PS(actor).m_switchweapon != WEP_ARC )
+               !( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) ) ) || actor.(weaponentity).m_switchweapon != WEP_ARC )
        {
                actor.arc_smoke_sound = 0;
                sound(actor, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
index 2eb8f00..b669db7 100644 (file)
@@ -196,8 +196,8 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti
         {
             case 0: // switch to last used weapon
             {
-                if(PS(actor).m_switchweapon == WEP_BLASTER) // don't do this if already switching
-                    W_LastWeapon(actor);
+                if(actor.(weaponentity).m_switchweapon == WEP_BLASTER) // don't do this if already switching
+                    W_LastWeapon(actor, weaponentity);
                 break;
             }
 
index 58214bf..a6df250 100644 (file)
@@ -354,7 +354,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        vector forward, right, up;
        float maxdmg;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(crylink, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(crylink, ammo), weaponentity);
 
        maxdmg = WEP_CVAR_PRI(crylink, damage) * WEP_CVAR_PRI(crylink, shots);
        maxdmg *= 1 + WEP_CVAR_PRI(crylink, bouncedamagefactor) * WEP_CVAR_PRI(crylink, bounces);
@@ -464,7 +464,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        vector forward, right, up;
        float maxdmg;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(crylink, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(crylink, ammo), weaponentity);
 
        maxdmg = WEP_CVAR_SEC(crylink, damage) * WEP_CVAR_SEC(crylink, shots);
        maxdmg *= 1 + WEP_CVAR_SEC(crylink, bouncedamagefactor) * WEP_CVAR_SEC(crylink, bounces);
@@ -631,7 +631,7 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
             {
                 // ran out of ammo!
                 actor.cnt = WEP_CRYLINK.m_id;
-                PS(actor).m_switchweapon = w_getbestweapon(actor);
+                actor.(weaponentity).m_switchweapon = w_getbestweapon(actor);
             }
         }
     }
index 1fdb8d6..35435ab 100644 (file)
@@ -115,7 +115,8 @@ void W_Devastator_Explode(entity this, entity directhitentity)
        );
 
        Weapon thiswep = WEP_DEVASTATOR;
-       if(PS(this.realowner).m_weapon == thiswep)
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                if(this.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo))
                if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
@@ -123,7 +124,7 @@ void W_Devastator_Explode(entity this, entity directhitentity)
                        this.realowner.cnt = WEP_DEVASTATOR.m_id;
                        int slot = 0; // TODO: unhardcode
                        ATTACK_FINISHED(this.realowner, slot) = time;
-                       PS(this.realowner).m_switchweapon = w_getbestweapon(this.realowner);
+                       this.realowner.(weaponentity).m_switchweapon = w_getbestweapon(this.realowner);
                }
        }
        delete(this);
@@ -201,7 +202,7 @@ void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity)
        );
 
        Weapon thiswep = WEP_DEVASTATOR;
-       if(PS(this.realowner).m_weapon == thiswep)
+       if(this.realowner.(weaponentity).m_weapon == thiswep)
        {
                if(this.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo))
                if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
@@ -209,7 +210,7 @@ void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity)
                        this.realowner.cnt = WEP_DEVASTATOR.m_id;
                        int slot = weaponslot(weaponentity);
                        ATTACK_FINISHED(this.realowner, slot) = time;
-                       PS(this.realowner).m_switchweapon = w_getbestweapon(this.realowner);
+                       this.realowner.(weaponentity).m_switchweapon = w_getbestweapon(this.realowner);
                }
        }
        delete(this);
@@ -361,7 +362,7 @@ void W_Devastator_Damage(entity this, entity inflictor, entity attacker, float d
 
 void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(devastator, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(devastator, ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
@@ -515,7 +516,7 @@ METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponen
             actor.rl_release[slot] = 1;
 
         if(fire & 2)
-        if(PS(actor).m_switchweapon == WEP_DEVASTATOR)
+        if(actor.(weaponentity).m_switchweapon == WEP_DEVASTATOR)
         {
             bool rockfound = false;
             IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket",
index 7e05241..b5ee530 100644 (file)
@@ -265,7 +265,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity proj;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(electro, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(electro, ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(
                actor,
@@ -410,7 +410,7 @@ void W_Electro_Orb_Damage(entity this, entity inflictor, entity attacker, float
 
 void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(electro, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(electro, ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(
                actor,
index 9a178c0..5bc2994 100644 (file)
@@ -139,7 +139,7 @@ void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hagar, ammo), weaponentity);
 
        W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
 
@@ -183,7 +183,7 @@ void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity missile;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
 
        W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
 
@@ -334,7 +334,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
                        {
                                // if we pressed primary fire while loading, unload all rockets and abort
                                actor.(weaponentity).state = WS_READY;
-                               W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1); // give back ammo
+                               W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1, weaponentity); // give back ammo
                                actor.hagar_load = 0;
                                sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
 
@@ -352,7 +352,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
                        {
                                if(!actor.hagar_loadblock && actor.hagar_loadstep < time)
                                {
-                                       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo));
+                                       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo), weaponentity);
                                        actor.(weaponentity).state = WS_INUSE;
                                        actor.hagar_load += 1;
                                        sound(actor, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
@@ -408,7 +408,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
-                       W_SwitchToOtherWeapon(actor);
+                       W_SwitchToOtherWeapon(actor, weaponentity);
                        return;
                }
        }
@@ -425,7 +425,7 @@ void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int
        if(!thiswep.wr_checkammo1(thiswep, actor))
        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
@@ -490,7 +490,8 @@ METHOD(Hagar, wr_setup, void(entity thiswep, entity actor))
 
     if(actor.hagar_load)
     {
-        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1); // give back ammo if necessary
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1, weaponentity); // give back ammo if necessary
         actor.hagar_load = 0;
     }
 }
index 79bf081..beb42d5 100644 (file)
@@ -75,7 +75,7 @@ void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        entity missile;
     float spread;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hlac, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hlac, ammo), weaponentity);
 
     spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * actor.misc_bulletcounter);
     spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
@@ -168,7 +168,7 @@ void W_HLAC_Attack2(entity actor, .entity weaponentity)
 // weapon frames
 void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if(PS(actor).m_weapon != PS(actor).m_switchweapon) // abort immediately if switching
+       if(actor.(weaponentity).m_weapon != actor.(weaponentity).m_switchweapon) // abort immediately if switching
        {
                w_ready(thiswep, actor, weaponentity, fire);
                return;
@@ -179,7 +179,7 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
                if(!thiswep.wr_checkammo1(thiswep, actor))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
                        return;
                }
@@ -200,7 +200,7 @@ void W_HLAC_Attack2_Frame(Weapon thiswep, entity actor, .entity weaponentity)
 {
     float i;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hlac, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hlac, ammo), weaponentity);
 
     for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
         W_HLAC_Attack2(actor, weaponentity);
index 23e7c23..38a4163 100644 (file)
@@ -196,7 +196,7 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         if(time > actor.hook_refire)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, -1))
         {
-            W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo));
+            W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo), weaponentity);
             actor.hook_state |= HOOK_FIRING;
             actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
@@ -243,7 +243,7 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
                 {
                     if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
                     {
-                        W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel);
+                        W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel, weaponentity);
                         actor.hook_time_fueldecrease = time;
                         // decrease next frame again
                     }
@@ -251,7 +251,7 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
                     {
                         actor.ammo_fuel = 0;
                         actor.hook_state |= HOOK_REMOVING;
-                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                     }
                 }
             }
index 81da28d..dc6d28a 100644 (file)
@@ -122,9 +122,9 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity we
        ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(actor);
 
        if(actor.misc_bulletcounter == 1)
-               fireBullet(actor, w_shotorg, w_shotdir, WEP_CVAR(machinegun, first_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, first_damage), WEP_CVAR(machinegun, first_force), deathtype, 0);
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, first_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, first_damage), WEP_CVAR(machinegun, first_force), deathtype, 0);
        else
-               fireBullet(actor, w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, 0);
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, 0);
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -139,15 +139,15 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity we
        }
 
        if(actor.misc_bulletcounter == 1)
-               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, first_ammo));
+               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, first_ammo), weaponentity);
        else
-               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, sustained_ammo));
+               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, sustained_ammo), weaponentity);
 }
 
 // weapon frames
 void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if(PS(actor).m_weapon != PS(actor).m_switchweapon) // abort immediately if switching
+       if(actor.(weaponentity).m_weapon != actor.(weaponentity).m_switchweapon) // abort immediately if switching
        {
                w_ready(thiswep, actor, weaponentity, fire);
                return;
@@ -157,7 +157,7 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit
                if(!thiswep.wr_checkammo2(thiswep, actor))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
                        return;
                }
@@ -183,12 +183,12 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
        if(!thiswep.wr_checkammo1(thiswep, actor))
        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
 
-       W_DecreaseAmmo(WEP_MACHINEGUN, actor, WEP_CVAR(machinegun, sustained_ammo));
+       W_DecreaseAmmo(WEP_MACHINEGUN, actor, WEP_CVAR(machinegun, sustained_ammo), weaponentity);
 
        W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
        if(!autocvar_g_norecoil)
@@ -198,7 +198,7 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
        }
 
        machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * actor.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
-       fireBullet(actor, w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
 
        actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
 
@@ -227,7 +227,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
                actor.punchangle_y = random() - 0.5;
        }
 
-       fireBullet(actor, w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -281,12 +281,12 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
             if(!thiswep.wr_checkammo2(thiswep, actor))
             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
             {
-                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                 w_ready(thiswep, actor, weaponentity, fire);
                 return;
             }
 
-            W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, burst_ammo));
+            W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, burst_ammo), weaponentity);
 
             actor.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
             W_MachineGun_Attack_Burst(thiswep, actor, weaponentity, fire);
index 5f5898a..35507c3 100644 (file)
@@ -126,17 +126,17 @@ void W_MineLayer_Explode(entity this, entity directhitentity)
 
        RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, damage), WEP_CVAR(minelayer, edgedamage), WEP_CVAR(minelayer, radius), NULL, NULL, WEP_CVAR(minelayer, force), this.projectiledeathtype, directhitentity);
 
-       if(PS(this.realowner).m_weapon == WEP_MINE_LAYER)
+       .entity weaponentity = this.weaponentity_fld;
+       if(this.realowner.(weaponentity).m_weapon == WEP_MINE_LAYER)
        {
                entity own = this.realowner;
                Weapon w = WEP_MINE_LAYER;
                if(!w.wr_checkammo1(w, own))
                {
                        own.cnt = WEP_MINE_LAYER.m_id;
-                       .entity weaponentity = this.weaponentity_fld;
                        int slot = weaponslot(weaponentity);
                        ATTACK_FINISHED(own, slot) = time;
-                       PS(own).m_switchweapon = w_getbestweapon(own);
+                       own.(weaponentity).m_switchweapon = w_getbestweapon(own);
                }
        }
        this.realowner.minelayer_mines -= 1;
@@ -158,17 +158,17 @@ void W_MineLayer_DoRemoteExplode(entity this)
 
        RadiusDamage(this, this.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius), NULL, NULL, WEP_CVAR(minelayer, remote_force), this.projectiledeathtype | HITTYPE_BOUNCE, NULL);
 
-       if(PS(this.realowner).m_weapon == WEP_MINE_LAYER)
+       .entity weaponentity = this.weaponentity_fld;
+       if(this.realowner.(weaponentity).m_weapon == WEP_MINE_LAYER)
        {
                entity own = this.realowner;
                Weapon w = WEP_MINE_LAYER;
                if(!w.wr_checkammo1(w, own))
                {
                        own.cnt = WEP_MINE_LAYER.m_id;
-                       .entity weaponentity = this.weaponentity_fld;
                        int slot = weaponslot(weaponentity);
                        ATTACK_FINISHED(own, slot) = time;
-                       PS(own).m_switchweapon = w_getbestweapon(own);
+                       own.(weaponentity).m_switchweapon = w_getbestweapon(own);
                }
        }
        this.realowner.minelayer_mines -= 1;
@@ -273,7 +273,8 @@ void W_MineLayer_Think(entity this)
        }
 
        // remote detonation
-       if(PS(this.realowner).m_weapon == WEP_MINE_LAYER)
+       .entity weaponentity = this.weaponentity_fld;
+       if(this.realowner.(weaponentity).m_weapon == WEP_MINE_LAYER)
        if(!IS_DEAD(this.realowner))
        if(this.minelayer_detonate)
                W_MineLayer_RemoteExplode(this);
@@ -336,7 +337,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
                }
        }
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(minelayer, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(minelayer, ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(actor, weaponentity, '-4 -4 -4', '4 4 4', false, 5, SND_MINE_FIRE, CH_WEAPON_A, WEP_CVAR(minelayer, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
index 1428cc4..fa08908 100644 (file)
@@ -212,7 +212,7 @@ void W_Mortar_Grenade_Touch2(entity this, entity toucher)
 
 void W_Mortar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(mortar, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(mortar, ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
        w_shotdir = v_forward; // no TrueAim for grenades please
@@ -262,7 +262,7 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 {
        entity gren;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(mortar, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(mortar, ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 4, SND_GRENADE_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
        w_shotdir = v_forward; // no TrueAim for grenades please
index 3e4654f..e47d5dd 100644 (file)
@@ -66,7 +66,7 @@ void W_Porto_Success(entity this)
        delete(this);
 }
 
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
+string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity);
 void W_Porto_Fail(entity this, float failhard)
 {
        if(this.realowner == NULL)
@@ -95,7 +95,8 @@ void W_Porto_Fail(entity this, float failhard)
                        tracetoss(this, this);
                        if(vdist(trace_endpos - this.realowner.origin, <, 128))
                        {
-                               W_ThrowNewWeapon(this.realowner, WEP_PORTO.m_id, 0, this.origin, this.velocity);
+                               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+                               W_ThrowNewWeapon(this.realowner, WEP_PORTO.m_id, 0, this.origin, this.velocity, weaponentity);
                                Send_Notification(NOTIF_ONE, this.realowner, MSG_CENTER, CENTER_PORTO_FAILED);
                        }
                }
index 478a315..b290728 100644 (file)
@@ -61,7 +61,7 @@ void W_Rifle_FireBullet(Weapon thiswep, .entity weaponentity, float pSpread, flo
 {
        float i;
 
-       W_DecreaseAmmo(thiswep, actor, pAmmo);
+       W_DecreaseAmmo(thiswep, actor, pAmmo, weaponentity);
 
        W_SetupShot(actor, weaponentity, true, 2, pSound, CH_WEAPON_A, pDamage * pShots);
 
@@ -74,7 +74,7 @@ void W_Rifle_FireBullet(Weapon thiswep, .entity weaponentity, float pSpread, flo
        }
 
        for(i = 0; i < pShots; ++i)
-               fireBullet(actor, w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE));
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE));
 
        if(autocvar_g_casings >= 2)
     {
@@ -101,14 +101,14 @@ void W_Rifle_BulletHail_Continue(Weapon thiswep, entity actor, .entity weaponent
 {
        float r, af;
 
-       Weapon sw = PS(actor).m_switchweapon; // make it not detect weapon changes as reason to abort firing
+       Weapon sw = actor.(weaponentity).m_switchweapon; // make it not detect weapon changes as reason to abort firing
        int slot = weaponslot(weaponentity);
        af = ATTACK_FINISHED(actor, slot);
-       PS(actor).m_switchweapon = PS(actor).m_weapon;
+       actor.(weaponentity).m_switchweapon = actor.(weaponentity).m_weapon;
        ATTACK_FINISHED(actor, slot) = time;
        r = weapon_prepareattack(thiswep, actor, weaponentity, actor.rifle_bullethail_frame == WFRAME_FIRE2, actor.rifle_bullethail_refire);
-       if(PS(actor).m_switchweapon == PS(actor).m_weapon)
-               PS(actor).m_switchweapon = sw;
+       if(actor.(weaponentity).m_switchweapon == actor.(weaponentity).m_weapon)
+               actor.(weaponentity).m_switchweapon = sw;
        if(r)
        {
                actor.rifle_bullethail_attackfunc(actor, weaponentity);
index 268e191..fb22362 100644 (file)
@@ -256,7 +256,7 @@ void W_Seeker_Missile_Animate(entity this)
 
 void W_Seeker_Fire_Missile(Weapon thiswep, entity actor, .entity weaponentity, vector f_diff, entity m_target)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, missile_ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, missile_ammo), weaponentity);
 
        makevectors(actor.v_angle);
        W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_SEEKER_FIRE, CH_WEAPON_A, 0);
@@ -335,7 +335,7 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor, .entity weaponentity)
        vector f_diff;
        float c;
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, flac_ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, flac_ammo), weaponentity);
 
        c = actor.bulletcounter % 4;
        switch(c)
@@ -432,7 +432,8 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
        this.cnt = this.cnt - 1;
 
        Weapon thiswep = WEP_SEEKER;
-       if((!(this.realowner.items & IT_UNLIMITED_AMMO) && this.realowner.(thiswep.ammo_field) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (PS(this.realowner).m_switchweapon != WEP_SEEKER))
+       .entity weaponentity = this.weaponentity_fld;
+       if((!(this.realowner.items & IT_UNLIMITED_AMMO) && this.realowner.(thiswep.ammo_field) < WEP_CVAR(seeker, missile_ammo)) || (this.cnt <= -1) || (IS_DEAD(this.realowner)) || (this.realowner.(weaponentity).m_switchweapon != WEP_SEEKER))
        {
                delete(this);
                return;
@@ -444,7 +445,6 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
 
        oldenemy = own.enemy;
        own.enemy = this.enemy;
-       .entity weaponentity = this.weaponentity_fld;
 
        c = own.cnt % 4;
        switch(c)
@@ -469,8 +469,9 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
 
 void W_Seeker_Tracker_Think(entity this)
 {
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
        // commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
-       if((IS_DEAD(this.realowner)) || (IS_DEAD(this.tag_target)) || (PS(this.realowner).m_switchweapon != WEP_SEEKER)
+       if((IS_DEAD(this.realowner)) || (IS_DEAD(this.tag_target)) || (this.realowner.(weaponentity).m_switchweapon != WEP_SEEKER)
        || (time > this.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime)))
        {
                if(this)
@@ -571,7 +572,7 @@ void W_Seeker_Tag_Touch(entity this, entity toucher)
 
 void W_Seeker_Fire_Tag(Weapon thiswep, entity actor, .entity weaponentity)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, tag_ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(seeker, tag_ammo), weaponentity);
 
        W_SetupShot_ProjectileSize(actor, weaponentity, '-2 -2 -2', '2 2 2', false, 2, SND_TAG_FIRE, CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
 
index 9ae0c60..13de3fb 100644 (file)
@@ -61,11 +61,11 @@ spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(this, WEP_SHOTGUN); }
 
 void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(shotgun, ammo));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(shotgun, ammo), weaponentity);
 
        W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
        for(int sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
-               fireBullet(actor, w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0);
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0);
 
        Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
 
@@ -202,7 +202,7 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
        if (!thiswep.wr_checkammo2(thiswep, actor))
        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                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, actor))
        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
index 546e59f..8fa9e7f 100644 (file)
@@ -412,7 +412,12 @@ NET_HANDLE(tuba_instrument, bool)
        string s = (i == 0) ? "tuba" :
                   (i == 1) ? "akordeon" :
                              "kleinbottle" ;
-       CL_WeaponEntity_SetModel(viewmodel, s, true);
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       entity wep = viewmodels[slot];
+       if(wep.activeweapon == WEP_TUBA)
+               CL_WeaponEntity_SetModel(wep, s, true);
+    }
 }
 #endif
 #ifdef SVQC
@@ -437,15 +442,15 @@ METHOD(Tuba, wr_reload, void(Tuba this, entity actor, .entity weaponentity))
                {
                        case 0:
                                actor.tuba_instrument = 1;
-                               actor.weaponname = "akordeon";
+                               actor.(weaponentity).weaponname = "akordeon";
                                break;
                        case 1:
                                actor.tuba_instrument = 2;
-                               actor.weaponname = "kleinbottle";
+                               actor.(weaponentity).weaponname = "kleinbottle";
                                break;
                        case 2:
                                actor.tuba_instrument = 0;
-                               actor.weaponname = "tuba";
+                               actor.(weaponentity).weaponname = "tuba";
                                break;
                }
                tuba_instrument_send(actor, actor.tuba_instrument);
index e11e4d8..01c8847 100644 (file)
@@ -193,7 +193,7 @@ void W_Vaporizer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        yoda = 0;
        damage_goodhits = 0;
-       FireRailgunBullet(actor, w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, vaporizer_damage, 800, 0, 0, 0, 0, WEP_VAPORIZER.m_id);
+       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, vaporizer_damage, 800, 0, 0, 0, 0, WEP_VAPORIZER.m_id);
 
        // do this now, as goodhits is disabled below
        SendCSQCVaporizerBeamParticle(actor, damage_goodhits);
@@ -212,7 +212,7 @@ void W_Vaporizer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        if(!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
                W_RocketMinsta_Explosion(actor, trace_endpos);
 
-       W_DecreaseAmmo(thiswep, actor, ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)));
+       W_DecreaseAmmo(thiswep, actor, ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)), weaponentity);
 }
 
 void W_RocketMinsta_Laser_Explode (entity this)
@@ -253,10 +253,10 @@ void W_RocketMinsta_Attack2(entity actor, .entity weaponentity)
        float spread = autocvar_g_rm_laser_spread;
        float rndspread = autocvar_g_rm_laser_spread_random;
 
-       Weapon w = PS(actor).m_weapon;
-       PS(actor).m_weapon = WEP_ELECTRO;
+       Weapon w = actor.(weaponentity).m_weapon;
+       actor.(weaponentity).m_weapon = WEP_ELECTRO;
        W_SetupShot_ProjectileSize (actor, weaponentity, '0 0 -3', '0 0 -3', false, 2, SND_CRYLINK_FIRE, CH_WEAPON_A, autocvar_g_rm_laser_damage);
-       PS(actor).m_weapon = w;
+       actor.(weaponentity).m_weapon = w;
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -307,10 +307,10 @@ void W_RocketMinsta_Attack3 (entity actor, .entity weaponentity)
        float counter = 0;
        float total = 1;
 
-       Weapon w = PS(actor).m_weapon;
-       PS(actor).m_weapon = WEP_ELECTRO;
+       Weapon w = actor.(weaponentity).m_weapon;
+       actor.(weaponentity).m_weapon = WEP_ELECTRO;
        W_SetupShot_ProjectileSize (actor, weaponentity, '0 0 -3', '0 0 -3', false, 2, SND_ELECTRO_FIRE2, CH_WEAPON_A, autocvar_g_rm_laser_damage);
-       PS(actor).m_weapon = w;
+       actor.(weaponentity).m_weapon = w;
 
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -404,12 +404,12 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent
 
             // decrease ammo for the laser?
             if(WEP_CVAR_SEC(vaporizer, ammo))
-                W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(vaporizer, ammo));
+                W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(vaporizer, ammo), weaponentity);
 
             // ugly instagib hack to reuse the fire mode of the laser
             makevectors(actor.v_angle);
-            Weapon oldwep = PS(actor).m_weapon; // we can't avoid this hack
-            PS(actor).m_weapon = WEP_BLASTER;
+            Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+            actor.(weaponentity).m_weapon = WEP_BLASTER;
             W_Blaster_Attack(
                 actor,
                 weaponentity,
@@ -424,7 +424,7 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent
                 WEP_CVAR_SEC(vaporizer, delay),
                 WEP_CVAR_SEC(vaporizer, lifetime)
             );
-            PS(actor).m_weapon = oldwep;
+            actor.(weaponentity).m_weapon = oldwep;
 
             // now do normal refire
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready);
index bf3ce81..660c754 100644 (file)
@@ -148,7 +148,8 @@ MUTATOR_HOOKFUNCTION(vortex_charge, GetPressedKeys)
 
        // WEAPONTODO
        float xyspeed = vlen(vec2(player.velocity));
-       if (PS(player).m_weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+    .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       if (player.(weaponentity).m_weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
        {
                // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
                xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
@@ -193,7 +194,7 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float i
 
        yoda = 0;
        damage_goodhits = 0;
-       FireRailgunBullet(actor, w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_VORTEX.m_id);
+       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_VORTEX.m_id);
 
        if(yoda && flying)
                Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
@@ -208,7 +209,7 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float i
        //beam and muzzle flash done on client
        SendCSQCVortexBeamParticle(charge);
 
-       W_DecreaseAmmo(thiswep, actor, myammo);
+       W_DecreaseAmmo(thiswep, actor, myammo, weaponentity);
 }
 
 .float vortex_chargepool_pauseregen_finished;
diff --git a/qcsrc/common/wepent.qc b/qcsrc/common/wepent.qc
new file mode 100644 (file)
index 0000000..0368678
--- /dev/null
@@ -0,0 +1,134 @@
+#include "wepent.qh"
+
+#define WEPENT_SET_NORMAL(var, x) MACRO_BEGIN \
+       var = x; \
+MACRO_END
+
+/** the engine player name strings are mutable! */
+#define WEPENT_SET_MUTABLE_STRING(var, x) MACRO_BEGIN \
+       if (var) strunzone(var); \
+       var = strzone(x); \
+MACRO_END
+
+.int w_sv_entnum;
+.Weapon w_m_switchweapon;
+.Weapon w_m_switchingweapon;
+.Weapon w_m_weapon;
+//.float w_weapon_nextthink;
+
+// #define PROP(public, fld, set, sv, cl)
+#define WEPENT_NETPROPS(PROP) PROP(false, sv_entnum, WEPENT_SET_NORMAL, {}, {}) /* sentinel */ \
+       PROP(false, m_switchweapon, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_switchweapon.m_id); }, \
+       { (viewmodels[this.m_wepent_slot]).switchweapon = Weapons_from(ReadByte()); }) \
+    \
+    PROP(false, m_switchingweapon, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_switchingweapon.m_id); }, \
+       { (viewmodels[this.m_wepent_slot]).switchingweapon = Weapons_from(ReadByte()); }) \
+    \
+    PROP(false, m_weapon, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_weapon.m_id); }, \
+       { (viewmodels[this.m_wepent_slot]).activeweapon = Weapons_from(ReadByte()); }) \
+    \
+       /**/
+
+#ifdef SVQC
+
+       int WEPENT_PUBLICMASK = 0;
+       STATIC_INIT(WEPENT_PUBLICMASK)
+       {
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (public) { \
+                               WEPENT_PUBLICMASK |= BIT(i); \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+               if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded WEPENT_NETPROPS limit");
+       }
+
+       bool _wepent_send(entity this, entity to, int sf, int chan)
+       {
+               sf |= this.m_forceupdate;
+               this.m_forceupdate = 0;
+               if (chan == MSG_ENTITY)
+                       WriteHeader(chan, ENT_CLIENT_WEPENT);
+               else
+                       WriteHeader(chan, CLIENT_WEPENT);
+               .entity weaponentity = this.weaponentity_fld;
+               WriteByte(chan, weaponslot(weaponentity));
+               WriteShort(chan, sf);
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (sf & BIT(i)) { \
+                               sv; \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+               return true;
+       }
+
+       bool wepent_send(entity this, entity to, int sf)
+       {
+               return _wepent_send(this, to, sf, MSG_ENTITY);
+       }
+
+       void wepent_update(entity this)
+       {
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (this.w_##fld != this.fld) { \
+                               set(this.w_##fld, this.fld); \
+                               this.SendFlags |= BIT(i); \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+       }
+
+       void wepent_link(entity wep)
+       {
+               Net_LinkEntity(wep, false, 0, wepent_send);
+       }
+
+#endif
+
+#ifdef CSQC
+
+       bool ReadWepent(entity this)
+       {
+               this.m_wepent_slot = ReadByte();
+               int sf = ReadShort();
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (sf & BIT(i)) { \
+                               cl; \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+               return true;
+       }
+
+       NET_HANDLE(ENT_CLIENT_WEPENT, bool isnew)
+       {
+               if (isnew)
+               {
+                       make_pure(this);
+                       this.classname = "wepent_receiver";
+               }
+               return ReadWepent(this);
+       }
+
+       NET_HANDLE(CLIENT_WEPENT, bool isnew)
+       {
+               return ReadWepent(NULL);
+       }
+
+#endif
diff --git a/qcsrc/common/wepent.qh b/qcsrc/common/wepent.qh
new file mode 100644 (file)
index 0000000..7729601
--- /dev/null
@@ -0,0 +1,28 @@
+#pragma once
+
+REGISTER_NET_LINKED(ENT_CLIENT_WEPENT)
+REGISTER_NET_TEMP(CLIENT_WEPENT)
+
+#ifdef SVQC
+
+       bool wepent_send(entity this, entity to, int sf);
+
+       void wepent_update(entity this);
+
+       void wepent_link(entity wep);
+
+       .int m_forceupdate;
+
+       .Weapon m_switchweapon;
+       .Weapon m_weapon;
+       .Weapon m_switchingweapon;
+
+#endif
+
+#ifdef CSQC
+       .int m_wepent_slot;
+
+       .Weapon activeweapon;
+       .Weapon switchingweapon;
+       .Weapon switchweapon;
+#endif
index 1624676..46d1775 100644 (file)
@@ -339,16 +339,18 @@ bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshott
        hf = this.dphitcontentsmask;
        this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        shotspeed *= W_WeaponSpeedFactor(this);
        shotspeedupward *= W_WeaponSpeedFactor(this);
        if (!shotspeed)
        {
-               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " shotspeed is zero!");
+               LOG_TRACE("bot_aim: WARNING: weapon ", this.(weaponentity).m_weapon.m_name, " shotspeed is zero!");
                shotspeed = 1000000;
        }
        if (!maxshottime)
        {
-               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " maxshottime is zero!");
+               LOG_TRACE("bot_aim: WARNING: weapon ", this.(weaponentity).m_weapon.m_name, " maxshottime is zero!");
                maxshottime = 1;
        }
        makevectors(this.v_angle);
index 45051b6..b3bc26b 100644 (file)
@@ -98,7 +98,8 @@ void havocbot_ai(entity this)
 
                if(this.weapons)
                {
-                       Weapon w = PS(this).m_weapon;
+                       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+                       Weapon w = this.(weaponentity).m_weapon;
                        w.wr_aim(w, this);
                        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
                        {
@@ -108,7 +109,7 @@ void havocbot_ai(entity this)
                        else
                        {
                                if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))
-                                       this.lastfiredweapon = PS(this).m_weapon.m_id;
+                                       this.lastfiredweapon = this.(weaponentity).m_weapon.m_id;
                        }
                }
                else
@@ -165,9 +166,10 @@ void havocbot_ai(entity this)
                if(skill >= 5) // bots can only look for unloaded weapons past this skill
                if(this.clip_load >= 0) // only if we're not reloading a weapon already
                {
+                       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                        FOREACH(Weapons, it != WEP_Null, LAMBDA(
                                if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.weapon_load[it.m_id] < it.reloading_ammo))
-                                       PS(this).m_switchweapon = it;
+                                       this.(weaponentity).m_switchweapon = it;
                        ));
                }
        }
@@ -598,7 +600,8 @@ void havocbot_movetogoal(entity this)
                                        return;
                                }
 
-                               PS(this).m_switchweapon = WEP_DEVASTATOR;
+                               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+                               this.(weaponentity).m_switchweapon = WEP_DEVASTATOR;
                                this.v_angle_x = 90;
                                PHYS_INPUT_BUTTON_ATCK(this) = true;
                                this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
@@ -1009,10 +1012,12 @@ void havocbot_chooseweapon(entity this)
 {
        int i;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        // ;)
        if(g_weaponarena_weapons == WEPSET(TUBA))
        {
-               PS(this).m_switchweapon = WEP_TUBA;
+               this.(weaponentity).m_switchweapon = WEP_TUBA;
                return;
        }
 
@@ -1020,11 +1025,11 @@ void havocbot_chooseweapon(entity this)
        if(this.enemy==NULL)
        {
                // If no weapon was chosen get the first available weapon
-               if(PS(this).m_weapon==WEP_Null)
+               if(this.(weaponentity).m_weapon==WEP_Null)
                FOREACH(Weapons, it != WEP_Null, LAMBDA(
                        if(client_hasweapon(this, it, true, false))
                        {
-                               PS(this).m_switchweapon = it;
+                               this.(weaponentity).m_switchweapon = it;
                                return;
                        }
                ));
@@ -1052,7 +1057,7 @@ void havocbot_chooseweapon(entity this)
        combo = false;
 
        if(autocvar_bot_ai_weapon_combo)
-       if(PS(this).m_weapon.m_id == this.lastfiredweapon)
+       if(this.(weaponentity).m_weapon.m_id == this.lastfiredweapon)
        if(af > combo_time)
        {
                combo = true;
@@ -1070,9 +1075,9 @@ void havocbot_chooseweapon(entity this)
                                w = bot_weapons_far[i];
                                if ( client_hasweapon(this, Weapons_from(w), true, false) )
                                {
-                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                       if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
                                                continue;
-                                       PS(this).m_switchweapon = Weapons_from(w);
+                                       this.(weaponentity).m_switchweapon = Weapons_from(w);
                                        return;
                                }
                        }
@@ -1084,9 +1089,9 @@ void havocbot_chooseweapon(entity this)
                                w = bot_weapons_mid[i];
                                if ( client_hasweapon(this, Weapons_from(w), true, false) )
                                {
-                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                       if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
                                                continue;
-                                       PS(this).m_switchweapon = Weapons_from(w);
+                                       this.(weaponentity).m_switchweapon = Weapons_from(w);
                                        return;
                                }
                        }
@@ -1097,9 +1102,9 @@ void havocbot_chooseweapon(entity this)
                        w = bot_weapons_close[i];
                        if ( client_hasweapon(this, Weapons_from(w), true, false) )
                        {
-                               if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                               if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
                                        continue;
-                               PS(this).m_switchweapon = Weapons_from(w);
+                               this.(weaponentity).m_switchweapon = Weapons_from(w);
                                return;
                        }
                }
index e835557..19baa58 100644 (file)
@@ -568,8 +568,10 @@ float bot_cmd_select_weapon(entity this)
        if(id < WEP_FIRST || id > WEP_LAST)
                return CMD_STATUS_ERROR;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        if(client_hasweapon(this, Weapons_from(id), true, false))
-               PS(this).m_switchweapon = Weapons_from(id);
+               this.(weaponentity).m_switchweapon = Weapons_from(id);
        else
                return CMD_STATUS_ERROR;
 
@@ -1054,7 +1056,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(f)
                {
                        this.colormod = '0 8 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by weaponentity state\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by weaponentity state\n");
                }
        }
        else if(ATTACK_FINISHED(this, slot) > time)
@@ -1062,7 +1064,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(f)
                {
                        this.colormod = '8 0 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n");
                }
        }
        else if(this.tuba_note)
@@ -1070,7 +1072,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(f)
                {
                        this.colormod = '8 0 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, bot still has an active tuba note\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, bot still has an active tuba note\n");
                }
        }
        else
@@ -1078,7 +1080,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(!f)
                {
                        this.colormod = '8 8 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n");
                }
        }
 
index e42807e..b3e87e0 100644 (file)
@@ -23,6 +23,7 @@
 #include "bot/api.qh"
 
 #include "../common/ent_cs.qh"
+#include "../common/wepent.qh"
 #include <common/state.qh>
 
 #include <common/effects/qc/globalsound.qh>
@@ -342,10 +343,10 @@ void PutObserverInServer(entity this)
        this.weapons = '0 0 0';
        this.drawonlytoclient = this;
 
-       this.weaponname = "";
        this.weaponmodel = "";
        for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
+               this.weaponentities[slot].weaponname = "";
                this.weaponentities[slot] = NULL;
        }
        this.exteriorweaponentity = NULL;
@@ -691,11 +692,18 @@ void PutClientInServer(entity this)
                        delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
                }
 
-               PS(this).m_switchweapon = w_getbestweapon(this);
-               this.cnt = -1; // W_LastWeapon will not complain
-               PS(this).m_weapon = WEP_Null;
-               this.weaponname = "";
-               PS(this).m_switchingweapon = WEP_Null;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(slot == 0)
+                               this.(weaponentity).m_switchweapon = w_getbestweapon(this);
+                       else
+                               this.(weaponentity).m_switchweapon = WEP_Null;
+                       this.(weaponentity).weaponname = "";
+                       this.(weaponentity).m_switchingweapon = WEP_Null;
+               }
+
+               this.cnt = -1; // TODO
 
                if (!warmup_stage && !this.alivetime)
                        this.alivetime = time;
@@ -2421,13 +2429,11 @@ void PlayerPreThink (entity this)
                {
                        this.items &= ~this.items_added;
 
-                       //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);
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               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))
@@ -2465,11 +2471,12 @@ void PlayerPreThink (entity this)
        }
 
        // WEAPONTODO: Add weapon request for this
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
        if (!zoomstate_set) {
                SetZoomState(this,
                        PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this)
-                       || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_VORTEX)
-                       || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
+                       || (PHYS_INPUT_BUTTON_ATCK2(this) && this.(weaponentity).m_weapon == WEP_VORTEX)
+                       || (PHYS_INPUT_BUTTON_ATCK2(this) && this.(weaponentity).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
                );
     }
 
@@ -2493,7 +2500,7 @@ void PlayerPreThink (entity this)
 
        // WEAPONTODO: Move into weaponsystem somehow
        // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
-       if (PS(this).m_weapon == WEP_Null)
+       if (this.(weaponentity).m_weapon == WEP_Null)
                this.clip_load = this.clip_size = 0;
 }
 
index b034968..ce9d174 100644 (file)
@@ -210,7 +210,7 @@ float bot_waypoints_for_items;
 #else
 #define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).attack_finished_single[slot])
 #endif
-#define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, PS(ent).m_weapon.m_id, slot)
+#define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, ent.(weaponentity).m_weapon.m_id, slot)
 
 // assault game mode: Which team is attacking in this round?
 float assault_attacker_team;
index cb43861..7a28ae7 100644 (file)
@@ -58,13 +58,15 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 
        PlayerScore_Add(targ, SP_DEATHS, 1);
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        if(targ != attacker) // not for suicides
        if(g_weaponarena_random)
        {
                // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
                Weapon culprit = DEATH_WEAPONOF(deathtype);
-               if(!culprit) culprit = PS(attacker).m_weapon;
-               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = PS(attacker).m_weapon;
+               if(!culprit) culprit = attacker.(weaponentity).m_weapon;
+               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = attacker.(weaponentity).m_weapon;
 
                if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
                {
@@ -97,8 +99,8 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
                }
 
                // after a frag, choose another random weapon set
-               if (!(attacker.weapons & WepSet_FromWeapon(PS(attacker).m_weapon)))
-                       W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
+               if (!(attacker.weapons & WepSet_FromWeapon(attacker.(weaponentity).m_weapon)))
+                       W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker), weaponentity);
        }
 
        // FIXME fix the mess this is (we have REAL points now!)
@@ -115,7 +117,9 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 
 string AppendItemcodes(string s, entity player)
 {
-       int w = PS(player).m_weapon.m_id;
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
+       int w = player.(weaponentity).m_weapon.m_id;
        //if(w == 0)
        //      w = player.switchweapon;
        if(w == 0)
index 019c8fc..9a4a8b9 100644 (file)
@@ -55,7 +55,7 @@ float IsFlying(entity a);
 void UpdateFrags(entity player, int f);
 
 // NOTE: f=0 means still count as a (positive) kill, but count no frags for it
-void W_SwitchWeapon_Force(Player this, Weapon w);
+void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
 entity GiveFrags_randomweapons;
 void GiveFrags (entity attacker, entity targ, float f, int deathtype);
 
index fe7822b..4af2430 100644 (file)
@@ -2081,10 +2081,6 @@ void EndFrame()
        {
                antilag_record(it, it, altime);
        });
-       FOREACH_CLIENT(PS(it), {
-               PlayerState s = PS(it);
-               s.ps_push(s, it);
-       });
        systems_update();
        IL_ENDFRAME();
 }
index 8a10a6d..0324212 100644 (file)
@@ -60,7 +60,8 @@
                        this.impulse = IMP_weapon_group_##slot.impulse; \
                        return; \
                } \
-               W_NextWeaponOnImpulse(this, slot); \
+               .entity weaponentity = weaponentities[0]; \
+               W_NextWeaponOnImpulse(this, slot, weaponentity); \
        }
 X(1)
 X(2)
@@ -88,7 +89,8 @@ X(0)
                noref int prev = -1; \
                noref int best =  0; \
                noref int next = +1; \
-               W_CycleWeapon(this, this.cvar_cl_weaponpriorities[slot], dir); \
+               .entity weaponentity = weaponentities[0]; \
+               W_CycleWeapon(this, this.cvar_cl_weaponpriorities[slot], dir, weaponentity); \
        }
 X(0, prev)
 X(1, prev)
@@ -135,7 +137,8 @@ X(9, next)
                        this.impulse = IMP_weapon_byid_##i.impulse; \
                        return; \
                } \
-               W_SwitchWeapon(this, Weapons_from(WEP_FIRST + i)); \
+               .entity weaponentity = weaponentities[0]; \
+               W_SwitchWeapon(this, Weapons_from(WEP_FIRST + i), weaponentity); \
        }
 X(0)
 X(1)
@@ -171,7 +174,8 @@ IMPULSE(weapon_next_byid)
                this.impulse = IMP_weapon_next_byid.impulse;
                return;
        }
-       W_NextWeapon(this, 0);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_NextWeapon(this, 0, weaponentity);
 }
 
 IMPULSE(weapon_prev_byid)
@@ -182,7 +186,8 @@ IMPULSE(weapon_prev_byid)
                this.impulse = IMP_weapon_prev_byid.impulse;
                return;
        }
-       W_PreviousWeapon(this, 0);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_PreviousWeapon(this, 0, weaponentity);
 }
 
 IMPULSE(weapon_next_bygroup)
@@ -193,7 +198,8 @@ IMPULSE(weapon_next_bygroup)
                this.impulse = IMP_weapon_next_bygroup.impulse;
                return;
        }
-       W_NextWeapon(this, 1);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_NextWeapon(this, 1, weaponentity);
 }
 
 IMPULSE(weapon_prev_bygroup)
@@ -204,7 +210,8 @@ IMPULSE(weapon_prev_bygroup)
                this.impulse = IMP_weapon_prev_bygroup.impulse;
                return;
        }
-       W_PreviousWeapon(this, 1);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_PreviousWeapon(this, 1, weaponentity);
 }
 
 IMPULSE(weapon_next_bypriority)
@@ -215,7 +222,8 @@ IMPULSE(weapon_next_bypriority)
                this.impulse = IMP_weapon_next_bypriority.impulse;
                return;
        }
-       W_NextWeapon(this, 2);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_NextWeapon(this, 2, weaponentity);
 }
 
 IMPULSE(weapon_prev_bypriority)
@@ -226,28 +234,32 @@ IMPULSE(weapon_prev_bypriority)
                this.impulse = IMP_weapon_prev_bypriority.impulse;
                return;
        }
-       W_PreviousWeapon(this, 2);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_PreviousWeapon(this, 2, weaponentity);
 }
 
 IMPULSE(weapon_last)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_LastWeapon(this);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_LastWeapon(this, weaponentity);
 }
 
 IMPULSE(weapon_best)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_SwitchWeapon(this, w_getbestweapon(this));
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_SwitchWeapon(this, w_getbestweapon(this), weaponentity);
 }
 
 IMPULSE(weapon_drop)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_ThrowWeapon(this, weaponentities[0], W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+       W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
 }
 
 IMPULSE(weapon_reload)
@@ -255,11 +267,11 @@ IMPULSE(weapon_reload)
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
        if (forbidWeaponUse(this)) return;
-       Weapon w = PS(this).m_weapon;
        entity actor = this;
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
                .entity weaponentity = weaponentities[slot];
+               Weapon w = this.(weaponentity).m_weapon;
                w.wr_reload(w, actor, weaponentity);
        }
 }
index 4b3d404..00e33f0 100644 (file)
@@ -259,6 +259,8 @@ string formatmessage(entity this, string msg)
                replacement = substring(msg, p, 2);
                escape = substring(msg, p + 1, 1);
 
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
                switch(escape)
                {
                        case "%": replacement = "%"; break;
@@ -269,7 +271,7 @@ string formatmessage(entity this, string msg)
                        case "l": replacement = NearestLocation(this.origin); break;
                        case "y": replacement = NearestLocation(cursor); break;
                        case "d": replacement = NearestLocation(this.death_origin); break;
-                       case "w": replacement = ((PS(this).m_weapon == WEP_Null) ? ((PS(this).m_switchweapon == WEP_Null) ? Weapons_from(this.cnt) : PS(this).m_switchweapon) : PS(this).m_weapon).m_name; break;
+                       case "w": replacement = ((this.(weaponentity).m_weapon == WEP_Null) ? ((this.(weaponentity).m_switchweapon == WEP_Null) ? Weapons_from(this.cnt) : this.(weaponentity).m_switchweapon) : this.(weaponentity).m_weapon).m_name; break;
                        case "W": replacement = ammoitems; break;
                        case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
                        case "s": replacement = ftos(vlen(this.velocity - this.velocity_z * '0 0 1')); break;
@@ -446,8 +448,9 @@ void GetCvars(entity this, int f)
        // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early)
        if (f > 0)
        {
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                if (s == "cl_weaponpriority")
-                       if (PS(this)) PS(this).m_switchweapon = w_getbestweapon(this);
+                       if (this.(weaponentity)) this.(weaponentity).m_switchweapon = w_getbestweapon(this);
                if (s == "cl_allow_uidtracking")
                        PlayerStats_GameReport_AddPlayer(this);
        }
index e270f38..6bfee14 100644 (file)
@@ -486,6 +486,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
        valid_damage_for_weaponstats = 0;
        Weapon awep = WEP_Null;
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 
        if(vbot || IS_REAL_CLIENT(this))
        if(abot || IS_REAL_CLIENT(attacker))
@@ -493,7 +494,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        if(DIFF_TEAM(this, attacker))
        {
                if(DEATH_ISSPECIAL(deathtype))
-                       awep = PS(attacker).m_weapon;
+                       awep = attacker.(weaponentity).m_weapon;
                else
                        awep = DEATH_WEAPONOF(deathtype);
                valid_damage_for_weaponstats = 1;
@@ -503,7 +504,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        da = da - max(this.armorvalue, 0);
        if(valid_damage_for_weaponstats)
        {
-               WeaponStats_LogDamage(awep.m_id, abot, PS(this).m_weapon.m_id, vbot, dh + da);
+               WeaponStats_LogDamage(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot, dh + da);
        }
        if (dh + da)
        {
@@ -522,7 +523,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                }
 
                if(valid_damage_for_weaponstats)
-                       WeaponStats_LogKill(awep.m_id, abot, PS(this).m_weapon.m_id, vbot);
+                       WeaponStats_LogKill(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot);
 
                if(autocvar_sv_gentle < 1)
                if(sound_allowed(MSG_BROADCAST, attacker))
@@ -561,13 +562,12 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype, damage);
                excess = M_ARGV(4, float);
 
-               Weapon wep = PS(this).m_weapon;
+               Weapon wep = this.(weaponentity).m_weapon;
                /*for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
                        .entity weaponentity = weaponentities[slot];
                        wep.wr_playerdeath(wep, this, weaponentity);
                }*/
-               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
                wep.wr_playerdeath(wep, this, weaponentity);
 
                RemoveGrapplingHook(this);
@@ -592,7 +592,8 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                // clear waypoints
                WaypointSprite_PlayerDead(this);
                // throw a weapon
-               SpawnThrownWeapon(this, this.origin + (this.mins + this.maxs) * 0.5, PS(this).m_switchweapon.m_id);
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+               SpawnThrownWeapon(this, this.origin + (this.mins + this.maxs) * 0.5, this.(weaponentity).m_switchweapon.m_id, weaponentity);
 
                // become fully visible
                this.alpha = default_player_alpha;
index 96674db..388c4af 100644 (file)
@@ -25,8 +25,9 @@ TEST(Weapons, Hurt)
     PHYS_INPUT_BUTTON_ATCK(it) = true;
     it.items |= IT_UNLIMITED_AMMO;
     Weapon wep = WEP_VORTEX;
+    .entity weaponentity = weaponentities[0]; // TODO: unhardcode
     W_GiveWeapon(it, wep.m_id);
-    W_SwitchWeapon_Force(it, wep);
+    W_SwitchWeapon_Force(it, wep, weaponentity);
 
     it = b;
     PHYS_INPUT_BUTTON_JUMP(it) = true;
index 372f735..2e1c405 100644 (file)
@@ -73,7 +73,8 @@ void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright,
                        antilag_takeback(trace_ent, store, time - lag);
                        hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos);
                        antilag_restore(trace_ent, store);
-                       fputs(player.hitplotfh, strcat(ftos(hitplot.x), " ", ftos(hitplot.y), " ", ftos(hitplot.z), " ", ftos(PS(player).m_switchweapon.m_id), "\n"));
+                       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+                       fputs(player.hitplotfh, strcat(ftos(hitplot.x), " ", ftos(hitplot.y), " ", ftos(hitplot.z), " ", ftos(player.(weaponentity).m_switchweapon.m_id), "\n"));
                        //print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n"));
                }
        }
index 56df6c3..da66310 100644 (file)
@@ -119,7 +119,7 @@ bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
        return false;
 }
 
-float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing)
+float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing, .entity weaponentity)
 {
        // We cannot tokenize in this function, as GiveItems calls this
        // function. Thus we must use car/cdr.
@@ -130,10 +130,10 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
        float weaponcur;
        entity wep;
 
-       if(skipmissing || this.selectweapon == 0)
-               weaponcur = PS(this).m_switchweapon.m_id;
+       if(skipmissing || this.(weaponentity).selectweapon == 0)
+               weaponcur = this.(weaponentity).m_switchweapon.m_id;
        else
-               weaponcur = this.selectweapon;
+               weaponcur = this.(weaponentity).selectweapon;
 
        if(dir == 0)
                switchtonext = 1;
@@ -231,20 +231,20 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
        return 0;
 }
 
-void W_SwitchWeapon_Force(Player this, Weapon wep)
+void W_SwitchWeapon_Force(Player this, Weapon wep, .entity weaponentity)
 {
-    TC(Player, this); TC(Weapon, wep);
-       this.cnt = PS(this).m_switchweapon.m_id;
-       PS(this).m_switchweapon = wep;
-       this.selectweapon = wep.m_id;
+    TC(Weapon, wep);
+       this.(weaponentity).cnt = this.(weaponentity).m_switchweapon.m_id;
+       this.(weaponentity).m_switchweapon = wep;
+       this.(weaponentity).selectweapon = wep.m_id;
 }
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity this)
+void W_SwitchToOtherWeapon(entity this, .entity weaponentity)
 {
        // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
        Weapon ww;
-       WepSet set = WepSet_FromWeapon(PS(this).m_weapon);
+       WepSet set = WepSet_FromWeapon(this.(weaponentity).m_weapon);
        if (this.weapons & set)
        {
                this.weapons &= ~set;
@@ -256,72 +256,69 @@ void W_SwitchToOtherWeapon(entity this)
                ww = w_getbestweapon(this);
        }
        if (ww == WEP_Null) return;
-       W_SwitchWeapon_Force(this, ww);
+       W_SwitchWeapon_Force(this, ww, weaponentity);
 }
 
-void W_SwitchWeapon(entity this, Weapon w)
+void W_SwitchWeapon(entity this, Weapon w, .entity weaponentity)
 {
-       if (PS(this).m_switchweapon != w)
+       if(this.(weaponentity).m_switchweapon != w)
        {
-               if (client_hasweapon(this, w, true, true))
-                       W_SwitchWeapon_Force(this, w);
+               if(client_hasweapon(this, w, true, true))
+                       W_SwitchWeapon_Force(this, w, weaponentity);
                else
-                       this.selectweapon = w.m_id; // update selectweapon ANYWAY
+                       this.(weaponentity).selectweapon = w.m_id; // update selectweapon anyway
        }
-       else if(!forbidWeaponUse(this)) {
+       else if(!forbidWeaponUse(this))
+       {
                entity actor = this;
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-               {
-                       .entity weaponentity = weaponentities[slot];
-                       w.wr_reload(w, actor, weaponentity);
-               }
+               w.wr_reload(w, actor, weaponentity);
        }
 }
 
-void W_CycleWeapon(entity this, string weaponorder, float dir)
+void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity)
 {
        float w;
-       w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true);
+       w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true, weaponentity);
        if(w > 0)
-               W_SwitchWeapon(this, Weapons_from(w));
+               W_SwitchWeapon(this, Weapons_from(w), weaponentity);
 }
 
-void W_NextWeaponOnImpulse(entity this, float imp)
+void W_NextWeaponOnImpulse(entity this, float imp, .entity weaponentity)
 {
        float w;
-       w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0));
+       w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0), weaponentity);
        if(w > 0)
-               W_SwitchWeapon(this, Weapons_from(w));
+               W_SwitchWeapon(this, Weapons_from(w), weaponentity);
 }
 
 // next weapon
-void W_NextWeapon(entity this, int list)
+void W_NextWeapon(entity this, int list, .entity weaponentity)
 {
        if(list == 0)
-               W_CycleWeapon(this, weaponorder_byid, -1);
+               W_CycleWeapon(this, weaponorder_byid, -1, weaponentity);
        else if(list == 1)
-               W_CycleWeapon(this, this.weaponorder_byimpulse, -1);
+               W_CycleWeapon(this, this.weaponorder_byimpulse, -1, weaponentity);
        else if(list == 2)
-               W_CycleWeapon(this, this.cvar_cl_weaponpriority, -1);
+               W_CycleWeapon(this, this.cvar_cl_weaponpriority, -1, weaponentity);
 }
 
 // prev weapon
-void W_PreviousWeapon(entity this, float list)
+void W_PreviousWeapon(entity this, float list, .entity weaponentity)
 {
        if(list == 0)
-               W_CycleWeapon(this, weaponorder_byid, +1);
+               W_CycleWeapon(this, weaponorder_byid, +1, weaponentity);
        else if(list == 1)
-               W_CycleWeapon(this, this.weaponorder_byimpulse, +1);
+               W_CycleWeapon(this, this.weaponorder_byimpulse, +1, weaponentity);
        else if(list == 2)
-               W_CycleWeapon(this, this.cvar_cl_weaponpriority, +1);
+               W_CycleWeapon(this, this.cvar_cl_weaponpriority, +1, weaponentity);
 }
 
 // previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(entity this)
+void W_LastWeapon(entity this, .entity weaponentity)
 {
        Weapon wep = Weapons_from(this.cnt);
        if (client_hasweapon(this, wep, true, false))
-               W_SwitchWeapon(this, wep);
+               W_SwitchWeapon(this, wep, weaponentity);
        else
-               W_SwitchToOtherWeapon(this);
+               W_SwitchToOtherWeapon(this, weaponentity);
 }
index 0c30b7c..336dc13 100644 (file)
@@ -7,25 +7,26 @@ void Send_WeaponComplain(entity e, float wpn, float type);
 bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain);
 
 .int weaponcomplainindex;
-float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing);
+float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing, .entity weaponentity);
 
-#define w_getbestweapon(ent) Weapons_from(W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true))
+// TODO: unhardcode
+#define w_getbestweapon(ent) Weapons_from(W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true, weaponentities[0]))
 
-void W_SwitchWeapon_Force(Player this, Weapon w);
+void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity this);
-void W_SwitchWeapon(entity this, Weapon imp);
+void W_SwitchToOtherWeapon(entity this, .entity weaponentity);
+void W_SwitchWeapon(entity this, Weapon imp, .entity weaponentity);
 
-void W_CycleWeapon(entity this, string weaponorder, float dir);
+void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity);
 
-void W_NextWeaponOnImpulse(entity this, float imp);
+void W_NextWeaponOnImpulse(entity this, float imp, .entity weaponentity);
 
 // next weapon
-void W_NextWeapon(entity this, float list);
+void W_NextWeapon(entity this, float list, .entity weaponentity);
 
 // prev weapon
-void W_PreviousWeapon(entity this, float list);
+void W_PreviousWeapon(entity this, float list, .entity weaponentity);
 
 // previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(entity this);
+void W_LastWeapon(entity this, .entity weaponentity);
index bd69e33..47531ec 100644 (file)
@@ -31,7 +31,7 @@ void thrown_wep_think(entity this)
 }
 
 // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
+string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity)
 {
        float thisammo;
        string s;
@@ -97,7 +97,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                if(doreduce && g_weapon_stay == 2)
                {
                        // if our weapon is loaded, give its load back to the player
-                       int i = PS(own).m_weapon.m_id;
+                       int i = own.(weaponentity).m_weapon.m_id;
                        if(own.(weapon_load[i]) > 0)
                        {
                                own.(ammotype) += own.(weapon_load[i]);
@@ -109,7 +109,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                else if(doreduce)
                {
                        // if our weapon is loaded, give its load back to the player
-                       int i = PS(own).m_weapon.m_id;
+                       int i = own.(weaponentity).m_weapon.m_id;
                        if(own.(weapon_load[i]) > 0)
                        {
                                own.(ammotype) += own.(weapon_load[i]);
@@ -167,7 +167,7 @@ bool W_IsWeaponThrowable(entity this, int w)
 // toss current weapon
 void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta, float doreduce)
 {
-       Weapon w = PS(this).m_weapon;
+       Weapon w = this.(weaponentity).m_weapon;
        if (w == WEP_Null)
                return; // just in case
        if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon, this))
@@ -183,16 +183,16 @@ void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta,
        if(!(this.weapons & set)) return;
        this.weapons &= ~set;
 
-       W_SwitchWeapon_Force(this, w_getbestweapon(this));
-       string a = W_ThrowNewWeapon(this, w.m_id, doreduce, this.origin + delta, velo);
+       W_SwitchWeapon_Force(this, w_getbestweapon(this), weaponentity);
+       string a = W_ThrowNewWeapon(this, w.m_id, doreduce, this.origin + delta, velo, weaponentity);
 
        if(!a) return;
        Send_Notification(NOTIF_ONE, this, MSG_MULTI, ITEM_WEAPON_DROP, a, w.m_id);
 }
 
-void SpawnThrownWeapon(entity this, vector org, float w)
+void SpawnThrownWeapon(entity this, vector org, float w, .entity weaponentity)
 {
-       if(this.weapons & WepSet_FromWeapon(PS(this).m_weapon))
-               if(W_IsWeaponThrowable(this, PS(this).m_weapon.m_id))
-                       W_ThrowNewWeapon(this, PS(this).m_weapon.m_id, false, org, randomvec() * 125 + '0 0 200');
+       if(this.weapons & WepSet_FromWeapon(this.(weaponentity).m_weapon))
+               if(W_IsWeaponThrowable(this, this.(weaponentity).m_weapon.m_id))
+                       W_ThrowNewWeapon(this, this.(weaponentity).m_weapon.m_id, false, org, randomvec() * 125 + '0 0 200', weaponentity);
 }
index a039680..01ab21b 100644 (file)
@@ -4,11 +4,11 @@
 void thrown_wep_think(entity this);
 
 // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
+string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity);
 
 bool W_IsWeaponThrowable(entity this, int w);
 
 // toss current weapon
 void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta, float doreduce);
 
-void SpawnThrownWeapon(entity this, vector org, float w);
+void SpawnThrownWeapon(entity this, vector org, float w, .entity weaponentity);
index 3b7aa7b..1f7f594 100644 (file)
@@ -27,7 +27,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
        float oldsolid;
        vector vecs, dv;
        oldsolid = ent.dphitcontentsmask;
-       if (IS_PLAYER(ent) && PS(ent).m_weapon == WEP_RIFLE)
+       if (IS_PLAYER(ent) && ent.(weaponentity).m_weapon == WEP_RIFLE)
                ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
        else
                ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
@@ -53,7 +53,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
 
        // track max damage
        if (IS_PLAYER(ent) && accuracy_canbegooddamage(ent))
-               accuracy_add(ent, PS(ent).m_weapon.m_id, maxdamage, 0);
+               accuracy_add(ent, ent.(weaponentity).m_weapon.m_id, maxdamage, 0);
 
        if(IS_PLAYER(ent))
                W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
@@ -196,7 +196,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 //  Ballistics Tracing
 // ====================
 
-void FireRailgunBullet (entity this, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
+void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
 {
        vector hitloc, force, endpoint, dir;
        entity ent, endent;
@@ -333,7 +333,7 @@ void FireRailgunBullet (entity this, vector start, vector end, float bdamage, fl
        }
 
        // calculate hits and fired shots for hitscan
-       accuracy_add(this, PS(this).m_weapon.m_id, 0, min(bdamage, totaldmg));
+       accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, min(bdamage, totaldmg));
 
        trace_endpos = endpoint;
        trace_ent = endent;
@@ -348,7 +348,7 @@ void fireBullet_trace_callback(vector start, vector hit, vector end)
        fireBullet_last_hit = NULL;
 }
 
-void fireBullet(entity this, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
+void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
 {
        vector  end;
 
@@ -441,7 +441,7 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s
                                // do not exceed 100%
                                float added_damage = min(damage - total_damage, damage * solid_penetration_left);
                                total_damage += damage * solid_penetration_left;
-                               accuracy_add(this, PS(this).m_weapon.m_id, 0, added_damage);
+                               accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, added_damage);
                        }
                }
 
index 21f12c1..aec2741 100644 (file)
@@ -49,9 +49,9 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 
 .float railgundistance;
 .vector railgunforce;
-void FireRailgunBullet (entity this, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype);
+void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype);
 
 entity fireBullet_trace_callback_eff;
 entity fireBullet_last_hit;
 void fireBullet_trace_callback(vector start, vector hit, vector end);
-void fireBullet(entity this, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects);
+void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects);
index 4968d3c..3b8047e 100644 (file)
@@ -62,6 +62,9 @@ vector CL_Weapon_GetShotOrg(int wpn)
 
 ..entity weaponentity_fld;
 .float m_alpha;
+.string w_weaponname;
+.int w_dmg;
+.int w_deadflag;
 
 void CL_Weaponentity_Think(entity this)
 {
@@ -82,16 +85,16 @@ void CL_Weaponentity_Think(entity this)
                if (this.weaponchild) this.weaponchild.model = "";
                return;
        }
-       if (this.weaponname != this.owner.weaponname
-           || this.dmg != this.owner.modelindex
-           || this.deadflag != this.owner.deadflag)
+       if (this.w_weaponname != this.weaponname
+           || this.w_dmg != this.modelindex
+           || this.w_deadflag != this.deadflag)
        {
                // owner changed weapons; update appearance
-               this.weaponname = this.owner.weaponname;
-               this.dmg = this.owner.modelindex;
-               this.deadflag = this.owner.deadflag;
+               this.w_weaponname = this.weaponname;
+               this.w_dmg = this.modelindex;
+               this.w_deadflag = this.deadflag;
 
-               CL_WeaponEntity_SetModel(this, this.owner.weaponname, true);
+               CL_WeaponEntity_SetModel(this, this.weaponname, true);
        }
 
        this.alpha = -1;  // TODO: don't render this entity at all
@@ -105,11 +108,15 @@ void CL_Weaponentity_Think(entity this)
                this.weaponchild.alpha = this.alpha;
                this.weaponchild.effects = this.effects;
        }
+
+       wepent_update(this);
 }
 
 void CL_ExteriorWeaponentity_Think(entity this)
 {
        this.nextthink = time;
+       .entity weaponentity = this.weaponentity_fld;
+       entity wepent = this.owner.(weaponentity);
        if (this.owner.exteriorweaponentity != this)
        {
                delete(this);
@@ -120,15 +127,15 @@ void CL_ExteriorWeaponentity_Think(entity this)
                this.model = "";
                return;
        }
-       if (this.weaponname != this.owner.weaponname || this.dmg != this.owner.modelindex
-           || this.deadflag != this.owner.deadflag)
+       if (this.weaponname != wepent.weaponname || this.dmg != wepent.modelindex
+           || this.deadflag != wepent.deadflag)
        {
-               this.weaponname = this.owner.weaponname;
-               this.dmg = this.owner.modelindex;
-               this.deadflag = this.owner.deadflag;
-               if (this.owner.weaponname != "")
+               this.weaponname = wepent.weaponname;
+               this.dmg = wepent.modelindex;
+               this.deadflag = wepent.deadflag;
+               if (wepent.weaponname != "")
                {
-                       _setmodel(this, W_Model(strcat("v_", this.owner.weaponname, ".md3")));
+                       _setmodel(this, W_Model(strcat("v_", wepent.weaponname, ".md3")));
                        setsize(this, '0 0 0', '0 0 0');
                }
                else this.model = "";
@@ -151,7 +158,7 @@ void CL_ExteriorWeaponentity_Think(entity this)
        else if (this.owner.alpha != 0) this.alpha = this.owner.alpha;
        else this.alpha = 1;
 
-    Weapon wep = PS(this.owner).m_weapon;
+    Weapon wep = this.owner.(weaponentity).m_weapon;
        if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors);
        this.colormap = this.owner.colormap;
 
@@ -172,11 +179,14 @@ void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
        view.viewmodelforclient = actor;
        setcefc(view, CL_Weaponentity_CustomizeEntityForClient);
 
+       wepent_link(view);
+
        if (weaponentity == weaponentities[0])
        {
                entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
                exterior.solid = SOLID_NOT;
                exterior.owner = actor;
+               exterior.weaponentity_fld = weaponentity;
                setorigin(exterior, '0 0 0');
                setthink(exterior, CL_ExteriorWeaponentity_Think);
                exterior.nextthink = time;
@@ -188,8 +198,8 @@ void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
 // Weapon subs
 void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       PS(actor).m_weapon = WEP_Null;
-       PS(actor).m_switchingweapon = WEP_Null;
+       actor.(weaponentity).m_weapon = WEP_Null;
+       actor.(weaponentity).m_switchingweapon = WEP_Null;
        entity this = actor.(weaponentity);
        if (this)
        {
@@ -207,7 +217,7 @@ void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 
 .float prevdryfire;
 .float prevwarntime;
-bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary)
+bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary, .entity weaponentity)
 {
        if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
        bool ammo = false;
@@ -226,7 +236,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 == PS(actor).m_switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+       if (thiswep == actor.(weaponentity).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;
@@ -254,7 +264,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
        }
        else  // this weapon is totally unable to fire, switch to another one
        {
-               W_SwitchToOtherWeapon(actor);
+               W_SwitchToOtherWeapon(actor, weaponentity);
        }
 
        return false;
@@ -264,7 +274,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
 bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponentity, bool secondary, float attacktime)
 {
        if (actor.weaponentity == NULL) return true;
-       if (!weapon_prepareattack_checkammo(thiswep, actor, secondary)) return false;
+       if (!weapon_prepareattack_checkammo(thiswep, actor, secondary, weaponentity)) return false;
 
        // if sv_ready_restart_after_countdown is set, don't allow the player to shoot
        // if all players readied up and the countdown is running
@@ -274,7 +284,7 @@ bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponenti
                return false;
 
        // do not even think about shooting if switching
-       if (PS(actor).m_switchweapon != PS(actor).m_weapon) return false;
+       if (actor.(weaponentity).m_switchweapon != actor.(weaponentity).m_weapon) return false;
 
        if (attacktime >= 0)
        {
@@ -378,7 +388,6 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(
                // dprint("reset weapon animation timer at ", ftos(time), "\n");
        }
        this.weapon_nextthink += t;
-       if (weaponentity == weaponentities[0]) STAT(WEAPON_NEXTTHINK, actor) = this.weapon_nextthink;
        this.weapon_think = func;
        // dprint("next ", ftos(this.weapon_nextthink), "\n");
 
@@ -392,8 +401,8 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(
 
        if ((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
        {
-               bool primary_melee = boolean(fr == WFRAME_FIRE1 && (PS(actor).m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
-               bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (PS(actor).m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
+               bool primary_melee = boolean(fr == WFRAME_FIRE1 && (actor.(weaponentity).m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
+               bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (actor.(weaponentity).m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
                int act = (primary_melee || secondary_melee)
                        ? ANIMACTION_MELEE
                        : ANIMACTION_SHOOT
@@ -434,18 +443,18 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        {
                if (actor.(weaponentity).state != WS_CLEAR)
                {
-                       Weapon wpn = PS(actor).m_weapon;
+                       Weapon wpn = this.m_weapon;
                        w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
                        return;
                }
        }
 
-       if (PS(actor).m_switchweapon == WEP_Null)
+       if (this.m_switchweapon == WEP_Null)
        {
-               PS(actor).m_weapon = WEP_Null;
-               PS(actor).m_switchingweapon = WEP_Null;
+               this.m_weapon = WEP_Null;
+               this.m_switchingweapon = WEP_Null;
                this.state = WS_CLEAR;
-               actor.weaponname = "";
+               this.weaponname = "";
                // actor.items &= ~IT_AMMO;
                return;
        }
@@ -456,7 +465,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        vector up = v_up;
 
        // Change weapon
-       if (PS(actor).m_weapon != PS(actor).m_switchweapon)
+       if (this.m_weapon != this.m_switchweapon)
        {
                switch (this.state)
                {
@@ -469,12 +478,12 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        case WS_CLEAR:
                        {
                                // end switching!
-                               Weapon newwep = PS(actor).m_switchweapon;
-                               PS(actor).m_switchingweapon = newwep;
+                               Weapon newwep = this.m_switchweapon;
+                               this.m_switchingweapon = newwep;
 
                                // the two weapon entities will notice this has changed and update their models
-                               PS(actor).m_weapon = newwep;
-                               actor.weaponname = newwep.mdl;
+                               this.m_weapon = newwep;
+                               this.weaponname = newwep.mdl;
                                actor.bulletcounter = 0;
                                actor.ammo_field = newwep.ammo_field;
                                newwep.wr_setup(newwep, actor);
@@ -483,7 +492,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                                // 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[PS(actor).m_switchweapon.m_id]);
+                                       actor.clip_load = actor.(weapon_load[this.m_switchweapon.m_id]);
                                        actor.clip_size = newwep.reloading_ammo;
                                }
                                else
@@ -497,14 +506,14 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        case WS_DROP:
                        {
                                // in dropping phase we can switch at any time
-                               PS(actor).m_switchingweapon = PS(actor).m_switchweapon;
+                               this.m_switchingweapon = this.m_switchweapon;
                                break;
                        }
                        case WS_READY:
                        {
                                // start switching!
-                               PS(actor).m_switchingweapon = PS(actor).m_switchweapon;
-                               entity oldwep = PS(actor).m_weapon;
+                               this.m_switchingweapon = this.m_switchweapon;
+                               entity oldwep = this.m_weapon;
 
                                // set up weapon switch think in the future, and start drop anim
                                if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + actor.weapon_frametime * 0.5)
@@ -522,7 +531,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        // if (actor.button0)
        //      print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor, slot)), " >= ", ftos(this.weapon_nextthink), "\n");
 
-       Weapon w = PS(actor).m_weapon;
+       Weapon w = this.m_weapon;
 
        // call the think code which may fire the weapon
        // and do so multiple times to resolve framerate dependency issues if the
@@ -531,7 +540,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        {
                if (w != WEP_Null && !(actor.weapons & WepSet_FromWeapon(w)))
                {
-                       if (PS(actor).m_weapon == PS(actor).m_switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       if (this.m_weapon == this.m_switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor), weaponentity);
                        w = WEP_Null;
                }
 
@@ -549,11 +558,11 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        }
                        else
                        {
-                               if (key_pressed && PS(actor).m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
-                                       W_SwitchWeapon(actor, WEP_HOOK);
+                               if (key_pressed && this.m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
+                                       W_SwitchWeapon(actor, WEP_HOOK, weaponentity);
                                actor.hook_switchweapon = key_pressed;
                                Weapon h = WEP_HOOK;
-                               block_weapon = (PS(actor).m_weapon == h && (PHYS_INPUT_BUTTON_ATCK(actor) || key_pressed));
+                               block_weapon = (this.m_weapon == h && (PHYS_INPUT_BUTTON_ATCK(actor) || key_pressed));
                                h.wr_think(h, actor, weaponentity, block_weapon ? 1 : 0);
                        }
                }
@@ -564,7 +573,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
 
                if (!block_weapon)
                {
-            Weapon e = PS(actor).m_weapon;
+            Weapon e = this.m_weapon;
             TC(Weapon, e);
                        if (w != WEP_Null)
                        {
@@ -583,7 +592,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                                v_forward = fo;
                                v_right = ri;
                                v_up = up;
-                               Weapon wpn = PS(actor).m_weapon;
+                               Weapon wpn = this.m_weapon;
                                this.weapon_think(wpn, actor, weaponentity,
                                        PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
                        }
@@ -625,7 +634,7 @@ void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector
        }
 }
 
-void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use)
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
 {
        if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor)) return;
 
@@ -635,7 +644,7 @@ void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use)
        if (wep.reloading_ammo)
        {
                actor.clip_load -= ammo_use;
-               actor.(weapon_load[PS(actor).m_weapon.m_id]) = actor.clip_load;
+               actor.(weapon_load[actor.(weaponentity).m_weapon.m_id]) = actor.clip_load;
        }
        else if (wep.ammo_field != ammo_none)
        {
@@ -679,7 +688,7 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
                actor.clip_load += load;
                actor.(actor.ammo_field) -= load;
        }
-       actor.(weapon_load[PS(actor).m_weapon.m_id]) = actor.clip_load;
+       actor.(weapon_load[actor.(weaponentity).m_weapon.m_id]) = actor.clip_load;
 
        // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
@@ -687,7 +696,7 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
 
        // ATTACK_FINISHED(actor, slot) -= actor.reload_time - 1;
 
-       Weapon wpn = Weapons_from(PS(actor).m_weapon.m_id);
+       Weapon wpn = Weapons_from(actor.(weaponentity).m_weapon.m_id);
        w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
 }
 
@@ -695,7 +704,7 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
 {
     TC(Sound, sent_sound);
        // set global values to work with
-       Weapon e = PS(actor).m_weapon;
+       Weapon e = actor.(weaponentity).m_weapon;
 
        if (MUTATOR_CALLHOOK(W_Reload, actor)) return;
 
@@ -729,15 +738,15 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
                                if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
                                {
                                        play2(actor, SND(UNAVAILABLE));
-                                       sprint(actor, strcat("You don't have enough ammo to reload the ^2", PS(actor).m_weapon.m_name, "\n"));
+                                       sprint(actor, strcat("You don't have enough ammo to reload the ^2", actor.(weaponentity).m_weapon.m_name, "\n"));
                                        actor.reload_complain = time + 1;
                                }
                                // switch away if the amount of ammo is not enough to keep using this weapon
-                               Weapon w = PS(actor).m_weapon;
+                               Weapon w = actor.(weaponentity).m_weapon;
                                if (!(w.wr_checkammo1(w, actor) + w.wr_checkammo2(w, actor)))
                                {
                                        actor.clip_load = -1;  // reload later
-                                       W_SwitchToOtherWeapon(actor);
+                                       W_SwitchToOtherWeapon(actor, weaponentity);
                                }
                                return;
                        }
@@ -767,7 +776,7 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
 
        if (actor.clip_load < 0) actor.clip_load = 0;
        actor.old_clip_load = actor.clip_load;
-       actor.clip_load = actor.(weapon_load[PS(actor).m_weapon.m_id]) = -1;
+       actor.clip_load = actor.(weapon_load[actor.(weaponentity).m_weapon.m_id]) = -1;
 }
 
 void W_DropEvent(.void(Weapon, entity actor) event, entity player, float weapon_type, entity weapon_item)
index b7ca597..bdc261d 100644 (file)
@@ -12,7 +12,7 @@ bool forbidWeaponUse(entity player);
 
 void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector offset);
 
-void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use);
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity);
 
 void W_DropEvent(.void(Weapon, entity actor) event, entity player, float weapon_type, entity weapon_item);