Skip to content

Commit aadd0a1

Browse files
authored
[Customized] Extended gattling rate down logic (#1469)
- Now you can customize some effects of RateDown. - `RateDown.Delay` controls the delay before using `RateDown` to reduce the gattling value. - `RateDown.Reset` controls whether to reset the gattling value directly when the techno has no target or changes targets. - `RateDown.Cover.Value` replaces the original `RateDown` when techno's ammo is lower than `RateDown.Cover.AmmoBelow`. In `rulesmd.ini`: ```ini [SOMETECHNO] ; TechnoType, `IsGattling=yes` RateDown.Delay=0 ; integer, game frames RateDown.Reset=false ; boolean RateDown.Cover.Value=0 ; integer RateDown.Cover.AmmoBelow=-2 ; integer ```
1 parent da2f6f1 commit aadd0a1

File tree

9 files changed

+170
-0
lines changed

9 files changed

+170
-0
lines changed

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ This page lists all the individual contributions to the project by their author.
390390
- Enhanced Bombard trajectory
391391
- No turret unit turn to the target
392392
- Damage multiplier for different houses
393+
- Extended gattling rate down logic
393394
- **Ollerus**
394395
- Build limit group enhancement
395396
- Customizable rocker amplitude

docs/New-or-Enhanced-Logics.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,6 +1577,22 @@ Convert.HumanToComputer= ; TechnoType
15771577
Convert.ComputerToHuman= ; TechnoType
15781578
```
15791579

1580+
### Extended gattling rate down logic
1581+
1582+
- Now you can customize some effects of RateDown.
1583+
- `RateDown.Delay` controls the delay before using `RateDown` to reduce the gattling value.
1584+
- `RateDown.Reset` controls whether to reset the gattling value directly when the techno has no target or changes targets.
1585+
- `RateDown.Cover.Value` replaces the original `RateDown` when techno's ammo is lower than `RateDown.Cover.AmmoBelow`.
1586+
1587+
In `rulesmd.ini`:
1588+
```ini
1589+
[SOMETECHNO] ; TechnoType, `IsGattling=yes`
1590+
RateDown.Delay=0 ; integer, game frames
1591+
RateDown.Reset=false ; boolean
1592+
RateDown.Cover.Value=0 ; integer
1593+
RateDown.Cover.AmmoBelow=-2 ; integer
1594+
```
1595+
15801596
## Terrain
15811597

15821598
### Destroy animation & sound

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ New:
327327
- No turret unit turn to the target (by CrimRecya & TaranDahl)
328328
- Damage multiplier for different houses (by CrimRecya)
329329
- Customizable duration for electric bolts (by Starkku)
330+
- Extended gattling rate down logic (by CrimRecya)
330331
331332
Vanilla fixes:
332333
- Prevent the units with locomotors that cause problems from entering the tank bunker (by TaranDahl)

src/Ext/Techno/Body.Update.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ void TechnoExt::ExtData::OnEarlyUpdate()
4343
this->UpdateLaserTrails();
4444
this->DepletedAmmoActions();
4545
this->UpdateAttachEffects();
46+
this->UpdateGattlingRateDownReset();
4647
}
4748

4849
void TechnoExt::ExtData::ApplyInterceptor()
@@ -614,6 +615,25 @@ void TechnoExt::ExtData::UpdateMindControlAnim()
614615
}
615616
}
616617

618+
void TechnoExt::ExtData::UpdateGattlingRateDownReset()
619+
{
620+
const auto pTypeExt = this->TypeExtData;
621+
622+
if (pTypeExt->OwnerObject()->IsGattling)
623+
{
624+
const auto pThis = this->OwnerObject();
625+
626+
if (pTypeExt->RateDown_Reset && (!pThis->Target || this->LastTargetID != pThis->Target->UniqueID))
627+
{
628+
this->LastTargetID = pThis->Target ? pThis->Target->UniqueID : 0xFFFFFFFF;
629+
pThis->GattlingValue = 0;
630+
pThis->CurrentGattlingStage = 0;
631+
this->AccumulatedGattlingValue = 0;
632+
this->ShouldUpdateGattlingValue = false;
633+
}
634+
}
635+
}
636+
617637
void TechnoExt::ApplyGainedSelfHeal(TechnoClass* pThis)
618638
{
619639
if (!RulesExt::Global()->GainSelfHealAllowMultiplayPassive && pThis->Owner->Type->MultiplayPassive)

src/Ext/Techno/Body.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,9 @@ void TechnoExt::ExtData::Serialize(T& Stm)
555555
.Process(this->WHAnimRemainingCreationInterval)
556556
.Process(this->FiringObstacleCell)
557557
.Process(this->IsDetachingForCloak)
558+
.Process(this->LastTargetID)
559+
.Process(this->AccumulatedGattlingValue)
560+
.Process(this->ShouldUpdateGattlingValue)
558561
.Process(this->OriginalPassengerOwner)
559562
.Process(this->HasRemainingWarpInDelay)
560563
.Process(this->LastWarpInDelay)

src/Ext/Techno/Body.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ class TechnoExt
5252
bool CanCurrentlyDeployIntoBuilding; // Only set on UnitClass technos with DeploysInto set in multiplayer games, recalculated once per frame so no need to serialize.
5353
CellClass* FiringObstacleCell; // Set on firing if there is an obstacle cell between target and techno, used for updating WaveClass target etc.
5454
bool IsDetachingForCloak; // Used for checking animation detaching, set to true before calling Detach_All() on techno when this anim is attached to and to false after when cloaking only.
55+
DWORD LastTargetID;
56+
int AccumulatedGattlingValue;
57+
bool ShouldUpdateGattlingValue;
5558

5659
// Used for Passengers.SyncOwner.RevertOnExit instead of TechnoClass::InitialOwner / OriginallyOwnedByHouse,
5760
// as neither is guaranteed to point to the house the TechnoClass had prior to entering transport and cannot be safely overridden.
@@ -92,6 +95,9 @@ class TechnoExt
9295
, CanCurrentlyDeployIntoBuilding { false }
9396
, FiringObstacleCell {}
9497
, IsDetachingForCloak { false }
98+
, LastTargetID { 0xFFFFFFFF }
99+
, AccumulatedGattlingValue { 0 }
100+
, ShouldUpdateGattlingValue { false }
95101
, OriginalPassengerOwner {}
96102
, HasRemainingWarpInDelay { false }
97103
, LastWarpInDelay { 0 }
@@ -112,6 +118,7 @@ class TechnoExt
112118
void UpdateTypeData(TechnoTypeClass* currentType);
113119
void UpdateLaserTrails();
114120
void UpdateAttachEffects();
121+
void UpdateGattlingRateDownReset();
115122
void UpdateCumulativeAttachEffects(AttachEffectTypeClass* pAttachEffectType, AttachEffectClass* pRemoved = nullptr);
116123
void RecalculateStatMultipliers();
117124
void UpdateTemporal();

src/Ext/Techno/Hooks.Misc.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,108 @@ DEFINE_HOOK(0x74691D, UnitClass_UpdateDisguise_EMP, 0x6)
338338

339339
#pragma endregion
340340

341+
#pragma region ExtendedGattlingRateDown
342+
343+
DEFINE_HOOK(0x70DE40, BuildingClass_sub_70DE40_GattlingRateDownDelay, 0xA)
344+
{
345+
enum { Return = 0x70DE62 };
346+
347+
GET(BuildingClass* const, pThis, ECX);
348+
GET_STACK(int, rateDown, STACK_OFFSET(0x0, 0x4));
349+
350+
const auto pExt = TechnoExt::ExtMap.Find(pThis);
351+
const auto pTypeExt = pExt->TypeExtData;
352+
353+
if (pTypeExt->RateDown_Delay < 0)
354+
return Return;
355+
356+
++pExt->AccumulatedGattlingValue;
357+
auto remain = pExt->AccumulatedGattlingValue;
358+
359+
if (!pExt->ShouldUpdateGattlingValue)
360+
remain -= pTypeExt->RateDown_Delay;
361+
362+
if (remain <= 0)
363+
return Return;
364+
365+
// Time's up
366+
pExt->AccumulatedGattlingValue = 0;
367+
pExt->ShouldUpdateGattlingValue = true;
368+
369+
if (pThis->Ammo <= pTypeExt->RateDown_Cover_AmmoBelow)
370+
rateDown = pTypeExt->RateDown_Cover_Value;
371+
372+
if (!rateDown)
373+
{
374+
pThis->GattlingValue = 0;
375+
return Return;
376+
}
377+
378+
auto newValue = pThis->GattlingValue;
379+
newValue -= (rateDown * remain);
380+
pThis->GattlingValue = (newValue <= 0) ? 0 : newValue;
381+
return Return;
382+
}
383+
384+
DEFINE_HOOK(0x70DE70, TechnoClass_sub_70DE70_GattlingRateDownReset, 0x5)
385+
{
386+
GET(TechnoClass* const, pThis, ECX);
387+
388+
const auto pExt = TechnoExt::ExtMap.Find(pThis);
389+
pExt->AccumulatedGattlingValue = 0;
390+
pExt->ShouldUpdateGattlingValue = false;
391+
392+
return 0;
393+
}
394+
395+
DEFINE_HOOK(0x70E01E, TechnoClass_sub_70E000_GattlingRateDownDelay, 0x6)
396+
{
397+
enum { SkipGameCode = 0x70E04D };
398+
399+
GET(TechnoClass* const, pThis, ESI);
400+
GET_STACK(int, rateMult, STACK_OFFSET(0x10, 0x4));
401+
402+
const auto pExt = TechnoExt::ExtMap.Find(pThis);
403+
const auto pTypeExt = pExt->TypeExtData;
404+
405+
if (pTypeExt->RateDown_Delay < 0)
406+
return SkipGameCode;
407+
408+
pExt->AccumulatedGattlingValue += rateMult;
409+
auto remain = pExt->AccumulatedGattlingValue;
410+
411+
if (!pExt->ShouldUpdateGattlingValue)
412+
remain -= pTypeExt->RateDown_Delay;
413+
414+
if (remain <= 0 && rateMult)
415+
return SkipGameCode;
416+
417+
// Time's up
418+
pExt->AccumulatedGattlingValue = 0;
419+
pExt->ShouldUpdateGattlingValue = true;
420+
421+
if (!rateMult)
422+
{
423+
pThis->GattlingValue = 0;
424+
return SkipGameCode;
425+
}
426+
427+
const auto rateDown = (pThis->Ammo <= pTypeExt->RateDown_Cover_AmmoBelow) ? pTypeExt->RateDown_Cover_Value.Get() : pTypeExt->OwnerObject()->RateDown;
428+
429+
if (!rateDown)
430+
{
431+
pThis->GattlingValue = 0;
432+
return SkipGameCode;
433+
}
434+
435+
auto newValue = pThis->GattlingValue;
436+
newValue -= (rateDown * remain);
437+
pThis->GattlingValue = (newValue <= 0) ? 0 : newValue;
438+
return SkipGameCode;
439+
}
440+
441+
#pragma endregion
442+
341443
#pragma region NoTurretUnitAlwaysTurnToTarget
342444

343445
DEFINE_HOOK(0x7410BB, UnitClass_GetFireError_CheckFacingError, 0x8)

src/Ext/TechnoType/Body.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,11 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
464464
this->BuildLimitGroup_ExtraLimit_MaxCount.Read(exINI, pSection, "BuildLimitGroup.ExtraLimit.MaxCount");
465465
this->BuildLimitGroup_ExtraLimit_MaxNum.Read(exINI, pSection, "BuildLimitGroup.ExtraLimit.MaxNum");
466466

467+
this->RateDown_Delay.Read(exINI, pSection, "RateDown.Delay");
468+
this->RateDown_Reset.Read(exINI, pSection, "RateDown.Reset");
469+
this->RateDown_Cover_Value.Read(exINI, pSection, "RateDown.Cover.Value");
470+
this->RateDown_Cover_AmmoBelow.Read(exINI, pSection, "RateDown.Cover.AmmoBelow");
471+
467472
this->NoTurret_TrackTarget.Read(exINI, pSection, "NoTurret.TrackTarget");
468473

469474
this->Wake.Read(exINI, pSection, "Wake");
@@ -849,6 +854,11 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
849854
.Process(this->BuildLimitGroup_ExtraLimit_MaxCount)
850855
.Process(this->BuildLimitGroup_ExtraLimit_MaxNum)
851856

857+
.Process(this->RateDown_Delay)
858+
.Process(this->RateDown_Reset)
859+
.Process(this->RateDown_Cover_Value)
860+
.Process(this->RateDown_Cover_AmmoBelow)
861+
852862
.Process(this->NoTurret_TrackTarget)
853863

854864
.Process(this->Wake)

src/Ext/TechnoType/Body.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,11 @@ class TechnoTypeExt
233233
ValueableVector<int> BuildLimitGroup_ExtraLimit_MaxCount;
234234
Valueable<int> BuildLimitGroup_ExtraLimit_MaxNum;
235235

236+
Valueable<int> RateDown_Delay;
237+
Valueable<bool> RateDown_Reset;
238+
Valueable<int> RateDown_Cover_Value;
239+
Valueable<int> RateDown_Cover_AmmoBelow;
240+
236241
Nullable<bool> NoTurret_TrackTarget;
237242

238243
Nullable<AnimTypeClass*> Wake;
@@ -471,6 +476,11 @@ class TechnoTypeExt
471476
, BuildLimitGroup_ExtraLimit_MaxCount {}
472477
, BuildLimitGroup_ExtraLimit_MaxNum { 0 }
473478

479+
, RateDown_Delay { 0 }
480+
, RateDown_Reset { false }
481+
, RateDown_Cover_Value { 0 }
482+
, RateDown_Cover_AmmoBelow { -2 }
483+
474484
, NoTurret_TrackTarget {}
475485

476486
, Wake { }

0 commit comments

Comments
 (0)