Merge branch 'master' into Mario/wepent_experimental
authorMario <mario@smbclan.net>
Sat, 5 Nov 2016 02:43:35 +0000 (12:43 +1000)
committerMario <mario@smbclan.net>
Sat, 5 Nov 2016 02:43:35 +0000 (12:43 +1000)
# Conflicts:
# qcsrc/client/view.qc
# qcsrc/common/weapons/weapon/tuba.qc

104 files changed:
mutators.cfg
qcsrc/client/_all.qh
qcsrc/client/defs.qh
qcsrc/client/hud/hud.qh
qcsrc/client/hud/panel/ammo.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/view.qc
qcsrc/client/view.qh
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/breakablehook/sv_breakablehook.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/nades/nades.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/physics/player.qc
qcsrc/common/state.qc
qcsrc/common/state.qh
qcsrc/common/stats.qh
qcsrc/common/t_items.qc
qcsrc/common/triggers/trigger/magicear.qc
qcsrc/common/triggers/trigger/teleport.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/racer.qc
qcsrc/common/vehicles/vehicle/racer_weapon.qc
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/raptor_weapons.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/calculations.qc
qcsrc/common/weapons/calculations.qh
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.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/shockwave.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/api.qh
qcsrc/server/bot/default/aim.qc
qcsrc/server/bot/default/aim.qh
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/havocbot/havocbot.qh
qcsrc/server/bot/default/scripting.qc
qcsrc/server/bot/null/bot_null.qc
qcsrc/server/client.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_damage.qh
qcsrc/server/g_hook.qc
qcsrc/server/g_hook.qh
qcsrc/server/g_world.qc
qcsrc/server/impulse.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/events.qh
qcsrc/server/player.qc
qcsrc/server/portals.qc
qcsrc/server/sv_main.qc
qcsrc/server/tests.qc
qcsrc/server/weapons/hitplot.qc
qcsrc/server/weapons/hitplot.qh
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 2188f80..abb74df 100644 (file)
@@ -55,22 +55,6 @@ set g_overkill_filter_armormedium 0
 set g_overkill_filter_armorbig 0
 set g_overkill_filter_armorlarge 0
 
-set g_overkill_ammo_charge 0
-set g_overkill_ammo_charge_notice 1
-set g_overkill_ammo_charge_limit 1
-set g_overkill_ammo_charge_rate 0.5
-set g_overkill_ammo_charge_rate_vortex 0.5
-set g_overkill_ammo_charge_rate_machinegun 0.5
-set g_overkill_ammo_charge_rate_shotgun 0.5
-set g_overkill_ammo_charge_rate_hmg 0.25
-set g_overkill_ammo_charge_rate_rpc 1.5
-set g_overkill_ammo_decharge 0.1
-set g_overkill_ammo_decharge_machinegun 0.025
-set g_overkill_ammo_decharge_shotgun 0.15
-set g_overkill_ammo_decharge_vortex 0.2
-set g_overkill_ammo_decharge_rpc 1
-set g_overkill_ammo_decharge_hmg 0.01
-
 
 // =========
 //  vampire
index 077b5f4..5935342 100644 (file)
@@ -11,5 +11,7 @@
 #include "defs.qh"
 #include "main.qh"
 #include "miscfunctions.qh"
+#include "view.qh"
 
 #include <common/ent_cs.qh>
+#include <common/wepent.qh>
index 437e1dd..b89ecf5 100644 (file)
@@ -98,10 +98,6 @@ const float MAX_DAMAGEEXTRARADIUS = 16;
 .float damageextraradius;
 .void(entity this, float thisdmg, int hittype, vector org, vector thisforce) event_damage;
 
-// only for Porto
-float angles_held_status;
-vector angles_held;
-
 // weapons
 .bool silent;
 
index 4cd0ee8..58e6a1b 100644 (file)
@@ -90,8 +90,8 @@ float complain_weapon_time;
 PlayerScoreField ps_primary, ps_secondary;
 int ts_primary, ts_secondary;
 
-Weapon last_switchweapon;
-Weapon last_activeweapon;
+.Weapon last_switchweapon;
+.Weapon last_activeweapon;
 float weapontime;
 float weaponprevtime;
 
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 36ca217..f48c0c5 100644 (file)
@@ -494,16 +494,6 @@ NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
 
        spectatorbutton_zoom = (f & 4);
 
-       if(f & 8)
-       {
-               angles_held_status = 1;
-               angles_held.x = ReadAngle();
-               angles_held.y = ReadAngle();
-               angles_held.z = 0;
-       }
-       else
-               angles_held_status = 0;
-
        if(f & 16)
        {
                num_spectators = ReadByte();
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 12f4c6a..9c19493 100644 (file)
@@ -284,9 +284,11 @@ void viewmodel_animate(entity this)
 .float weapon_eta_last;
 .float weapon_switchdelay;
 
+.string name_last;
+
 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;
@@ -295,9 +297,9 @@ 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);
+       vector g = weaponentity_glowmod(wep, NULL, c, this);
        entity me = CSQCModel_server2csqc(player_localentnum - 1);
        int fx = ((me.csqcmodel_effects & EFMASK_CHEAP)
                | EF_NODEPTHTEST)
@@ -312,7 +314,6 @@ void viewmodel_draw(entity this)
                CSQCModel_Effects_Apply(e);
        }
        {
-               static string name_last;
                string name = wep.mdl;
                if(wep == WEP_TUBA)
                {
@@ -320,10 +321,10 @@ void viewmodel_draw(entity this)
                           (this.tuba_instrument == 1) ? "akordeon" :
                                                     "kleinbottle";
                }
-               bool swap = name != name_last;
+               bool swap = name != this.name_last;
                // if (swap)
                {
-                       name_last = name;
+                       this.name_last = name;
                        CL_WeaponEntity_SetModel(this, name, swap);
                        this.viewmodel_origin = this.origin;
                        this.viewmodel_angles = this.angles;
@@ -362,9 +363,9 @@ void viewmodel_draw(entity this)
        setorigin(this, this.origin);
 }
 
-entity viewmodel;
 STATIC_INIT(viewmodel) {
-    viewmodel = new(viewmodel);
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       viewmodels[slot] = new(viewmodel);
 }
 
 void Porto_Draw(entity this);
@@ -377,65 +378,70 @@ STATIC_INIT(Porto)
 }
 
 const int polyline_length = 16;
-vector polyline[polyline_length];
+.vector polyline[polyline_length];
 void Porto_Draw(entity this)
 {
-       if (activeweapon != WEP_PORTO) return;
-       if (spectatee_status) return;
-       if (WEP_CVAR(porto, secondary)) return;
-       if (intermission == 1) return;
-       if (intermission == 2) return;
-       if (STAT(HEALTH) <= 0) return;
-
-       vector pos = view_origin;
-       vector dir = view_forward;
-       if (angles_held_status)
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               makevectors(angles_held);
-               dir = v_forward;
-       }
+               entity wepent = viewmodels[slot];
 
-       polyline[0] = pos;
+               if (wepent.activeweapon != WEP_PORTO) continue;
+               if (spectatee_status) continue;
+               if (WEP_CVAR(porto, secondary)) continue;
+               if (intermission == 1) continue;
+               if (intermission == 2) continue;
+               if (STAT(HEALTH) <= 0) continue;
 
-       int portal_number = 0, portal1_idx = 1, portal_max = 2;
-       int n = 1 + 2;  // 2 lines == 3 points
-       for (int idx = 0; idx < n && idx < polyline_length - 1; )
-       {
-               traceline(pos, pos + 65536 * dir, true, this);
-               dir = reflect(dir, trace_plane_normal);
-               pos = trace_endpos;
-               polyline[++idx] = pos;
-               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+               vector pos = view_origin;
+               vector dir = view_forward;
+               if (wepent.angles_held_status)
                {
-                       n += 1;
-                       continue;
+                       makevectors(wepent.angles_held);
+                       dir = v_forward;
                }
-               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-               {
-                       n = max(2, idx);
-                       break;
-               }
-               // check size
+
+               wepent.polyline[0] = pos;
+
+               int portal_number = 0, portal1_idx = 1, portal_max = 2;
+               int n = 1 + 2;  // 2 lines == 3 points
+               for (int idx = 0; idx < n && idx < polyline_length - 1; )
                {
-                       vector ang = vectoangles2(trace_plane_normal, dir);
-                       ang.x = -ang.x;
-                       makevectors(ang);
-                       if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+                       traceline(pos, pos + 65536 * dir, true, this);
+                       dir = reflect(dir, trace_plane_normal);
+                       pos = trace_endpos;
+                       wepent.polyline[++idx] = pos;
+                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+                       {
+                               n += 1;
+                               continue;
+                       }
+                       if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
                        {
                                n = max(2, idx);
                                break;
                        }
+                       // check size
+                       {
+                               vector ang = vectoangles2(trace_plane_normal, dir);
+                               ang.x = -ang.x;
+                               makevectors(ang);
+                               if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+                               {
+                                       n = max(2, idx);
+                                       break;
+                               }
+                       }
+                       portal_number += 1;
+                       if (portal_number >= portal_max) break;
+                       if (portal_number == 1) portal1_idx = idx;
+               }
+               for (int idx = 0; idx < n - 1; ++idx)
+               {
+                       vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
+                       if (idx == 0) p -= view_up * 16;  // line from player
+                       vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
+                       Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
                }
-               portal_number += 1;
-               if (portal_number >= portal_max) break;
-               if (portal_number == 1) portal1_idx = idx;
-       }
-       for (int idx = 0; idx < n - 1; ++idx)
-       {
-               vector p = polyline[idx], q = polyline[idx + 1];
-               if (idx == 0) p -= view_up * 16;  // line from player
-               vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
-               Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
        }
 }
 
@@ -457,10 +463,17 @@ vector GetCurrentFov(float fov)
                        zoomspeed = 3.5;
 
        zoomdir = button_zoom;
+
        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
-               zoomdir += button_attack2;
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       entity wepent = viewmodels[slot];
+                       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())
        {
                if(spectatorbutton_zoom)
@@ -627,7 +640,7 @@ float EnemyHitCheck()
        return SHOTTYPE_HITENEMY;
 }
 
-float TrueAimCheck()
+float TrueAimCheck(entity wepent)
 {
        float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
        vector vecs, trueaimpoint, w_shotorg;
@@ -640,7 +653,7 @@ float TrueAimCheck()
        ta = trueaim;
        mv = MOVE_NOMONSTERS;
 
-       switch(activeweapon) // WEAPONTODO
+       switch(wepent.activeweapon) // WEAPONTODO
        {
                case WEP_TUBA: // no aim
                case WEP_PORTO: // shoots from eye
@@ -723,7 +736,6 @@ float camera_mode;
 const float CAMERA_FREE = 1;
 const float CAMERA_CHASE = 2;
 float reticle_type;
-string reticle_image;
 string NextFrameCommand;
 
 vector freeze_org, freeze_ang;
@@ -815,9 +827,18 @@ void HitSound()
 {
        // varying sound pitch
 
+       bool have_arc = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wepent = viewmodels[slot];
+
+               if(wepent.activeweapon == WEP_ARC)
+                       have_arc = true;
+       }
+
        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;
+       bool arc_hack = have_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)
@@ -981,8 +1002,9 @@ void HUD_Crosshair(entity this)
                if(autocvar_crosshair_hittest)
                {
                        vector wcross_oldorigin;
+                       entity thiswep = viewmodels[0]; // TODO: unhardcode
                        wcross_oldorigin = wcross_origin;
-                       shottype = TrueAimCheck();
+                       shottype = TrueAimCheck(thiswep);
                        if(shottype == SHOTTYPE_HITWORLD)
                        {
                                v = wcross_origin - wcross_oldorigin;
@@ -1004,7 +1026,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)
@@ -1149,10 +1172,6 @@ void HUD_Crosshair(entity this)
                                weapon_clipload = STAT(WEAPON_CLIPLOAD);
                                weapon_clipsize = STAT(WEAPON_CLIPSIZE);
 
-                               float ok_ammo_charge, ok_ammo_chargepool;
-                               ok_ammo_charge = STAT(OK_AMMO_CHARGE);
-                               ok_ammo_chargepool = STAT(OK_AMMO_CHARGEPOOL);
-
                                float vortex_charge, vortex_chargepool;
                                vortex_charge = STAT(VORTEX_CHARGE);
                                vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
@@ -1162,9 +1181,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;
@@ -1184,27 +1204,20 @@ 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;
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring.tga";
                                }
-                               else if (ok_ammo_charge)
-                               {
-                                       ring_value = ok_ammo_chargepool;
-                                       ring_alpha = autocvar_crosshair_ring_reload_alpha;
-                                       ring_rgb = wcross_color;
-                                       ring_image = "gfx/crosshair_ring.tga";
-                               }
                                else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
                                {
                                        ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
@@ -1214,12 +1227,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 +
@@ -1708,7 +1721,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);
@@ -1786,39 +1800,36 @@ 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));
-
-       if(last_switchweapon != switchweapon)
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               weapontime = time;
-               last_switchweapon = switchweapon;
-               if(button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+               entity wepent = viewmodels[slot];
+
+               if(wepent.last_switchweapon != wepent.switchweapon)
                {
-                       localcmd("-zoom\n");
-                       button_zoom = false;
+                       weapontime = time;
+                       wepent.last_switchweapon = wepent.switchweapon;
+                       if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+                       {
+                               localcmd("-zoom\n");
+                               button_zoom = false;
+                       }
+                       if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch)
+                       {
+                               localcmd("-fire\n");
+                               localcmd("-fire2\n");
+                               button_attack2 = false;
+                       }
                }
-               if(autocvar_cl_unpress_attack_on_weapon_switch)
+               if(wepent.last_activeweapon != wepent.activeweapon)
                {
-                       localcmd("-fire\n");
-                       localcmd("-fire2\n");
-                       button_attack2 = false;
-               }
-       }
-       if(last_activeweapon != activeweapon)
-       {
-               last_activeweapon = activeweapon;
+                       wepent.last_activeweapon = wepent.activeweapon;
 
-               e = activeweapon;
-               if(e.netname != "")
-                       localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
-               else
-                       localcmd("\ncl_hook_activeweapon none\n");
+                       e = wepent.activeweapon;
+                       if(e.netname != "")
+                               localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
+                       else if(slot == 0)
+                               localcmd("\ncl_hook_activeweapon none\n");
+               }
        }
 
        // ALWAYS Clear Current Scene First
@@ -1946,7 +1957,20 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        if(autocvar_cl_reticle)
        {
-               Weapon wep = activeweapon;
+               string reticle_image = "";
+               bool wep_zoomed = false;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       entity wepe = viewmodels[slot];
+                       Weapon wep = wepe.activeweapon;
+                       if(wep != WEP_Null && wep.wr_zoom)
+                       {
+                               bool do_zoom = wep.wr_zoom(wep, NULL);
+                               if(wep.w_reticle && wep.w_reticle != "")
+                                       reticle_image = wep.w_reticle;
+                               wep_zoomed += do_zoom;
+                       }
+               }
                // 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
@@ -1956,9 +1980,9 @@ void CSQC_UpdateView(entity this, float w, float h)
                        // no zoom reticle while dead
                        reticle_type = 0;
                }
-               else if(wep.wr_zoomreticle(wep) && autocvar_cl_reticle_weapon)
+               else if(wep_zoomed && autocvar_cl_reticle_weapon)
                {
-                       if(reticle_image != "") { reticle_type = 2; }
+                       if(reticle_image && reticle_image != "") { reticle_type = 2; }
                        else { reticle_type = 0; }
                }
                else if(button_zoom || zoomscript_caught)
index f8c8bd2..01d4546 100644 (file)
@@ -1,3 +1,5 @@
 #pragma once
 
 vector crosshair_getcolor(entity this, float health_stat);
+
+entity viewmodels[MAX_WEAPONSLOTS];
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 d67ce5f..a9bd737 100644 (file)
@@ -168,6 +168,7 @@ void GiveBall(entity plyr, entity ball)
                ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
 
        ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
+       ball.weaponentity_fld = weaponentity;
        ball.team = plyr.team;
        plyr.ballcarried = ball;
        ball.nb_dropper = plyr;
@@ -191,12 +192,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)
@@ -219,7 +220,7 @@ void DropBall(entity ball, vector org, vector vel)
        if(ball.owner.metertime)
        {
                ball.owner.metertime = 0;
-               .entity weaponentity = weaponentities[0]; // TODO: find ballstealer
+               .entity weaponentity = ball.weaponentity_fld;
                ball.owner.(weaponentity).state = WS_READY;
        }
 
@@ -903,19 +904,19 @@ METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, .entity we
     }
 }
 
-METHOD(BallStealer, wr_setup, void(BallStealer this, entity actor))
+METHOD(BallStealer, wr_setup, void(BallStealer this, entity actor, .entity weaponentity))
 {
     TC(BallStealer, this);
     //weapon_setup(WEP_PORTO.m_id);
 }
 
-METHOD(BallStealer, wr_checkammo1, bool(BallStealer this, entity actor))
+METHOD(BallStealer, wr_checkammo1, bool(BallStealer this, entity actor, .entity weaponentity))
 {
     TC(BallStealer, this);
     return true;
 }
 
-METHOD(BallStealer, wr_checkammo2, bool(BallStealer this, entity actor))
+METHOD(BallStealer, wr_checkammo2, bool(BallStealer this, entity actor, .entity weaponentity))
 {
     TC(BallStealer, this);
     return true;
@@ -998,16 +999,20 @@ MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
                }
                else
                {
-                       .entity weaponentity = weaponentities[0]; // TODO
-                       if(player.(weaponentity).weapons)
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                        {
-                               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);
+                               .entity weaponentity = weaponentities[slot];
 
-                               player.(weaponentity).weapons = '0 0 0';
+                               if(player.(weaponentity).weapons)
+                               {
+                                       player.weapons = player.(weaponentity).weapons;
+                                       Weapon w = WEP_NEXBALL;
+                                       w.wr_resetplayer(w, player);
+                                       player.(weaponentity).m_switchweapon = player.m_switchweapon;
+                                       W_SwitchWeapon(player, player.(weaponentity).m_switchweapon, weaponentity);
+
+                                       player.(weaponentity).weapons = '0 0 0';
+                               }
                        }
                }
 
@@ -1029,8 +1034,11 @@ MUTATOR_HOOKFUNCTION(nb, PlayerSpawn)
        entity player = M_ARGV(0, entity);
 
        player.metertime = 0;
-       .entity weaponentity = weaponentities[0];
-       player.(weaponentity).weapons = '0 0 0';
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               player.(weaponentity).weapons = '0 0 0';
+       }
 
        if (nexball_mode & NBM_BASKETBALL)
                player.weapons |= WEPSET(NEXBALL);
