Skip to content

EMPulseCannon.InaccurateRadius for projectiles in EMPulseCannon=yes superweapons and Ammo support #1698

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

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
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 @@ -149,6 +149,7 @@ This page lists all the individual contributions to the project by their author.
- Warhead activation target health thresholds enhancements
- Event 606: AttachEffect is attaching to a Techno
- Linked superweapons
- `EMPulseCannon.InaccurateRadius` for projectiles in `EMPulseCannon=yes` superweapons and `Ammo` support
- **Starkku**:
- Misc. minor bugfixes & improvements
- AI script actions:
Expand Down
2 changes: 1 addition & 1 deletion YRpp
Submodule YRpp updated 1 files
+3 −3 ScenarioClass.h
11 changes: 8 additions & 3 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1092,12 +1092,17 @@ TabIndex=1 ; integer
- Note that if you fire another `Type=EMPulse` superweapon with different weapon index that the same building is capable of launching before the first weapon was fired, the latter superweapon's settings will take precedence.
- Additionally, due to technical limitations the targeting constraints will always default to primary weapon's `Range/MinimumRange` unless `SW.RangeMinimum` / `SW.RangeMaximum` are explicitly set.
- Is is now also possible to have all other `Type=EMPulse` superweapons that can be fired by same buildings as current one be put on hold until first of the buildings currently set to fire goes off if the firing superweapon has `EMPulse.SuspendOthers=true`.
- Structures with `Ammo` now fire repeatedly until the weapon no longer has enough ammo.
- `EMPulseCannon.InaccurateRadius` defines an area around the target location where the projectile can land randomly.

In `rulesmd.ini`:
```ini
[SOMESW] ; SuperWeaponType
EMPulse.WeaponIndex=0 ; integer, weapon slot index
EMPulse.SuspendOthers=false ; boolean
[SOMESW] ; SuperWeaponType
EMPulse.WeaponIndex=0 ; integer, weapon slot index
EMPulse.SuspendOthers=false ; boolean

[SOMEPROJECTILE] ; Projectile
EMPulseCannon.InaccurateRadius=0 ; integer
```

