Repository navigation
bugfix(specialpower): Fix special powers never becoming ready on constructed structures - #3629
tintinhamans wants to merge 2 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Availability and construction readiness Generals/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp, GeneralsMD/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp |
Both editions initialize m_availableOnFrame to zero and set the ready frame only when a pre-built, non-shared power does not start paused. In non-retail-compatible builds, isReady() returns false and getPercentReady() returns 0.0f while the object is under construction. isReady() retrieves the controlling player through the validated local object pointer. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Suggested labels: Fix
Suggested reviewers: stubbjax, xezon
Merge Risk: 
Minimal · up to 4b714
-
No concrete merge-blocking defect is established by the available evidence.
Pre-merge checks: 
4
-
Full details: Linked Issues check
-
Explanation
[
#3618] requires USA Strategy Center battle plans to become available whenRETAIL_COMPATIBLE_CRCis disabled. BothGenerals/.../SpecialPowerModule.cppandGeneralsMD/.../SpecialPowerModule.cppnow initializem_availableOnFrameto0instead of0xFFFFFFFF. Both files also report powers as not ready during construction, so the construction safeguard remains active. The paused-power condition prevents paused powers from being marked ready before they are unpaused. No linked issue requires an automated test change.
Full details: Out of Scope Changes check
-
Explanation
The whole-PR diff is limited to
SpecialPowerModule.cppin the Generals and GeneralsMD trees. The timer initialization, construction readiness checks, paused-power handling, and validated-object player lookup directly support the special-power readiness fix and its safety behavior. No unrelated change is demonstrated.
-
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
[Medium impact] The PR appears safe to merge.
|
c5e2c9c to
41e618d
Compare
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 · Check construction status before the cheat bypass. · SpecialPowerModule.cpp:277-302
Generals/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp:277-302
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winCheck construction status before the cheat bypass.
The special-power delay cheat can set
m_specialPowerUsesDelaytoFALSE. In non-retail builds,isReady()then returnsTRUEbefore checkingOBJECT_STATUS_UNDER_CONSTRUCTION. The same PR already makesgetPercentReady()return0.0fduring construction before its cheat path, so construction is not intended to be a cheat exception. A direct script consumer can pass itsisReady()gate while the object is still being built.Apply the same ordering in both mirrored files.
Suggested fix
--- a/Generals/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp @@ -274,6 +274,14 @@ Bool SpecialPowerModule::isReady() const //------------------------------------------------------------------------------------------------- Bool SpecialPowerModule::isReady() const { + const Object* obj = getObject(); + +#if !RETAIL_COMPATIBLE_CRC + if ( obj && obj->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION ) ) + return FALSE; +#endif + #if defined(RTS_DEBUG) || defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE) // this is a cheat ... remove this for release! if( TheGlobalData->m_specialPowerUsesDelay == FALSE ) @@ -281,15 +289,8 @@ Bool SpecialPowerModule::isReady() const #endif - const Object* obj = getObject(); const SpecialPowerModuleData *modData = getSpecialPowerModuleData(); if ( obj && modData ) { -#if !RETAIL_COMPATIBLE_CRC - // TheSuperHackers @bugfix arcticdolphin 29/10/2026 Not ready while under construction. - if ( obj->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION ) ) - return FALSE; -#endif - Player *player = getObject()->getControllingPlayer();--- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp @@ -290,6 +290,14 @@ Bool SpecialPowerModule::isReady() const //------------------------------------------------------------------------------------------------- Bool SpecialPowerModule::isReady() const { + const Object* obj = getObject(); + +#if !RETAIL_COMPATIBLE_CRC + if ( obj && obj->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION ) ) + return FALSE; +#endif + #if defined(RTS_DEBUG) || defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE) // this is a cheat ... remove this for release! if( TheGlobalData->m_specialPowerUsesDelay == FALSE ) @@ -297,15 +305,8 @@ Bool SpecialPowerModule::isReady() const #endif - const Object* obj = getObject(); const SpecialPowerModuleData *modData = getSpecialPowerModuleData(); if ( obj && modData ) { -#if !RETAIL_COMPATIBLE_CRC - // TheSuperHackers @bugfix arcticdolphin 29/10/2026 Not ready while under construction. - if ( obj->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION ) ) - return FALSE; -#endif - Player *player = getObject()->getControllingPlayer();

Review info
-
Run configuration-
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
ef02c0d5-cd3c-4205-aff8-95918fa02480
Files selected for processing: 2-
Generals/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cppGeneralsMD/Code/GameEngine/Source/GameLogic/Object/SpecialPower/SpecialPowerModule.cpp
Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.
-
41e618d to
522bf93
Compare
|
While you're at it, would you mind adding
|
Done. |
|
I was going to have a look at this later, i can check if i can still launch nuke scaffolds with this implementation. |
4b714eb to
607b4a6
Compare
|
So i tested this last night and it appears to prevent the exploit i was using from occuring due to the under construction check in the Powers that are meant to be instantly available are also working as expected. You might also want to put with the Fixes in the original comment. |
Thanks for testing, will drop comments in those other PRs. |

Fixes #3618
Closes #1444
Closes #1461
With
RETAIL_COMPATIBLE_CRCoff, #1218 starts the special power timer at 0xFFFFFFFF so a structure cannot fire while under construction. OnlySpecialPowerCreateresets it when construction completes. A dozer-built structure without that module never gets a timer.The timer starts at 0 again, like retail, and a structure under construction reports its powers as not ready. The UI and
ActionManager::canDoSpecialPowerboth check that, so the nuke exploit from #1218 stays closed.