Skip to content
Merged
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
4 changes: 4 additions & 0 deletions Core/GameEngine/Include/Common/GameDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
// 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_BUG
#define RETAIL_COMPATIBLE_BUG (1) // Retain bugs 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
Expand Down
12 changes: 12 additions & 0 deletions Generals/Code/GameEngine/Source/GameClient/SelectionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,18 @@ Bool addDrawableToList( Drawable *draw, void *userData )
if (!pds->drawableListToFill)
return FALSE;

#if !RTS_GENERALS || !RETAIL_COMPATIBLE_BUG
// TheSuperHackers @info
// In retail, drag-selecting allows the player to select stealthed objects and objects through the
// fog. Some players exploit this bug to determine where an opponent's units are and consider this
// an important feature and an advanced skill to pull off, so we must leave the exploit.
if (draw->getFullyObscuredByShroud())
return FALSE;

if (draw->isDrawableEffectivelyHidden())
return FALSE;
#endif

if (!draw->getTemplate()->isAnyKindOf(pds->kindofsToMatch))
return FALSE;

Expand Down
39 changes: 17 additions & 22 deletions GeneralsMD/Code/GameEngine/Source/GameClient/SelectionInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,14 @@ Bool addDrawableToList( Drawable *draw, void *userData )
if (!pds->drawableListToFill)
return FALSE;

#if !RTS_GENERALS || !RETAIL_COMPATIBLE_BUG
if (draw->getFullyObscuredByShroud())
return FALSE;

if (draw->isDrawableEffectivelyHidden())
return FALSE;
#endif

if (!draw->getTemplate()->isAnyKindOf(pds->kindofsToMatch))
return FALSE;

Expand All @@ -368,28 +376,15 @@ Bool addDrawableToList( Drawable *draw, void *userData )
return FALSE;
}

//Kris: Aug 9, 2003!!! Wow, this bug has been around a LONG time!!
//Basically, it was possible to drag select a single enemy/neutral unit even if you couldn't see it
//including stealthed units.
const Object *obj = draw->getObject();
if( obj )
{
const Player *player = ThePlayerList->getLocalPlayer();
Relationship rel = player->getRelationship( obj->getTeam() );
if( rel == NEUTRAL || rel == ENEMIES )
{
if( obj->getShroudedStatus( player->getPlayerIndex() ) >= OBJECTSHROUD_FOGGED )
{
return FALSE;
}

//If stealthed, no way!
if( obj->testStatus( OBJECT_STATUS_STEALTHED ) && !obj->testStatus( OBJECT_STATUS_DETECTED ) )
{
return FALSE;
Copy link

Choose a reason for hiding this comment

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

With this condition gone, does it mean that we can now select enemy stealth units, while they are stealth? Or is that covered by isDrawableEffectivelyHidden ?

If so, then this fix needs to be different, for example allowing the observer to skip these tests.

Copy link
Author

Choose a reason for hiding this comment

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

Absolutely not, or this change would be a regression. The original stealth selection condition is now covered by isDrawableEffectivelyHidden. The benefit to this is that as observers can see stealthed units and beacons, isDrawableEffectivelyHidden returns false for them (unless the units are in a closed container).

NO_STEALTH.mp4
OBSERVE_STEALTH.mp4

}
}
}
#if !RTS_GENERALS && RETAIL_COMPATIBLE_BUG
// TheSuperHackers @info
// In retail, hidden objects such as passengers are included here when drag-selected, which causes
// enemy selection logic to exit early (only 1 enemy unit can be selected at a time). Some players
// exploit this bug to determine if a transport contains passengers and consider this an important
// feature and an advanced skill to pull off, so we must leave the exploit.
if (draw->getObject() && draw->getObject()->getContain() && draw->getObject()->getContain()->getContainCount() > 0)
pds->drawableListToFill->push_back(draw); // Just add the unit twice to prevent enemy selections
#endif

pds->drawableListToFill->push_back(draw);
return TRUE;
Expand Down
Loading