Repository navigation
bugfix(ai): Fix checkForCrateToPickup never returning the created crate - #3481
WebbontheWeb wants to merge 1 commit into
Conversation
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configuration
📒 Files selected for processing (2)
WalkthroughAI update logic now uses build-specific behavior for crate lookup and contact-weapon position searches in Generals and Zero Hour. Non-retail-compatible Zero Hour builds also validate explicit exit targets. ChangesAI update behavior
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~12 minutes Change: Bug fix · Severity of issue fixed: Low Suggested reviewers: Merge Risk: 🔵 Low · up to Some contact-weapon units may fail to find a reachable attack position when obstacles block their view. Restore the fallback in both editions; this is a localized gameplay issue. Pre-merge checks |
|
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
🟡 Minor · Retain the fallback for blocked in-range positions. · AIUpdate.cpp:3418-3422
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp:3418-3422
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRetain the fallback for blocked in-range positions.
When the attack position is in range but its attack view is blocked, the current non-retail guard skips
findPositionAround.computeAttackPaththen tries to path to the exact unreachable position and can fail. A nearby position returned byfindPositionAroundcan provide a reachable, clear attack position.Keep the range optimization only when the attack view is clear in both editions.
Suggested fix
-if (weapon && weapon->isContactWeapon() && !weapon->isWithinAttackRange(getObject(), &localPos) && !isPathAvailable(&localPos)) +if (weapon && weapon->isContactWeapon() && + (!weapon->isWithinAttackRange(getObject(), &localPos) || + (isDoingGroundMovement() && + TheAI->pathfinder()->isAttackViewBlockedByObstacle( + getObject(), *getObject()->getPosition(), nullptr, localPos))) && + !isPathAvailable(&localPos))Apply the same change in
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
c535d213-a6b4-4625-a0b9-d1f75c8165ad
📒 Files selected for processing (2)
Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cppGeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.
| // TheSuperHackers @bugfix WebbontheWeb 07/10/2026 Looks up the crate before clearing its id, | ||
| // so that computer controlled units pick up the crates created by their kills. |
There was a problem hiding this comment.
Once the retail compatible code is removed the comment is unnecessary. Better to put the comment in the retail compatibility section (3 lines up), and adjust it slightly so that it describes the retail compatible code.
| m_crateCreated = INVALID_ID; // we have processed it, so clear it. | ||
| Object* crate = TheGameLogic->findObjectByID(m_crateCreated); |
There was a problem hiding this comment.
I think we can take advantage of the fact that the retail compatible code always returns a nullptr. Perhaps like this:
Code
Object* AIUpdateInterface::checkForCrateToPickup()
{
#if RETAIL_COMPATIBLE_CRC
// TheSuperHackers @bugfix WebbontheWeb 07/10/2026
// ... describe that the retail compatible behavior of this function is bugged
m_crateCreated = INVALID_ID;
return nullptr;
#else
if (m_crateCreated != INVALID_ID)
{
Object* crate = TheGameLogic->findObjectByID(m_crateCreated);
m_crateCreated = INVALID_ID; // we have processed it, so clear it.
if (crate)
{
for (BehaviorModule** m = crate->getBehaviorModules(); *m; ++m)
{
CollideModuleInterface* collide = (*m)->getCollide();
if (!collide)
continue;
if( collide->wouldLikeToCollideWith(getObject()))
{
return crate;
}
}
}
}
return nullptr;
#endif
}There was a problem hiding this comment.
I prefer my solution because it keeps the intent of the original code, even though it's bugged. I'm completely willing to update if you have strong preference though
There was a problem hiding this comment.
I appreciate that your version nicely shows what the bug is, but that's not worth doing unnecessary run-time work for imo.
…ing the created crate
98e71bb to
bcd2da6
Compare
Updates
AIUpdateInterface::checkForCrateToPickupto search for crates before clearing their id, allowing units to correctly pickup crates. Since this updates AI behavior, it's turned off withRETAIL_COMPATIBLE_CRC.Before update - both guard and idle units ignore the crate
beforesalvagefix.mp4
After update - both guard and idle units persue the crate
aftersalvagefix.mp4
Map:
SalvagePickup.zip
All replays ran successfully.