]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/weapons/weapon/arc.qc
Fix Arc bolts bouncing more times than they're supposed to, rename the bounce_damage...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapon / arc.qc
index 5f79c8ccfa58d622c4607dc5129e73783399b103..44fd539bebc5feca780e89e059f5a5f7de1c8461 100644 (file)
@@ -118,20 +118,28 @@ void W_Arc_Bolt_Damage(entity this, entity inflictor, entity attacker, float dam
 void W_Arc_Bolt_Touch(entity this, entity toucher)
 {
        PROJECTILE_TOUCH(this, toucher);
-       this.use(this, NULL, toucher);
+       if(this.cnt >= WEP_CVAR(arc, bolt_bounce_count) || !WEP_CVAR(arc, bolt_bounce_count) || toucher.takedamage == DAMAGE_AIM) {
+               this.use(this, NULL, toucher);
+       } else {
+               this.cnt++;
+               Send_Effect(EFFECT_BALL_SPARKS, this.origin, this.velocity, 1);
+               this.angles = vectoangles(this.velocity);
+               this.owner = NULL;
+               this.projectiledeathtype |= HITTYPE_BOUNCE;
+               if(WEP_CVAR(arc, bolt_bounce_explode))
+                       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, toucher);
+               if(this.cnt == 1 && WEP_CVAR(arc, bolt_bounce_lifetime))
+                       this.nextthink = time + WEP_CVAR(arc, bolt_bounce_lifetime);
+       }
 }
 
-void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
+void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity, int fire)
 {
-       entity missile;
-
-       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), WEP_ARC.m_id | HITTYPE_SECONDARY);
+       W_SetupShot(actor, weaponentity, false, 2, SND_ELECTRO_FIRE2, CH_WEAPON_A, WEP_CVAR(arc, bolt_damage), thiswep.m_id | HITTYPE_SECONDARY);
 
        W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
 
-       missile = new(missile);
+       entity missile = new(missile);
        missile.owner = missile.realowner = actor;
        missile.bot_dodge = true;
        IL_PUSH(g_bot_dodge, missile);
@@ -145,25 +153,38 @@ void W_Arc_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity)
        IL_PUSH(g_damagedbycontents, missile);
 
        settouch(missile, W_Arc_Bolt_Touch);
+       missile.cnt = 0;
        missile.use = W_Arc_Bolt_Explode_use;
        setthink(missile, adaptor_think2use_hittype_splash);
        missile.nextthink = time + WEP_CVAR(arc, bolt_lifetime);
        PROJECTILE_MAKETRIGGER(missile);
-       missile.projectiledeathtype = WEP_ARC.m_id | HITTYPE_SECONDARY;
+       missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
        missile.weaponentity_fld = weaponentity;
        setorigin(missile, w_shotorg);
        setsize(missile, '0 0 0', '0 0 0');
 
-       set_movetype(missile, MOVETYPE_FLY);
+       set_movetype(missile, MOVETYPE_BOUNCEMISSILE);
        W_SetupProjVelocity_PRE(missile, arc, bolt_);
 
        missile.angles = vectoangles(missile.velocity);
        missile.flags = FL_PROJECTILE;
+       IL_PUSH(g_projectiles, missile);
        missile.missile_flags = MIF_SPLASH;
 
        CSQCProjectile(missile, true, PROJECTILE_ARC_BOLT, true);
 
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
+
+       actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+       if(actor.(weaponentity).misc_bulletcounter == 0)
+       {
+               ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(arc, bolt_refire2) * W_WeaponRateFactor(actor);
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), w_ready);
+       }
+       else
+       {
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), W_Arc_Attack_Bolt);
+       }
 }
 
 void W_Arc_Beam_Think(entity this)
@@ -656,10 +677,28 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
     }
     else if(fire & 2)
     {
-        if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR(arc, bolt_refire)))
+        if(weapon_prepareattack(thiswep, actor, weaponentity, true, 0))
         {
-            W_Arc_Attack_Bolt(thiswep, actor, weaponentity);
-            weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), w_ready);
+               if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
+            if(!(actor.items & IT_UNLIMITED_AMMO))
+            {
+                W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
+                w_ready(thiswep, actor, weaponentity, fire);
+                return;
+            }
+            float ammo_available = GetResource(actor, thiswep.ammo_type);
+            // We don't want to shoot 3 rounds if there's 2 left in the mag, so we'll use a fraction.
+            // Also keep the fraction <= 1 otherwise we'd mag dump in one burst.
+            float burst_fraction = min(1, ammo_available / WEP_CVAR(arc, bolt_ammo));
+            int to_shoot = floor(WEP_CVAR(arc, bolt_count) * burst_fraction);
+
+            // We also don't want to use 3 rounds if there's only 2 left.
+            int to_use = min(WEP_CVAR(arc, bolt_ammo), ammo_available);
+            W_DecreaseAmmo(thiswep, actor, to_use, weaponentity);
+
+            // Bursting counts up to 0 from a negative.
+            actor.(weaponentity).misc_bulletcounter = -to_shoot;
+            W_Arc_Attack_Bolt(thiswep, actor, weaponentity, fire);
         }
     }
 
@@ -761,8 +800,8 @@ METHOD(Arc, wr_impacteffect, void(entity thiswep, entity actor))
     {
         vector org2;
         org2 = w_org + w_backoff * 6;
-        pointparticles(EFFECT_ARC_BOLT_EXPLODE, org2, w_backoff * 1000, 1);
-        if(!w_issilent) { sound(actor, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
+        pointparticles(EFFECT_ELECTRO_IMPACT, org2, w_backoff * 1000, 1);
+        if(!w_issilent) { sound(actor, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTN_NORM); }
     }
 }
 
@@ -931,9 +970,7 @@ void Draw_ArcBeam(entity this)
                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;
+                       origin_offset = right * -this.beam_shotorigin.y + up * this.beam_shotorigin.z;
                }
                else
                        this.beam_shotorigin = '0 0 0';