diff --git a/CREDITS.md b/CREDITS.md index 07ce2f8ab7..325b1a7c8a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -510,7 +510,7 @@ This page lists all the individual contributions to the project by their author. - Fix `DefaultDisguise` showing wrong house colors for different players - Fire weapon when Warhead kills something - Promotion animation deglobalization - - Forcing specific weapon by range + - Forcing specific weapon by range and target type - Passenger-based insignias - Use `InsigniaType` to set the properties of insignia in a batch - Allow player's self-healing effects to be benefited by allied or `PlayerControl=true` houses diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index 745bfbfa0c..70f704ce14 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -1486,7 +1486,7 @@ FLHKEY.BurstN= ; integer - Forward,Lateral,Height. FLHKey refers to weapon-spec *Enemy behavior against EMP targets with `ForceWeapon.UnderEMP` in [C&C: Reloaded](https://www.moddb.com/mods/cncreloaded)* - Can be used to override normal weapon selection logic to force specific weapons to use against certain targets. If multiple are set and target satisfies the conditions, the first one in listed order satisfied takes effect. - - `ForceWeapon.Naval.Decloaked` forces specified weapon to be used against uncloaked naval targets. Useful if your naval unit has one weapon only for underwater and another weapon for surface targets. + - `ForceWeapon.Naval.Decloaked` forces specified weapon to be used against uncloaked `Naval=yes` targets. Useful if your naval unit has one weapon only for underwater and another weapon for surface targets. - `ForceWeapon.Cloaked` forces specified weapon to be used against any cloaked targets. - `ForceWeapon.Disguised` forces specified weapon to be used against any disguised targets. - `ForceWeapon.UnderEMP` forces specified weapon to be used if the target is under EMP effect. @@ -1494,21 +1494,35 @@ FLHKEY.BurstN= ; integer - Forward,Lateral,Height. FLHKey refers to weapon-spec - `ForceAAWeapon.InRange` does the same thing but only for air target. Taking priority to `ForceWeapon.InRange`, which means that it can only be applied to ground target when they're both set. - `Force(AA)Weapon.InRange.Overrides` overrides the range when decides which weapon to use. Value from position matching the position from `Force(AA)Weapon.InRange` is used if found, or the weapon's own `Range` if not found or set to a value below 0. - If `Force(AA)Weapon.InRange.ApplyRangeModifiers` is set to true, any applicable weapon range modifiers from the firer are applied to the decision range. + - A series of tags can force specified weapons based on the target's type. + - `ForceWeapon.Naval.Units` forces specified weapon to be used against `Naval=yes` units. Taking priority to `ForceWeapon.Units`. + - If `ForceWeapon.Defenses` is enabled, it'll be used if the target is a building with `BuildCat=Combat`. Otherwise it'll follow `ForceWeapon.Buildings`, if enabled. + - `ForceWeapon.Infantry/Units/Aircraft` can be applied to both ground and air target if `ForceAAWeapon.Infantry/Units/Aircraft` is not set. + - `ForceAAWeapon.Infantry/Units/Aircraft` do the same things but only for air target. Taking priority to `ForceWeapon.Infantry/Units/Naval.Units/Aircraft`, which means that they can only be applied to ground target when they're both set. In `rulesmd.ini`: ```ini [SOMETECHNO] ; TechnoType -ForceWeapon.Naval.Decloaked=-1 ; integer. 0 for primary weapon, 1 for secondary weapon, -1 to disable -ForceWeapon.Cloaked=-1 ; integer. 0 for primary weapon, 1 for secondary weapon, -1 to disable -ForceWeapon.Disguised=-1 ; integer. 0 for primary weapon, 1 for secondary weapon, -1 to disable -ForceWeapon.UnderEMP=-1 ; integer. 0 for primary weapon, 1 for secondary weapon, -1 to disable -ForceWeapon.InRange= ; List of integers. 0 for primary weapon, 1 for secondary weapon, -1 to disable +ForceWeapon.Naval.Decloaked=-1 ; integer, -1 to disable +ForceWeapon.Cloaked=-1 ; integer, -1 to disable +ForceWeapon.Disguised=-1 ; integer, -1 to disable +ForceWeapon.UnderEMP=-1 ; integer, -1 to disable +ForceWeapon.InRange= ; List of integers ForceWeapon.InRange.Overrides= ; List of floating-point values ForceWeapon.InRange.ApplyRangeModifiers=false ; boolean ForceWeapon.InRange.TechnoOnly=true ; boolean -ForceAAWeapon.InRange= ; List of integers. 0 for primary weapon, 1 for secondary weapon, -1 to disable +ForceAAWeapon.InRange= ; List of integers ForceAAWeapon.InRange.Overrides= ; List of floating-point values ForceAAWeapon.InRange.ApplyRangeModifiers=false ; boolean +ForceWeapon.Buildings=-1 ; integer, -1 to disable +ForceWeapon.Defenses=-1 ; integer, -1 to disable +ForceWeapon.Infantry=-1 ; integer, -1 to disable +ForceWeapon.Naval.Units=-1 ; integer, -1 to disable +ForceWeapon.Units=-1 ; integer, -1 to disable +ForceWeapon.Aircraft=-1 ; integer, -1 to disable +ForceAAWeapon.Infantry=-1 ; integer, -1 to disable +ForceAAWeapon.Units=-1 ; integer, -1 to disable +ForceAAWeapon.Aircraft=-1 ; integer, -1 to disable ``` ```{note} diff --git a/docs/Whats-New.md b/docs/Whats-New.md index e8b9c2c3e0..88566e1c14 100644 --- a/docs/Whats-New.md +++ b/docs/Whats-New.md @@ -365,7 +365,7 @@ New: - [Customize overpower logic](Fixed-or-Improved-Logics.md#customize-overpower-logic) (by NetsuNegi) - [Promotion animation deglobalization](New-or-Enhanced-Logics.md#promotion-animation) (by Ollerus) - Enhanced [reveal](New-or-Enhanced-Logics.md#reveal-map-for-owner-on-impact) & [gap](New-or-Enhanced-Logics.md#shroud-map-for-enemies-on-impact) warhead (by NetsuNegi) -- [Forcing specific weapon by range](New-or-Enhanced-Logics.md#forcing-specific-weapon-against-certain-targets) (by Ollerus) +- [Forcing specific weapon by range and target type](New-or-Enhanced-Logics.md#forcing-specific-weapon-against-certain-targets) (by Ollerus) - [Jumpjet Tilts While Moving](New-or-Enhanced-Logics.md#jumpjet-tilts-while-moving) (by CrimRecya) - [Spawned aircraft facing to match turret toggle](New-or-Enhanced-Logics.md#aircraft-spawner-customizations) (by Starkku) - [Removed dependency on `blowfish.dll`](Miscellanous.md#blowfish-dependency) (by ZivDero) diff --git a/src/Ext/TechnoType/Body.cpp b/src/Ext/TechnoType/Body.cpp index 230253f92f..eca20a5e60 100644 --- a/src/Ext/TechnoType/Body.cpp +++ b/src/Ext/TechnoType/Body.cpp @@ -41,10 +41,11 @@ int TechnoTypeExt::ExtData::SelectForceWeapon(TechnoClass* pThis, AbstractClass* int forceWeaponIndex = -1; const auto pTargetTechno = abstract_cast(pTarget); + TechnoTypeClass* pTargetType = nullptr; if (pTargetTechno) { - const auto pTargetType = pTargetTechno->GetTechnoType(); + pTargetType = pTargetTechno->GetTechnoType(); if (this->ForceWeapon_Naval_Decloaked >= 0 && pTargetType->Cloakable @@ -79,6 +80,49 @@ int TechnoTypeExt::ExtData::SelectForceWeapon(TechnoClass* pThis, AbstractClass* TechnoTypeExt::SelectWeaponMutex = false; } + if (forceWeaponIndex == -1 && pTargetType) + { + switch (pTarget->WhatAmI()) + { + case AbstractType::Building: + { + forceWeaponIndex = this->ForceWeapon_Buildings; + + if (this->ForceWeapon_Defenses >= 0) + { + auto const pBuildingType = static_cast(pTargetType); + + if (pBuildingType->BuildCat == BuildCat::Combat) + forceWeaponIndex = this->ForceWeapon_Defenses; + } + + break; + } + case AbstractType::Infantry: + { + forceWeaponIndex = (this->ForceAAWeapon_Infantry >= 0 && pTarget->IsInAir()) + ? this->ForceAAWeapon_Infantry : this->ForceWeapon_Infantry; + + break; + } + case AbstractType::Unit: + { + forceWeaponIndex = (this->ForceAAWeapon_Units >= 0 && pTarget->IsInAir()) + ? this->ForceAAWeapon_Units : ((this->ForceWeapon_Naval_Units >= 0 && pTargetType->Naval) + ? this->ForceWeapon_Naval_Units : this->ForceWeapon_Units); + + break; + } + case AbstractType::Aircraft: + { + forceWeaponIndex = (this->ForceAAWeapon_Aircraft >= 0 && pTarget->IsInAir()) + ? this->ForceAAWeapon_Aircraft : this->ForceWeapon_Aircraft; + + break; + } + } + } + return forceWeaponIndex; } @@ -639,6 +683,16 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) this->ForceAAWeapon_InRange.Read(exINI, pSection, "ForceAAWeapon.InRange"); this->ForceAAWeapon_InRange_Overrides.Read(exINI, pSection, "ForceAAWeapon.InRange.Overrides"); this->ForceAAWeapon_InRange_ApplyRangeModifiers.Read(exINI, pSection, "ForceAAWeapon.InRange.ApplyRangeModifiers"); + this->ForceWeapon_Buildings.Read(exINI, pSection, "ForceWeapon.Buildings"); + this->ForceWeapon_Defenses.Read(exINI, pSection, "ForceWeapon.Defenses"); + this->ForceWeapon_Infantry.Read(exINI, pSection, "ForceWeapon.Infantry"); + this->ForceWeapon_Naval_Units.Read(exINI, pSection, "ForceWeapon.Naval.Units"); + this->ForceWeapon_Units.Read(exINI, pSection, "ForceWeapon.Units"); + this->ForceWeapon_Aircraft.Read(exINI, pSection, "ForceWeapon.Aircraft"); + this->ForceAAWeapon_Infantry.Read(exINI, pSection, "ForceAAWeapon.Infantry"); + this->ForceAAWeapon_Units.Read(exINI, pSection, "ForceAAWeapon.Units"); + this->ForceAAWeapon_Aircraft.Read(exINI, pSection, "ForceAAWeapon.Aircraft"); + this->ForceWeapon_Check = ( this->ForceWeapon_Naval_Decloaked >= 0 || this->ForceWeapon_Cloaked >= 0 @@ -646,6 +700,15 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI) || this->ForceWeapon_UnderEMP >= 0 || !this->ForceWeapon_InRange.empty() || !this->ForceAAWeapon_InRange.empty() + || this->ForceWeapon_Buildings >= 0 + || this->ForceWeapon_Defenses >= 0 + || this->ForceWeapon_Infantry >= 0 + || this->ForceWeapon_Naval_Units >= 0 + || this->ForceWeapon_Units >= 0 + || this->ForceWeapon_Aircraft >= 0 + || this->ForceAAWeapon_Infantry >= 0 + || this->ForceAAWeapon_Units >= 0 + || this->ForceAAWeapon_Aircraft >= 0 ); this->Ammo_Shared.Read(exINI, pSection, "Ammo.Shared"); @@ -1234,6 +1297,15 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm) .Process(this->ForceAAWeapon_InRange) .Process(this->ForceAAWeapon_InRange_Overrides) .Process(this->ForceAAWeapon_InRange_ApplyRangeModifiers) + .Process(this->ForceWeapon_Buildings) + .Process(this->ForceWeapon_Defenses) + .Process(this->ForceWeapon_Infantry) + .Process(this->ForceWeapon_Naval_Units) + .Process(this->ForceWeapon_Units) + .Process(this->ForceWeapon_Aircraft) + .Process(this->ForceAAWeapon_Infantry) + .Process(this->ForceAAWeapon_Units) + .Process(this->ForceAAWeapon_Aircraft) .Process(this->Ammo_Shared) .Process(this->Ammo_Shared_Group) diff --git a/src/Ext/TechnoType/Body.h b/src/Ext/TechnoType/Body.h index 78a8304108..cadcc75028 100644 --- a/src/Ext/TechnoType/Body.h +++ b/src/Ext/TechnoType/Body.h @@ -182,6 +182,15 @@ class TechnoTypeExt ValueableVector ForceAAWeapon_InRange; ValueableVector ForceAAWeapon_InRange_Overrides; Valueable ForceAAWeapon_InRange_ApplyRangeModifiers; + Valueable ForceWeapon_Buildings; + Valueable ForceWeapon_Defenses; + Valueable ForceWeapon_Infantry; + Valueable ForceWeapon_Naval_Units; + Valueable ForceWeapon_Units; + Valueable ForceWeapon_Aircraft; + Valueable ForceAAWeapon_Infantry; + Valueable ForceAAWeapon_Units; + Valueable ForceAAWeapon_Aircraft; Valueable Ammo_Shared; Valueable Ammo_Shared_Group; @@ -534,6 +543,15 @@ class TechnoTypeExt , ForceAAWeapon_InRange {} , ForceAAWeapon_InRange_Overrides {} , ForceAAWeapon_InRange_ApplyRangeModifiers { false } + , ForceWeapon_Buildings { -1 } + , ForceWeapon_Defenses { -1 } + , ForceWeapon_Infantry { -1 } + , ForceWeapon_Naval_Units { -1 } + , ForceWeapon_Units { -1 } + , ForceWeapon_Aircraft { -1 } + , ForceAAWeapon_Infantry { -1 } + , ForceAAWeapon_Units { -1 } + , ForceAAWeapon_Aircraft { -1 } , Ammo_Shared { false } , Ammo_Shared_Group { -1 }