Skip to content

[Highly Customized] Directional armor #1623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 17 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 11 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 @@ -372,6 +372,7 @@ This page lists all the individual contributions to the project by their author.
- Enhanced reveal & gap warhead
- Fix an issue that teleport units board transport vehicles on the bridge will create an impassable invisible barrier, which may cause the game to freeze or even crash
- Fix wrong shadow when a vehicle has hover locomotor and is being lifted by `IsLocomotor=yes` warhead
- Directional armor
- **Apollo** - Translucent SHP drawing patches
- **ststl**:
- Customizable `ShowTimer` priority of superweapons
Expand Down
32 changes: 32 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1764,6 +1764,38 @@ JumpjetTilt.SidewaysRotationFactor=1.0 ; floating point value
JumpjetTilt.SidewaysSpeedFactor=1.0 ; floating point value
```

### Directional armor

- The damage suffered by the vehicle can now be affected by the hit direction.
- The front and rear judgment ranges are always symmetrical. A front angle of 0.5 indicates that the front direction is the axis, and the 45 degree angle range on both sides belongs to the front judgment range.
A front angle of 1.0 indicates that the 90 degree angle range on both sides belongs to the front judgment range;
- The lateral range refers to the remaining angle range after excluding the front and back sides.
- The warhead needs to have `Directional=true` to enable this effect.
- `Directional.Multiplier` is an additional multiplier used to control the intensity of the effect.

In `rulesmd.ini`
```ini
[CombatDamage]
DirectionalArmor=false ; boolean
DirectionalArmor.FrontMultiplier=1.0 ; float
DirectionalArmor.SideMultiplier=1.0 ; float
DirectionalArmor.BackMultiplier=1.0 ; float
DirectionalArmor.FrontField=0.5 ; float
DirectionalArmor.BackField=0.5 ; float

[SOMEVEHICLE] ; VehicleType
DirectionalArmor= ; boolean
DirectionalArmor.FrontMultiplier= ; float
DirectionalArmor.SideMultiplier= ; float
DirectionalArmor.BackMultiplier= ; float
DirectionalArmor.FrontField= ; float
DirectionalArmor.BackField= ; float

[SOMEWARHEAD]
Directional=false ; boolean
Directional.Multiplier=1.0 ; float
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the use case of this flag?