```{note}
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ New:
- [Damaged aircraft image changes](New-or-Enhanced-Logics.md#damaged-aircraft-image-changes) (by Fryone)
- [Additional attached animation position customizations](Fixed-or-Improved-Logics.md#attached-animation-position-customization) (by Starkku)
- Use `SkipCrushSlowdown=true` to avoid the bug related to `Accelerates=true` and `MovementZone=CrushAll` (by TaranDahl)
- `EMPulseCannon.InaccurateRadius` for projectiles in `EMPulseCannon=yes` superweapons and `Ammo` support (by FS-21)

Vanilla fixes:
- Fixed sidebar not updating queued unit numbers when adding or removing units when the production is on hold (by CrimRecya)
Expand Down
1 change: 1 addition & 0 deletions src/Ext/Building/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ void BuildingExt::ExtData::Serialize(T& Stm)
.Process(this->CurrentLaserWeaponIndex)
.Process(this->PoweredUpToLevel)
.Process(this->EMPulseSW)
.Process(this->RandomEMPTarget);
;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Ext/Building/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class BuildingExt
std::optional<int> CurrentLaserWeaponIndex;
int PoweredUpToLevel; // Distinct from UpgradeLevel, and set to highest PowersUpToLevel out of applied upgrades regardless of how many are currently applied to this building.
SuperClass* EMPulseSW;
CellStruct RandomEMPTarget;

ExtData(BuildingClass* OwnerObject) : Extension<BuildingClass>(OwnerObject)
, TypeExtData { nullptr }
Expand All @@ -52,6 +53,7 @@ class BuildingExt
, CurrentLaserWeaponIndex {}
, PoweredUpToLevel { 0 }
, EMPulseSW {}
, RandomEMPTarget { CellStruct::Empty }
{ }

void DisplayIncomeString();
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/BulletType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ void BulletTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->Parachuted_FallRate.Read(exINI, pSection, "Parachuted.FallRate");
this->Parachuted_MaxFallRate.Read(exINI, pSection, "Parachuted.MaxFallRate");
this->BombParachute.Read(exINI, pSection, "BombParachute");
this->EMPulseCannon_InaccurateRadius.Read(exINI, pSection, "EMPulseCannon.InaccurateRadius");

// Ares 0.7
this->BallisticScatter_Min.Read(exINI, pSection, "BallisticScatter.Min");
Expand Down Expand Up @@ -168,6 +169,7 @@ void BulletTypeExt::ExtData::Serialize(T& Stm)
.Process(this->Parachuted_FallRate)
.Process(this->Parachuted_MaxFallRate)
.Process(this->BombParachute)
.Process(this->EMPulseCannon_InaccurateRadius)

.Process(this->TrajectoryType) // just keep this shit at last
;
Expand Down
3 changes: 3 additions & 0 deletions src/Ext/BulletType/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class BulletTypeExt
Nullable<int> Parachuted_MaxFallRate;
Nullable<AnimTypeClass*> BombParachute;

Valueable<int> EMPulseCannon_InaccurateRadius;

// Ares 0.7
Nullable<Leptons> BallisticScatter_Min;
Nullable<Leptons> BallisticScatter_Max;
Expand Down Expand Up @@ -120,6 +122,7 @@ class BulletTypeExt
, Parachuted_FallRate { 1 }
, Parachuted_MaxFallRate {}
, BombParachute {}
, EMPulseCannon_InaccurateRadius { 0 }
{ }

virtual ~ExtData() = default;
Expand Down
82 changes: 82 additions & 0 deletions src/Ext/Techno/Hooks.Firing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <Ext/WarheadType/Body.h>
#include <Ext/WeaponType/Body.h>
#include <Utilities/EnumFunctions.h>
#include <Ext/SWType/Body.h>
#include <Ext/House/Body.h>

#pragma region TechnoClass_SelectWeapon

Expand Down Expand Up @@ -924,3 +926,83 @@ DEFINE_HOOK(0x5223B3, InfantryClass_Approach_Target_DeployFireWeapon, 0x6)
R->EDI(deployFireWeapon == -1 ? pThis->SelectWeapon(pThis->Target) : deployFireWeapon);
return 0x5223B9;
}

DEFINE_HOOK(0x44CD18, BuildingClass_MissionMissile_EMPulseCannon_InaccurateRadius, 0x6)
{
GET(BuildingClass*, pThis, ESI);

HouseClass* pHouse = pThis->Owner;
const auto pCell = MapClass::Instance.TryGetCellAt(pHouse->EMPTarget);

if (!pThis->Type->EMPulseCannon || !pCell)
return 0;

// Obtain the weapon used by the EMP weapon
int weaponIndex = 0;
const auto pExt = BuildingExt::ExtMap.Find(pThis);

if (pExt->EMPulseSW)
{
const auto pSWExt = SWTypeExt::ExtMap.Find(pExt->EMPulseSW->Type);

if (pSWExt->EMPulse_WeaponIndex >= 0)
{
weaponIndex = pSWExt->EMPulse_WeaponIndex;
}
else
{
AbstractClass* pTarget = pCell;

if (const auto pObject = pCell->GetContent())
pTarget = pObject;

weaponIndex = pThis->SelectWeapon(pTarget);
}
}

const auto pWeapon = pThis->GetWeapon(weaponIndex)->WeaponType;

// Innacurate random strike Area calculation
int radius = BulletTypeExt::ExtMap.Find(pWeapon->Projectile)->EMPulseCannon_InaccurateRadius;
radius = radius < 0 ? 0 : radius;

if (radius > 0)
{
if (pExt->RandomEMPTarget == CellStruct::Empty)
{
// Calculate a new valid random target coordinate
do
{
pExt->RandomEMPTarget.X = (short)ScenarioClass::Instance->Random.RandomRanged(pHouse->EMPTarget.X - radius, pHouse->EMPTarget.X + radius);
pExt->RandomEMPTarget.Y = (short)ScenarioClass::Instance->Random.RandomRanged(pHouse->EMPTarget.Y - radius, pHouse->EMPTarget.Y + radius);
}
while (!MapClass::Instance.IsWithinUsableArea(pExt->RandomEMPTarget, false));
}

pHouse->EMPTarget = pExt->RandomEMPTarget; // Value overwrited every frame
}

if (pThis->MissionStatus != 3)
return 0;

pExt->RandomEMPTarget = CellStruct::Empty;

// Restart the super weapon firing process if there is enough ammo set for the current weapon
if (pThis->Type->Ammo > 0 && pThis->Ammo > 0)
{
int ammo = WeaponTypeExt::ExtMap.Find(pWeapon)->Ammo.Get(1);
pThis->Ammo -= ammo;
pThis->Ammo = pThis->Ammo < 0 ? 0 : pThis->Ammo;

if (pThis->Ammo >= ammo)
pThis->MissionStatus = 0;

if (!pThis->ReloadTimer.InProgress())
pThis->ReloadTimer.Start(pThis->Type->Reload);

if (pThis->Ammo == 0 && pThis->Type->EmptyReload >= 0 && pThis->ReloadTimer.GetTimeLeft() > pThis->Type->EmptyReload)
pThis->ReloadTimer.Start(pThis->Type->EmptyReload);
}

return 0;
}
3 changes: 3 additions & 0 deletions src/Ext/WeaponType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
{
this->SkipWeaponPicking = false;
}

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

template <typename T>
Expand Down Expand Up @@ -233,6 +235,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm)
.Process(this->DelayedFire_OnlyOnInitialBurst)
.Process(this->DelayedFire_AnimOffset)
.Process(this->DelayedFire_AnimOnTurret)
.Process(this->Ammo)
;
};

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

bool SkipWeaponPicking;

Expand Down Expand Up @@ -160,6 +161,7 @@ class WeaponTypeExt
, DelayedFire_OnlyOnInitialBurst { false }
, DelayedFire_AnimOffset {}
, DelayedFire_AnimOnTurret { true }
, Ammo { }
{ }

int GetBurstDelay(int burstIndex) const;
Expand Down
Loading