Skip to content

Commit 4ab5de1

Browse files
committed
Berzerk / Psychedelic duration stacking customization
1 parent 47b4713 commit 4ab5de1

12 files changed

Lines changed: 152 additions & 0 deletions

File tree

CREDITS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ This page lists all the individual contributions to the project by their author.
292292
- Fix vehicles disguised as trees incorrectly displaying veterancy insignia when they shouldn't
293293
- GapGen + SpySat desync fix
294294
- Frame CRC generation rewrite
295+
- Berzerk duration stacking behaviour customization
295296
- **Morton (MortonPL)**:
296297
- `XDrawOffset` for animations
297298
- Shield passthrough & absorption

docs/Fixed-or-Improved-Logics.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,6 +2446,19 @@ AllowBerzerkOnAllies=false ; boolean
24462446
No per-warhead setting because `AffectsAllies` etc. is respected.
24472447
```
24482448

2449+
### Berzerk (Psychedelic) duration stacking customization
2450+
2451+
- By default `Psychedelic` warheads override the current duration of the berzerk effect regardless of if the new duration is higher or lower than the current one. This can now be customized with `Psychedelic.StackingMode`, with both global setting under `[CombatDamage]` and per-Warhead customization.
2452+
2453+
In `rulesmd.ini`:
2454+
```ini
2455+
[CombatDamage]
2456+
Psychedelic.StackingMode=override ; Stacking mode enum (override|setifzero|min|max|add|subtract|multiply|divide)
2457+
2458+
[SOMEWARHEAD] ; WarheadType
2459+
Psychedelic.StackingMode= ; Stacking mode enum (override|setifzero|min|max|add|subtract|multiply|divide)
2460+
```
2461+
24492462
### Combat light customizations
24502463

24512464
- You can now set minimum detail level at which combat light effects are shown by setting `[AudioVisual] -> CombatLightDetailLevel` or `CombatLightDetailLevel` on Warhead.

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ New:
576576
- Customize `HarvesterLoadRate` (by Noble_Fish)
577577
- [Toggle to prevent `ShrapnelWeapon` from targeting buildings multiple times](Fixed-or-Improved-Logics.md#shrapnel-enhancements) (by Starkku)
578578
- [Laser drawing Z-adjust customization](Fixed-or-Improved-Logics.md#laser-z-adjust) (by Starkku)
579+
- [Berzerk / `Psychedelic` duration stacking customization](Fixed-or-Improved-Logics.md#berzerk-psychedelic-duration-stacking-customization) (by Starkku)
579580
580581
Vanilla fixes:
581582
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)

src/Ext/Rules/Body.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)
400400
this->ExtendedPlayerRepair.Read(exINI, GameStrings::General, "ExtendedPlayerRepair");
401401

402402
this->Shrapnel_IgnoreHitBuildings.Read(exINI, GameStrings::CombatDamage, "Shrapnel.IgnoreHitBuildings");
403+
this->Psychedelic_StackingMode.Read(exINI, GameStrings::CombatDamage, "Psychedelic.StackingMode");
403404

404405
// Section AITargetTypes
405406
int itemsCount = pINI->GetKeyCount("AITargetTypes");
@@ -726,6 +727,7 @@ void RulesExt::ExtData::Serialize(T& Stm)
726727
.Process(this->FiringAnim_Update)
727728
.Process(this->ExtendedPlayerRepair)
728729
.Process(this->Shrapnel_IgnoreHitBuildings)
730+
.Process(this->Psychedelic_StackingMode)
729731
;
730732
}
731733

src/Ext/Rules/Body.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ class RulesExt
348348
Valueable<bool> ShipLocomotorMakesWake;
349349

350350
Valueable<bool> Shrapnel_IgnoreHitBuildings;
351+
352+
Valueable<StackingMode> Psychedelic_StackingMode;
351353

352354
ExtData(RulesClass* OwnerObject) : Extension<RulesClass>(OwnerObject)
353355
, Storage_TiberiumIndex { -1 }
@@ -636,7 +638,9 @@ class RulesExt
636638
, ShipLocomotorMakesWake { true }
637639
, FiringAnim_Update { false }
638640
, ExtendedPlayerRepair { false }
641+
639642
, Shrapnel_IgnoreHitBuildings { false }
643+
, Psychedelic_StackingMode { StackingMode::Override }
640644
{ }
641645

642646
virtual ~ExtData() = default;

src/Ext/WarheadType/Body.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
410410

411411
this->Taunt.Read(exINI, pSection, "Taunt");
412412

413+
this->Psychedelic_StackingMode.Read(exINI, pSection, "Psychedelic.StackingMode");
414+
413415
// Convert.From & Convert.To
414416
TypeConvertGroup::Parse(this->Convert_Pairs, exINI, pSection, AffectedHouse::All);
415417

@@ -742,6 +744,8 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
742744

743745
.Process(this->Taunt)
744746

747+
.Process(this->Psychedelic_StackingMode)
748+
745749
// Ares tags
746750
.Process(this->AffectsEnemies)
747751
.Process(this->AffectsOwner)

src/Ext/WarheadType/Body.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ class WarheadTypeExt
247247

248248
Valueable<bool> Taunt;
249249

250+
Nullable<StackingMode> Psychedelic_StackingMode;
251+
250252
// Ares tags
251253
// http://ares-developers.github.io/Ares-docs/new/warheads/general.html
252254
Valueable<bool> AffectsEnemies;
@@ -522,6 +524,8 @@ class WarheadTypeExt
522524
, ApplyPerTargetEffectsOnDetonate {}
523525

524526
, Taunt { false }
527+
528+
, Psychedelic_StackingMode {}
525529
{ }
526530

527531
void ApplyConvert(HouseClass* pHouse, TechnoClass* pTarget);

src/Ext/WarheadType/Hooks.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,17 @@ DEFINE_HOOK(0x48DC90, MapClass_UnselectAll_ClearLimboLaunchers, 0x5)
665665
}
666666

667667
#pragma endregion
668+
669+
DEFINE_HOOK(0x701D6B, TechnoClass_ReceiveDamage_Psychedelic, 0x6)
670+
{
671+
enum { SkipGameCode = 0x701D71 };
672+
673+
GET(TechnoClass*, pThis, ESI);
674+
GET(WarheadTypeClass*, pWH, EBP);
675+
GET(int, damage, EAX);
676+
677+
auto const pWHExt = WarheadTypeExt::ExtMap.Find(pWH);
678+
EnumFunctions::CalcValueWithStackingMode(pThis->BerzerkDurationLeft, damage, pWHExt->Psychedelic_StackingMode);
679+
680+
return SkipGameCode;
681+
}

src/Utilities/Enum.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,18 @@ enum class DamageDisplayType
243243
Intercept = 2
244244
};
245245

246+
enum class StackingMode
247+
{
248+
Override = 0,
249+
SetIfZero = 1,
250+
Min = 2,
251+
Max = 3,
252+
Add = 4,
253+
Subtract = 5,
254+
Multiply = 6,
255+
Divide = 7
256+
};
257+
246258
enum class ChronoSparkleDisplayPosition : unsigned char
247259
{
248260
None = 0x0,

src/Utilities/EnumFunctions.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "EnumFunctions.h"
22

3+
#include <Utilities/GeneralUtils.h>
4+
35
bool EnumFunctions::CanTargetHouse(AffectedHouse flags, HouseClass* ownerHouse, HouseClass* targetHouse)
46
{
57
if (flags == AffectedHouse::All)
@@ -111,3 +113,48 @@ bool EnumFunctions::AreCellAndObjectsEligible(CellClass* const pCell, AffectedTa
111113

112114
return true;
113115
}
116+
117+
bool EnumFunctions::CalcValueWithStackingMode(int& oldValue, int newValue, StackingMode stackingMode)
118+
{
119+
bool valueChanged = true;
120+
int oldValueTemp = oldValue;
121+
122+
switch (stackingMode)
123+
{
124+
case StackingMode::Override:
125+
oldValue = newValue;
126+
break;
127+
case StackingMode::SetIfZero:
128+
if (oldValue == 0)
129+
oldValue = newValue;
130+
else
131+
valueChanged = false;
132+
break;
133+
case StackingMode::Min:
134+
oldValue = Math::min(oldValue, newValue);
135+
break;
136+
case StackingMode::Max:
137+
oldValue = Math::max(oldValue, newValue);
138+
break;
139+
case StackingMode::Add:
140+
oldValue += newValue;
141+
break;
142+
case StackingMode::Subtract:
143+
oldValue -= newValue;
144+
break;
145+
case StackingMode::Multiply:
146+
oldValue = GeneralUtils::SafeMultiply(oldValue, newValue);
147+
break;
148+
case StackingMode::Divide:
149+
if (newValue != 0)
150+
oldValue /= newValue;
151+
else
152+
valueChanged = false;
153+
break;
154+
default:
155+
valueChanged = false;
156+
break;
157+
}
158+
159+
return valueChanged && oldValueTemp != oldValue;
160+
}

0 commit comments

Comments
 (0)