]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/wepent_experimental
authorMario <mario@smbclan.net>
Wed, 21 Dec 2016 07:43:38 +0000 (17:43 +1000)
committerMario <mario@smbclan.net>
Wed, 21 Dec 2016 07:43:38 +0000 (17:43 +1000)
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 781377637e076515e4fc0474340d4357e4460079..f36a5a77494e9508a79bc8d083574b408c2f1262 100644 (file)
@@ -55,22 +55,6 @@ set g_overkill_filter_armormedium 0
 set g_overkill_filter_armorbig 0
 set g_overkill_filter_armormega 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 077b5f450a5ff2eee4b0ca4dd52a5aee382c77ee..5935342ae474c7e064159402e5b830c1752caaed 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 309ed1d81572998098dcc40fdaad24ae72df6ba1..c520a2f1eb8fe6180cfb7ddb18ab5d890f91b259 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 06a34911453f3a8120a89171ab237e1283dd2172..7ea0ce57916e51a95fda69fe15082299ece1b364 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 e299d1416ea1485da0cd4dee153aa1afc835dd4f..94545ac4bff69ea3511cb20866973709d190895a 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 db25d532a016f938e31a04045ac54e1886f03617..69fd82c9e0d9d79a71890c6e6c3d88f82c334ecb 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 36ca217240f0ba0e8a6966fcb25b06829df43491..f48c0c530a40cf631c10c1e54c696d80db6dc741 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 54ed9e2c39aafd90498b2ad39633fe3846540a89..bbf69d28d1bcd39586a78041babc247bc2166cea 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 5f88e78edf4b13bcc8702fc030edb6f22cc1d8ac..63a0aef279706cdc7ec78d7c649c30734ee12856 100644 (file)
@@ -283,9 +283,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;
@@ -294,9 +296,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)
@@ -311,15 +313,14 @@ void viewmodel_draw(entity this)
                CSQCModel_Effects_Apply(e);
        }
        {
-               static string name_last;
                string name = wep.mdl;
                string newname = wep.wr_viewmodel(wep, this);
                if(newname)
                        name = newname;
-               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;
@@ -358,9 +359,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);
@@ -373,65 +374,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)
-               {
-                       n += 1;
-                       continue;
-               }
-               if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+               vector pos = view_origin;
+               vector dir = view_forward;
+               if (wepent.angles_held_status)
                {
-                       n = max(2, idx);
-                       break;
+                       makevectors(wepent.angles_held);
+                       dir = v_forward;
                }
-               // 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);
        }
 }
 
@@ -453,10 +459,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)
@@ -623,7 +636,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;
@@ -636,7 +649,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
@@ -719,7 +732,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;
@@ -811,9 +823,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)
@@ -977,8 +998,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;
@@ -1000,7 +1022,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)
@@ -1145,10 +1168,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);
@@ -1158,9 +1177,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;
@@ -1180,27 +1200,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);
@@ -1210,12 +1223,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 +
@@ -1704,7 +1717,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);
@@ -1782,39 +1796,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
@@ -1942,7 +1953,23 @@ 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 != "")
+                               {
+                                       reticle_image = wep.w_reticle;
+                                       break; // we can only draw 1 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
@@ -1952,7 +1979,7 @@ 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; }
                        else { reticle_type = 0; }
index f8c8bd26b65e20203bcdf36d08869345bb516951..01d4546374d40dcea83ae807eee7d1064a785bae 100644 (file)
@@ -1,3 +1,5 @@
 #pragma once
 
 vector crosshair_getcolor(entity this, float health_stat);
+
+entity viewmodels[MAX_WEAPONSLOTS];
index 988413f7a9593f9e17efc9a51ad354ac823c71f4..56681b099e756f6075da949446ca5dd605c7f102 100644 (file)
@@ -5,6 +5,7 @@ noref float autocvar_net_connecttimeout = 30;
 #include "animdecide.qc"
 #include "ent_cs.qc"
 #include "net_notice.qc"
+#include "wepent.qc"
 #endif
 
 #include "mapinfo.qc"
index 90edfa6185ac02c18f24faa61136a7b2a05abb7d..0ac07a19aa1e86e7e7b8682c5ff33687892b00b7 100644 (file)
@@ -11,3 +11,4 @@
 #include <common/t_items.qc>
 #include <common/util.qc>
 #include <common/viewloc.qc>
+#include <common/wepent.qc>
index d67ce5ff070ed640bfa70c342907e803616951ec..a9bd737ca0066caff3db25d142ae2b4afa4e9a9e 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 ab644988aa4d1192e60fde95bb97f28da642c0d3..8e086a085c62218ba68ee20cc7107f933f9da320 100644 (file)
@@ -15,7 +15,7 @@ const int MONSTER_TYPE_PASSIVE = BIT(14); // doesn't target or chase enemies
 const int MONSTER_TYPE_UNDEAD = BIT(15); // monster is by most definitions a zombie (doesn't fully die unless gibbed)
 
 // 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 748f9a9bd639130f695a0d5f936c93492f016d32..39f4982309785be35ee8f68a3dc83f1458f7de18 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 aae268666f1e72d501150f8e0fff59fa9c786272..6baa4534754e499164665095255cc8a580256104 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 a122865321f0a5a69897245c38f69b9df00a4b11..8c90ade8a4c0f3c41bd1fd46edebce68667c0285 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 cd53ff26f75aa2d483de2e55730fd56cce824962..92a098abf2d0c2040522c88f8b6b8e3e620b1bb1 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 8bbb300c76b6fc12cfae5ee55309c242d75a8115..d9f866e9d145f205b74f8041a581c1d054250fc2 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 b8c3bab21e77240e82dcef113826ab1b5b96c751..a89e55b1ce0b6644ddde27b59bacb7b30dbefa03 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 fdb0dc38d1ee24161bfe30e83ca172c23d065f63..dfde6ed73b163be7c5bc3c30027d87b47f206793 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 45037186d01c230777694969e04c9b8603a2957f..a5d3490a459186e0ff8fa71d9e57905dad91354d 100644 (file)
@@ -843,8 +843,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)
@@ -871,9 +877,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)
@@ -883,8 +897,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 c09e221e469ec96b7e912b3bc0491dd372cc68e7..7f2bed6973aafcdd50327c74e9a5d8b6b266267a 100644 (file)
@@ -738,7 +738,7 @@ void nade_boom(entity this)
 
        IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this,
        {
-               RemoveGrapplingHook(it.realowner);
+               RemoveHook(it);
        });
 
        delete(this);
@@ -787,7 +787,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;
@@ -893,7 +893,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);
 
@@ -1036,6 +1036,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;
@@ -1050,10 +1052,10 @@ 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;
        n.nade_lifetime = ntime;
 
        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;
@@ -1061,6 +1063,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 76e735e5505b482a34df8cd32d09847a6a21b58b..fb995a10a44543d730a57c02aff14993bedf2c4f 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 024fdb1cc768397f28409097e9f2e5166fa57b0a..caf96a67b3fc7e11a7dad4b8a01d2587908e4eee 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 ad2ee3f02994ca9e8098e794fcb7fa0d6c036f5c..745b87f85349714f4ffe81241ebcbb50a9d920e4 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 56bc8d14cce8d4fad53d010fd57ecea83fa17e1d..9bc39781bace277a70743819d32dda4440b089ac 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_armormega;
 
-.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); }
@@ -319,15 +252,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 bc3887e860f8dd50a76f2ea5a4f61fd866020046..ff942db310e4fbf434c725343e091cdab24b39f9 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 6e6dd9fb01b3e44530ca1bc58cdce987d979d426..1723584889fb1ce5619ec097a35b9e6ecbf68397 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 1a2fb1e7bfb171bb0405c1f8a02f83f09bde43dd..a9bc3e5e3cf8aa379ead84d3cc37163b70e46df1 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 94b9bc325f26288ebe8ccc8ff8cf67756366c334..850e7ac9db6b67cd77650cd005ae4729a4148ce5 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 b3459a67b9e5dcacfc4a33c0ce03b6a0fd47f1fb..995923a5ee943e3b746a629a37531cadd262b999 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);
 float gameover;
 #endif
@@ -115,8 +109,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 19aa6ba54aa3136348469a5cf5912a0a077849a3..f799ec6dbd1d6b33d220159bc0bbd4cf7342e035 100644 (file)
@@ -673,21 +673,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);
@@ -710,7 +719,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);
                                }
                        });
@@ -761,13 +775,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;
 }
