Skip to content
Open
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
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ This page lists all the individual contributions to the project by their author.
- Customize size for mind controlled unit
- Fix the issue that weapon selection don't check if secondary's warhead has `IsLocomotor=yes`
- Fix the issue that warhead with `IsLocomotor=yes` can be used to vehicles who is in tank bunker
- Customize whether warhead can be used to targeting ironcurtained technos or not
- **Apollo** - Translucent SHP drawing patches
- **ststl**:
- Customizable `ShowTimer` priority of superweapons
Expand Down
14 changes: 14 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -2748,6 +2748,20 @@ UnlimboDetonate.KeepSelected=false ; boolean
`UnlimboDetonate` cannot be used in conjunction with `Parasite`.
```

### Customize whether warhead can be used to targeting ironcurtained technos or not

- In vanilla, computer player's techno always dont attack ironcurtained technos. Now you can customize it.

In `rulesmd.ini`:
```ini
[CombatDamage]
CanAITargetIronCurtained=false ; boolean
CanHumanTargetIronCurtained=true ; boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the current handling is unnecessary. You only need to:

bool canTargetIronCurtained = !pThis->Owner->IsControlledByHuman() ? RulesExt::Global()->CanHumanTargetIronCurtained : RulesExt::Global()->CanAITargetIronCurtained;

if (pTargetTechno->IsIronCurtained() && !pWeaponExt->CanTarget_IronCurtained.Get(pWeapon->Damage >= 0 ? canTargetIronCurtained : true))
    return CannotFire;


