Skip to content

bugfix(ini): Store every debris model name in GenericObjectCreationNugget::parseDebrisObjectNames#2597

Open
Caball009 wants to merge 1 commit into
TheSuperHackers:mainfrom
Caball009:ini_change_next_token
Open

bugfix(ini): Store every debris model name in GenericObjectCreationNugget::parseDebrisObjectNames#2597
Caball009 wants to merge 1 commit into
TheSuperHackers:mainfrom
Caball009:ini_change_next_token

Conversation

@Caball009

@Caball009 Caball009 commented Apr 13, 2026

Copy link
Copy Markdown

This PR fixes a minor bug in the parsing of the ini OCL model names; every even token would be skipped.

This affects two types of OCL:

  1. ObjectCreationList Name - CreateDebris (doesn't impact game logic AFAIK)
  2. ObjectCreationList Name - CreateObject (does impact game logic AFAIK)

Example of debris with multiple model names:
https://github.com/TheSuperHackers/GeneralsGamePatch/blob/5845293dd12ab10c5f16c6f3116ce526f62dc369/Patch104pZH/GameFilesOriginalZH/Data/INI/ObjectCreationList.ini#L2130-L2138

It should have no effect on the game logic for the default ini files, but it may be different for mods that create ObjectCreationList Name - CreateObject with more than one model name.

GenericObjectCreationNugget::m_names is used for the game logic here:

Int pick = GameLogicRandomValue(0, m_names.size() - 1);

@Caball009 Caball009 added the Minor Severity: Minor < Major < Critical < Blocker label Apr 13, 2026
@Mauller

Mauller commented Apr 13, 2026

Copy link
Copy Markdown

I mentioned this in the other PR, but i think we should just go down to having a single function getNextToken but it can return null.

External code should then check for null on the first token and gracefully handle it instead of throwing like the original variant did.

@Caball009 Caball009 force-pushed the ini_change_next_token branch from ecbefac to a716f4d Compare June 28, 2026 22:12
@Caball009 Caball009 added Gen Relates to Generals ZH Relates to Zero Hour Fix Is fixing something, but is not user facing labels Jun 28, 2026
@Caball009 Caball009 changed the title tweak(ini): Improve consistency in use of INI::getNextTokenOrNull fix(ini): Remove superfluous call to INI::getNextTokenOrNull Jun 28, 2026
@Caball009 Caball009 changed the title fix(ini): Remove superfluous call to INI::getNextTokenOrNull fix(ini): Remove superfluous call to INI::getNextTokenOrNull in GenericObjectCreationNugget::parseDebrisObjectNames Jun 28, 2026
@Caball009

Copy link
Copy Markdown
Author

I narrowed the scope of this PR.

@Caball009 Caball009 marked this pull request as ready for review June 28, 2026 23:04
@greptile-apps

greptile-apps Bot commented Jun 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a token-skipping bug in GenericObjectCreationNugget::parseDebrisObjectNames, where the INI parser advanced twice per loop iteration (once in the loop body, once in the for-increment), causing every second debris object name to be silently dropped. The fix wraps the redundant in-body getNextTokenOrNull() call in a #if RETAIL_COMPATIBLE_CRC guard to preserve the original behavior for CRC-compatible builds while correcting parsing in non-retail builds.

  • Bug fix: Removes the extra ini->getNextTokenOrNull() call inside the loop body so all tokens are consumed exactly once per iteration, restoring full debris name lists for non-retail builds.
  • Retail compatibility: The original (buggy) behavior is preserved under the RETAIL_COMPATIBLE_CRC macro to avoid breaking replay/CRC compatibility with the shipped retail game.
  • Both game directories affected: The identical fix is applied to both Generals/ and GeneralsMD/ (Zero Hour) copies of ObjectCreationList.cpp.

Confidence Score: 5/5

Safe to merge — the change is a minimal, well-scoped fix with no risk of unintended side effects outside the debris name parsing loop.

The fix removes exactly one redundant getNextTokenOrNull() call per loop iteration and correctly preserves the original double-advance under RETAIL_COMPATIBLE_CRC for CRC/replay compatibility. Both affected files receive the identical change. The loop logic before and after is easy to follow and the fix is demonstrably correct.

No files require special attention.

Important Files Changed

Filename Overview
Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp Wraps the superfluous in-body getNextTokenOrNull() in #if RETAIL_COMPATIBLE_CRC so non-retail builds parse all debris names correctly; change is minimal and correct.
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp Identical fix applied to the Zero Hour copy of parseDebrisObjectNames; same correctness assessment as the Generals counterpart.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["for-init: token = getNextToken()"] --> B{token != null?}
    B -- No --> Z[End loop]
    B -- Yes --> C["push token to m_names"]
    C --> D{RETAIL_COMPATIBLE_CRC?}
    D -- Yes --> E["token = getNextTokenOrNull()\n(extra advance — skips one token)"]
    E --> F["for-increment: token = getNextTokenOrNull()"]
    D -- No --> F
    F --> B

    style E fill:#f9a,stroke:#c33
    style D fill:#adf,stroke:#36c
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["for-init: token = getNextToken()"] --> B{token != null?}
    B -- No --> Z[End loop]
    B -- Yes --> C["push token to m_names"]
    C --> D{RETAIL_COMPATIBLE_CRC?}
    D -- Yes --> E["token = getNextTokenOrNull()\n(extra advance — skips one token)"]
    E --> F["for-increment: token = getNextTokenOrNull()"]
    D -- No --> F
    F --> B

    style E fill:#f9a,stroke:#c33
    style D fill:#adf,stroke:#36c
Loading

Reviews (1): Last reviewed commit: "Removed superfluous call to 'getNextToke..." | Re-trigger Greptile

@Caball009 Caball009 requested a review from xezon June 29, 2026 18:28
@xezon

xezon commented Jul 4, 2026

Copy link
Copy Markdown

This is a bug fix, no? If every second debris model was skipped, then not all debris objects were used in the game, right? So this is a user facing fix?

Can we get list of all affected Objects and Models, so that we can review this?

@Caball009

Caball009 commented Jul 4, 2026

Copy link
Copy Markdown
Author

This is a bug fix, no? If every second debris model was skipped, then not all debris objects were used in the game, right? So this is a user facing fix?

Perhaps I wasn't testing it correctly, but I couldn't really see a difference.

https://raw.githubusercontent.com/TheSuperHackers/GeneralsGamePatch/refs/heads/main/Patch104pZH/GameFilesOriginalZH/Data/INI/ObjectCreationList.ini

Here's the complete list of skipped debris for the default ini files (only model names, no object names):
OCL_SmallStructureDebris                 - ABPwrPlant_d02
OCL_SmallStructureDebris                 - ABPwrPlant_d04
OCL_SmallStructureDebris                 - ABPwrPlant_d06
OCL_SmallStructureDebris                 - ABPwrPlant_d08
OCL_SmallStructureDebris                 - ABPwrPlant_d10
OCL_SmallStructureDebris                 - ABPwrPlant_d12
OCL_SmallStructureDebris                 - ABPwrPlant_d14
OCL_SmallStructureDebris                 - ABPwrPlant_d16
OCL_SmallStructureDebris                 - ABPwrPlant_d18
OCL_SmallStructureDebris                 - ABPwrPlant_d20
OCL_SmallStructureDebris                 - ABPwrPlant_d22
OCL_SmallStructureDebris                 - ABPwrPlant_d24
OCL_SmallStructureDebris                 - ABPwrPlant_d26
OCL_SmallStructureDebris                 - ABPwrPlant_d28
OCL_SmallStructureDebris                 - ABPwrPlant_d30
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d02
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d04
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d06
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d08
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d10
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d12
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d14
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d16
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d18
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d20
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d22
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d24
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d26
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d28
OCL_ParticleUplinkDeathFinal             - ABPwrPlant_d30
OCL_LargeStructureDebris                 - ABPwrPlant_d02
OCL_LargeStructureDebris                 - ABPwrPlant_d04
OCL_LargeStructureDebris                 - ABPwrPlant_d06
OCL_LargeStructureDebris                 - ABPwrPlant_d08
OCL_LargeStructureDebris                 - ABPwrPlant_d10
OCL_LargeStructureDebris                 - ABPwrPlant_d12
OCL_LargeStructureDebris                 - ABPwrPlant_d14
OCL_LargeStructureDebris                 - ABPwrPlant_d16
OCL_LargeStructureDebris                 - ABPwrPlant_d18
OCL_LargeStructureDebris                 - ABPwrPlant_d20
OCL_LargeStructureDebris                 - ABPwrPlant_d22
OCL_LargeStructureDebris                 - ABPwrPlant_d24
OCL_LargeStructureDebris                 - ABPwrPlant_d26
OCL_LargeStructureDebris                 - ABPwrPlant_d28
OCL_LargeStructureDebris                 - ABPwrPlant_d30
OCL_VeryLargeStructureDebris             - ABPwrPlant_d02
OCL_VeryLargeStructureDebris             - ABPwrPlant_d04
OCL_VeryLargeStructureDebris             - ABPwrPlant_d06
OCL_VeryLargeStructureDebris             - ABPwrPlant_d08
OCL_VeryLargeStructureDebris             - ABPwrPlant_d10
OCL_VeryLargeStructureDebris             - ABPwrPlant_d12
OCL_VeryLargeStructureDebris             - ABPwrPlant_d14
OCL_VeryLargeStructureDebris             - ABPwrPlant_d16
OCL_VeryLargeStructureDebris             - ABPwrPlant_d18
OCL_VeryLargeStructureDebris             - ABPwrPlant_d20
OCL_VeryLargeStructureDebris             - ABPwrPlant_d22
OCL_VeryLargeStructureDebris             - ABPwrPlant_d24
OCL_VeryLargeStructureDebris             - ABPwrPlant_d26
OCL_VeryLargeStructureDebris             - ABPwrPlant_d28
OCL_VeryLargeStructureDebris             - ABPwrPlant_d30
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d02
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d04
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d06
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d08
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d10
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d12
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d14
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d16
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d18
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d20
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d22
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d24
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d26
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d28
OCL_AmericaWarFactoryDebris              - ABPwrPlant_d30
OCL_ABPowerPlantExplode                  - ABPwrPlant_d02
OCL_ABPowerPlantExplode                  - ABPwrPlant_d04
OCL_ABPowerPlantExplode                  - ABPwrPlant_d06
OCL_ABPowerPlantExplode                  - ABPwrPlant_d08
OCL_ABPowerPlantExplode                  - ABPwrPlant_d10
OCL_ABPowerPlantExplode                  - ABPwrPlant_d12
OCL_ABPowerPlantExplode                  - ABPwrPlant_d14
OCL_ABPowerPlantExplode                  - ABPwrPlant_d16
OCL_ABPowerPlantExplode                  - ABPwrPlant_d18
OCL_ABPowerPlantExplode                  - ABPwrPlant_d20
OCL_ABPowerPlantExplode                  - ABPwrPlant_d22
OCL_ABPowerPlantExplode                  - ABPwrPlant_d24
OCL_ABPowerPlantExplode                  - ABPwrPlant_d26
OCL_ABPowerPlantExplode                  - ABPwrPlant_d28
OCL_ABPowerPlantExplode                  - ABPwrPlant_d30
OCL_ABStingerSiteDebris                  - ABPwrPlant_d02
OCL_ABStingerSiteDebris                  - ABPwrPlant_d04
OCL_ABStingerSiteDebris                  - ABPwrPlant_d06
OCL_ABStingerSiteDebris                  - ABPwrPlant_d08
OCL_ABStingerSiteDebris                  - ABPwrPlant_d10
OCL_ABStingerSiteDebris                  - ABPwrPlant_d12
OCL_ABStingerSiteDebris                  - ABPwrPlant_d14
OCL_ABStingerSiteDebris                  - ABPwrPlant_d16
OCL_ABStingerSiteDebris                  - ABPwrPlant_d18
OCL_ABStingerSiteDebris                  - ABPwrPlant_d20
OCL_ABStingerSiteDebris                  - ABPwrPlant_d22
OCL_ABStingerSiteDebris                  - ABPwrPlant_d24
OCL_ABStingerSiteDebris                  - ABPwrPlant_d26
OCL_ABStingerSiteDebris                  - ABPwrPlant_d28
OCL_ABStingerSiteDebris                  - ABPwrPlant_d30
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d02
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d04
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d06
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d08
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d10
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d12
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d14
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d16
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d18
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d20
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d22
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d24
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d26
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d28
OCL_ABTunnelNetworkDebris                - ABPwrPlant_d30
OCL_HelicopterStartDeath                 - GXMammoth_D02
OCL_HelicopterStartDeath                 - GXMammoth_D04
OCL_HelicopterBladeExplosion             - GXMammoth_D02
OCL_HelicopterBladeExplosion             - GXMammoth_D04
OCL_HelicopterBladeExplosion             - GXMammoth_D06
OCL_HelicopterBladeExplosion             - GXMammoth_D08
OCL_HelicopterHitGround                  - GXMammoth_D10
OCL_HelicopterHitGround                  - GXMammoth_D12
OCL_GroundedHelicopterBlowUp             - GXMammoth_D02
OCL_GroundedHelicopterBlowUp             - GXMammoth_D04
OCL_GroundedHelicopterBlowUp             - GXMammoth_D06
OCL_GroundedHelicopterBlowUp             - GXMammoth_D08
OCL_GroundedHelicopterBlowUp             - GXMammoth_D10
OCL_GroundedHelicopterBlowUp             - GXMammoth_D12
OCL_DaisyCutterExplode                   - GXMammoth_D02
OCL_DaisyCutterExplode                   - GXMammoth_D04
OCL_FinalHumveeDebris                    - AVScrap3
OCL_FinalHumveeDebris                    - AVScrap5
OCL_FinalAmbulanceDebris                 - AVScrap3
OCL_FinalAmbulanceDebris                 - AVScrap5
OCL_FinalTroopCrawlerDebris              - AVScrap3
OCL_FinalTroopCrawlerDebris              - AVScrap5
OCL_FinalAssaultTroopCrawlerDebris       - AVScrap3
OCL_FinalAssaultTroopCrawlerDebris       - AVScrap5
OCL_ChinaTankBattleMasterDebris          - AVScrap3
OCL_ChinaTankBattleMasterDebris          - AVScrap5
OCL_ChinaTankGattlingDebris              - AVScrap3
OCL_ChinaTankGattlingDebris              - AVScrap5
OCL_ChinaTankECMDebris                   - AVScrap3
OCL_ChinaTankECMDebris                   - AVScrap5
OCL_BattleBusStartUndeath                - GXMammoth_D10
OCL_BattleBusStartUndeath                - GXMammoth_D12
OCL_BattleBusHitGround                   - GXMammoth_D10
OCL_BattleBusHitGround                   - GXMammoth_D12
OCL_BigPlaneDeath                        - GXMammoth_D10
OCL_BigPlaneDeath                        - GXMammoth_D12
OCL_AmericaJetCargoDeathStart            - GXMammoth_D10
OCL_AmericaJetCargoDeathStart            - GXMammoth_D12
OCL_AmericaJetCargoHulkDeath             - GXMammoth_D10
OCL_AmericaJetCargoHulkDeath             - GXMammoth_D12
OCL_MIGDeathFinalBlowUp_CinematicVersion - AVScrap3
OCL_MIGDeathFinalBlowUp_CinematicVersion - AVScrap5
OCL_VehicleCrashesIntoBuilding           - GXMammoth_D10
OCL_VehicleCrashesIntoBuilding           - GXMammoth_D12
OCL_TsingMaExplosion                     - CMTsingMa_d05
OCL_TsingMaExplosion                     - CMTsingMa_d02
OCL_TrainWreckExplosion                  - CMTsingMa_d04
OCL_MOABExplode                          - GXMammoth_D02
OCL_MOABExplode                          - GXMammoth_D04
OCL_LeafletContainerExplode              - GXMammoth_D02
OCL_LeafletContainerExplode              - GXMammoth_D04
SupW_OCL_FuelAirBomb                     - GXMammoth_D02
SupW_OCL_FuelAirBomb                     - GXMammoth_D04
AirF_OCL_AuroraBombExplode               - GXMammoth_D02
AirF_OCL_AuroraBombExplode               - GXMammoth_D04

@Caball009 Caball009 changed the title fix(ini): Remove superfluous call to INI::getNextTokenOrNull in GenericObjectCreationNugget::parseDebrisObjectNames fix(ini): Store every debris model name in GenericObjectCreationNugget::parseDebrisObjectNames Jul 5, 2026
@Caball009 Caball009 changed the title fix(ini): Store every debris model name in GenericObjectCreationNugget::parseDebrisObjectNames bugfix(ini): Store every debris model name in GenericObjectCreationNugget::parseDebrisObjectNames Jul 5, 2026
@Caball009 Caball009 added Bug Something is not working right, typically is user facing and removed Fix Is fixing something, but is not user facing labels Jul 5, 2026
@xezon

xezon commented Jul 5, 2026

Copy link
Copy Markdown

Here's the complete list of skipped debris for the default ini files (only model names, no object names):

Ok that is quite a big list.

Perhaps I wasn't testing it correctly, but I couldn't really see a difference.

It should be testable by putting Retail vs Patch side by side and then trigger a debris event and compare the visuals.

@Caball009

Copy link
Copy Markdown
Author

It should be testable by putting Retail vs Patch side by side and then trigger a debris event and compare the visuals.

Yeah, that's how that works.

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 ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants