Skip to content

bugfix: Diving missiles no longer miss moving targets - #3192

Open
Stubbjax wants to merge 1 commit into
TheSuperHackers:mainfrom
Stubbjax:fix-diving-missile-targeting
Open

bugfix: Diving missiles no longer miss moving targets#3192
Stubbjax wants to merge 1 commit into
TheSuperHackers:mainfrom
Stubbjax:fix-diving-missile-targeting

Conversation

@Stubbjax

Copy link
Copy Markdown

This change fixes an issue where diving missiles (such as Tomahawk missiles) would miss moving targets. This was because the distance calculation did not account for a target object, and instead calculated the distance to the target position (which is only set once). This matches the logic in the above m_lockDistance calculation.

Before

BEFORE.mp4

After

AFTER.mp4

@Stubbjax Stubbjax self-assigned this Aug 23, 2026
@Stubbjax Stubbjax added Bug Something is not working right, typically is user facing Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour NoRetail This fix or change is not applicable with Retail game compatibility labels Aug 23, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix diving missile dive-distance check for moving targets

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Compute dive trigger distance using live target object position when tracking.
• Fall back to static goal position when no target object is available.
• Preserve retail CRC behavior behind RETAIL_COMPATIBLE_CRC guard.
Diagram

graph TD
  A["MissileAIUpdate::doAttackState"] --> B{"Tracking target
& goal object exists?"}
  B -->|"Yes"| C["PartitionManager.getDistanceSquared(obj, goalObject)"] --> D["Compare vs diveDistanceSquared"]
  B -->|"No"| E["PartitionManager.getDistanceSquared(obj, goalPosition)"] --> D
  A --> F["RETAIL_COMPATIBLE_CRC guard"] --> E
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Extract a shared helper for distance-to-target selection
  • ➕ Removes duplicated logic between Generals and GeneralsMD variants
  • ➕ Reduces risk of future divergence for similar targeting fixes
  • ➖ Slightly larger refactor surface area for a bugfix PR
  • ➖ May be constrained by legacy build/CRC compatibility concerns
2. Always prefer goalObject when present (ignore m_isTrackingTarget)
  • ➕ Simpler branching; fewer conditions to maintain
  • ➕ May fix additional edge cases where tracking flag is stale
  • ➖ Behavior change risk: could affect missiles that intentionally use a fixed point
  • ➖ Harder to validate across all weapon/AI behaviors without broader testing

Recommendation: Keep the PR’s minimal, guarded approach: it aligns the dive-distance check with tracking intent and preserves retail-compatible behavior. If more targeting fixes are expected, follow up by extracting a small helper to avoid duplicating the same conditional in both codebases.

Files changed (2) +28 / -2

Bug fix (2) +28 / -2
MissileAIUpdate.cppUse goal object distance for dive logic when tracking moving targets +14/-1

Use goal object distance for dive logic when tracking moving targets

• Updates the preferred-height bypass check to compute distance against the tracked target object (when available) rather than only the initial goal position. Keeps the legacy goal-position calculation under RETAIL_COMPATIBLE_CRC for compatibility.

Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp

MissileAIUpdate.cppMirror dive-distance fix for moving targets in GeneralsMD variant +14/-1

Mirror dive-distance fix for moving targets in GeneralsMD variant

• Applies the same distance calculation change as the Generals variant: prefer goalObject distance when tracking, otherwise fall back to goalPosition. Maintains retail-compatible behavior behind RETAIL_COMPATIBLE_CRC.

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Fix compiled out 🐞 Bug ≡ Correctness
Description
The new diving-missile distance calculation is placed in the #else of #if RETAIL_COMPATIBLE_CRC,
but RETAIL_COMPATIBLE_CRC defaults to 1, so the bugfix code is not compiled in typical builds.
This means diving missiles will still use getGoalPosition() (static snapshot) and can continue
missing moving targets despite the PR.
Code

Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp[R524-531]

+#if RETAIL_COMPATIBLE_CRC
+		Real distanceToTargetSquared = ThePartitionManager->getDistanceSquared(getObject(), getGoalPosition(), FROM_CENTER_2D);
+#else
+		// TheSuperHackers @bugfix Stubbjax 23/08/2026 Diving missiles now use their target's position to determine distance
+		// when applicable rather than the goal position. This allows them to properly determine when to dive on moving targets.
+		Real distanceToTargetSquared;
+		if (m_isTrackingTarget && (getGoalObject() != nullptr)) {
+			distanceToTargetSquared = ThePartitionManager->getDistanceSquared(getObject(), getGoalObject(), FROM_CENTER_2D);
Evidence
The PR adds the intended bugfix logic only in the #else branch, while the `#if
RETAIL_COMPATIBLE_CRC branch keeps the old getGoalPosition()` calculation. Since
RETAIL_COMPATIBLE_CRC is defined to 1 by default, the compiler will select the old behavior and
exclude the fix.

Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp[521-536]
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp[551-566]
Core/GameEngine/Include/Common/GameDefines.h[90-97]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The diving-missile distance fix is under `#else` of `#if RETAIL_COMPATIBLE_CRC`, but `RETAIL_COMPATIBLE_CRC` defaults to `1`, so the fix is compiled out by default and the bug remains.

## Issue Context
`RETAIL_COMPATIBLE_CRC` is defined as `1` when not overridden. The PR’s new logic only runs when `RETAIL_COMPATIBLE_CRC` is `0`.

## Fix Focus Areas
- Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp[524-536]
- GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp[554-566]
- Core/GameEngine/Include/Common/GameDefines.h[94-96]

## Suggested fix
- Remove the `#if RETAIL_COMPATIBLE_CRC` gating for this change so the corrected distance logic is always used, OR
- Gate it behind a new, purpose-specific toggle (e.g. `PRESERVE_RETAIL_DIVE_MISSILE_DISTANCE` defaulting to `0`), instead of `RETAIL_COMPATIBLE_CRC`, so the bugfix is enabled in normal builds while still allowing strict retail behavior when explicitly requested.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can turn these tips off under Display preferences

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@Skyaero42 Skyaero42 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Makes sense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Something is not working right, typically is user facing Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker NoRetail This fix or change is not applicable with Retail game compatibility ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants