Skip to content

refactor: Split preserve retail behavior flags#2691

Open
Stubbjax wants to merge 5 commits intoTheSuperHackers:mainfrom
Stubbjax:split-preserve-retail-behavior-flags
Open

refactor: Split preserve retail behavior flags#2691
Stubbjax wants to merge 5 commits intoTheSuperHackers:mainfrom
Stubbjax:split-preserve-retail-behavior-flags

Conversation

@Stubbjax
Copy link
Copy Markdown

@Stubbjax Stubbjax commented May 6, 2026

This change splits the PRESERVE_RETAIL_BEHAVIOR flag into a separate, dedicated flag for each fix. This allows publishers to more easily toggle controversial fixes without having to manually look through the code and figure out how particular fixes work or are implemented.

@Stubbjax Stubbjax self-assigned this May 6, 2026
@Stubbjax Stubbjax added Gen Relates to Generals ZH Relates to Zero Hour Refactor Edits the code with insignificant behavior changes, is never user facing labels May 6, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR replaces the single PRESERVE_RETAIL_BEHAVIOR flag in GameDefines.h with 14 dedicated per-behavior flags, giving publishers and developers fine-grained control over which retail quirks and bugs to retain. The previous thread's concern about PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION being undefined is resolved — the flag is now properly defined with a default of (1).

  • 14 new flags in GameDefines.h replace the monolithic PRESERVE_RETAIL_BEHAVIOR (1); flags default to (0) for bug-fixes deemed safe to enable and (1) for behaviors intentionally preserved.
  • ALLOW_MONEY_PER_MINUTE_FOR_PLAYER correctly translates the prior negative condition (#if !PRESERVE_RETAIL_BEHAVIOR) into a positive opt-in, maintaining the same default-disabled behavior.
  • All 35 changed files across both the Generals/ and GeneralsMD/ codebases are updated symmetrically; a grep confirms zero remaining references to the removed PRESERVE_RETAIL_BEHAVIOR macro.

Confidence Score: 5/5

This PR is safe to merge; it is a mechanical flag-splitting refactor with no unintended logic changes.

Every old PRESERVE_RETAIL_BEHAVIOR reference has been removed and correctly replaced with a scoped flag. The previously missing PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION is now defined, and no stale references to the old macro survive anywhere in the codebase.

No files require special attention; both Generals/ and GeneralsMD/ codebases are updated symmetrically and all flag substitutions are logically consistent.

Important Files Changed

Filename Overview
Core/GameEngine/Include/Common/GameDefines.h Core header: removes PRESERVE_RETAIL_BEHAVIOR and adds 14 granular PRESERVE_* flags plus ALLOW_MONEY_PER_MINUTE_FOR_PLAYER; PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION correctly added here as (1), resolving the prior thread.
Core/GameEngine/Source/GameClient/SelectionInfo.cpp Replaces PRESERVE_RETAIL_BEHAVIOR with PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION in both drag-selection guards; logic is preserved correctly since the new flag defaults to (1).
Generals/Code/GameEngine/Source/GameLogic/Object/Collide/CrateCollide/CrateCollide.cpp Switches m_allowMultiPickup initializer to PRESERVE_MULTI_CRATE_PICKUP (0); intentionally disables multi-crate pickup by default as a bug-fix.
Generals/Code/GameEngine/Source/GameLogic/Object/Body/ActiveBody.cpp PRESERVE_STRUCTURE_STEALTH_DURING_REPAIR (0) now guards m_lastDamageTimestamp update during healing; paired correctly with StealthUpdate.cpp change.
GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthUpdate.cpp Paired with ActiveBody.cpp: when PRESERVE_STRUCTURE_STEALTH_DURING_REPAIR=0, the healing-type guard is removed; since healing no longer updates the timestamp either, stealth is correctly unblocked during repair.
Generals/Code/GameEngine/Source/Common/GlobalData.cpp Replaces !PRESERVE_RETAIL_BEHAVIOR with ALLOW_MONEY_PER_MINUTE_FOR_PLAYER; both evaluate to 0 by default, preserving the existing disabled state of the INI entry.
Generals/Code/GameEngine/Include/Common/TunnelTracker.h PRESERVE_TUNNEL_HEAL_STACKING replaces PRESERVE_RETAIL_BEHAVIOR in the healObjects overload guard; GeneralsMD version updated identically.
Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp Both trimOldHistoricDamage and processHistoricDamage definitions switch to PRESERVE_UNRELIABLE_FIRESTORMS (0); guarded consistently in both Generals and GeneralsMD.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["GameDefines.h"] --> B["RETAIL_COMPATIBLE_CRC=1 (default)"]
    A --> C["RETAIL_COMPATIBLE_CRC=0 (non-retail mode)"]
    B --> D["Retail behaviour retained regardless of PRESERVE_* values"]
    C --> E["Flags=0 → fix applied"]
    C --> F["Flags=1 → retail preserved"]
    E --> G["PRESERVE_BUILDING_RESUMPTION_DELAY=0\nPRESERVE_MULTI_CRATE_PICKUP=0\nPRESERVE_NO_XP_FROM_FLAME_KILLS=0\nPRESERVE_STRUCTURE_STEALTH_DURING_REPAIR=0\nPRESERVE_UNRELIABLE_FIRESTORMS=0"]
    F --> H["PRESERVE_CHINOOK_PASSENGER_DUMPING=1\nPRESERVE_HARDCODED_BLACK_LOTUS_CASH_HACK=1\nPRESERVE_NO_XP_FROM_OCL_KILLS=1\nPRESERVE_NO_XP_FROM_POISON_KILLS=1\nPRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION=1\nPRESERVE_PERPETUAL_HORDE_BONUS=1\nPRESERVE_PREMATURE_BATTLE_BUS_DEATH=1\nPRESERVE_RADAR_WARNING_SUPPRESSION=1\nPRESERVE_TUNNEL_HEAL_STACKING=1"]
Loading

Reviews (2): Last reviewed commit: "tweak: Enable fixes approved by the Desi..." | Re-trigger Greptile

return FALSE;

#if !RTS_GENERALS || !PRESERVE_RETAIL_BEHAVIOR
#if !RTS_GENERALS || !PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Missing macro definition for PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION

PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION is referenced here and on line 379 but is never defined in GameDefines.h (only the 13 other split flags were added). An undefined identifier in a #if expression evaluates to 0, which silently flips both conditions: the first guard becomes !RTS_GENERALS || 1 (always true, enabling the fix unconditionally in Generals too), and the second guard becomes !RTS_GENERALS && 0 (always false, permanently disabling its code path). The intended per-flag control is completely lost.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Core/GameEngine/Source/GameClient/SelectionInfo.cpp
Line: 348

Comment:
**Missing macro definition for `PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION`**

`PRESERVE_OCCUPANT_DETECTION_VIA_DRAG_SELECTION` is referenced here and on line 379 but is never defined in `GameDefines.h` (only the 13 other split flags were added). An undefined identifier in a `#if` expression evaluates to `0`, which silently flips both conditions: the first guard becomes `!RTS_GENERALS || 1` (always true, enabling the fix unconditionally in Generals too), and the second guard becomes `!RTS_GENERALS && 0` (always false, permanently disabling its code path). The intended per-flag control is completely lost.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It is missing yes.

@Mauller
Copy link
Copy Markdown

Mauller commented May 6, 2026

I think it would be better to split these defines out into their own file of GameplayFixDefines or something similar

But keep preserve retail behaviour as an encompassing switch.

#endif

#ifndef PRESERVE_UNRELIABLE_FIRESTORMS
#define PRESERVE_UNRELIABLE_FIRESTORMS (1)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe set those to 0 that where already approved by the Committee?

#endif

#ifndef ENABLE_MONEY_PER_MINUTE
#define ENABLE_MONEY_PER_MINUTE (0) // When enabled, a money-per-minute stat is calculated and displayed in-game
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ENABLE_MONEY_PER_MINUTE_FOR_PLAYER

This setting only prevents it showing to a player, not observers

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think ALLOW_MONEY_PER_MINUTE_FOR_PLAYER would suit more as It does allow players to enable it, not enable it for players.

@Stubbjax
Copy link
Copy Markdown
Author

Stubbjax commented May 7, 2026

I think it would be better to split these defines out into their own file of GameplayFixDefines or something similar

But keep preserve retail behaviour as an encompassing switch.

How useful do you think a master flag would be? Does it outweigh the additional maintenance burden?

#endif

#ifndef PRESERVE_UNRELIABLE_FIRESTORMS
#define PRESERVE_UNRELIABLE_FIRESTORMS (0)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I suggest also add comments that these are approved by Committee, to understand why they are default 0 while others are still 1.

Copy link
Copy Markdown
Author

@Stubbjax Stubbjax May 7, 2026

Choose a reason for hiding this comment

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

How should that look? A // TheSuperHackers @info Approved by the Design Committee. comment at the end of each (0)?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Maybe

// Fix for this unfavourable behavior was approved by the Game Design Committee

TheSuperHackers @info is not necessary because the file is ours.

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

Labels

Gen Relates to Generals Refactor Edits the code with insignificant behavior changes, is never user facing ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants