]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/weapons/weapon/arc.qc
Merge branch 'master' into Mario/weaponarena_available
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapon / arc.qc
index 88ba1c768c63cacf23e4ac0524f8dbb181ea13e6..6efb21495bbaed25831066aba3eddc9c91c24c18 100644 (file)
@@ -1,151 +1,8 @@
 #include "arc.qh"
-#ifndef IMPLEMENTATION
-CLASS(Arc, Weapon)
-/* ammotype  */ ATTRIB(Arc, ammo_field, .int, ammo_cells);
-/* impulse   */ ATTRIB(Arc, impulse, int, 3);
-/* flags     */ ATTRIB(Arc, spawnflags, int, WEP_FLAG_NORMAL);
-/* rating    */ ATTRIB(Arc, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH);
-/* color     */ ATTRIB(Arc, wpcolor, vector, '1 1 1');
-/* modelname */ ATTRIB(Arc, mdl, string, "arc");
-#ifdef GAMEQC
-/* model     */ ATTRIB(Arc, m_model, Model, MDL_ARC_ITEM);
-#endif
-/* crosshair */ ATTRIB(Arc, w_crosshair, string, "gfx/crosshairhlac");
-/* crosshair */ ATTRIB(Arc, w_crosshair_size, float, 0.7);
-/* wepimg    */ ATTRIB(Arc, model2, string, "weaponarc");
-/* refname   */ ATTRIB(Arc, netname, string, "arc");
-/* wepname   */ ATTRIB(Arc, m_name, string, _("Arc"));
-
-#define X(BEGIN, P, END, class, prefix) \
-       BEGIN(class) \
-               P(class, prefix, bolt, float, NONE) \
-               P(class, prefix, bolt_ammo, float, NONE) \
-        P(class, prefix, bolt_damageforcescale, float, NONE) \
-        P(class, prefix, bolt_damage, float, NONE) \
-        P(class, prefix, bolt_edgedamage, float, NONE) \
-        P(class, prefix, bolt_force, float, NONE) \
-        P(class, prefix, bolt_health, float, NONE) \
-        P(class, prefix, bolt_lifetime, float, NONE) \
-        P(class, prefix, bolt_radius, float, NONE) \
-        P(class, prefix, bolt_refire, float, NONE) \
-        P(class, prefix, bolt_speed, float, NONE) \
-        P(class, prefix, bolt_spread, float, NONE) \
-               P(class, prefix, beam_ammo, float, NONE) \
-        P(class, prefix, beam_animtime, float, NONE) \
-        P(class, prefix, beam_botaimlifetime, float, NONE) \
-        P(class, prefix, beam_botaimspeed, float, NONE) \
-        P(class, prefix, beam_damage, float, NONE) \
-        P(class, prefix, beam_degreespersegment, float, NONE) \
-        P(class, prefix, beam_distancepersegment, float, NONE) \
-        P(class, prefix, beam_falloff_halflifedist, float, NONE) \
-        P(class, prefix, beam_falloff_maxdist, float, NONE) \
-        P(class, prefix, beam_falloff_mindist, float, NONE) \
-        P(class, prefix, beam_force, float, NONE) \
-        P(class, prefix, beam_healing_amax, float, NONE) \
-        P(class, prefix, beam_healing_aps, float, NONE) \
-        P(class, prefix, beam_healing_hmax, float, NONE) \
-        P(class, prefix, beam_healing_hps, float, NONE) \
-        P(class, prefix, beam_heat, float, NONE) /* heat increase per second (primary) */ \
-        P(class, prefix, beam_maxangle, float, NONE) \
-        P(class, prefix, beam_nonplayerdamage, float, NONE) \
-        P(class, prefix, beam_range, float, NONE) \
-        P(class, prefix, beam_refire, float, NONE) \
-        P(class, prefix, beam_returnspeed, float, NONE) \
-        P(class, prefix, beam_tightness, float, NONE) \
-        P(class, prefix, burst_ammo, float, NONE) \
-        P(class, prefix, burst_damage, float, NONE) \
-        P(class, prefix, burst_healing_aps, float, NONE) \
-        P(class, prefix, burst_healing_hps, float, NONE) \
-        P(class, prefix, burst_heat, float, NONE) /* heat increase per second (secondary) */ \
-        P(class, prefix, cooldown, float, NONE) /* heat decrease per second when resting */ \
-        P(class, prefix, cooldown_release, float, NONE) /* delay weapon re-use when releasing button */ \
-        P(class, prefix, overheat_max, float, NONE) /* maximum heat before jamming */ \
-        P(class, prefix, overheat_min, float, NONE) /* minimum heat to wait for cooldown */ \
-        P(class, prefix, switchdelay_drop, float, NONE) \
-        P(class, prefix, switchdelay_raise, float, NONE) \
-        P(class, prefix, weaponreplace, string, NONE) \
-        P(class, prefix, weaponstartoverride, float, NONE) \
-        P(class, prefix, weaponstart, float, NONE) \
-        P(class, prefix, weaponthrowable, float, NONE) \
-    END()
-    W_PROPS(X, Arc, arc)
-#undef X
-
-ENDCLASS(Arc)
-REGISTER_WEAPON(ARC, arc, NEW(Arc));
-
-
-#ifdef GAMEQC
-const float ARC_MAX_SEGMENTS = 20;
-vector arc_shotorigin[4];
-.vector beam_start;
-.vector beam_dir;
-.vector beam_wantdir;
-.int beam_type;
-
-const int ARC_BT_MISS =        0x00;
-const int ARC_BT_WALL =        0x01;
-const int ARC_BT_HEAL =        0x02;
-const int ARC_BT_HIT =         0x03;
-const int ARC_BT_BURST_MISS =  0x10;
-const int ARC_BT_BURST_WALL =  0x11;
-const int ARC_BT_BURST_HEAL =  0x12;
-const int ARC_BT_BURST_HIT =   0x13;
-const int ARC_BT_BURSTMASK =   0x10;
-
-const int ARC_SF_SETTINGS =    BIT(0);
-const int ARC_SF_START =       BIT(1);
-const int ARC_SF_WANTDIR =     BIT(2);
-const int ARC_SF_BEAMDIR =     BIT(3);
-const int ARC_SF_BEAMTYPE =    BIT(4);
-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; // for better animation control
-.float beam_prev;
-.float beam_initialized;
-.float beam_bursting;
-.float beam_teleporttime;
-.float beam_heat; // (beam) amount of heat produced
-.float arc_overheat; // (dropped arc/player) time during which it's too hot
-.float arc_cooldown; // (dropped arc/player) cooling speed
-.float arc_heat_percent = _STAT(ARC_HEAT);
-.float arc_smoke_sound;
-#endif
-#ifdef CSQC
 
-.vector beam_color;
-.float beam_alpha;
-.float beam_thickness;
-.entity beam_traileffect;
-.entity beam_hiteffect;
-.float beam_hitlight[4]; // 0: radius, 123: rgb
-.entity beam_muzzleeffect;
-.float beam_muzzlelight[4]; // 0: radius, 123: rgb
-.string beam_image;
-
-.entity beam_muzzleentity;
-
-.float beam_degreespersegment;
-.float beam_distancepersegment;
-.float beam_usevieworigin;
-.float beam_initialized;
-.float beam_maxangle;
-.float beam_range;
-.float beam_returnspeed;
-.float beam_tightness;
-.vector beam_shotorigin;
-
-entity Draw_ArcBeam_callback_entity;
-float Draw_ArcBeam_callback_last_thickness;
-vector Draw_ArcBeam_callback_last_top; // NOTE: in same coordinate system as player.
-vector Draw_ArcBeam_callback_last_bottom; // NOTE: in same coordinate system as player.
-#endif
-#endif
-#ifdef IMPLEMENTATION
 #ifdef SVQC
-spawnfunc(weapon_arc) { weapon_defaultspawnfunc(this, WEP_ARC); }
+#include <common/gamemodes/gamemode/onslaught/sv_onslaught.qh>
+#include <common/gamemodes/gamemode/onslaught/sv_generator.qh>
 
 bool W_Arc_Beam_Send(entity this, entity to, int sf)
 {
@@ -175,21 +32,17 @@ bool W_Arc_Beam_Send(entity this, entity to, int sf)
        }
        if(sf & ARC_SF_START) // starting location
        {
-               WriteCoord(MSG_ENTITY, this.beam_start.x);
-               WriteCoord(MSG_ENTITY, this.beam_start.y);
-               WriteCoord(MSG_ENTITY, this.beam_start.z);
+               WriteVector(MSG_ENTITY, this.beam_start);
        }
        if(sf & ARC_SF_WANTDIR) // want/aim direction
        {
-               WriteCoord(MSG_ENTITY, this.beam_wantdir.x);
-               WriteCoord(MSG_ENTITY, this.beam_wantdir.y);
-               WriteCoord(MSG_ENTITY, this.beam_wantdir.z);
+               WriteVector(MSG_ENTITY, this.beam_wantdir);
        }
        if(sf & ARC_SF_BEAMDIR) // beam direction
        {
-               WriteCoord(MSG_ENTITY, this.beam_dir.x);
-               WriteCoord(MSG_ENTITY, this.beam_dir.y);
-               WriteCoord(MSG_ENTITY, this.beam_dir.z);
+               WriteAngle(MSG_ENTITY, this.beam_dir.x);
+               WriteAngle(MSG_ENTITY, this.beam_dir.y);
+               WriteAngle(MSG_ENTITY, this.beam_dir.z);
        }
        if(sf & ARC_SF_BEAMTYPE) // beam type
        {
@@ -232,14 +85,14 @@ float Arc_GetHeat_Percent(entity player, .entity weaponentity)
 }
 void Arc_Player_SetHeat(entity player, .entity weaponentity)
 {
-       player.arc_heat_percent = Arc_GetHeat_Percent(player, weaponentity);
+       player.(weaponentity).arc_heat_percent = Arc_GetHeat_Percent(player, weaponentity);
        //dprint("Heat: ",ftos(player.arc_heat_percent*100),"%\n");
 }
 
 void W_Arc_Bolt_Explode(entity this, entity directhitentity)
 {
        this.event_damage = func_null;
-       RadiusDamage(this, this.realowner, WEP_CVAR(arc, bolt_damage), WEP_CVAR(arc, bolt_edgedamage), WEP_CVAR(arc, bolt_radius), NULL, NULL, WEP_CVAR(arc, bolt_force), this.projectiledeathtype, directhitentity);
+       RadiusDamage(this, this.realowner, WEP_CVAR(arc, bolt_damage), WEP_CVAR(arc, bolt_edgedamage), WEP_CVAR(arc, bolt_radius), NULL, NULL, WEP_CVAR(arc, bolt_force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
 
        delete(this);
 }
@@ -249,18 +102,18 @@ void W_Arc_Bolt_Explode_use(entity this, entity actor, entity trigger)
        W_Arc_Bolt_Explode(this, trigger);
 }
 
-void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
-       if(this.health <= 0)
+       if(GetResource(this, RES_HEALTH) <= 0)
                return;
 
        if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1))
                return; // g_projectiles_damage says to halt
 
-       this.health = this.health - damage;
+       TakeResource(this, RES_HEALTH, damage);
        this.angles = vectoangles(this.velocity);
 
-       if(this.health <= 0)
+       if(GetResource(this, RES_HEALTH) <= 0)
                W_PrepareExplosionByDamage(this, attacker, getthink(this));
 }
 
@@ -276,7 +129,7 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
 
        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));
+       W_SetupShot(actor, weaponentity, false, 2, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR(arc, bolt_damage), WEP_ARC.m_id | HITTYPE_SECONDARY);
 
        Send_Effect(EFFECT_ARC_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
 
@@ -287,7 +140,7 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        missile.bot_dodgerating = WEP_CVAR(arc, bolt_damage);
 
        missile.takedamage = DAMAGE_YES;
-       missile.health = WEP_CVAR(arc, bolt_health);
+       SetResourceExplicit(missile, RES_HEALTH, WEP_CVAR(arc, bolt_health));
        missile.damageforcescale = WEP_CVAR(arc, bolt_damageforcescale);
        missile.event_damage = W_Arc_Bolt_Damage;
        missile.damagedbycontents = true;
@@ -299,6 +152,7 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        missile.nextthink = time + WEP_CVAR(arc, bolt_lifetime);
        PROJECTILE_MAKETRIGGER(missile);
        missile.projectiledeathtype = WEP_ARC.m_id | HITTYPE_SECONDARY;
+       missile.weaponentity_fld = weaponentity;
        setorigin(missile, w_shotorg);
        setsize(missile, '0 0 0', '0 0 0');
 
@@ -317,14 +171,15 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
 void W_Arc_Beam_Think(entity this)
 {
        .entity weaponentity = this.weaponentity_fld;
-       if(this != this.owner.(weaponentity).arc_beam)
+       entity own = this.owner;
+       if(this != own.(weaponentity).arc_beam)
        {
                delete(this);
                return;
        }
 
        float burst = 0;
-       if( (PHYS_INPUT_BUTTON_ATCK2(this.owner) && !WEP_CVAR(arc, bolt)) || this.beam_bursting)
+       if( (PHYS_INPUT_BUTTON_ATCK2(own) && !WEP_CVAR(arc, bolt)) || this.beam_bursting)
        {
                if(!this.beam_bursting)
                        this.beam_bursting = true;
@@ -334,19 +189,17 @@ void W_Arc_Beam_Think(entity this)
        Weapon thiswep = WEP_ARC;
 
        if(
-               !IS_PLAYER(this.owner)
-               ||
-               (this.owner.(thiswep.ammo_field) <= 0 && !(this.owner.items & IT_UNLIMITED_WEAPON_AMMO))
+               !IS_PLAYER(own)
                ||
-               IS_DEAD(this.owner)
+               IS_DEAD(own)
                ||
-               forbidWeaponUse(this.owner)
+               !weapon_prepareattack_check(thiswep, own, weaponentity, this.beam_bursting, -1)
                ||
-               this.owner.(weaponentity).m_switchweapon != WEP_ARC
+               own.(weaponentity).m_switchweapon != WEP_ARC
                ||
-               (!PHYS_INPUT_BUTTON_ATCK(this.owner) && !burst )
+               (!PHYS_INPUT_BUTTON_ATCK(own) && !burst )
                ||
-               this.owner.vehicle
+               own.vehicle
                ||
                (WEP_CVAR(arc, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(arc, overheat_max))
        )
@@ -366,8 +219,8 @@ void W_Arc_Beam_Think(entity this)
                        if ( cooldown_speed )
                        {
                                if ( WEP_CVAR(arc, cooldown_release) || (WEP_CVAR(arc, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(arc, overheat_max)) )
-                                       this.owner.arc_overheat = time + this.beam_heat / cooldown_speed;
-                               this.owner.arc_cooldown = cooldown_speed;
+                                       own.arc_overheat = time + this.beam_heat / cooldown_speed;
+                               own.arc_cooldown = cooldown_speed;
                        }
 
                        if ( WEP_CVAR(arc, overheat_max) > 0 && this.beam_heat >= WEP_CVAR(arc, overheat_max) )
@@ -378,22 +231,20 @@ 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, weaponentity) && !w.wr_checkammo2(w, own, weaponentity))
-               if(!(own.items & IT_UNLIMITED_WEAPON_AMMO))
+               if(this == own.(weaponentity).arc_beam) { own.(weaponentity).arc_beam = NULL; }
+               if(!thiswep.wr_checkammo1(thiswep, own, weaponentity) && !(own.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
                        W_SwitchToOtherWeapon(own, weaponentity);
                }
+               own.(weaponentity).arc_BUTTON_ATCK_prev = false; // allow switching weapons
                delete(this);
                return;
        }
 
        // decrease ammo
        float coefficient = frametime;
-       if(!(this.owner.items & IT_UNLIMITED_WEAPON_AMMO))
+       if(!(own.items & IT_UNLIMITED_WEAPON_AMMO))
        {
                float rootammo;
                if(burst)
@@ -403,28 +254,29 @@ void W_Arc_Beam_Think(entity this)
 
                if(rootammo)
                {
-                       coefficient = min(coefficient, this.owner.(thiswep.ammo_field) / rootammo);
-                       this.owner.(thiswep.ammo_field) = max(0, this.owner.(thiswep.ammo_field) - (rootammo * frametime));
+                       coefficient = min(coefficient, GetResource(own, thiswep.ammo_type) / rootammo);
+                       SetResource(own, thiswep.ammo_type, max(0, GetResource(own, thiswep.ammo_type) - (rootammo * frametime)));
                }
        }
        float heat_speed = burst ? WEP_CVAR(arc, burst_heat) : WEP_CVAR(arc, beam_heat);
        this.beam_heat = min( WEP_CVAR(arc, overheat_max), this.beam_heat + heat_speed*frametime );
 
-       makevectors(this.owner.v_angle);
+       makevectors(own.v_angle);
 
        W_SetupShot_Range(
-               this.owner,
-               weaponentity, // TODO
+               own,
+               weaponentity,
                true,
                0,
                SND_Null,
                0,
                WEP_CVAR(arc, beam_damage) * coefficient,
-               WEP_CVAR(arc, beam_range)
+               WEP_CVAR(arc, beam_range),
+               thiswep.m_id
        );
 
        // After teleport, "lock" the beam until the teleport is confirmed.
-       if (time < this.beam_teleporttime + ANTILAG_LATENCY(this.owner)) {
+       if (time < this.beam_teleporttime + ANTILAG_LATENCY(own)) {
                w_shotdir = this.beam_dir;
        }
 
@@ -470,7 +322,10 @@ void W_Arc_Beam_Think(entity this)
                                (1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)),
                                min(WEP_CVAR(arc, beam_maxangle) / angle, 1)
                        );
-                       this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
+                       if(vdist(this.beam_dir - w_shotdir, <, 0.01))
+                               this.beam_dir = w_shotdir;
+                       else
+                               this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
                }
                else
                {
@@ -480,7 +335,10 @@ void W_Arc_Beam_Think(entity this)
                                (1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)),
                                1
                        );
-                       this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
+                       if(vdist(this.beam_dir - w_shotdir, <, 0.01))
+                               this.beam_dir = w_shotdir;
+                       else
+                               this.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (this.beam_dir * blendfactor));
                }
 
                // network information: beam direction
@@ -539,12 +397,12 @@ void W_Arc_Beam_Think(entity this)
                vector new_dir = normalize(new_origin - last_origin);
 
                WarpZone_traceline_antilag(
-                       this.owner,
+                       own,
                        last_origin,
                        new_origin,
                        MOVE_NORMAL,
-                       this.owner,
-                       ANTILAG_LATENCY(this.owner)
+                       own,
+                       ANTILAG_LATENCY(own)
                );
 
                // Do all the transforms for warpzones right now, as we already
@@ -556,7 +414,7 @@ void W_Arc_Beam_Think(entity this)
                beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
                new_dir = WarpZone_TransformVelocity(WarpZone_trace_transform, new_dir);
 
-               float is_player = (
+               bool is_player = (
                        IS_PLAYER(trace_ent)
                        ||
                        trace_ent.classname == "body"
@@ -564,65 +422,42 @@ void W_Arc_Beam_Think(entity this)
                        IS_MONSTER(trace_ent)
                );
 
-               if(trace_ent && trace_ent.takedamage && (is_player || WEP_CVAR(arc, beam_nonplayerdamage)))
+               if(trace_ent)
                {
-                       // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
-                       // NO. trace_endpos should be just fine. If not,
-                       // that's an engine bug that needs proper debugging.
-                       vector hitorigin = trace_endpos;
-
-                       float falloff = ExponentialFalloff(
-                               WEP_CVAR(arc, beam_falloff_mindist),
-                               WEP_CVAR(arc, beam_falloff_maxdist),
-                               WEP_CVAR(arc, beam_falloff_halflifedist),
-                               vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, hitorigin) - w_shotorg)
-                       );
-
-                       if(is_player && SAME_TEAM(this.owner, trace_ent))
+                       if(SAME_TEAM(own, trace_ent))
                        {
-                               float roothealth, rootarmor;
-                               if(burst)
-                               {
-                                       roothealth = WEP_CVAR(arc, burst_healing_hps);
-                                       rootarmor = WEP_CVAR(arc, burst_healing_aps);
-                               }
-                               else
+                               float roothealth = ((burst) ? WEP_CVAR(arc, burst_healing_hps) : WEP_CVAR(arc, beam_healing_hps));
+                               float rootarmor = ((burst) ? WEP_CVAR(arc, burst_healing_aps) : WEP_CVAR(arc, beam_healing_aps));
+                               float hplimit = ((IS_PLAYER(trace_ent)) ? WEP_CVAR(arc, beam_healing_hmax) : RES_LIMIT_NONE);
+                               Heal(trace_ent, own, (roothealth * coefficient), hplimit);
+                               if(IS_PLAYER(trace_ent) && rootarmor)
                                {
-                                       roothealth = WEP_CVAR(arc, beam_healing_hps);
-                                       rootarmor = WEP_CVAR(arc, beam_healing_aps);
+                                       if(GetResource(trace_ent, RES_ARMOR) <= WEP_CVAR(arc, beam_healing_amax))
+                                       {
+                                               GiveResourceWithLimit(trace_ent, RES_ARMOR, (rootarmor * coefficient), WEP_CVAR(arc, beam_healing_amax));
+                                               trace_ent.pauserotarmor_finished = max(
+                                                       trace_ent.pauserotarmor_finished,
+                                                       time + autocvar_g_balance_pause_armor_rot
+                                               );
+                                       }
                                }
-
-                               if(trace_ent.health <= WEP_CVAR(arc, beam_healing_hmax) && roothealth)
-                               {
-                                       trace_ent.health = min(
-                                               trace_ent.health + (roothealth * coefficient),
-                                               WEP_CVAR(arc, beam_healing_hmax)
-                                       );
-                               }
-                               if(trace_ent.armorvalue <= WEP_CVAR(arc, beam_healing_amax) && rootarmor)
-                               {
-                                       trace_ent.armorvalue = min(
-                                               trace_ent.armorvalue + (rootarmor * coefficient),
-                                               WEP_CVAR(arc, beam_healing_amax)
-                                       );
-                               }
-
-                               // stop rot, set visual effect
                                if(roothealth || rootarmor)
-                               {
-                                       trace_ent.pauserothealth_finished = max(
-                                               trace_ent.pauserothealth_finished,
-                                               time + autocvar_g_balance_pause_health_rot
-                                       );
-                                       trace_ent.pauserotarmor_finished = max(
-                                               trace_ent.pauserotarmor_finished,
-                                               time + autocvar_g_balance_pause_armor_rot
-                                       );
                                        new_beam_type = ARC_BT_HEAL;
-                               }
                        }
-                       else
+                       else if(trace_ent.takedamage && (is_player || WEP_CVAR(arc, beam_nonplayerdamage)))
                        {
+                               // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
+                               // NO. trace_endpos should be just fine. If not,
+                               // that's an engine bug that needs proper debugging.
+                               vector hitorigin = trace_endpos;
+
+                               float falloff = ExponentialFalloff(
+                                       WEP_CVAR(arc, beam_falloff_mindist),
+                                       WEP_CVAR(arc, beam_falloff_maxdist),
+                                       WEP_CVAR(arc, beam_falloff_halflifedist),
+                                       vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, hitorigin) - w_shotorg)
+                               );
+
                                float rootdamage;
                                if(is_player)
                                {
@@ -634,11 +469,11 @@ void W_Arc_Beam_Think(entity this)
                                else
                                        { rootdamage = WEP_CVAR(arc, beam_nonplayerdamage); }
 
-                               if(accuracy_isgooddamage(this.owner, trace_ent))
+                               if(accuracy_isgooddamage(own, trace_ent))
                                {
                                        accuracy_add(
-                                               this.owner,
-                                               WEP_ARC.m_id,
+                                               own,
+                                               WEP_ARC,
                                                0,
                                                rootdamage * coefficient * falloff
                                        );
@@ -646,10 +481,11 @@ void W_Arc_Beam_Think(entity this)
 
                                Damage(
                                        trace_ent,
-                                       this.owner,
-                                       this.owner,
+                                       own,
+                                       own,
                                        rootdamage * coefficient * falloff,
                                        WEP_ARC.m_id,
+                                       weaponentity,
                                        hitorigin,
                                        WEP_CVAR(arc, beam_force) * new_dir * coefficient * falloff
                                );
@@ -678,7 +514,7 @@ void W_Arc_Beam_Think(entity this)
                this.beam_type = new_beam_type;
        }
 
-       this.owner.(weaponentity).beam_prev = time;
+       own.(weaponentity).beam_prev = time;
        this.nextthink = time;
 }
 
@@ -703,17 +539,33 @@ void W_Arc_Beam(float burst, entity actor, .entity weaponentity)
 
        getthink(beam)(beam);
 }
-void Arc_Smoke(entity actor, .entity weaponentity)
+void W_Arc_Attack(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
+       if(!actor.(weaponentity).arc_beam || wasfreed(actor.(weaponentity).arc_beam))
+       {
+               w_ready(thiswep, actor, weaponentity, fire);
+               return;
+       }
+
+       // attack handled by the beam itself, this is just a loop to keep the attack happening!
+
+       // NOTE: arc doesn't use a refire
+       //ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(arc, refire) * W_WeaponRateFactor(actor);
+       actor.(weaponentity).wframe = WFRAME_FIRE1;
+       weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), W_Arc_Attack);
+}
+void Arc_Smoke(Weapon thiswep, entity actor, .entity weaponentity, int fire)
+{
+       // TODO: spamming this without checking any refires is asking for trouble!
        makevectors(actor.v_angle);
-       W_SetupShot_Range(actor,weaponentity,true,0,SND_Null,0,0,0);
+       W_SetupShot_Range(actor,weaponentity,false,0,SND_Null,0,0,0,thiswep.m_id); // TODO: probably doesn't need deathtype, since this is just a prefire effect
 
        vector smoke_origin = w_shotorg + actor.velocity*frametime;
        if ( actor.arc_overheat > time )
        {
-               if ( random() < actor.arc_heat_percent )
+               if ( random() < actor.(weaponentity).arc_heat_percent )
                        Send_Effect(EFFECT_ARC_SMOKE, smoke_origin, '0 0 0', 1 );
-               if ( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) )
+               if ( (fire & 1) || (fire & 2) )
                {
                        Send_Effect(EFFECT_ARC_OVERHEAT_FIRE, smoke_origin, w_shotdir, 1 );
                        if ( !actor.arc_smoke_sound )
@@ -732,7 +584,7 @@ void Arc_Smoke(entity actor, .entity weaponentity)
        }
 
        if (  actor.arc_smoke_sound && ( actor.arc_overheat <= time ||
-               !( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) ) ) || actor.(weaponentity).m_switchweapon != WEP_ARC )
+               !( PHYS_INPUT_BUTTON_ATCK(actor) || PHYS_INPUT_BUTTON_ATCK2(actor) ) ) || actor.(weaponentity).m_switchweapon != thiswep )
        {
                actor.arc_smoke_sound = 0;
                sound(actor, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
@@ -767,14 +619,14 @@ METHOD(Arc, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     Arc_Player_SetHeat(actor, weaponentity);
-    Arc_Smoke(actor, weaponentity);
+    Arc_Smoke(thiswep, actor, weaponentity, fire);
 
     bool beam_fire2 = ((fire & 2) && !WEP_CVAR(arc, bolt));
 
     if (time >= actor.arc_overheat)
     if ((fire & 1) || beam_fire2 || actor.(weaponentity).arc_beam.beam_bursting)
     {
-
+       #if 0
         if(actor.(weaponentity).arc_BUTTON_ATCK_prev)
         {
             #if 0
@@ -784,6 +636,7 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
             #endif
                 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), w_ready);
         }
+        #endif
 
         if((!actor.(weaponentity).arc_beam) || wasfreed(actor.(weaponentity).arc_beam))
         {
@@ -793,7 +646,8 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
 
                 if(!actor.(weaponentity).arc_BUTTON_ATCK_prev)
                 {
-                    weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
+                       actor.(weaponentity).wframe = WFRAME_FIRE1;
+                    weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR(arc, beam_animtime), W_Arc_Attack);
                     actor.(weaponentity).arc_BUTTON_ATCK_prev = true;
                 }
             }
@@ -803,7 +657,7 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
     }
     else if(fire & 2)
     {
-        if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(arc, bolt_refire)))
+        if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR(arc, bolt_refire)))
         {
             W_Arc_Attack_Bolt(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), w_ready);
@@ -812,10 +666,9 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
 
     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);
+        ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor(actor);
     }
     actor.(weaponentity).arc_BUTTON_ATCK_prev = false;
 
@@ -842,19 +695,19 @@ METHOD(Arc, wr_init, void(entity thiswep))
 }
 METHOD(Arc, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    return ((!WEP_CVAR(arc, beam_ammo)) || (actor.(thiswep.ammo_field) > 0));
+    return ((!WEP_CVAR(arc, beam_ammo)) || (GetResource(actor, thiswep.ammo_type) > 0));
 }
 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);
+        float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR(arc, bolt_ammo);
         ammo_amount += actor.(weaponentity).(weapon_load[WEP_ARC.m_id]) >= WEP_CVAR(arc, bolt_ammo);
         return ammo_amount;
     }
     else
         return WEP_CVAR(arc, overheat_max) > 0 &&
-            ((!WEP_CVAR(arc, burst_ammo)) || (actor.(thiswep.ammo_field) > 0));
+            ((!WEP_CVAR(arc, burst_ammo)) || (GetResource(actor, thiswep.ammo_type) > 0));
 }
 METHOD(Arc, wr_killmessage, Notification(entity thiswep))
 {
@@ -899,6 +752,9 @@ METHOD(Arc, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponent
 #endif
 #ifdef CSQC
 bool autocvar_cl_arcbeam_teamcolor = true;
+bool autocvar_cl_arcbeam_simple = true;
+
+.int beam_slot;
 
 METHOD(Arc, wr_impacteffect, void(entity thiswep, entity actor))
 {
@@ -949,32 +805,37 @@ void Draw_ArcBeam_callback(vector start, vector hit, vector end)
        vector last_top = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_top);
        vector last_bottom = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_bottom);
 
-       R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL); // DRAWFLAG_ADDITIVE
-       R_PolygonVertex(
-               top,
-               '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
-               beam.beam_color,
-               beam.beam_alpha
-       );
-       R_PolygonVertex(
-               last_top,
-               '0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
-               beam.beam_color,
-               beam.beam_alpha
-       );
-       R_PolygonVertex(
-               last_bottom,
-               '0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
-               beam.beam_color,
-               beam.beam_alpha
-       );
-       R_PolygonVertex(
-               bottom,
-               '0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
-               beam.beam_color,
-               beam.beam_alpha
-       );
-       R_EndPolygon();
+       if(autocvar_cl_arcbeam_simple)
+               Draw_CylindricLine(start, end, thickness, beam.beam_image, 0.25, -time * 3, beam.beam_color, beam.beam_alpha, DRAWFLAG_NORMAL, transformed_view_org);
+       else
+       {
+               R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL); // DRAWFLAG_ADDITIVE
+               R_PolygonVertex(
+                       top,
+                       '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
+                       beam.beam_color,
+                       beam.beam_alpha
+               );
+               R_PolygonVertex(
+                       last_top,
+                       '0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
+                       beam.beam_color,
+                       beam.beam_alpha
+               );
+               R_PolygonVertex(
+                       last_bottom,
+                       '0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
+                       beam.beam_color,
+                       beam.beam_alpha
+               );
+               R_PolygonVertex(
+                       bottom,
+                       '0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
+                       beam.beam_color,
+                       beam.beam_alpha
+               );
+               R_EndPolygon();
+       }
 
        // draw trailing particles
        // NOTES:
@@ -1031,17 +892,30 @@ void Draw_ArcBeam(entity this)
                // into a weapon system for client code.
 
                // find where we are aiming
-               makevectors(warpzone_save_view_angles);
+               makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
                vector forward = v_forward;
                vector right = v_right;
                vector up = v_up;
+               entity wepent = viewmodels[this.beam_slot];
+
+               if(autocvar_chase_active)
+                       this.beam_usevieworigin = 1;
+               else
+                       this.beam_usevieworigin = 2;
 
                // decide upon start position
                if(this.beam_usevieworigin == 2)
                        { start_pos = warpzone_save_view_origin; }
+               else if(csqcplayer)
+                       { start_pos = csqcplayer.origin + csqcplayer.view_ofs; }
                else
                        { start_pos = this.origin; }
 
+               int v_shot_idx;  // used later
+               (v_shot_idx = gettagindex(wepent, "shot")) || (v_shot_idx = gettagindex(wepent, "tag_shot"));
+               if(v_shot_idx && this.beam_usevieworigin == 2)
+                       start_pos = gettaginfo(wepent, v_shot_idx) - '0 0 2';
+
                // trace forward with an estimation
                WarpZone_TraceLine(
                        start_pos,
@@ -1058,9 +932,16 @@ void Draw_ArcBeam(entity this)
                        end_pos = start_pos + (forward * g_trueaim_minrange);
 
                // move shot origin to the actual gun muzzle origin
-               vector origin_offset =
-                         right * -this.beam_shotorigin.y
-                       + up * this.beam_shotorigin.z;
+               vector origin_offset = '0 0 0';
+               if(!v_shot_idx || this.beam_usevieworigin != 2)
+               {
+                       this.beam_shotorigin = wepent.movedir;
+                       origin_offset =
+                                right * -this.beam_shotorigin.y
+                               + up * this.beam_shotorigin.z;
+               }
+               else
+                       this.beam_shotorigin = '0 0 0';
 
                start_pos = start_pos + origin_offset;
 
@@ -1266,7 +1147,7 @@ void Draw_ArcBeam(entity this)
                        )
                );
        }
-       if(this.beam_muzzleeffect)
+       if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
        {
                pointparticles(
                        this.beam_muzzleeffect,
@@ -1307,18 +1188,20 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
        int slot = ReadByte();
        entity flash;
 
+       this.beam_slot = slot;
+
        if(isnew)
        {
                int gunalign = W_GunAlign(viewmodels[slot], STAT(GUNALIGN)) - 1;
 
-               this.beam_shotorigin = arc_shotorigin[gunalign];
+               this.beam_shotorigin = arc_shotorigin[gunalign]; // get a starting point
 
                // set other main attributes of the beam
                this.draw = Draw_ArcBeam;
                IL_PUSH(g_drawables, this);
                this.entremove = Remove_ArcBeam;
                this.move_time = time;
-               loopsound(this, CH_SHOTS_SINGLE, SND(ARC_LOOP), VOL_BASE, ATTEN_NORM);
+               loopsound(this, CH_SHOTS_SINGLE, SND_ARC_LOOP, VOL_BASE, ATTEN_NORM);
 
                flash = spawn();
                flash.owner = this;
@@ -1370,9 +1253,7 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
 
        if(sf & ARC_SF_START) // starting location
        {
-               this.origin_x = ReadCoord();
-               this.origin_y = ReadCoord();
-               this.origin_z = ReadCoord();
+               this.origin = ReadVector();
        }
        else if(this.beam_usevieworigin) // infer the location from player location
        {
@@ -1392,16 +1273,14 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
 
        if(sf & ARC_SF_WANTDIR) // want/aim direction
        {
-               this.v_angle_x = ReadCoord();
-               this.v_angle_y = ReadCoord();
-               this.v_angle_z = ReadCoord();
+               this.v_angle = ReadVector();
        }
 
        if(sf & ARC_SF_BEAMDIR) // beam direction
        {
-               this.angles_x = ReadCoord();
-               this.angles_y = ReadCoord();
-               this.angles_z = ReadCoord();
+               this.angles_x = ReadAngle();
+               this.angles_y = ReadAngle();
+               this.angles_z = ReadAngle();
        }
 
        if(sf & ARC_SF_BEAMTYPE) // beam type
@@ -1422,17 +1301,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
-                               if(this.beam_muzzleeffect)
+                               this.beam_image = "particles/lgbeam";
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1447,18 +1327,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; // (EFFECT_GRENADE_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null; // (EFFECT_GRENADE_MUZZLEFLASH);
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1473,18 +1353,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1499,18 +1379,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 0;
                                this.beam_hitlight[3] = 0;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 50;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 0;
                                this.beam_muzzlelight[3] = 0;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1525,18 +1405,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1551,18 +1431,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1577,18 +1457,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1603,18 +1483,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1631,18 +1511,18 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
                                this.beam_hitlight[1] = 1;
                                this.beam_hitlight[2] = 1;
                                this.beam_hitlight[3] = 1;
-                               this.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
+                               this.beam_muzzleeffect = EFFECT_Null;
                                this.beam_muzzlelight[0] = 0;
                                this.beam_muzzlelight[1] = 1;
                                this.beam_muzzlelight[2] = 1;
                                this.beam_muzzlelight[3] = 1;
                                this.beam_image = "particles/lgbeam";
-                               if(this.beam_muzzleeffect)
+                               if(this.beam_muzzleeffect && autocvar_r_drawviewmodel)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = this.beam_alpha;
                                        flash.colormod = this.beam_color;
-                                       flash.scale = 0.5;
+                                       flash.scale = 0.35;
                                }
                                break;
                        }
@@ -1657,4 +1537,3 @@ NET_HANDLE(ENT_CLIENT_ARC_BEAM, bool isnew)
 }
 
 #endif
-#endif