IStatObj::SSubObject* FindHelperObject_Basic( const char* pHelperName, const EntityId objectId, const int slot ) { IStatObj::SSubObject* pSObjHelper = NULL; IEntity* pEntity = gEnv->pEntitySystem->GetEntity( objectId ); SEntitySlotInfo info; if ((pEntity != NULL) && pEntity->GetSlotInfo( slot, info )) { if (info.pStatObj) // TODO: this code is getting too much complicated, we should restrict how and where to place the helpers. But too late now. { IStatObj* pStatObj = info.pStatObj->GetCloneSourceObject(); // we use the clone source in case it exists. Because when it is cloned, only geometries are cloned. the helpers are NOT cloned. if (!pStatObj) pStatObj = info.pStatObj; pSObjHelper = pStatObj->FindSubObject( pHelperName ); // first try an easy look in the current object // if not success, look recursively. if (!pSObjHelper) { pSObjHelper = FindHelperObject_RecursivePart( pStatObj, pHelperName ); } } } return pSObjHelper; }
// TODO: this whole function should be removed and FindHelperObject_Basic integrated back into FindHelperObject. // It manages some undefined cases that appeared in C2, but it should not be needed with a strict definition of how the grabAndThrow helpers have to be defined in the objects IStatObj::SSubObject* FindHelperObject_Extended( const char* pHelperName, EntityId objectId, int slot ) { IStatObj::SSubObject* pSObjHelper = NULL; IEntity* pEntity = gEnv->pEntitySystem->GetEntity( objectId ); SEntitySlotInfo info; if (pEntity && pEntity->GetSlotInfo( slot, info )) { if (info.pStatObj) { IStatObj* pStatObj = info.pStatObj->GetCloneSourceObject(); // we use the clone source in case it exists. Because when it is cloned, only geometries are cloned. the helpers are NOT cloned. if (!pStatObj) pStatObj = info.pStatObj; // special case: when the pStatObj is the root, we look for the first helper that does not have a hidden parent, whatever is its name as long as it includes pHelperName // because: it can be child of a visible geometry (usually "main"...) even when that geometry is not the root if (!pSObjHelper && !pStatObj->GetParentObject()) { const int subObjectCount = pStatObj->GetSubObjectCount(); for (int sid = 0; sid < subObjectCount; ++sid) { IStatObj::SSubObject* pLocSObjHelper = pStatObj->GetSubObject( sid ); if ( pLocSObjHelper && (pLocSObjHelper->nType==STATIC_SUB_OBJECT_DUMMY) && strstr( pLocSObjHelper->name.c_str(), pHelperName )) { pLocSObjHelper = pStatObj->GetSubObject( pLocSObjHelper->nParent ); if (pLocSObjHelper && (pLocSObjHelper->nType==STATIC_SUB_OBJECT_MESH) && !pLocSObjHelper->bHidden) { pSObjHelper = pStatObj->GetSubObject( sid ); break; } } } } // if all failed, we look from the parent, but by id // because: helpers are not necesarily a subobject of their geometry, but just a child if (!pSObjHelper && pStatObj->GetParentObject()) { IStatObj* pParent = pStatObj->GetParentObject(); IStatObj::SSubObject* pMeSubObject = pParent->FindSubObject( pStatObj->GetGeoName() ); if (pMeSubObject) { const int subObjectCount = pParent->GetSubObjectCount(); for (int sid=0; sid < subObjectCount; ++sid) { IStatObj::SSubObject* pLocSObjHelper = pParent->GetSubObject( sid ); if ( pLocSObjHelper && (pLocSObjHelper->nType==STATIC_SUB_OBJECT_DUMMY) && (pLocSObjHelper->name==pHelperName) && (pParent->GetSubObject( pLocSObjHelper->nParent )==pMeSubObject) ) { pSObjHelper = pLocSObjHelper; break; } } } } //If STILL we don't find the object, try with composed name based on geometry name (for destroyed pieces), and look on the whole hierarchy if (!pSObjHelper) { CryFixedStringT<128> helperNameBuffer; helperNameBuffer.Format("%s_%s", pStatObj->GetGeoName(), pHelperName); pSObjHelper = pStatObj->FindSubObject( helperNameBuffer.c_str() ); if (!pSObjHelper) { IStatObj* pObj = pStatObj; while (pObj->GetParentObject()) pObj = pObj->GetParentObject(); pSObjHelper = FindHelperObject_RecursivePart( pObj, helperNameBuffer.c_str() ); } } } } return pSObjHelper; }