@@ -1648,7 +1674,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;
@@ -1656,10 +1681,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);
@@ -1825,10 +1858,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 065d8c932ac1ffdd04c2cf0b1054cf231877b6d4..354ed1bfedd61f284ad76ae0f0fa73107b34abda 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 c3de654609ff5e0db36ad1bf01e4b314b3283023..1fabc80a571514315c7c3469437741e8e03dbe6b 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 44c8d645990152caf90e8b7b67e70e79e559f089..c60cd3b37e11ff245e3877dd76c638585079ce3c 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 d161436ab0807041b4bff31e65205cea02a15264..ed7d4f16088636f71bce125bda130dea77be921a 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 9e6d80b2fd830f165117630e685779d19afb82ca..b1e7d5850aa08416e77ed650418234dc4eace550 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 88b18b9198385bb8b5027fc2139c61750f0680eb..9bcf902902f2b43f07efe0cba526d08b086f3a64 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 b165bb3e481551b5cf5261390832e2a50b55b764..491962b67a5f74d14f193375de0cc4c49c7022e9 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 95cc74802ceab386bc8611a277e9c9f3bd4eec04..eb976aa8bc7e0792138c8da10112abc63857b4fc 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 80c28a8ab9ac7eab11f3f0fbd29053ad072864c3..4480ec658fc756466ffc202a520f93a95ef03984 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 d20210c6118434d1c83dffc44729c65080bf4a4e..838f0cf42773b81469326c48d17dfe88e32c9268 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 7c433f9c76f69dce59cbdba280418880c8210fe1..5dbd4f4ccb8adc8726f6022949e83348d1fe3305 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 4e16efbcc903df3227c1dc30ae419ef7e4f45731..5cb0f271c52fec0effb514dff201983fa2069c02 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 6ad46946d70927728dd7447d96d8314a907cc5f9..60a56944ab19b05678b0b6c28ea110cf001066ed 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 763dd6e8de83646cefda1786d8f6b51d3ce1dbaf..c236bb47c4d3ef361bc5ac9705e88a78483d1933 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 a805ce5fd4210a014b938bcf41c7cf46df4ad034..22d0e294eb1df06fadf46de4a9558bb7e7592345 100644 (file)
@@ -328,13 +328,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 c35b1930c44672995718ab746454da9aabfcd243..367bab6afb26c5aba16179d96fae28096b765827 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 c349eeca4f355a3b8b55ee588e65cfaf5471739e..d749cc15eea53f9d89595941ce82c58e1de0538e 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 b287b148f3175727cebf8fa1e44a288099ae8e2b..c873f4463302337faf73b3e29ddbba2471b9bf15 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,19 +114,19 @@ 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 view model */
     METHOD(Weapon, wr_viewmodel, string(Weapon this, entity wep)) { return string_null; }
     /** (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 4c9415305ab64b5fa68b765df55ca547ed734c3f..88ba1c768c63cacf23e4ac0524f8dbb181ea13e6 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 2eb8f00b4179c72cd91727168bbee9f7719c93d4..cc2fedccfe84e21be7ccedc038aa9e12985eba1f 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 58214bf390feed3d2f41e1ec5ec24c847b02c10f..e4d66ebe603a7598f2ef3151a750537e8b5fef57 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 7e63e760ec96d4d879a6813e6e436232aef965f2..a6473b39274c552dc2520dc218b08cfb42fcbc91 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 319f0d1d701ca936491e65d271e248ebedaf8202..46e46c24059660e8fd3b30b7ffe37da13d704d9d 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 ae1e48bb2c3e7f511af59d27ba3235a2434f07f5..dff721aa1a540e194b70a016d6785fcc5d07f5f2 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 684ee75d377540a15de2911269dbf6ccf078d982..eff656a6e1dce2ae5f271c4de27c454a6a654dc7 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 79bf08193ec05b9b38e3fa1ac1be46ca102043f3..010ca4fe8e18183e7c7f970f311844df3eb790e0 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 f5dd96e4c3c6b22ebf31c95f09a09f3b3e7fa03c..ff815d4619115869dff624b175e2f066a2c6b2fe 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 81da28ddb05b3741fa0d68f180829f8b49380130..7344ba9d0da4e220f66b01d2a602029fce4adff9 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 7df6984baabb4b584570b7b7b39a958efae4c33f..00f729b113e14f7bf87dc02eb1e006c1dc7a2f65 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 89ff5bbd8852eef69e0c497a679da28c5bde1293..56338da17182d72edbc50b1887e3fbb968786e8b 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 3e4654fcbbcc41171454192188a8e1ef9f72f393..8c5ade911cd9787f4340fbc3b1bf136d9506411d 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 478a3152536945aedae9ccbd9a53c369e52b8065..37d8e0e23a22eee23405f8664fb4f2a73f4f2b00 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 0e73adf2d3bd23da383640b9b6f875851ddeb150..20f5995e547c06c66a407f8267b03b149cfe17cd 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 28cbe69bbe5a1a04a7a52f400127070ff5d49732..823aac11c1d223a35ab068280503eb628194aa7b 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 9ae0c6069ab7b748b8f63a8c4c147891533ec8cf..f6d730fcb1f9dffc28331e6d17e718558f190779 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 e3e1f5228dc0d0839efeb1a4f9015f8d04f38ce1..09d050833b46de6323e9cf880cce3c80b2b2cd44 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 e11e4d8d5211aacc6e6d6e483afd0fe0ac45ea88..7866f1b828e27d55312b3952c0b164a837b01e11 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 bf3ce8185f2f33168e3da300b5722447151d14c3..b3ba65c5056eba74be4d85dcde6874eff9e2a885 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)
         {
             if(actor.vortex_chargepool_pauseregen_finished < time)
-                actor.vortex_chargepool_ammo = min(1, actor.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
+                actor.(weaponentity).vortex_chargepool_ammo = min(1, actor.(weaponentity).vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
             actor.pauseregen_finished = max(actor.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen));
         }
 
-    if(autocvar_g_balance_vortex_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
+    if(weaponslot(weaponentity) == 0)
+        actor.vortex_chargepool_ammo = actor.(weaponentity).vortex_chargepool_ammo;
+
+    if(autocvar_g_balance_vortex_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
     } else
     {
@@ -252,10 +267,10 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         {
             if(WEP_CVAR(vortex, charge))
             {
-                actor.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
+                actor.(weaponentity).vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
                 float dt = frametime / W_TICSPERFRAME;
 
-                if(actor.vortex_charge < 1)
+                if(actor.(weaponentity).vortex_charge < 1)
                 {
                     if(WEP_CVAR_SEC(vortex, chargepool))
                     {
@@ -264,12 +279,12 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
                             // always deplete if secondary is held
                             actor.vortex_chargepool_ammo = max(0, actor.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt);
 
-                            dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+                            dt = min(dt, (1 - actor.(weaponentity).vortex_charge) / WEP_CVAR(vortex, charge_rate));
                             actor.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen);
                             dt = min(dt, actor.vortex_chargepool_ammo);
                             dt = max(0, dt);
 
-                            actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+                            actor.(weaponentity).vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
                         }
                     }
 
@@ -277,19 +292,19 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
                     {
                         if(fire & 2) // only eat ammo when the button is pressed
                         {
-                            dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
+                            dt = min(dt, (1 - actor.(weaponentity).vortex_charge) / WEP_CVAR(vortex, charge_rate));
                             if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                             {
                                 // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
                                 if(autocvar_g_balance_vortex_reload_ammo)
                                 {
-                                    dt = min(dt, (actor.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
+                                    dt = min(dt, (actor.(weaponentity).clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
                                     dt = max(0, dt);
                                     if(dt > 0)
                                     {
-                                        actor.clip_load = max(WEP_CVAR_SEC(vortex, ammo), actor.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
+                                        actor.(weaponentity).clip_load = max(WEP_CVAR_SEC(vortex, ammo), actor.(weaponentity).clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
                                     }
-                                    actor.(weapon_load[WEP_VORTEX.m_id]) = actor.clip_load;
+                                    actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) = actor.(weaponentity).clip_load;
                                 }
                                 else
                                 {
@@ -301,14 +316,14 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
                                     }
                                 }
                             }
-                            actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+                            actor.(weaponentity).vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
                         }
                     }
 
                     else
                     {
-                        dt = min(dt, (1 - actor.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-                        actor.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
+                        dt = min(dt, (1 - actor.(weaponentity).vortex_charge) / WEP_CVAR(vortex, charge_rate));
+                        actor.(weaponentity).vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
                     }
                 }
             }
@@ -323,23 +338,23 @@ METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity
         }
     }
 }
-METHOD(Vortex, wr_setup, void(entity thiswep, entity actor))
+METHOD(Vortex, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
 {
     actor.vortex_lasthit = 0;
 }
-METHOD(Vortex, wr_checkammo1, bool(entity thiswep, entity actor))
+METHOD(Vortex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(vortex, ammo);
-    ammo_amount += (autocvar_g_balance_vortex_reload_ammo && actor.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
+    ammo_amount += (autocvar_g_balance_vortex_reload_ammo && actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_PRI(vortex, ammo));
     return ammo_amount;
 }
-METHOD(Vortex, wr_checkammo2, bool(entity thiswep, entity actor))
+METHOD(Vortex, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
     if(WEP_CVAR(vortex, secondary))
     {
         // don't allow charging if we don't have enough ammo
         float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(vortex, ammo);
-        ammo_amount += actor.(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_VORTEX.m_id]) >= WEP_CVAR_SEC(vortex, ammo);
         return ammo_amount;
     }
     else
@@ -354,6 +369,14 @@ METHOD(Vortex, wr_resetplayer, void(entity thiswep, entity actor))
             actor.vortex_chargepool_ammo = 1;
         }
         actor.vortex_charge = WEP_CVAR(vortex, charge_start);
+        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+        {
+            .entity weaponentity = weaponentities[slot];
+            actor.(weaponentity).vortex_charge = WEP_CVAR(vortex, charge_start);
+
+            if (WEP_CVAR_SEC(vortex, chargepool))
+                actor.(weaponentity).vortex_chargepool_ammo = 1;
+        }
     }
     actor.vortex_lasthit = 0;
 }
@@ -369,6 +392,10 @@ METHOD(Vortex, wr_killmessage, Notification(entity thiswep))
 {
     return WEAPON_VORTEX_MURDER;
 }
+METHOD(Vortex, wr_zoom, bool(entity thiswep, entity actor))
+{
+    return PHYS_INPUT_BUTTON_ATCK2(actor) && !WEP_CVAR(vortex, secondary);
+}
 
 #endif
 #ifdef CSQC
@@ -388,11 +415,10 @@ METHOD(Vortex, wr_init, void(entity thiswep))
         precache_pic("gfx/reticle_nex");
     }
 }
-METHOD(Vortex, wr_zoomreticle, bool(entity thiswep))
+METHOD(Vortex, wr_zoom, bool(entity thiswep, entity actor))
 {
     if(button_zoom || zoomscript_caught || (!WEP_CVAR(vortex, secondary) && button_attack2))
     {
-        reticle_image = "gfx/reticle_nex";
         return true;
     }
     else
diff --git a/qcsrc/common/wepent.qc b/qcsrc/common/wepent.qc
new file mode 100644 (file)
index 0000000..e244e7b
--- /dev/null
@@ -0,0 +1,168 @@
+#include "wepent.qh"
+
+#define WEPENT_SET_NORMAL(var, x) MACRO_BEGIN \
+       var = x; \
+MACRO_END
+
+// #define PROP(public, fld, set, sv, cl)
+#define WEPENT_NETPROPS(PROP) PROP(false, sv_entnum, WEPENT_SET_NORMAL, {}, {}) /* sentinel */ \
+       PROP(false, m_switchweapon, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_switchweapon.m_id); }, \
+       { (viewmodels[this.m_wepent_slot]).switchweapon = Weapons_from(ReadByte()); }) \
+    \
+    PROP(false, m_switchingweapon, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_switchingweapon.m_id); }, \
+       { (viewmodels[this.m_wepent_slot]).switchingweapon = Weapons_from(ReadByte()); }) \
+    \
+    PROP(false, m_weapon, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_weapon.m_id); }, \
+       { (viewmodels[this.m_wepent_slot]).activeweapon = Weapons_from(ReadByte()); }) \
+    \
+    PROP(false, m_alpha, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_alpha * 16); }, \
+       { (viewmodels[this.m_wepent_slot]).alpha = ReadByte() / 16; }) \
+    \
+    PROP(false, vortex_charge, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.vortex_charge * 16); }, \
+       { (viewmodels[this.m_wepent_slot]).vortex_charge = ReadByte() / 16; }) \
+    \
+    PROP(false, m_gunalign, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.m_gunalign); }, \
+       { (viewmodels[this.m_wepent_slot]).m_gunalign = ReadByte(); }) \
+    \
+    PROP(false, porto_v_angle_held, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.porto_v_angle_held); if(this.porto_v_angle_held) { \
+                WriteAngle(chan, this.porto_v_angle.x); WriteAngle(chan, this.porto_v_angle.y); \
+               } }, \
+       { (viewmodels[this.m_wepent_slot]).angles_held_status = ReadByte(); if((viewmodels[this.m_wepent_slot]).angles_held_status) { \
+               (viewmodels[this.m_wepent_slot]).angles_held_x = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_y = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_z = 0; } \
+               else { (viewmodels[this.m_wepent_slot]).angles_held = '0 0 0'; } }) \
+    \
+    PROP(false, tuba_instrument, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.tuba_instrument); }, \
+       { (viewmodels[this.m_wepent_slot]).tuba_instrument = ReadByte(); }) \
+    \
+       /**/
+
+#ifdef SVQC
+
+       int WEPENT_PUBLICMASK = 0;
+       STATIC_INIT(WEPENT_PUBLICMASK)
+       {
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (public) { \
+                               WEPENT_PUBLICMASK |= BIT(i); \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+               if (i >= BITS(16 - 1)) LOG_FATAL("Exceeded WEPENT_NETPROPS limit");
+       }
+
+       bool _wepent_send(entity this, entity to, int sf, int chan)
+       {
+               sf |= this.m_forceupdate;
+               this.m_forceupdate = 0;
+               if (chan == MSG_ENTITY)
+                       WriteHeader(chan, ENT_CLIENT_WEPENT);
+               else
+                       WriteHeader(chan, CLIENT_WEPENT);
+               .entity weaponentity = this.owner.weaponentity_fld;
+               WriteByte(chan, weaponslot(weaponentity));
+               WriteShort(chan, sf);
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (sf & BIT(i)) { \
+                               sv; \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+               return true;
+       }
+
+       bool wepent_send(entity this, entity to, int sf)
+       {
+               return _wepent_send(this, to, sf, MSG_ENTITY);
+       }
+
+       void wepent_think(entity this)
+       {
+               if(wasfreed(this.owner) || !this.owner)
+               {
+                       delete(this);
+                       return;
+               }
+
+               this.nextthink = time;
+
+               entity o = this.owner;
+
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (this.fld != o.fld) { \
+                               set(this.fld, o.fld); \
+                               this.SendFlags |= BIT(i); \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+       }
+
+       bool wepent_customize(entity this, entity client)
+       {
+               //entity e = WaypointSprite_getviewentity(client);
+               .entity weaponentity = this.owner.weaponentity_fld;
+               return client.(weaponentity) == this.owner;
+       }
+
+       void wepent_link(entity wep)
+       {
+               entity e = new(wepent_sender);
+               e.owner = wep;
+               setthink(e, wepent_think);
+               e.nextthink = time;
+               //e.drawonlytoclient = wep.owner;
+               setcefc(e, wepent_customize);
+               Net_LinkEntity(e, false, 0, wepent_send);
+       }
+
+#endif
+
+#ifdef CSQC
+
+       bool ReadWepent(entity this)
+       {
+               int slot = ReadByte();
+               this.m_wepent_slot = slot;
+               viewmodels[slot].m_wepent_slot = slot;
+               int sf = ReadShort();
+               int i = 0;
+               #define X(public, fld, set, sv, cl) { \
+                       if (sf & BIT(i)) { \
+                               cl; \
+                       } \
+                       i += 1; \
+               }
+               WEPENT_NETPROPS(X);
+       #undef X
+               return true;
+       }
+
+       NET_HANDLE(ENT_CLIENT_WEPENT, bool isnew)
+       {
+               if (isnew)
+                       this.classname = "wepent_receiver";
+               return ReadWepent(this);
+       }
+
+       NET_HANDLE(CLIENT_WEPENT, bool isnew)
+       {
+               return ReadWepent(NULL);
+       }
+
+#endif
diff --git a/qcsrc/common/wepent.qh b/qcsrc/common/wepent.qh
new file mode 100644 (file)
index 0000000..46180d7
--- /dev/null
@@ -0,0 +1,33 @@
+#pragma once
+
+REGISTER_NET_LINKED(ENT_CLIENT_WEPENT)
+REGISTER_NET_TEMP(CLIENT_WEPENT)
+
+.float vortex_charge;
+.int tuba_instrument;
+
+#ifdef SVQC
+
+       bool wepent_send(entity this, entity to, int sf);
+
+       void wepent_link(entity wep);
+
+       .int m_forceupdate;
+
+       .Weapon m_switchweapon;
+       .Weapon m_weapon;
+       .Weapon m_switchingweapon;
+
+#endif
+
+#ifdef CSQC
+       .int m_wepent_slot;
+
+       .Weapon activeweapon;
+       .Weapon switchingweapon;
+       .Weapon switchweapon;
+
+       // only for Porto
+       .bool angles_held_status;
+       .vector angles_held;
+#endif
index dbe3197a7c97c0a6cbbe2e7e108281a4444adb5f..97104ef3765908f46d29ad59368f325e3781d759 100644 (file)
@@ -46,7 +46,7 @@ float skill;
 .float wpcost;
 .int wpflags;
 
-bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, float applygravity);
+bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity);
 void bot_clientconnect(entity this);
 void bot_clientdisconnect(entity this);
 void bot_cmdhelp(string scmd);
index 1624676b82ca032b0a7d8d4c65589a1a8d2934bc..c278be915a2278a3eabd89966c990cf6ad44c75e 100644 (file)
@@ -323,7 +323,7 @@ vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, flo
        return targorigin + targvelocity * (shotdelay + vlen(targorigin - shotorg) / shotspeed);
 }
 
-bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity)
+bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity)
 {
        float f, r, hf, distanceratio;
        vector v;
@@ -343,12 +343,12 @@ bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshott
        shotspeedupward *= W_WeaponSpeedFactor(this);
        if (!shotspeed)
        {
-               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " shotspeed is zero!");
+               LOG_TRACE("bot_aim: WARNING: weapon ", this.(weaponentity).m_weapon.m_name, " shotspeed is zero!");
                shotspeed = 1000000;
        }
        if (!maxshottime)
        {
-               LOG_TRACE("bot_aim: WARNING: weapon ", PS(this).m_weapon.m_name, " maxshottime is zero!");
+               LOG_TRACE("bot_aim: WARNING: weapon ", this.(weaponentity).m_weapon.m_name, " maxshottime is zero!");
                maxshottime = 1;
        }
        makevectors(this.v_angle);
index dfe10e265688a8db44aa7c794ed76eb68bd69bd4..e7c60758aec2eca3c46fe3c588a8cce4e635551e 100644 (file)
@@ -91,7 +91,7 @@ void bot_lagfunc(entity this, float t, float f1, float f2, entity e1, vector v1,
 
 float bot_shouldattack(entity this, entity targ);
 float bot_aimdir(entity this, vector v, float maxfiredeviation);
-bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity);
+bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, bool applygravity);
 float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, float shotspeed, float shotspeedupward, float maxtime, float shotdelay, entity ignore);
 
 vector bot_shotlead(vector targorigin, vector targvelocity, float shotspeed, float shotdelay);
index b23c15bcafdeccbfb0b4874f0d8cfe77f18c5aaa..0047a26283ba485710c5cb3630fc4af7b16a20da 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/physics/player.qh>
 #include <common/state.qh>
 #include <common/items/_mod.qh>
+#include <common/wepent.qh>
 
 #include <common/triggers/teleporters.qh>
 #include <common/triggers/trigger/jumppads.qh>
@@ -92,10 +93,16 @@ void havocbot_ai(entity this)
                return;
 
        havocbot_chooseenemy(this);
-       if (this.bot_chooseweapontime < time )
+
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
-               this.bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
-               havocbot_chooseweapon(this);
+               .entity weaponentity = weaponentities[slot];
+               if(this.(weaponentity).m_weapon != WEP_Null || slot == 0)
+               if(this.(weaponentity).bot_chooseweapontime < time)
+               {
+                       this.(weaponentity).bot_chooseweapontime = time + autocvar_bot_ai_chooseweaponinterval;
+                       havocbot_chooseweapon(this, weaponentity);
+               }
        }
        havocbot_aim(this);
        lag_update(this);
@@ -106,8 +113,6 @@ void havocbot_ai(entity this)
 
                if(this.weapons)
                {
-                       Weapon w = PS(this).m_weapon;
-                       w.wr_aim(w, this);
                        if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(this))
                        {
                                PHYS_INPUT_BUTTON_ATCK(this) = false;
@@ -115,8 +120,16 @@ void havocbot_ai(entity this)
                        }
                        else
                        {
-                               if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this))
-                                       this.lastfiredweapon = PS(this).m_weapon.m_id;
+                               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                               {
+                                       .entity weaponentity = weaponentities[slot];
+                                       Weapon w = this.(weaponentity).m_weapon;
+                                       if(w == WEP_Null && slot != 0)
+                                               continue;
+                                       w.wr_aim(w, this, weaponentity);
+                                       if(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) // TODO: what if we didn't fire this weapon, but the previous?
+                                               this.(weaponentity).lastfiredweapon = this.(weaponentity).m_weapon.m_id;
+                               }
                        }
                }
                else
