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

[General Purpose] New Tracing trajectory #1481

Open
wants to merge 32 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4e68633
Core
CrimRecya Dec 26, 2024
b23c79e
Remove useless sanity check
CrimRecya Dec 27, 2024
e7c7fa1
Synchronize
CrimRecya Dec 27, 2024
cef2e4e
Synchronize
CrimRecya Dec 29, 2024
13e034d
Merge branch 'develop' into develop-trajectory-tracing
CrimRecya Dec 29, 2024
962ef23
Synchronize
CrimRecya Dec 29, 2024
662ba46
Synchronous packaging
CrimRecya Dec 30, 2024
d60279b
Synchronize
CrimRecya Dec 31, 2024
001a1cd
Merge branch 'develop' into develop-trajectory-tracing
CrimRecya Jan 15, 2025
32c90bd
")"
DeathFishAtEase Feb 2, 2025
e0c3ee9
Simplified
CrimRecya Feb 3, 2025
ed7e309
Merge branch 'develop' into develop-trajectory-tracing
CrimRecya Feb 3, 2025
48c1402
Fix merge
CrimRecya Feb 3, 2025
b54815a
Fix merge
CrimRecya Feb 3, 2025
c0a0705
New `Trajectory.Tracing.UseDisperseCoord`
CrimRecya Feb 3, 2025
47db217
Optimize
CrimRecya Feb 7, 2025
d3d6855
Merge remote-tracking branch 'upstream/develop' into develop-trajecto…
CrimRecya Feb 7, 2025
faa3ff5
Fix a typo
CrimRecya Feb 10, 2025
7f6b029
Merge branch 'develop' into develop-trajectory-tracing
CrimRecya Feb 10, 2025
0962a76
New `Trajectory.Tracing.AllowFirerTurning`
CrimRecya Feb 13, 2025
5db50ae
Merge branch 'develop' into develop-trajectory-tracing
CrimRecya Feb 13, 2025
e4605f2
Fix copy
CrimRecya Feb 13, 2025
1ae519a
Fix a typo
CrimRecya Feb 13, 2025
86eda84
Sync
CrimRecya Feb 14, 2025
af55344
Merge branch 'develop' into develop-trajectory-tracing
CrimRecya Feb 14, 2025
f2f94ca
Should not sync target at invalid position
CrimRecya Feb 18, 2025
b544b36
Merge remote-tracking branch 'upstream/develop' into develop-trajecto…
CrimRecya Feb 18, 2025
9e70579
Fix fire in transporter
CrimRecya Feb 18, 2025
5a4a38f
Fix name
CrimRecya Feb 18, 2025
d6cd394
Merge remote-tracking branch 'upstream/develop' into develop-trajecto…
CrimRecya Feb 18, 2025
ff1e20f
Fix typo
CrimRecya Feb 18, 2025
e36bb9b
Fix a typo
CrimRecya Feb 18, 2025
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 @@ -386,6 +386,7 @@ This page lists all the individual contributions to the project by their author.
- Fix for sidebar not updating queued unit numbers when on hold
- New Parabola trajectory
- Enhanced Bombard trajectory
- New Tracing trajectory
- **Ollerus**
- Build limit group enhancement
- Customizable rocker amplitude
Expand Down
2 changes: 2 additions & 0 deletions Phobos.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<ClCompile Include="src\Ext\Bullet\Trajectories\BombardTrajectory.cpp" />
<ClCompile Include="src\Ext\Bullet\Trajectories\PhobosTrajectory.cpp" />
<ClCompile Include="src\Ext\Bullet\Trajectories\StraightTrajectory.cpp" />
<ClCompile Include="src\Ext\Bullet\Trajectories\TracingTrajectory.cpp" />
<ClCompile Include="src\Ext\Bullet\Trajectories\ParabolaTrajectory.cpp" />
<ClCompile Include="src\Ext\CaptureManager\Hooks.cpp" />
<ClCompile Include="src\Ext\CaptureManager\Body.cpp" />
Expand Down Expand Up @@ -200,6 +201,7 @@
<ClInclude Include="src\Ext\Bullet\Trajectories\BombardTrajectory.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\PhobosTrajectory.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\StraightTrajectory.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\TracingTrajectory.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\ParabolaTrajectory.h" />
<ClInclude Include="src\Ext\OverlayType\Body.h" />
<ClInclude Include="src\Ext\ParticleType\Body.h" />
Expand Down
67 changes: 67 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ Currently interceptor weapons with projectiles that do not have `Inviso=true` wi
- In `Trajectory=Straight`, it refers to the whole distance speed of the projectile and it has no restrictions.
- In `Trajectory=Bombard`, it refers to the initial speed of the projectile and it has no restrictions.
- In `Trajectory=Parabola`, it refers to the horizontal velocity of the projectile and is only used for modes 0, 3, or 5 and it has no restrictions.
- In `Trajectory=Tracing`, it refers to the speed of tracing and turning around of the projectile.

