void CLIENTFX_INSTANCE::DeleteFX(CLinkListNode<FX_LINK> *pDelNode) { if( !pDelNode ) return; CBaseFX* pDelFX = pDelNode->m_Data.m_pFX; if(pDelFX) { // Make sure no other active FX in this instance have this pDelFX has their parent... CLinkListNode<FX_LINK> *pActiveNode = m_collActiveFX.GetHead(); while( pActiveNode ) { CBaseFX *pPossibleChildFX = pActiveNode->m_Data.m_pFX; if( pPossibleChildFX && (pPossibleChildFX->GetParent() == pDelFX->GetFXObject())) { // NULL out the parent otherwise it will reference an object that is no longer there pPossibleChildFX->SetParent( LTNULL ); } pActiveNode = pActiveNode->m_pNext; } // Give the FX a chance to clean itself up pDelFX->Term(); CClientFXDB::GetSingleton().DeleteEffect(pDelFX); } //now remove this node from our list m_collActiveFX.Remove(pDelNode); }
void CClientFXMgr::ShutdownClientFX(CLIENTFX_INSTANCE *pFxGroup) { CLinkListNode<CLIENTFX_INSTANCE *> *pActiveNode = m_collActiveGroupFX.GetHead(); //setup the callback in case any create effects as they are destroyed SetupCreateEffectCallback(); while (pActiveNode) { CLIENTFX_INSTANCE* pInst = pActiveNode->m_Data; if (pInst == pFxGroup) { // Shut it down !! pInst->m_bShutdown = true; HOBJECT hReplaceParent = NULL; //see if this effect performs a smooth shutdown, if so, we need to create a dummy //object to place everything under a dummy object if (pInst->m_bSmoothShutdown) { LTVector vPos; LTRotation rRot; if (pFxGroup->m_hParent) { m_pClientDE->GetObjectPos(pFxGroup->m_hParent, &vPos); m_pClientDE->GetObjectRotation(pFxGroup->m_hParent, &rRot); } else { vPos = pFxGroup->m_vPos; rRot = pFxGroup->m_rRot; } // Create a temporary parent object.... ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); ocs.m_ObjectType = OT_NORMAL; ocs.m_Pos = vPos; ocs.m_Rotation = rRot; ocs.m_Flags = 0; hReplaceParent = m_pClientDE->CreateObject(&ocs); pFxGroup->m_hAlternateParent = hReplaceParent; pFxGroup->m_hParent = hReplaceParent; } if (!hReplaceParent) { //we couldn't create or didn't need a replacement object, so just remove all fx pInst->m_hAlternateParent = NULL; pInst->m_hParent = NULL; pInst->RemoveAllEffects(); } else { // We have a parent to set, but in addition we need to notify all effects that //we are shutting down, and remove any effects that don't need a smooth shutdown (this //way it can be polled instantly after to determine if it is done) CLinkListNode<FX_LINK> *pActiveFxNode = pInst->m_collActiveFX.GetHead(); CLinkListNode<FX_LINK> *pNextActiveFxNode = NULL; while( pActiveFxNode ) { //cache the next in case this node is deleted pNextActiveFxNode = pActiveFxNode->m_pNext; CBaseFX *pFX = pActiveFxNode->m_Data.m_pFX; //we want to remove any inactive nodes if(!pFX->IsActive()) { pInst->DeleteFX(pActiveFxNode); } else { const FX_KEY* pKey = pActiveFxNode->m_Data.m_pRef; //reassign the parent of this object pFX->SetParent(hReplaceParent); //we have an active effect, set it to shutting down pFX->SetState(FS_SHUTTINGDOWN); //now that it is shutting down, see if it is complete if(pFX->IsFinishedShuttingDown() || !pInst->m_bSmoothShutdown || !pKey->m_bSmoothShutdown) { //we can just remove the effect pInst->DeleteFX(pActiveFxNode); } } pActiveFxNode = pNextActiveFxNode; } } break; } pActiveNode = pActiveNode->m_pNext; } }