@@ -163,20 +176,28 @@ void havocbot_ai(entity this)
        // if the bot is not attacking, consider reloading weapons
        if (!(this.aistatus & AI_STATUS_ATTACKING))
        {
-               // we are currently holding a weapon that's not fully loaded, reload it
-               if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
-               if(this.clip_load < this.clip_size)
-                       this.impulse = 20; // "press" the reload button, not sure if this is done right
-
-               // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
-               // the code above executes next frame, starting the reloading then
-               if(skill >= 5) // bots can only look for unloaded weapons past this skill
-               if(this.clip_load >= 0) // only if we're not reloading a weapon already
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
-                       FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                               if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.weapon_load[it.m_id] < it.reloading_ammo))
-                                       PS(this).m_switchweapon = it;
-                       ));
+                       .entity weaponentity = weaponentities[slot];
+
+                       if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+                               continue;
+
+                       // we are currently holding a weapon that's not fully loaded, reload it
+                       if(skill >= 2) // bots can only reload the held weapon on purpose past this skill
+                       if(this.(weaponentity).clip_load < this.(weaponentity).clip_size)
+                               this.impulse = 20; // "press" the reload button, not sure if this is done right
+
+                       // if we're not reloading a weapon, switch to any weapon in our invnetory that's not fully loaded to reload it next
+                       // the code above executes next frame, starting the reloading then
+                       if(skill >= 5) // bots can only look for unloaded weapons past this skill
+                       if(this.(weaponentity).clip_load >= 0) // only if we're not reloading a weapon already
+                       {
+                               FOREACH(Weapons, it != WEP_Null, LAMBDA(
+                                       if((this.weapons & (it.m_wepset)) && (it.spawnflags & WEP_FLAG_RELOADABLE) && (this.(weaponentity).weapon_load[it.m_id] < it.reloading_ammo))
+                                               this.(weaponentity).m_switchweapon = it;
+                               ));
+                       }
                }
        }
 }
@@ -592,25 +613,35 @@ void havocbot_movetogoal(entity this)
                else if(this.health>WEP_CVAR(devastator, damage)*0.5)
                {
                        if(this.velocity.z < 0)
-                       if(client_hasweapon(this, WEP_DEVASTATOR, true, false))
                        {
-                               this.movement_x = maxspeed;
-
-                               if(this.rocketjumptime)
+                               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                                {
-                                       if(time > this.rocketjumptime)
+                                       .entity weaponentity = weaponentities[slot];
+
+                                       if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+                                               continue;
+
+                                       if(client_hasweapon(this, WEP_DEVASTATOR, weaponentity, true, false))
                                        {
-                                               PHYS_INPUT_BUTTON_ATCK2(this) = true;
-                                               this.rocketjumptime = 0;
+                                               this.movement_x = maxspeed;
+
+                                               if(this.rocketjumptime)
+                                               {
+                                                       if(time > this.rocketjumptime)
+                                                       {
+                                                               PHYS_INPUT_BUTTON_ATCK2(this) = true;
+                                                               this.rocketjumptime = 0;
+                                                       }
+                                                       return;
+                                               }
+
+                                               this.(weaponentity).m_switchweapon = WEP_DEVASTATOR;
+                                               this.v_angle_x = 90;
+                                               PHYS_INPUT_BUTTON_ATCK(this) = true;
+                                               this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
+                                               return;
                                        }
-                                       return;
                                }
-
-                               PS(this).m_switchweapon = WEP_DEVASTATOR;
-                               this.v_angle_x = 90;
-                               PHYS_INPUT_BUTTON_ATCK(this) = true;
-                               this.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
-                               return;
                        }
                }
                else
@@ -981,7 +1012,7 @@ LABEL(scan_targets)
                this.havocbot_stickenemy = false;
 }
 
-float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
+float havocbot_chooseweapon_checkreload(entity this, .entity weaponentity, int new_weapon)
 {
        // bots under this skill cannot find unloaded weapons to reload idly when not in combat,
        // so skip this for them, or they'll never get to reload their weapons at all.
@@ -990,11 +1021,11 @@ float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
                return false;
 
        // if this weapon is scheduled for reloading, don't switch to it during combat
-       if (this.weapon_load[new_weapon] < 0)
+       if (this.(weaponentity).weapon_load[new_weapon] < 0)
        {
                bool other_weapon_available = false;
                FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                       if(it.wr_checkammo1(it, this) + it.wr_checkammo2(it, this))
+                       if(it.wr_checkammo1(it, this, weaponentity) + it.wr_checkammo2(it, this, weaponentity))
                                other_weapon_available = true;
                ));
                if(other_weapon_available)
@@ -1004,14 +1035,14 @@ float havocbot_chooseweapon_checkreload(entity this, int new_weapon)
        return false;
 }
 
-void havocbot_chooseweapon(entity this)
+void havocbot_chooseweapon(entity this, .entity weaponentity)
 {
        int i;
 
        // ;)
        if(g_weaponarena_weapons == WEPSET(TUBA))
        {
-               PS(this).m_switchweapon = WEP_TUBA;
+               this.(weaponentity).m_switchweapon = WEP_TUBA;
                return;
        }
 
@@ -1019,11 +1050,11 @@ void havocbot_chooseweapon(entity this)
        if(this.enemy==NULL)
        {
                // If no weapon was chosen get the first available weapon
-               if(PS(this).m_weapon==WEP_Null)
+               if(this.(weaponentity).m_weapon==WEP_Null)
                FOREACH(Weapons, it != WEP_Null, LAMBDA(
-                       if(client_hasweapon(this, it, true, false))
+                       if(client_hasweapon(this, it, weaponentity, true, false))
                        {
-                               PS(this).m_switchweapon = it;
+                               this.(weaponentity).m_switchweapon = it;
                                return;
                        }
                ));
@@ -1051,7 +1082,7 @@ void havocbot_chooseweapon(entity this)
        combo = false;
 
        if(autocvar_bot_ai_weapon_combo)
-       if(PS(this).m_weapon.m_id == this.lastfiredweapon)
+       if(this.(weaponentity).m_weapon.m_id == this.(weaponentity).lastfiredweapon)
        if(af > combo_time)
        {
                combo = true;
@@ -1067,11 +1098,11 @@ void havocbot_chooseweapon(entity this)
                if ( distance > bot_distance_far ) {
                        for(i=0; i < Weapons_COUNT && bot_weapons_far[i] != -1 ; ++i){
                                w = bot_weapons_far[i];
-                               if ( client_hasweapon(this, Weapons_from(w), true, false) )
+                               if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
                                {
-                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                       if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
                                                continue;
-                                       PS(this).m_switchweapon = Weapons_from(w);
+                                       this.(weaponentity).m_switchweapon = Weapons_from(w);
                                        return;
                                }
                        }
@@ -1081,11 +1112,11 @@ void havocbot_chooseweapon(entity this)
                if ( distance > bot_distance_close) {
                        for(i=0; i < Weapons_COUNT && bot_weapons_mid[i] != -1 ; ++i){
                                w = bot_weapons_mid[i];
-                               if ( client_hasweapon(this, Weapons_from(w), true, false) )
+                               if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
                                {
-                                       if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                                       if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
                                                continue;
-                                       PS(this).m_switchweapon = Weapons_from(w);
+                                       this.(weaponentity).m_switchweapon = Weapons_from(w);
                                        return;
                                }
                        }
@@ -1094,11 +1125,11 @@ void havocbot_chooseweapon(entity this)
                // Choose weapons for close distance
                for(i=0; i < Weapons_COUNT && bot_weapons_close[i] != -1 ; ++i){
                        w = bot_weapons_close[i];
-                       if ( client_hasweapon(this, Weapons_from(w), true, false) )
+                       if ( client_hasweapon(this, Weapons_from(w), weaponentity, true, false) )
                        {
-                               if ((PS(this).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, w))
+                               if ((this.(weaponentity).m_weapon.m_id == w && combo) || havocbot_chooseweapon_checkreload(this, weaponentity, w))
                                        continue;
-                               PS(this).m_switchweapon = Weapons_from(w);
+                               this.(weaponentity).m_switchweapon = Weapons_from(w);
                                return;
                        }
                }
index 4a391b6e7ceb9682a2df64023aa98751e88974d1..8ab4cba6e973309029860712ab799f87fd245ff5 100644 (file)
@@ -39,7 +39,7 @@ void havocbot_setupbot(entity this);
 void havocbot_movetogoal(entity this);
 void havocbot_chooserole(entity this);
 void havocbot_chooseenemy(entity this);
-void havocbot_chooseweapon(entity this);
+void havocbot_chooseweapon(entity this, .entity weaponentity);
 void havocbot_bunnyhop(entity this, vector dir);
 void havocbot_keyboard_movement(entity this, vector destorg);
 
index 0d34ae3c24bc973d285c3ab07a0ab7713afbdac5..f975f74e56743ec7472ff04c8488e8f890fe7888 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <common/state.qh>
 #include <common/physics/player.qh>
+#include <common/wepent.qh>
 
 #include "bot.qh"
 
@@ -569,9 +570,22 @@ float bot_cmd_select_weapon(entity this)
        if(id < WEP_FIRST || id > WEP_LAST)
                return CMD_STATUS_ERROR;
 
-       if(client_hasweapon(this, Weapons_from(id), true, false))
-               PS(this).m_switchweapon = Weapons_from(id);
-       else
+       bool success = false;
+
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
+                       continue;
+
+               if(client_hasweapon(this, Weapons_from(id), weaponentity, true, false))
+               {
+                       success = true;
+                       this.(weaponentity).m_switchweapon = Weapons_from(id);
+               }
+       }
+
+       if(!success)
                return CMD_STATUS_ERROR;
 
        return CMD_STATUS_FINISHED;
@@ -1056,7 +1070,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(f)
                {
                        this.colormod = '0 8 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by weaponentity state\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by weaponentity state\n");
                }
        }
        else if(ATTACK_FINISHED(this, slot) > time)
@@ -1064,15 +1078,15 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(f)
                {
                        this.colormod = '8 0 8';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, inhibited by ATTACK_FINISHED (", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left)\n");
                }
        }
-       else if(this.tuba_note)
+       else if(this.(weaponentity).tuba_note)
        {
                if(f)
                {
                        this.colormod = '8 0 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " wants to fire, bot still has an active tuba note\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " wants to fire, bot still has an active tuba note\n");
                }
        }
        else
@@ -1080,7 +1094,7 @@ float bot_cmd_debug_assert_canfire(entity this)
                if(!f)
                {
                        this.colormod = '8 8 0';
-                       LOG_INFO("Bot ", this.netname, " using ", this.weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n");
+                       LOG_INFO("Bot ", this.netname, " using ", this.(weaponentity).weaponname, " thinks it has fired, but apparently did not; ATTACK_FINISHED says ", ftos(ATTACK_FINISHED(this, slot) - time), " seconds left\n");
                }
        }
 
index b4102cb6c09a20178f8549f1051da6afa71f5f45..68ae41670644dd1e241752f946ba0d5aeb071c54 100644 (file)
@@ -1,7 +1,7 @@
 #include "bot_null.qh"
 
 #if 0
-bool bot_aim(entity this, float shotspeed, float shotspeedupward, float maxshottime, float applygravity) { return false; }
+bool bot_aim(entity this, .entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity) { return false; }
 void bot_clientconnect(entity this) { }
 void bot_clientdisconnect(entity this) { }
 void bot_cmdhelp(string scmd) { }
index 9583118ceacae67335fc8ff8612e17d3b4bd97e5..f573a1d650ab32a3f8ddd967258f85b81b37e9a6 100644 (file)
@@ -23,6 +23,7 @@
 #include "bot/api.qh"
 
 #include "../common/ent_cs.qh"
+#include "../common/wepent.qh"
 #include <common/state.qh>
 
 #include <common/effects/qc/globalsound.qh>
@@ -112,7 +113,6 @@ bool ClientData_Send(entity this, entity to, int sf)
        if (e.race_completed)       sf |= 1; // forced scoreboard
        if (to.spectatee_status)    sf |= 2; // spectator ent number follows
        if (e.zoomstate)            sf |= 4; // zoomed
-       if (e.porto_v_angle_held)   sf |= 8; // angles held
        if (autocvar_sv_showspectators) sf |= 16; // show spectators
 
        WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
@@ -122,11 +122,6 @@ bool ClientData_Send(entity this, entity to, int sf)
        {
                WriteByte(MSG_ENTITY, to.spectatee_status);
        }
-       if (sf & 8)
-       {
-               WriteAngle(MSG_ENTITY, e.v_angle.x);
-               WriteAngle(MSG_ENTITY, e.v_angle.y);
-       }
 
        if(sf & 16)
        {
@@ -257,7 +252,7 @@ void PutObserverInServer(entity this)
         this.view_ofs = '0 0 0';
     }
 
-    RemoveGrapplingHook(this);
+    RemoveGrapplingHooks(this);
        Portal_ClearAll(this);
        Unfreeze(this);
        SetSpectatee(this, NULL);
@@ -336,7 +331,6 @@ void PutObserverInServer(entity this)
        this.istypefrag = 0;
        setthink(this, func_null);
        this.nextthink = 0;
-       this.hook_time = 0;
        this.deadflag = DEAD_NO;
        this.crouch = false;
        this.revive_progress = 0;
@@ -346,10 +340,13 @@ void PutObserverInServer(entity this)
        this.weapons = '0 0 0';
        this.drawonlytoclient = this;
 
-       this.weaponname = "";
        this.weaponmodel = "";
        for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
+               if(!this.weaponentities[slot])
+                       continue; // first load
+               this.weaponentities[slot].hook_time = 0;
+               this.weaponentities[slot].weaponname = "";
                this.weaponentities[slot] = NULL;
        }
        this.exteriorweaponentity = NULL;
@@ -361,10 +358,6 @@ void PutObserverInServer(entity this)
        this.oldvelocity = this.velocity;
        this.fire_endtime = -1;
        this.event_damage = func_null;
-
-       STAT(ACTIVEWEAPON, this) = WEP_Null.m_id;
-       STAT(SWITCHINGWEAPON, this) = WEP_Null.m_id;
-       STAT(SWITCHWEAPON, this) = WEP_Null.m_id;
 }
 
 int player_getspecies(entity this)
@@ -664,7 +657,8 @@ void PutClientInServer(entity this)
 
                for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
-                       CL_SpawnWeaponentity(this, weaponentities[slot]);
+                       .entity weaponentity = weaponentities[slot];
+                       CL_SpawnWeaponentity(this, weaponentity);
                }
                this.alpha = default_player_alpha;
                this.colormod = '1 1 1' * autocvar_g_player_brightness;
@@ -679,7 +673,11 @@ void PutClientInServer(entity this)
                        it.wr_resetplayer(it, this);
                        // reload all reloadable weapons
                        if (it.spawnflags & WEP_FLAG_RELOADABLE) {
-                               this.weapon_load[it.m_id] = it.reloading_ammo;
+                               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                               {
+                                       .entity weaponentity = weaponentities[slot];
+                                       this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo;
+                               }
                        }
                ));
 
@@ -700,11 +698,18 @@ void PutClientInServer(entity this)
                        delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
                }
 
-               PS(this).m_switchweapon = w_getbestweapon(this);
-               this.cnt = -1; // W_LastWeapon will not complain
-               PS(this).m_weapon = WEP_Null;
-               this.weaponname = "";
-               PS(this).m_switchingweapon = WEP_Null;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(slot == 0)
+                               this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+                       else
+                               this.(weaponentity).m_switchweapon = WEP_Null;
+                       this.(weaponentity).m_weapon = WEP_Null;
+                       this.(weaponentity).weaponname = "";
+                       this.(weaponentity).m_switchingweapon = WEP_Null;
+                       this.(weaponentity).cnt = -1;
+               }
 
                if (!warmup_stage && !this.alivetime)
                        this.alivetime = time;
@@ -1261,7 +1266,7 @@ void ClientDisconnect(entity this)
 
        Unfreeze(this);
 
-       RemoveGrapplingHook(this);
+       RemoveGrapplingHooks(this);
 
        // Here, everything has been done that requires this player to be a client.
 
@@ -1692,6 +1697,12 @@ void SpectateCopy(entity this, entity spectatee)
        setsize(this, spectatee.mins, spectatee.maxs);
        SetZoomState(this, spectatee.zoomstate);
 
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               this.(weaponentity) = spectatee.(weaponentity);
+       }
+
     anticheat_spectatecopy(this, spectatee);
        this.hud = spectatee.hud;
        if(spectatee.vehicle)
@@ -2441,13 +2452,17 @@ void PlayerPreThink (entity this)
                {
                        this.items &= ~this.items_added;
 
-                       //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-                       //{
-                               //.entity weaponentity = weaponentities[slot];
-                               //W_WeaponFrame(this, weaponentity);
-                       //}
-                       .entity weaponentity = weaponentities[0]; // TODO
-                       W_WeaponFrame(this, weaponentity);
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               W_WeaponFrame(this, weaponentity);
+
+                               if(slot == 0)
+                               {
+                                       this.clip_load = this.(weaponentity).clip_load;
+                                       this.clip_size = this.(weaponentity).clip_size;
+                               }
+                       }
 
                        this.items_added = 0;
                        if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
@@ -2460,8 +2475,12 @@ void PlayerPreThink (entity this)
 
                // WEAPONTODO: Add a weapon request for this
                // rot vortex charge to the charge limit
-               if (WEP_CVAR(vortex, charge_rot_rate) && this.vortex_charge > WEP_CVAR(vortex, charge_limit) && this.vortex_charge_rottime < time)
-                       this.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time)
+                               this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+               }
 
                if (frametime) player_anim(this);
 
@@ -2487,11 +2506,15 @@ void PlayerPreThink (entity this)
 
        // WEAPONTODO: Add weapon request for this
        if (!zoomstate_set) {
-               SetZoomState(this,
-                       PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this)
-                       || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_VORTEX)
-                       || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
-               );
+               bool wep_zoomed = false;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       Weapon thiswep = this.(weaponentity).m_weapon;
+                       if(thiswep != WEP_Null && thiswep.wr_zoom)
+                               wep_zoomed += thiswep.wr_zoom(thiswep, this);
+               }
+               SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed);
     }
 
        if (this.teamkill_soundtime && time > this.teamkill_soundtime)
@@ -2514,8 +2537,12 @@ void PlayerPreThink (entity this)
 
        // WEAPONTODO: Move into weaponsystem somehow
        // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
-       if (PS(this).m_weapon == WEP_Null)
-               this.clip_load = this.clip_size = 0;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               if(this.(weaponentity).m_weapon == WEP_Null)
+                       this.(weaponentity).clip_load = this.(weaponentity).clip_size = 0;
+       }
 }
 
 void DrownPlayer(entity this)
index fedd5eb1ab346354f6121da51fa247627a5de039..43e1eb59993aa93bc28f4a5275d8a527c9bbc400 100644 (file)
@@ -116,7 +116,7 @@ const float MAX_DAMAGEEXTRARADIUS = 16;
 
 // WEAPONTODO
 .float autoswitch;
-bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain);
+bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andammo, bool complain);
 void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire);
 void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
 // VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
@@ -208,7 +208,7 @@ float bot_waypoints_for_items;
 #else
 #define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).attack_finished_single[slot])
 #endif
-#define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, PS(ent).m_weapon.m_id, slot)
+#define ATTACK_FINISHED(ent, slot) ATTACK_FINISHED_FOR(ent, ent.(weaponentity).m_weapon.m_id, slot)
 
 // assault game mode: Which team is attacking in this round?
 float assault_attacker_team;
index a604a2bade1ef61b8ac45bb1eeac7d068ed3b406..ac19363cca71453481684233336c8bd6a3a35819 100644 (file)
@@ -58,13 +58,15 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 
        PlayerScore_Add(targ, SP_DEATHS, 1);
 
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
        if(targ != attacker) // not for suicides
        if(g_weaponarena_random)
        {
                // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
                Weapon culprit = DEATH_WEAPONOF(deathtype);
-               if(!culprit) culprit = PS(attacker).m_weapon;
-               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = PS(attacker).m_weapon;
+               if(!culprit) culprit = attacker.(weaponentity).m_weapon;
+               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = attacker.(weaponentity).m_weapon;
 
                if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
                {
@@ -97,8 +99,8 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
                }
 
                // after a frag, choose another random weapon set
-               if (!(attacker.weapons & WepSet_FromWeapon(PS(attacker).m_weapon)))
-                       W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
+               if (!(attacker.weapons & WepSet_FromWeapon(attacker.(weaponentity).m_weapon)))
+                       W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker, weaponentity), weaponentity);
        }
 
        // FIXME fix the mess this is (we have REAL points now!)
@@ -115,12 +117,15 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 
 string AppendItemcodes(string s, entity player)
 {
-       int w = PS(player).m_weapon.m_id;
-       //if(w == 0)
-       //      w = player.switchweapon;
-       if(w == 0)
-               w = player.cnt; // previous weapon!
-       s = strcat(s, ftos(w));
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               int w = player.(weaponentity).m_weapon.m_id;
+               if(w == 0)
+                       w = player.(weaponentity).cnt; // previous weapon
+               if(w != 0 || slot == 0)
+                       s = strcat(s, ftos(w));
+       }
        if(time < player.strength_finished)
                s = strcat(s, "S");
        if(time < player.invincible_finished)
@@ -556,9 +561,17 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
 
        Ice_Think(ice);
 
-       RemoveGrapplingHook(targ);
+       RemoveGrapplingHooks(targ);
 
-       FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == targ, LAMBDA(RemoveGrapplingHook(it)));
+       FOREACH_CLIENT(IS_PLAYER(it),
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           {
+               .entity weaponentity = weaponentities[slot];
+               if(it.(weaponentity).hook.aiment == targ)
+                       RemoveHook(it.(weaponentity).hook);
+           }
+       });
 
        // add waypoint
        if(show_waypoint)
@@ -585,7 +598,15 @@ void Unfreeze (entity targ)
 
        WaypointSprite_Kill(targ.waypointsprite_attached);
 
-       FOREACH_CLIENT(IS_PLAYER(it) && it.hook.aiment == targ, LAMBDA(RemoveGrapplingHook(it)));
+       FOREACH_CLIENT(IS_PLAYER(it),
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           {
+               .entity weaponentity = weaponentities[slot];
+               if(it.(weaponentity).hook.aiment == targ)
+                       RemoveHook(it.(weaponentity).hook);
+           }
+       });
 
        // remove the ice block
        if(targ.iceblock)
@@ -611,10 +632,14 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
        attacker_save = attacker;
 
        if(IS_PLAYER(targ))
-               if(targ.hook)
-                       if(targ.hook.aiment)
-                               if(targ.hook.aiment == attacker)
-                                       RemoveGrapplingHook(targ); // STOP THAT, you parasite!
+       {
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           {
+               .entity weaponentity = weaponentities[slot];
+               if(targ.(weaponentity).hook && targ.(weaponentity).hook.aiment == attacker)
+                       RemoveHook(targ.(weaponentity).hook);
+           }
+       }
 
        // special rule: gravity bomb does not hit team mates (other than for disconnecting the hook)
        if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || DEATH_ISWEAPON(deathtype, WEP_TUBA))
index 019c8fc9a8efc92bc5d280f2352d796acd99f574..9a4a8b95d759579f9f3902ffc9165c8246fcf987 100644 (file)
@@ -55,7 +55,7 @@ float IsFlying(entity a);
 void UpdateFrags(entity player, int f);
 
 // NOTE: f=0 means still count as a (positive) kill, but count no frags for it
-void W_SwitchWeapon_Force(Player this, Weapon w);
+void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
 entity GiveFrags_randomweapons;
 void GiveFrags (entity attacker, entity targ, float f, int deathtype);
 
index cccba42bb42128fff96050498f317875c050c360..a69b98487d2cbb7cb16833656178e4b369419faa 100644 (file)
@@ -71,24 +71,41 @@ And you should be done!
 
 .float hook_length;
 
-void RemoveGrapplingHook(entity pl)
+void RemoveGrapplingHooks(entity pl)
 {
-       if(pl.hook == NULL)
-               return;
-       delete(pl.hook);
-       pl.hook = NULL;
        if(pl.move_movetype == MOVETYPE_FLY)
                set_movetype(pl, MOVETYPE_WALK);
 
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       if(pl.(weaponentity).hook)
+       {
+               delete(pl.(weaponentity).hook);
+               pl.(weaponentity).hook = NULL;
+       }
+    }
+
        //pl.disableclientprediction = false;
 }
 
+void RemoveHook(entity this)
+{
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+    {
+       .entity weaponentity = weaponentities[slot];
+       if(this.realowner.(weaponentity).hook == this)
+               this.realowner.(weaponentity).hook = NULL;
+    }
+
+    if(this.realowner.move_movetype == MOVETYPE_FLY)
+       set_movetype(this.realowner, MOVETYPE_WALK);
+    delete(this);
+}
+
 void GrapplingHookReset(entity this)
 {
-       if(this.realowner.hook == this)
-               RemoveGrapplingHook(this.owner);
-       else // in any case:
-               delete(this);
+       RemoveHook(this);
 }
 
 void GrapplingHookThink(entity this);
@@ -117,6 +134,7 @@ bool GrapplingHookSend(entity this, entity to, int sf)
        if(sf & 1)
        {
                WriteByte(MSG_ENTITY, etof(this.realowner));
+               WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
        }
        if(sf & 2)
        {
@@ -139,14 +157,15 @@ void GrapplingHookThink(entity this)
 {
        float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
        vector dir, org, end, v0, dv, v, myorg, vs;
-       if(this.realowner.hook != this) // how did that happen?
+       .entity weaponentity = this.weaponentity_fld;
+       if(this.realowner.(weaponentity).hook != this)  // how did that happen?
        {
                error("Owner lost the hook!\n");
                return;
        }
        if(LostMovetypeFollow(this) || gameover || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
        {
-               RemoveGrapplingHook(this.realowner);
+               RemoveHook(this);
                return;
        }
        if(this.aiment)
@@ -154,7 +173,7 @@ void GrapplingHookThink(entity this)
 
        this.nextthink = time;
 
-       int s = W_GetGunAlignment(this.realowner);
+       int s = W_GunAlign(this.realowner.(weaponentity), STAT(GUNALIGN, this.realowner)) - 1;
        vs = hook_shotorigin[s];
 
        makevectors(this.realowner.v_angle);
@@ -206,7 +225,7 @@ void GrapplingHookThink(entity this)
                        v = v0 = WarpZone_RefSys_TransformVelocity(pull_entity, this, pull_entity.velocity);
 
                        // first pull the rope...
-                       if(this.realowner.hook_state & HOOK_PULLING)
+                       if(this.realowner.(weaponentity).hook_state & HOOK_PULLING)
                        {
                                newlength = this.hook_length;
                                newlength = max(newlength - pullspeed * frametime, minlength);
@@ -224,7 +243,7 @@ void GrapplingHookThink(entity this)
                        if(pull_entity.move_movetype == MOVETYPE_FLY)
                                set_movetype(pull_entity, MOVETYPE_WALK);
 
-                       if(this.realowner.hook_state & HOOK_RELEASING)
+                       if(this.realowner.(weaponentity).hook_state & HOOK_RELEASING)
                        {
                                newlength = dist;
                                this.hook_length = newlength;
@@ -266,7 +285,7 @@ void GrapplingHookThink(entity this)
 
                        if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment))
                        {
-                               RemoveGrapplingHook(this.realowner);
+                               RemoveHook(this);
                                return;
                        }
                }
@@ -338,36 +357,33 @@ void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float
                        this.realowner.pushltime = time + autocvar_g_maxpushtime;
                        this.realowner.istypefrag = PHYS_INPUT_BUTTON_CHAT(this.realowner);
                }
-               RemoveGrapplingHook(this.realowner);
+               RemoveHook(this);
        }
 }
 
-void FireGrapplingHook(entity actor)
+void FireGrapplingHook(entity actor, .entity weaponentity)
 {
-       entity missile;
-       vector org;
-       vector vs;
-
        if(forbidWeaponUse(actor)) return;
        if(actor.vehicle) return;
 
        makevectors(actor.v_angle);
 
-       int s = W_GetGunAlignment(actor);
-       vs = hook_shotorigin[s];
+       int s = W_GunAlign(actor.(weaponentity), STAT(GUNALIGN, actor)) - 1;
+       vector vs = hook_shotorigin[s];
 
        // UGLY WORKAROUND: play this on CH_WEAPON_B so it can't cut off fire sounds
        sound (actor, CH_WEAPON_B, SND_HOOK_FIRE, VOL_BASE, ATTEN_NORM);
-       org = actor.origin + actor.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
+       vector org = actor.origin + actor.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
 
        tracebox(actor.origin + actor.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, actor);
        org = trace_endpos;
 
        Send_Effect(EFFECT_HOOK_MUZZLEFLASH, org, '0 0 0', 1);
 
-       missile = WarpZone_RefSys_SpawnSameRefSys(actor);
+       entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
        missile.owner = missile.realowner = actor;
-       actor.hook = missile;
+       actor.(weaponentity).hook = missile;
+       missile.weaponentity_fld = weaponentity;
        missile.reset = GrapplingHookReset;
        missile.classname = "grapplinghook";
        missile.flags = FL_PROJECTILE;
index 900c23d36abac3eb9ce8dfb5edf0c1a8681c6bf3..719bf5b605bdbfc1832761610f0f0ac8a3c88670 100644 (file)
@@ -2,7 +2,8 @@
 
 // Wazat's grappling hook
 .entity                hook;
-void RemoveGrapplingHook(entity pl);
+void RemoveGrapplingHooks(entity pl);
+void RemoveHook(entity this);
 // (note: you can change the hook impulse #'s to whatever you please)
 .float hook_time;
 
index 4ca9ef77c8afb16b1b5fab0190bc1cbd1770e8f5..b1246091bcb1a1ca3d1f21477b32817f71e4a1bb 100644 (file)
@@ -2088,10 +2088,6 @@ void EndFrame()
        {
                antilag_record(it, it, altime);
        });