In `rulesmd.ini`:
```ini
Expand Down Expand Up @@ -930,6 +931,72 @@ Trajectory.Parabola.AxisOfRotation=0,0,1 ; integer - Forward,Lateral,Heig
- Certainly, `Gravity` can also affect the trajectory.
```

#### Tracing trajectory

- A trajectory that keeps following the target and will only detonate when its survival time is exhausted.
- `Trajectory.Tracing.TraceMode` controls how should the projectile trace the target. This is used to calculate coordinate axis of `Trajectory.Tracing.OffsetCoord` located on the tracking target. The H axis is not affected by the tilt and deflection of the tracking target, and always faces directly above. This has the following 6 modes.
- Connection - Line vector. Take the horizontal component of the vector between the launch position and the target position as the F axis.
- Global - Map direction. Take the lower right side of the map as the F axis.
- Body - Follow the body. The F axis is the body orientation of the tracking target.
- Turret - Follow the turret. The F axis is the turret orientation of the tracking target.
- RotateCW - Rotate clockwise. Rotate clockwise around the H axis with the resultant offset in the FL direction as the radius.
- RotateCCW - Rotate counterclockwise. Rotate counterclockwise around the H axis with the resultant offset in the FL direction as the radius.
- `Trajectory.Tracing.TheDuration` controls the tracing duration in frames. If it is a non-positive number, the projectile will use weapon's `ROF`-10 as the duration. At least 1 frame.
- `Trajectory.Tracing.TolerantTime` controls how long the projectile will detonate after losing the target. If it is 0, it will detonate directly when switching targets.
- `Trajectory.Tracing.ROT` controls the rotational speed of the projectile. When it is negative, it will follow the direction of movement. When it is 0, it will always face the target. When it is positive, it will rotate towards the target according to this speed. If `Trajectory.Tracing.BulletSpin=true`, the direction of rotation is determined by its positive or negative sign, and the speed of rotation is determined by its value.
- `Trajectory.Tracing.BulletSpin` controls whether the projectile will continuously rotate itself like `TurretSpin`.
- `Trajectory.Tracing.PeacefullyVanish` controls whether the projectile disappears directly when it is about to detonate, without producing animation or causing damage
- `Trajectory.Tracing.TraceTheTarget` controls whether the target tracked by the projectile is the target of the projectile, and the tracing weapons will be fired by the unit towards the projectile. Otherwise, it will trace the firer, and the tracing weapons will be fired from the projectile towards the target. At the same time, the projectile will detonate if the firer dies.
- `Trajectory.Tracing.CreateAtTarget` controls whether the projectile is directly generated at the target position.
- `Trajectory.Tracing.CreateCoord` controls the generate position. Not related to `Trajectory.Tracing.TraceMode`.
- `Trajectory.Tracing.OffsetCoord` controls the tracing position on its target, use `Trajectory.Tracing.TraceMode` determines the specific location.
- `Trajectory.Tracing.WeaponCoord` controls the FLH where the projectile fires the weapon when `Trajectory.Tracing.TraceTheTarget=false`.
- `Trajectory.Tracing.UseDisperseCoord` controls whether the fire position of `Trajectory.Tracing.Weapons` need to replaced with the FLH of its superior's dispersed trajectory, which set `Trajectory.Disperse.RecordSourceCoord` to true (Only if the weapon should be fired from the unit position).
- `Trajectory.Tracing.AllowFirerTurning` controls whether the projectile allow for significant changes in the orientation of the firer, otherwise it will disappear.
- `Trajectory.Tracing.Weapons` defines the tracing weapons of the projectile.
- `Trajectory.Tracing.WeaponCount` controls how many times the projectile can fire the corresponding weapon. Set to a negative value means unlimited times. If set to zero, the cooling will be calculated directly without firing the tracing weapon. If the quantity is less than `Trajectory.Tracing.Weapons`, the last value in the list will be used.
- `Trajectory.Tracing.WeaponDelay` controls the delay after firing the corresponding weapon, at least 1 frame. If the quantity is less than `Trajectory.Tracing.Weapons`, the last value in the list will be used.
- `Trajectory.Tracing.WeaponInitialDelay` controls the initial delay for firing the tracing weapons defined by `Trajectory.Tracing.Weapons`.
- `Trajectory.Tracing.WeaponCycle` controls how many rounds of weapons the projectile can fire, zero will not fire weapons, and negative numbers are considered infinite.
- `Trajectory.Tracing.WeaponCheck` controls whether the projectile will check its orientation before firing the tracing weapons. Ignore this if `Trajectory.Tracing.Synchronize=false` or `Trajectory.Tracing.TraceTheTarget=true` or `Trajectory.Tracing.BulletSpin=true` or have negative `Trajectory.Tracing.ROT`.
- `Trajectory.Tracing.Synchronize` controls whether the target of the projectile is synchronized with the target of its firer. If not, the projectile will not update the target. When `Trajectory.Tracing.TraceTheTarget=no`, the tracing weapons will select their own targets to attack based on its range.
- `Trajectory.Tracing.SuicideAboveRange` controls whether the projectile will explode if its target exceeds the range.
- `Trajectory.Tracing.SuicideIfNoWeapon` controls whether the projectile will explode after firing the final weapon.

In `rulesmd.ini`:
```ini
[SOMEPROJECTILE] ; Projectile
Trajectory=Tracing ; Trajectory type
Trajectory.Tracing.TraceMode=Connection ; TraceMode value enumeration (Connection|Global|Body|Turret|RotateCW|RotateCCW)
Trajectory.Tracing.TheDuration=0 ; integer
Trajectory.Tracing.TolerantTime=-1 ; integer
Trajectory.Tracing.ROT=-1 ; integer
Trajectory.Tracing.BulletSpin=false ; boolean
Trajectory.Tracing.PeacefullyVanish=false ; boolean
Trajectory.Tracing.TraceTheTarget=true ; boolean
Trajectory.Tracing.CreateAtTarget=false ; boolean
Trajectory.Tracing.CreateCoord=0,0,0 ; integer - Forward,Lateral,Height
Trajectory.Tracing.OffsetCoord=0,0,0 ; integer - Forward,Lateral,Height
Trajectory.Tracing.WeaponCoord=0,0,0 ; integer - Forward,Lateral,Height
Trajectory.Tracing.UseDisperseCoord=false ; boolean
Trajectory.Tracing.AllowFirerTurning=true ; boolean
Trajectory.Tracing.Weapons= ; list of WeaponTypes
Trajectory.Tracing.WeaponCount= ; list of integers
Trajectory.Tracing.WeaponDelay= ; list of integers
Trajectory.Tracing.WeaponInitialDelay=0 ; integer
Trajectory.Tracing.WeaponCycle=-1 ; integer
Trajectory.Tracing.WeaponCheck=false ; boolean
Trajectory.Tracing.Synchronize=true ; boolean
Trajectory.Tracing.SuicideAboveRange=false ; boolean
Trajectory.Tracing.SuicideIfNoWeapon=false ; boolean
```

```{note}
- If you set `Trajectory.Tracing.TraceTheTarget=false` and `Trajectory.Tracing.Synchronize=false`, make sure you set low `Range` values for weapons in `Trajectory.Tracing.Weapons` unless necessary.
- Note that the listed Weapons in `Trajectory.Tracing.Weapons` must be listed in `[WeaponTypes]` for them to work.
- `Trajectory.Tracing.Weapons` now not support customized `Bolt.ColorN`.
```

### Shrapnel enhancements

![image](_static/images/shrapnel.gif)
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ New:
- Enhanced Bombard trajectory (by CrimRecya & Ollerus, based on knowledge of NaotoYuuki)
- Toggle waypoint for building (by TaranDahl)
- Bunkerable checks dehardcode (by TaranDahl)
- New Tracing trajectory (by CrimRecya)

Vanilla fixes:
- Aircraft will now behave as expected according to it's `MovementZone` and `SpeedType` when moving onto different surfaces. In particular, this fixes erratic behavior when vanilla aircraft is ordered to move onto water surface and instead the movement order changes to a shore nearby (by CrimRecya)
Expand Down
193 changes: 193 additions & 0 deletions src/Ext/Bullet/Body.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "Body.h"

#include <Ext/Anim/Body.h>
#include <Ext/RadSite/Body.h>
#include <Ext/WeaponType/Body.h>
#include <Ext/TechnoType/Body.h>
Expand Down Expand Up @@ -155,6 +156,198 @@ void BulletExt::ExtData::InitializeLaserTrails()
}
}

static inline int SetBuildingFireAnimZAdjust(BuildingClass* pBuilding, int animY)
{
if (pBuilding->GetOccupantCount() > 0)
return -200;

const auto renderCoords = pBuilding->GetRenderCoords();
const auto zAdj = (animY - renderCoords.Y) / -4;
return (zAdj >= 0) ? 0 : zAdj;
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
inline void BulletExt::SimulatedFiringAnim(BulletClass* pBullet, HouseClass* pHouse, ObjectClass* pAttach)
{
const auto pWeapon = pBullet->WeaponType;
const auto animCounts = pWeapon->Anim.Count;

if (animCounts <= 0)
return;

const auto pFirer = pBullet->Owner;
const auto pAnimType = pWeapon->Anim[(animCounts % 8 == 0) // Have direction
? (static_cast<int>((Math::atan2(pBullet->Velocity.Y , pBullet->Velocity.X) / Math::TwoPi + 1.5) * animCounts - (animCounts / 8) + 0.5) % animCounts) // Calculate direction
: ScenarioClass::Instance->Random.RandomRanged(0 , animCounts - 1)]; // Simple random;
/*
const auto velocityRadian = Math::atan2(pBullet->Velocity.Y , pBullet->Velocity.X);
const auto ratioOfRotateAngle = velocityRadian / Math::TwoPi;
const auto correctRatioOfRotateAngle = ratioOfRotateAngle + 1.5; // Correct the Y-axis in reverse and ensure that the ratio is a positive number
const auto animIndex = correctRatioOfRotateAngle * animCounts;
const auto correctAnimIndex = animIndex - (animCounts / 8); // A multiple of 8 greater than 8 will have an additional offset
const auto trueAnimIndex = static_cast<int>(correctAnimIndex + 0.5) % animCounts; // Round down and prevent exceeding the scope
*/

if (!pAnimType)
return;

const auto pAnim = GameCreate<AnimClass>(pAnimType, pBullet->SourceCoords);

AnimExt::SetAnimOwnerHouseKind(pAnim, pHouse, nullptr, false, true);
AnimExt::ExtMap.Find(pAnim)->SetInvoker(pFirer, pHouse);

if (pAttach)
{
if (pAttach->WhatAmI() == AbstractType::Building)
pAnim->ZAdjust = SetBuildingFireAnimZAdjust(static_cast<BuildingClass*>(pAttach), pBullet->SourceCoords.Y);
else
pAnim->SetOwnerObject(pAttach);
}
else if (const auto pBuilding = abstract_cast<BuildingClass*>(pFirer))
{
pAnim->ZAdjust = SetBuildingFireAnimZAdjust(pBuilding, pBullet->SourceCoords.Y);
}
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
inline void BulletExt::SimulatedFiringReport(BulletClass* pBullet)
{
const auto pWeapon = pBullet->WeaponType;

if (pWeapon->Report.Count <= 0)
return;

const auto pFirer = pBullet->Owner;
const auto reportIndex = pWeapon->Report[(pFirer ? pFirer->unknown_short_3C8 : ScenarioClass::Instance->Random.Random()) % pWeapon->Report.Count];

if (reportIndex != -1)
VocClass::PlayAt(reportIndex, pBullet->Location, nullptr);
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
inline void BulletExt::SimulatedFiringLaser(BulletClass* pBullet, HouseClass* pHouse)
{
const auto pWeapon = pBullet->WeaponType;

if (!pWeapon->IsLaser)
return;

const auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);

if (pWeapon->IsHouseColor || pWeaponExt->Laser_IsSingleColor)
{
const auto black = ColorStruct { 0, 0, 0 };
const auto pLaser = GameCreate<LaserDrawClass>(pBullet->SourceCoords, pBullet->TargetCoords, ((pWeapon->IsHouseColor && pHouse) ? pHouse->LaserColor : pWeapon->LaserInnerColor), black, black, pWeapon->LaserDuration);
pLaser->IsHouseColor = true;
pLaser->Thickness = pWeaponExt->LaserThickness;
pLaser->IsSupported = (pLaser->Thickness > 3);
}
else
{
const auto pLaser = GameCreate<LaserDrawClass>(pBullet->SourceCoords, pBullet->TargetCoords, pWeapon->LaserInnerColor, pWeapon->LaserOuterColor, pWeapon->LaserOuterSpread, pWeapon->LaserDuration);
pLaser->IsHouseColor = false;
pLaser->Thickness = 3;
pLaser->IsSupported = false;
}
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
inline void BulletExt::SimulatedFiringElectricBolt(BulletClass* pBullet)
{
const auto pWeapon = pBullet->WeaponType;

if (!pWeapon->IsElectricBolt)
return;

if (auto const pEBolt = GameCreate<EBolt>())
{
pEBolt->AlternateColor = pWeapon->IsAlternateColor;
//TODO Weapon's Bolt.Color1, Bolt.Color2, Bolt.Color3(Ares)
WeaponTypeExt::BoltWeaponMap[pEBolt] = WeaponTypeExt::ExtMap.Find(pWeapon);
pEBolt->Fire(pBullet->SourceCoords, pBullet->TargetCoords, 0);
}
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
inline void BulletExt::SimulatedFiringRadBeam(BulletClass* pBullet, HouseClass* pHouse)
{
const auto pWeapon = pBullet->WeaponType;

if (!pWeapon->IsRadBeam)
return;

const bool isTemporal = pWeapon->Warhead && pWeapon->Warhead->Temporal;

if (const auto pRadBeam = RadBeam::Allocate(isTemporal ? RadBeamType::Temporal : RadBeamType::RadBeam))
{
pRadBeam->SetCoordsSource(pBullet->SourceCoords);
pRadBeam->SetCoordsTarget(pBullet->TargetCoords);

const auto pWeaponExt = WeaponTypeExt::ExtMap.Find(pWeapon);

pRadBeam->Color = (pWeaponExt->Beam_IsHouseColor && pHouse) ? pHouse->LaserColor : pWeaponExt->Beam_Color.Get(isTemporal ? RulesClass::Instance->ChronoBeamColor : RulesClass::Instance->RadColor);
pRadBeam->Period = pWeaponExt->Beam_Duration;
pRadBeam->Amplitude = pWeaponExt->Beam_Amplitude;
}
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
inline void BulletExt::SimulatedFiringParticleSystem(BulletClass* pBullet, HouseClass* pHouse)
{
if (const auto pPSType = pBullet->WeaponType->AttachedParticleSystem)
GameCreate<ParticleSystemClass>(pPSType, pBullet->SourceCoords, pBullet->Target, pBullet->Owner, pBullet->TargetCoords, pHouse);
}

// Make sure pBullet is not empty before call
void BulletExt::SimulatedFiringUnlimbo(BulletClass* pBullet, HouseClass* pHouse, WeaponTypeClass* pWeapon, const CoordStruct& sourceCoords, bool randomVelocity)
{
// Weapon
pBullet->WeaponType = pWeapon;

// Range
int projectileRange = WeaponTypeExt::ExtMap.Find(pWeapon)->ProjectileRange.Get();
pBullet->Range = projectileRange;

// House
BulletExt::ExtMap.Find(pBullet)->FirerHouse = pHouse;

// Velocity
auto velocity = BulletVelocity::Empty;

if (randomVelocity)
{
DirStruct dir;
dir.SetValue<5>(ScenarioClass::Instance->Random.RandomRanged(0, 31));

const auto cos_factor = -2.44921270764e-16; // cos(1.5 * Math::Pi * 1.00001)
const auto flatSpeed = cos_factor * pBullet->Speed;

const auto radians = dir.GetRadian<32>();
velocity = BulletVelocity { Math::cos(radians) * flatSpeed, Math::sin(radians) * flatSpeed, static_cast<double>(-pBullet->Speed) };
}

// Unlimbo
pBullet->MoveTo(sourceCoords, velocity);
}

// Make sure pBullet and pBullet->WeaponType is not empty before call
void BulletExt::SimulatedFiringEffects(BulletClass* pBullet, HouseClass* pHouse, ObjectClass* pAttach, bool firingEffect, bool visualEffect)
{
if (firingEffect)
{
BulletExt::SimulatedFiringAnim(pBullet, pHouse, pAttach);
BulletExt::SimulatedFiringReport(pBullet);
}

if (visualEffect)
{
BulletExt::SimulatedFiringLaser(pBullet, pHouse);
BulletExt::SimulatedFiringElectricBolt(pBullet);
BulletExt::SimulatedFiringRadBeam(pBullet, pHouse);
BulletExt::SimulatedFiringParticleSystem(pBullet, pHouse);
}
}

// =============================
// load / save

Expand Down
9 changes: 9 additions & 0 deletions src/Ext/Bullet/Body.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,13 @@ class BulletExt
};

static ExtContainer ExtMap;

static void SimulatedFiringUnlimbo(BulletClass* pBullet, HouseClass* pHouse, WeaponTypeClass* pWeapon, const CoordStruct& sourceCoords, bool randomVelocity);
static void SimulatedFiringEffects(BulletClass* pBullet, HouseClass* pHouse, ObjectClass* pAttach, bool firingEffect, bool visualEffect);
static inline void SimulatedFiringAnim(BulletClass* pBullet, HouseClass* pHouse, ObjectClass* pAttach);
static inline void SimulatedFiringReport(BulletClass* pBullet);
static inline void SimulatedFiringLaser(BulletClass* pBullet, HouseClass* pHouse);
static inline void SimulatedFiringElectricBolt(BulletClass* pBullet);
static inline void SimulatedFiringRadBeam(BulletClass* pBullet, HouseClass* pHouse);
static inline void SimulatedFiringParticleSystem(BulletClass* pBullet, HouseClass* pHouse);
};
3 changes: 2 additions & 1 deletion src/Ext/Bullet/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,8 @@ constexpr bool CheckTrajectoryCanNotAlwaysSnap(const TrajectoryFlag flag)
return flag != TrajectoryFlag::Invalid;
/* return flag == TrajectoryFlag::Straight
|| flag == TrajectoryFlag::Bombard
|| flag == TrajectoryFlag::Parabola;*/
|| flag == TrajectoryFlag::Parabola;
|| flag == TrajectoryFlag::Tracing;*/
}

DEFINE_HOOK(0x467CCA, BulletClass_AI_TargetSnapChecks, 0x6)
Expand Down
Loading