```

## Warheads

```{hint}
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ New:
- Jumpjet Tilts While Moving (by CrimRecya)
- [Spawned aircraft facing to match turret toggle](New-or-Enhanced-Logics.md#aircraft-spawner-customizations) (by Starkku)
- Removed dependency on `blowfish.dll` (by ZivDero)
- Directional armor (by NetsuNegi)

Vanilla fixes:
- Prevent the units with locomotors that cause problems from entering the tank bunker (by TaranDahl)
Expand Down
1 change: 1 addition & 0 deletions src/Ext/Bullet/Trajectories/PhobosTrajectory.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <Ext/BulletType/Body.h>
#include <Ext/Bullet/Body.h>
#include <Ext/WeaponType/Body.h>
#include <Ext/WarheadType/Body.h>

#include <BulletClass.h>
#include <Helpers/Macro.h>
Expand Down
13 changes: 13 additions & 0 deletions src/Ext/Rules/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ void RulesExt::ExtData::LoadBeforeTypeData(RulesClass* pThis, CCINIClass* pINI)
this->DamageAlliesMultiplier.Read(exINI, GameStrings::CombatDamage, "DamageAlliesMultiplier");
this->DamageEnemiesMultiplier.Read(exINI, GameStrings::CombatDamage, "DamageEnemiesMultiplier");

this->DirectionalArmor.Read(exINI, GameStrings::CombatDamage, "DirectionalArmor");
this->DirectionalArmor_FrontMultiplier.Read(exINI, GameStrings::CombatDamage, "DirectionalArmor.FrontMultiplier");
this->DirectionalArmor_SideMultiplier.Read(exINI, GameStrings::CombatDamage, "DirectionalArmor.SideMultiplier");
this->DirectionalArmor_BackMultiplier.Read(exINI, GameStrings::CombatDamage, "DirectionalArmor.BackMultiplier");
this->DirectionalArmor_FrontField.Read(exINI, GameStrings::CombatDamage, "DirectionalArmor.FrontField");
this->DirectionalArmor_BackField.Read(exINI, GameStrings::CombatDamage, "DirectionalArmor.BackField");

this->AircraftLevelLightMultiplier.Read(exINI, GameStrings::AudioVisual, "AircraftLevelLightMultiplier");
this->JumpjetLevelLightMultiplier.Read(exINI, GameStrings::AudioVisual, "JumpjetLevelLightMultiplier");

Expand Down Expand Up @@ -429,6 +436,12 @@ void RulesExt::ExtData::Serialize(T& Stm)
.Process(this->DamageOwnerMultiplier)
.Process(this->DamageAlliesMultiplier)
.Process(this->DamageEnemiesMultiplier)
.Process(this->DirectionalArmor)
.Process(this->DirectionalArmor_FrontMultiplier)
.Process(this->DirectionalArmor_SideMultiplier)
.Process(this->DirectionalArmor_BackMultiplier)
.Process(this->DirectionalArmor_FrontField)
.Process(this->DirectionalArmor_BackField)
.Process(this->AircraftLevelLightMultiplier)
.Process(this->JumpjetLevelLightMultiplier)
.Process(this->VoxelLightSource)
Expand Down
15 changes: 15 additions & 0 deletions src/Ext/Rules/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ class RulesExt
Valueable<double> DamageAlliesMultiplier;
Valueable<double> DamageEnemiesMultiplier;

Valueable<bool> DirectionalArmor;
Valueable<float> DirectionalArmor_FrontMultiplier;
Valueable<float> DirectionalArmor_SideMultiplier;
Valueable<float> DirectionalArmor_BackMultiplier;
Valueable<float> DirectionalArmor_FrontField;
Valueable<float> DirectionalArmor_BackField;

Valueable<double> AircraftLevelLightMultiplier;
Valueable<double> JumpjetLevelLightMultiplier;

Expand Down Expand Up @@ -325,6 +332,14 @@ class RulesExt
, DamageOwnerMultiplier { 1.0 }
, DamageAlliesMultiplier { 1.0 }
, DamageEnemiesMultiplier { 1.0 }

, DirectionalArmor { false }
, DirectionalArmor_FrontMultiplier { 1.0 }
, DirectionalArmor_SideMultiplier { 1.0 }
, DirectionalArmor_BackMultiplier { 1.0 }
, DirectionalArmor_FrontField { 0.5 }
, DirectionalArmor_BackField { 0.5 }

, AircraftLevelLightMultiplier { 1.0 }
, JumpjetLevelLightMultiplier { 0.0 }
, VoxelLightSource { }
Expand Down
15 changes: 15 additions & 0 deletions src/Ext/Techno/Hooks.ReceiveDamage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ DEFINE_HOOK(0x701900, TechnoClass_ReceiveDamage_Shield, 0x6)
else
multiplier = pWHExt->DamageOwnerMultiplier.Get(pRules->DamageOwnerMultiplier);

if (pTypeExt->DirectionalArmor.Get(RulesExt::Global()->DirectionalArmor) && pThis->WhatAmI() == AbstractType::Unit && pWHExt->HitDirection >= 0 && args->DistanceToEpicenter <= 64)
{
const int tarFacing = pThis->PrimaryFacing.Current().GetValue<16>();
const int angle = abs(pWHExt->HitDirection - tarFacing);
const int frontField = static_cast<int>(16384 * pTypeExt->DirectionalArmor_FrontField.Get(RulesExt::Global()->DirectionalArmor_FrontField));
const int backField = static_cast<int>(16384 * pTypeExt->DirectionalArmor_BackField.Get(RulesExt::Global()->DirectionalArmor_BackField));

if (angle >= 32768 - frontField && angle <= 32768 + frontField)
multiplier *= pTypeExt->DirectionalArmor_FrontMultiplier.Get(RulesExt::Global()->DirectionalArmor_FrontMultiplier) * pWHExt->Directional_Multiplier;
else if ((angle < backField && angle >= 0) || (angle > 49152 + backField && angle <= 65536))
multiplier *= pTypeExt->DirectionalArmor_BackMultiplier.Get(RulesExt::Global()->DirectionalArmor_BackMultiplier) * pWHExt->Directional_Multiplier;
else
multiplier *= pTypeExt->DirectionalArmor_SideMultiplier.Get(RulesExt::Global()->DirectionalArmor_SideMultiplier) * pWHExt->Directional_Multiplier;
}

if (multiplier != 1.0)
{
const auto sgnDamage = *args->Damage > 0 ? 1 : -1;
Expand Down
14 changes: 14 additions & 0 deletions src/Ext/TechnoType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,13 @@ void TechnoTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->KeepTargetOnMove.Read(exINI, pSection, "KeepTargetOnMove");
this->KeepTargetOnMove_ExtraDistance.Read(exINI, pSection, "KeepTargetOnMove.ExtraDistance");

this->DirectionalArmor.Read(exINI, pSection, "DirectionalArmor");
this->DirectionalArmor_FrontMultiplier.Read(exINI, pSection, "DirectionalArmor.FrontMultiplier");
this->DirectionalArmor_SideMultiplier.Read(exINI, pSection, "DirectionalArmor.SideMultiplier");
this->DirectionalArmor_BackMultiplier.Read(exINI, pSection, "DirectionalArmor.BackMultiplier");
this->DirectionalArmor_FrontField.Read(exINI, pSection, "DirectionalArmor.FrontField");
this->DirectionalArmor_BackField.Read(exINI, pSection, "DirectionalArmor.BackField");

this->Power.Read(exINI, pSection, "Power");

this->Image_ConditionYellow.Read(exINI, pSection, "Image.ConditionYellow");
Expand Down Expand Up @@ -943,6 +950,13 @@ void TechnoTypeExt::ExtData::Serialize(T& Stm)
.Process(this->KeepTargetOnMove)
.Process(this->KeepTargetOnMove_ExtraDistance)

.Process(this->DirectionalArmor)
.Process(this->DirectionalArmor_FrontMultiplier)
.Process(this->DirectionalArmor_SideMultiplier)
.Process(this->DirectionalArmor_BackMultiplier)
.Process(this->DirectionalArmor_FrontField)
.Process(this->DirectionalArmor_BackField)

.Process(this->Power)

.Process(this->Image_ConditionYellow)
Expand Down
14 changes: 14 additions & 0 deletions src/Ext/TechnoType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,13 @@ class TechnoTypeExt
Valueable<bool> KeepTargetOnMove;
Valueable<Leptons> KeepTargetOnMove_ExtraDistance;

Nullable<bool> DirectionalArmor;
Nullable<float> DirectionalArmor_FrontMultiplier;
Nullable<float> DirectionalArmor_SideMultiplier;
Nullable<float> DirectionalArmor_BackMultiplier;
Nullable<float> DirectionalArmor_FrontField;
Nullable<float> DirectionalArmor_BackField;

Valueable<int> Power;

Nullable<UnitTypeClass*> Image_ConditionYellow;
Expand Down Expand Up @@ -568,6 +575,13 @@ class TechnoTypeExt
, KeepTargetOnMove { false }
, KeepTargetOnMove_ExtraDistance { Leptons(0) }

, DirectionalArmor {}
, DirectionalArmor_FrontMultiplier {}
, DirectionalArmor_SideMultiplier {}
, DirectionalArmor_BackMultiplier {}
, DirectionalArmor_FrontField {}
, DirectionalArmor_BackField {}

, Power { }

, Image_ConditionYellow { }
Expand Down
7 changes: 7 additions & 0 deletions src/Ext/WarheadType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ void WarheadTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->Shield_Respawn_Types.Read(exINI, pSection, "Shield.Respawn.Types");
this->Shield_SelfHealing_Types.Read(exINI, pSection, "Shield.SelfHealing.Types");

this->Directional.Read(exINI, pSection, "Directional");
this->Directional_Multiplier.Read(exINI, pSection, "Directional.Multiplier");

this->NotHuman_DeathSequence.Read(exINI, pSection, "NotHuman.DeathSequence");
this->LaunchSW.Read(exINI, pSection, "LaunchSW");
this->LaunchSW_RealLaunch.Read(exINI, pSection, "LaunchSW.RealLaunch");
Expand Down Expand Up @@ -474,6 +477,9 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
.Process(this->Shield_Respawn_Types)
.Process(this->Shield_SelfHealing_Types)

.Process(this->Directional)
.Process(this->Directional_Multiplier)

.Process(this->SpawnsCrate_Types)
.Process(this->SpawnsCrate_Weights)

Expand Down Expand Up @@ -547,6 +553,7 @@ void WarheadTypeExt::ExtData::Serialize(T& Stm)
.Process(this->PossibleCellSpreadDetonate)
.Process(this->Reflected)
.Process(this->DamageAreaTarget)
.Process(this->HitDirection)
;
}

Expand Down
8 changes: 8 additions & 0 deletions src/Ext/WarheadType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class WarheadTypeExt
NullableVector<ShieldTypeClass*> Shield_Respawn_Types;
NullableVector<ShieldTypeClass*> Shield_SelfHealing_Types;

Valueable<bool> Directional;
Valueable<double> Directional_Multiplier;

Valueable<int> NotHuman_DeathSequence;
ValueableIdxVector<SuperWeaponTypeClass> LaunchSW;
Valueable<bool> LaunchSW_RealLaunch;
Expand Down Expand Up @@ -189,6 +192,7 @@ class WarheadTypeExt
int RemainingAnimCreationInterval;
bool PossibleCellSpreadDetonate;
TechnoClass* DamageAreaTarget;
int HitDirection;

private:
Valueable<double> Shield_Respawn_Rate_InMinutes;
Expand Down Expand Up @@ -285,6 +289,9 @@ class WarheadTypeExt
, Shield_Respawn_Types {}
, Shield_SelfHealing_Types {}

, Directional { false}
, Directional_Multiplier { 1.0 }

, SpawnsCrate_Types {}
, SpawnsCrate_Weights {}

Expand Down Expand Up @@ -355,6 +362,7 @@ class WarheadTypeExt
, RemainingAnimCreationInterval { 0 }
, PossibleCellSpreadDetonate { false }
, DamageAreaTarget {}
, HitDirection { -1 }

, KillWeapon {}
, KillWeapon_OnFirer {}
Expand Down
46 changes: 46 additions & 0 deletions src/Ext/WarheadType/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,58 @@ DEFINE_HOOK(0x46920B, BulletClass_Detonate, 0x6)
auto const pOwner = pBullet->Owner;
auto const pHouse = pOwner ? pOwner->Owner : nullptr;
auto const pDecidedHouse = pHouse ? pHouse : pBulletExt->FirerHouse;

pWHExt->Detonate(pOwner, pDecidedHouse, pBulletExt, *pCoords);
pWHExt->InDamageArea = false;

return 0;
}