-       FOREACH_CLIENT(PS(it), {
-               PlayerState s = PS(it);
-               s.ps_push(s, it);
-       });
        systems_update();
        IL_ENDFRAME();
 }
index 8a10a6d7525f5c973367b7adef18c16546cfd8a6..89e2744c2daeaa0afe65d7fad95a64d60e54b280 100644 (file)
@@ -52,6 +52,8 @@
 
 // weapon switching impulses
 
+bool autocvar_g_weaponswitch_debug;
+
 #define X(slot) \
        IMPULSE(weapon_group_##slot) \
        { \
                        this.impulse = IMP_weapon_group_##slot.impulse; \
                        return; \
                } \
-               W_NextWeaponOnImpulse(this, slot); \
+               for(int wepslot = 0; wepslot < MAX_WEAPONSLOTS; ++wepslot) \
+               { \
+                       .entity weaponentity = weaponentities[wepslot]; \
+                       W_NextWeaponOnImpulse(this, slot, weaponentity); \
+                       if(wepslot == 0 && !autocvar_g_weaponswitch_debug) \
+                               break; \
+               } \
        }
 X(1)
 X(2)
@@ -88,7 +96,13 @@ X(0)
                noref int prev = -1; \
                noref int best =  0; \
                noref int next = +1; \
-               W_CycleWeapon(this, this.cvar_cl_weaponpriorities[slot], dir); \
+               for(int wepslot = 0; wepslot < MAX_WEAPONSLOTS; ++wepslot) \
+               { \
+                       .entity weaponentity = weaponentities[wepslot]; \
+                       W_CycleWeapon(this, this.cvar_cl_weaponpriorities[slot], dir, weaponentity); \
+                       if(wepslot == 0 && !autocvar_g_weaponswitch_debug) \
+                               break; \
+               } \
        }
 X(0, prev)
 X(1, prev)
@@ -135,7 +149,13 @@ X(9, next)
                        this.impulse = IMP_weapon_byid_##i.impulse; \
                        return; \
                } \
-               W_SwitchWeapon(this, Weapons_from(WEP_FIRST + i)); \
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) \
+               { \
+                       .entity weaponentity = weaponentities[slot]; \
+                       W_SwitchWeapon(this, Weapons_from(WEP_FIRST + i), weaponentity); \
+                       if(slot == 0 && !autocvar_g_weaponswitch_debug) \
+                               break; \
+               } \
        }
 X(0)
 X(1)
@@ -171,7 +191,14 @@ IMPULSE(weapon_next_byid)
                this.impulse = IMP_weapon_next_byid.impulse;
                return;
        }
-       W_NextWeapon(this, 0);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_NextWeapon(this, 0, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_prev_byid)
@@ -182,7 +209,14 @@ IMPULSE(weapon_prev_byid)
                this.impulse = IMP_weapon_prev_byid.impulse;
                return;
        }
-       W_PreviousWeapon(this, 0);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_PreviousWeapon(this, 0, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_next_bygroup)
@@ -193,7 +227,14 @@ IMPULSE(weapon_next_bygroup)
                this.impulse = IMP_weapon_next_bygroup.impulse;
                return;
        }
-       W_NextWeapon(this, 1);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_NextWeapon(this, 1, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_prev_bygroup)
@@ -204,7 +245,14 @@ IMPULSE(weapon_prev_bygroup)
                this.impulse = IMP_weapon_prev_bygroup.impulse;
                return;
        }
-       W_PreviousWeapon(this, 1);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_PreviousWeapon(this, 1, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_next_bypriority)
@@ -215,7 +263,14 @@ IMPULSE(weapon_next_bypriority)
                this.impulse = IMP_weapon_next_bypriority.impulse;
                return;
        }
-       W_NextWeapon(this, 2);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_NextWeapon(this, 2, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_prev_bypriority)
@@ -226,28 +281,56 @@ IMPULSE(weapon_prev_bypriority)
                this.impulse = IMP_weapon_prev_bypriority.impulse;
                return;
        }
-       W_PreviousWeapon(this, 2);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_PreviousWeapon(this, 2, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_last)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_LastWeapon(this);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_LastWeapon(this, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_best)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_SwitchWeapon(this, w_getbestweapon(this));
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_SwitchWeapon(this, w_getbestweapon(this, weaponentity), weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_drop)
 {
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
-       W_ThrowWeapon(this, weaponentities[0], W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+               W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
+       }
 }
 
 IMPULSE(weapon_reload)
@@ -255,12 +338,15 @@ IMPULSE(weapon_reload)
        if (this.vehicle) return;
        if (IS_DEAD(this)) return;
        if (forbidWeaponUse(this)) return;
-       Weapon w = PS(this).m_weapon;
        entity actor = this;
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
                .entity weaponentity = weaponentities[slot];
+               Weapon w = this.(weaponentity).m_weapon;
                w.wr_reload(w, actor, weaponentity);
+
+               if(slot == 0 && !autocvar_g_weaponswitch_debug)
+                       break;
        }
 }
 
index d2aff2ae7bbc53d7378372b3aac05033ecb826a7..e88ef02abb43ecd506693d2a964a03d26f195b7c 100644 (file)
@@ -26,6 +26,7 @@
 #include "../common/items/_mod.qh"
 #include "../common/state.qh"
 #include "../common/effects/qc/globalsound.qh"
+#include "../common/wepent.qh"
 #include "../lib/csqcmodel/sv_model.qh"
 #include "../lib/warpzone/anglestransform.qh"
 #include "../lib/warpzone/server.qh"
@@ -263,6 +264,8 @@ string formatmessage(entity this, string msg)
                replacement = substring(msg, p, 2);
                escape = substring(msg, p + 1, 1);
 
+               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
+
                switch(escape)
                {
                        case "%": replacement = "%"; break;
@@ -273,7 +276,7 @@ string formatmessage(entity this, string msg)
                        case "l": replacement = NearestLocation(this.origin); break;
                        case "y": replacement = NearestLocation(cursor); break;
                        case "d": replacement = NearestLocation(this.death_origin); break;
-                       case "w": replacement = ((PS(this).m_weapon == WEP_Null) ? ((PS(this).m_switchweapon == WEP_Null) ? Weapons_from(this.cnt) : PS(this).m_switchweapon) : PS(this).m_weapon).m_name; break;
+                       case "w": replacement = ((this.(weaponentity).m_weapon == WEP_Null) ? ((this.(weaponentity).m_switchweapon == WEP_Null) ? Weapons_from(this.(weaponentity).cnt) : this.(weaponentity).m_switchweapon) : this.(weaponentity).m_weapon).m_name; break;
                        case "W": replacement = ammoitems; break;
                        case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
                        case "s": replacement = ftos(vlen(this.velocity - this.velocity_z * '0 0 1')); break;
@@ -451,7 +454,14 @@ void GetCvars(entity this, int f)
        if (f > 0)
        {
                if (s == "cl_weaponpriority")
-                       if (PS(this)) PS(this).m_switchweapon = w_getbestweapon(this);
+               {
+                       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+                       {
+                               .entity weaponentity = weaponentities[slot];
+                               if (this.(weaponentity) && (this.(weaponentity).m_weapon != WEP_Null || slot == 0))
+                                       this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+                       }
+               }
                if (s == "cl_allow_uidtracking")
                        PlayerStats_GameReport_AddPlayer(this);
        }
@@ -1077,7 +1087,7 @@ bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher
                if(this.classname == "nade")
                        return false; // no checks here
                else if(this.classname == "grapplinghook")
-                       RemoveGrapplingHook(this.realowner);
+                       RemoveHook(this);
                else if(this.classname == "spike")
                {
                        W_Crylink_Dequeue(this);
index 09e1cf70bd212497b69907be4ec13c31e97d33ca..fb0f977a7254ca145a11dbec70b67f0c815f9301 100644 (file)
@@ -153,12 +153,14 @@ MUTATOR_HOOKABLE(PreFormatMessage, EV_PreFormatMessage);
 /** returns true if throwing the current weapon shall not be allowed */
 #define EV_ForbidThrowCurrentWeapon(i, o) \
     /** player        */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** weapon entity */ i(entity, MUTATOR_ARGV_1_entity) \
     /**/
 MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon, EV_ForbidThrowCurrentWeapon);
 
 /** returns true if dropping the current weapon shall not be allowed at any time including death */
 #define EV_ForbidDropCurrentWeapon(i, o) \
-    /** player */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** player */        i(entity, MUTATOR_ARGV_0_entity) \
+    /** weapon id */     i(int, MUTATOR_ARGV_1_int) \
     /**/
 MUTATOR_HOOKABLE(ForbidDropCurrentWeapon, EV_ForbidDropCurrentWeapon);
 
@@ -383,7 +385,8 @@ MUTATOR_HOOKABLE(PlayerDamaged, EV_PlayerDamaged);
  * Called by W_DecreaseAmmo
  */
 #define EV_W_DecreaseAmmo(i, o) \
-    /** actor */ i(entity, MUTATOR_ARGV_0_entity) \
+    /** actor */            i(entity, MUTATOR_ARGV_0_entity) \
+    /** weapon entity */    i(entity, MUTATOR_ARGV_1_entity) \
     /**/
 MUTATOR_HOOKABLE(W_DecreaseAmmo, EV_W_DecreaseAmmo);
 
index 9cccbe887a87790aa49ce0b8ac1b9a32e8304483..50708f33eb9b1aa53b0c7ceb7640198990a5df11 100644 (file)
@@ -24,6 +24,7 @@
 #include "../common/effects/qc/all.qh"
 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 #include "../common/triggers/include.qh"
+#include "../common/wepent.qh"
 
 #include "weapons/weaponstats.qh"
 
@@ -485,6 +486,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
 
        valid_damage_for_weaponstats = 0;
        Weapon awep = WEP_Null;
+       .entity weaponentity = weaponentities[0]; // TODO: unhardcode
 
        if(vbot || IS_REAL_CLIENT(this))
        if(abot || IS_REAL_CLIENT(attacker))
@@ -492,7 +494,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        if(DIFF_TEAM(this, attacker))
        {
                if(DEATH_ISSPECIAL(deathtype))
-                       awep = PS(attacker).m_weapon;
+                       awep = attacker.(weaponentity).m_weapon;
                else
                        awep = DEATH_WEAPONOF(deathtype);
                valid_damage_for_weaponstats = 1;
@@ -502,7 +504,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        da = da - max(this.armorvalue, 0);
        if(valid_damage_for_weaponstats)
        {
-               WeaponStats_LogDamage(awep.m_id, abot, PS(this).m_weapon.m_id, vbot, dh + da);
+               WeaponStats_LogDamage(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot, dh + da);
        }
        if (damage)
        {
@@ -521,7 +523,7 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                }
 
                if(valid_damage_for_weaponstats)
-                       WeaponStats_LogKill(awep.m_id, abot, PS(this).m_weapon.m_id, vbot);
+                       WeaponStats_LogKill(awep.m_id, abot, this.(weaponentity).m_weapon.m_id, vbot);
 
                if(autocvar_sv_gentle < 1)
                if(sound_allowed(MSG_BROADCAST, attacker))
@@ -560,16 +562,14 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, this, deathtype, damage);
                excess = M_ARGV(4, float);
 
-               Weapon wep = PS(this).m_weapon;
-               /*for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               Weapon wep = this.(weaponentity).m_weapon;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
-                       .entity weaponentity = weaponentities[slot];
-                       wep.wr_playerdeath(wep, this, weaponentity);
-               }*/
-               .entity weaponentity = weaponentities[0]; // TODO: unhardcode
-               wep.wr_playerdeath(wep, this, weaponentity);
+                       .entity went = weaponentities[slot];
+                       wep.wr_playerdeath(wep, this, went);
+               }
 
-               RemoveGrapplingHook(this);
+               RemoveGrapplingHooks(this);
 
                Portal_ClearAllLater(this);
 
@@ -591,7 +591,11 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                // clear waypoints
                WaypointSprite_PlayerDead(this);
                // throw a weapon
-               SpawnThrownWeapon(this, this.origin + (this.mins + this.maxs) * 0.5, PS(this).m_switchweapon.m_id);
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity went = weaponentities[slot];
+                       SpawnThrownWeapon(this, this.origin + (this.mins + this.maxs) * 0.5, this.(went).m_switchweapon.m_id, went);
+               }
 
                // become fully visible
                this.alpha = default_player_alpha;
index 12083e423cb573b940c3c82c9453450447f6c096..b41c53bbcce4eed3dcd541f25fd738ebfb750fae 100644 (file)
@@ -481,8 +481,12 @@ void Portal_Think(entity this)
                if(it != o || time >= this.portal_activatetime)
                        Portal_Think_TryTeleportPlayer(this, it, g);
 
-               if(it.hook)
-                       Portal_Think_TryTeleportPlayer(this, it.hook, g);
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           {
+               .entity weaponentity = weaponentities[slot];
+               if(it.(weaponentity).hook)
+                       Portal_Think_TryTeleportPlayer(this, it.(weaponentity).hook, g);
+           }
        ));
        this.solid = SOLID_TRIGGER;
        this.aiment = o;