@@ -1056,16 +1064,18 @@ MUTATOR_HOOKFUNCTION(nb, PlayerPhysics)
 
 MUTATOR_HOOKFUNCTION(nb, ForbidThrowCurrentWeapon)
 {
-       entity player = M_ARGV(0, entity);
+       //entity player = M_ARGV(0, entity);
+       entity wepent = M_ARGV(1, entity);
 
-       return PS(player).m_weapon == WEP_NEXBALL;
+       return wepent.m_weapon == WEP_NEXBALL;
 }
 
 MUTATOR_HOOKFUNCTION(nb, ForbidDropCurrentWeapon)
 {
-       entity player = M_ARGV(0, entity);
+       //entity player = M_ARGV(0, entity);
+       int wep = M_ARGV(1, int);
 
-       return PS(player).m_weapon == WEP_MORTAR; // TODO: what is this for?
+       return wep == WEP_MORTAR.m_id; // TODO: what is this for?
 }
 
 MUTATOR_HOOKFUNCTION(nb, FilterItem)
index 2685e2f..5572fe9 100644 (file)
@@ -14,7 +14,7 @@ const int MONSTER_SIZE_QUAKE = BIT(13);
 const int MONSTER_TYPE_PASSIVE = BIT(14); // doesn't target or chase enemies
 
 // 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 71bca32..de2a99e 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 aae2686..6baa453 100644 (file)
@@ -156,7 +156,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 a122865..8c90ade 100644 (file)
@@ -170,9 +170,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 cd53ff2..92a098a 100644 (file)
@@ -46,7 +46,7 @@ METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, .entity
     }
 }
 
-METHOD(WyvernAttack, wr_checkammo1, bool(WyvernAttack this, entity actor)) {
+METHOD(WyvernAttack, wr_checkammo1, bool(WyvernAttack this, entity actor, .entity weaponentity)) {
     TC(WyvernAttack, this);
        return true;
 }
@@ -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 8bbb300..d9f866e 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 b8c3bab..a89e55b 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)
@@ -1036,7 +1037,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 fdb0dc3..dfde6ed 100644 (file)
@@ -23,7 +23,7 @@ MUTATOR_HOOKFUNCTION(breakablehook, PlayerDamage_Calculate)
                if(DIFF_TEAM(frag_attacker, frag_target.realowner))
                {
                        Damage (frag_target.realowner, frag_attacker, frag_attacker, 5, WEP_HOOK.m_id | HITTYPE_SPLASH, frag_target.realowner.origin, '0 0 0');
-                       RemoveGrapplingHook(frag_target.realowner);
+                       RemoveHook(frag_target);
                        return; // dead
                }
        }
index 5587da5..bfd83be 100644 (file)
@@ -842,8 +842,14 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
        }
 
        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;
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(player.(weaponentity).clip_size)
+                               player.(weaponentity).clip_load = player.(weaponentity).(weapon_load[player.(weaponentity).m_switchweapon.m_id]) = player.(weaponentity).clip_size;
+               }
+       }
 
        if((player.buffs & BUFF_INVISIBLE.m_itemid) && (player.oldbuffs & BUFF_INVISIBLE.m_itemid))
        if(player.alpha != autocvar_g_buffs_invisible_alpha)
@@ -870,9 +876,17 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                        player.buff_ammo_prev_infitems = (player.items & IT_UNLIMITED_WEAPON_AMMO);
                        player.items |= IT_UNLIMITED_WEAPON_AMMO;
 
-                       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;
+                       if(player.buffs & BUFF_AMMO.m_itemid)
+                       {
+                               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                               {
+                                       .entity weaponentity = weaponentities[slot];
+                                       if(player.(weaponentity).clip_load)
+                                               player.(weaponentity).buff_ammo_prev_clipload = player.(weaponentity).clip_load;
+                                       if(player.(weaponentity).clip_size)
+                                               player.(weaponentity).clip_load = player.(weaponentity).(weapon_load[player.(weaponentity).m_switchweapon.m_id]) = player.(weaponentity).clip_size;
+                               }
+                       }
                }
 
                BUFF_ONREM(BUFF_AMMO)
@@ -882,8 +896,15 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
                        else
                                player.items &= ~IT_UNLIMITED_WEAPON_AMMO;
 
-                       if(player.buff_ammo_prev_clipload)
-                               player.clip_load = player.buff_ammo_prev_clipload;
+                       if(player.buffs & BUFF_AMMO.m_itemid)
+                       {
+                               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                               {
+                                       .entity weaponentity = weaponentities[slot];
+                                       if(player.(weaponentity).buff_ammo_prev_clipload)
+                                               player.(weaponentity).clip_load = player.(weaponentity).buff_ammo_prev_clipload;
+                               }
+                       }
                }
 
                BUFF_ONADD(BUFF_INVISIBLE)
index 0d804a9..71fb67a 100644 (file)
@@ -736,7 +736,7 @@ void nade_boom(entity this)
 
        IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
        {
-               RemoveGrapplingHook(it.realowner);
+               RemoveHook(it);
        });
 
        delete(this);
@@ -785,7 +785,7 @@ void nade_touch(entity this, entity toucher)
        {
                IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
                {
-                       RemoveGrapplingHook(it.realowner);
+                       RemoveHook(it);
                });
                delete(this);
                return;
@@ -891,7 +891,7 @@ void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
        makevectors(e.v_angle);
 
        // NOTE: always throw from first weapon entity?
-       W_SetupShot(e, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0);
+       W_SetupShot(e, _nade.weaponentity_fld, false, false, SND_Null, CH_WEAPON_A, 0);
 
        Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER, CPID_NADES);
 
@@ -1034,6 +1034,8 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        if(Nades_from(n.nade_type) == NADE_TYPE_Null)
                n.nade_type = NADE_TYPE_NORMAL.m_id;
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        setmodel(n, MDL_PROJECTILE_NADE);
        //setattachment(n, player, "bip01 l hand");
        n.exteriormodeltoclient = player;
@@ -1048,9 +1050,9 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        setthink(n, nade_beep);
        n.nextthink = max(n.wait - 3, time);
        n.projectiledeathtype = DEATH_NADE.m_id;
+       n.weaponentity_fld = weaponentity;
 
        setmodel(fn, MDL_NADE_VIEW);
-       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
        setattachment(fn, player.(weaponentity), "");
        fn.realowner = fn.owner = player;
        fn.colormod = Nades_from(n.nade_type).m_color;
@@ -1058,6 +1060,7 @@ void spawn_held_nade(entity player, entity nowner, float ntime, int ntype, strin
        fn.glowmod = player.glowmod;
        setthink(fn, SUB_Remove);
        fn.nextthink = n.wait;
+       fn.weaponentity_fld = weaponentity;
 
        player.nade = n;
        player.fake_nade = fn;
index 39072ce..b33cd73 100644 (file)
@@ -63,8 +63,14 @@ 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);
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if(it.(weaponentity).m_weapon == WEP_Null && slot != 0)
+                                       continue;
+                               if(!client_hasweapon(it, it.(weaponentity).m_weapon, weaponentity, true, false))
+                                       it.(weaponentity).m_switchweapon = w_getbestweapon(it, weaponentity);
+                       }
                });
        }
 
@@ -164,14 +170,24 @@ void NIX_GiveCurrentWeapon(entity this)
 
                // all weapons must be fully loaded when we spawn
                if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
-                       this.(weapon_load[nix_weapon]) = e.reloading_ammo;
+               {
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               this.(weaponentity).(weapon_load[nix_weapon]) = e.reloading_ammo;
+                       }
+               }
 
                // vortex too
                if(WEP_CVAR(vortex, charge))
                {
                        if(WEP_CVAR_SEC(vortex, chargepool))
                                this.vortex_chargepool_ammo = 1;
-                       this.vortex_charge = WEP_CVAR(vortex, charge_start);
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               this.(weaponentity).vortex_charge = WEP_CVAR(vortex, charge_start);
+                       }
                }
 
                // set last change info
@@ -205,12 +221,19 @@ void NIX_GiveCurrentWeapon(entity this)
        this.weapons |= e.m_wepset;
 
     Weapon w = Weapons_from(nix_weapon);
-       if(PS(this).m_switchweapon != w)
-               if(!client_hasweapon(this, PS(this).m_switchweapon, true, false))
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+               continue;
+
+               if(this.(weaponentity).m_switchweapon != w)
+               if(!client_hasweapon(this, this.(weaponentity).m_switchweapon, weaponentity, true, false))
                {
-                       if(client_hasweapon(this, w, true, false))
-                               W_SwitchWeapon(this, w);
+                       if(client_hasweapon(this, w, weaponentity, true, false))
+                               W_SwitchWeapon(this, w, weaponentity);
                }
+       }
 }
 
 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
index 024fdb1..caf96a6 100644 (file)
@@ -20,14 +20,14 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
                return;
        }
 
-       if((!thiswep.wr_checkammo1(thiswep, actor) && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (!(actor.items & IT_SUPERWEAPON) && !(actor.items & IT_UNLIMITED_SUPERWEAPONS)))
+       if((!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !(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), 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));
 
@@ -37,10 +37,10 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
                actor.punchangle_y = random () - 0.5;
        }
 
-       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);
+       float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(hmg, spread_max));
+       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;
+       actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -58,45 +58,45 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
 }
 
-METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor))
+METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
     else
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
+        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 }
 
 METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(hmg, reload_ammo) && actor.clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
+    if(WEP_CVAR(hmg, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else
     {
         if (fire & 1)
         if (weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
         {
-            actor.misc_bulletcounter = 0;
+            actor.(weaponentity).misc_bulletcounter = 0;
             W_HeavyMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
         }
     }
 }
 
-METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.ammo_nails >= WEP_CVAR(hmg, ammo);
 
     if(autocvar_g_balance_hmg_reload_ammo)
-        ammo_amount += actor.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
 
     return ammo_amount;
 }
 
-METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.ammo_nails >= WEP_CVAR(hmg, ammo);
 
     if(autocvar_g_balance_hmg_reload_ammo)
-        ammo_amount += actor.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
 
     return ammo_amount;
 }
index ad2ee3f..745b87f 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);
@@ -111,14 +111,14 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
 
-METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor))
+METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
+    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
 }
 
 METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(rpc, reload_ammo) && actor.clip_load < WEP_CVAR(rpc, ammo)) {
+    if(WEP_CVAR(rpc, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(rpc, ammo)) {
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else
     {
@@ -138,14 +138,14 @@ METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .en
     }
 }
 
-METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(rpc, ammo);
-    ammo_amount += actor.(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
     return ammo_amount;
 }
 
-METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return false;
 }
index d47da6c..0c7e6b0 100644 (file)
@@ -4,24 +4,15 @@
 #include "rpc.qh"
 
 bool autocvar_g_overkill_powerups_replace;
-bool autocvar_g_overkill_ammo_charge;
-float autocvar_g_overkill_ammo_charge_notice;
-float autocvar_g_overkill_ammo_charge_limit;
 
 bool autocvar_g_overkill_filter_healthmega;
 bool autocvar_g_overkill_filter_armormedium;
 bool autocvar_g_overkill_filter_armorbig;
 bool autocvar_g_overkill_filter_armorlarge;
 
-.float ok_lastwep;
 .float ok_item;
 
-.float ok_notice_time;
-.float ammo_charge[Weapons_MAX];
-.float ok_use_ammocharge = _STAT(OK_AMMO_CHARGE);
-.float ok_ammo_charge = _STAT(OK_AMMO_CHARGEPOOL);
-
-void(entity ent, float wep) ok_DecreaseCharge;
+.Weapon ok_lastwep[MAX_WEAPONSLOTS];
 
 void ok_Initialize();
 
@@ -39,59 +30,10 @@ REGISTER_MUTATOR(ok, cvar("g_overkill") && !cvar("g_instagib") && !g_nexball &&
        }
 }
 
-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);
-               return true;
-       }
-}
-
-MUTATOR_HOOKFUNCTION(ok, W_Reload)
-{
-       entity actor = M_ARGV(0, entity);
-       return actor.ok_use_ammocharge;
-}
-
 void W_Blaster_Attack(entity, .entity, float, float, float, float, float, float, float, float, float, float);
 spawnfunc(weapon_hmg);
 spawnfunc(weapon_rpc);
 
-void ok_DecreaseCharge(entity ent, int wep)
-{
-       if(!ent.ok_use_ammocharge) return;
-
-       entity wepent = Weapons_from(wep);
-
-       if (wepent == WEP_Null) return;  // dummy
-
-       ent.ammo_charge[wep] -= max(0, cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname)));
-}
-
-void ok_IncreaseCharge(entity ent, int wep)
-{
-       entity wepent = Weapons_from(wep);
-
-       if (wepent == WEP_Null) return;  // dummy
-
-       if(ent.ok_use_ammocharge)
-       if(!PHYS_INPUT_BUTTON_ATCK(ent)) // not while attacking?
-               ent.ammo_charge[wep] = min(autocvar_g_overkill_ammo_charge_limit, ent.ammo_charge[wep] + cvar(sprintf("g_overkill_ammo_charge_rate_%s", wepent.netname)) * frametime / W_TICSPERFRAME);
-}
-
-float ok_CheckWeaponCharge(entity ent, int wep)
-{
-       if(!ent.ok_use_ammocharge) return true;
-
-       entity wepent = Weapons_from(wep);
-
-       if(wepent == WEP_Null) return false;  // dummy
-
-       return (ent.ammo_charge[wep] >= cvar(sprintf("g_overkill_ammo_decharge_%s", wepent.netname)));
-}
-
 MUTATOR_HOOKFUNCTION(ok, PlayerDamage_Calculate, CBC_ORDER_LAST)
 {
        entity frag_attacker = M_ARGV(1, entity);
@@ -141,7 +83,12 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDies)
 
        ok_DropItem(frag_target, targ);
 
-       frag_target.ok_lastwep = PS(frag_target).m_switchweapon.m_id;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+
+               frag_target.ok_lastwep[slot] = frag_target.(weaponentity).m_switchweapon;
+       }
 }
 
 MUTATOR_HOOKFUNCTION(ok, MonsterDropItem)
@@ -172,18 +119,22 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
        if(IS_DEAD(player) || !IS_PLAYER(player) || STAT(FROZEN, player))
                return;
 
-       if(player.ok_lastwep)
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               Weapon newwep = Weapons_from(player.ok_lastwep);
-               if(player.ok_lastwep == WEP_HMG.m_id)
-                       newwep = WEP_MACHINEGUN;
-               if(player.ok_lastwep == WEP_RPC.m_id)
-                       newwep = WEP_VORTEX;
-               PS(player).m_switchweapon = newwep;
-               player.ok_lastwep = 0;
-       }
+               .entity weaponentity = weaponentities[slot];
+               entity thiswep = player.(weaponentity);
 
-       ok_IncreaseCharge(player, PS(player).m_weapon.m_id);
+               if(player.ok_lastwep[slot] && player.ok_lastwep[slot] != WEP_Null)
+               {
+                       Weapon newwep = player.ok_lastwep[slot];
+                       if(player.ok_lastwep[slot] == WEP_HMG)
+                               newwep = WEP_MACHINEGUN;
+                       if(player.ok_lastwep[slot] == WEP_RPC)
+                               newwep = WEP_VORTEX;
+                       thiswep.m_switchweapon = newwep;
+                       player.ok_lastwep[slot] = WEP_Null;
+               }
+       }
 
        if(PHYS_INPUT_BUTTON_ATCK2(player))
        if( !forbidWeaponUse(player) || player.weapon_blocked // allow if weapon is blocked
@@ -193,44 +144,31 @@ 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;
-               W_Blaster_Attack(
-                       player,
-                       weaponentities[0], // TODO: unhardcode
-                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
-                       WEP_CVAR_SEC(vaporizer, shotangle),
-                       WEP_CVAR_SEC(vaporizer, damage),
-                       WEP_CVAR_SEC(vaporizer, edgedamage),
-                       WEP_CVAR_SEC(vaporizer, radius),
-                       WEP_CVAR_SEC(vaporizer, force),
-                       WEP_CVAR_SEC(vaporizer, speed),
-                       WEP_CVAR_SEC(vaporizer, spread),
-                       WEP_CVAR_SEC(vaporizer, delay),
-                       WEP_CVAR_SEC(vaporizer, lifetime)
-               );
-               PS(player).m_weapon = oldwep;
-       }
-
-       player.weapon_blocked = false;
-
-       player.ok_ammo_charge = player.ammo_charge[PS(player).m_weapon.m_id];
-
-       if(player.ok_use_ammocharge)
-       if(!ok_CheckWeaponCharge(player, PS(player).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)
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
-                       //Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_OVERKILL_CHARGE);
-                       player.ok_notice_time = time + 2;
-                       play2(player, SND(DRYFIRE));
+                       .entity weaponentity = weaponentities[slot];
+
+                       if(player.(weaponentity).m_weapon == WEP_Null && slot != 0)
+                               continue;
+
+                       Weapon oldwep = player.(weaponentity).m_weapon;
+                       player.(weaponentity).m_weapon = WEP_BLASTER;
+                       W_Blaster_Attack(
+                               player,
+                               weaponentity,
+                               WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                               WEP_CVAR_SEC(vaporizer, shotangle),
+                               WEP_CVAR_SEC(vaporizer, damage),
+                               WEP_CVAR_SEC(vaporizer, edgedamage),
+                               WEP_CVAR_SEC(vaporizer, radius),
+                               WEP_CVAR_SEC(vaporizer, force),
+                               WEP_CVAR_SEC(vaporizer, speed),
+                               WEP_CVAR_SEC(vaporizer, spread),
+                               WEP_CVAR_SEC(vaporizer, delay),
+                               WEP_CVAR_SEC(vaporizer, lifetime)
+                       );
+                       player.(weaponentity).m_weapon = oldwep;
                }
-               Weapon wpn = PS(player).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));
-
-               player.weapon_blocked = true;
        }
 
        PHYS_INPUT_BUTTON_ATCK2(player) = false;
@@ -240,19 +178,14 @@ MUTATOR_HOOKFUNCTION(ok, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
 
-       if(autocvar_g_overkill_ammo_charge)
-       {
-               FOREACH(Weapons, it != WEP_Null, LAMBDA(player.ammo_charge[it.m_id] = autocvar_g_overkill_ammo_charge_limit));
-
-               player.ok_use_ammocharge = 1;
-               player.ok_notice_time = time;
-       }
-       else
-               player.ok_use_ammocharge = 0;
-
        // if player changed their weapon while dead, don't switch to their death weapon
        if(player.impulse)
-               player.ok_lastwep = 0;
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       player.ok_lastwep[slot] = WEP_Null;
+               }
+       }
 }
 
 void self_spawnfunc_weapon_hmg(entity this) { spawnfunc_weapon_hmg(this); }
@@ -321,15 +254,6 @@ MUTATOR_HOOKFUNCTION(ok, FilterItem)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ok, SpectateCopy)
-{
-       entity spectatee = M_ARGV(0, entity);
-       entity client = M_ARGV(1, entity);
-
-       client.ammo_charge[PS(client).m_weapon.m_id] = spectatee.ammo_charge[PS(spectatee).m_weapon.m_id];
-       client.ok_use_ammocharge = spectatee.ok_use_ammocharge;
-}
-
 MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
 {
        WepSet ok_start_items = (WEPSET(MACHINEGUN) | WEPSET(VORTEX) | WEPSET(SHOTGUN));
index bc3887e..ff942db 100644 (file)
@@ -6,12 +6,20 @@ MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
 {
        entity frag_target = M_ARGV(2, entity);
 
-       FOREACH(Weapons, it != WEP_Null, LAMBDA(
-               if(frag_target.weapons & WepSet_FromWeapon(it))
-               if(PS(frag_target).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');
-       ));
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+
+               if(frag_target.(weaponentity).m_weapon == WEP_Null && slot != 0)
+                       continue;
+
+               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                       if(frag_target.weapons & WepSet_FromWeapon(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', weaponentity);
+               ));
+       }
 
        return true;
 }
index b5635e0..76b8126 100644 (file)
@@ -96,8 +96,15 @@ void PM_ClientMovement_UpdateStatus(entity this)
 
        // set crouched
        bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
-       if(this.hook && !wasfreed(this.hook))
-               do_crouch = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wep = viewmodels[slot];
+               if(wep.hook && !wasfreed(wep.hook))
+               {
+                       do_crouch = false;
+                       break; // don't bother checking the others
+               }
+       }
        if(this.waterlevel >= WATERLEVEL_SWIMMING)
                do_crouch = false;
        if(hud != HUD_NORMAL)
@@ -608,7 +615,12 @@ void PM_check_hitground(entity this)
     this.wasFlying = false;
     if (this.waterlevel >= WATERLEVEL_SWIMMING) return;
     if (time < this.ladder_time) return;
-    if (this.hook) return;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       if(this.(weaponentity).hook)
+               return;
+    }
     this.nextstep = time + 0.3 + random() * 0.1;
     trace_dphitq3surfaceflags = 0;
     tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
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 82398aa..c4c5172 100644 (file)
@@ -55,13 +55,7 @@ REGISTER_STAT(PL_CROUCH_MAX, vector, autocvar_sv_player_crouch_maxs)
 
 REGISTER_STAT(KH_KEYS, int)
 
-/** weapon requested to switch to; next WANTED weapon (for HUD) */
-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))
@@ -114,8 +108,6 @@ REGISTER_STAT(NADE_BONUS_SCORE, float)
 REGISTER_STAT(HEALING_ORB, float)
 REGISTER_STAT(HEALING_ORB_ALPHA, float)
 REGISTER_STAT(PLASMA, int)
-REGISTER_STAT(OK_AMMO_CHARGE, float)
-REGISTER_STAT(OK_AMMO_CHARGEPOOL, float)
 REGISTER_STAT(FROZEN, int)
 REGISTER_STAT(REVIVE_PROGRESS, float)
 REGISTER_STAT(ROUNDLOST, int)
index 7424d69..af0c52e 100644 (file)
@@ -672,21 +672,30 @@ LABEL(YEAH)
 
 float Item_GiveTo(entity item, entity player)
 {
-       float _switchweapon;
        float pickedup;
 
        // if nothing happens to player, just return without taking the item
        pickedup = false;
-       _switchweapon = false;
+       int _switchweapon = 0;
        // in case the player has autoswitch enabled do the following:
        // 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))
-               _switchweapon = true;
 
-       if (!(player.weapons & WepSet_FromWeapon(PS(player).m_switchweapon)))
-               _switchweapon = true;
+       if(player.autoswitch)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                       {
+                               if(player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
+                                       _switchweapon |= BIT(slot);
+
+                               if(!(player.weapons & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
+                                       _switchweapon |= BIT(slot);
+                       }
+               }
+       }
 
        pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
        pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE);
@@ -709,7 +718,12 @@ float Item_GiveTo(entity item, entity player)
                        FOREACH(Weapons, it != WEP_Null, {
                                if(w & (it.m_wepset))
                                {
-                                       W_DropEvent(wr_pickup, player, it.m_id, item);
+                                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                                       {
+                                               .entity weaponentity = weaponentities[slot];
+                                               if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                                                       W_DropEvent(wr_pickup, player, it.m_id, item, weaponentity);
+                                       }
                                        W_GiveWeapon(player, it.m_id);
                                }
                        });
@@ -760,13 +774,25 @@ LABEL(skip)
        // crude hack to enforce switching weapons
        if(g_cts && item.itemdef.instanceOfWeaponPickup)
        {
-               W_SwitchWeapon_Force(player, Weapons_from(item.weapon));
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                               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(_switchweapon)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(_switchweapon & BIT(slot))
+                       if(player.(weaponentity).m_switchweapon != w_getbestweapon(player, weaponentity))
+                               W_SwitchWeapon_Force(player, w_getbestweapon(player, weaponentity), weaponentity);
+               }
+       }
 
        return 1;
 }
@@ -1645,7 +1671,6 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
 float GiveItems(entity e, float beginarg, float endarg)
 {
        float got, i, val, op;
-       float _switchweapon;
        string cmd;
 
        val = 999;
@@ -1653,10 +1678,18 @@ float GiveItems(entity e, float beginarg, float endarg)
 
        got = 0;
 
-       _switchweapon = false;
-       if (e.autoswitch)
-               if (PS(e).m_switchweapon == w_getbestweapon(e))
-                       _switchweapon = true;
+       int _switchweapon = 0;
+
+       if(e.autoswitch)
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+                       if(e.(weaponentity).m_switchweapon == w_getbestweapon(e, weaponentity))
+                               _switchweapon |= BIT(slot);
+               }
+       }
 
        e.strength_finished = max(0, e.strength_finished - time);
        e.invincible_finished = max(0, e.invincible_finished - time);
@@ -1821,10 +1854,23 @@ float GiveItems(entity e, float beginarg, float endarg)
        else
                e.superweapons_finished += time;
 
-       if (!(e.weapons & WepSet_FromWeapon(PS(e).m_switchweapon)))
-               _switchweapon = true;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+               if(!(e.weapons & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
+                       _switchweapon |= BIT(slot);
+       }
+
        if(_switchweapon)
-               W_SwitchWeapon_Force(e, w_getbestweapon(e));
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(_switchweapon & BIT(slot))
+                               W_SwitchWeapon_Force(e, w_getbestweapon(e, weaponentity), weaponentity);
+               }
+       }
 
        return got;
 }
index 065d8c9..354ed1b 100644 (file)
@@ -1,7 +1,7 @@
 #include "magicear.qh"
 #ifdef SVQC
 float magicear_matched;
-float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
+float W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
 string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
 {
        float domatch, dotrigger, matchstart, l;
@@ -22,8 +22,12 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
                if (!(ear.spawnflags & 256))
                        return msgin;
 
-               if(!W_Tuba_HasPlayed(source, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
-                       return msgin;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(!W_Tuba_HasPlayed(source, weaponentity, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
+                               return msgin;
+               }
 
                magicear_matched = true;
 
index c3de654..1fabc80 100644 (file)
@@ -43,7 +43,7 @@ void Teleport_Touch(entity this, entity toucher)
 
 #ifdef SVQC
        if(IS_PLAYER(toucher))
-               RemoveGrapplingHook(toucher);
+               RemoveGrapplingHooks(toucher);
 #endif
 
        entity e;
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 b165bb3..491962b 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;
 
@@ -942,7 +947,7 @@ void vehicles_enter(entity pl, entity veh)
        }
        else return;
 
-       RemoveGrapplingHook(pl);
+       RemoveGrapplingHooks(pl);
 
        veh.vehicle_ammo1 = 0;
        veh.vehicle_ammo2 = 0;
@@ -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;
 
@@ -1099,7 +1109,15 @@ void vehicles_spawn(entity this)
        if(this.vehicle_controller)
                this.team = this.vehicle_controller.team;
 
-       FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == this, RemoveGrapplingHook(it));
+       FOREACH_CLIENT(IS_PLAYER(it),
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           {
+               .entity weaponentity = weaponentities[slot];
+               if(it.(weaponentity).hook.aiment == this)
+                       RemoveHook(it.(weaponentity).hook);
+           }
+       });
 
        vehicles_reset_colors(this);
 
index 3f5f404..7bc10b4 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);
@@ -304,9 +309,15 @@ bool bumblebee_gunner_enter(entity this, entity player)
        player.vehicle_energy   = vehic.vehicle_energy;
        UNSET_ONGROUND(player);
 
-       RemoveGrapplingHook(player);
+       RemoveGrapplingHooks(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 41a3174..e6364a6 100644 (file)
@@ -289,9 +289,10 @@ bool racer_frame(entity this, float dt)
 #ifdef SVQC
 
        Weapon wep1 = WEP_RACER;
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
        if (!forbidWeaponUse(this))
        if (PHYS_INPUT_BUTTON_ATCK(this))
-       if (wep1.wr_checkammo1(wep1, vehic))
+       if (wep1.wr_checkammo1(wep1, vehic, weaponentity))
        {
                string tagname = (vehic.cnt)
                    ? (vehic.cnt = 0, "tag_fire1")
@@ -302,7 +303,6 @@ bool racer_frame(entity this, float dt)
                // Fix z-aim (for chase mode)
                crosshair_trace(this);
                w_shotdir.z = normalize(trace_endpos - org).z * 0.5;
-               .entity weaponentity = weaponentities[0];
                wep1.wr_think(wep1, vehic, weaponentity, 1);
        }
 
index d20210c..838f0cf 100644 (file)
@@ -34,7 +34,7 @@ METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weapone
     }
 }
 
-METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep, entity actor))
+METHOD(RacerAttack, wr_checkammo1, bool(RacerAttack thiswep, entity actor, .entity weaponentity))
 {
     bool isPlayer = IS_PLAYER(actor);
     entity player = isPlayer ? actor : actor.owner;
index 1068e74..8ede8f2 100644 (file)
@@ -356,11 +356,11 @@ bool raptor_frame(entity this, float dt)
        */
 
        Weapon wep1 = WEP_RAPTOR;
+       .entity weaponentity = weaponentities[0];
        if(!forbidWeaponUse(this))
        if(PHYS_INPUT_BUTTON_ATCK(this))
-       if (wep1.wr_checkammo1(wep1, vehic))
+       if (wep1.wr_checkammo1(wep1, vehic, weaponentity))
        {
-           .entity weaponentity = weaponentities[0];
                wep1.wr_think(wep1, vehic, weaponentity, 1);
        }
 
index 4e16efb..5cb0f27 100644 (file)
@@ -30,7 +30,7 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weapon
         weapon_thinkf(player, weaponentity, WFRAME_FIRE1, 0, w_ready);
     }
 }
-METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep, entity actor)) {
+METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep, entity actor, .entity weaponentity)) {
     bool isPlayer = IS_PLAYER(actor);
     entity player = isPlayer ? actor : actor.owner;
     entity veh = player.vehicle;
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 763dd6e..c236bb4 100644 (file)
@@ -391,7 +391,9 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
 {
        if (name == "")
        {
-               this.model = "";
+               vector oldmin = this.mins, oldmax = this.maxs;
+               setmodel(this, MDL_Null);
+               setsize(this, oldmin, oldmax);
                if (this.weaponchild) delete(this.weaponchild);
                this.weaponchild = NULL;
                this.movedir = '0 0 0';
@@ -523,7 +525,11 @@ void CL_WeaponEntity_SetModel(entity this, string name, bool _anim)
 
        if (this.movedir.x >= 0)
        {
-               int algn = STAT(GUNALIGN, this.owner);
+               //int algn = STAT(GUNALIGN, this.owner);
+               int algn = W_GunAlign(this, STAT(GUNALIGN, this.owner));
+       #ifdef SVQC
+               this.m_gunalign = algn;
+       #endif
                vector v = this.movedir;
                this.movedir = shotorg_adjust(v, false, false, algn);
                this.view_ofs = shotorg_adjust(v, false, true, algn) - v;
@@ -557,21 +563,22 @@ 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();
+       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,10 +595,10 @@ 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);
-       WriteByte(channel, weaponentity.m_alpha * 255);
 }
 #endif
 
index 9570e8c..287963e 100644 (file)
@@ -326,13 +326,15 @@ STATIC_INIT(register_weapons_done)
 
 .entity weaponchild;
 .entity exteriorweaponentity;
-vector weaponentity_glowmod(Weapon wep, entity actor, int c)
+vector weaponentity_glowmod(Weapon wep, entity actor, int c, entity wepent)
 {
     vector g;
-    if (!(g = wep.wr_glow(wep, actor))) g = colormapPaletteColor(c & 0x0F, true) * 2;
+    if (!(g = wep.wr_glow(wep, actor, wepent))) g = colormapPaletteColor(c & 0x0F, true) * 2;
     return g;
 }
 
+.int m_gunalign;
+
 //.int weapon; // current weapon
 .string weaponname; // name of .weapon
 
index c35b193..367bab6 100644 (file)
@@ -144,6 +144,45 @@ vector findperpendicular(vector v)
        return normalize(cliptoplane(p, v));
 }
 
+#ifdef SVQC
+       int W_GunAlign(entity this, int preferred_align)
+       {
+               if(this.m_gunalign)
+                       return this.m_gunalign; // no adjustment needed
+
+               entity own = this.owner;
+
+               if(preferred_align < 1 || preferred_align > 4)
+                       preferred_align = 3; // default
+
+               for(int j = 4; j > 1; --j) // > 1 as 1 is just center again
+               {
+                       int taken = 0;
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if(own.(weaponentity).m_gunalign == j) // we know it can't be ours thanks to the above check
+                                       taken |= BIT(j);
+                               if(own.(weaponentity).m_gunalign == preferred_align)
+                                       taken |= BIT(preferred_align);
+                       }
+
+                       if(!(taken & BIT(preferred_align)))
+                               return preferred_align; // prefer the recommended
+                       if(!(taken & BIT(j)))
+                               return j; // or fall back if it's not available
+               }
+
+               return preferred_align; // return it anyway
+       }
+#else
+       int W_GunAlign(entity this, int preferred_align)
+       {
+               return this.m_gunalign > 0 ? this.m_gunalign : preferred_align;
+       }
+#endif
+
+#if 0
 int W_GetGunAlignment(entity player)
 {
        int gunalign = STAT(GUNALIGN, player);
@@ -153,6 +192,7 @@ int W_GetGunAlignment(entity player)
 
        return gunalign;
 }
+#endif
 
 vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
 {
index c349eec..d749cc1 100644 (file)
@@ -2,5 +2,6 @@
 
 vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
 vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle);
-int W_GetGunAlignment(entity player);
+int W_GunAlign(entity this, int preferred_align);
+//int W_GetGunAlignment(entity player);
 float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v);
index d16d733..782f3c5 100644 (file)
@@ -75,6 +75,8 @@ CLASS(Weapon, Object)
     ATTRIB(Weapon, w_crosshair, string, "gfx/crosshair1");
     /** A: crosshair : per-weapon crosshair size (argument two of "crosshair" field) */
     ATTRIB(Weapon, w_crosshair_size, float, 1);
+    /** A: reticle   : per-weapon zoom reticle */
+    ATTRIB(Weapon, w_reticle, string, "");
     /** M: wepimg    : "weaponfoobar" side view image file of weapon. WEAPONTODO: Move out of skin files, move to common files */
     ATTRIB(Weapon, model2, string, "");
     /** M: refname   : reference name name */
@@ -85,15 +87,15 @@ CLASS(Weapon, Object)
     ATTRIB(Weapon, m_pickup, entity);
 
     /** (SERVER) setup weapon data */
