Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions Core/GameEngine/Include/Common/GameDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,20 @@
// Note: Retail compatibility must not be broken before this project officially does.
// Use RETAIL_COMPATIBLE_CRC and RETAIL_COMPATIBLE_XFER_SAVE to guard breaking changes.

#ifndef RETAIL_COMPATIBLE_CRC
#define RETAIL_COMPATIBLE_CRC (1) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04
#endif

#ifndef RETAIL_COMPATIBLE_XFER_SAVE
#define RETAIL_COMPATIBLE_XFER_SAVE (1) // Game is expected to be Xfer Save compatible with retail Generals 1.08, Zero Hour 1.04
#endif

#if RETAIL_COMPATIBLE_CRC || !defined(PRESERVE_RETAIL_BEHAVIOR)
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 don't think re-adding the PRESEVE_RETAIL_BEHAVIOR flag is really necessary.

We only need to fix the site of use.

Copy link
Copy Markdown

@xezon xezon May 18, 2026

Choose a reason for hiding this comment

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

Yes. Just add RETAIL_COMPATIBLE_CRC next to PRESERVE_STRUCTURE_STEALTH_DURING_REPAIR and PRESERVE_MULTI_CRATE_PICKUP and this will be it.

#define PRESERVE_RETAIL_BEHAVIOR (1) // Retain specific behavior present in retail Generals 1.08 and Zero Hour 1.04. Should only be used in this file.
#endif
Comment on lines +34 to +36
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 The PRESERVE_RETAIL_BEHAVIOR condition is always true at this point in the file, making RETAIL_COMPATIBLE_CRC have no practical effect. When RETAIL_COMPATIBLE_CRC is 0, the expression evaluates to 0 || !defined(PRESERVE_RETAIL_BEHAVIOR). Since PRESERVE_RETAIL_BEHAVIOR has not been defined yet at this location, !defined(PRESERVE_RETAIL_BEHAVIOR) is unconditionally true, so the macro is set to 1 regardless of the CRC flag. A developer setting RETAIL_COMPATIBLE_CRC=0 to test bug-fixed code will find that all PRESERVE_RETAIL_BEHAVIOR-gated paths (building resumption delay, multi-crate pickup, flame-kill XP, structure stealth, unreliable firestorms, money-per-minute) remain active.

Suggested change
#if RETAIL_COMPATIBLE_CRC || !defined(PRESERVE_RETAIL_BEHAVIOR)
#define PRESERVE_RETAIL_BEHAVIOR (1) // Retain specific behavior present in retail Generals 1.08 and Zero Hour 1.04. Should only be used in this file.
#endif
#ifndef PRESERVE_RETAIL_BEHAVIOR
#define PRESERVE_RETAIL_BEHAVIOR RETAIL_COMPATIBLE_CRC // Retain specific behavior present in retail Generals 1.08 and Zero Hour 1.04. Should only be used in this file.
#endif
Prompt To Fix With AI
This is a comment left during a code review.
Path: Core/GameEngine/Include/Common/GameDefines.h
Line: 34-36

Comment:
The `PRESERVE_RETAIL_BEHAVIOR` condition is always true at this point in the file, making `RETAIL_COMPATIBLE_CRC` have no practical effect. When `RETAIL_COMPATIBLE_CRC` is 0, the expression evaluates to `0 || !defined(PRESERVE_RETAIL_BEHAVIOR)`. Since `PRESERVE_RETAIL_BEHAVIOR` has not been defined yet at this location, `!defined(PRESERVE_RETAIL_BEHAVIOR)` is unconditionally true, so the macro is set to 1 regardless of the CRC flag. A developer setting `RETAIL_COMPATIBLE_CRC=0` to test bug-fixed code will find that all `PRESERVE_RETAIL_BEHAVIOR`-gated paths (building resumption delay, multi-crate pickup, flame-kill XP, structure stealth, unreliable firestorms, money-per-minute) remain active.

```suggestion
#ifndef PRESERVE_RETAIL_BEHAVIOR
#define PRESERVE_RETAIL_BEHAVIOR RETAIL_COMPATIBLE_CRC // Retain specific behavior present in retail Generals 1.08 and Zero Hour 1.04. Should only be used in this file.
#endif
```

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