DEFINE_HOOK(0x469A69, BulletClass_Detonate_DamageArea, 0x6)
{
enum { SkipGameCode = 0x469A88 };

GET(BulletClass*, pBullet, ESI);
GET(TechnoClass*, pSourceTechno, EAX);
GET(int, damage, EDX);
GET_BASE(CoordStruct*, coords, 0x8);
const auto pBulletExt = BulletExt::ExtMap.Find(pBullet);
const auto pSourceHouse = pSourceTechno ? pSourceTechno->Owner : pBulletExt->FirerHouse;
const auto pWH = pBullet->WH;
const auto pWHExt = WarheadTypeExt::ExtMap.Find(pWH);

do
{
if (pWHExt->Directional)
{
if (pBullet->Type->Inviso)
{
if (pBullet->SourceCoords.X != pBullet->TargetCoords.X || pBullet->SourceCoords.Y != pBullet->TargetCoords.Y)
{
pWHExt->HitDirection = DirStruct(Math::atan2(static_cast<double>(pBullet->SourceCoords.Y - pBullet->TargetCoords.Y), static_cast<double>(pBullet->TargetCoords.X - pBullet->SourceCoords.X))).GetValue<16>();
break;
}
}
else
{
if (pBullet->Velocity.X != 0.0 || pBullet->Velocity.Y != 0.0)
{
pWHExt->HitDirection = DirStruct((-1) * Math::atan2(pBullet->Velocity.Y, pBullet->Velocity.X)).GetValue<16>();
break;
}
}
}

pWHExt->HitDirection = -1;
}
while (false);

R->EAX(MapClass::Instance.DamageArea(*coords, damage, pSourceTechno, pWH, true, pSourceHouse));
pWHExt->HitDirection = -1;

return SkipGameCode;
}

DEFINE_HOOK(0x489286, MapClass_DamageArea, 0x6)
{
GET_BASE(const WarheadTypeClass*, pWH, 0x0C);
Expand Down