[SOMEWEAPON] ; WeaponType
CanTarget.IronCurtained= ; boolean
```

## Weapons

### AreaFire target customization
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ New:
- [Attack non-threatening structures extensions](New-or-Enhanced-Logics.md#attack-non-threatening-structures-techno) (by FlyStar)
- [Customize size for mind controlled unit](New-or-Enhanced-Logics.md#mind-control-enhancement) (by NetsuNegi)
- [Deploy priority filtering](New-or-Enhanced-Logics.md#low-priority-for-deploy) (by Starkku)
- Customize whether warhead can be used to targeting ironcurtained technos or not (by NetsuNegi)

Vanilla fixes:
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)
Expand Down
5 changes: 5 additions & 0 deletions src/Ext/Rules/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,9 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)
this->PlayerAttackMoveTargetingDelay.Read(exINI, GameStrings::General, "PlayerAttackMoveTargetingDelay");
this->DistributeTargetingFrame.Read(exINI, GameStrings::General, "DistributeTargetingFrame");
this->DistributeTargetingFrame_AIOnly.Read(exINI, GameStrings::General, "DistributeTargetingFrame.AIOnly");

this->CanAITargetIronCurtained.Read(exINI, GameStrings::CombatDamage, "CanAITargetIronCurtained");
this->CanHumanTargetIronCurtained.Read(exINI, GameStrings::CombatDamage, "CanHumanTargetIronCurtained");

this->InfantryAutoDeploy.Read(exINI, GameStrings::General, "InfantryAutoDeploy");

Expand Down Expand Up @@ -602,6 +605,8 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->PlayerAttackMoveTargetingDelay)
.Process(this->DistributeTargetingFrame)
.Process(this->DistributeTargetingFrame_AIOnly)
.Process(this->CanAITargetIronCurtained)
.Process(this->CanHumanTargetIronCurtained)
.Process(this->BuildingTypeSelectable)
.Process(this->ProneSpeed_Crawls)
.Process(this->ProneSpeed_NoCrawls)
Expand Down
5 changes: 5 additions & 0 deletions src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ class RulesExt
Valueable<bool> DistributeTargetingFrame;
Valueable<bool> DistributeTargetingFrame_AIOnly;

Valueable<bool> CanAITargetIronCurtained;
Valueable<bool> CanHumanTargetIronCurtained;

Valueable<bool> BuildingWaypoints;
Valueable<bool> BuildingTypeSelectable;

Expand Down Expand Up @@ -489,6 +492,8 @@ class RulesExt
, PlayerAttackMoveTargetingDelay {}
, DistributeTargetingFrame { false }
, DistributeTargetingFrame_AIOnly { true }
, CanAITargetIronCurtained { false }
, CanHumanTargetIronCurtained { true }
, BuildingWaypoints { false }
, BuildingTypeSelectable { false }
, ProneSpeed_Crawls { 0.67 }
Expand Down
46 changes: 42 additions & 4 deletions src/Ext/Techno/Hooks.Firing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,11 @@ DEFINE_HOOK(0x6FC339, TechnoClass_CanFire, 0x6)

if (pTargetTechno)
{
if (pThis->Berzerk
&& !EnumFunctions::CanTargetHouse(RulesExt::Global()->BerzerkTargeting, pThis->Owner, pTargetTechno->Owner))
{
if (!pThis->Owner->IsControlledByHuman() && pTargetTechno->IsIronCurtained() && !pWeaponExt->CanTarget_IronCurtained.Get(RulesExt::Global()->CanAITargetIronCurtained))
return CannotFire;

if (pThis->Berzerk && !EnumFunctions::CanTargetHouse(RulesExt::Global()->BerzerkTargeting, pThis->Owner, pTargetTechno->Owner))
return CannotFire;
}

if (!pWeaponExt->SkipWeaponPicking)
{
Expand Down Expand Up @@ -400,6 +400,8 @@ DEFINE_HOOK(0x6FC0C5, TechnoClass_CanFire_DisableWeapons, 0x6)
return Continue;
}

DEFINE_JUMP(LJMP, 0x6FC22A, 0x6FC24D) // Skip IronCurtain check

DEFINE_HOOK(0x6FC3AE, TechnoClass_CanFire_TankInBunker_LocomotorWarhead, 0x6)
{
enum { Illegal = 0x6FC86A };
Expand Down Expand Up @@ -1086,3 +1088,39 @@ DEFINE_HOOK(0x5223B3, InfantryClass_Approach_Target_DeployFireWeapon, 0x6)
R->EDI(deployFireWeapon == -1 ? pThis->SelectWeapon(pThis->Target) : deployFireWeapon);
return 0x5223B9;
}

DEFINE_HOOK(0x708AD0, TechnoClass_ShouldRetaliate_IronCurtain, 0x6)
{
enum { ContinueCheck = 0x708AD6, ReturnTrue = 0x708B0B, ReturnFalse = 0x708B17 };

GET(TechnoClass*, pThis, ESI);
GET(TechnoClass*, pTarget, EBP);
GET(WeaponTypeClass*, pWeapon, EAX);

do
{
if (!pThis->Owner->IsControlledByHuman() || !pTarget->IsIronCurtained())
break;

if (pWeapon)
{
const auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);

if (pWeaponExt->CanTarget_IronCurtained.isset())
{
if (!pWeaponExt->CanTarget_IronCurtained.Get())
return ReturnFalse;

break;
}
}

if (!RulesExt::Global()->CanHumanTargetIronCurtained)
return ReturnFalse;
}
while (false);

// Restore overriden instructions
R->ESI(pWeapon);
return pWeapon ? ContinueCheck : ReturnTrue;
}
27 changes: 27 additions & 0 deletions src/Ext/Techno/Hooks.Targeting.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "Body.h"

#include <Ext/WeaponType/Body.h>

DEFINE_HOOK(0x6FA697, TechnoClass_Update_DontScanIfUnarmed, 0x6)
{
enum { SkipTargeting = 0x6FA6F5 };
Expand Down Expand Up @@ -42,3 +44,28 @@ DEFINE_HOOK(0x70982C, TechnoClass_TargetAndEstimateDamage_TargetingDelay, 0x8)

return SkipGameCode;
}

DEFINE_HOOK(0x6F7CE2, TechnoClass_CanAutoTargetObject_IronCurtain, 0x6)
{
enum { ReturnFalse = 0x6F894F };

GET(TechnoClass*, pThis, EDI);
GET(TechnoClass*, pTarget, ESI);

if (pThis->Owner->IsControlledByHuman() && pTarget->IsIronCurtained())
{
GET(WeaponTypeClass*, pWeapon, EBP);

if (pWeapon)
{
const auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);

if (pWeaponExt->CanTarget_IronCurtained.isset())
return pWeaponExt->CanTarget_IronCurtained.Get() ? 0 : ReturnFalse;
}

return RulesExt::Global()->CanHumanTargetIronCurtained ? 0 : ReturnFalse;
}

return 0;
}
2 changes: 2 additions & 0 deletions src/Ext/WeaponType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->CanTargetHouses.Read(exINI, pSection, "CanTargetHouses");
this->CanTarget_MaxHealth.Read(exINI, pSection, "CanTarget.MaxHealth");
this->CanTarget_MinHealth.Read(exINI, pSection, "CanTarget.MinHealth");
this->CanTarget_IronCurtained.Read(exINI, pSection, "CanTarget.IronCurtained");
this->Burst_Delays.Read(exINI, pSection, "Burst.Delays");
this->Burst_FireWithinSequence.Read(exINI, pSection, "Burst.FireWithinSequence");
this->Burst_NoDelay.Read(exINI, pSection, "Burst.NoDelay");
Expand Down Expand Up @@ -192,6 +193,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm)
.Process(this->CanTargetHouses)
.Process(this->CanTarget_MaxHealth)
.Process(this->CanTarget_MinHealth)
.Process(this->CanTarget_IronCurtained)
.Process(this->RadType)
.Process(this->Burst_Delays)
.Process(this->Burst_FireWithinSequence)
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/WeaponType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class WeaponTypeExt
Valueable<AffectedHouse> CanTargetHouses;
Valueable<double> CanTarget_MaxHealth;
Valueable<double> CanTarget_MinHealth;
Nullable<bool> CanTarget_IronCurtained;
ValueableVector<int> Burst_Delays;
Valueable<bool> Burst_FireWithinSequence;
Valueable<bool> Burst_NoDelay;
Expand Down Expand Up @@ -115,6 +116,7 @@ class WeaponTypeExt
, CanTargetHouses { AffectedHouse::All }
, CanTarget_MaxHealth { 1.0 }
, CanTarget_MinHealth { 0.0 }
, CanTarget_IronCurtained {}
, Burst_Delays {}
, Burst_FireWithinSequence { false }
, Burst_NoDelay { false }
Expand Down