From c344197ee5193081f449a010c78ea4f1a606e2ae Mon Sep 17 00:00:00 2001 From: drjaska Date: Wed, 4 Sep 2024 21:03:25 +0300 Subject: [PATCH] Rework Machinegun's spread to be time-based --- .gitlab-ci.yml | 2 +- bal-wep-mario.cfg | 1 + bal-wep-nexuiz25.cfg | 1 + bal-wep-samual.cfg | 1 + bal-wep-xdf.cfg | 1 + bal-wep-xonotic.cfg | 1 + qcsrc/common/weapons/weapon/machinegun.qc | 83 +++++++++++++++++++---- qcsrc/common/weapons/weapon/machinegun.qh | 1 + 8 files changed, 78 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d1ed8f093..04c31a34c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,7 +36,7 @@ test_compilation_units: test_sv_game: stage: test script: - - export EXPECT=7004fcba787d0fbe17240beb84d8af3c + - export EXPECT=17e9738e7898923e862b0b72da30c5ad - qcsrc/tools/sv_game-hashtest.sh - exit $? diff --git a/bal-wep-mario.cfg b/bal-wep-mario.cfg index 957ee3768..306fb9a02 100644 --- a/bal-wep-mario.cfg +++ b/bal-wep-mario.cfg @@ -81,6 +81,7 @@ set g_balance_machinegun_reload_ammo 0 set g_balance_machinegun_reload_time 2 set g_balance_machinegun_solidpenetration 13.1 set g_balance_machinegun_spread_add 0.012 +set g_balance_machinegun_spread_decay 0.048 set g_balance_machinegun_spread_max 0.05 set g_balance_machinegun_spread_min 0.02 set g_balance_machinegun_sustained_ammo 1 diff --git a/bal-wep-nexuiz25.cfg b/bal-wep-nexuiz25.cfg index ac49e4617..aa241622e 100644 --- a/bal-wep-nexuiz25.cfg +++ b/bal-wep-nexuiz25.cfg @@ -81,6 +81,7 @@ set g_balance_machinegun_reload_ammo 0 set g_balance_machinegun_reload_time 2 set g_balance_machinegun_solidpenetration 13.1 set g_balance_machinegun_spread_add 0.02 +set g_balance_machinegun_spread_decay 0 set g_balance_machinegun_spread_max 0.6 set g_balance_machinegun_spread_min 0.02 set g_balance_machinegun_sustained_ammo 1 diff --git a/bal-wep-samual.cfg b/bal-wep-samual.cfg index 53d2c7dbb..1320937e7 100644 --- a/bal-wep-samual.cfg +++ b/bal-wep-samual.cfg @@ -81,6 +81,7 @@ set g_balance_machinegun_reload_ammo 60 set g_balance_machinegun_reload_time 2 set g_balance_machinegun_solidpenetration 13.1 set g_balance_machinegun_spread_add 0.012 +set g_balance_machinegun_spread_decay 0.048 set g_balance_machinegun_spread_max 0.05 set g_balance_machinegun_spread_min 0.02 set g_balance_machinegun_sustained_ammo 1 diff --git a/bal-wep-xdf.cfg b/bal-wep-xdf.cfg index 8e22f7b5b..36bd4b407 100644 --- a/bal-wep-xdf.cfg +++ b/bal-wep-xdf.cfg @@ -81,6 +81,7 @@ set g_balance_machinegun_reload_ammo 0 set g_balance_machinegun_reload_time 2 set g_balance_machinegun_solidpenetration 13.1 set g_balance_machinegun_spread_add 0 +set g_balance_machinegun_spread_decay 0 set g_balance_machinegun_spread_max 0 set g_balance_machinegun_spread_min 0 set g_balance_machinegun_sustained_ammo 1 diff --git a/bal-wep-xonotic.cfg b/bal-wep-xonotic.cfg index 07a6fc0d0..803ae377d 100644 --- a/bal-wep-xonotic.cfg +++ b/bal-wep-xonotic.cfg @@ -81,6 +81,7 @@ set g_balance_machinegun_reload_ammo 0 set g_balance_machinegun_reload_time 2 set g_balance_machinegun_solidpenetration 13.1 set g_balance_machinegun_spread_add 0.012 +set g_balance_machinegun_spread_decay 0.048 set g_balance_machinegun_spread_max 0.05 set g_balance_machinegun_spread_min 0.02 set g_balance_machinegun_sustained_ammo 1 diff --git a/qcsrc/common/weapons/weapon/machinegun.qc b/qcsrc/common/weapons/weapon/machinegun.qc index b0517597f..0f32850e6 100644 --- a/qcsrc/common/weapons/weapon/machinegun.qc +++ b/qcsrc/common/weapons/weapon/machinegun.qc @@ -2,6 +2,34 @@ #ifdef SVQC +.float machinegun_spread_accumulation; +.float spreadUpdateTime; + +ERASEABLE +void MachineGun_Update_Spread(entity actor, .entity weaponentity) +{ + float spread_accum = actor.(weaponentity).machinegun_spread_accumulation; + + // time based spread decay + if (WEP_CVAR(WEP_MACHINEGUN, spread_decay)) + { + float spreadSpectrumDistance = WEP_CVAR(WEP_MACHINEGUN, spread_max) - WEP_CVAR(WEP_MACHINEGUN, spread_min); + 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); @@ -72,7 +100,7 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit 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); } @@ -83,8 +111,6 @@ void W_MachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentit 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); @@ -108,12 +134,29 @@ void W_MachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity 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); + + 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); @@ -136,9 +179,21 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit 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); + + 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); @@ -148,7 +203,11 @@ 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), 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); diff --git a/qcsrc/common/weapons/weapon/machinegun.qh b/qcsrc/common/weapons/weapon/machinegun.qh index cf6a17434..10bfc08f0 100644 --- a/qcsrc/common/weapons/weapon/machinegun.qh +++ b/qcsrc/common/weapons/weapon/machinegun.qh @@ -43,6 +43,7 @@ CLASS(MachineGun, Weapon) P(class, prefix, reload_time, float, NONE) \ P(class, prefix, solidpenetration, float, NONE) \ P(class, prefix, spread_add, float, NONE) \ + P(class, prefix, spread_decay, float, NONE) \ P(class, prefix, spread_max, float, NONE) \ P(class, prefix, spread_min, float, NONE) \ P(class, prefix, sustained_ammo, float, NONE) \ -- 2.39.2