diff --git a/Generals/Code/GameEngine/Include/GameLogic/Object.h b/Generals/Code/GameEngine/Include/GameLogic/Object.h index 9252f81886..d26ffd6edf 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Object.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Object.h @@ -417,7 +417,8 @@ class Object : public Thing, public Snapshot void onRemovedFrom( Object *removedFrom ); Int getTransportSlotCount() const; void friend_setContainedBy( Object *containedBy ) { m_containedBy = containedBy; } - Object* getEnclosingContainedBy(); ///< Find the first enclosing container in the containment chain. + const Object* getEnclosingContainedBy() const; ///< Find the first enclosing container in the containment chain. + const Object* getOuterObject() const; ///< Get the top-level object // Special Powers ------------------------------------------------------------------------------- SpecialPowerModuleInterface *getSpecialPowerModule( const SpecialPowerTemplate *specialPowerTemplate ) const; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index d6fa162257..870d5fa384 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -667,9 +667,9 @@ Int Object::getTransportSlotCount() const return count; } -Object* Object::getEnclosingContainedBy() +const Object* Object::getEnclosingContainedBy() const { - for (Object* child = this, *container = getContainedBy(); container; child = container, container = container->getContainedBy()) + for (const Object* child = this, *container = getContainedBy(); container; child = container, container = container->getContainedBy()) { ContainModuleInterface* containModule = container->getContain(); if (containModule && containModule->isEnclosingContainerFor(child)) @@ -679,6 +679,14 @@ Object* Object::getEnclosingContainedBy() return NULL; } +const Object* Object::getOuterObject() const +{ + if (const Object* enclosing = getEnclosingContainedBy()) + return enclosing; + + return this; +} + //------------------------------------------------------------------------------------------------- /** Run from GameLogic::destroyObject */ //------------------------------------------------------------------------------------------------- @@ -2821,10 +2829,13 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne break; } + Drawable* outerDrawable = getOuterObject()->getDrawable(); + Bool doAnimation = provideFeedback && newLevel > oldLevel && !isKindOf(KINDOF_IGNORED_IN_GUI) - && getDrawable()->isVisible(); + && outerDrawable + && outerDrawable->isVisible(); if( doAnimation && TheGameLogic->getDrawIconUI() ) { diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 65439088f0..a104f9d9da 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -886,7 +886,10 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate // TheSuperHackers @todo: Remove hardcoded KINDOF_MINE check and apply PlayFXWhenStealthed = Yes to the mine weapons instead. - if(!sourceObj->getDrawable()->isVisible() // if user watching cannot see us + Drawable* outerDrawable = sourceObj->getOuterObject()->getDrawable(); + const Bool isVisible = outerDrawable && outerDrawable->isVisible(); + + if (!isVisible // if user watching cannot see us && !sourceObj->isKindOf(KINDOF_MINE) // and not a mine (which always do the FX, even if hidden)... && !isPlayFXWhenStealthed() // and not a weapon marked to playwhenstealthed ) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h index 9a37ddeb1e..cbf10e4bfd 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h @@ -442,7 +442,8 @@ class Object : public Thing, public Snapshot void onRemovedFrom( Object *removedFrom ); Int getTransportSlotCount() const; void friend_setContainedBy( Object *containedBy ) { m_containedBy = containedBy; } - Object* getEnclosingContainedBy(); ///< Find the first enclosing container in the containment chain. + const Object* getEnclosingContainedBy() const; ///< Find the first enclosing container in the containment chain. + const Object* getOuterObject() const; ///< Get the top-level object // Special Powers ------------------------------------------------------------------------------- SpecialPowerModuleInterface *getSpecialPowerModule( const SpecialPowerTemplate *specialPowerTemplate ) const; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index dad917d20a..48a7f739b3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -731,9 +731,9 @@ Int Object::getTransportSlotCount() const return count; } -Object* Object::getEnclosingContainedBy() +const Object* Object::getEnclosingContainedBy() const { - for (Object* child = this, *container = getContainedBy(); container; child = container, container = container->getContainedBy()) + for (const Object* child = this, *container = getContainedBy(); container; child = container, container = container->getContainedBy()) { ContainModuleInterface* containModule = container->getContain(); if (containModule && containModule->isEnclosingContainerFor(child)) @@ -743,6 +743,14 @@ Object* Object::getEnclosingContainedBy() return NULL; } +const Object* Object::getOuterObject() const +{ + if (const Object* enclosing = getEnclosingContainedBy()) + return enclosing; + + return this; +} + //------------------------------------------------------------------------------------------------- /** Run from GameLogic::destroyObject */ //------------------------------------------------------------------------------------------------- @@ -3136,10 +3144,13 @@ void Object::onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel ne break; } + Drawable* outerDrawable = getOuterObject()->getDrawable(); + Bool doAnimation = provideFeedback && newLevel > oldLevel && !isKindOf(KINDOF_IGNORED_IN_GUI) - && getDrawable()->isVisible(); + && outerDrawable + && outerDrawable->isVisible(); if( doAnimation && TheGameLogic->getDrawIconUI() ) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/HackInternetAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/HackInternetAIUpdate.cpp index 1567f4e887..b395edd50e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/HackInternetAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/HackInternetAIUpdate.cpp @@ -543,7 +543,8 @@ StateReturnType HackInternetState::update() //Grant the unit some experience for a successful hack. xp->addExperiencePoints( ai->getXpPerCashUpdate() ); - if (owner->getDrawable()->isVisible()) + Drawable* outerDrawable = owner->getOuterObject()->getDrawable(); + if (outerDrawable && outerDrawable->isVisible()) { // OY LOOK! I AM USING LOCAL PLAYER. Do not put anything other than TheInGameUI->addFloatingText in the block this controls!!! //Display cash income floating over the hacker. diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp index 28db02d0ee..dbda4390ce 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AutoDepositUpdate.cpp @@ -173,7 +173,8 @@ UpdateSleepTime AutoDepositUpdate::update( void ) getObject()->getControllingPlayer()->getScoreKeeper()->addMoneyEarned( modData->m_depositAmount); } - if (moneyAmount > 0 && getObject()->getDrawable()->isVisible()) + Drawable* outerDrawable = getObject()->getOuterObject()->getDrawable(); + if (moneyAmount > 0 && outerDrawable && outerDrawable->isVisible()) { const Object *owner = getObject(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyCenterDockUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyCenterDockUpdate.cpp index c1db777c70..407b32a0dc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyCenterDockUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyCenterDockUpdate.cpp @@ -129,7 +129,8 @@ Bool SupplyCenterDockUpdate::action( Object* docker, Object *drone ) } } - if (value > 0 && getObject()->getDrawable()->isVisible()) + Drawable* outerDrawable = getObject()->getOuterObject()->getDrawable(); + if (value > 0 && outerDrawable && outerDrawable->isVisible()) { // OY LOOK! I AM USING LOCAL PLAYER. Do not put anything other than TheInGameUI->addFloatingText in the block this controls!!! // Setup info for adding a floating text diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index 5c761a654c..996a06cb1e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -917,7 +917,10 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate // TheSuperHackers @todo: Remove hardcoded KINDOF_MINE check and apply PlayFXWhenStealthed = Yes to the mine weapons instead. - if(!sourceObj->getDrawable()->isVisible() // if user watching cannot see us + Drawable* outerDrawable = sourceObj->getOuterObject()->getDrawable(); + const Bool isVisible = outerDrawable && outerDrawable->isVisible(); + + if (!isVisible // if user watching cannot see us && !sourceObj->isKindOf(KINDOF_MINE) // and not a mine (which always do the FX, even if hidden)... && !isPlayFXWhenStealthed() // and not a weapon marked to playwhenstealthed )