Comment thread
xezon marked this conversation as resolved.

#ifndef PRESERVE_BUILDING_RESUMPTION_DELAY
#define PRESERVE_BUILDING_RESUMPTION_DELAY (0) // The fix for this unfavorable behavior was approved by the Game Design Committee.
#define PRESERVE_BUILDING_RESUMPTION_DELAY PRESERVE_RETAIL_BEHAVIOR // The fix for this unfavorable behavior was approved by the Game Design Committee.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The problem here is that you have re-enabled the retail behaviour being used when retail compatibler CRC is disabled.

#endif

#ifndef PRESERVE_CHINOOK_PASSENGER_DUMPING
Expand All @@ -36,11 +48,11 @@
#endif

#ifndef PRESERVE_MULTI_CRATE_PICKUP
#define PRESERVE_MULTI_CRATE_PICKUP (0) // The fix for this unfavorable behavior was approved by the Game Design Committee.
#define PRESERVE_MULTI_CRATE_PICKUP PRESERVE_RETAIL_BEHAVIOR // The fix for this unfavorable behavior was approved by the Game Design Committee.
#endif

#ifndef PRESERVE_NO_XP_FROM_FLAME_KILLS
#define PRESERVE_NO_XP_FROM_FLAME_KILLS (0) // The fix for this unfavorable behavior was approved by the Game Design Committee.
#define PRESERVE_NO_XP_FROM_FLAME_KILLS PRESERVE_RETAIL_BEHAVIOR // The fix for this unfavorable behavior was approved by the Game Design Committee.
#endif

#ifndef PRESERVE_NO_XP_FROM_OCL_KILLS
Expand Down Expand Up @@ -68,29 +80,21 @@
#endif

#ifndef PRESERVE_STRUCTURE_STEALTH_DURING_REPAIR
#define PRESERVE_STRUCTURE_STEALTH_DURING_REPAIR (0) // The fix for this unfavorable behavior was approved by the Game Design Committee.
#define PRESERVE_STRUCTURE_STEALTH_DURING_REPAIR PRESERVE_RETAIL_BEHAVIOR // The fix for this unfavorable behavior was approved by the Game Design Committee.
#endif

#ifndef PRESERVE_TUNNEL_HEAL_STACKING
#define PRESERVE_TUNNEL_HEAL_STACKING (1)
#endif

#ifndef PRESERVE_UNRELIABLE_FIRESTORMS
#define PRESERVE_UNRELIABLE_FIRESTORMS (0) // The fix for this unfavorable behavior was approved by the Game Design Committee.
#define PRESERVE_UNRELIABLE_FIRESTORMS PRESERVE_RETAIL_BEHAVIOR // The fix for this unfavorable behavior was approved by the Game Design Committee.
#endif

#ifndef PRESERVE_RETAIL_SCRIPTED_CAMERA
#define PRESERVE_RETAIL_SCRIPTED_CAMERA (1) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04
#endif

#ifndef RETAIL_COMPATIBLE_CRC
#define RETAIL_COMPATIBLE_CRC (1) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04
#endif

#ifndef RETAIL_COMPATIBLE_XFER_SAVE
#define RETAIL_COMPATIBLE_XFER_SAVE (1) // Game is expected to be Xfer Save compatible with retail Generals 1.08, Zero Hour 1.04
#endif

// This is here to easily toggle between the retail compatible with fixed pathfinding fallback and pure fixed pathfinding mode
#ifndef RETAIL_COMPATIBLE_PATHFINDING
#define RETAIL_COMPATIBLE_PATHFINDING (1)
Expand Down Expand Up @@ -123,7 +127,7 @@
#endif

#ifndef ALLOW_MONEY_PER_MINUTE_FOR_PLAYER
#define ALLOW_MONEY_PER_MINUTE_FOR_PLAYER (0) // When enabled, a money-per-minute stat is calculated and displayed in-game
#define ALLOW_MONEY_PER_MINUTE_FOR_PLAYER PRESERVE_RETAIL_BEHAVIOR // When enabled, a money-per-minute stat is calculated and displayed in-game
#endif

