Skip to content

Commit

Permalink
Simplify vector calculation for Straight
Browse files Browse the repository at this point in the history
- Simplify vector calculation
- Place commonly used values outside the loop for calculation
- Fix doc typo
  • Loading branch information
CrimRecya committed Feb 8, 2025
1 parent a7ca25f commit 54a4b35
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 20 deletions.
4 changes: 2 additions & 2 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -757,15 +757,15 @@ Trajectory.Speed=100.0 ; floating point value
- `Trajectory.Straight.PassDetonate` enables extra detonations when the projectile is traveling. (You can use this when you want the projectile to detonate warheads every other distance/time during the flight.)
- `Trajectory.Straight.PassDetonateWarhead` defines the warhead detonated by `Trajectory.Straight.PassDetonate`, and `Trajectory.Straight.PassDetonateDamage` defines the damage caused by `Trajectory.Straight.PassDetonateWarhead`.
- `Trajectory.Straight.PassDetonateDelay` controls the delay for detonating the warhead defined by `Trajectory.Straight.Warhead`.
- `Trajectory.Straight.PassDetonateInitialDelay` controls the initial delay for detonating the warhead defined by `Trajectory.Straight.Warhead`.
- `Trajectory.Straight.PassDetonateInitialDelay` controls the initial delay for detonating the warhead defined by `Trajectory.Straight.PassDetonateWarhead`.
- `Trajectory.Straight.PassDetonateLocal` controls whether `Trajectory.Straight.PassDetonateWarhead` and weapon's `Warhead` are always detonate at ground level. It will also no longer restrict vertical velocity of the projectile when using `Trajectory.Straight.ConfineAtHeight`.
- `Trajectory.Straight.LeadTimeCalculate` controls whether the projectile need to calculate the lead time of the target when firing. Note that this will not affect the facing of the turret.
- `Trajectory.Straight.OffsetCoord` controls the offsets of the target. Projectile will aim at this position to attack. It also supports `Inaccurate=yes` and `Trajectory.Straight.LeadTimeCalculate=true` on this basis.
- `Trajectory.Straight.RotateCoord` controls whether to rotate the projectile's firing direction within the angle bisector of `Trajectory.Straight.OffsetCoord` according to the weapon's `Burst`. Set to 0 to disable this function.
- `Trajectory.Straight.MirrorCoord` controls whether `Trajectory.Straight.OffsetCoord` need to mirror the lateral value to adapt to the current burst index. At the same time, the rotation direction calculated by `Trajectory.Straight.RotateCoord` will also be reversed, and the rotation angle between each adjacent projectile on each side will not change as a result.
- `Trajectory.Straight.UseDisperseBurst` controls whether the calculation of `Trajectory.Straight.RotateCoord` is based on its superior's `Trajectory.Disperse.WeaponBurst` of the dispersed trajectory, rather than `Burst` of the weapon. If this value is not appropriate, it will result in unsatisfactory visual displays.
- `Trajectory.Straight.AxisOfRotation` controls the rotation axis when calculating `Trajectory.Straight.RotateCoord`. The axis will rotates with the unit orientation or the vector that from target position to the source position.
- `Trajectory.Straight.ProximityImpact` controls the initial proximity fuse times. When there are enough remaining times and the projectile approaches another valid target, it will detonate a warhead defined by `Trajectory.Straight.Warhead` on it. If the times is about to run out, it will also detonate itself at its location. This function can be cancelled by setting to 0. A negative integer means unlimited times. By the way, you can use the weapon's `Warhead` with low versus only to aim at the target, and use the `Trajectory.Straight.ProximityWarhead` to causing actual harm. (You can use this to cause non repeated damage to all units encountered during the flight of the projectile.)
- `Trajectory.Straight.ProximityImpact` controls the initial proximity fuse times. When there are enough remaining times and the projectile approaches another valid target, it will detonate a warhead defined by `Trajectory.Straight.ProximityWarhead` on it. If the times is about to run out, it will also detonate itself at its location. This function can be cancelled by setting to 0. A negative integer means unlimited times. By the way, you can use the weapon's `Warhead` with low versus only to aim at the target, and use the `Trajectory.Straight.ProximityWarhead` to causing actual harm. (You can use this to cause non repeated damage to all units encountered during the flight of the projectile.)
- `Trajectory.Straight.ProximityWarhead` defines the warhead detonated by `Trajectory.Straight.ProximityImpact`, and `Trajectory.Straight.ProximityDamage` defines the damage caused by `Trajectory.Straight.ProximityWarhead`.
- `Trajectory.Straight.ProximityRadius` controls the range of proximity fuse. It can NOT be set as a negative integer.
- `Trajectory.Straight.ProximityDirect` controls whether let the target receive damage instead of detonating the warhead.
Expand Down
51 changes: 33 additions & 18 deletions src/Ext/Bullet/Trajectories/StraightTrajectory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,7 +787,8 @@ void StraightTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass*
return;

// Step 1: Find valid targets on the ground within range.
std::vector<CellClass*> recCellClass = PhobosTrajectoryType::GetCellsInProximityRadius(pBullet, pType->ProximityRadius.Get());
const auto radius = pType->ProximityRadius.Get();
std::vector<CellClass*> recCellClass = PhobosTrajectoryType::GetCellsInProximityRadius(pBullet, radius);
const size_t cellSize = recCellClass.size() * 2;
size_t vectSize = cellSize;
size_t thisSize = 0;
Expand All @@ -798,10 +799,11 @@ void StraightTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass*
static_cast<int>(pBullet->Velocity.Y),
static_cast<int>(pBullet->Velocity.Z)
};
const auto velocitySq = velocityCrd.MagnitudeSquared();
const auto pTarget = pBullet->Target;

std::vector<TechnoClass*> validTechnos;
validTechnos.reserve(vectSize);
const auto pTarget = pBullet->Target;

for (const auto& pRecCell : recCellClass)
{
Expand All @@ -824,19 +826,23 @@ void StraightTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass*
if (!pType->ProximityAllies && pOwner && pOwner->IsAlliedWith(pTechno->Owner) && pTechno != pTarget)
continue;

const auto distanceCrd = pTechno->GetCoords() - pBullet->SourceCoords;
const auto locationCrd = (velocityCrd + (pBullet->Location - pBullet->SourceCoords));
const auto terminalCrd = distanceCrd - locationCrd;
auto distance = locationCrd.MagnitudeSquared(); // Not true distance yet.
// Check distance
const auto targetCrd = pTechno->GetCoords();
const auto pathCrd = targetCrd - pBullet->SourceCoords;

if (pathCrd * velocityCrd < 0) // In front of the techno
continue;

const auto distanceCrd = targetCrd - pBullet->Location;
const auto nextDistanceCrd = distanceCrd - velocityCrd;

// Between front and back
if (distanceCrd * velocityCrd < 0 || terminalCrd * velocityCrd > 0)
if (nextDistanceCrd * velocityCrd > 0) // Behind the bullet
continue;

distance = (distance > 1e-10) ? sqrt(distanceCrd.CrossProduct(terminalCrd).MagnitudeSquared() / distance) : distanceCrd.Magnitude();
const auto cross = distanceCrd.CrossProduct(nextDistanceCrd).MagnitudeSquared();
const auto distance = (velocitySq > 1e-10) ? sqrt(cross / velocitySq) : distanceCrd.Magnitude();

// Between left and right (cylindrical)
if (technoType != AbstractType::Building && distance > pType->ProximityRadius.Get())
if (technoType != AbstractType::Building && distance > radius) // In the cylinder
continue;

if (thisSize >= vectSize)
Expand All @@ -854,26 +860,35 @@ void StraightTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass*
if (pType->ProximityFlight)
{
const auto airTracker = &AircraftTrackerClass::Instance;
airTracker->FillCurrentVector(MapClass::Instance->GetCellAt(pBullet->Location + velocityCrd * 0.5), static_cast<int>((pType->ProximityRadius.Get() + pType->Trajectory_Speed / 2) / Unsorted::LeptonsPerCell));
airTracker->FillCurrentVector(MapClass::Instance->GetCellAt(pBullet->Location + velocityCrd * 0.5),
Game::F2I(sqrt(radius * radius + (velocitySq / 4)) / Unsorted::LeptonsPerCell));

for (auto pTechno = airTracker->Get(); pTechno; pTechno = airTracker->Get())
{
if (!pTechno->IsAlive || !pTechno->IsOnMap || pTechno->Health <= 0 || pTechno->InLimbo || pTechno->IsSinking)
continue;

// Not directly harming friendly forces
if (!pType->ProximityAllies && pOwner && pOwner->IsAlliedWith(pTechno->Owner) && pTechno != pTarget)
continue;

const auto distanceCrd = pTechno->GetCoords() - pBullet->Location;
const auto terminalCrd = distanceCrd - velocityCrd;
auto distance = velocityCrd.MagnitudeSquared(); // Not true distance yet.
// Check distance
const auto targetCrd = pTechno->GetCoords();
const auto pathCrd = targetCrd - pBullet->SourceCoords;

if (pathCrd * velocityCrd < 0) // In front of the techno
continue;

const auto distanceCrd = targetCrd - pBullet->Location;
const auto nextDistanceCrd = distanceCrd - velocityCrd;

if (distanceCrd * velocityCrd < 0 || terminalCrd * velocityCrd > 0)
if (nextDistanceCrd * velocityCrd > 0) // Behind the bullet
continue;

distance = (distance > 1e-10) ? sqrt(distanceCrd.CrossProduct(terminalCrd).MagnitudeSquared() / distance) : distanceCrd.Magnitude();
const auto cross = distanceCrd.CrossProduct(nextDistanceCrd).MagnitudeSquared();
const auto distance = (velocitySq > 1e-10) ? sqrt(cross / velocitySq) : distanceCrd.Magnitude();

if (distance > pType->ProximityRadius.Get())
if (distance > radius) // In the cylinder
continue;

if (thisSize >= vectSize)
Expand Down

0 comments on commit 54a4b35

Please sign in to comment.