-    METHOD(Weapon, wr_setup, void(Weapon this, entity actor)) {}
+    METHOD(Weapon, wr_setup, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (SERVER) logic to run every frame */
     METHOD(Weapon, wr_think, void(Weapon this, entity actor, .entity weaponentity, int fire)) {}
     /** (SERVER) checks ammo for weapon primary */
-    METHOD(Weapon, wr_checkammo1, bool(Weapon this, entity actor)) {return false;}
+    METHOD(Weapon, wr_checkammo1, bool(Weapon this, entity actor, .entity weaponentity)) {return false;}
     /** (SERVER) checks ammo for weapon second */
-    METHOD(Weapon, wr_checkammo2, bool(Weapon this, entity actor)) {return false;}
+    METHOD(Weapon, wr_checkammo2, bool(Weapon this, entity actor, .entity weaponentity)) {return false;}
     /** (SERVER) runs bot aiming code for this weapon */
-    METHOD(Weapon, wr_aim, void(Weapon this, entity actor)) {}
+    METHOD(Weapon, wr_aim, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties */
     METHOD(Weapon, wr_init, void(Weapon this)) {}
     /** (SERVER) notification number for suicide message (may inspect w_deathtype for details) */
@@ -112,17 +114,17 @@ CLASS(Weapon, Object)
     METHOD(Weapon, wr_gonethink, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons) */
     METHOD(Weapon, wr_config, void(Weapon this)) {}
-    /** (CLIENT) weapon specific zoom reticle */
-    METHOD(Weapon, wr_zoomreticle, bool(Weapon this)) {
+    /** (BOTH) weapon specific zoom reticle */
+    METHOD(Weapon, wr_zoom, bool(Weapon this, entity actor)) {
         // no weapon specific image for this weapon
         return false;
     }
     /** (CLIENT) weapon specific glow */
-    METHOD(Weapon, wr_glow, vector(Weapon this, entity actor)) { return '0 0 0'; }
+    METHOD(Weapon, wr_glow, vector(Weapon this, entity actor, entity wepent)) { return '0 0 0'; }
     /** (SERVER) the weapon is dropped */
-    METHOD(Weapon, wr_drop, void(Weapon this, entity actor)) {}
+    METHOD(Weapon, wr_drop, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (SERVER) a weapon is picked up */
-    METHOD(Weapon, wr_pickup, void(Weapon this, entity actor)) {}
+    METHOD(Weapon, wr_pickup, void(Weapon this, entity actor, .entity weaponentity)) {}
     /** (SERVER) update cvar based properties */
     METHOD(Weapon, wr_update, void(Weapon this)) {}
        METHOD(Weapon, display, void(entity this, void(string name, string icon) returns)) {
index 4c94153..88ba1c7 100644 (file)
@@ -102,7 +102,7 @@ const int ARC_SF_LOCALMASK =   ARC_SF_START | ARC_SF_WANTDIR | ARC_SF_BEAMDIR;
 #endif
 #ifdef SVQC
 .entity arc_beam;
-.bool arc_BUTTON_ATCK_prev[MAX_WEAPONSLOTS]; // for better animation control
+.bool arc_BUTTON_ATCK_prev; // for better animation control
 .float beam_prev;
 .float beam_initialized;
 .float beam_bursting;
@@ -159,6 +159,7 @@ bool W_Arc_Beam_Send(entity this, entity to, int sf)
        if(drawlocal) { sf &= ~ARC_SF_LOCALMASK; }
 
        WriteByte(MSG_ENTITY, sf);
+       WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
 
        if(sf & ARC_SF_SETTINGS) // settings information
        {
@@ -273,7 +274,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));
 
@@ -341,7 +342,7 @@ void W_Arc_Beam_Think(entity this)
                ||
                forbidWeaponUse(this.owner)
                ||
-               PS(this.owner).m_switchweapon != WEP_ARC
+               this.owner.(weaponentity).m_switchweapon != WEP_ARC
                ||
                (!PHYS_INPUT_BUTTON_ATCK(this.owner) && !burst )
                ||
@@ -380,11 +381,11 @@ void W_Arc_Beam_Think(entity this)
                if(this == this.owner.(weaponentity).arc_beam) { this.owner.(weaponentity).arc_beam = NULL; }
                entity own = this.owner;
                Weapon w = WEP_ARC;
-               if(!w.wr_checkammo1(w, own) && !w.wr_checkammo2(w, own))
+               if(!w.wr_checkammo1(w, own, weaponentity) && !w.wr_checkammo2(w, own, weaponentity))
                if(!(own.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
-                       W_SwitchToOtherWeapon(own);
+                       W_SwitchToOtherWeapon(own, weaponentity);
                }
                delete(this);
                return;
@@ -677,7 +678,7 @@ void W_Arc_Beam_Think(entity this)
                this.beam_type = new_beam_type;
        }
 
-       this.owner.beam_prev = time;
+       this.owner.(weaponentity).beam_prev = time;
        this.nextthink = time;
 }
 
@@ -685,7 +686,7 @@ void W_Arc_Beam(float burst, entity actor, .entity weaponentity)
 {
 
        // only play fire sound if 1 sec has passed since player let go the fire button
-       if(time - actor.beam_prev > 1)
+       if(time - actor.(weaponentity).beam_prev > 1)
                sound(actor, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
 
        entity beam = actor.(weaponentity).arc_beam = new(W_Arc_Beam);
@@ -731,19 +732,20 @@ 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);
        }
 }
 
-METHOD(Arc, wr_aim, void(entity thiswep, entity actor))
+METHOD(Arc, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(WEP_CVAR(arc, beam_botaimspeed))
     {
         PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(
                actor,
+               weaponentity,
             WEP_CVAR(arc, beam_botaimspeed),
             0,
             WEP_CVAR(arc, beam_botaimlifetime),
@@ -754,6 +756,7 @@ METHOD(Arc, wr_aim, void(entity thiswep, entity actor))
     {
         PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(
                actor,
+               weaponentity,
             1000000,
             0,
             0.001,
@@ -767,13 +770,12 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
     Arc_Smoke(actor, weaponentity);
 
     bool beam_fire2 = ((fire & 2) && !WEP_CVAR(arc, bolt));
-    int slot = weaponslot(weaponentity);
 
     if (time >= actor.arc_overheat)
     if ((fire & 1) || beam_fire2 || actor.(weaponentity).arc_beam.beam_bursting)
     {
 
-        if(actor.arc_BUTTON_ATCK_prev[slot])
+        if(actor.(weaponentity).arc_BUTTON_ATCK_prev)
         {
             #if 0
             if(actor.animstate_startframe == actor.anim_shoot.x && actor.animstate_numframes == actor.anim_shoot.y)
@@ -789,10 +791,10 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
             {
                 W_Arc_Beam(boolean(beam_fire2), actor, weaponentity);
 
-                if(!actor.arc_BUTTON_ATCK_prev[slot])
+                if(!actor.(weaponentity).arc_BUTTON_ATCK_prev)
                 {
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-                    actor.arc_BUTTON_ATCK_prev[slot] = true;
+                    actor.(weaponentity).arc_BUTTON_ATCK_prev = true;
                 }
             }
         }
@@ -808,13 +810,14 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
         }
     }
 
-    if(actor.arc_BUTTON_ATCK_prev[slot])
+    if(actor.(weaponentity).arc_BUTTON_ATCK_prev)
     {
+       int slot = weaponslot(weaponentity);
         sound(actor, CH_WEAPON_A, SND_ARC_STOP, VOL_BASE, ATTN_NORM);
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
         ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor(actor);
     }
-    actor.arc_BUTTON_ATCK_prev[slot] = false;
+    actor.(weaponentity).arc_BUTTON_ATCK_prev = false;
 
     #if 0
     if(fire & 2)
@@ -837,16 +840,16 @@ METHOD(Arc, wr_init, void(entity thiswep))
         arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 4);
     }
 }
-METHOD(Arc, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Arc, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return ((!WEP_CVAR(arc, beam_ammo)) || (actor.(thiswep.ammo_field) > 0));
 }
-METHOD(Arc, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Arc, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     if(WEP_CVAR(arc, bolt))
     {
         float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(arc, bolt_ammo);
-        ammo_amount += actor.(weapon_load[WEP_ARC.m_id]) >= WEP_CVAR(arc, bolt_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_ARC.m_id]) >= WEP_CVAR(arc, bolt_ammo);
         return ammo_amount;
     }
     else
@@ -860,18 +863,17 @@ METHOD(Arc, wr_killmessage, Notification(entity thiswep))
     else
         return WEAPON_ARC_MURDER;
 }
-METHOD(Arc, wr_drop, void(entity thiswep, entity actor))
+METHOD(Arc, wr_drop, void(entity thiswep, entity actor, .entity weaponentity))
 {
     weapon_dropevent_item.arc_overheat = actor.arc_overheat;
     weapon_dropevent_item.arc_cooldown = actor.arc_cooldown;
     actor.arc_overheat = 0;
     actor.arc_cooldown = 0;
-    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       actor.arc_BUTTON_ATCK_prev[slot] = false;
+    actor.(weaponentity).arc_BUTTON_ATCK_prev = false;
 }
-METHOD(Arc, wr_pickup, void(entity thiswep, entity actor))
+METHOD(Arc, wr_pickup, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    if ( !client_hasweapon(actor, thiswep, false, false) &&
+    if ( !client_hasweapon(actor, thiswep, weaponentity, false, false) &&
         weapon_dropevent_item.arc_overheat > time )
     {
         actor.arc_overheat = weapon_dropevent_item.arc_overheat;
@@ -883,14 +885,16 @@ METHOD(Arc, wr_resetplayer, void(entity thiswep, entity actor))
     actor.arc_overheat = 0;
     actor.arc_cooldown = 0;
     for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       actor.arc_BUTTON_ATCK_prev[slot] = false;
+    {
+       .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).arc_BUTTON_ATCK_prev = false;
+    }
 }
 METHOD(Arc, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
 {
     actor.arc_overheat = 0;
     actor.arc_cooldown = 0;
-    int slot = weaponslot(weaponentity);
-    actor.arc_BUTTON_ATCK_prev[slot] = false;
+    actor.(weaponentity).arc_BUTTON_ATCK_prev = false;
 }
 #endif
 #ifdef CSQC
@@ -1300,11 +1304,12 @@ void Remove_ArcBeam(entity this)
 NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
 {
        int sf = ReadByte();
+       int slot = ReadByte();
        entity flash;
 
        if(isnew)
        {
-               int gunalign = W_GetGunAlignment(NULL);
+               int gunalign = W_GunAlign(viewmodels[slot], STAT(GUNALIGN)) - 1;
 
                this.beam_shotorigin = arc_shotorigin[gunalign];
 
index 2eb8f00..cc2fedc 100644 (file)
@@ -154,17 +154,17 @@ void W_Blaster_Attack(
        }
 }
 
-METHOD(Blaster, wr_aim, void(entity thiswep, entity actor))
+METHOD(Blaster, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(WEP_CVAR(blaster, secondary))
     {
         if((random() * (WEP_CVAR_PRI(blaster, damage) + WEP_CVAR_SEC(blaster, damage))) > WEP_CVAR_PRI(blaster, damage))
-            { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_SEC(blaster, speed), 0, WEP_CVAR_SEC(blaster, lifetime), false); }
+            { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(blaster, speed), 0, WEP_CVAR_SEC(blaster, lifetime), false); }
         else
-            { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
+            { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
     }
     else
-        { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
+        { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
 }
 
 METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponentity, int fire))
@@ -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;
             }
 
@@ -228,17 +228,12 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti
     }
 }
 
-METHOD(Blaster, wr_setup, void(entity thiswep, entity actor))
-{
-    actor.ammo_field = ammo_none;
-}
-
-METHOD(Blaster, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Blaster, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return true; // infinite ammo
 }
 
-METHOD(Blaster, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Blaster, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return true; // blaster has infinite ammo
 }
index 58214bf..e4d66eb 100644 (file)
@@ -98,8 +98,9 @@ void W_Crylink_CheckLinks(entity e)
 void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next)
 {
        W_Crylink_CheckLinks(next);
-       if(me == own.crylink_lastgroup)
-               own.crylink_lastgroup = ((me == next) ? NULL : next);
+       .entity weaponentity = me.weaponentity_fld;
+       if(me == own.(weaponentity).crylink_lastgroup)
+               own.(weaponentity).crylink_lastgroup = ((me == next) ? NULL : next);
        prev.queuenext = next;
        next.queueprev = prev;
        me.classname = "spike_oktoremove";
@@ -128,8 +129,9 @@ void W_Crylink_LinkExplode(entity e, entity e2, entity directhitentity)
 
        a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
 
-       if(e == e.realowner.crylink_lastgroup)
-               e.realowner.crylink_lastgroup = NULL;
+       .entity weaponentity = e.weaponentity_fld;
+       if(e == e.realowner.(weaponentity).crylink_lastgroup)
+               e.realowner.(weaponentity).crylink_lastgroup = NULL;
 
        float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
 
@@ -235,7 +237,8 @@ void W_Crylink_LinkJoinEffect_Think(entity this)
        // is there at least 2 projectiles very close?
        entity e, p;
        float n;
-       e = this.owner.crylink_lastgroup;
+       .entity weaponentity = this.weaponentity_fld;
+       e = this.owner.(weaponentity).crylink_lastgroup;
        n = 0;
        if(e)
        {
@@ -317,8 +320,9 @@ void W_Crylink_Touch(entity this, entity toucher)
 
        if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(this, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
        {
-               if(this == this.realowner.crylink_lastgroup)
-                       this.realowner.crylink_lastgroup = NULL;
+               .entity weaponentity = this.weaponentity_fld;
+               if(this == this.realowner.(weaponentity).crylink_lastgroup)
+                       this.realowner.(weaponentity).crylink_lastgroup = NULL;
                W_Crylink_LinkExplode(this.queuenext, this, toucher);
                this.classname = "spike_oktoremove";
                delete(this);
@@ -354,7 +358,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);
@@ -374,6 +378,7 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
                proj = new(spike);
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
+               proj.weaponentity_fld = weaponentity;
                proj.bot_dodge = true;
                proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage);
                if(shots == 1) {
@@ -450,9 +455,9 @@ void W_Crylink_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        }
        if(WEP_CVAR_PRI(crylink, joinspread) != 0)
        {
-               actor.crylink_lastgroup = proj;
+               actor.(weaponentity).crylink_lastgroup = proj;
                W_Crylink_CheckLinks(proj);
-               actor.crylink_waitrelease = 1;
+               actor.(weaponentity).crylink_waitrelease = 1;
        }
 }
 
@@ -464,7 +469,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);
@@ -482,6 +487,7 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        for(counter = 0; counter < shots; ++counter)
        {
                proj = new(spike);
+               proj.weaponentity_fld = weaponentity;
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = actor;
                proj.bot_dodge = true;
@@ -567,28 +573,28 @@ void W_Crylink_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
        }
        if(WEP_CVAR_SEC(crylink, joinspread) != 0)
        {
-               actor.crylink_lastgroup = proj;
+               actor.(weaponentity).crylink_lastgroup = proj;
                W_Crylink_CheckLinks(proj);
-               actor.crylink_waitrelease = 2;
+               actor.(weaponentity).crylink_waitrelease = 2;
        }
 }
 
-METHOD(Crylink, wr_aim, void(entity thiswep, entity actor))
+METHOD(Crylink, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(random() < 0.10)
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), false);
     else
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), false);
+        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), false);
 }
 METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(autocvar_g_balance_crylink_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
+    if(autocvar_g_balance_crylink_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     }
 
     if(fire & 1)
     {
-        if(actor.crylink_waitrelease != 1)
+        if(actor.(weaponentity).crylink_waitrelease != 1)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(crylink, refire)))
         {
             W_Crylink_Attack(thiswep, actor, weaponentity);
@@ -598,7 +604,7 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
 
     if((fire & 2) && autocvar_g_balance_crylink_secondary)
     {
-        if(actor.crylink_waitrelease != 2)
+        if(actor.(weaponentity).crylink_waitrelease != 2)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(crylink, refire)))
         {
             W_Crylink_Attack2(thiswep, actor, weaponentity);
@@ -606,54 +612,55 @@ METHOD(Crylink, wr_think, void(entity thiswep, entity actor, .entity weaponentit
         }
     }
 
-    if((actor.crylink_waitrelease == 1 && !(fire & 1)) || (actor.crylink_waitrelease == 2 && !(fire & 2)))
+    if((actor.(weaponentity).crylink_waitrelease == 1 && !(fire & 1)) || (actor.(weaponentity).crylink_waitrelease == 2 && !(fire & 2)))
     {
-        if(!actor.crylink_lastgroup || time > actor.crylink_lastgroup.teleport_time)
+        if(!actor.(weaponentity).crylink_lastgroup || time > actor.(weaponentity).crylink_lastgroup.teleport_time)
         {
             // fired and released now!
-            if(actor.crylink_lastgroup)
+            if(actor.(weaponentity).crylink_lastgroup)
             {
                 vector pos;
                 entity linkjoineffect;
-                float isprimary = (actor.crylink_waitrelease == 1);
+                float isprimary = (actor.(weaponentity).crylink_waitrelease == 1);
 
-                pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
+                pos = W_Crylink_LinkJoin(actor.(weaponentity).crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
 
                 linkjoineffect = new(linkjoineffect);
+                linkjoineffect.weaponentity_fld = weaponentity;
                 setthink(linkjoineffect, W_Crylink_LinkJoinEffect_Think);
                 linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
                 linkjoineffect.owner = actor;
                 setorigin(linkjoineffect, pos);
             }
-            actor.crylink_waitrelease = 0;
-            if(!thiswep.wr_checkammo1(thiswep, actor) && !thiswep.wr_checkammo2(thiswep, actor))
+            actor.(weaponentity).crylink_waitrelease = 0;
+            if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity) && !thiswep.wr_checkammo2(thiswep, actor, weaponentity))
             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
             {
                 // ran out of ammo!
                 actor.cnt = WEP_CRYLINK.m_id;
-                PS(actor).m_switchweapon = w_getbestweapon(actor);
+                actor.(weaponentity).m_switchweapon = w_getbestweapon(actor, weaponentity);
             }
         }
     }
 }
-METHOD(Crylink, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Crylink, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     // don't "run out of ammo" and switch weapons while waiting for release
-    if(actor.crylink_lastgroup && actor.crylink_waitrelease)
+    if(actor.(weaponentity).crylink_lastgroup && actor.(weaponentity).crylink_waitrelease)
         return true;
 
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(crylink, ammo);
-    ammo_amount += actor.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
     return ammo_amount;
 }
-METHOD(Crylink, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Crylink, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     // don't "run out of ammo" and switch weapons while waiting for release
-    if(actor.crylink_lastgroup && actor.crylink_waitrelease)
+    if(actor.(weaponentity).crylink_lastgroup && actor.(weaponentity).crylink_waitrelease)
         return true;
 
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(crylink, ammo);
-    ammo_amount += actor.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
     return ammo_amount;
 }
 METHOD(Crylink, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index 7e63e76..a6473b3 100644 (file)
@@ -63,7 +63,7 @@ ENDCLASS(Devastator)
 REGISTER_WEAPON(DEVASTATOR, devastator, NEW(Devastator));
 
 #ifdef SVQC
-.float rl_release[MAX_WEAPONSLOTS];
+.float rl_release;
 .float rl_detonate_later;
 #endif
 #endif
@@ -116,15 +116,16 @@ void W_Devastator_Explode(entity this, entity directhitentity)
        );
 
        Weapon thiswep = WEP_DEVASTATOR;
-       if(PS(this.realowner).m_weapon == thiswep)
+       .entity weaponentity = this.weaponentity_fld;
+       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))
                {
                        this.realowner.cnt = WEP_DEVASTATOR.m_id;
-                       int slot = 0; // TODO: unhardcode
+                       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, weaponentity);
                }
        }
        delete(this);
@@ -208,7 +209,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))
@@ -216,7 +217,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, weaponentity);
                }
        }
        delete(this);
@@ -289,13 +290,11 @@ void W_Devastator_Think(entity this)
                this.velocity = this.velocity + v_forward * min(WEP_CVAR(devastator, speedaccel) * W_WeaponSpeedFactor(this.realowner) * frametime, velspeed);
 
        // laser guided, or remote detonation
-       if(PS(this.realowner).m_weapon == WEP_DEVASTATOR)
+       .entity weaponentity = this.weaponentity_fld;
+       if(this.realowner.(weaponentity).m_weapon == WEP_DEVASTATOR)
        {
-               .entity weaponentity = this.weaponentity_fld;
-               int slot = weaponslot(weaponentity);
-
                if(this == this.realowner.(weaponentity).lastrocket)
-               if(!this.realowner.rl_release[slot])
+               if(!this.realowner.(weaponentity).rl_release)
                if(!PHYS_INPUT_BUTTON_ATCK2(this))
                if(WEP_CVAR(devastator, guiderate))
                if(time > this.pushltime)
@@ -368,7 +367,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);
@@ -424,10 +423,10 @@ void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
 
-METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
+METHOD(Devastator, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     // aim and decide to fire if appropriate
-    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
+    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false);
     if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
     {
         // decide whether to detonate rockets
@@ -505,25 +504,24 @@ METHOD(Devastator, wr_aim, void(entity thiswep, entity actor))
 
 METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
+    if(WEP_CVAR(devastator, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(devastator, ammo)) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else {
-       int slot = weaponslot(weaponentity);
         if(fire & 1)
         {
-            if(actor.rl_release[slot] || WEP_CVAR(devastator, guidestop))
+            if(actor.(weaponentity).rl_release || WEP_CVAR(devastator, guidestop))
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(devastator, refire)))
             {
                 W_Devastator_Attack(thiswep, actor, weaponentity);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
-                actor.rl_release[slot] = 0;
+                actor.(weaponentity).rl_release = 0;
             }
         }
         else
-            actor.rl_release[slot] = 1;
+            actor.(weaponentity).rl_release = 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",
@@ -539,12 +537,11 @@ METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponen
         }
     }
 }
-METHOD(Devastator, wr_setup, void(entity thiswep, entity actor))
+METHOD(Devastator, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       actor.rl_release[slot] = 1;
+    actor.(weaponentity).rl_release = 1;
 }
-METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     #if 0
     // don't switch while guiding a missile
@@ -553,7 +550,7 @@ METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor))
         ammo_amount = false;
         if(WEP_CVAR(devastator, reload_ammo))
         {
-            if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo) && actor.(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo))
+            if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo) && actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo))
                 ammo_amount = true;
         }
         else if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo))
@@ -570,17 +567,17 @@ METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor))
     else
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(devastator, ammo);
-        ammo_amount += actor.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
         LOG_INFOF("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s\n", actor.rl_release, actor.(thiswep.ammo_field), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE"));
         return ammo_amount;
     }
     #else
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(devastator, ammo);
-    ammo_amount += actor.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
     return ammo_amount;
     #endif
 }
-METHOD(Devastator, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Devastator, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return false;
 }
