Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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 @@ -394,6 +394,7 @@ This page lists all the individual contributions to the project by their author.
- Health bar permanently displayed
- Unlimbo Detonate warhead
- Fast access structure
- Attack non-threatening structures extensions
- **NetsuNegi**:
- Forbidding parallel AI queues by type
- Jumpjet crash speed fix when crashing onto building
Expand Down
25 changes: 25 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1312,6 +1312,21 @@ In `rulesmd.ini`:
AttackMove.IgnoreWeaponCheck=false ; boolean
```

### Attack non-threatening structures

- You can now freely configure whether units can automatically target non-threatening structures.
- `AutoTarget.NoThreatBuildings` affects player-controlled units, `AutoTargetAI.NoThreatBuildings` affects other units.

In `rulesmd.ini`:
```ini
[General]
AutoTarget.NoThreatBuildings=false ; boolean
AutoTargetAI.NoThreatBuildings=true ; boolean

[SOMETECHNO] ; TechnoType
AttackNoThreatBuildings= ; boolean, default to [General] -> AutoTarget.NoThreatBuildings/AutoTargetAI.NoThreatBuildings.
```

### Aircraft spawner customizations

![image](_static/images/spawnrange-01.gif)
Expand Down Expand Up @@ -2568,6 +2583,16 @@ In `rulesmd.ini`:
AreaFire.Target=base ; AreaFire Target Enumeration (base|self|random)
```

### Attack non-threatening structures

- `AttackNoThreatBuildings` permits shooters to attack non-threatening structures. This setting overrides other configurations.

In `rulesmd.ini`:
```ini
[SOMEWEAPON] ; WeaponType
AttackNoThreatBuildings= ; boolean
```

### Burst delay customizations

- `Burst.Delays` allows specifying weapon-specific burst shot delays. Takes precedence over the old `BurstDelayX` logic available on VehicleTypes, functions with Infantry & BuildingType weapons (AircraftTypes are not supported due to their weapon firing system being completely different) and allows every shot of `Burst` to have a separate delay instead of only first four shots.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ New:
- [Unlimbo Detonate warhead](New-or-Enhanced-Logics.md#unlimbo-detonate-warhead) (by FlyStar)
- Attack and damage technos underground (by TaranDahl)
- Fast access structure (by FlyStar)
- Attack non-threatening structures extensions (by FlyStar)

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 @@ -323,6 +323,9 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)

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

this->AutoTarget_NoThreatBuildings.Read(exINI, GameStrings::General, "AutoTarget.NoThreatBuildings");
this->AutoTargetAI_NoThreatBuildings.Read(exINI, GameStrings::General, "AutoTargetAI.NoThreatBuildings");

// Section AITargetTypes
int itemsCount = pINI->GetKeyCount("AITargetTypes");
for (int i = 0; i < itemsCount; ++i)
Expand Down Expand Up @@ -595,6 +598,8 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->Parasite_GrappleAnim)
.Process(this->InfantryAutoDeploy)
.Process(this->AdjacentWallDamage)
.Process(this->AutoTarget_NoThreatBuildings)
.Process(this->AutoTargetAI_NoThreatBuildings)
;
}

Expand Down
8 changes: 7 additions & 1 deletion src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,10 @@ class RulesExt
Valueable<bool> InfantryAutoDeploy;

Valueable<int> AdjacentWallDamage;


Valueable<bool> AutoTarget_NoThreatBuildings;
Valueable<bool> AutoTargetAI_NoThreatBuildings;

ExtData(RulesClass* OwnerObject) : Extension<RulesClass>(OwnerObject)
, Storage_TiberiumIndex { -1 }
, HarvesterDumpAmount { 0.0f }
Expand Down Expand Up @@ -486,6 +489,9 @@ class RulesExt
, Parasite_GrappleAnim {}
, InfantryAutoDeploy { false }
, AdjacentWallDamage { 200 }

, AutoTarget_NoThreatBuildings { false }
, AutoTargetAI_NoThreatBuildings { true }
{ }

virtual ~ExtData() = default;
Expand Down
17 changes: 0 additions & 17 deletions src/Ext/Techno/Hooks.TargetEvaluation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,23 +197,6 @@ DEFINE_HOOK(0x4DF3A0, FootClass_UpdateAttackMove_SelectNewTarget, 0x6)
return 0;
}

DEFINE_HOOK(0x6F85AB, TechnoClass_CanAutoTargetObject_AggressiveAttackMove, 0x6)
{
enum { ContinueCheck = 0x6F85BA, CanTarget = 0x6F8604 };

GET(TechnoClass* const, pThis, EDI);

if (!pThis->Owner->IsControlledByHuman())
return CanTarget;

if (!pThis->MegaMissionIsAttackMove())
return ContinueCheck;

const auto pExt = TechnoExt::ExtMap.Find(pThis);

return pExt->TypeExtData->AttackMove_Aggressive.Get(RulesExt::Global()->AttackMove_Aggressive) ? CanTarget : ContinueCheck;
}

#pragma endregion

