Conversation
b303e28 to
abba8ab
Compare
|
With the validate code "gui hack" check you could put this one for review independent of the data change. |
…kes effect in Generals
b88197d to
6434a09
Compare
PR Summary by QodoFix UI message delay conversion and normalize retail value
AI Description
Diagram
High-Level Assessment
Files changed (4)
|
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp | Corrects frame conversion but applies the retail-value normalization to every parsed InGameUI configuration. |
| GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp | Mirrors the conversion correction and the overly broad normalization in the Zero Hour implementation. |
| Generals/Code/GameEngine/Include/GameClient/InGameUI.h | Declares the new validation method used by the Generals parser. |
| GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h | Declares the corresponding validation method for Zero Hour. |
Prompt To Fix All With AI
### Issue 1
Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp:935-938
**Intentional delays are overridden**
Every parsed `InGameUI` block that sets `MessageDelayMS = 75000` is silently rewritten to `7500` when GUI hacks are enabled. Because this parser also handles layered and mod-provided InGameUI files, an intentional 75-second delay becomes 7.5 seconds, causing messages to fade roughly 67.5 seconds earlier than configured. The same issue appears in `GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp:964-967`. Restrict this correction to known retail source data rather than applying it to every parsed value.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "bugfix(gui): Normalize retail message de..." | Re-trigger Greptile
Code Review by Qodo
1. Negative delays keep messages forever
|
| const int messageTimeout = m_messageDelayMS / LOGICFRAMES_PER_SECOND / 1000; | ||
| // TheSuperHackers @bugfix bobtista 13/08/2026 Convert milliseconds to logic frames. Dividing by | ||
| // both evaluated to floor(m_messageDelayMS / 30000), so MessageDelayMS had no effect below 30s | ||
| const int messageTimeout = REAL_TO_INT_CEIL( ConvertDurationFromMsecsToFrames( (Real)m_messageDelayMS ) ); |
There was a problem hiding this comment.
1. Negative delays keep messages forever 🐞 Bug ≡ Correctness
InGameUI::update converts a negative m_messageDelayMS into a negative signed timeout and compares it with an unsigned message age. Values such as -1000, which previously truncated to zero, now become approximately -30 and are promoted to a huge unsigned threshold in both game editions, preventing the fade and removal block from running during normal play.
Agent Prompt
## Issue description
Negative `MessageDelayMS` values can produce a negative timeout that is promoted to unsigned during the message-age comparison, effectively preventing messages from fading or being removed.
## Fix Focus Areas
- Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp[1864-1866]
- GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp[1898-1900]
## Recommended Fix
Clamp `m_messageDelayMS` to zero before converting it to logic frames in both implementations, or validate it unconditionally after parsing. Ensure the resulting timeout is nonnegative before it is compared with the unsigned message age.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| // TheSuperHackers @bugfix bobtista 02/09/2026 Correct the known retail InGameUI.ini message delay typo | ||
| if (m_messageDelayMS == 75000) | ||
| { | ||
| m_messageDelayMS = 7500; |
There was a problem hiding this comment.
Intentional delays are overridden
Every parsed InGameUI block that sets MessageDelayMS = 75000 is silently rewritten to 7500 when GUI hacks are enabled. Because this parser also handles layered and mod-provided InGameUI files, an intentional 75-second delay becomes 7.5 seconds, causing messages to fade roughly 67.5 seconds earlier than configured. The same issue appears in GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp:964-967. Restrict this correction to known retail source data rather than applying it to every parsed value.
Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp
Line: 935-938
Comment:
**Intentional delays are overridden**
Every parsed `InGameUI` block that sets `MessageDelayMS = 75000` is silently rewritten to `7500` when GUI hacks are enabled. Because this parser also handles layered and mod-provided InGameUI files, an intentional 75-second delay becomes 7.5 seconds, causing messages to fade roughly 67.5 seconds earlier than configured. The same issue appears in `GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp:964-967`. Restrict this correction to known retail source data rather than applying it to every parsed value.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| UnsignedInt currLogicFrame = TheGameLogic->getFrame(); | ||
| const int messageTimeout = m_messageDelayMS / LOGICFRAMES_PER_SECOND / 1000; | ||
| // TheSuperHackers @bugfix bobtista 13/08/2026 Convert milliseconds to logic frames. Dividing by | ||
| // both evaluated to floor(m_messageDelayMS / 30000), so MessageDelayMS had no effect below 30s |
Fixes #3131.
InGameUI::updatecomputed the message timeout asm_messageDelayMS / LOGICFRAMES_PER_SECOND / 1000, dividing by both instead of converting milliseconds to logic frames. For positive values that reduces tofloor(MessageDelayMS / 30000), which is wrong by a factor of about 900 and has no practical effect at any realistic setting.REAL_TO_INT_CEIL( ConvertDurationFromMsecsToFrames( ... ) )is the conversion the codebase already uses for this, atScriptEngine.cpp:6746,ScriptEngine.cpp:6803andFXList.cpp:650.Now converts through
ConvertDurationFromMsecsToFrames, rounding partial frames up as that helper documents, so the timeout is the configured delay expressed in logic frames.The shipped
InGameUI.inicarriesMessageDelayMS = 75000, an extra zero that never mattered while the conversion was broken. Once the conversion is correct that value would hold UI messages for 75 seconds, soInGameUI::validate()normalizes the known retail value to 7500 underENABLE_GUI_HACKS, in the same spirit as the smudge particle validation.TheSuperHackers/GeneralsGamePatch2#175 is the source data correction and can land whenever it is ready; once it does the validation is a no-op, since it only matches the exact retail value.
Predicted total message lifetime at 30 render / 30 logic FPS, including the existing alpha drain:
Measured on MD_CHI01 before the validation was added, with the shipped
MessageDelayMS = 75000reaching the timeout unaltered, posting a message at logic frame 300 and logging the computed timeout and the message's age when it is removed:Verified in game by instrumenting the message alpha and setting the delay to 3400 ms, which converts to 103 logic frames. The message stayed at full alpha through age 100 and only began draining after the timeout:
Age 100 is the telling one: the existing fade amount becomes non-zero there, so on current
main(where the timeout evaluates to 2 frames) the message is already draining by then. Holding to 103 shows the configured delay is what gates the fade.Todo: