#ifdef SVQC
+.float machinegun_spread_accumulation;
+.float spreadUpdateTime;
+
+
+ERASEABLE
+void MachineGun_Update_Spread(entity actor, .entity weaponentity, float spreadSpectrumMin, float spreadSpectrumMax)
+{
+ float spread_accum = actor.(weaponentity).machinegun_spread_accumulation;
+
+ // time based spread decay
+ if (WEP_CVAR(WEP_MACHINEGUN, spread_decay))
+ {
+ float spreadSpectrumDistance = spreadSpectrumMax - spreadSpectrumMin;
+ float timediff = time - actor.(weaponentity).spreadUpdateTime;
+ spread_accum = bound(0,
+ spread_accum - (timediff * WEP_CVAR(WEP_MACHINEGUN, spread_decay)),
+ spreadSpectrumDistance);
+ }
+ else // legacy behavior for Nexuiz weapon balance
+ {
+ spread_accum = bound(WEP_CVAR(WEP_MACHINEGUN, spread_min),
+ (WEP_CVAR(WEP_MACHINEGUN, spread_add) * actor.(weaponentity).misc_bulletcounter),
+ WEP_CVAR(WEP_MACHINEGUN, spread_max));
+ }
+
+ actor.(weaponentity).machinegun_spread_accumulation = spread_accum;
+ actor.(weaponentity).spreadUpdateTime = time;
+}
+
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.(weaponentity).misc_bulletcounter == 1) ? WEP_CVAR(WEP_MACHINEGUN, first_damage) : WEP_CVAR(WEP_MACHINEGUN, sustained_damage)), deathtype);
w_ready(thiswep, actor, weaponentity, fire);
return;
}
- actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+ ++actor.(weaponentity).misc_bulletcounter;
W_MachineGun_Attack(thiswep, thiswep.m_id, actor, weaponentity);
weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(WEP_MACHINEGUN, sustained_refire), W_MachineGun_Attack_Frame);
}
void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
{
- float machinegun_spread;
-
if(!(fire & 1) || !weapon_prepareattack_check(thiswep, actor, weaponentity, false, -1))
{
w_ready(thiswep, actor, weaponentity, fire);
actor.punchangle_y = random() - 0.5;
}
- machinegun_spread = bound(WEP_CVAR(WEP_MACHINEGUN, spread_min), WEP_CVAR(WEP_MACHINEGUN, spread_min) + (WEP_CVAR(WEP_MACHINEGUN, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(WEP_MACHINEGUN, spread_max));
- fireBullet_falloff(actor, weaponentity, w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(WEP_MACHINEGUN, solidpenetration), WEP_CVAR(WEP_MACHINEGUN, sustained_damage),
- WEP_CVAR(WEP_MACHINEGUN, damagefalloff_halflife), WEP_CVAR(WEP_MACHINEGUN, damagefalloff_mindist), WEP_CVAR(WEP_MACHINEGUN, damagefalloff_maxdist), 0,
- WEP_CVAR(WEP_MACHINEGUN, sustained_force), WEP_CVAR(WEP_MACHINEGUN, damagefalloff_forcehalflife), thiswep.m_id, EFFECT_BULLET, true);
+ MachineGun_Update_Spread(actor, weaponentity, WEP_CVAR(WEP_MACHINEGUN, spread_min), WEP_CVAR(WEP_MACHINEGUN, spread_max));
+
+ float spread_accum = actor.(weaponentity).machinegun_spread_accumulation;
+
+ float spread_accuracy = WEP_CVAR(WEP_MACHINEGUN, spread_min) + spread_accum;
+
+ fireBullet_falloff(actor, weaponentity, w_shotorg, w_shotdir,
+ spread_accuracy,
+ WEP_CVAR(WEP_MACHINEGUN, solidpenetration),
+ WEP_CVAR(WEP_MACHINEGUN, sustained_damage),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_halflife),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_mindist),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_maxdist),
+ 0,
+ WEP_CVAR(WEP_MACHINEGUN, sustained_force),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_forcehalflife),
+ thiswep.m_id, EFFECT_BULLET, true);
+
+ ++actor.(weaponentity).misc_bulletcounter;
- actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+ spread_accum += WEP_CVAR(WEP_MACHINEGUN, spread_add);
+
+ actor.(weaponentity).machinegun_spread_accumulation = spread_accum;
W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
actor.punchangle_y = random() - 0.5;
}
- fireBullet_falloff(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(WEP_MACHINEGUN, burst_spread), WEP_CVAR(WEP_MACHINEGUN, solidpenetration), WEP_CVAR(WEP_MACHINEGUN, sustained_damage),
- WEP_CVAR(WEP_MACHINEGUN, damagefalloff_halflife), WEP_CVAR(WEP_MACHINEGUN, damagefalloff_mindist), WEP_CVAR(WEP_MACHINEGUN, damagefalloff_maxdist), 0,
- WEP_CVAR(WEP_MACHINEGUN, sustained_force), WEP_CVAR(WEP_MACHINEGUN, damagefalloff_forcehalflife), thiswep.m_id, EFFECT_BULLET, true);
+ MachineGun_Update_Spread(actor, weaponentity, WEP_CVAR(WEP_MACHINEGUN, spread_min), WEP_CVAR(WEP_MACHINEGUN, spread_max));
+
+ float spread_accum = actor.(weaponentity).machinegun_spread_accumulation;
+
+ fireBullet_falloff(actor, weaponentity, w_shotorg, w_shotdir,
+ WEP_CVAR(WEP_MACHINEGUN, burst_spread),
+ WEP_CVAR(WEP_MACHINEGUN, solidpenetration),
+ WEP_CVAR(WEP_MACHINEGUN, sustained_damage),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_halflife),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_mindist),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_maxdist),
+ 0,
+ WEP_CVAR(WEP_MACHINEGUN, sustained_force),
+ WEP_CVAR(WEP_MACHINEGUN, damagefalloff_forcehalflife),
+ thiswep.m_id, EFFECT_BULLET, true);
W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), vectoangles(v_forward), 3, actor, weaponentity);
}
- actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+ spread_accum += WEP_CVAR(WEP_MACHINEGUN, spread_add);
+
+ actor.(weaponentity).machinegun_spread_accumulation = spread_accum;
+
+ ++actor.(weaponentity).misc_bulletcounter;
if(actor.(weaponentity).misc_bulletcounter == 0)
{
ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR(WEP_MACHINEGUN, burst_refire2) * W_WeaponRateFactor(actor);