#pragma region HealingWeapons
Expand Down
42 changes: 42 additions & 0 deletions src/Ext/Techno/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1459,3 +1459,45 @@ DEFINE_HOOK(0x6F7E1E, TechnoClass_CanAutoTargetObject_AU, 0x6)
}

#pragma endregion

#pragma region AutoTargetExtension

namespace CanAutoTargetTemp
{
TechnoTypeExt::ExtData* TypeExtData;
WeaponTypeExt::ExtData* WeaponExt;
}

DEFINE_HOOK(0x6F7E30, TechnoClass_CanAutoTarget_SetContent, 0x6)
{
GET(TechnoClass*, pThis, EDI);
GET(WeaponTypeClass*, pWeapon, EBP);

CanAutoTargetTemp::TypeExtData = TechnoExt::ExtMap.Find(pThis)->TypeExtData;
CanAutoTargetTemp::WeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);

return 0;
}

DEFINE_HOOK(0x6F85AB, TechnoClass_CanAutoTargetObject_AggressiveAttackMove, 0x6)
{
enum { ContinueCheck = 0x6F85BA, CanTarget = 0x6F8604 };

GET(TechnoClass* const, pThis, EDI);

if (!pThis->MegaMissionIsAttackMove())
return ContinueCheck;

const bool canAttack = CanAutoTargetTemp::WeaponExt->AttackNoThreatBuildings.Get(
CanAutoTargetTemp::TypeExtData->AutoTarget_NoThreatBuildings.Get(pThis->Owner->IsControlledByHuman()
? RulesExt::Global()->AutoTarget_NoThreatBuildings : RulesExt::Global()->AutoTargetAI_NoThreatBuildings));

if (!canAttack)
return ContinueCheck;

const auto pExt = TechnoExt::ExtMap.Find(pThis);

return pExt->TypeExtData->AttackMove_Aggressive.Get(RulesExt::Global()->AttackMove_Aggressive) ? CanTarget : ContinueCheck;
}

#pragma endregion
4 changes: 4 additions & 0 deletions src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,8 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
// VoiceIFVRepair from Ares 0.2
this->VoiceIFVRepair.Read(exINI, pSection, "VoiceIFVRepair");
this->ParseVoiceWeaponAttacks(exINI, pSection, this->VoiceWeaponAttacks, this->VoiceEliteWeaponAttacks);

this->AutoTarget_NoThreatBuildings.Read(exINI, pSection, "AutoTarget.NoThreatBuildings");
}

void TechnoTypeExt::ExtData::LoadFromINIByWhatAmI(INI_EX& exINI, const char* pSection, INI_EX& exArtINI, const char* pArtSection)
Expand Down Expand Up @@ -1609,6 +1611,8 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->InfantryAutoDeploy)

.Process(this->TurretResponse)

.Process(this->AutoTarget_NoThreatBuildings)
;
}
void TechnoTypeExt::ExtData::LoadFromStream(PhobosStreamReader& Stm)
Expand Down
4 changes: 4 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ class TechnoTypeExt

Nullable<bool> TurretResponse;

Nullable<bool> AutoTarget_NoThreatBuildings;

ExtData(TechnoTypeClass* OwnerObject) : Extension<TechnoTypeClass>(OwnerObject)
, HealthBar_Hide { false }
, HealthBar_HidePips { false }
Expand Down Expand Up @@ -812,6 +814,8 @@ class TechnoTypeExt
, InfantryAutoDeploy {}

, TurretResponse {}

, AutoTarget_NoThreatBuildings {}
{ }

virtual ~ExtData() = default;
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/WeaponType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->DelayedFire_OnlyOnInitialBurst.Read(exINI, pSection, "DelayedFire.OnlyOnInitialBurst");
this->DelayedFire_AnimOffset.Read(exINI, pSection, "DelayedFire.AnimOffset");
this->DelayedFire_AnimOnTurret.Read(exINI, pSection, "DelayedFire.AnimOnTurret");
this->AttackNoThreatBuildings.Read(exINI, pSection, "AttackNoThreatBuildings");

// handle SkipWeaponPicking
if (this->CanTarget != AffectedTarget::All || this->CanTargetHouses != AffectedHouse::All
Expand Down Expand Up @@ -237,6 +238,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm)
.Process(this->DelayedFire_OnlyOnInitialBurst)
.Process(this->DelayedFire_AnimOffset)
.Process(this->DelayedFire_AnimOnTurret)
.Process(this->AttackNoThreatBuildings)
;
};

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 @@ -91,6 +91,7 @@ class WeaponTypeExt
Valueable<bool> DelayedFire_OnlyOnInitialBurst;
Nullable<CoordStruct> DelayedFire_AnimOffset;
Valueable<bool> DelayedFire_AnimOnTurret;
Nullable<bool> AttackNoThreatBuildings;

bool SkipWeaponPicking;

Expand Down Expand Up @@ -164,6 +165,7 @@ class WeaponTypeExt
, DelayedFire_OnlyOnInitialBurst { false }
, DelayedFire_AnimOffset {}
, DelayedFire_AnimOnTurret { true }
, AttackNoThreatBuildings {}
{ }

int GetBurstDelay(int burstIndex) const;
Expand Down