diff --git a/CREDITS.md b/CREDITS.md index fae33729f7..337f9a4699 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -670,6 +670,7 @@ This page lists all the individual contributions to the project by their author. - Return warhead - `ElectricAssault` weapons can now auto acquire allies' overpowerable defenses - Allow `AuxBuilding` and Ares' `SW.Aux/NegBuildings` to count building upgrades + - Weapon maximum/minimum `Range` - **NaotoYuuki** - Vertical & meteor trajectory projectile prototypes - **handama**: - AI script action to `16005 Jump Back To Previous Script` diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index a26ebde75d..6d1f15fce8 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -48,6 +48,7 @@ This page describes all the engine features that are either new and introduced b - `WeaponRange.Multiplier` and `WeaponRange.ExtraRange` can be used to multiply the weapon firing range of the object the effect is attached to, or give it an increase / decrease (measured in cells), respectively. `ExtraRange` is cumulatively applied from all attached effects after all `Multiplier` values have been applied. - `WeaponRange.AllowWeapons` can be used to list only weapons that can benefit from this range bonus and `WeaponRange.DisallowWeapons` weapons that are not allowed to, respectively. - On TechnoTypes with `OpenTopped=true`, `OpenTopped.UseTransportRangeModifiers` can be set to true to make passengers firing out use the transport's active range bonuses instead. + - The weapon range with all sort of range modifiers can't be greater than `WeaponRange.Maximum` or smaller than `WeaponRange.Minimum` of the affected weapon. Notice that `Range=-2` is a special case and will be ignored. - `Crit.Multiplier` and `Crit.ExtraChance` can be used to multiply the [critical hit](#chance-based-extra-damage-or-warhead-detonation--critical-hits) chance or grant a fixed bonus to it for the object the effect is attached to, respectively. - `Crit.AllowWarheads` can be used to list only Warheads that can benefit from this critical hit chance multiplier and `Crit.DisallowWarheads` weapons that are not allowed to, respectively. - `RevengeWeapon` can be used to temporarily grant the specified weapon as a [revenge weapon](#revenge-weapon) for the attached object. @@ -177,6 +178,8 @@ AttachEffect.DisallowedMinCounts= ; integer - minimum disallowe AttachEffect.DisallowedMaxCounts= ; integer - maximum disallowed instance count (comma-separated) for cumulative types in order from first to last. AttachEffect.IgnoreFromSameSource=false ; boolean AttachEffect.CheckOnFirer=false ; boolean +WeaponRange.Maximum=100000 ; floating point value, distance in cells +WeaponRange.Minimum=0 ; floating point value, distance in cells [SOMEWARHEAD] ; WarheadType AttachEffect.AttachTypes= ; List of AttachEffectTypes diff --git a/docs/Whats-New.md b/docs/Whats-New.md index 7e91c9da99..cfcfc9c97e 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -737,7 +737,7 @@ HideShakeEffects=false ; boolean - Allowed `AuxBuilding` and Ares' `SW.Aux/NegBuildings` to count building upgrades (by Ollerus & NetsuNegi) - [Aux technos and TechLevel requirement of superweapon](New-or-Enhanced-Logics.md#aux-technos-and-techlevel-requirement-of-superweapon) (by NetsuNegi & Ollerus) - [Export interface for external call](index.md#interoperability) (by TaranDahl) - +- Weapon maximum/minimum `Range` (by Ollerus) ``` ### 0.4.0.3 diff --git a/src/Ext/WeaponType/Body.cpp b/src/Ext/WeaponType/Body.cpp index f98678cfdc..5d0c53df7f 100644 --- a/src/Ext/WeaponType/Body.cpp +++ b/src/Ext/WeaponType/Body.cpp @@ -172,6 +172,25 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->AttackNoThreatBuildings.Read(exINI, pSection, "AttackNoThreatBuildings"); this->CylinderRangefinding.Read(exINI, pSection, "CylinderRangefinding"); this->Anim_Update.Read(exINI, pSection, "Anim.Update"); + this->WeaponRange_Maximum.Read(exINI, pSection, "WeaponRange.Maximum"); + this->WeaponRange_Minimum.Read(exINI, pSection, "WeaponRange.Minimum"); + + if (this->WeaponRange_Maximum.Get() < pThis->Range && pThis->Range != -512) + { + Debug::Log("[Developer warning][%s] WeaponRange.Maximum is smaller than Range, it'll be reset to the value of Range!\n", pSection); + this->WeaponRange_Maximum = Leptons(static_cast(pThis->Range / static_cast(Unsorted::LeptonsPerCell))); + } + + if (this->WeaponRange_Minimum.Get() < 0) + { + Debug::Log("[Developer warning][%s] WeaponRange.Minimum is smaller than 0, it'll be reset to 0!\n", pSection); + this->WeaponRange_Minimum = Leptons(0); + } + else if (this->WeaponRange_Minimum.Get() > pThis->Range && pThis->Range != -512) + { + Debug::Log("[Developer warning][%s] WeaponRange.Minimum is bigger than Range, it'll be reset to the value of Range!\n", pSection); + this->WeaponRange_Minimum = Leptons(static_cast(pThis->Range / static_cast(Unsorted::LeptonsPerCell))); + } // handle SkipWeaponPicking if (this->CanTarget != AffectedTarget::All || this->CanTargetHouses != AffectedHouse::All @@ -272,6 +291,8 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm) .Process(this->AttackNoThreatBuildings) .Process(this->CylinderRangefinding) .Process(this->Anim_Update) + .Process(this->WeaponRange_Maximum) + .Process(this->WeaponRange_Minimum) ; }; @@ -353,10 +374,19 @@ int WeaponTypeExt::GetRangeWithModifiers(WeaponTypeClass* pThis, TechnoClass* pF pTechno = pTransport; } + int min = 0; + int max = 25600000; // Unsorted::LeptonsPerCell * 100000 + + if (auto const pExt = WeaponTypeExt::ExtMap.Find(pThis)) + { + min = pExt->WeaponRange_Minimum.Get(); + max = pExt->WeaponRange_Maximum.Get(); + } + auto const pTechnoExt = TechnoExt::ExtMap.Find(pTechno); if (!pTechnoExt->AE.HasRangeModifier) - return range; + return Math::clamp(range, min, max); double extraRange = 0.0; @@ -382,7 +412,7 @@ int WeaponTypeExt::GetRangeWithModifiers(WeaponTypeClass* pThis, TechnoClass* pF range += static_cast(extraRange * Unsorted::LeptonsPerCell); - return Math::max(range, 0); + return Math::clamp(range, min, max); } int WeaponTypeExt::GetTechnoKeepRange(WeaponTypeClass* pThis, TechnoClass* pFirer, bool isMinimum) diff --git a/src/Ext/WeaponType/Body.h b/src/Ext/WeaponType/Body.h index 5bb8734a4b..b39f73e82c 100644 --- a/src/Ext/WeaponType/Body.h +++ b/src/Ext/WeaponType/Body.h @@ -98,12 +98,12 @@ class WeaponTypeExt Nullable AttackFriendlies; Nullable AttackCursorOnFriendlies; Nullable AttackNoThreatBuildings; - + Nullable CylinderRangefinding; Nullable Anim_Update; + Valueable WeaponRange_Maximum; + Valueable WeaponRange_Minimum; bool SkipWeaponPicking; - - Nullable CylinderRangefinding; ExtData(WeaponTypeClass* OwnerObject) : Extension(OwnerObject) , DiskLaser_Radius { DiskLaserClass::Radius } @@ -190,6 +190,8 @@ class WeaponTypeExt , AttackNoThreatBuildings {} , CylinderRangefinding {} , Anim_Update {} + , WeaponRange_Maximum { Leptons(100000) } + , WeaponRange_Minimum { Leptons(0) } { } int GetBurstDelay(int burstIndex) const;