@@ -590,7 +587,7 @@ METHOD(Devastator, wr_resetplayer, void(entity thiswep, entity actor))
     {
        .entity weaponentity = weaponentities[slot];
        actor.(weaponentity).lastrocket = NULL; // stop rocket guiding, no revenge from the grave!
-       actor.rl_release[slot] = 0;
+       actor.(weaponentity).rl_release = 0;
     }
 }
 METHOD(Devastator, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index 319f0d1..46e46c2 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,
@@ -411,7 +411,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,
@@ -476,12 +476,12 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity)
 
 void W_Electro_CheckAttack(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if(actor.electro_count > 1)
+       if(actor.(weaponentity).electro_count > 1)
        if(PHYS_INPUT_BUTTON_ATCK2(actor))
        if(weapon_prepareattack(thiswep, actor, weaponentity, true, -1))
        {
                W_Electro_Attack_Orb(WEP_ELECTRO, actor, weaponentity);
-               actor.electro_count -= 1;
+               actor.(weaponentity).electro_count -= 1;
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
                return;
        }
@@ -491,7 +491,7 @@ void W_Electro_CheckAttack(Weapon thiswep, entity actor, .entity weaponentity, i
 
 .float bot_secondary_electromooth;
 
-METHOD(Electro, wr_aim, void(entity thiswep, entity actor))
+METHOD(Electro, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     PHYS_INPUT_BUTTON_ATCK(actor) = PHYS_INPUT_BUTTON_ATCK2(actor) = false;
     if(vdist(actor.origin - actor.enemy.origin, >, 1000)) { actor.bot_secondary_electromooth = 0; }
@@ -500,9 +500,9 @@ METHOD(Electro, wr_aim, void(entity thiswep, entity actor))
         float shoot;
 
         if(WEP_CVAR_PRI(electro, speed))
-            shoot = bot_aim(actor, WEP_CVAR_PRI(electro, speed), 0, WEP_CVAR_PRI(electro, lifetime), false);
+            shoot = bot_aim(actor, weaponentity, WEP_CVAR_PRI(electro, speed), 0, WEP_CVAR_PRI(electro, lifetime), false);
         else
-            shoot = bot_aim(actor, 1000000, 0, 0.001, false);
+            shoot = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 
         if(shoot)
         {
@@ -512,7 +512,7 @@ METHOD(Electro, wr_aim, void(entity thiswep, entity actor))
     }
     else
     {
-        if(bot_aim(actor, WEP_CVAR_SEC(electro, speed), WEP_CVAR_SEC(electro, speed_up), WEP_CVAR_SEC(electro, lifetime), true))
+        if(bot_aim(actor, weaponentity, WEP_CVAR_SEC(electro, speed), WEP_CVAR_SEC(electro, speed_up), WEP_CVAR_SEC(electro, lifetime), true))
         {
             PHYS_INPUT_BUTTON_ATCK2(actor) = true;
             if(random() < 0.03) actor.bot_secondary_electromooth = 0;
@@ -524,9 +524,9 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit
     if(autocvar_g_balance_electro_reload_ammo) // forced reload // WEAPONTODO
     {
         float ammo_amount = 0;
-        if(actor.clip_load >= WEP_CVAR_PRI(electro, ammo))
+        if(actor.(weaponentity).clip_load >= WEP_CVAR_PRI(electro, ammo))
             ammo_amount = 1;
-        if(actor.clip_load >= WEP_CVAR_SEC(electro, ammo))
+        if(actor.(weaponentity).clip_load >= WEP_CVAR_SEC(electro, ammo))
             ammo_amount += 1;
 
         if(!ammo_amount)
@@ -546,40 +546,44 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit
     }
     else if(fire & 2)
     {
-        if(time >= actor.electro_secondarytime)
+        if(time >= actor.(weaponentity).electro_secondarytime)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(electro, refire)))
         {
             W_Electro_Attack_Orb(thiswep, actor, weaponentity);
-            actor.electro_count = WEP_CVAR_SEC(electro, count);
+            actor.(weaponentity).electro_count = WEP_CVAR_SEC(electro, count);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
-            actor.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor(actor);
+            actor.(weaponentity).electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor(actor);
         }
     }
 }
-METHOD(Electro, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Electro, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(electro, ammo);
-    ammo_amount += actor.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
     return ammo_amount;
 }
-METHOD(Electro, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Electro, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount;
     if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
-        ammo_amount += actor.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
     }
     else
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(electro, ammo);
-        ammo_amount += actor.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo);
     }
     return ammo_amount;
 }
 METHOD(Electro, wr_resetplayer, void(entity thiswep, entity actor))
 {
-    actor.electro_secondarytime = time;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).electro_secondarytime = time;
+    }
 }
 METHOD(Electro, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
index ae1e48b..dff721a 100644 (file)
@@ -56,7 +56,7 @@ REGISTER_WEAPON(FIREBALL, fireball, NEW(Fireball));
 #ifdef SVQC
 .float bot_primary_fireballmooth; // whatever a mooth is
 .vector fireball_impactvec;
-.float fireball_primarytime[MAX_WEAPONSLOTS];
+.float fireball_primarytime;
 #endif
 #endif
 #ifdef IMPLEMENTATION
@@ -314,7 +314,7 @@ void W_Fireball_Attack2(entity actor, .entity weaponentity)
        vector f_diff;
        float c;
 
-       c = actor.bulletcounter % 4;
+       c = actor.(weaponentity).bulletcounter % 4;
        switch(c)
        {
                case 0:
@@ -364,13 +364,13 @@ void W_Fireball_Attack2(entity actor, .entity weaponentity)
        MUTATOR_CALLHOOK(EditProjectile, actor, proj);
 }
 
-METHOD(Fireball, wr_aim, void(entity thiswep, entity actor))
+METHOD(Fireball, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     PHYS_INPUT_BUTTON_ATCK(actor) = false;
     PHYS_INPUT_BUTTON_ATCK2(actor) = false;
     if(actor.bot_primary_fireballmooth == 0)
     {
-        if(bot_aim(actor, WEP_CVAR_PRI(fireball, speed), 0, WEP_CVAR_PRI(fireball, lifetime), false))
+        if(bot_aim(actor, weaponentity, WEP_CVAR_PRI(fireball, speed), 0, WEP_CVAR_PRI(fireball, lifetime), false))
         {
             PHYS_INPUT_BUTTON_ATCK(actor) = true;
             if(random() < 0.02) actor.bot_primary_fireballmooth = 0;
@@ -378,7 +378,7 @@ METHOD(Fireball, wr_aim, void(entity thiswep, entity actor))
     }
     else
     {
-        if(bot_aim(actor, WEP_CVAR_SEC(fireball, speed), WEP_CVAR_SEC(fireball, speed_up), WEP_CVAR_SEC(fireball, lifetime), true))
+        if(bot_aim(actor, weaponentity, WEP_CVAR_SEC(fireball, speed), WEP_CVAR_SEC(fireball, speed_up), WEP_CVAR_SEC(fireball, lifetime), true))
         {
             PHYS_INPUT_BUTTON_ATCK2(actor) = true;
             if(random() < 0.01) actor.bot_primary_fireballmooth = 1;
@@ -389,12 +389,11 @@ METHOD(Fireball, wr_think, void(entity thiswep, entity actor, .entity weaponenti
 {
     if(fire & 1)
     {
-       int slot = weaponslot(weaponentity);
-        if(time >= actor.fireball_primarytime[slot])
+        if(time >= actor.(weaponentity).fireball_primarytime)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(fireball, refire)))
         {
             W_Fireball_Attack1_Frame0(thiswep, actor, weaponentity, fire);
-            actor.fireball_primarytime[slot] = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(actor);
+            actor.(weaponentity).fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(actor);
         }
     }
     else if(fire & 2)
@@ -406,22 +405,21 @@ METHOD(Fireball, wr_think, void(entity thiswep, entity actor, .entity weaponenti
         }
     }
 }
-METHOD(Fireball, wr_setup, void(entity thiswep, entity actor))
-{
-    actor.ammo_field = ammo_none;
-}
-METHOD(Fireball, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Fireball, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return true; // infinite ammo
 }
-METHOD(Fireball, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Fireball, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return true; // fireball has infinite ammo
 }
 METHOD(Fireball, wr_resetplayer, void(entity thiswep, entity actor))
 {
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       actor.fireball_primarytime[slot] = time;
+       {
+               .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).fireball_primarytime = time;
+       }
 }
 METHOD(Fireball, wr_suicidemessage, Notification(entity thiswep))
 {
index 684ee75..eff656a 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));
 
@@ -184,7 +184,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));
 
@@ -236,7 +236,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
        vector s;
        vector forward, right, up;
 
-       if(!actor.hagar_load)
+       if(!actor.(weaponentity).hagar_load)
                return;
 
        weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(hagar, refire));
@@ -248,7 +248,7 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
        right = v_right;
        up = v_up;
 
-       shots = actor.hagar_load;
+       shots = actor.(weaponentity).hagar_load;
        missile = NULL;
        for(counter = 0; counter < shots; ++counter)
        {
@@ -305,8 +305,11 @@ void W_Hagar_Attack2_Load_Release(entity actor, .entity weaponentity)
        }
 
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
-       actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor(actor);
-       actor.hagar_load = 0;
+       actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor(actor);
+       actor.(weaponentity).hagar_load = 0;
+
+       if(weaponslot(weaponentity) == 0)
+               actor.hagar_load = 0;
 }
 
 void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
@@ -316,14 +319,14 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
        if(time < game_starttime)
                return;
 
-       bool loaded = actor.hagar_load >= WEP_CVAR_SEC(hagar, load_max);
+       bool loaded = actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max);
 
        // this is different than WR_CHECKAMMO when it comes to reloading
        bool enough_ammo;
        if(actor.items & IT_UNLIMITED_WEAPON_AMMO)
                enough_ammo = true;
        else if(autocvar_g_balance_hagar_reload_ammo)
-               enough_ammo = actor.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+               enough_ammo = actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
        else
                enough_ammo = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
 
@@ -333,19 +336,21 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
        {
                if(PHYS_INPUT_BUTTON_ATCK(actor) && WEP_CVAR_SEC(hagar, load_abort))
                {
-                       if(actor.hagar_load)
+                       if(actor.(weaponentity).hagar_load)
                        {
                                // 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
-                               actor.hagar_load = 0;
+                               W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo
+                               actor.(weaponentity).hagar_load = 0;
+                               if(weaponslot(weaponentity) == 0)
+                                       actor.hagar_load = 0;
                                sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
 
                                // pause until we can load rockets again, once we re-press the alt fire button
-                               actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
+                               actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
 
                                // require letting go of the alt fire button before we can load again
-                               actor.hagar_loadblock = true;
+                               actor.(weaponentity).hagar_loadblock = true;
                        }
                }
                else
@@ -353,49 +358,49 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
                        // check if we can attempt to load another rocket
                        if(!stopped)
                        {
-                               if(!actor.hagar_loadblock && actor.hagar_loadstep < time)
+                               if(!actor.(weaponentity).hagar_loadblock && actor.(weaponentity).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;
+                                       actor.(weaponentity).hagar_load += 1;
                                        sound(actor, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
 
-                                       if(actor.hagar_load >= WEP_CVAR_SEC(hagar, load_max))
+                                       if(actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max))
                                                stopped = true;
                                        else
-                                               actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
+                                               actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(actor);
                                }
                        }
-                       if(stopped && !actor.hagar_loadbeep && actor.hagar_load) // prevents the beep from playing each frame
+                       if(stopped && !actor.(weaponentity).hagar_loadbeep && actor.(weaponentity).hagar_load) // prevents the beep from playing each frame
                        {
                                // if this is the last rocket we can load, play a beep sound to notify the player
                                sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
-                               actor.hagar_loadbeep = true;
-                               actor.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor(actor);
+                               actor.(weaponentity).hagar_loadbeep = true;
+                               actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor(actor);
                        }
                }
        }
-       else if(actor.hagar_loadblock)
+       else if(actor.(weaponentity).hagar_loadblock)
        {
                // the alt fire button has been released, so re-enable loading if blocked
-               actor.hagar_loadblock = false;
+               actor.(weaponentity).hagar_loadblock = false;
        }
 
-       if(actor.hagar_load)
+       if(actor.(weaponentity).hagar_load)
        {
                // play warning sound if we're about to release
-               if(stopped && actor.hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)
+               if(stopped && actor.(weaponentity).hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)
                {
-                       if(!actor.hagar_warning) // prevents the beep from playing each frame
+                       if(!actor.(weaponentity).hagar_warning) // prevents the beep from playing each frame
                        {
                                // we're about to automatically release after holding time, play a beep sound to notify the player
                                sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
-                               actor.hagar_warning = true;
+                               actor.(weaponentity).hagar_warning = true;
                        }
                }
 
                // release if player let go of button or if they've held it in too long
-               if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
+               if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.(weaponentity).hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
                {
                        actor.(weaponentity).state = WS_READY;
                        W_Hagar_Attack2_Load_Release(actor, weaponentity);
@@ -403,15 +408,15 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
        }
        else
        {
-               actor.hagar_loadbeep = false;
-               actor.hagar_warning = false;
+               actor.(weaponentity).hagar_loadbeep = false;
+               actor.(weaponentity).hagar_warning = false;
 
                // we aren't checking ammo during an attack, so we must do it here
-               if(!(thiswep.wr_checkammo1(thiswep, actor) + thiswep.wr_checkammo2(thiswep, actor)))
+               if(!(thiswep.wr_checkammo1(thiswep, actor, weaponentity) + thiswep.wr_checkammo2(thiswep, actor, weaponentity)))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
-                       W_SwitchToOtherWeapon(actor);
+                       W_SwitchToOtherWeapon(actor, weaponentity);
                        return;
                }
        }
@@ -419,16 +424,16 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
 
 void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if(!(fire & 1) || actor.hagar_load || actor.hagar_loadblock || PS(actor).m_switchweapon != WEP_HAGAR)
+       if(!(fire & 1) || actor.(weaponentity).hagar_load || actor.(weaponentity).hagar_loadblock || actor.(weaponentity).m_switchweapon != WEP_HAGAR)
        {
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
 
-       if(!thiswep.wr_checkammo1(thiswep, actor))
+       if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
@@ -447,24 +452,26 @@ void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int
        weapon_thinkf(actor, weaponentity, theframe, WEP_CVAR_PRI(hagar, refire), W_Hagar_Attack_Auto);
 }
 
-METHOD(Hagar, wr_aim, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(random()>0.15)
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
     else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
+        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), false);
 }
 METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     float loadable_secondary;
     loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
+    if(weaponslot(weaponentity) == 0)
+       actor.hagar_load = actor.(weaponentity).hagar_load;
 
     if(loadable_secondary)
         W_Hagar_Attack2_Load(thiswep, actor, weaponentity); // must always run each frame
-    if(autocvar_g_balance_hagar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
+    if(autocvar_g_balance_hagar_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     }
-    else if((fire & 1) && !actor.hagar_load && !actor.hagar_loadblock) // not while secondary is loaded or awaiting reset
+    else if((fire & 1) && !actor.(weaponentity).hagar_load && !actor.(weaponentity).hagar_loadblock) // not while secondary is loaded or awaiting reset
        {
                if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
                        W_Hagar_Attack_Auto(thiswep, actor, weaponentity, fire);
@@ -481,47 +488,52 @@ METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
 METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor, .entity weaponentity))
 {
     // we lost the weapon and want to prepare switching away
-    if(actor.hagar_load)
+    if(actor.(weaponentity).hagar_load)
     {
        actor.(weaponentity).state = WS_READY;
        W_Hagar_Attack2_Load_Release(actor, weaponentity);
     }
 }
-METHOD(Hagar, wr_setup, void(entity thiswep, entity actor))
+METHOD(Hagar, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    actor.hagar_loadblock = false;
-
-    if(actor.hagar_load)
+       actor.hagar_load = 0;
+    actor.(weaponentity).hagar_loadblock = false;
+    if(actor.(weaponentity).hagar_load)
     {
-        W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.hagar_load * -1); // give back ammo if necessary
-        actor.hagar_load = 0;
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hagar, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo if necessary
+       actor.(weaponentity).hagar_load = 0;
     }
 }
-METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hagar, ammo);
-    ammo_amount += actor.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
     return ammo_amount;
 }
-METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hagar, ammo);
-    ammo_amount += actor.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
     return ammo_amount;
 }
 METHOD(Hagar, wr_resetplayer, void(entity thiswep, entity actor))
 {
     actor.hagar_load = 0;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).hagar_load = 0;
+    }
 }
 METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
 {
     // if we have any rockets loaded when we die, release them
-    if(actor.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
+    if(actor.(weaponentity).hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
        W_Hagar_Attack2_Load_Release(actor, weaponentity);
 }
 METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    if(!actor.hagar_load) // require releasing loaded rockets first
+    if(!actor.(weaponentity).hagar_load) // require releasing loaded rockets first
         W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), SND_RELOAD);
 }
 METHOD(Hagar, wr_suicidemessage, Notification(entity thiswep))
index 79bf081..010ca4f 100644 (file)
@@ -75,9 +75,9 @@ 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 = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * actor.(weaponentity).misc_bulletcounter);
     spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
     if(actor.crouch)
         spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
@@ -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;
@@ -176,10 +176,10 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
 
        if(PHYS_INPUT_BUTTON_ATCK(actor))
        {
-               if(!thiswep.wr_checkammo1(thiswep, actor))
+               if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
                        return;
                }
@@ -187,7 +187,7 @@ void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int
                int slot = weaponslot(weaponentity);
                ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(actor);
                W_HLAC_Attack(WEP_HLAC, actor, weaponentity);
-               actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+               actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
        }
        else
@@ -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);
@@ -212,19 +212,19 @@ void W_HLAC_Attack2_Frame(Weapon thiswep, entity actor, .entity weaponentity)
        }
 }
 
-METHOD(HLAC, wr_aim, void(entity thiswep, entity actor))
+METHOD(HLAC, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false);
+    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false);
 }
 METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(autocvar_g_balance_hlac_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
+    if(autocvar_g_balance_hlac_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else if(fire & 1)
     {
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hlac, refire)))
         {
-            actor.misc_bulletcounter = 0;
+            actor.(weaponentity).misc_bulletcounter = 0;
             W_HLAC_Attack(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
         }
@@ -239,16 +239,16 @@ METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         }
     }
 }
-METHOD(HLAC, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(HLAC, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hlac, ammo);
-    ammo_amount += actor.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
     return ammo_amount;
 }
-METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hlac, ammo);
-    ammo_amount += actor.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
     return ammo_amount;
 }
 METHOD(HLAC, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index f5dd96e..ff815d4 100644 (file)
@@ -192,19 +192,19 @@ void W_Hook_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     if (fire & 1) {
-        if(!actor.hook)
-        if(!(actor.hook_state & HOOK_WAITING_FOR_RELEASE))
-        if(time > actor.hook_refire)
+        if(!actor.(weaponentity).hook)
+        if(!(actor.(weaponentity).hook_state & HOOK_WAITING_FOR_RELEASE))
+        if(time > actor.(weaponentity).hook_refire)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, -1))
         {
-            W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo));
-            actor.hook_state |= HOOK_FIRING;
-            actor.hook_state |= HOOK_WAITING_FOR_RELEASE;
+            W_DecreaseAmmo(thiswep, actor, thiswep.ammo_factor * WEP_CVAR_PRI(hook, ammo), weaponentity);
+            actor.(weaponentity).hook_state |= HOOK_FIRING;
+            actor.(weaponentity).hook_state |= HOOK_WAITING_FOR_RELEASE;
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);
         }
     } else {
-        actor.hook_state |= HOOK_REMOVING;
-        actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+        actor.(weaponentity).hook_state |= HOOK_REMOVING;
+        actor.(weaponentity).hook_state &= ~HOOK_WAITING_FOR_RELEASE;
     }
 
     if(fire & 2)
@@ -216,43 +216,43 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         }
     }
 
-    if(actor.hook)
+    if(actor.(weaponentity).hook)
     {
         // if hooked, no bombs, and increase the timer
-        actor.hook_refire = max(actor.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor(actor));
+        actor.(weaponentity).hook_refire = max(actor.(weaponentity).hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor(actor));
 
         // hook also inhibits health regeneration, but only for 1 second
         if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
             actor.pauseregen_finished = max(actor.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
     }
 
-    if(actor.hook && actor.hook.state == 1)
+    if(actor.(weaponentity).hook && actor.(weaponentity).hook.state == 1)
     {
         float hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);
         if(hooked_time_max > 0)
         {
-            if( time > actor.hook_time_hooked + hooked_time_max )
-                actor.hook_state |= HOOK_REMOVING;
+            if( time > actor.(weaponentity).hook_time_hooked + hooked_time_max )
+                actor.(weaponentity).hook_state |= HOOK_REMOVING;
         }
 
         float hooked_fuel = thiswep.ammo_factor * WEP_CVAR_PRI(hook, hooked_ammo);
         if(hooked_fuel > 0)
         {
-            if( time > actor.hook_time_fueldecrease )
+            if( time > actor.(weaponentity).hook_time_fueldecrease )
             {
                 if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                 {
-                    if( actor.ammo_fuel >= (time - actor.hook_time_fueldecrease) * hooked_fuel )
+                    if( actor.ammo_fuel >= (time - actor.(weaponentity).hook_time_fueldecrease) * hooked_fuel )
                     {
-                        W_DecreaseAmmo(thiswep, actor, (time - actor.hook_time_fueldecrease) * hooked_fuel);
-                        actor.hook_time_fueldecrease = time;
+                        W_DecreaseAmmo(thiswep, actor, (time - actor.(weaponentity).hook_time_fueldecrease) * hooked_fuel, weaponentity);
+                        actor.(weaponentity).hook_time_fueldecrease = time;
                         // decrease next frame again
                     }
                     else
                     {
                         actor.ammo_fuel = 0;
-                        actor.hook_state |= HOOK_REMOVING;
-                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                        actor.(weaponentity).hook_state |= HOOK_REMOVING;
+                        W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                     }
                 }
             }
@@ -260,49 +260,54 @@ METHOD(Hook, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
     }
     else
     {
-        actor.hook_time_hooked = time;
-        actor.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
+        actor.(weaponentity).hook_time_hooked = time;
+        actor.(weaponentity).hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
     }
 
-    actor.hook_state = BITSET(actor.hook_state, HOOK_PULLING, (!PHYS_INPUT_BUTTON_CROUCH(actor) || !autocvar_g_balance_grapplehook_crouchslide));
+    actor.(weaponentity).hook_state = BITSET(actor.(weaponentity).hook_state, HOOK_PULLING, (!PHYS_INPUT_BUTTON_CROUCH(actor) || !autocvar_g_balance_grapplehook_crouchslide));
 
-    if (actor.hook_state & HOOK_FIRING)
+    if (actor.(weaponentity).hook_state & HOOK_FIRING)
     {
-        if (actor.hook)
-            RemoveGrapplingHook(actor);
-        FireGrapplingHook(actor);
-        actor.hook_state &= ~HOOK_FIRING;
-        actor.hook_refire = max(actor.hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor(actor));
+        if (actor.(weaponentity).hook)
+            RemoveHook(actor.(weaponentity).hook);
+        FireGrapplingHook(actor, weaponentity);
+        actor.(weaponentity).hook_state &= ~HOOK_FIRING;
+        actor.(weaponentity).hook_refire = max(actor.(weaponentity).hook_refire, time + autocvar_g_balance_grapplehook_refire * W_WeaponRateFactor(actor));
     }
-    else if (actor.hook_state & HOOK_REMOVING)
+    else if (actor.(weaponentity).hook_state & HOOK_REMOVING)
     {
-        if (actor.hook)
-            RemoveGrapplingHook(actor);
-        actor.hook_state &= ~HOOK_REMOVING;
+        if (actor.(weaponentity).hook)
+            RemoveHook(actor.(weaponentity).hook);
+        actor.(weaponentity).hook_state &= ~HOOK_REMOVING;
     }
 }
-METHOD(Hook, wr_setup, void(entity thiswep, entity actor))
+METHOD(Hook, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    actor.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+       actor.(weaponentity).hook_state &= ~HOOK_WAITING_FOR_RELEASE;
 }
-METHOD(Hook, wr_checkammo1, bool(Hook thiswep, entity actor))
+METHOD(Hook, wr_checkammo1, bool(Hook thiswep, entity actor, .entity weaponentity))
 {
     if (!thiswep.ammo_factor) return true;
-    if(actor.hook)
-        return actor.ammo_fuel > 0;
-    else
-        return actor.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
+
+    if(actor.(weaponentity).hook)
+       return actor.ammo_fuel > 0;
+
+    return actor.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
 }
-METHOD(Hook, wr_checkammo2, bool(Hook thiswep, entity actor))
+METHOD(Hook, wr_checkammo2, bool(Hook thiswep, entity actor, .entity weaponentity))
 {
     // infinite ammo for now
     return true; // actor.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above
 }
 METHOD(Hook, wr_resetplayer, void(entity thiswep, entity actor))
 {
-    RemoveGrapplingHook(actor);
-    actor.hook_time = 0;
-    actor.hook_refire = time;
+    RemoveGrapplingHooks(actor);
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).hook_time = 0;
+       actor.(weaponentity).hook_refire = time;
+    }
 }
 METHOD(Hook, wr_killmessage, Notification(entity thiswep))
 {
@@ -371,7 +376,7 @@ void Draw_GrapplingHook(entity this)
 
        InterpolateOrigin_Do(this);
 
-       int s = W_GetGunAlignment(NULL);
+       int s = W_GunAlign(viewmodels[this.cnt], STAT(GUNALIGN)) - 1;
 
        switch(this.HookType)
        {
@@ -514,10 +519,12 @@ NET_HANDLE(ENT_CLIENT_HOOK, bool bIsNew)
        if(sf & 1)
        {
                int myowner = ReadByte();
+               int slot = ReadByte();
                this.owner = playerslots[myowner - 1];
                this.sv_entnum = myowner;
-               if(csqcplayer && myowner == player_localentnum)
-                       csqcplayer.hook = this;
+               if(myowner == player_localentnum)
+                       viewmodels[slot].hook = this;
+               this.cnt = slot;
                switch(this.HookType)
                {
                        default:
index 81da28d..7344ba9 100644 (file)
@@ -111,7 +111,7 @@ void W_MachineGun_MuzzleFlash(entity actor, .entity weaponentity)
 
 void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity weaponentity)
 {
-       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, ((actor.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, ((actor.(weaponentity).misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
        if(!autocvar_g_norecoil)
        {
                actor.punchangle_x = random() - 0.5;
@@ -121,10 +121,10 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity we
        // this attack_finished just enforces a cooldown at the end of a burst
        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);
+       if(actor.(weaponentity).misc_bulletcounter == 1)
+               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);
 
@@ -138,30 +138,30 @@ void W_MachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity we
                SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
-       if(actor.misc_bulletcounter == 1)
-               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(machinegun, first_ammo));
+       if(actor.(weaponentity).misc_bulletcounter == 1)
+               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;
        }
        if(PHYS_INPUT_BUTTON_ATCK(actor))
        {
-               if(!thiswep.wr_checkammo2(thiswep, actor))
+               if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
                if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                {
-                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                        w_ready(thiswep, actor, weaponentity, fire);
                        return;
                }
-               actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
+               actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
                W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id, actor, weaponentity);
                weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
        }
@@ -180,15 +180,15 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
                return;
        }
 
-       if(!thiswep.wr_checkammo1(thiswep, actor))
+       if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
        if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), 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)
@@ -197,10 +197,10 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity
                actor.punchangle_y = random() - 0.5;
        }
 
-       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);
+       machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
+       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;
+       actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 
        Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 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);
 
@@ -240,8 +240,8 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
                SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, actor, weaponentity);
        }
 
-       actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
-       if(actor.misc_bulletcounter == 0)
+       actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+       if(actor.(weaponentity).misc_bulletcounter == 0)
        {
                int slot = weaponslot(weaponentity);
                ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor(actor);
@@ -254,16 +254,16 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit
 
 }
 
-METHOD(MachineGun, wr_aim, void(entity thiswep, entity actor))
+METHOD(MachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
     else
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
+        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 }
 METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(machinegun, reload_ammo) && actor.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
+    if(WEP_CVAR(machinegun, reload_ammo) && actor.(weaponentity).clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else
     if(WEP_CVAR(machinegun, mode) == 1)
@@ -271,24 +271,24 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
         if(fire & 1)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
         {
-            actor.misc_bulletcounter = 0;
+            actor.(weaponentity).misc_bulletcounter = 0;
             W_MachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
         }
 
         if(fire & 2)
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
         {
-            if(!thiswep.wr_checkammo2(thiswep, actor))
+            if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
             {
-                W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), 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;
+            actor.(weaponentity).misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
             W_MachineGun_Attack_Burst(thiswep, actor, weaponentity, fire);
         }
     }
@@ -298,7 +298,7 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
         if(fire & 1)
         if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
         {
-            actor.misc_bulletcounter = 1;
+            actor.(weaponentity).misc_bulletcounter = 1;
             W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id, actor, weaponentity); // sets attack_finished
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
         }
@@ -306,13 +306,13 @@ METHOD(MachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponen
         if((fire & 2) && WEP_CVAR(machinegun, first))
         if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
         {
-            actor.misc_bulletcounter = 1;
+            actor.(weaponentity).misc_bulletcounter = 1;
             W_MachineGun_Attack(WEP_MACHINEGUN, WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY, actor, weaponentity); // sets attack_finished
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
         }
     }
 }
-METHOD(MachineGun, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(MachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount;
     if(WEP_CVAR(machinegun, mode) == 1)
@@ -323,13 +323,13 @@ METHOD(MachineGun, wr_checkammo1, bool(entity thiswep, entity actor))
     if(WEP_CVAR(machinegun, reload_ammo))
     {
         if(WEP_CVAR(machinegun, mode) == 1)
-            ammo_amount += actor.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, sustained_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, sustained_ammo);
         else
-            ammo_amount += actor.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
     }
     return ammo_amount;
 }
-METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount;
     if(WEP_CVAR(machinegun, mode) == 1)
@@ -340,9 +340,9 @@ METHOD(MachineGun, wr_checkammo2, bool(entity thiswep, entity actor))
     if(WEP_CVAR(machinegun, reload_ammo))
     {
         if(WEP_CVAR(machinegun, mode) == 1)
-            ammo_amount += actor.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
         else
-            ammo_amount += actor.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
     }
     return ammo_amount;
 }
index 7df6984..00f729b 100644 (file)
@@ -72,6 +72,7 @@ void W_MineLayer_Stick(entity this, entity to)
 
        entity newmine = spawn();
        IL_PUSH(g_mines, newmine);
+       newmine.weaponentity_fld = this.weaponentity_fld;
        newmine.classname = this.classname;
 
        newmine.bot_dodge = this.bot_dodge;
@@ -127,20 +128,20 @@ 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))
+               if(!w.wr_checkammo1(w, own, weaponentity))
                {
                        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, weaponentity);
                }
        }
-       this.realowner.minelayer_mines -= 1;
+       this.realowner.(weaponentity).minelayer_mines -= 1;
        delete(this);
 }
 
@@ -159,20 +160,20 @@ 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))
+               if(!w.wr_checkammo1(w, own, weaponentity))
                {
                        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, weaponentity);
                }
        }
-       this.realowner.minelayer_mines -= 1;
+       this.realowner.(weaponentity).minelayer_mines -= 1;
        delete(this);
 }
 
@@ -207,10 +208,10 @@ void W_MineLayer_ProximityExplode(entity this)
        W_MineLayer_Explode(this, NULL);
 }
 
-int W_MineLayer_Count(entity e)
+int W_MineLayer_Count(entity e, .entity weaponentity)
 {
        int minecount = 0;
-       IL_EACH(g_mines, it.realowner == e,
+       IL_EACH(g_mines, it.realowner == e && it.weaponentity_fld == weaponentity,
        {
                minecount += 1;
        });
@@ -274,7 +275,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);
@@ -288,13 +290,16 @@ void W_MineLayer_Touch(entity this, entity toucher)
        if(WarpZone_Projectile_Touch(this, toucher))
        {
                if(wasfreed(this))
-                       this.realowner.minelayer_mines -= 1;
+               {
+                       .entity weaponentity = this.weaponentity_fld;
+                       this.realowner.(weaponentity).minelayer_mines -= 1;
+               }
                return;
        }
 
-       if(toucher && IS_PLAYER(toucher) && !IS_DEAD(toucher))
+       if((toucher && IS_PLAYER(toucher) && !IS_DEAD(toucher)) || toucher.owner == this.owner)
        {
-               // hit a player
+               // hit a player or other mine
                // don't stick
        }
        else
@@ -328,7 +333,7 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        // scan how many mines we placed, and return if we reached our limit
        if(WEP_CVAR(minelayer, limit))
        {
-               if(actor.minelayer_mines >= WEP_CVAR(minelayer, limit))
+               if(actor.(weaponentity).minelayer_mines >= WEP_CVAR(minelayer, limit))
                {
                        // the refire delay keeps this message from being spammed
                        Send_Notification(NOTIF_ONE, actor, MSG_MULTI, WEAPON_MINELAYER_LIMIT, WEP_CVAR(minelayer, limit));
@@ -337,7 +342,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);
@@ -394,14 +399,14 @@ void W_MineLayer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
 
        MUTATOR_CALLHOOK(EditProjectile, actor, mine);
 
-       actor.minelayer_mines = W_MineLayer_Count(actor);
+       actor.(weaponentity).minelayer_mines = W_MineLayer_Count(actor, weaponentity);
 }
 
-bool W_MineLayer_PlacedMines(entity this, bool detonate)
+bool W_MineLayer_PlacedMines(entity this, .entity weaponentity, bool detonate)
 {
        bool minfound = false;
 
-       IL_EACH(g_mines, it.realowner == this,
+       IL_EACH(g_mines, it.realowner == this && it.weaponentity_fld == weaponentity,
        {
                if(detonate)
                {
@@ -417,13 +422,13 @@ bool W_MineLayer_PlacedMines(entity this, bool detonate)
        return minfound;
 }
 
-METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
+METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     // aim and decide to fire if appropriate
-    if(actor.minelayer_mines >= WEP_CVAR(minelayer, limit))
+    if(actor.(weaponentity).minelayer_mines >= WEP_CVAR(minelayer, limit))
         PHYS_INPUT_BUTTON_ATCK(actor) = false;
     else
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(minelayer, speed), 0, WEP_CVAR(minelayer, lifetime), false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(minelayer, speed), 0, WEP_CVAR(minelayer, lifetime), false);
     if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
     {
         // decide whether to detonate mines
@@ -503,10 +508,13 @@ METHOD(MineLayer, wr_aim, void(entity thiswep, entity actor))
 }
 METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(autocvar_g_balance_minelayer_reload_ammo && actor.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
+       if(weaponslot(weaponentity) == 0)
+               actor.minelayer_mines = actor.(weaponentity).minelayer_mines;
+
+    if(autocvar_g_balance_minelayer_reload_ammo && actor.(weaponentity).clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
     {
         // not if we're holding the minelayer without enough ammo, but can detonate existing mines
-        if(!(W_MineLayer_PlacedMines(actor, false) && actor.(thiswep.ammo_field) < WEP_CVAR(minelayer, ammo))) {
+        if(!(W_MineLayer_PlacedMines(actor, weaponentity, false) && actor.(thiswep.ammo_field) < WEP_CVAR(minelayer, ammo))) {
             thiswep.wr_reload(thiswep, actor, weaponentity);
         }
     }
@@ -521,25 +529,25 @@ METHOD(MineLayer, wr_think, void(entity thiswep, entity actor, .entity weaponent
 
     if(fire & 2)
     {
-        if(W_MineLayer_PlacedMines(actor, true))
+        if(W_MineLayer_PlacedMines(actor, weaponentity, true))
             sound(actor, CH_WEAPON_B, SND_MINE_DET, VOL_BASE, ATTN_NORM);
     }
 }
-METHOD(MineLayer, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(MineLayer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     //int slot = 0; // TODO: unhardcode
     // actually do // don't switch while placing a mine
     //if(ATTACK_FINISHED(actor, slot) <= time || PS(actor).m_weapon != WEP_MINE_LAYER)
     //{
         float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(minelayer, ammo);
-        ammo_amount += actor.(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
         return ammo_amount;
     //}
     //return true;
 }
-METHOD(MineLayer, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(MineLayer, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    if(W_MineLayer_PlacedMines(actor, false))
+    if(W_MineLayer_PlacedMines(actor, weaponentity, false))
         return true;
     else
         return false;
@@ -547,6 +555,11 @@ METHOD(MineLayer, wr_checkammo2, bool(entity thiswep, entity actor))
 METHOD(MineLayer, wr_resetplayer, void(entity thiswep, entity actor))
 {
     actor.minelayer_mines = 0;
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       actor.(weaponentity).minelayer_mines = 0;
+    }
 }
 METHOD(MineLayer, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
index 89ff5bb..56338da 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
@@ -263,7 +263,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
@@ -311,13 +311,13 @@ void W_Mortar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
 
 .float bot_secondary_grenademooth;
 
-METHOD(Mortar, wr_aim, void(entity thiswep, entity actor))
+METHOD(Mortar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     PHYS_INPUT_BUTTON_ATCK(actor) = false;
     PHYS_INPUT_BUTTON_ATCK2(actor) = false;
     if(actor.bot_secondary_grenademooth == 0) // WEAPONTODO: merge this into using WEP_CVAR_BOTH
     {
-        if(bot_aim(actor, WEP_CVAR_PRI(mortar, speed), WEP_CVAR_PRI(mortar, speed_up), WEP_CVAR_PRI(mortar, lifetime), true))
+        if(bot_aim(actor, weaponentity, WEP_CVAR_PRI(mortar, speed), WEP_CVAR_PRI(mortar, speed_up), WEP_CVAR_PRI(mortar, lifetime), true))
         {
             PHYS_INPUT_BUTTON_ATCK(actor) = true;
             if(random() < 0.01) actor.bot_secondary_grenademooth = 1;
@@ -325,7 +325,7 @@ METHOD(Mortar, wr_aim, void(entity thiswep, entity actor))
     }
     else
     {
-        if(bot_aim(actor, WEP_CVAR_SEC(mortar, speed), WEP_CVAR_SEC(mortar, speed_up), WEP_CVAR_SEC(mortar, lifetime), true))
+        if(bot_aim(actor, weaponentity, WEP_CVAR_SEC(mortar, speed), WEP_CVAR_SEC(mortar, speed_up), WEP_CVAR_SEC(mortar, lifetime), true))
         {
             PHYS_INPUT_BUTTON_ATCK2(actor) = true;
             if(random() < 0.02) actor.bot_secondary_grenademooth = 0;
@@ -350,7 +350,7 @@ METHOD(Mortar, wr_aim, void(entity thiswep, entity actor))
     */
 METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(autocvar_g_balance_mortar_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
+    if(autocvar_g_balance_mortar_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else if(fire & 1)
     {
@@ -383,16 +383,16 @@ METHOD(Mortar, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         }
     }
 }
-METHOD(Mortar, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Mortar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(mortar, ammo);
-    ammo_amount += actor.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
     return ammo_amount;
 }
-METHOD(Mortar, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Mortar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(mortar, ammo);
-    ammo_amount += actor.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
     return ammo_amount;
 }
 METHOD(Mortar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
index 3e4654f..8c5ade9 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 = this.weaponentity_fld;
+                               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);
                        }
                }
@@ -147,7 +148,7 @@ void W_Porto_Touch(entity this, entity toucher)
                sound(this, CH_SHOTS, SND_PORTO_UNSUPPORTED, VOL_BASE, ATTEN_NORM);
                delete(this);
        }
-       else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+       else if((trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK) || (trace_dphitcontents & DPCONTENTS_PLAYERCLIP))
        {
                spamsound(this, CH_SHOTS, SND(PORTO_BOUNCE), VOL_BASE, ATTEN_NORM);
                // just reflect
@@ -254,6 +255,7 @@ void W_Porto_Attack(entity actor, .entity weaponentity, float type)
        //Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
        gren = new(porto);
+       gren.weaponentity_fld = weaponentity;
        gren.cnt = type;
        gren.owner = gren.realowner = actor;
        gren.playerid = actor.playerid;
@@ -296,12 +298,12 @@ void W_Porto_Attack(entity actor, .entity weaponentity, float type)
        MUTATOR_CALLHOOK(EditProjectile, actor, gren);
 }
 
-METHOD(PortoLaunch, wr_aim, void(entity thiswep, entity actor))
+METHOD(PortoLaunch, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     PHYS_INPUT_BUTTON_ATCK(actor) = false;
     PHYS_INPUT_BUTTON_ATCK2(actor) = false;
     if(!WEP_CVAR(porto, secondary))
-        if(bot_aim(actor, WEP_CVAR_PRI(porto, speed), 0, WEP_CVAR_PRI(porto, lifetime), false))
+        if(bot_aim(actor, weaponentity, WEP_CVAR_PRI(porto, speed), 0, WEP_CVAR_PRI(porto, lifetime), false))
             PHYS_INPUT_BUTTON_ATCK(actor) = true;
 }
 METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
@@ -328,27 +330,21 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
     }
     else
     {
-        if(actor.porto_v_angle_held)
+        if(actor.(weaponentity).porto_v_angle_held)
         {
             if(!(fire & 2))
-            {
-                actor.porto_v_angle_held = 0;
-
-                ClientData_Touch(actor);
-            }
+                actor.(weaponentity).porto_v_angle_held = 0;
         }
         else
         {
             if(fire & 2)
             {
-                actor.porto_v_angle = actor.v_angle;
-                actor.porto_v_angle_held = 1;
-
-                ClientData_Touch(actor);
+                actor.(weaponentity).porto_v_angle = actor.v_angle;
+                actor.(weaponentity).porto_v_angle_held = 1;
             }
         }
-        if(actor.porto_v_angle_held)
-            makevectors(actor.porto_v_angle); // override the previously set angles
+        if(actor.(weaponentity).porto_v_angle_held)
+            makevectors(actor.(weaponentity).porto_v_angle); // override the previously set angles
 
         if(fire & 1)
         if(!actor.porto_current)
@@ -360,20 +356,16 @@ METHOD(PortoLaunch, wr_think, void(entity thiswep, entity actor, .entity weapone
         }
     }
 }
-METHOD(PortoLaunch, wr_checkammo1, bool(entity thiswep, entity this))
+METHOD(PortoLaunch, wr_checkammo1, bool(entity thiswep, entity this, .entity weaponentity))
 {
     // always allow infinite ammo
     return true;
 }
-METHOD(PortoLaunch, wr_checkammo2, bool(entity thiswep, entity this))
+METHOD(PortoLaunch, wr_checkammo2, bool(entity thiswep, entity this, .entity weaponentity))
 {
     // always allow infinite ammo
     return true;
 }
-METHOD(PortoLaunch, wr_setup, void(entity thiswep, entity actor))
-{
-    actor.ammo_field = ammo_none;
-}
 METHOD(PortoLaunch, wr_resetplayer, void(entity thiswep, entity actor))
 {
     actor.porto_current = NULL;
index 478a315..37d8e0e 100644 (file)
@@ -12,6 +12,7 @@ CLASS(Rifle, Weapon)
 #endif
 /* crosshair */ ATTRIB(Rifle, w_crosshair, string, "gfx/crosshairrifle");
 /* crosshair */ ATTRIB(Rifle, w_crosshair_size, float, 0.6);
+/* reticle   */ ATTRIB(Rifle, w_reticle, string, "gfx/reticle_nex");
 /* wepimg    */ ATTRIB(Rifle, model2, string, "weaponrifle");
 /* refname   */ ATTRIB(Rifle, netname, string, "rifle");
 /* wepname   */ ATTRIB(Rifle, m_name, string, _("Rifle"));
@@ -61,7 +62,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 +75,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 +102,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);
@@ -142,7 +143,7 @@ void W_Rifle_BulletHail(entity actor, .entity weaponentity, float mode, void(ent
 
 .float bot_secondary_riflemooth;
 
-METHOD(Rifle, wr_aim, void(entity thiswep, entity actor))
+METHOD(Rifle, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     PHYS_INPUT_BUTTON_ATCK(actor) = false;
     PHYS_INPUT_BUTTON_ATCK2(actor) = false;
@@ -150,7 +151,7 @@ METHOD(Rifle, wr_aim, void(entity thiswep, entity actor))
         actor.bot_secondary_riflemooth = 0;
     if(actor.bot_secondary_riflemooth == 0)
     {
-        if(bot_aim(actor, 1000000, 0, 0.001, false))
+        if(bot_aim(actor, weaponentity, 1000000, 0, 0.001, false))
         {
             PHYS_INPUT_BUTTON_ATCK(actor) = true;
             if(random() < 0.01) actor.bot_secondary_riflemooth = 1;
@@ -158,7 +159,7 @@ METHOD(Rifle, wr_aim, void(entity thiswep, entity actor))
     }
     else
     {
-        if(bot_aim(actor, 1000000, 0, 0.001, false))
+        if(bot_aim(actor, weaponentity, 1000000, 0, 0.001, false))
         {
             PHYS_INPUT_BUTTON_ATCK2(actor) = true;
             if(random() < 0.03) actor.bot_secondary_riflemooth = 0;
@@ -167,7 +168,7 @@ METHOD(Rifle, wr_aim, void(entity thiswep, entity actor))
 }
 METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(autocvar_g_balance_rifle_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) { // forced reload
+    if(autocvar_g_balance_rifle_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else
     {
@@ -200,16 +201,16 @@ METHOD(Rifle, wr_think, void(entity thiswep, entity actor, .entity weaponentity,
         }
     }
 }
-METHOD(Rifle, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Rifle, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(rifle, ammo);
-    ammo_amount += actor.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
     return ammo_amount;
 }
-METHOD(Rifle, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Rifle, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(rifle, ammo);
-    ammo_amount += actor.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
     return ammo_amount;
 }
 METHOD(Rifle, wr_resetplayer, void(entity thiswep, entity actor))
@@ -241,6 +242,10 @@ METHOD(Rifle, wr_killmessage, Notification(entity thiswep))
             return WEAPON_RIFLE_MURDER;
     }
 }
+METHOD(Rifle, wr_zoom, bool(entity thiswep, entity actor))
+{
+    return PHYS_INPUT_BUTTON_ATCK2(actor) && WEP_CVAR(rifle, secondary) == 0;
+}
 
 #endif
 #ifdef CSQC
@@ -262,11 +267,10 @@ METHOD(Rifle, wr_init, void(entity thiswep))
         precache_pic("gfx/reticle_nex");
     }
 }
-METHOD(Rifle, wr_zoomreticle, bool(entity thiswep))
+METHOD(Rifle, wr_zoom, bool(entity thiswep, entity actor))
 {
     if(button_zoom || zoomscript_caught)
     {
-        reticle_image = "gfx/reticle_nex";
         return true;
     }
     else
index 0e73adf..20f5995 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);
@@ -336,9 +336,9 @@ 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;
+       c = actor.(weaponentity).bulletcounter % 4;
        switch(c)
        {
                case 0:
@@ -393,11 +393,11 @@ void W_Seeker_Fire_Flac(Weapon thiswep, entity actor, .entity weaponentity)
 // ============================
 // Begin: Tag and rocket controllers
 // ============================
-entity W_Seeker_Tagged_Info(entity isowner, entity istarget)
+entity W_Seeker_Tagged_Info(entity isowner, .entity weaponentity, entity istarget)
 {
        entity tag;
        for(tag = NULL; (tag = find(tag, classname, "tag_tracker")); )
-               if((tag.realowner == isowner) && (tag.tag_target == istarget))
+               if((tag.realowner == isowner) && (tag.tag_target == istarget) && (tag.weaponentity_fld == weaponentity))
                        return tag;
 
        return NULL;
@@ -433,7 +433,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;
@@ -445,7 +446,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)
@@ -470,8 +470,9 @@ void W_Seeker_Vollycontroller_Think(entity this) // TODO: Merge this with W_Seek
 
 void W_Seeker_Tracker_Think(entity this)
 {
+       .entity weaponentity = this.weaponentity_fld;
        // 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)
@@ -526,7 +527,8 @@ void W_Seeker_Tag_Touch(entity this, entity toucher)
        if(toucher.takedamage == DAMAGE_AIM && !IS_DEAD(toucher))
        {
                // check to see if this person is already tagged by me
-               entity tag = W_Seeker_Tagged_Info(this.realowner, toucher);
+               .entity weaponentity = this.weaponentity_fld;
+               entity tag = W_Seeker_Tagged_Info(this.realowner, weaponentity, toucher);
 
                if(tag != NULL)
                {
@@ -572,7 +574,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));
 
@@ -613,19 +615,19 @@ void W_Seeker_Fire_Tag(Weapon thiswep, entity actor, .entity weaponentity)
 // Begin: Genereal weapon functions
 // ============================
 
-METHOD(Seeker, wr_aim, void(entity thiswep, entity actor))
+METHOD(Seeker, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(WEP_CVAR(seeker, type) == 1)
-        if(W_Seeker_Tagged_Info(actor, actor.enemy) != NULL)
-            PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(seeker, missile_speed_max), 0, WEP_CVAR(seeker, missile_lifetime), false);
+        if(W_Seeker_Tagged_Info(actor, weaponentity, actor.enemy) != NULL)
+            PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(seeker, missile_speed_max), 0, WEP_CVAR(seeker, missile_lifetime), false);
         else
-            PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
+            PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
     else
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), false);
 }
 METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(autocvar_g_balance_seeker_reload_ammo && actor.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) { // forced reload
+    if(autocvar_g_balance_seeker_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else if(fire & 1)
     {
@@ -667,33 +669,33 @@ METHOD(Seeker, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         }
     }
 }
-METHOD(Seeker, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Seeker, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount;
     if(WEP_CVAR(seeker, type) == 1)
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, missile_ammo);
-        ammo_amount += actor.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, missile_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, missile_ammo);
     }
     else
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, tag_ammo);
-        ammo_amount += actor.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
     }
     return ammo_amount;
 }
-METHOD(Seeker, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Seeker, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount;
     if(WEP_CVAR(seeker, type) == 1)
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, tag_ammo);
-        ammo_amount += actor.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
     }
     else
     {
         ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(seeker, flac_ammo);
-        ammo_amount += actor.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, flac_ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, flac_ammo);
     }
     return ammo_amount;
 }
index 28cbe69..823aac1 100644 (file)
@@ -695,23 +695,23 @@ void W_Shockwave_Attack(entity actor, .entity weaponentity)
        }
 }
 
-METHOD(Shockwave, wr_aim, void(entity thiswep, entity actor))
+METHOD(Shockwave, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(vdist(actor.origin - actor.enemy.origin, <=, WEP_CVAR(shockwave, melee_range)))
-        { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false); }
+        { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false); }
     else
-        { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false); }
+        { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false); }
 }
 METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     if(fire & 1)
     {
-        if(time >= actor.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
+        if(time >= actor.(weaponentity).shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
         {
             if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(shockwave, blast_animtime)))
             {
                 W_Shockwave_Attack(actor, weaponentity);
-                actor.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor(actor);
+                actor.(weaponentity).shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor(actor);
                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
             }
         }
@@ -726,11 +726,11 @@ METHOD(Shockwave, wr_think, void(entity thiswep, entity actor, .entity weaponent
         }
     }
 }
-METHOD(Shockwave, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Shockwave, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     return true; // infinite ammo
 }
-METHOD(Shockwave, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Shockwave, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     // shockwave has infinite ammo
     return true;
index 9ae0c60..f6d730f 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));
 
@@ -199,10 +199,10 @@ void W_Shotgun_Attack2(Weapon thiswep, entity actor, .entity weaponentity, int f
 // alternate secondary weapon frames
 void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if (!thiswep.wr_checkammo2(thiswep, actor))
+       if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
@@ -213,10 +213,10 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
 }
 void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       if (!thiswep.wr_checkammo2(thiswep, actor))
+       if (!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
        {
-               W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                w_ready(thiswep, actor, weaponentity, fire);
                return;
        }
@@ -225,18 +225,18 @@ void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
 }
 
-.float shotgun_primarytime[MAX_WEAPONSLOTS];
+.float shotgun_primarytime;
 
-METHOD(Shotgun, wr_aim, void(entity thiswep, entity actor))
+METHOD(Shotgun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(vdist(actor.origin - actor.enemy.origin, <=, WEP_CVAR_SEC(shotgun, melee_range)))
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
+        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
     else
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 0.001, false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 }
 METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(shotgun, reload_ammo) && actor.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
+    if(WEP_CVAR(shotgun, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
     {
         // don't force reload an empty shotgun if its melee attack is active
         if(WEP_CVAR(shotgun, secondary) < 2) {
@@ -247,32 +247,30 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
     {
         if(fire & 1)
         {
-               int slot = weaponslot(weaponentity);
-            if(time >= actor.shotgun_primarytime[slot]) // handle refire separately so the secondary can be fired straight after a primary
+            if(time >= actor.(weaponentity).shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(shotgun, animtime)))
                 {
                     W_Shotgun_Attack(thiswep, actor, weaponentity, true);
-                    actor.shotgun_primarytime[slot] = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
+                    actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
                 }
             }
         }
         else if((fire & 2) && WEP_CVAR(shotgun, secondary) == 2)
         {
-               int slot = weaponslot(weaponentity);
-            if(time >= actor.shotgun_primarytime[slot]) // handle refire separately so the secondary can be fired straight after a primary
+            if(time >= actor.(weaponentity).shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(shotgun, alt_animtime)))
                 {
                     W_Shotgun_Attack(thiswep, actor, weaponentity, false);
-                    actor.shotgun_primarytime[slot] = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
+                    actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
                 }
             }
         }
     }
-    if(actor.clip_load >= 0) // we are not currently reloading
+    if(actor.(weaponentity).clip_load >= 0) // we are not currently reloading
     if(WEP_CVAR(shotgun, secondary) == 1)
     if(((fire & 1) && actor.(thiswep.ammo_field) <= 0 && !(actor.items & IT_UNLIMITED_WEAPON_AMMO)) || (fire & 2))
     if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(shotgun, refire)))
@@ -281,17 +279,13 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0, W_Shotgun_Attack2);
     }
 }
-METHOD(Shotgun, wr_setup, void(entity thiswep, entity actor))
-{
-    actor.ammo_field = ammo_none;
-}
-METHOD(Shotgun, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Shotgun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(shotgun, ammo);
-    ammo_amount += actor.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
     return ammo_amount;
 }
-METHOD(Shotgun, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Shotgun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     if(IS_BOT_CLIENT(actor))
     if(vdist(actor.origin - actor.enemy.origin, >, WEP_CVAR_SEC(shotgun, melee_range)))
@@ -302,7 +296,7 @@ METHOD(Shotgun, wr_checkammo2, bool(entity thiswep, entity actor))
         case 2: // secondary triple shot
         {
             float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(shotgun, ammo);
-            ammo_amount += actor.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
+            ammo_amount += actor.(weaponentity).(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
             return ammo_amount;
         }
         default: return false; // secondary unavailable
index 1f01ef0..786c960 100644 (file)
@@ -47,7 +47,6 @@ REGISTER_WEAPON(TUBA, tuba, NEW(Tuba));
 
 .entity tuba_note;
 .float tuba_smoketime;
-.float tuba_instrument;
 
 #define MAX_TUBANOTES 32
 .float tuba_lastnotes_last;
@@ -56,23 +55,23 @@ REGISTER_WEAPON(TUBA, tuba, NEW(Tuba));
 
 spawnfunc(weapon_tuba) { weapon_defaultspawnfunc(this, WEP_TUBA); }
 
-bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
+bool W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
 {
        float i, j, mmin, mmax, nolength;
        float n = tokenize_console(melody);
-       if(n > pl.tuba_lastnotes_cnt)
+       if(n > pl.(weaponentity).tuba_lastnotes_cnt)
                return false;
        float pitchshift = 0;
 
        if(instrument >= 0)
-               if(pl.tuba_instrument != instrument)
+               if(pl.(weaponentity).tuba_instrument != instrument)
                        return false;
 
        // verify notes...
        nolength = false;
        for(i = 0; i < n; ++i)
        {
-               vector v = pl.(tuba_lastnotes[(pl.tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
+               vector v = pl.(weaponentity).(tuba_lastnotes[(pl.(weaponentity).tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
                float ai = stof(argv(n - i - 1));
                float np = floor(ai);
                if(ai == np)
@@ -109,13 +108,13 @@ bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch
 
                for(i = 0; i < n; ++i)
                {
-                       vector vi = pl.(tuba_lastnotes[(pl.tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
+                       vector vi = pl.(weaponentity).(tuba_lastnotes[(pl.(weaponentity).tuba_lastnotes_last - i + MAX_TUBANOTES) % MAX_TUBANOTES]);
                        float ai = stof(argv(n - i - 1));
                        ti -= 1 / (ai - floor(ai));
                        float tj = ti;
                        for(j = i+1; j < n; ++j)
                        {
-                               vector vj = pl.(tuba_lastnotes[(pl.tuba_lastnotes_last - j + MAX_TUBANOTES) % MAX_TUBANOTES]);
+                               vector vj = pl.(weaponentity).(tuba_lastnotes[(pl.(weaponentity).tuba_lastnotes_last - j + MAX_TUBANOTES) % MAX_TUBANOTES]);
                                float aj = stof(argv(n - j - 1));
                                tj -= (aj - floor(aj));
 
@@ -142,7 +141,7 @@ bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch
                        return false;
        }
 
-       pl.tuba_lastnotes_cnt = 0;
+       pl.(weaponentity).tuba_lastnotes_cnt = 0;
 
        return true;
 }
@@ -154,12 +153,13 @@ void W_Tuba_NoteOff(entity this)
        //   on: this.spawnshieldtime
        //   off: time
        //   note: this.cnt
-       if (actor.tuba_note == this)
+       .entity weaponentity = this.weaponentity_fld;
+       if (actor.(weaponentity).tuba_note == this)
        {
-               actor.tuba_lastnotes_last = (actor.tuba_lastnotes_last + 1) % MAX_TUBANOTES;
-               actor.(tuba_lastnotes[actor.tuba_lastnotes_last]) = eX * this.spawnshieldtime + eY * time + eZ * this.cnt;
-               actor.tuba_note = NULL;
-               actor.tuba_lastnotes_cnt = bound(0, actor.tuba_lastnotes_cnt + 1, MAX_TUBANOTES);
+               actor.(weaponentity).tuba_lastnotes_last = (actor.(weaponentity).tuba_lastnotes_last + 1) % MAX_TUBANOTES;
+               actor.(weaponentity).(tuba_lastnotes[actor.(weaponentity).tuba_lastnotes_last]) = eX * this.spawnshieldtime + eY * time + eZ * this.cnt;
+               actor.(weaponentity).tuba_note = NULL;
+               actor.(weaponentity).tuba_lastnotes_cnt = bound(0, actor.(weaponentity).tuba_lastnotes_cnt + 1, MAX_TUBANOTES);
 
                string s = trigger_magicear_processmessage_forallears(actor, 0, NULL, string_null);
                if (s != "")
@@ -320,47 +320,49 @@ void W_Tuba_NoteOn(entity actor, .entity weaponentity, float hittype)
        n = W_Tuba_GetNote(actor, hittype);
 
        hittype = 0;
-       if(actor.tuba_instrument & 1)
+       if(actor.(weaponentity).tuba_instrument & 1)
                hittype |= HITTYPE_SECONDARY;
-       if(actor.tuba_instrument & 2)
+       if(actor.(weaponentity).tuba_instrument & 2)
                hittype |= HITTYPE_BOUNCE;
 
-       if(actor.tuba_note)
+       if(actor.(weaponentity).tuba_note)
        {
-               if(actor.tuba_note.cnt != n || actor.tuba_note.tuba_instrument != actor.tuba_instrument)
+               if(actor.(weaponentity).tuba_note.cnt != n || actor.(weaponentity).tuba_note.tuba_instrument != actor.(weaponentity).tuba_instrument)
                {
-                       W_Tuba_NoteOff(actor.tuba_note);
+                       W_Tuba_NoteOff(actor.(weaponentity).tuba_note);
                }
        }
 
-       if(!actor.tuba_note)
+       if(!actor.(weaponentity).tuba_note)
        {
-               actor.tuba_note = new(tuba_note);
-               actor.tuba_note.owner = actor.tuba_note.realowner = actor;
-               actor.tuba_note.cnt = n;
-               actor.tuba_note.tuba_instrument = actor.tuba_instrument;
-               setthink(actor.tuba_note, W_Tuba_NoteThink);
-               actor.tuba_note.nextthink = time;
-               actor.tuba_note.spawnshieldtime = time;
-               Net_LinkEntity(actor.tuba_note, false, 0, W_Tuba_NoteSendEntity);
+               entity note = new(tuba_note);
+               note.weaponentity_fld = weaponentity;
+               actor.(weaponentity).tuba_note = note;
+               note.owner = note.realowner = actor;
+               note.cnt = n;
+               note.tuba_instrument = actor.(weaponentity).tuba_instrument;
+               setthink(note, W_Tuba_NoteThink);
+               note.nextthink = time;
+               note.spawnshieldtime = time;
+               Net_LinkEntity(note, false, 0, W_Tuba_NoteSendEntity);
        }
 
-       actor.tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(actor); // so it can get prolonged safely
+       actor.(weaponentity).tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(actor); // so it can get prolonged safely
 
        //sound(actor, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation);
        RadiusDamage(actor, actor, WEP_CVAR(tuba, damage), WEP_CVAR(tuba, edgedamage), WEP_CVAR(tuba, radius), NULL, NULL, WEP_CVAR(tuba, force), hittype | WEP_TUBA.m_id, NULL);
 
        o = gettaginfo(actor.exteriorweaponentity, 0);
-       if(time > actor.tuba_smoketime)
+       if(time > actor.(weaponentity).tuba_smoketime)
        {
                Send_Effect(EFFECT_SMOKE_RING, o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1);
-               actor.tuba_smoketime = time + 0.25;
+               actor.(weaponentity).tuba_smoketime = time + 0.25;
        }
 }
 #endif
 
 #ifdef SVQC
-METHOD(Tuba, wr_aim, void(Tuba this, entity actor))
+METHOD(Tuba, wr_aim, void(Tuba this, entity actor, .entity weaponentity))
 {
        // bots cannot play the Tuba well yet
        // I think they should start with the recorder first
@@ -387,73 +389,40 @@ METHOD(Tuba, wr_think, void(Tuba this, entity actor, .entity weaponentity, int f
                W_Tuba_NoteOn(actor, weaponentity, HITTYPE_SECONDARY);
                weapon_thinkf(actor, weaponentity, WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
        }
-       if (actor.tuba_note)
+       if (actor.(weaponentity).tuba_note)
        {
                if (!(fire & 1) && !(fire & 2))
                {
-                       W_Tuba_NoteOff(actor.tuba_note);
+                       W_Tuba_NoteOff(actor.(weaponentity).tuba_note);
                }
        }
 }
 
-void tuba_instrument_send(entity this, int instr);
-METHOD(Tuba, wr_setup, void(Tuba this, entity actor))
+METHOD(Tuba, wr_setup, void(Tuba this, entity actor, .entity weaponentity))
 {
-       actor.ammo_field = ammo_none;
-       actor.tuba_instrument = 0;
-       tuba_instrument_send(actor, actor.tuba_instrument);
+       actor.(weaponentity).tuba_instrument = 0;
 }
-#endif
 
-REGISTER_NET_S2C(tuba_instrument)
-#ifdef CSQC
-NET_HANDLE(tuba_instrument, bool)
-{
-       int i = ReadByte();
-       return = true;
-       string s = (i == 0) ? "tuba" :
-                  (i == 1) ? "akordeon" :
-                             "kleinbottle" ;
-    viewmodel.tuba_instrument = i;
-       CL_WeaponEntity_SetModel(viewmodel, s, true);
-}
-#endif
-#ifdef SVQC
-void tuba_instrument_send(entity this, int instr)
-{
-       msg_entity = this;
-       if (!IS_REAL_CLIENT(this))
-               return;
-       int chan = MSG_ONE;
-       WriteHeader(chan, tuba_instrument);
-       WriteByte(chan, instr);
-}
-SPECTATE_COPY()
-{
-       if (this.tuba_instrument != spectatee.tuba_instrument)
-               tuba_instrument_send(this, this.tuba_instrument = spectatee.tuba_instrument);
-}
 METHOD(Tuba, wr_reload, void(Tuba this, entity actor, .entity weaponentity))
 {
        // switch to alternate instruments :)
        if (actor.(weaponentity).state == WS_READY)
        {
-               switch (actor.tuba_instrument)
+               switch (actor.(weaponentity).tuba_instrument)
                {
                        case 0:
-                               actor.tuba_instrument = 1;
-                               actor.weaponname = "akordeon";
+                               actor.(weaponentity).tuba_instrument = 1;
+                               actor.(weaponentity).weaponname = "akordeon";
                                break;
                        case 1:
-                               actor.tuba_instrument = 2;
-                               actor.weaponname = "kleinbottle";
+                               actor.(weaponentity).tuba_instrument = 2;
+                               actor.(weaponentity).weaponname = "kleinbottle";
                                break;
                        case 2:
-                               actor.tuba_instrument = 0;
-                               actor.weaponname = "tuba";
+                               actor.(weaponentity).tuba_instrument = 0;
+                               actor.(weaponentity).weaponname = "tuba";
                                break;
                }
-               tuba_instrument_send(actor, actor.tuba_instrument);
                W_SetupShot(actor, weaponentity, false, 0, SND_Null, 0, 0);
                Send_Effect(EFFECT_TELEPORT, w_shotorg, '0 0 0', 1);
                actor.(weaponentity).state = WS_INUSE;
@@ -465,8 +434,8 @@ METHOD(Tuba, wr_reload, void(Tuba this, entity actor, .entity weaponentity))
 #ifdef SVQC
 
 // infinite ammo
-METHOD(Tuba, wr_checkammo1, bool(Tuba this, entity actor)) { return true; }
-METHOD(Tuba, wr_checkammo2, bool(Tuba this, entity actor)) { return true; }
+METHOD(Tuba, wr_checkammo1, bool(Tuba this, entity actor, .entity weaponentity)) { return true; }
+METHOD(Tuba, wr_checkammo2, bool(Tuba this, entity actor, .entity weaponentity)) { return true; }
 
 METHOD(Tuba, wr_suicidemessage, Notification(Tuba this))
 {
index e11e4d8..7866f1b 100644 (file)
@@ -12,6 +12,7 @@ CLASS(Vaporizer, Weapon)
 #endif
 /* crosshair */ ATTRIB(Vaporizer, w_crosshair, string, "gfx/crosshairminstanex");
 /* crosshair */ ATTRIB(Vaporizer, w_crosshair_size, float, 0.6);
+/* reticle   */ ATTRIB(Vaporizer, w_reticle, string, "gfx/reticle_nex");
 /* wepimg    */ ATTRIB(Vaporizer, model2, string, "weaponminstanex");
 /* refname   */ ATTRIB(Vaporizer, netname, string, "vaporizer");
 /* wepname   */ ATTRIB(Vaporizer, m_name, string, _("Vaporizer"));
@@ -193,7 +194,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 +213,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 +254,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 +308,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);
 
@@ -351,20 +352,20 @@ void W_RocketMinsta_Attack3 (entity actor, .entity weaponentity)
     }
 }
 
-METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor))
+METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
     if(actor.(thiswep.ammo_field) > 0)
-        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, 1000000, 0, 1, false);
+        PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 1, false);
     else
-        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
+        PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), false); // WEAPONTODO: replace with proper vaporizer cvars
 }
 METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
     // if the laser uses load, we also consider its ammo for reloading
-    if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
+    if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.(weaponentity).clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
-    } else if(WEP_CVAR(vaporizer, reload_ammo) && actor.clip_load < vaporizer_ammo) { // forced reload
+    } else if(WEP_CVAR(vaporizer, reload_ammo) && actor.(weaponentity).clip_load < vaporizer_ammo) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     }
     if((fire & 1) && (actor.ammo_cells || !autocvar_g_rm) && !forbidWeaponUse(actor))
@@ -380,36 +381,36 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent
         if((autocvar_g_rm && autocvar_g_rm_laser) || autocvar_g_rm_laser == 2)
         {
             bool rapid = autocvar_g_rm_laser_rapid;
-            if(actor.jump_interval <= time && !actor.held_down)
+            if(actor.(weaponentity).jump_interval <= time && !actor.(weaponentity).held_down)
             {
                 if(rapid)
-                    actor.held_down = true;
-                actor.jump_interval = time + autocvar_g_rm_laser_refire;
-                actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_delay;
+                    actor.(weaponentity).held_down = true;
+                actor.(weaponentity).jump_interval = time + autocvar_g_rm_laser_refire;
+                actor.(weaponentity).jump_interval2 = time + autocvar_g_rm_laser_rapid_delay;
                 damage_goodhits = 0;
                 W_RocketMinsta_Attack2(actor, weaponentity);
             }
-            else if(rapid && actor.jump_interval2 <= time && actor.held_down)
+            else if(rapid && actor.(weaponentity).jump_interval2 <= time && actor.(weaponentity).held_down)
             {
-                actor.jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
+                actor.(weaponentity).jump_interval2 = time + autocvar_g_rm_laser_rapid_refire;
                 damage_goodhits = 0;
                 W_RocketMinsta_Attack3(actor, weaponentity);
                 //weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_rm_laser_rapid_animtime, w_ready);
             }
         }
-        else if (actor.jump_interval <= time)
+        else if (actor.(weaponentity).jump_interval <= time)
         {
             // handle refire manually, so that primary and secondary can be fired without conflictions (important for instagib)
-            actor.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor(actor);
+            actor.(weaponentity).jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor(actor);
 
             // 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,33 +425,32 @@ 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);
         }
     }
     else
-        actor.held_down = false;
+        actor.(weaponentity).held_down = false;
 }
-METHOD(Vaporizer, wr_setup, void(entity thiswep, entity actor))
+METHOD(Vaporizer, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    actor.ammo_field = (thiswep.ammo_field);
     actor.vaporizer_lasthit = 0;
 }
-METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
     float ammo_amount = actor.(thiswep.ammo_field) >= vaporizer_ammo;
-    ammo_amount += actor.(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
     return ammo_amount;
 }
-METHOD(Vaporizer, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Vaporizer, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     if(!WEP_CVAR_SEC(vaporizer, ammo))
         return true;
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(vaporizer, ammo);
-    ammo_amount += actor.(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
     return ammo_amount;
 }
 METHOD(Vaporizer, wr_resetplayer, void(entity thiswep, entity actor))
@@ -501,11 +501,10 @@ METHOD(Vaporizer, wr_init, void(entity thiswep))
         precache_pic("gfx/reticle_nex");
     }
 }
-METHOD(Vaporizer, wr_zoomreticle, bool(entity thiswep))
+METHOD(Vaporizer, wr_zoom, bool(entity thiswep, entity actor))
 {
     if(button_zoom || zoomscript_caught)
     {
-        reticle_image = "gfx/reticle_nex";
         return true;
     }
     else
index bf3ce81..b3ba65c 100644 (file)
@@ -12,6 +12,7 @@ CLASS(Vortex, Weapon)
 #endif
 /* crosshair */ ATTRIB(Vortex, w_crosshair, string, "gfx/crosshairnex");
 /* crosshair */ ATTRIB(Vortex, w_crosshair_size, float, 0.65);
+/* reticle   */ ATTRIB(Vortex, w_reticle, string, "gfx/reticle_nex");
 /* wepimg    */ ATTRIB(Vortex, model2, string, "weaponnex");
 /* refname   */ ATTRIB(Vortex, netname, string, "vortex");
 /* wepname   */ ATTRIB(Vortex, m_name, string, _("Vortex"));
@@ -78,10 +79,10 @@ float autocvar_g_weapon_charge_colormod_blue_half;
 float autocvar_g_weapon_charge_colormod_green_half;
 float autocvar_g_weapon_charge_colormod_hdrmultiplier;
 
-METHOD(Vortex, wr_glow, vector(Vortex this, entity actor))
+METHOD(Vortex, wr_glow, vector(Vortex this, entity actor, entity wepent))
 {
        if (!STAT(WEP_CVAR_vortex_charge, actor)) return '0 0 0';
-       float charge = STAT(VORTEX_CHARGE, actor);
+       float charge = wepent.vortex_charge;
        float animlimit = STAT(WEP_CVAR_vortex_charge_animlimit, actor);
        vector g;
        g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, charge / animlimit);
@@ -147,15 +148,23 @@ MUTATOR_HOOKFUNCTION(vortex_charge, GetPressedKeys)
     entity player = M_ARGV(0, entity);
 
        // 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))
-       {
-               // 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));
-               float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
-               // add the extra charge
-               player.vortex_charge = min(1, player.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
-       }
+    if(!WEP_CVAR(vortex, charge) || !WEP_CVAR(vortex, charge_velocity_rate))
+        return;
+
+    for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+        .entity weaponentity = weaponentities[slot];
+
+       if (player.(weaponentity).m_weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && vdist(vec2(player.velocity), >, WEP_CVAR(vortex, charge_minspeed)))
+       {
+            float xyspeed = vlen(vec2(player.velocity));
+               // 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));
+               float f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
+               // add the extra charge
+               player.(weaponentity).vortex_charge = min(1, player.(weaponentity).vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
+       }
+    }
 }
 
 void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float issecondary)
@@ -175,8 +184,8 @@ void W_Vortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float i
 
        if(WEP_CVAR(vortex, charge))
        {
-               charge = WEP_CVAR(vortex, charge_mindmg) / mydmg + (1 - WEP_CVAR(vortex, charge_mindmg) / mydmg) * actor.vortex_charge;
-               actor.vortex_charge *= WEP_CVAR(vortex, charge_shot_multiplier); // do this AFTER setting mydmg/myforce
+               charge = WEP_CVAR(vortex, charge_mindmg) / mydmg + (1 - WEP_CVAR(vortex, charge_mindmg) / mydmg) * actor.(weaponentity).vortex_charge;
+               actor.(weaponentity).vortex_charge *= WEP_CVAR(vortex, charge_shot_multiplier); // do this AFTER setting mydmg/myforce
                // O RLY? -- divVerent
                // YA RLY -- FruitieX
        }
@@ -193,7 +202,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,14 +217,14 @@ 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;
 
-METHOD(Vortex, wr_aim, void(entity thiswep, entity actor))
+METHOD(Vortex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    if(bot_aim(actor, 1000000, 0, 1, false))
+    if(bot_aim(actor, weaponentity, 1000000, 0, 1, false))
         PHYS_INPUT_BUTTON_ATCK(actor) = true;
     else
     {
@@ -225,18 +234,24 @@ METHOD(Vortex, wr_aim, void(entity thiswep, entity actor))
 }
 METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(vortex, charge) && actor.vortex_charge < WEP_CVAR(vortex, charge_limit))
-        actor.vortex_charge = min(1, actor.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
+    if(WEP_CVAR(vortex, charge) && actor.(weaponentity).vortex_charge < WEP_CVAR(vortex, charge_limit))
+        actor.(weaponentity).vortex_charge = min(1, actor.(weaponentity).vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
+
+    if(weaponslot(weaponentity) == 0)
+        actor.vortex_charge = actor.(weaponentity).vortex_charge;
 
     if(WEP_CVAR_SEC(vortex, chargepool))
-        if(actor.vortex_chargepool_ammo < 1)
+        if(actor.(weaponentity).vortex_chargepool_ammo < 1)
         {
         &nbs