// Previously the configurable shroud sat behind #if defined(RTS_DEBUG)
Expand Down
2 changes: 1 addition & 1 deletion GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class TunnelTracker : public MemoryPoolObject,
static void destroyObject( Object *obj, void *userData ); ///< Callback for Iterate Contained system
static void healObject( Object *obj, void *frames ); ///< Callback for Iterate Contained system

#if PRESERVE_TUNNEL_HEAL_STACKING || RETAIL_COMPATIBLE_CRC
#if RETAIL_COMPATIBLE_CRC || PRESERVE_TUNNEL_HEAL_STACKING
void healObjects(Real frames); ///< heal all objects within the tunnel
#else
void healObjects(); ///< heal all objects within the tunnel
Expand Down
2 changes: 1 addition & 1 deletion GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ void Player::update()
}
}

#if !PRESERVE_TUNNEL_HEAL_STACKING && !RETAIL_COMPATIBLE_CRC
#if !(RETAIL_COMPATIBLE_CRC || PRESERVE_TUNNEL_HEAL_STACKING)
// TheSuperHackers @bugfix Stubbjax 26/09/2025 The Tunnel System now heals
// all units once per frame instead of once per frame per Tunnel Network.
TunnelTracker* tunnelSystem = getTunnelSystem();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ void TunnelTracker::destroyObject( Object *obj, void * )

// ------------------------------------------------------------------------
// heal all the objects within the tunnel system using the iterateContained function
#if PRESERVE_TUNNEL_HEAL_STACKING || RETAIL_COMPATIBLE_CRC
#if RETAIL_COMPATIBLE_CRC || PRESERVE_TUNNEL_HEAL_STACKING
void TunnelTracker::healObjects(Real frames)
{
iterateContained(healObject, &frames, FALSE);
Expand All @@ -302,7 +302,7 @@ void TunnelTracker::healObject( Object *obj, void *frames)
{

//get the number of frames to heal
#if PRESERVE_TUNNEL_HEAL_STACKING || RETAIL_COMPATIBLE_CRC
#if RETAIL_COMPATIBLE_CRC || PRESERVE_TUNNEL_HEAL_STACKING
Real *framesForFullHeal = (Real*)frames;
#else
UnsignedInt* framesForFullHeal = (UnsignedInt*)frames;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ void PoisonedBehavior::startPoisonedEffects( const DamageInfo *damageInfo )

// We are going to take the damage dealt by the original poisoner every so often for a while.
m_poisonDamageAmount = damageInfo->out.m_actualDamageDealt;
#if !RETAIL_COMPATIBLE_CRC && !PRESERVE_NO_XP_FROM_POISON_KILLS
#if !(RETAIL_COMPATIBLE_CRC || PRESERVE_NO_XP_FROM_POISON_KILLS)
// TheSuperHackers @bugfix Stubbjax 03/09/2025 Allow poison damage to award xp to the poison source.
m_poisonSource = damageInfo->in.m_sourceID;
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ UpdateSleepTime TunnelContain::update()
if (controllingPlayer)
{
TunnelTracker *tunnelSystem = controllingPlayer->getTunnelSystem();
#if PRESERVE_TUNNEL_HEAL_STACKING || RETAIL_COMPATIBLE_CRC
#if RETAIL_COMPATIBLE_CRC || PRESERVE_TUNNEL_HEAL_STACKING
if (tunnelSystem)
{
const TunnelContainModuleData* modData = getTunnelContainModuleData();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget
}
}

#if !RETAIL_COMPATIBLE_CRC && !PRESERVE_NO_XP_FROM_OCL_KILLS
#if !(RETAIL_COMPATIBLE_CRC || PRESERVE_NO_XP_FROM_OCL_KILLS)
ObjectID sinkID = sourceObj->getExperienceTracker()->getExperienceSink();
firstObject->getExperienceTracker()->setExperienceSink(sinkID != INVALID_ID ? sinkID : sourceObj->getID());
#endif
Expand Down
Loading