From a11414adc79ea6eec465573ca80082488a1cec03 Mon Sep 17 00:00:00 2001 From: CrimRecya <335958461@qq.com> Date: Fri, 28 Feb 2025 18:15:42 +0800 Subject: [PATCH] New `Trajectory.Engrave.ProximityFlight` and `Trajectory.Engrave.ConfineOnGround` --- docs/New-or-Enhanced-Logics.md | 12 +++- .../Bullet/Trajectories/EngraveTrajectory.cpp | 67 +++++++++++++++++-- .../Bullet/Trajectories/EngraveTrajectory.h | 4 ++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index ae854dfade..1cc62431dc 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -727,7 +727,7 @@ Currently interceptor weapons with projectiles that do not have `Inviso=true` wi - The speed of the projectile is defined by `Trajectory.Speed`, which unlike `Speed` used by `ROT` > 0 projectiles is defined on projectile not weapon. - 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=Engrave`, it refers to the engrave speed of the projectile and it cannot exceed 128. Recommend set as about 40. + - In `Trajectory=Engrave`, it refers to the horizontal engrave speed of the projectile and it cannot exceed 128. Recommend set as about 40. - 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 `rulesmd.ini`: @@ -921,8 +921,8 @@ Trajectory.Parabola.AxisOfRotation=0,0,1 ; integer - Forward,Lateral,Heig #### Engrave trajectory - Visually, like the thermal lance. Calling it 'trajectory' may not be appropriate. It does not read the settings on the weapon. - - `Trajectory.Engrave.SourceCoord` controls the starting point of engraving line segment. Taking the target as the coordinate center. Specifically, it will start from the firing position when set to 0,0 . The height of the point will always at ground level. - - `Trajectory.Engrave.TargetCoord` controls the end point of engraving line segment. Taking the target as the coordinate center. The height of the point will always at ground level. + - `Trajectory.Engrave.SourceCoord` controls the starting point of engraving line segment. Taking the target as the coordinate center. Specifically, it will start from the firing position when set to 0,0 . The height of the point will always at ground level, unless `Trajectory.Engrave.ConfineOnGround` is set to false. + - `Trajectory.Engrave.TargetCoord` controls the end point of engraving line segment. Taking the target as the coordinate center. The height of the point will always at ground level, unless `Trajectory.Engrave.ConfineOnGround` is set to false. - `Trajectory.Engrave.MirrorCoord` controls whether `Trajectory.Engrave.SourceCoord` and `Trajectory.Engrave.TargetCoord` need to mirror the lateral value to adapt to the current FLH. - `Trajectory.Engrave.UseDisperseCoord` controls whether the emission position of the engrave laser need to replaced with the FLH of its superior's dispersed trajectory, which set `Trajectory.Disperse.RecordSourceCoord` to true. - `Trajectory.Engrave.ApplyRangeModifiers` controls whether any applicable weapon range modifiers from the firer are applied to the engrave process. @@ -945,7 +945,10 @@ Trajectory.Parabola.AxisOfRotation=0,0,1 ; integer - Forward,Lateral,Heig - `Trajectory.Engrave.ProximityDirect` controls whether let the target receive damage instead of detonating the warhead. - `Trajectory.Engrave.ProximityMedial` controls whether to detonate `Trajectory.Engrave.ProximityWarhead` at the bullet's location rather than the proximity target's location. - `Trajectory.Engrave.ProximityAllies` controls whether allies will also trigger the proximity fuse. + - `Trajectory.Engrave.ProximityFlight` controls whether to count units in the air. - `Trajectory.Engrave.ProximitySuicide` controls whether the projectile will self destruct after the number of proximity fuse times has been exhausted. If `Trajectory.Engrave.ProximityImpact` set to 0, this will not be enabled. + - `Trajectory.Engrave.ConfineOnGround` controls whether the height of the projectile will always at ground level. + In `rulesmd.ini`: ```ini @@ -976,11 +979,14 @@ Trajectory.Engrave.ProximityRadius=0.7 ; floating point value Trajectory.Engrave.ProximityDirect=false ; boolean Trajectory.Engrave.ProximityMedial=false ; boolean Trajectory.Engrave.ProximityAllies=false ; boolean +Trajectory.Engrave.ProximityFlight=false ; boolean Trajectory.Engrave.ProximitySuicide=false ; boolean +Trajectory.Engrave.ConfineOnGround=true ; boolean ``` ```{note} - It's best not to let it be intercepted. +- Make sure you set a low `Trajectory.Engrave.ProximityRadius` value unless necessary. ``` ### Shrapnel enhancements diff --git a/src/Ext/Bullet/Trajectories/EngraveTrajectory.cpp b/src/Ext/Bullet/Trajectories/EngraveTrajectory.cpp index b532d398d3..28c366e06d 100644 --- a/src/Ext/Bullet/Trajectories/EngraveTrajectory.cpp +++ b/src/Ext/Bullet/Trajectories/EngraveTrajectory.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -42,7 +43,9 @@ void EngraveTrajectoryType::Serialize(T& Stm) .Process(this->ProximityDirect) .Process(this->ProximityMedial) .Process(this->ProximityAllies) + .Process(this->ProximityFlight) .Process(this->ProximitySuicide) + .Process(this->ConfineOnGround) ; } @@ -94,7 +97,9 @@ void EngraveTrajectoryType::Read(CCINIClass* const pINI, const char* pSection) this->ProximityDirect.Read(exINI, pSection, "Trajectory.Engrave.ProximityDirect"); this->ProximityMedial.Read(exINI, pSection, "Trajectory.Engrave.ProximityMedial"); this->ProximityAllies.Read(exINI, pSection, "Trajectory.Engrave.ProximityAllies"); + this->ProximityFlight.Read(exINI, pSection, "Trajectory.Engrave.ProximityFlight"); this->ProximitySuicide.Read(exINI, pSection, "Trajectory.Engrave.ProximitySuicide"); + this->ConfineOnGround.Read(exINI, pSection, "Trajectory.Engrave.ConfineOnGround"); } template @@ -276,7 +281,9 @@ void EngraveTrajectory::SetEngraveDirection(BulletClass* pBullet, double rotateA theSource.Y += static_cast(this->SourceCoord.X * Math::sin(rotateAngle) - this->SourceCoord.Y * Math::cos(rotateAngle)); } - theSource.Z = this->GetFloorCoordHeight(pBullet, theSource); + if (this->Type->ConfineOnGround) + theSource.Z = this->GetFloorCoordHeight(pBullet, theSource); + this->StartCoord = theSource; pBullet->SetLocation(theSource); @@ -318,13 +325,16 @@ int EngraveTrajectory::GetFloorCoordHeight(BulletClass* pBullet, const CoordStru { const auto pCell = MapClass::Instance->GetCellAt(coord); const auto onFloor = MapClass::Instance->GetCellFloorHeight(coord); - const auto onBridge = pCell->GetCoordsWithBridge().Z; + const auto onBridge = pCell->ContainsBridge() ? onFloor + CellClass::BridgeHeight : onFloor; return (pBullet->SourceCoords.Z >= onBridge || pBullet->TargetCoords.Z >= onBridge) ? onBridge : onFloor; } bool EngraveTrajectory::PlaceOnCorrectHeight(BulletClass* pBullet) { + if (!this->Type->ConfineOnGround) + return false; + auto bulletCoords = pBullet->Location; CoordStruct futureCoords { @@ -446,6 +456,7 @@ void EngraveTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass* p static_cast(pBullet->Velocity.Z) }; const auto velocitySq = velocityCrd.MagnitudeSquared(); + const auto pTarget = pBullet->Target; std::vector validTechnos; validTechnos.reserve(vectSize); @@ -468,7 +479,7 @@ void EngraveTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass* p continue; // Not directly harming friendly forces - if (!pType->ProximityAllies && pOwner && pOwner->IsAlliedWith(pTechno->Owner) && pTechno != pBullet->Target) + if (!pType->ProximityAllies && pOwner && pOwner->IsAlliedWith(pTechno->Owner) && pTechno != pTarget) continue; // Check distance @@ -501,7 +512,53 @@ void EngraveTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass* p } } - // Step 2: Record each target without repetition. + // Step 2: Find valid targets in the air within range if necessary. + if (pType->ProximityFlight) + { + const auto airTracker = &AircraftTrackerClass::Instance; + 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; + + // Check distance + const auto targetCrd = pTechno->GetCoords(); + const auto pathCrd = targetCrd - this->StartCoord; + + if (pathCrd * velocityCrd < 0) // In front of the techno + continue; + + const auto distanceCrd = targetCrd - pBullet->Location; + const auto nextDistanceCrd = distanceCrd - velocityCrd; + + if (nextDistanceCrd * velocityCrd > 0) // Behind the bullet + continue; + + const auto cross = distanceCrd.CrossProduct(nextDistanceCrd).MagnitudeSquared(); + const auto distance = (velocitySq > 1e-10) ? sqrt(cross / velocitySq) : distanceCrd.Magnitude(); + + if (distance > radius) // In the cylinder + continue; + + if (thisSize >= vectSize) + { + vectSize += cellSize; + validTechnos.reserve(vectSize); + } + + validTechnos.push_back(pTechno); + thisSize += 1; + } + } + + // Step 3: Record each target without repetition. std::vector casualtyChecked; casualtyChecked.reserve(std::max(validTechnos.size(), this->TheCasualty.size())); @@ -531,7 +588,7 @@ void EngraveTrajectory::PrepareForDetonateAt(BulletClass* pBullet, HouseClass* p this->TheCasualty[pTechno->UniqueID] = 20; } - // Step 3: Detonate warheads in sequence based on distance. + // Step 4: Detonate warheads in sequence based on distance. const auto targetsSize = validTargets.size(); if (this->ProximityImpact > 0 && static_cast(targetsSize) > this->ProximityImpact) diff --git a/src/Ext/Bullet/Trajectories/EngraveTrajectory.h b/src/Ext/Bullet/Trajectories/EngraveTrajectory.h index 395f2b5a8f..c4fe89d1ce 100644 --- a/src/Ext/Bullet/Trajectories/EngraveTrajectory.h +++ b/src/Ext/Bullet/Trajectories/EngraveTrajectory.h @@ -31,7 +31,9 @@ class EngraveTrajectoryType final : public PhobosTrajectoryType , ProximityDirect { false } , ProximityMedial { false } , ProximityAllies { false } + , ProximityFlight { false } , ProximitySuicide { false } + , ConfineOnGround { true } { } virtual bool Load(PhobosStreamReader& Stm, bool RegisterForChange) override; @@ -65,7 +67,9 @@ class EngraveTrajectoryType final : public PhobosTrajectoryType Valueable ProximityDirect; Valueable ProximityMedial; Valueable ProximityAllies; + Valueable ProximityFlight; Valueable ProximitySuicide; + Valueable ConfineOnGround; private: template