Skip to content

Commit 123492c

Browse files
authored
bugfix(object): Fix visibility conditions for client-side effects (#1964)
1 parent 844c436 commit 123492c

File tree

9 files changed

+61
-24
lines changed

9 files changed

+61
-24
lines changed

Generals/Code/GameEngine/Include/GameLogic/Object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ class Object : public Thing, public Snapshot
237237
void setCustomIndicatorColor(Color c);
238238
void removeCustomIndicatorColor();
239239

240+
Bool isLogicallyVisible() const; ///< Returns whether the object is logically visible to the player, irrespective of shroud.
241+
240242
Bool isLocallyControlled() const;
241243
Bool isLocallyViewed() const;
242244
Bool isNeutralControlled() const;

Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,31 @@ Color Object::getNightIndicatorColor() const
15411541
}
15421542
}
15431543

1544+
//=============================================================================
1545+
// Object::isLogicallyVisible
1546+
//=============================================================================
1547+
Bool Object::isLogicallyVisible() const
1548+
{
1549+
const Object* obj = getOuterObject();
1550+
1551+
// Disguisers are always visible to all players, irrespective of any stealth
1552+
// status. We thus need to check the type rather than the status as the
1553+
// disguise status is absent during the disguise transition phase.
1554+
if (obj->isKindOf(KINDOF_DISGUISER))
1555+
return true;
1556+
1557+
if (obj->testStatus(OBJECT_STATUS_STEALTHED) && !obj->testStatus(OBJECT_STATUS_DETECTED))
1558+
{
1559+
const Player* player = rts::getObservedOrLocalPlayer();
1560+
const Relationship relationship = player->getRelationship(getTeam());
1561+
1562+
if (player->isPlayerActive() && relationship != ALLIES)
1563+
return false;
1564+
}
1565+
1566+
return true;
1567+
}
1568+
15441569
//=============================================================================
15451570
// Object::isLocallyControlled
15461571
//=============================================================================
@@ -2835,13 +2860,10 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne
28352860
break;
28362861
}
28372862

2838-
Drawable* outerDrawable = getOuterObject()->getDrawable();
2839-
28402863
Bool doAnimation = provideFeedback
28412864
&& newLevel > oldLevel
28422865
&& !isKindOf(KINDOF_IGNORED_IN_GUI)
2843-
&& outerDrawable
2844-
&& outerDrawable->isVisible();
2866+
&& isLogicallyVisible();
28452867

28462868
if( doAnimation && TheGameLogic->getDrawIconUI() )
28472869
{

Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -886,11 +886,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate
886886

887887
// TheSuperHackers @todo: Remove hardcoded KINDOF_MINE check and apply PlayFXWhenStealthed = Yes to the mine weapons instead.
888888

889-
Drawable* outerDrawable = sourceObj->getOuterObject()->getDrawable();
890-
const Bool isVisible = outerDrawable && outerDrawable->isVisible();
891-
892-
if (!isVisible // if user watching cannot see us
893-
&& sourceObj->testStatus(OBJECT_STATUS_STEALTHED) // if unit is stealthed (like a Pathfinder)
889+
if (!sourceObj->isLogicallyVisible() // if user watching cannot see us
894890
&& !sourceObj->isKindOf(KINDOF_MINE) // and not a mine (which always do the FX, even if hidden)...
895891
&& !isPlayFXWhenStealthed() // and not a weapon marked to playwhenstealthed
896892
)

GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ class Object : public Thing, public Snapshot
253253
void setCustomIndicatorColor(Color c);
254254
void removeCustomIndicatorColor();
255255

256+
Bool isLogicallyVisible() const; ///< Returns whether the object is logically visible to the player, irrespective of shroud.
257+
256258
Bool isLocallyControlled() const;
257259
Bool isLocallyViewed() const;
258260
Bool isNeutralControlled() const;

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,31 @@ Color Object::getNightIndicatorColor() const
16961696
}
16971697
}
16981698

1699+
//=============================================================================
1700+
// Object::isLogicallyVisible
1701+
//=============================================================================
1702+
Bool Object::isLogicallyVisible() const
1703+
{
1704+
const Object* obj = getOuterObject();
1705+
1706+
// Disguisers are always visible to all players, irrespective of any stealth
1707+
// status. We thus need to check the type rather than the status as the
1708+
// disguise status is absent during the disguise transition phase.
1709+
if (obj->isKindOf(KINDOF_DISGUISER))
1710+
return true;
1711+
1712+
if (obj->testStatus(OBJECT_STATUS_STEALTHED) && !obj->testStatus(OBJECT_STATUS_DETECTED))
1713+
{
1714+
const Player* player = rts::getObservedOrLocalPlayer();
1715+
const Relationship relationship = player->getRelationship(getTeam());
1716+
1717+
if (player->isPlayerActive() && relationship != ALLIES)
1718+
return false;
1719+
}
1720+
1721+
return true;
1722+
}
1723+
16991724
//=============================================================================
17001725
// Object::isLocallyControlled
17011726
//=============================================================================
@@ -3150,13 +3175,10 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne
31503175
break;
31513176
}
31523177

3153-
Drawable* outerDrawable = getOuterObject()->getDrawable();
3154-
31553178
Bool doAnimation = provideFeedback
31563179
&& newLevel > oldLevel
31573180
&& !isKindOf(KINDOF_IGNORED_IN_GUI)
3158-
&& outerDrawable
3159-
&& outerDrawable->isVisible();
3181+
&& isLogicallyVisible();
31603182

31613183
if( doAnimation && TheGameLogic->getDrawIconUI() )
31623184
{

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/HackInternetAIUpdate.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,8 +543,7 @@ StateReturnType HackInternetState::update()
543543
//Grant the unit some experience for a successful hack.
544544
xp->addExperiencePoints( ai->getXpPerCashUpdate() );
545545

546-
Drawable* outerDrawable = owner->getOuterObject()->getDrawable();
547-
if (outerDrawable && outerDrawable->isVisible())
546+
if (owner->isLogicallyVisible())
548547
{
549548
// OY LOOK! I AM USING LOCAL PLAYER. Do not put anything other than TheInGameUI->addFloatingText in the block this controls!!!
550549
//Display cash income floating over the hacker.

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,7 @@ UpdateSleepTime AutoDepositUpdate::update( void )
172172
getObject()->getControllingPlayer()->getScoreKeeper()->addMoneyEarned( modData->m_depositAmount);
173173
}
174174

175-
Drawable* outerDrawable = getObject()->getOuterObject()->getDrawable();
176-
if (moneyAmount > 0 && outerDrawable && outerDrawable->isVisible())
175+
if (moneyAmount > 0 && getObject()->isLogicallyVisible())
177176
{
178177

179178
const Object *owner = getObject();

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyCenterDockUpdate.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,7 @@ Bool SupplyCenterDockUpdate::action( Object* docker, Object *drone )
129129
}
130130
}
131131

132-
Drawable* outerDrawable = getObject()->getOuterObject()->getDrawable();
133-
if (value > 0 && outerDrawable && outerDrawable->isVisible())
132+
if (value > 0 && getObject()->isLogicallyVisible())
134133
{
135134
// OY LOOK! I AM USING LOCAL PLAYER. Do not put anything other than TheInGameUI->addFloatingText in the block this controls!!!
136135
// Setup info for adding a floating text

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -917,11 +917,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate
917917

918918
// TheSuperHackers @todo: Remove hardcoded KINDOF_MINE check and apply PlayFXWhenStealthed = Yes to the mine weapons instead.
919919

920-
Drawable* outerDrawable = sourceObj->getOuterObject()->getDrawable();
921-
const Bool isVisible = outerDrawable && outerDrawable->isVisible();
922-
923-
if (!isVisible // if user watching cannot see us
924-
&& sourceObj->testStatus(OBJECT_STATUS_STEALTHED) // if unit is stealthed (like a Pathfinder)
920+
if (!sourceObj->isLogicallyVisible() // if user watching cannot see us
925921
&& !sourceObj->isKindOf(KINDOF_MINE) // and not a mine (which always do the FX, even if hidden)...
926922
&& !isPlayFXWhenStealthed() // and not a weapon marked to playwhenstealthed
927923
)

0 commit comments

Comments
 (0)