Skip to content
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

[Customized] Avoid weapon fire overflow in the same frame #1472

Closed
Closed
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 @@ -372,6 +372,7 @@ This page lists all the individual contributions to the project by their author.
- Allow to change the speed of gas particles
- **CrimRecya**
- Fix `LimboKill` not working reliably
- Avoid weapon fire overflow in the same frame
- **Ollerus**
- Build limit group enhancement
- Customizable rocker amplitude
Expand Down
10 changes: 10 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1748,3 +1748,13 @@ In `rulesmd.ini`:
CanTarget=all ; list of Affected Target Enumeration (none|land|water|empty|infantry|units|buildings|all)
CanTargetHouses=all ; list of Affected House Enumeration (none|owner/self|allies/ally|team|enemies/enemy|all)
```

### Avoid weapon fire overflow in the same frame

- Now you can make the weapon declare that the target has been locked at the moment of firing, and all weapons with positive `NoRepeatFire` value will not attack the declared target again during this period of time. Made for seckill and control weapons.
Copy link
Contributor

Choose a reason for hiding this comment

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

Rename the tag to something like PreventTargetDuration for better clarification

  • what it can stop is the targeting process, but not the real damage
  • it's supposed to be an integer tag for frame amount, instead of a boolean one


In `rulesmd.ini`:
```ini
[SOMEWEAPON] ; WeaponType
NoRepeatFire=0 ; integer, game frames
```
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ New:
- Allow infantry to use land sequences in water (by Starkku)
- `<Player @ X>` can now be used as owner for pre-placed objects on skirmish and multiplayer maps (by Starkku)
- Allow customizing charge turret delays per burst on a weapon (by Starkku)
- Avoid weapon fire overflow in the same frame (by CrimRecya)
- Unit `Speed` setting now accepts floating point values (by Starkku)

Vanilla fixes:
Expand Down
1 change: 1 addition & 0 deletions src/Ext/Techno/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ void TechnoExt::ExtData::Serialize(T& Stm)
.Process(this->WHAnimRemainingCreationInterval)
.Process(this->FiringObstacleCell)
.Process(this->IsDetachingForCloak)
.Process(this->LastBeLockedFrame)
.Process(this->OriginalPassengerOwner)
.Process(this->HasRemainingWarpInDelay)
.Process(this->LastWarpInDelay)
Expand Down
2 changes: 2 additions & 0 deletions src/Ext/Techno/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class TechnoExt
bool CanCurrentlyDeployIntoBuilding; // Only set on UnitClass technos with DeploysInto set in multiplayer games, recalculated once per frame so no need to serialize.
CellClass* FiringObstacleCell; // Set on firing if there is an obstacle cell between target and techno, used for updating WaveClass target etc.
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.
int LastBeLockedFrame;

// Used for Passengers.SyncOwner.RevertOnExit instead of TechnoClass::InitialOwner / OriginallyOwnedByHouse,
// as neither is guaranteed to point to the house the TechnoClass had prior to entering transport and cannot be safely overridden.
Expand Down Expand Up @@ -88,6 +89,7 @@ class TechnoExt
, CanCurrentlyDeployIntoBuilding { false }
, FiringObstacleCell {}
, IsDetachingForCloak { false }
, LastBeLockedFrame { 0 }
, OriginalPassengerOwner {}
, HasRemainingWarpInDelay { false }
, LastWarpInDelay { 0 }
Expand Down
22 changes: 21 additions & 1 deletion src/Ext/Techno/Hooks.Firing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,15 @@ DEFINE_HOOK(0x6FC339, TechnoClass_CanFire, 0x6)
const auto pTechno = abstract_cast<TechnoClass*>(pTarget);
CellClass* pTargetCell = nullptr;

if (pWeaponExt->NoRepeatFire > 0)
{
if (const auto pTargetTechnoExt = TechnoExt::ExtMap.Find(pTechno))
{
if ((Unsorted::CurrentFrame - pTargetTechnoExt->LastBeLockedFrame) < pWeaponExt->NoRepeatFire)
return CannotFire;
}
}

// AAOnly doesn't need to be checked if LandTargeting=1.
if (pThis->GetTechnoType()->LandTargeting != LandTargetingType::Land_Not_OK && pWeapon->Projectile->AA && pTarget && !pTarget->IsInAir())
{
Expand Down Expand Up @@ -414,8 +423,10 @@ DEFINE_HOOK(0x6FCBE6, TechnoClass_CanFire_BridgeAAFix, 0x6)
DEFINE_HOOK(0x6FDDC0, TechnoClass_FireAt_DiscardAEOnFire, 0x6)
{
GET(TechnoClass* const, pThis, ESI);
GET(AbstractClass* const, pTarget, EDI);
GET(WeaponTypeClass* const, pWeapon, EBX);

auto const pExt = TechnoExt::ExtMap.Find(pThis);
const auto pExt = TechnoExt::ExtMap.Find(pThis);

if (pExt->AE.HasOnFireDiscardables)
{
Expand All @@ -426,6 +437,15 @@ DEFINE_HOOK(0x6FDDC0, TechnoClass_FireAt_DiscardAEOnFire, 0x6)
}
}

if (const auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon))
{
if (pWeaponExt->NoRepeatFire > 0)
{
if (const auto pTargetTechnoExt = TechnoExt::ExtMap.Find(abstract_cast<TechnoClass*>(pTarget)))
pTargetTechnoExt->LastBeLockedFrame = Unsorted::CurrentFrame;
}
}

return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Ext/WeaponType/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ void WeaponTypeExt::ExtData::LoadFromINIFile(CCINIClass* const pINI)
this->AttachEffect_CheckOnFirer.Read(exINI, pSection, "AttachEffect.CheckOnFirer");
this->AttachEffect_IgnoreFromSameSource.Read(exINI, pSection, "AttachEffect.IgnoreFromSameSource");
this->KickOutPassengers.Read(exINI, pSection, "KickOutPassengers");
this->NoRepeatFire.Read(exINI, pSection, "NoRepeatFire");
}

template <typename T>
Expand Down Expand Up @@ -160,6 +161,7 @@ void WeaponTypeExt::ExtData::Serialize(T& Stm)
.Process(this->AttachEffect_CheckOnFirer)
.Process(this->AttachEffect_IgnoreFromSameSource)
.Process(this->KickOutPassengers)
.Process(this->NoRepeatFire)
;
};

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 @@ -60,6 +60,7 @@ class WeaponTypeExt
Valueable<bool> AttachEffect_CheckOnFirer;
Valueable<bool> AttachEffect_IgnoreFromSameSource;
Valueable<bool> KickOutPassengers;
Valueable<int> NoRepeatFire;

ExtData(WeaponTypeClass* OwnerObject) : Extension<WeaponTypeClass>(OwnerObject)
, DiskLaser_Radius { DiskLaserClass::Radius }
Expand Down Expand Up @@ -101,6 +102,7 @@ class WeaponTypeExt
, AttachEffect_CheckOnFirer { false }
, AttachEffect_IgnoreFromSameSource { false }
, KickOutPassengers { true }
, NoRepeatFire { 0 }
{ }

int GetBurstDelay(int burstIndex) const;
Expand Down
Loading