index 0c36a77c5b7689665d101e1d676efe67af567e21..b510b43c8076b0b81c606e44ca3e6f00b076eb95 100644 (file)
@@ -99,7 +99,17 @@ void CreatureFrame_FallDamage(entity this)
        {
                // check for falling damage
                float velocity_len = vlen(this.velocity);
-               if(!this.hook.state)
+               bool have_hook = false;
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+           {
+               .entity weaponentity = weaponentities[slot];
+               if(this.(weaponentity).hook && this.(weaponentity).hook.state)
+               {
+                       have_hook = true;
+                       break;
+               }
+           }
+               if(!have_hook)
                {
                        float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
                        if (IS_DEAD(this))
index 96674db702943a933786ca954c4ec20498839ae8..50dc5a35bca7cd130b7732fe141819539bc64e01 100644 (file)
@@ -26,7 +26,7 @@ TEST(Weapons, Hurt)
     it.items |= IT_UNLIMITED_AMMO;
     Weapon wep = WEP_VORTEX;
     W_GiveWeapon(it, wep.m_id);
-    W_SwitchWeapon_Force(it, wep);
+    W_SwitchWeapon_Force(it, wep, weaponentities[0]);
 
     it = b;
     PHYS_INPUT_BUTTON_JUMP(it) = true;
index 372f7357b4057a95d63cba482b826d87b23a441d..d148ab54f4597de3da7193d05c8104bd09a7fc80 100644 (file)
@@ -4,6 +4,7 @@
 #include "../g_subs.qh"
 #include <common/weapons/_all.qh>
 #include <common/state.qh>
+#include <common/wepent.qh>
 
 vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v)
 {
@@ -51,7 +52,7 @@ vector W_HitPlotNormalizedUntransform(vector org, entity targ, vector screenforw
        return ret;
 }
 
-void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup)
+void W_HitPlotAnalysis(entity player, .entity weaponentity, vector screenforward, vector screenright, vector screenup)
 {
        vector hitplot;
        vector org;
@@ -73,7 +74,7 @@ void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright,
                        antilag_takeback(trace_ent, store, time - lag);
                        hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos);
                        antilag_restore(trace_ent, store);
-                       fputs(player.hitplotfh, strcat(ftos(hitplot.x), " ", ftos(hitplot.y), " ", ftos(hitplot.z), " ", ftos(PS(player).m_switchweapon.m_id), "\n"));
+                       fputs(player.hitplotfh, strcat(ftos(hitplot.x), " ", ftos(hitplot.y), " ", ftos(hitplot.z), " ", ftos(player.(weaponentity).m_switchweapon.m_id), "\n"));
                        //print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n"));
                }
        }
index 8aa15a61b4f37222725bc539f51d4e7682545766..89f7f50504d580c04f354fd971d61d56fddb7824 100644 (file)
@@ -2,6 +2,6 @@
 
 .float hitplotfh;
 
-void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup);
+void W_HitPlotAnalysis(entity player, .entity weaponentity, vector screenforward, vector screenright, vector screenup);
 void W_HitPlotOpen(entity player);
 void W_HitPlotClose(entity player);
index cdb337d145bb948a877141cd610f4a0b74a58acc..06d5f30851711c5a952ce3935513d870da97d12a 100644 (file)
@@ -9,6 +9,7 @@
 #include <common/weapons/_all.qh>
 #include <common/state.qh>
 #include <common/mutators/mutator/waypoints/waypointsprites.qh>
+#include <common/wepent.qh>
 
 // switch between weapons
 void Send_WeaponComplain(entity e, float wpn, float type)
@@ -39,7 +40,7 @@ void Weapon_whereis(Weapon this, entity cl)
        });
 }
 
-bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
+bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andammo, bool complain)
 {
        float f = 0;
 
@@ -70,11 +71,11 @@ bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
                        }
                        else
                        {
-                               f = wpn.wr_checkammo1(wpn, this) + wpn.wr_checkammo2(wpn, this);
+                               f = wpn.wr_checkammo1(wpn, this, weaponentity) + wpn.wr_checkammo2(wpn, this, weaponentity);
 
                                // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
                                if(wpn == WEP_MINE_LAYER)
-                                       IL_EACH(g_mines, it.owner == this,
+                                       IL_EACH(g_mines, it.owner == this && it.weaponentity_fld == weaponentity,
                                        {
                                                f = 1;
                                                break; // no need to continue
@@ -120,7 +121,7 @@ bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain)
        return false;
 }
 
-float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing)
+float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing, .entity weaponentity)
 {
        // We cannot tokenize in this function, as GiveItems calls this
        // function. Thus we must use car/cdr.
@@ -131,10 +132,10 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
        float weaponcur;
        entity wep;
 
-       if(skipmissing || this.selectweapon == 0)
-               weaponcur = PS(this).m_switchweapon.m_id;
+       if(skipmissing || this.(weaponentity).selectweapon == 0)
+               weaponcur = this.(weaponentity).m_switchweapon.m_id;
        else
-               weaponcur = this.selectweapon;
+               weaponcur = this.(weaponentity).selectweapon;
 
        if(dir == 0)
                switchtonext = 1;
@@ -167,7 +168,7 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
 
                ++c;
 
-               if(!skipmissing || client_hasweapon(this, wep, true, false))
+               if(!skipmissing || client_hasweapon(this, wep, weaponentity, true, false))
                {
                        if(switchtonext)
                                return weaponwant;
@@ -224,7 +225,7 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
                        --c;
                        if(c == 0)
                        {
-                               client_hasweapon(this, wep, true, true);
+                               client_hasweapon(this, wep, weaponentity, true, true);
                                break;
                        }
                }
@@ -232,97 +233,94 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
        return 0;
 }
 
-void W_SwitchWeapon_Force(Player this, Weapon wep)
+void W_SwitchWeapon_Force(Player this, Weapon wep, .entity weaponentity)
 {
-    TC(Player, this); TC(Weapon, wep);
-       this.cnt = PS(this).m_switchweapon.m_id;
-       PS(this).m_switchweapon = wep;
-       this.selectweapon = wep.m_id;
+    TC(Weapon, wep);
+       this.(weaponentity).cnt = this.(weaponentity).m_switchweapon.m_id;
+       this.(weaponentity).m_switchweapon = wep;
+       this.(weaponentity).selectweapon = wep.m_id;
 }
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity this)
+void W_SwitchToOtherWeapon(entity this, .entity weaponentity)
 {
        // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
        Weapon ww;
-       WepSet set = WepSet_FromWeapon(PS(this).m_weapon);
+       WepSet set = WepSet_FromWeapon(this.(weaponentity).m_weapon);
        if (this.weapons & set)
        {
                this.weapons &= ~set;
-               ww = w_getbestweapon(this);
+               ww = w_getbestweapon(this, weaponentity);
                this.weapons |= set;
        }
        else
        {
-               ww = w_getbestweapon(this);
+               ww = w_getbestweapon(this, weaponentity);
        }
        if (ww == WEP_Null) return;
-       W_SwitchWeapon_Force(this, ww);
+       W_SwitchWeapon_Force(this, ww, weaponentity);
 }
 
-void W_SwitchWeapon(entity this, Weapon w)
+void W_SwitchWeapon(entity this, Weapon w, .entity weaponentity)
 {
-       if (PS(this).m_switchweapon != w)
+       if(this.(weaponentity).m_switchweapon != w)
        {
-               if (client_hasweapon(this, w, true, true))
-                       W_SwitchWeapon_Force(this, w);
+               if(client_hasweapon(this, w, weaponentity, true, true))
+                       W_SwitchWeapon_Force(this, w, weaponentity);
                else
-                       this.selectweapon = w.m_id; // update selectweapon ANYWAY
+                       this.(weaponentity).selectweapon = w.m_id; // update selectweapon anyway
        }
-       else if(!forbidWeaponUse(this)) {
+       else if(!forbidWeaponUse(this))
+       {
                entity actor = this;
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-               {
-                       .entity weaponentity = weaponentities[slot];
-                       w.wr_reload(w, actor, weaponentity);
-               }
+               w.wr_reload(w, actor, weaponentity);
        }
 }
 
-void W_CycleWeapon(entity this, string weaponorder, float dir)
+void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity)
 {
        float w;
-       w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true);
+       w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true, weaponentity);
        if(w > 0)
-               W_SwitchWeapon(this, Weapons_from(w));
+               W_SwitchWeapon(this, Weapons_from(w), weaponentity);
 }
 
-void W_NextWeaponOnImpulse(entity this, float imp)
+void W_NextWeaponOnImpulse(entity this, float imp, .entity weaponentity)
 {
        float w;
-       w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0));
+       w = W_GetCycleWeapon(this, this.cvar_cl_weaponpriority, +1, imp, 1, (this.cvar_cl_weaponimpulsemode == 0), weaponentity);
        if(w > 0)
-               W_SwitchWeapon(this, Weapons_from(w));
+               W_SwitchWeapon(this, Weapons_from(w), weaponentity);
 }
 
 // next weapon
-void W_NextWeapon(entity this, int list)
+void W_NextWeapon(entity this, int list, .entity weaponentity)
 {
        if(list == 0)
-               W_CycleWeapon(this, weaponorder_byid, -1);
+               W_CycleWeapon(this, weaponorder_byid, -1, weaponentity);
        else if(list == 1)
-               W_CycleWeapon(this, this.weaponorder_byimpulse, -1);
+               W_CycleWeapon(this, this.weaponorder_byimpulse, -1, weaponentity);
        else if(list == 2)
-               W_CycleWeapon(this, this.cvar_cl_weaponpriority, -1);
+               W_CycleWeapon(this, this.cvar_cl_weaponpriority, -1, weaponentity);
 }
 
 // prev weapon
-void W_PreviousWeapon(entity this, float list)
+void W_PreviousWeapon(entity this, float list, .entity weaponentity)
 {
        if(list == 0)
-               W_CycleWeapon(this, weaponorder_byid, +1);
+               W_CycleWeapon(this, weaponorder_byid, +1, weaponentity);
        else if(list == 1)
-               W_CycleWeapon(this, this.weaponorder_byimpulse, +1);
+               W_CycleWeapon(this, this.weaponorder_byimpulse, +1, weaponentity);
        else if(list == 2)
-               W_CycleWeapon(this, this.cvar_cl_weaponpriority, +1);
+               W_CycleWeapon(this, this.cvar_cl_weaponpriority, +1, weaponentity);
 }
 
 // previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(entity this)
+void W_LastWeapon(entity this, .entity weaponentity)
 {
-       Weapon wep = Weapons_from(this.cnt);
-       if (client_hasweapon(this, wep, true, false))
-               W_SwitchWeapon(this, wep);
+       Weapon wep = Weapons_from(this.(weaponentity).cnt);
+       if (client_hasweapon(this, wep, weaponentity, true, false))
+               W_SwitchWeapon(this, wep, weaponentity);
        else
-               W_SwitchToOtherWeapon(this);
+               W_SwitchToOtherWeapon(this, weaponentity);
 }
index 0c30b7c1215040fd7bc2de7256f0dcd67b6095fc..071a0fea8bcb73fb1b2ebad279b7d26cbdcf3f83 100644 (file)
@@ -4,28 +4,28 @@
 void Send_WeaponComplain(entity e, float wpn, float type);
 
 .float hasweapon_complain_spam;
-bool client_hasweapon(entity this, Weapon wpn, float andammo, bool complain);
+bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andammo, bool complain);
 
 .int weaponcomplainindex;
-float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing);
+float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing, .entity weaponentity);
 
-#define w_getbestweapon(ent) Weapons_from(W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true))
+#define w_getbestweapon(ent,wepent) Weapons_from(W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, false, true, wepent))
 
-void W_SwitchWeapon_Force(Player this, Weapon w);
+void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
 
 // perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity this);
-void W_SwitchWeapon(entity this, Weapon imp);
+void W_SwitchToOtherWeapon(entity this, .entity weaponentity);
+void W_SwitchWeapon(entity this, Weapon imp, .entity weaponentity);
 
-void W_CycleWeapon(entity this, string weaponorder, float dir);
+void W_CycleWeapon(entity this, string weaponorder, float dir, .entity weaponentity);
 
-void W_NextWeaponOnImpulse(entity this, float imp);
+void W_NextWeaponOnImpulse(entity this, float imp, .entity weaponentity);
 
 // next weapon
-void W_NextWeapon(entity this, float list);
+void W_NextWeapon(entity this, float list, .entity weaponentity);
 
 // prev weapon
-void W_PreviousWeapon(entity this, float list);
+void W_PreviousWeapon(entity this, float list, .entity weaponentity);
 
 // previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(entity this);
+void W_LastWeapon(entity this, .entity weaponentity);
index bd69e33246d6b3dae4593e008493f0b2582d1f63..4114c3c58b199cc9a950c811dcf5269b0fdea807 100644 (file)
@@ -11,6 +11,7 @@
 #include <common/util.qh>
 #include <common/weapons/_all.qh>
 #include <common/state.qh>
+#include <common/wepent.qh>
 
 void thrown_wep_think(entity this)
 {
@@ -31,7 +32,7 @@ void thrown_wep_think(entity this)
 }
 
 // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
+string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity)
 {
        float thisammo;
        string s;
@@ -45,9 +46,9 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
        wep.owner = wep.enemy = own;
        wep.flags |= FL_TOSSED;
        wep.colormap = own.colormap;
-       wep.glowmod = weaponentity_glowmod(info, own, own.clientcolors);
+       wep.glowmod = weaponentity_glowmod(info, own, own.clientcolors, own.(weaponentity));
 
-       W_DropEvent(wr_drop,own,wpn,wep);
+       W_DropEvent(wr_drop,own,wpn,wep,weaponentity);
 
        if(WepSet_FromWeapon(Weapons_from(wpn)) & WEPSET_SUPERWEAPONS)
        {
@@ -97,11 +98,11 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                if(doreduce && g_weapon_stay == 2)
                {
                        // if our weapon is loaded, give its load back to the player
-                       int i = PS(own).m_weapon.m_id;
-                       if(own.(weapon_load[i]) > 0)
+                       int i = own.(weaponentity).m_weapon.m_id;
+                       if(own.(weaponentity).(weapon_load[i]) > 0)
                        {
-                               own.(ammotype) += own.(weapon_load[i]);
-                               own.(weapon_load[i]) = -1; // schedule the weapon for reloading
+                               own.(ammotype) += own.(weaponentity).(weapon_load[i]);
+                               own.(weaponentity).(weapon_load[i]) = -1; // schedule the weapon for reloading
                        }
 
                        wep.(ammotype) = 0;
@@ -109,11 +110,11 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                else if(doreduce)
                {
                        // if our weapon is loaded, give its load back to the player
-                       int i = PS(own).m_weapon.m_id;
-                       if(own.(weapon_load[i]) > 0)
+                       int i = own.(weaponentity).m_weapon.m_id;
+                       if(own.(weaponentity).(weapon_load[i]) > 0)
                        {
-                               own.(ammotype) += own.(weapon_load[i]);
-                               own.(weapon_load[i]) = -1; // schedule the weapon for reloading
+                               own.(ammotype) += own.(weaponentity).(weapon_load[i]);
+                               own.(weaponentity).(weapon_load[i]) = -1; // schedule the weapon for reloading
                        }
 
                        thisammo = min(own.(ammotype), wep.(ammotype));
@@ -138,7 +139,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
 
 bool W_IsWeaponThrowable(entity this, int w)
 {
-       if (MUTATOR_CALLHOOK(ForbidDropCurrentWeapon, this))
+       if (MUTATOR_CALLHOOK(ForbidDropCurrentWeapon, this, w))
                return false;
        if (!autocvar_g_pickup_items)
                return false;
@@ -167,10 +168,10 @@ bool W_IsWeaponThrowable(entity this, int w)
 // toss current weapon
 void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta, float doreduce)
 {
-       Weapon w = PS(this).m_weapon;
+       Weapon w = this.(weaponentity).m_weapon;
        if (w == WEP_Null)
                return; // just in case
-       if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon, this))
+       if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon, this, this.(weaponentity)))
                return;
        if(!autocvar_g_weapon_throwable)
                return;
@@ -183,16 +184,18 @@ void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta,
        if(!(this.weapons & set)) return;
        this.weapons &= ~set;
 
-       W_SwitchWeapon_Force(this, w_getbestweapon(this));
-       string a = W_ThrowNewWeapon(this, w.m_id, doreduce, this.origin + delta, velo);
+       W_SwitchWeapon_Force(this, w_getbestweapon(this, weaponentity), weaponentity);
+       string a = W_ThrowNewWeapon(this, w.m_id, doreduce, this.origin + delta, velo, weaponentity);
 
        if(!a) return;
        Send_Notification(NOTIF_ONE, this, MSG_MULTI, ITEM_WEAPON_DROP, a, w.m_id);
 }
 
-void SpawnThrownWeapon(entity this, vector org, float w)
+void SpawnThrownWeapon(entity this, vector org, float w, .entity weaponentity)
 {
-       if(this.weapons & WepSet_FromWeapon(PS(this).m_weapon))
-               if(W_IsWeaponThrowable(this, PS(this).m_weapon.m_id))
-                       W_ThrowNewWeapon(this, PS(this).m_weapon.m_id, false, org, randomvec() * 125 + '0 0 200');
+       entity wep = this.(weaponentity).m_weapon;
+
+       if(this.weapons & WepSet_FromWeapon(wep))
+               if(W_IsWeaponThrowable(this, wep.m_id))
+                       W_ThrowNewWeapon(this, wep.m_id, false, org, randomvec() * 125 + '0 0 200', weaponentity);
 }
index a03968083edbd5e1e0a1c06a8471a1058b8b8843..01ab21ba63323427fd8783bf8895fbee3a16fbbd 100644 (file)
@@ -4,11 +4,11 @@
 void thrown_wep_think(entity this);
 
 // returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
+string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity);
 
 bool W_IsWeaponThrowable(entity this, int w);
 
 // toss current weapon
 void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta, float doreduce);
 
-void SpawnThrownWeapon(entity this, vector org, float w);
+void SpawnThrownWeapon(entity this, vector org, float w, .entity weaponentity);
index b49ed88f596ca00a7ef4e6b3467b7e5a3f36c2e2..1417717e834e33270ed355d891a450bb73767938 100644 (file)
@@ -28,7 +28,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
        float oldsolid;
        vector vecs, dv;
        oldsolid = ent.dphitcontentsmask;
-       if (IS_PLAYER(ent) && PS(ent).m_weapon == WEP_RIFLE)
+       if (IS_PLAYER(ent) && ent.(weaponentity).m_weapon == WEP_RIFLE)
                ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
        else
                ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
@@ -54,10 +54,10 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
 
        // track max damage
        if (IS_PLAYER(ent) && accuracy_canbegooddamage(ent))
-               accuracy_add(ent, PS(ent).m_weapon.m_id, maxdamage, 0);
+               accuracy_add(ent, ent.(weaponentity).m_weapon.m_id, maxdamage, 0);
 
        if(IS_PLAYER(ent))
-               W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
+               W_HitPlotAnalysis(ent, weaponentity, v_forward, v_right, v_up);
 
        vector md = ent.(weaponentity).movedir;
        if(md.x > 0)
@@ -197,7 +197,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 //  Ballistics Tracing
 // ====================
 
-void FireRailgunBullet (entity this, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
+void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
 {
        vector hitloc, force, endpoint, dir;
        entity ent, endent;
@@ -334,7 +334,7 @@ void FireRailgunBullet (entity this, vector start, vector end, float bdamage, fl
        }
 
        // calculate hits and fired shots for hitscan
-       accuracy_add(this, PS(this).m_weapon.m_id, 0, min(bdamage, totaldmg));
+       accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, min(bdamage, totaldmg));
 
        trace_endpos = endpoint;
        trace_ent = endent;
@@ -349,7 +349,7 @@ void fireBullet_trace_callback(vector start, vector hit, vector end)
        fireBullet_last_hit = NULL;
 }
 
-void fireBullet(entity this, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
+void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects)
 {
        vector  end;
 
@@ -442,7 +442,7 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s
                                // do not exceed 100%
                                float added_damage = min(damage - total_damage, damage * solid_penetration_left);
                                total_damage += damage * solid_penetration_left;
-                               accuracy_add(this, PS(this).m_weapon.m_id, 0, added_damage);
+                               accuracy_add(this, this.(weaponentity).m_weapon.m_id, 0, added_damage);
                        }
                }
 
index 21f12c1e4c02633ef9d16f658b99990a87cf74b9..aec274143bd12c69db06411f00648b3d8c3a5187 100644 (file)
@@ -49,9 +49,9 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p
 
 .float railgundistance;
 .vector railgunforce;
-void FireRailgunBullet (entity this, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype);
+void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype);
 
 entity fireBullet_trace_callback_eff;
 entity fireBullet_last_hit;
 void fireBullet_trace_callback(vector start, vector hit, vector end);
-void fireBullet(entity this, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects);
+void fireBullet(entity this, .entity weaponentity, vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, int tracereffects);
index 7dbdae6838cb2d5adcd632b9f67404b1f9359021..18675f0d5763b8d91b49588f2a695d22eb21c639 100644 (file)
@@ -15,6 +15,7 @@
 #include <common/weapons/_all.qh>
 #include <common/state.qh>
 #include <lib/csqcmodel/sv_model.qh>
+#include <common/wepent.qh>
 
 .int state;
 
@@ -61,8 +62,10 @@ vector CL_Weapon_GetShotOrg(int wpn)
        return ret;
 }
 
-..entity weaponentity_fld;
 .float m_alpha;
+.string w_weaponname;
+.int w_dmg;
+.int w_deadflag;
 
 void CL_Weaponentity_Think(entity this)
 {
@@ -83,16 +86,16 @@ void CL_Weaponentity_Think(entity this)
                if (this.weaponchild) this.weaponchild.model = "";
                return;
        }
-       if (this.weaponname != this.owner.weaponname
-           || this.dmg != this.owner.modelindex
-           || this.deadflag != this.owner.deadflag)
+       if (this.w_weaponname != this.weaponname
+           || this.w_dmg != this.modelindex
+           || this.w_deadflag != this.deadflag)
        {
                // owner changed weapons; update appearance
-               this.weaponname = this.owner.weaponname;
-               this.dmg = this.owner.modelindex;
-               this.deadflag = this.owner.deadflag;
+               this.w_weaponname = this.weaponname;
+               this.w_dmg = this.modelindex;
+               this.w_deadflag = this.deadflag;
 
-               CL_WeaponEntity_SetModel(this, this.owner.weaponname, true);
+               CL_WeaponEntity_SetModel(this, this.weaponname, true);
        }
 
        this.alpha = -1;  // TODO: don't render this entity at all
