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 @@ -689,6 +689,7 @@ This page lists all the individual contributions to the project by their author.
- Fixed an issue that retaliation will make the unit keep switching among multiple targets with the same amount of threat
- Fix an issue where units recruited by a team with `AreTeamMembersRecruitable=false` cannot be recruited even if they have been liberated by that team
- Global default value for `DefaultToGuardArea`
- Customize several behavior of mission area guard
- **solar-III (凤九歌)**
- Target scanning delay customization (documentation)
- Skip target scanning function calling for unarmed technos (documentation)
Expand Down
21 changes: 21 additions & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,27 @@ FallingDownDamage= ; integer / percentage
FallingDownDamage.Water= ; integer / percentage
```

### Customize several behavior of mission area guard

- In vanilla, technos in area guard mission will use the focus as the center of targeting and stray.
- Now you can change the center to itself by using `AreaGuard.UseSelfAsCenter=true`. (For stray, what is checked is the distance between the techno and the current target)
- In vanilla, technos in area guard mission will do targeting in an extended range (roughly 2 times of the guard range).
- Now you can change the range to the guard range by using `AreaGuard.TargetingInRange=true`.
- In vanilla, technos in area guard mission will not stray unless it has no destination.
- Now you can change the behavior by using `AreaGuard.StrayIgnoreDestination=true`.

In `rulesmd.ini`:
```ini
[General]
AreaGuard.UseSelfAsCenter= ; boolean
AreaGuard.TargetingInRange= ; boolean
AreaGuard.StrayIgnoreDestination= ; boolean
```

```{note}
In vanilla, if `GuardRange` is not set, then the guard range will be automatically deduced based on the weapon range.
```

### Damaged speed customization

- In vanilla, units using drive/ship loco will has hardcoded speed multiplier when damaged. Now you can customize it.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ New:
- [Customizable paradropped unit missions](Fixed-or-Improved-Logics.md#customizable-paradrop-missions) (by Starkku)
- Option to scale `PowerSurplus` setting if enabled to current power drain with `PowerSurplus.ScaleToDrainAmount` (by Starkku)
- Global default value for `DefaultToGuardArea` (by TaranDahl)
- [Customize several behavior of mission area guard](Fixed-or-Improved-Logics.md#customize-several-behavior-of-mission-area-guard) (by TaranDahl)

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

this->AreaGuard_UseSelfAsCenter.Read(exINI, GameStrings::General, "AreaGuard.UseSelfAsCenter");
this->AreaGuard_TargetingInRange.Read(exINI, GameStrings::General, "AreaGuard.TargetingInRange");
this->AreaGuard_StrayIgnoreDestination.Read(exINI, GameStrings::General, "AreaGuard.StrayIgnoreDestination");

// Section AITargetTypes
int itemsCount = pINI->GetKeyCount("AITargetTypes");
for (int i = 0; i < itemsCount; ++i)
Expand Down Expand Up @@ -660,6 +664,9 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->ParadropMission)
.Process(this->AIParadropMission)
.Process(this->DefaultToGuardArea)
.Process(this->AreaGuard_UseSelfAsCenter)
.Process(this->AreaGuard_TargetingInRange)
.Process(this->AreaGuard_StrayIgnoreDestination)
;
}

Expand Down
8 changes: 7 additions & 1 deletion src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <RulesClass.h>
#include <Utilities/Container.h>
Expand Down Expand Up @@ -311,6 +311,9 @@ class RulesExt
Valueable<Mission> AIParadropMission;

Valueable<bool> DefaultToGuardArea;
Valueable<bool> AreaGuard_UseSelfAsCenter;
Valueable<bool> AreaGuard_TargetingInRange;
Valueable<bool> AreaGuard_StrayIgnoreDestination;

ExtData(RulesClass* OwnerObject) : Extension<RulesClass>(OwnerObject)
, Storage_TiberiumIndex { -1 }
Expand Down Expand Up @@ -566,6 +569,9 @@ class RulesExt
, AIParadropMission { Mission::Hunt }

, DefaultToGuardArea { false }
, AreaGuard_UseSelfAsCenter { false }
, AreaGuard_TargetingInRange { false }
, AreaGuard_StrayIgnoreDestination { false }
{ }

virtual ~ExtData() = default;
Expand Down
33 changes: 33 additions & 0 deletions src/Ext/Techno/Hooks.Targeting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,36 @@ DEFINE_HOOK(0x6F7CE2, TechnoClass_CanAutoTargetObject_IronCurtain, 0x6)

return 0;
}

#pragma region AreaGuard

DEFINE_HOOK(0x4D6E9F, FootClass_MissionAreaGuard_UseSelfAsCenter, 0x6)
{
enum { CheckDist = 0x4D6EAF, ResetTarget = 0x4D6ED1 };

GET(FootClass*, pThis, ESI);

if (!RulesExt::Global()->AreaGuard_StrayIgnoreDestination && pThis->Destination)
return ResetTarget;

R->EAX(pThis->DistanceFrom(RulesExt::Global()->AreaGuard_UseSelfAsCenter ? pThis->Target : pThis->ArchiveTarget));
return CheckDist;
}

namespace AreaGuard_UseSelfAsCenterContext
{
CoordStruct crd;
}

DEFINE_HOOK(0x4D6EFD, FootClass_MissionAreaGuard_Extend, 0x6)
{
enum { SkipGameCode = 0x4D6F03 };

GET(FootClass*, pThis, ESI);
AreaGuard_UseSelfAsCenterContext::crd = (RulesExt::Global()->AreaGuard_UseSelfAsCenter ? pThis : pThis->ArchiveTarget)->GetCoords();
R->EAX(&AreaGuard_UseSelfAsCenterContext::crd);
R->Stack(0, RulesExt::Global()->AreaGuard_TargetingInRange ? ThreatType::Range : ThreatType::Area);
return 0;
}

#pragma endregion