diff --git a/CREDITS.md b/CREDITS.md index 4c788fe55f..ee60d30a19 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -372,6 +372,7 @@ This page lists all the individual contributions to the project by their author. - Allow to change the speed of gas particles - **CrimRecya** - Fix `LimboKill` not working reliably + - Burst without delay - **Ollerus** - Build limit group enhancement - Customizable rocker amplitude @@ -380,6 +381,7 @@ This page lists all the individual contributions to the project by their author. - Skirmish AI "sell all buildings and set all technos to hunt" behavior dehardcode - Skirmish AI "gather when MCV deploy" behavior dehardcode - Global value of `RepairBaseNodes` + - Burst without delay - **tyuah8** - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix - **Aephiex** - initial fix for Ares academy not working on the initial payloads of vehicles built from a war factory - **Ares developers** diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index e553a34732..72896a08d3 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -1678,6 +1678,16 @@ Burst.Delays=-1 ; integer - burst delays (comma-separated) for s Burst.FireWithinSequence=false ; boolean ``` +### Burst without delay + +- In vanilla, vehicles and infantries will only fire once in one frame, even if their `ROF` or `BurstDelay` is set to 0. Now you can force units to fire all bursts in one frame by setting the `Burst.NoDelay` to true (useless for buildings yet). + +In `rulesmd.ini`: +```ini +[SOMEWEAPON] ; WeaponType +Burst.NoDelay=false ; boolean +``` + ### Extra warhead detonations - It is now possible to have same weapon detonate multiple Warheads on impact by listing `ExtraWarheads`. The warheads are detonated at same location as the main one, after it in listed order. This only works in cases where a projectile has been fired by a weapon and still remembers it when it is detonated (due to currently existing technical limitations, this excludes `AirburstWeapon`). diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 37c9f39e2f..6e2fc7333f 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -469,6 +469,7 @@ New: - Allow infantry to use land sequences in water (by Starkku) - `` can now be used as owner for pre-placed objects on skirmish and multiplayer maps (by Starkku) - Allow customizing charge turret delays per burst on a weapon (by Starkku) +- Burst without delay (by CrimRecya & TaranDahl) - Unit `Speed` setting now accepts floating point values (by Starkku) Vanilla fixes: diff --git a/src/Ext/Techno/Hooks.Firing.cpp b/src/Ext/Techno/Hooks.Firing.cpp index 1bc6f719a5..5eee176082 100644 --- a/src/Ext/Techno/Hooks.Firing.cpp +++ b/src/Ext/Techno/Hooks.Firing.cpp @@ -710,6 +710,88 @@ DEFINE_HOOK(0x6F3C88, TechnoClass_GetFLH_BurstFLH_2, 0x6) } #pragma endregion +#pragma region NoBurstDelay + +DEFINE_HOOK(0x5209EE, InfantryClass_UpdateFiring_BurstNoDelay, 0x5) +{ + enum { SkipVanillaFire = 0x520A57 }; + + GET(InfantryClass* const, pThis, EBP); + GET(const int, wpIdx, ESI); + GET(AbstractClass* const, pTarget, EAX); + + if (const auto pWeapon = pThis->GetWeapon(wpIdx)->WeaponType) + { + if (pWeapon->Burst > 1) + { + if (WeaponTypeExt::ExtMap.Find(pWeapon)->Burst_NoDelay) + { + if (pThis->Fire(pTarget, wpIdx)) + { + if (!pThis->CurrentBurstIndex) + return SkipVanillaFire; + + auto rof = pThis->RearmTimer.TimeLeft; + pThis->RearmTimer.Start(0); + + for (auto i = pThis->CurrentBurstIndex; i != pWeapon->Burst && pThis->GetFireError(pTarget, wpIdx, true) == FireError::OK && pThis->Fire(pTarget, wpIdx); ++i) + { + rof = pThis->RearmTimer.TimeLeft; + pThis->RearmTimer.Start(0); + } + + pThis->RearmTimer.Start(rof); + } + + return SkipVanillaFire; + } + } + } + + return 0; +} + +DEFINE_HOOK(0x736F67, UnitClass_UpdateFiring_BurstNoDelay, 0x6) +{ + enum { SkipVanillaFire = 0x737063 }; + + GET(UnitClass* const, pThis, ESI); + GET(const int, wpIdx, EDI); + GET(AbstractClass* const, pTarget, EAX); + + if (const auto pWeapon = pThis->GetWeapon(wpIdx)->WeaponType) + { + if (pWeapon->Burst > 1) + { + if (WeaponTypeExt::ExtMap.Find(pWeapon)->Burst_NoDelay) + { + if (pThis->Fire(pTarget, wpIdx)) + { + if (!pThis->CurrentBurstIndex) + return SkipVanillaFire; + + auto rof = pThis->RearmTimer.TimeLeft; + pThis->RearmTimer.Start(0); + + for (auto i = pThis->CurrentBurstIndex; i != pWeapon->Burst && pThis->GetFireError(pTarget, wpIdx, true) == FireError::OK && pThis->Fire(pTarget, wpIdx); ++i) + { + rof = pThis->RearmTimer.TimeLeft; + pThis->RearmTimer.Start(0); + } + + pThis->RearmTimer.Start(rof); + } + + return SkipVanillaFire; + } + } + } + + return 0; +} + +#pragma endregion + // Basically a hack to make game and Ares pick laser properties from non-Primary weapons. DEFINE_HOOK(0x70E1A0, TechnoClass_GetTurretWeapon_LaserWeapon, 0x5) { diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp index 3e82a2b5bc..1254a60d42 100644 --- a/src/Ext/WeaponType/Body.cpp +++ b/src/Ext/WeaponType/Body.cpp @@ -115,6 +115,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->AttachEffect_CheckOnFirer.Read(exINI, pSection, "AttachEffect.CheckOnFirer"); this->AttachEffect_IgnoreFromSameSource.Read(exINI, pSection, "AttachEffect.IgnoreFromSameSource"); this->KickOutPassengers.Read(exINI, pSection, "KickOutPassengers"); + this->Burst_NoDelay.Read(exINI, pSection, "Burst.NoDelay"); } template @@ -160,6 +161,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm) .Process(this->AttachEffect_CheckOnFirer) .Process(this->AttachEffect_IgnoreFromSameSource) .Process(this->KickOutPassengers) + .Process(this->Burst_NoDelay) ; }; diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h index 2a979bece1..de78228f94 100644 --- a/src/Ext/WeaponType/Body.h +++ b/src/Ext/WeaponType/Body.h @@ -60,6 +60,7 @@ class WeaponTypeExt Valueable AttachEffect_CheckOnFirer; Valueable AttachEffect_IgnoreFromSameSource; Valueable KickOutPassengers; + Valueable Burst_NoDelay; ExtData(WeaponTypeClass* OwnerObject) : Extension(OwnerObject) , DiskLaser_Radius { DiskLaserClass::Radius } @@ -101,6 +102,7 @@ class WeaponTypeExt , AttachEffect_CheckOnFirer { false } , AttachEffect_IgnoreFromSameSource { false } , KickOutPassengers { true } + , Burst_NoDelay { false } { } int GetBurstDelay(int burstIndex) const;