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
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ class ContainModuleInterface
virtual const Object *friend_getRider() const = 0; ///< Damn. The draw order dependency bug for riders means that our draw module needs to cheat to get around it.
virtual Real getContainedItemsMass() const = 0;
virtual UnsignedInt getStealthUnitsContained() const = 0;
virtual UnsignedInt getHeroUnitsContained() const = 0;

virtual Bool calcBestGarrisonPosition( Coord3D *sourcePos, const Coord3D *targetPos ) = 0;
virtual Bool attemptBestFirePointPosition( Object *source, Weapon *weapon, Object *victim ) = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class OpenContain : public UpdateModule,
virtual const Object *friend_getRider() const{return NULL;} ///< Damn. The draw order dependency bug for riders means that our draw module needs to cheat to get around it.
virtual Real getContainedItemsMass() const;
virtual UnsignedInt getStealthUnitsContained() const { return m_stealthUnitsContained; }
virtual UnsignedInt getHeroUnitsContained() const { return m_heroUnitsContained; }

virtual PlayerMaskType getPlayerWhoEntered(void) const { return m_playerEnteredMask; }

Expand Down Expand Up @@ -238,6 +239,7 @@ class OpenContain : public UpdateModule,

ObjectEnterExitMap m_objectEnterExitInfo;
UnsignedInt m_stealthUnitsContained; ///< number of stealth units that can't be seen by enemy players.
UnsignedInt m_heroUnitsContained; ///< cached hero count
Int m_whichExitPath; ///< Cycles from 1 to n and is used only in modules whose data has numberOfExitPaths > 1.
UnsignedInt m_doorCloseCountdown; ///< When should I shut my door.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ OpenContain::OpenContain( Thing *thing, const ModuleData* moduleData ) : UpdateM
m_lastLoadSoundFrame = 0;
m_containListSize = 0;
m_stealthUnitsContained = 0;
m_heroUnitsContained = 0;
m_doorCloseCountdown = 0;

m_rallyPoint.zero();
Expand Down Expand Up @@ -352,6 +353,10 @@ void OpenContain::addToContainList( Object *rider )
{
m_stealthUnitsContained++;
}
if( rider->isKindOf( KINDOF_HERO ) )
{
m_heroUnitsContained++;
}
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -542,6 +547,11 @@ void OpenContain::removeFromContainViaIterator( ContainedItemsList::iterator it,
}
}
}
if( rider->isKindOf( KINDOF_HERO ) )
{
DEBUG_ASSERTCRASH( m_heroUnitsContained > 0, ("Removing hero but hero count is 0") );
Copy link

Choose a reason for hiding this comment

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

Text is not quite accurate:

"OpenContain::removeFromContainViaIterator - Removing hero but hero count is %d", m_heroUnitsContained

Could add the same assert to stealth units above.

m_heroUnitsContained--;
}


if (isEnclosingContainerFor( rider ))
Expand Down Expand Up @@ -620,7 +630,7 @@ void OpenContain::scatterToNearbyPosition(Object* rider)
}

//-------------------------------------------------------------------------------------------------
void OpenContain::onContaining( Object * /*rider*/ )
void OpenContain::onContaining( Object *rider )
{
// Play audio
if( m_loadSoundsEnabled )
Expand Down Expand Up @@ -1442,13 +1452,18 @@ void OpenContain::crc( Xfer *xfer )
// ------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
* 1: Initial version
* 2: Added m_heroUnitsContained cached hero count (bobtista) */
Copy link

Choose a reason for hiding this comment

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

TheSuperHackers @tweak Serialize hero units contained count

Do not use trailing (bobtista) because this is not part of our comment convention for authors.

Can put */ in new line.

// ------------------------------------------------------------------------------------------------
void OpenContain::xfer( Xfer *xfer )
{

// version
const XferVersion currentVersion = 1;
#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 1;
#else
XferVersion currentVersion = 2;
#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );

Expand Down Expand Up @@ -1526,6 +1541,24 @@ void OpenContain::xfer( Xfer *xfer )
// stealth units contained
xfer->xferUnsignedInt( &m_stealthUnitsContained );

// hero units contained
#if !RETAIL_COMPATIBLE_XFER_SAVE
if (version >= 2)
{
xfer->xferUnsignedInt( &m_heroUnitsContained );
}
else if (xfer->getXferMode() == XFER_LOAD)
{
m_heroUnitsContained = 0;
}
#else
// In retail compatibility mode, hero count is restored by iterating hero objects in loadPostProcess
if (xfer->getXferMode() == XFER_LOAD)
{
m_heroUnitsContained = 0;
}
#endif
Copy link

Choose a reason for hiding this comment

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

This whole block looks overengineered. Can it be simplifed to just

	if (version >= 2)
	{
		xfer->xferUnsignedInt( &m_heroUnitsContained );
	}

?


// door close countdown
xfer->xferUnsignedInt( &m_doorCloseCountdown );

Expand Down Expand Up @@ -1658,6 +1691,18 @@ void OpenContain::loadPostProcess( void )

}

#if RETAIL_COMPATIBLE_XFER_SAVE
Copy link

Choose a reason for hiding this comment

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

Use same technique as in #2024 for particle cannon to condition it.

// In retail compatibility mode, restore hero count by iterating hero objects
m_heroUnitsContained = 0;
for( ContainedItemsList::const_iterator it = m_containList.begin(); it != m_containList.end(); ++it )
{
if( (*it)->isKindOf( KINDOF_HERO ) )
{
m_heroUnitsContained++;
}
}
#endif

// sanity
DEBUG_ASSERTCRASH( m_containListSize == m_containList.size(),
("OpenContain::loadPostProcess - contain list count mismatch") );
Expand Down
16 changes: 2 additions & 14 deletions Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,25 +593,13 @@ Object::~Object()
}

//-------------------------------------------------------------------------------------------------
void localIsHero( Object *obj, void* userData )
{
Bool *hero = (Bool*)userData;

if( obj && obj->isKindOf( KINDOF_HERO ) )
{
*hero = TRUE;
}
}

//-------------------------------------------------------------------------------------------------
// TheSuperHackers @performance bobtista 13/11/2025 Use cached hero count for O(1) lookup instead of O(n) iteration.
Bool Object::isHero() const
{
ContainModuleInterface *contain = getContain();
if( contain )
{
Bool heroInside = FALSE;
contain->iterateContained( localIsHero, (void*)(&heroInside), FALSE );
if( heroInside )
if( contain->getHeroUnitsContained() > 0 )
{
return TRUE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ class ContainModuleInterface
virtual const Object *friend_getRider() const = 0; ///< Damn. The draw order dependency bug for riders means that our draw module needs to cheat to get around it.
virtual Real getContainedItemsMass() const = 0;
virtual UnsignedInt getStealthUnitsContained() const = 0;
virtual UnsignedInt getHeroUnitsContained() const = 0;

virtual Bool calcBestGarrisonPosition( Coord3D *sourcePos, const Coord3D *targetPos ) = 0;
virtual Bool attemptBestFirePointPosition( Object *source, Weapon *weapon, Object *victim ) = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class OpenContain : public UpdateModule,
virtual const Object *friend_getRider() const{return NULL;} ///< Damn. The draw order dependency bug for riders means that our draw module needs to cheat to get around it.
virtual Real getContainedItemsMass() const;
virtual UnsignedInt getStealthUnitsContained() const { return m_stealthUnitsContained; }
virtual UnsignedInt getHeroUnitsContained() const { return m_heroUnitsContained; }

virtual PlayerMaskType getPlayerWhoEntered(void) const { return m_playerEnteredMask; }

Expand Down Expand Up @@ -259,6 +260,7 @@ class OpenContain : public UpdateModule,

ObjectEnterExitMap m_objectEnterExitInfo;
UnsignedInt m_stealthUnitsContained; ///< number of stealth units that can't be seen by enemy players.
UnsignedInt m_heroUnitsContained; ///< cached hero count
Int m_whichExitPath; ///< Cycles from 1 to n and is used only in modules whose data has numberOfExitPaths > 1.
UnsignedInt m_doorCloseCountdown; ///< When should I shut my door.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ OpenContain::OpenContain( Thing *thing, const ModuleData* moduleData ) : UpdateM
m_lastLoadSoundFrame = 0;
m_containListSize = 0;
m_stealthUnitsContained = 0;
m_heroUnitsContained = 0;
m_doorCloseCountdown = 0;

m_rallyPoint.zero();
Expand Down Expand Up @@ -374,6 +375,10 @@ void OpenContain::addToContainList( Object *rider )
{
m_stealthUnitsContained++;
}
if( rider->isKindOf( KINDOF_HERO ) )
{
m_heroUnitsContained++;
}
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -660,6 +665,11 @@ void OpenContain::removeFromContainViaIterator( ContainedItemsList::iterator it,
}
}
}
if( rider->isKindOf( KINDOF_HERO ) )
{
DEBUG_ASSERTCRASH( m_heroUnitsContained > 0, ("Removing hero but hero count is 0") );
m_heroUnitsContained--;
}


if (isEnclosingContainerFor( rider ))
Expand Down Expand Up @@ -1667,13 +1677,19 @@ void OpenContain::crc( Xfer *xfer )
// ------------------------------------------------------------------------------------------------
/** Xfer method
* Version Info:
* 1: Initial version */
* 1: Initial version
* 2: Added m_passengerAllowedToFire
* 3: Added m_heroUnitsContained cached hero count (bobtista) */
// ------------------------------------------------------------------------------------------------
void OpenContain::xfer( Xfer *xfer )
{

// version
const XferVersion currentVersion = 2;
#if RETAIL_COMPATIBLE_XFER_SAVE
XferVersion currentVersion = 2;
#else
XferVersion currentVersion = 3;
#endif
XferVersion version = currentVersion;
xfer->xferVersion( &version, currentVersion );

Expand Down Expand Up @@ -1751,6 +1767,24 @@ void OpenContain::xfer( Xfer *xfer )
// stealth units contained
xfer->xferUnsignedInt( &m_stealthUnitsContained );

// hero units contained
#if !RETAIL_COMPATIBLE_XFER_SAVE
if (version >= 3)
{
xfer->xferUnsignedInt( &m_heroUnitsContained );
}
else if (xfer->getXferMode() == XFER_LOAD)
{
m_heroUnitsContained = 0;
}
#else
// In retail compatibility mode, hero count is restored by iterating hero objects in loadPostProcess
if (xfer->getXferMode() == XFER_LOAD)
{
m_heroUnitsContained = 0;
}
#endif

// door close countdown
xfer->xferUnsignedInt( &m_doorCloseCountdown );

Expand Down Expand Up @@ -1890,6 +1924,18 @@ void OpenContain::loadPostProcess( void )

}

#if RETAIL_COMPATIBLE_XFER_SAVE
// In retail compatibility mode, restore hero count by iterating hero objects
m_heroUnitsContained = 0;
for( ContainedItemsList::const_iterator it = m_containList.begin(); it != m_containList.end(); ++it )
{
if( (*it)->isKindOf( KINDOF_HERO ) )
{
m_heroUnitsContained++;
}
}
#endif

// sanity
DEBUG_ASSERTCRASH( m_containListSize == m_containList.size(),
("OpenContain::loadPostProcess - contain list count mismatch") );
Expand Down
15 changes: 2 additions & 13 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2042,25 +2042,14 @@ Bool Object::isNonFactionStructure(void) const
return isStructure() && !isFactionStructure();
}

void localIsHero( Object *obj, void* userData )
{
Bool *hero = (Bool*)userData;

if( obj && obj->isKindOf( KINDOF_HERO ) )
{
*hero = TRUE;
}
}

//-------------------------------------------------------------------------------------------------
// TheSuperHackers @performance bobtista 13/11/2025 Use cached hero count for O(1) lookup instead of O(n) iteration.
Bool Object::isHero(void) const
{
ContainModuleInterface *contain = getContain();
if( contain )
{
Bool heroInside = FALSE;
contain->iterateContained( localIsHero, (void*)(&heroInside), FALSE );
if( heroInside )
if( contain->getHeroUnitsContained() > 0 )
{
return TRUE;
}
Expand Down
Loading