@@ -111,6 +114,8 @@ void CL_Weaponentity_Think(entity this)
 void CL_ExteriorWeaponentity_Think(entity this)
 {
        this.nextthink = time;
+       .entity weaponentity = this.weaponentity_fld;
+       entity w_ent = this.owner.(weaponentity);
        if (this.owner.exteriorweaponentity != this)
        {
                delete(this);
@@ -121,15 +126,15 @@ void CL_ExteriorWeaponentity_Think(entity this)
                this.model = "";
                return;
        }
-       if (this.weaponname != this.owner.weaponname || this.dmg != this.owner.modelindex
-           || this.deadflag != this.owner.deadflag)
+       if (this.weaponname != w_ent.weaponname || this.dmg != w_ent.modelindex
+           || this.deadflag != w_ent.deadflag)
        {
-               this.weaponname = this.owner.weaponname;
-               this.dmg = this.owner.modelindex;
-               this.deadflag = this.owner.deadflag;
-               if (this.owner.weaponname != "")
+               this.weaponname = w_ent.weaponname;
+               this.dmg = w_ent.modelindex;
+               this.deadflag = w_ent.deadflag;
+               if (w_ent.weaponname != "")
                {
-                       _setmodel(this, W_Model(strcat("v_", this.owner.weaponname, ".md3")));
+                       _setmodel(this, W_Model(strcat("v_", w_ent.weaponname, ".md3")));
                        setsize(this, '0 0 0', '0 0 0');
                }
                else this.model = "";
@@ -152,8 +157,8 @@ void CL_ExteriorWeaponentity_Think(entity this)
        else if (this.owner.alpha != 0) this.alpha = this.owner.alpha;
        else this.alpha = 1;
 
-    Weapon wep = PS(this.owner).m_weapon;
-       if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors);
+    Weapon wep = this.owner.(weaponentity).m_weapon;
+       if (wep) this.glowmod = weaponentity_glowmod(wep, this.owner, this.owner.clientcolors, this.owner.(weaponentity));
        this.colormap = this.owner.colormap;
 
        CSQCMODEL_AUTOUPDATE(this);
@@ -173,11 +178,14 @@ void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
        view.viewmodelforclient = actor;
        setcefc(view, CL_Weaponentity_CustomizeEntityForClient);
 
-       if (weaponentity == weaponentities[0])
+       wepent_link(view);
+
+       if (weaponentity == weaponentities[0]) // only one exterior model, thank you very much
        {
                entity exterior = actor.exteriorweaponentity = new(exteriorweaponentity);
                exterior.solid = SOLID_NOT;
                exterior.owner = actor;
+               exterior.weaponentity_fld = weaponentity;
                setorigin(exterior, '0 0 0');
                setthink(exterior, CL_ExteriorWeaponentity_Think);
                exterior.nextthink = time;
@@ -189,8 +197,8 @@ void CL_SpawnWeaponentity(entity actor, .entity weaponentity)
 // Weapon subs
 void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       PS(actor).m_weapon = WEP_Null;
-       PS(actor).m_switchingweapon = WEP_Null;
+       actor.(weaponentity).m_weapon = WEP_Null;
+       actor.(weaponentity).m_switchingweapon = WEP_Null;
        entity this = actor.(weaponentity);
        if (this)
        {
@@ -208,17 +216,17 @@ void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 
 .float prevdryfire;
 .float prevwarntime;
-bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary)
+bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary, .entity weaponentity)
 {
        if ((actor.items & IT_UNLIMITED_WEAPON_AMMO)) return true;
        bool ammo = false;
-       if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor);
-       else ammo = thiswep.wr_checkammo1(thiswep, actor);
+       if (secondary) ammo = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
+       else ammo = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
        if (ammo) return true;
        // always keep the Mine Layer if we placed mines, so that we can detonate them
        if (thiswep == WEP_MINE_LAYER)
        {
-               IL_EACH(g_mines, it.owner == actor,
+               IL_EACH(g_mines, it.owner == actor && it.weaponentity_fld == weaponentity,
                {
                        return false;
                });
@@ -227,7 +235,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
        if (thiswep == WEP_SHOTGUN)
                if (!secondary && WEP_CVAR(shotgun, secondary) == 1) return false;           // no clicking, just allow
 
-       if (thiswep == PS(actor).m_switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+       if (thiswep == actor.(weaponentity).m_switchweapon && time - actor.prevdryfire > 1) // only play once BEFORE starting to switch weapons
        {
                sound(actor, CH_WEAPON_A, SND_DRYFIRE, VOL_BASE, ATTEN_NORM);
                actor.prevdryfire = time;
@@ -235,8 +243,8 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
 
        // check if the other firing mode has enough ammo
        bool ammo_other = false;
-       if (secondary) ammo_other = thiswep.wr_checkammo1(thiswep, actor);
-       else ammo_other = thiswep.wr_checkammo2(thiswep, actor);
+       if (secondary) ammo_other = thiswep.wr_checkammo1(thiswep, actor, weaponentity);
+       else ammo_other = thiswep.wr_checkammo2(thiswep, actor, weaponentity);
        if (ammo_other)
        {
                if (time - actor.prevwarntime > 1)
@@ -255,7 +263,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
        }
        else  // this weapon is totally unable to fire, switch to another one
        {
-               W_SwitchToOtherWeapon(actor);
+               W_SwitchToOtherWeapon(actor, weaponentity);
        }
 
        return false;
@@ -265,7 +273,7 @@ bool weapon_prepareattack_checkammo(Weapon thiswep, entity actor, bool secondary
 bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponentity, bool secondary, float attacktime)
 {
        if (actor.weaponentity == NULL) return true;
-       if (!weapon_prepareattack_checkammo(thiswep, actor, secondary)) return false;
+       if (!weapon_prepareattack_checkammo(thiswep, actor, secondary, weaponentity)) return false;
 
        // if sv_ready_restart_after_countdown is set, don't allow the player to shoot
        // if all players readied up and the countdown is running
@@ -275,13 +283,13 @@ bool weapon_prepareattack_check(Weapon thiswep, entity actor, .entity weaponenti
                return false;
 
        // do not even think about shooting if switching
-       if (PS(actor).m_switchweapon != PS(actor).m_weapon) return false;
+       if (actor.(weaponentity).m_switchweapon != actor.(weaponentity).m_weapon) return false;
 
        if (attacktime >= 0)
        {
                int slot = weaponslot(weaponentity);
                // don't fire if previous attack is not finished
-               if (ATTACK_FINISHED(actor, slot) > time + actor.weapon_frametime * 0.5) return false;
+               if (ATTACK_FINISHED(actor, slot) > time + actor.(weaponentity).weapon_frametime * 0.5) return false;
                entity this = actor.(weaponentity);
                // don't fire while changing weapon
                if (this.state != WS_READY) return false;
@@ -301,14 +309,14 @@ void weapon_prepareattack_do(entity actor, .entity weaponentity, bool secondary,
        if (attacktime >= 0)
        {
                int slot = weaponslot(weaponentity);
-               if (ATTACK_FINISHED(actor, slot) < time - actor.weapon_frametime * 1.5)
+               if (ATTACK_FINISHED(actor, slot) < time - this.weapon_frametime * 1.5)
                {
                        ATTACK_FINISHED(actor, slot) = time;
                        // dprint("resetting attack finished to ", ftos(time), "\n");
                }
                ATTACK_FINISHED(actor, slot) = ATTACK_FINISHED(actor, slot) + attacktime * W_WeaponRateFactor(actor);
        }
-       actor.bulletcounter += 1;
+       this.bulletcounter += 1;
        // dprint("attack finished ", ftos(ATTACK_FINISHED(actor, slot)), "\n");
 }
 
@@ -372,14 +380,13 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(
                this.weapon_nextthink = time;
                // dprint("started firing at ", ftos(time), "\n");
        }
-       if (this.weapon_nextthink < time - actor.weapon_frametime * 1.5
-           || this.weapon_nextthink > time + actor.weapon_frametime * 1.5)
+       if (this.weapon_nextthink < time - this.weapon_frametime * 1.5
+           || this.weapon_nextthink > time + this.weapon_frametime * 1.5)
        {
                this.weapon_nextthink = time;
                // dprint("reset weapon animation timer at ", ftos(time), "\n");
        }
        this.weapon_nextthink += t;
-       if (weaponentity == weaponentities[0]) STAT(WEAPON_NEXTTHINK, actor) = this.weapon_nextthink;
        this.weapon_think = func;
        // dprint("next ", ftos(this.weapon_nextthink), "\n");
 
@@ -393,8 +400,8 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void(
 
        if ((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
        {
-               bool primary_melee = boolean(fr == WFRAME_FIRE1 && (PS(actor).m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
-               bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (PS(actor).m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
+               bool primary_melee = boolean(fr == WFRAME_FIRE1 && (this.m_weapon.spawnflags & WEP_TYPE_MELEE_PRI));
+               bool secondary_melee = boolean(fr == WFRAME_FIRE2 && (this.m_weapon.spawnflags & WEP_TYPE_MELEE_SEC));
                int act = (primary_melee || secondary_melee)
                        ? ANIMACTION_MELEE
                        : ANIMACTION_SHOOT
@@ -426,27 +433,27 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
     TC(Player, actor);
     TC(PlayerState, PS(actor));
        entity this = actor.(weaponentity);
-       if (frametime) actor.weapon_frametime = frametime;
+       if (frametime) this.weapon_frametime = frametime;
 
        if (!this || actor.health < 1) return;  // Dead player can't use weapons and injure impulse commands
 
 
        if (forbidWeaponUse(actor))
        {
-               if (actor.(weaponentity).state != WS_CLEAR)
+               if (this.state != WS_CLEAR)
                {
-                       Weapon wpn = PS(actor).m_weapon;
+                       Weapon wpn = this.m_weapon;
                        w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
                        return;
                }
        }
 
-       if (PS(actor).m_switchweapon == WEP_Null)
+       if (this.m_switchweapon == WEP_Null)
        {
-               PS(actor).m_weapon = WEP_Null;
-               PS(actor).m_switchingweapon = WEP_Null;
+               this.m_weapon = WEP_Null;
+               this.m_switchingweapon = WEP_Null;
                this.state = WS_CLEAR;
-               actor.weaponname = "";
+               this.weaponname = "";
                // actor.items &= ~IT_AMMO;
                return;
        }
@@ -457,7 +464,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        vector up = v_up;
 
        // Change weapon
-       if (PS(actor).m_weapon != PS(actor).m_switchweapon)
+       if (this.m_weapon != this.m_switchweapon)
        {
                switch (this.state)
                {
@@ -470,26 +477,25 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        case WS_CLEAR:
                        {
                                // end switching!
-                               Weapon newwep = PS(actor).m_switchweapon;
-                               PS(actor).m_switchingweapon = newwep;
+                               Weapon newwep = this.m_switchweapon;
+                               this.m_switchingweapon = newwep;
 
                                // the two weapon entities will notice this has changed and update their models
-                               PS(actor).m_weapon = newwep;
-                               actor.weaponname = newwep.mdl;
-                               actor.bulletcounter = 0;
-                               actor.ammo_field = newwep.ammo_field;
-                               newwep.wr_setup(newwep, actor);
+                               this.m_weapon = newwep;
+                               this.weaponname = newwep.mdl;
+                               this.bulletcounter = 0;
+                               newwep.wr_setup(newwep, actor, weaponentity);
                                this.state = WS_RAISE;
 
                                // set our clip load to the load of the weapon we switched to, if it's reloadable
                                if ((newwep.spawnflags & WEP_FLAG_RELOADABLE) && newwep.reloading_ammo)  // prevent accessing undefined cvars
                                {
-                                       actor.clip_load = actor.(weapon_load[PS(actor).m_switchweapon.m_id]);
-                                       actor.clip_size = newwep.reloading_ammo;
+                                       this.clip_load = this.(weapon_load[this.m_switchweapon.m_id]);
+                                       this.clip_size = newwep.reloading_ammo;
                                }
                                else
                                {
-                                       actor.clip_load = actor.clip_size = 0;
+                                       this.clip_load = this.clip_size = 0;
                                }
 
                                weapon_thinkf(actor, weaponentity, WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
@@ -498,17 +504,17 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        case WS_DROP:
                        {
                                // in dropping phase we can switch at any time
-                               PS(actor).m_switchingweapon = PS(actor).m_switchweapon;
+                               this.m_switchingweapon = this.m_switchweapon;
                                break;
                        }
                        case WS_READY:
                        {
                                // start switching!
-                               PS(actor).m_switchingweapon = PS(actor).m_switchweapon;
-                               entity oldwep = PS(actor).m_weapon;
+                               this.m_switchingweapon = this.m_switchweapon;
+                               entity oldwep = this.m_weapon;
 
                                // set up weapon switch think in the future, and start drop anim
-                               if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + actor.weapon_frametime * 0.5)
+                               if (INDEPENDENT_ATTACK_FINISHED || ATTACK_FINISHED(actor, weaponslot(weaponentity)) <= time + this.weapon_frametime * 0.5)
                                {
                                        sound(actor, CH_WEAPON_SINGLE, SND_WEAPON_SWITCH, VOL_BASE, ATTN_NORM);
                                        this.state = WS_DROP;
@@ -523,7 +529,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        // if (actor.button0)
        //      print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(actor, slot)), " >= ", ftos(this.weapon_nextthink), "\n");
 
-       Weapon w = PS(actor).m_weapon;
+       Weapon w = this.m_weapon;
 
        // call the think code which may fire the weapon
        // and do so multiple times to resolve framerate dependency issues if the
@@ -532,7 +538,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
        {
                if (w != WEP_Null && !(actor.weapons & WepSet_FromWeapon(w)))
                {
-                       if (PS(actor).m_weapon == PS(actor).m_switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
+                       if (this.m_weapon == this.m_switchweapon) W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
                        w = WEP_Null;
                }
 
@@ -550,11 +556,11 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        }
                        else
                        {
-                               if (key_pressed && PS(actor).m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
-                                       W_SwitchWeapon(actor, WEP_HOOK);
+                               if (key_pressed && this.m_switchweapon != WEP_HOOK && !actor.hook_switchweapon)
+                                       W_SwitchWeapon(actor, WEP_HOOK, weaponentity);
                                actor.hook_switchweapon = key_pressed;
                                Weapon h = WEP_HOOK;
-                               block_weapon = (PS(actor).m_weapon == h && (PHYS_INPUT_BUTTON_ATCK(actor) || key_pressed));
+                               block_weapon = (this.m_weapon == h && (PHYS_INPUT_BUTTON_ATCK(actor) || key_pressed));
                                h.wr_think(h, actor, weaponentity, block_weapon ? 1 : 0);
                        }
                }
@@ -565,7 +571,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
 
                if (!block_weapon)
                {
-            Weapon e = PS(actor).m_weapon;
+            Weapon e = this.m_weapon;
             TC(Weapon, e);
                        if (w != WEP_Null)
                        {
@@ -577,14 +583,14 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
                        }
                }
 
-               if (time + actor.weapon_frametime * 0.5 >= this.weapon_nextthink)
+               if (time + this.weapon_frametime * 0.5 >= this.weapon_nextthink)
                {
                        if (this.weapon_think)
                        {
                                v_forward = fo;
                                v_right = ri;
                                v_up = up;
-                               Weapon wpn = PS(actor).m_weapon;
+                               Weapon wpn = this.m_weapon;
                                this.weapon_think(wpn, actor, weaponentity,
                                        PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
                        }
@@ -626,17 +632,18 @@ void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector
        }
 }
 
-void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use)
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity)
 {
-       if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor)) return;
-
+       if (MUTATOR_CALLHOOK(W_DecreaseAmmo, actor, actor.(weaponentity))) return;
        if ((actor.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) return;
 
+       entity w_ent = actor.(weaponentity);
+
        // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if (wep.reloading_ammo)
        {
-               actor.clip_load -= ammo_use;
-               actor.(weapon_load[PS(actor).m_weapon.m_id]) = actor.clip_load;
+               w_ent.clip_load -= ammo_use;
+               w_ent.(weapon_load[w_ent.m_weapon.m_id]) = w_ent.clip_load;
        }
        else if (wep.ammo_field != ammo_none)
        {
@@ -666,29 +673,31 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
 {
        // finish the reloading process, and do the ammo transfer
 
-       actor.clip_load = actor.old_clip_load;  // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       entity w_ent = actor.(weaponentity);
+       Weapon wpn = w_ent.m_weapon;
+
+       w_ent.clip_load = w_ent.old_clip_load;  // restore the ammo counter, in case we still had ammo in the weapon before reloading
 
        // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
-       if (!actor.reload_ammo_min || actor.items & IT_UNLIMITED_WEAPON_AMMO || actor.ammo_field == ammo_none)
+       if (!w_ent.reload_ammo_min || (actor.items & IT_UNLIMITED_WEAPON_AMMO) || wpn.ammo_field == ammo_none)
        {
-               actor.clip_load = actor.reload_ammo_amount;
+               w_ent.clip_load = w_ent.reload_ammo_amount;
        }
        else
        {
                // make sure we don't add more ammo than we have
-               float load = min(actor.reload_ammo_amount - actor.clip_load, actor.(actor.ammo_field));
-               actor.clip_load += load;
-               actor.(actor.ammo_field) -= load;
+               float load = min(w_ent.reload_ammo_amount - w_ent.clip_load, actor.(wpn.ammo_field));
+               w_ent.clip_load += load;
+               actor.(wpn.ammo_field) -= load;
        }
-       actor.(weapon_load[PS(actor).m_weapon.m_id]) = actor.clip_load;
+       w_ent.(weapon_load[w_ent.m_weapon.m_id]) = w_ent.clip_load;
 
        // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
        // so your weapon is disabled for a few seconds without reason
 
-       // ATTACK_FINISHED(actor, slot) -= actor.reload_time - 1;
+       // ATTACK_FINISHED(actor, slot) -= w_ent.reload_time - 1;
 
-       Weapon wpn = Weapons_from(PS(actor).m_weapon.m_id);
        w_ready(wpn, actor, weaponentity, PHYS_INPUT_BUTTON_ATCK(actor) | (PHYS_INPUT_BUTTON_ATCK2(actor) << 1));
 }
 
@@ -696,13 +705,14 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
 {
     TC(Sound, sent_sound);
        // set global values to work with
-       Weapon e = PS(actor).m_weapon;
+       entity this = actor.(weaponentity);
+       Weapon e = this.m_weapon;
 
        if (MUTATOR_CALLHOOK(W_Reload, actor)) return;
 
-       actor.reload_ammo_min = sent_ammo_min;
-       actor.reload_ammo_amount = e.reloading_ammo;
-       actor.reload_time = e.reloading_time;
+       this.reload_ammo_min = sent_ammo_min;
+       this.reload_ammo_amount = e.reloading_ammo;
+       this.reload_time = e.reloading_time;
        if (actor.reload_sound) strunzone(actor.reload_sound);
        actor.reload_sound = strzone(Sound_fixpath(sent_sound));
 
@@ -715,37 +725,35 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
        }
 
        // return if reloading is disabled for this weapon
-       if (!actor.reload_ammo_amount) return;
+       if (!this.reload_ammo_amount) return;
 
        // our weapon is fully loaded, no need to reload
-       if (actor.clip_load >= actor.reload_ammo_amount) return;
+       if (this.clip_load >= this.reload_ammo_amount) return;
 
        // no ammo, so nothing to load
-       if (actor.ammo_field != ammo_none)
+       if (e.ammo_field != ammo_none)
        {
-               if (!actor.(actor.ammo_field) && actor.reload_ammo_min)
+               if (!actor.(e.ammo_field) && this.reload_ammo_min)
                {
                        if (!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
                        {
                                if (IS_REAL_CLIENT(actor) && actor.reload_complain < time)
                                {
                                        play2(actor, SND(UNAVAILABLE));
-                                       sprint(actor, strcat("You don't have enough ammo to reload the ^2", PS(actor).m_weapon.m_name, "\n"));
+                                       sprint(actor, strcat("You don't have enough ammo to reload the ^2", this.m_weapon.m_name, "\n"));
                                        actor.reload_complain = time + 1;
                                }
                                // switch away if the amount of ammo is not enough to keep using this weapon
-                               Weapon w = PS(actor).m_weapon;
-                               if (!(w.wr_checkammo1(w, actor) + w.wr_checkammo2(w, actor)))
+                               if (!(e.wr_checkammo1(e, actor, weaponentity) + e.wr_checkammo2(e, actor, weaponentity)))
                                {
-                                       actor.clip_load = -1;  // reload later
-                                       W_SwitchToOtherWeapon(actor);
+                                       this.clip_load = -1;  // reload later
+                                       W_SwitchToOtherWeapon(actor, weaponentity);
                                }
                                return;
                        }
                }
        }
 
-       entity this = actor.(weaponentity);
        if (this)
        {
                if (this.wframe == WFRAME_RELOAD) return;
@@ -762,18 +770,18 @@ void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sen
        // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
        // so your weapon is disabled for a few seconds without reason
 
-       // ATTACK_FINISHED(actor, slot) = max(time, ATTACK_FINISHED(actor, slot)) + actor.reload_time + 1;
+       // ATTACK_FINISHED(actor, slot) = max(time, ATTACK_FINISHED(actor, slot)) + this.reload_time + 1;
 
-       weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, actor.reload_time, W_ReloadedAndReady);
+       weapon_thinkf(actor, weaponentity, WFRAME_RELOAD, this.reload_time, W_ReloadedAndReady);
 
-       if (actor.clip_load < 0) actor.clip_load = 0;
-       actor.old_clip_load = actor.clip_load;
-       actor.clip_load = actor.(weapon_load[PS(actor).m_weapon.m_id]) = -1;
+       if (this.clip_load < 0) this.clip_load = 0;
+       this.old_clip_load = this.clip_load;
+       this.clip_load = this.(weapon_load[this.m_weapon.m_id]) = -1;
 }
 
-void W_DropEvent(.void(Weapon, entity actor) event, entity player, float weapon_type, entity weapon_item)
+void W_DropEvent(.void(Weapon, entity actor, .entity) event, entity player, float weapon_type, entity weapon_item, .entity weaponentity)
 {
        Weapon w = Weapons_from(weapon_type);
        weapon_dropevent_item = weapon_item;
-       w.event(w, player);
+       w.event(w, player, weaponentity);
 }
index b7ca597046fea210e290d2a00af5b10ef6a3367b..2fb0f9956833236250c0266fc70b91a2b412d21a 100644 (file)
@@ -4,6 +4,8 @@ float internalteam;
 float weaponswapping;
 entity weapon_dropevent_item;
 
+..entity weaponentity_fld;
+
 void CL_SpawnWeaponentity(entity e, .entity weaponentity);
 
 vector CL_Weapon_GetShotOrg(float wpn);
@@ -12,9 +14,9 @@ bool forbidWeaponUse(entity player);
 
 void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector offset);
 
-void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use);
+void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use, .entity weaponentity);
 
-void W_DropEvent(.void(Weapon, entity actor) event, entity player, float weapon_type, entity weapon_item);
+void W_DropEvent(.void(Weapon, entity actor, .entity) event, entity player, float weapon_type, entity weapon_item, .entity weaponentity);
 
 void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sent_sound);