Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 21 additions & 7 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1486,29 +1486,43 @@ 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.
- `ForceWeapon.InRange` forces specified a list of weapons to be used once the target is within their `Range`. If `ForceWeapon.InRange.TechnoOnly` set to true, it'll only be forced on TechnoTypes like other forced weapons, otherwise it'll also be forced when attacking empty grounds. The first weapon in the listed order satisfied will be selected. Can be applied to both ground and air target if `ForceAAWeapon.InRange` is not set.
- `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}
Expand Down
2 changes: 1 addition & 1 deletion docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
74 changes: 73 additions & 1 deletion src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ int TechnoTypeExt::ExtData::SelectForceWeapon(TechnoClass* pThis, AbstractClass*

int forceWeaponIndex = -1;
const auto pTargetTechno = abstract_cast<TechnoClass*>(pTarget);
TechnoTypeClass* pTargetType = nullptr;

if (pTargetTechno)
{
const auto pTargetType = pTargetTechno->GetTechnoType();
pTargetType = pTargetTechno->GetTechnoType();

if (this->ForceWeapon_Naval_Decloaked >= 0
&& pTargetType->Cloakable
Expand Down Expand Up @@ -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<BuildingTypeClass*>(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;
}

Expand Down Expand Up @@ -639,13 +683,32 @@ 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
|| this->ForceWeapon_Disguised >= 0
|| 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");
Expand Down Expand Up @@ -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)
Expand Down
18 changes: 18 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ class TechnoTypeExt
ValueableVector<int> ForceAAWeapon_InRange;
ValueableVector<double> ForceAAWeapon_InRange_Overrides;
Valueable<bool> ForceAAWeapon_InRange_ApplyRangeModifiers;
Valueable<int> ForceWeapon_Buildings;
Valueable<int> ForceWeapon_Defenses;
Valueable<int> ForceWeapon_Infantry;
Valueable<int> ForceWeapon_Naval_Units;
Valueable<int> ForceWeapon_Units;
Valueable<int> ForceWeapon_Aircraft;
Valueable<int> ForceAAWeapon_Infantry;
Valueable<int> ForceAAWeapon_Units;
Valueable<int> ForceAAWeapon_Aircraft;

Valueable<bool> Ammo_Shared;
Valueable<int> Ammo_Shared_Group;
Expand Down Expand Up @@ -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 }
Expand Down