void Alarm::CreateRegionList(HSTRING& hstrRegions, AIREGION_LIST* pList) { // Create a list of regions. // Named object may be a region, a list of regions separated by semicolons. if( hstrRegions ) { char szRegions[REGION_STRING_LEN + 1]; const char* pszRegions = g_pLTServer->GetStringData( hstrRegions ); AIASSERT( strlen( pszRegions ) <= REGION_STRING_LEN, m_hObject, "Alarm::CreateRegionList: RegionList is longer than 256 chars." ); strncpy( szRegions, pszRegions, REGION_STRING_LEN ); char* tok = strtok( szRegions, "; " ); while( tok ) { HOBJECT hObject; if( ( LT_OK == FindNamedObject( tok, hObject ) ) && ( IsAIRegion( hObject ) ) ) { pList->push_back( hObject ); } else { char szError[128]; sprintf( szError, "Alarm::CreateRegionList: '%s' is not a region.", tok ); AIASSERT( 0, m_hObject, szError ); } tok = strtok( LTNULL, "; " ); } } FREE_HSTRING( hstrRegions ); }
void CNamedObjectList::InitNamedObjectList( HOBJECT hOwner ) { m_hObject = hOwner; // Reserve space for handles. m_lstObjectHandles.reserve( m_lstObjectNames.size() ); // Find named objects. HOBJECT hObject = NULL; StringArray::iterator str_it; for ( str_it = m_lstObjectNames.begin(); str_it != m_lstObjectNames.end(); ++str_it ) { if( LT_OK != FindNamedObject( str_it->c_str(), hObject, false ) ) { LTASSERT_PARAM1( 0, "CNamedObjectList::InitNamedObjectList: Cannot find named object \"%s\"", str_it->c_str() ); hObject = NULL; } // Add handle to the list. m_lstObjectHandles.push_back( hObject ); } }
void CAIHelicopterStateAttack::HandleNameValuePair(char *szName, char *szValue) { CAIHelicopterState::HandleNameValuePair(szName, szValue); if ( !_stricmp(szName, "FIRE") ) { if ( !_stricmp(szValue, "FULL") ) { m_pStrategyShoot->SetFire(CAnimatorAIVehicle::eFireFull); } else if ( !_stricmp(szValue, "FIRE1") ) { m_pStrategyShoot->SetFire(CAnimatorAIVehicle::eFire1); } else if ( !_stricmp(szValue, "FIRE2") ) { m_pStrategyShoot->SetFire(CAnimatorAIVehicle::eFire2); } else if ( !_stricmp(szValue, "FIRE3") ) { m_pStrategyShoot->SetFire(CAnimatorAIVehicle::eFire3); } else if ( !_stricmp(szValue, "FIRE4") ) { m_pStrategyShoot->SetFire(CAnimatorAIVehicle::eFire4); } else { g_pLTServer->CPrint("CAIHelicopterStateAttack - FIRE=%s is not a valid fire type", szValue); } } else if ( !_stricmp(szName, "TARGET") ) { GetAI()->Unlink(m_hTarget); m_hTarget = LTNULL; if ( LT_OK == FindNamedObject(szValue, m_hTarget) ) { if ( IsKindOf(m_hTarget, "CCharacter") ) { GetAI()->Link(m_hTarget); } else { g_pLTServer->CPrint("ATTACK TARGET=%s -- this object is not a CCharacter!", szValue); m_hTarget = LTNULL; } } else { g_pLTServer->CPrint("ATTACK TARGET=%s -- this object does not exist!", szName); } } }
LTBOOL CAIGoalAbstractTargeted::HandleNameValuePair(const char *szName, const char *szValue) { ASSERT(szName && szValue); if ( !_stricmp(szName, "TARGET") ) { HOBJECT hObj = m_hTarget; FindNamedObject(szValue, hObj); m_hTarget = hObj; return LTTRUE; } return LTFALSE; }
void Camera::HandleMoveToMsg( HOBJECT hSender, const CParsedMsg &crParsedMsg ) { HOBJECT hObject; if( LT_OK == FindNamedObject( crParsedMsg.GetArg(1), hObject )) { if( !IsKindOf( hObject, "CameraPoint" )) return; // Just place the camera at the Point's position and rotation... LTRigidTransform tTrans; g_pLTServer->GetObjectTransform(hObject, &tTrans); g_pLTServer->SetObjectTransform(m_hObject, tTrans); } }
void AICmdTalk::Verify() { super::Verify(); HOBJECT hObject; if ( !!m_hstrFace && LT_OK != FindNamedObject(g_pLTServer->GetStringData(m_hstrFace), hObject) ) { Warn("AICmd \"%s\" - Could not find face \"%s\"", ::ToString(m_hstrName), ::ToString(m_hstrFace)); } if ( m_fFaceTime < 0.0f ) { Warn("AICmd \"%s\" - FaceTime is less than 0.0", ::ToString(m_hstrName)); } }
void AICmdCheckBody::Verify() { super::Verify(); if ( !!m_hstrBody ) { HOBJECT hObject; if ( LT_OK != FindNamedObject(g_pLTServer->GetStringData(m_hstrBody), hObject) ) { Warn("AICmd \"%s\" - Could not find body \"%s\"", ::ToString(m_hstrName), ::ToString(m_hstrBody)); } } else { Warn("AICmd \"%s\" - No body specified", ::ToString(m_hstrName)); } }
void AICmdAttackProp::Verify() { super::Verify(); if ( !!m_hstrProp ) { HOBJECT hObject; if ( LT_OK != FindNamedObject(g_pLTServer->GetStringData(m_hstrProp), hObject) ) { Warn("AICmd \"%s\" - Could not find prop \"%s\"", ::ToString(m_hstrName), ::ToString(m_hstrProp)); } } else { Warn("AICmd \"%s\" - No prop specified", ::ToString(m_hstrName)); } }
void AICmdFlee::Verify() { super::Verify(); if ( !!m_hstrDanger ) { HOBJECT hObject; if ( LT_OK != FindNamedObject(g_pLTServer->GetStringData(m_hstrDanger), hObject) ) { Warn("AICmd \"%s\" - Could not find danger \"%s\"", ::ToString(m_hstrName), ::ToString(m_hstrDanger)); } } else { Warn("AICmd \"%s\" - No danger specified", ::ToString(m_hstrName)); } }
void CAIGoalAttackProp::SetStateAttack() { m_pAI->SetCurrentWeapon( m_eWeaponType ); if( m_pAI->GetState()->GetStateType() != kState_HumanAttackProp ) { m_pAI->SetState( kState_HumanAttackProp ); // Set object to attack. HOBJECT hObject; AINode* pNode = (AINode*)g_pLTServer->HandleToObject(m_hNode); CAIHumanStateAttackProp* pStateAttackProp = (CAIHumanStateAttackProp*)(m_pAI->GetState()); if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) ) { pStateAttackProp->SetProp(hObject); } } }
AINode* CAIGoalAttackProp::HandleGoalAttractors() { // Check if already attacking a prop. if( m_pAI->GetState()->GetStateType() != kState_HumanAttackProp ) { CAIHuman* pAIHuman = (CAIHuman*)m_pAI; if( pAIHuman->HasHolsterString() || pAIHuman->GetPrimaryWeapon()) { AIGBM_GoalTemplate* pTemplate = g_pAIGoalButeMgr->GetTemplate( GetGoalType() ); AIASSERT(pTemplate->cAttractors > 0, m_pAI->m_hObject, "CAIGoalAbstract::HandleGoalAttractors: Goal has no attractors."); // Check if attractors are triggering activateability. AINode* pNode; for(uint32 iAttractor=0; iAttractor < pTemplate->cAttractors; ++iAttractor) { pNode = g_pAINodeMgr->FindNearestNodeInRadius(m_pAI, pTemplate->aAttractors[iAttractor], m_pAI->GetPosition(), pTemplate->fAttractorDistSqr * m_fBaseImportance, LTTRUE); if(pNode != LTNULL) { HOBJECT hObject; if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) ) { Prop* pProp = (Prop*)g_pLTServer->HandleToObject(hObject); if(pProp->GetState() != kState_PropDestroyed) { AIASSERT(pNode->GetType() == kNode_UseObject, m_pAI->m_hObject, "CAIGoalAttackProp::HandleGoalAttractors: AINode is not of type UseObject."); m_hNode = pNode->m_hObject; SetCurToBaseImportance(); return pNode; } } // Disable node if prop has been destroyed. pNode->Disable(); } } } m_hNode = LTNULL; } return LTNULL; }
void GameBase::HandleCopyXFormMsg( HOBJECT hSender, const CParsedMsg &crParsedMsg ) { // Make sure we have all the arguments. if( crParsedMsg.GetArgCount( ) < 2 ) return; // Get the target object. HOBJECT hTarget = NULL; FindNamedObject( crParsedMsg.GetArg( 1 ), hTarget, false ); if( !hTarget ) return; // Set the position for this object. LTVector vPos; g_pLTServer->GetObjectPos( hTarget, &vPos ); g_pLTServer->SetObjectPos( m_hObject, vPos ); // Set the rotation for this object. LTRotation rRot; g_pLTServer->GetObjectRotation( hTarget, &rRot ); g_pLTServer->SetObjectRotation( m_hObject, rRot ); }
void AICmdInvestigate::Verify() { super::Verify(); if ( LT_INSIDE != g_pLTServer->Common()->GetPointStatus(&m_vPosition) ) { Warn("AICmd \"%s\" - Position %s is not in the world", ::ToString(m_hstrName), ::ToString(m_vPosition)); } if ( !!m_hstrEnemy ) { HOBJECT hObject; if ( LT_OK != FindNamedObject(g_pLTServer->GetStringData(m_hstrEnemy), hObject) ) { Warn("AICmd \"%s\" - Could not find enemy \"%s\"", ::ToString(m_hstrName), ::ToString(m_hstrEnemy)); } } else { Warn("AICmd \"%s\" - No enemy specified", ::ToString(m_hstrName)); } }
void AINodeValidatorBoundaryRadius::InitNodeValidator( AINode* pNode ) { // Sanity check. if( !pNode ) { return; } // Find AIRegion by name, and record it's AIRegionID. if( !m_strBoundaryAIRegion.empty() ) { ILTBaseClass *pObject = NULL; if( LT_OK == FindNamedObject( m_strBoundaryAIRegion.c_str(), pObject ) ) { AIRegion* pAIRegion = (AIRegion*)pObject; if( pAIRegion ) { m_eBoundaryAIRegion = pAIRegion->GetAIRegionID(); } } } }
Maybe<bool> Compatibility::OnUIAMessage(WPARAM aWParam, LPARAM aLParam) { auto clearUiaRemotePid = MakeScopeExit([]() { sUiaRemotePid = Nothing(); }); Telemetry::AutoTimer<Telemetry::A11Y_UIA_DETECTION_TIMING_MS> timer; // UIA creates a section containing the substring "HOOK_SHMEM_" NS_NAMED_LITERAL_STRING(kStrHookShmem, "HOOK_SHMEM_"); // The section name always ends with this suffix, which is derived from the // current thread id and the UIA message's WPARAM and LPARAM. nsAutoString partialSectionSuffix; partialSectionSuffix.AppendPrintf("_%08x_%08x_%08x", ::GetCurrentThreadId(), static_cast<DWORD>(aLParam), aWParam); // Find any named Section that matches the naming convention of the UIA shared // memory. nsAutoHandle section; auto comparator = [&](const nsDependentSubstring& aName, const nsDependentSubstring& aType) -> bool { if (aType.Equals(NS_LITERAL_STRING("Section")) && FindInReadable(kStrHookShmem, aName) && StringEndsWith(aName, partialSectionSuffix)) { section.own(::OpenFileMapping(GENERIC_READ, FALSE, PromiseFlatString(aName).get())); return false; } return true; }; if (!FindNamedObject(comparator) || !section) { return Nothing(); } NTSTATUS ntStatus; // First we must query for a list of all the open handles in the system. UniquePtr<char[]> handleInfoBuf; ULONG handleInfoBufLen = sizeof(SYSTEM_HANDLE_INFORMATION_EX) + 1024 * sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX); // We must query for handle information in a loop, since we are effectively // asking the kernel to take a snapshot of all the handles on the system; // the size of the required buffer may fluctuate between successive calls. while (true) { // These allocations can be hundreds of megabytes on some computers, so // we should use fallible new here. handleInfoBuf = MakeUniqueFallible<char[]>(handleInfoBufLen); if (!handleInfoBuf) { return Nothing(); } ntStatus = ::NtQuerySystemInformation( (SYSTEM_INFORMATION_CLASS) SystemExtendedHandleInformation, handleInfoBuf.get(), handleInfoBufLen, &handleInfoBufLen); if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { continue; } if (!NT_SUCCESS(ntStatus)) { return Nothing(); } break; } const DWORD ourPid = ::GetCurrentProcessId(); Maybe<PVOID> kernelObject; static Maybe<USHORT> sectionObjTypeIndex; nsTHashtable<nsUint32HashKey> nonSectionObjTypes; nsDataHashtable<nsVoidPtrHashKey, DWORD> objMap; auto handleInfo = reinterpret_cast<SYSTEM_HANDLE_INFORMATION_EX*>(handleInfoBuf.get()); for (ULONG index = 0; index < handleInfo->mHandleCount; ++index) { SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX& curHandle = handleInfo->mHandles[index]; HANDLE handle = reinterpret_cast<HANDLE>(curHandle.mHandle); // The mapping of the curHandle.mObjectTypeIndex field depends on the // underlying OS kernel. As we scan through the handle list, we record the // type indices such that we may use those values to skip over handles that // refer to non-section objects. if (sectionObjTypeIndex) { // If we know the type index for Sections, that's the fastest check... if (sectionObjTypeIndex.value() != curHandle.mObjectTypeIndex) { // Not a section continue; } } else if (nonSectionObjTypes.Contains(static_cast<uint32_t>( curHandle.mObjectTypeIndex))) { // Otherwise we check whether or not the object type is definitely _not_ // a Section... continue; } else if (ourPid == curHandle.mPid) { // Otherwise we need to issue some system calls to find out the object // type corresponding to the current handle's type index. ULONG objTypeBufLen; ntStatus = ::NtQueryObject(handle, ObjectTypeInformation, nullptr, 0, &objTypeBufLen); if (ntStatus != STATUS_INFO_LENGTH_MISMATCH) { continue; } auto objTypeBuf = MakeUnique<char[]>(objTypeBufLen); ntStatus = ::NtQueryObject(handle, ObjectTypeInformation, objTypeBuf.get(), objTypeBufLen, &objTypeBufLen); if (!NT_SUCCESS(ntStatus)) { continue; } auto objType = reinterpret_cast<PUBLIC_OBJECT_TYPE_INFORMATION*>(objTypeBuf.get()); // Now we check whether the object's type name matches "Section" nsDependentSubstring objTypeName(objType->TypeName.Buffer, objType->TypeName.Length / sizeof(wchar_t)); if (!objTypeName.Equals(NS_LITERAL_STRING("Section"))) { nonSectionObjTypes.PutEntry(static_cast<uint32_t>(curHandle.mObjectTypeIndex)); continue; } sectionObjTypeIndex = Some(curHandle.mObjectTypeIndex); } // At this point we know that curHandle references a Section object. // Now we can do some actual tests on it. if (ourPid != curHandle.mPid) { if (kernelObject && kernelObject.value() == curHandle.mObject) { // The kernel objects match -- we have found the remote pid! sUiaRemotePid = Some(curHandle.mPid); break; } // An object that is not ours. Since we do not yet know which kernel // object we're interested in, we'll save the current object for later. objMap.Put(curHandle.mObject, curHandle.mPid); } else if (handle == section.get()) { // This is the file mapping that we opened above. We save this mObject // in order to compare to Section objects opened by other processes. kernelObject = Some(curHandle.mObject); } } if (!kernelObject) { return Nothing(); } if (!sUiaRemotePid) { // We found kernelObject *after* we saw the remote process's copy. Now we // must look it up in objMap. DWORD pid; if (objMap.Get(kernelObject.value(), &pid)) { sUiaRemotePid = Some(pid); } } if (!sUiaRemotePid) { return Nothing(); } a11y::SetInstantiator(sUiaRemotePid.value()); // Block if necessary nsCOMPtr<nsIFile> instantiator; if (a11y::GetInstantiator(getter_AddRefs(instantiator)) && ShouldBlockUIAClient(instantiator)) { return Some(false); } return Some(true); }
void CinematicTrigger::HandleOff() { if (!m_bOn) return; for ( uint32 iWho = 0 ; iWho < MAX_CT_MESSAGES; iWho++ ) { if ( m_hstrWhoPlaysDialogue[iWho] ) { HOBJECT hWho; if ( LT_OK == FindNamedObject(m_hstrWhoPlaysDialogue[iWho], hWho) ) { if ( IsKindOf(hWho, "CAI") ) { CAI* pAI = (CAI*)g_pLTServer->HandleToObject(hWho); pAI->UnlinkCinematicTrigger(m_hObject); } } } } m_bOn = LTFALSE; // If we have a current speaker, make sure he is done talking... if (m_hCurSpeaker) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(m_hCurSpeaker); if (pChar) { pChar->StopDialogue(); } // Clear our speaker... g_pLTServer->BreakInterObjectLink(m_hObject, m_hCurSpeaker); m_hCurSpeaker = LTNULL; } // Clear out our last speaker if (m_hLastSpeaker) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(m_hLastSpeaker); if (pChar) { pChar->StopDialogue(TRUE); } g_pLTServer->BreakInterObjectLink(m_hObject, m_hLastSpeaker); m_hLastSpeaker = LTNULL; } // Send the clean up trigger message... if (m_hstrCleanUpTriggerTarget && m_hstrCleanUpTriggerMsg) { SendTriggerMsgToObjects(this, g_pLTServer->GetStringData( m_hstrCleanUpTriggerTarget ), g_pLTServer->GetStringData( m_hstrCleanUpTriggerMsg )); } // Turn off the camera... if (m_hCamera && !m_bLeaveCameraOn) { SendTriggerMsgToObject(this, m_hCamera, FALSE, "OFF"); } // Turn off the keyframer... if (m_hKeyFramer) { SendTriggerMsgToObject(this, m_hKeyFramer, FALSE, "OFF"); } SetNextUpdate(m_hObject, 0.0f); if (m_bOneTimeOnly) { // Can't get rid of object if we're leaving the camera on ;)... if (!m_hCamera || !m_bLeaveCameraOn) { g_pLTServer->RemoveObject(m_hObject); } } }
LTBOOL CinematicTrigger::UpdateDialogue() { if (!g_pLTServer) return LTFALSE; // If we haven't yet done so, let all the cinematic participants know // they're under CinematicTrigger control if ( !m_bNotified ) { for ( uint32 iWho = 0 ; iWho < MAX_CT_MESSAGES; iWho++ ) { if ( m_hstrWhoPlaysDialogue[iWho] ) { HOBJECT hWho; if ( LT_OK == FindNamedObject(m_hstrWhoPlaysDialogue[iWho], hWho) ) { if ( IsKindOf(hWho, "CAI") ) { CAI* pAI = (CAI*)g_pLTServer->HandleToObject(hWho); pAI->LinkCinematicTrigger(m_hObject); } } } } m_bNotified = LTTRUE; } // Now update... LTFLOAT fTime = g_pLTServer->GetTime(); // See if we are playing a dialogue... BOOL bDone = FALSE; if (m_hCurSpeaker) { // If sound is done, stop it and wait for new sound... CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(m_hCurSpeaker); if (pChar) { bDone = !pChar->IsPlayingDialogue(); } } if (bDone) { // Send message for our last reply (since the dialog is now done)... if (m_byLastReply) { SendReplyMessage(m_byLastReply); } m_byLastReply = m_byDecision; m_byDecision = 0; // Clear our speaker... g_pLTServer->BreakInterObjectLink(m_hObject, m_hCurSpeaker); m_hCurSpeaker = LTNULL; if(m_byLastReply) { return StartDialogue(m_byLastReply); } m_nCurMessage++; if (m_nCurMessage < MAX_CT_MESSAGES) { m_fNextDialogueStart = fTime + m_fDelay[m_nCurMessage]; } else { return LTFALSE; } } if (!m_hCurSpeaker) { // See if we're done... if (m_nCurMessage >= MAX_CT_MESSAGES || !m_hstrDialogue[m_nCurMessage]) { return LTFALSE; } // Start next sound... if (m_fNextDialogueStart >= 0.0f && m_fNextDialogueStart <= fTime) { return StartDialogue(); } } return LTTRUE; }
LTBOOL AI_Helicopter::HandleCommand(char** pTokens, int nArgs) { // Let base class have a whack at it... if (CAIVehicle::HandleCommand(pTokens, nArgs)) return LTTRUE; // State-changing message for ( int iState = 0 ; iState < s_cStateMaps ; iState++ ) { if ( !_stricmp(pTokens[0], s_aStateMaps[iState].szState) ) { // Change states SetState(s_aStateMaps[iState].eState); HandleCommandParameters(pTokens, nArgs); return LTTRUE; } } // Non-state-changing messages if ( !_stricmp(pTokens[0], "FX") ) { if ( nArgs != 4 ) { g_pLTServer->CPrint("FX command needs 4 arguments! - FX IMPACT SOCKET \"IMPACTFX NAME\""); return LTTRUE; } if ( !_stricmp(pTokens[1], "IMPACT") ) { HCLASS hClass = g_pLTServer->GetClass("Explosion"); if (!hClass) return LTTRUE; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); HMODELSOCKET hSocket; if ( LT_OK == g_pModelLT->GetSocket(m_hObject, pTokens[2], hSocket) ) { LTransform tf; if ( LT_OK == g_pModelLT->GetSocketTransform(m_hObject, hSocket, tf, LTTRUE) ) { if ( LT_OK == g_pTransLT->GetPos(tf, vPos) ) { } } } IMPACTFX* pImpactFX = LTNULL; if ( pImpactFX = g_pFXButeMgr->GetImpactFX(pTokens[3]) ) { EXPLOSIONCREATESTRUCT cs; cs.nImpactFX = pImpactFX->nId; cs.rRot = m_rRot; cs.vPos = vPos; cs.fDamageRadius = 0.0f; HMESSAGEWRITE hMessage = g_pLTServer->StartInstantSpecialEffectMessage(&vPos); g_pLTServer->WriteToMessageByte(hMessage, SFX_EXPLOSION_ID); cs.Write(g_pLTServer, hMessage); g_pLTServer->EndMessage2(hMessage, MESSAGE_NAGGLEFAST); } } } else if ( !_stricmp(pTokens[0], "LIGHTFOLLOW") ) { if ( m_iObjectSearchLight == -1 ) return LTTRUE; HOBJECT hObject; if ( LT_OK == FindNamedObject(pTokens[1], hObject) ) { if ( !IsKindOf(hObject, "ControlledSearchLight") ) return LTTRUE; ControlledSearchLight* pSearchLight = ((ControlledSearchLight*)m_apObjects[m_iObjectSearchLight]); if (pSearchLight) { pSearchLight->SetTarget(hObject); } } return LTTRUE; } return LTFALSE; }
AINode* CAINodeMgr::FindNearestObjectNode(CAI* pAI, EnumAINodeType eNodeType, const LTVector& vPos, const char* szClass) { LTFLOAT fMinDistanceSqr = (float)INT_MAX; AINode* pClosestNode = LTNULL; // Get AIs Path Knowledge. CAIPathKnowledgeMgr* pPathKnowledgeMgr = LTNULL; if( pAI && pAI->GetPathKnowledgeMgr() ) { pPathKnowledgeMgr = pAI->GetPathKnowledgeMgr(); } AINode* pNode; AINODE_MAP::iterator it; for(it = m_mapAINodes.lower_bound(eNodeType); it != m_mapAINodes.upper_bound(eNodeType); ++it) { pNode = it->second; // Skip nodes in unreachable volumes. if( pPathKnowledgeMgr && ( pPathKnowledgeMgr->GetPathKnowledge( pNode->GetNodeContainingVolume() ) == CAIPathMgr::kPath_NoPathFound ) ) { continue; } // Skip nodes that are not in volumes. if( !pNode->GetNodeContainingVolume() ) { continue; } // Skip node if required alignment does not match. if( ( pNode->GetRequiredRelationTemplateID() != -1 ) && ( pNode->GetRequiredRelationTemplateID() != pAI->GetRelationMgr()->GetTemplateID() ) ) { continue; } if( !pNode->NodeTypeIsActive( eNodeType ) ) { continue; } if ( !pNode->IsLockedDisabledOrTimedOut() && pNode->HasObject() ) { LTFLOAT fDistanceSqr = VEC_DISTSQR(vPos, pNode->GetPos()); if ( (fDistanceSqr < fMinDistanceSqr) && (fDistanceSqr < pNode->GetRadiusSqr()) ) { HOBJECT hObject; if ( LT_OK == FindNamedObject(pNode->GetObject(), hObject) ) { HCLASS hClass = g_pLTServer->GetClass((char*)szClass); if ( g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hObject), hClass) ) { fMinDistanceSqr = fDistanceSqr; pClosestNode = pNode; } } } } } // Ensure that AI can pathfind to the destination node. // Ideally, we would like to do this check for each node as we iterate, // but that could result in multiple runs of BuildVolumePath() which // is expensive. So instead we just check the final returned node. // The calling code can call this function again later, and will not get // this node again. if( pAI && pClosestNode ) { AIVolume* pVolumeDest = pClosestNode->GetNodeContainingVolume(); if( !g_pAIPathMgr->HasPath( pAI, pVolumeDest ) ) { return LTNULL; } } return pClosestNode; }
bool ObjectRemover::AllObjectsCreated() { HOBJECT ahObjects[kMaxGroups][kMaxObjectsPerGroup][128]; memset(ahObjects, 0, sizeof(HOBJECT)*kMaxGroups*kMaxObjectsPerGroup*128); int cGroupsWithObjects = 0; {for ( int iGroup = 0 ; iGroup < kMaxGroups ; iGroup++ ) { bool bGroupHasObjects = false; {for ( int iObject = 0 ; iObject < kMaxObjectsPerGroup ; iObject++ ) { if ( !m_astrObjects[iGroup][iObject].empty() ) { char szString[1024]; strcpy(szString, m_astrObjects[iGroup][iObject].c_str()); uint32 cTokens = 0; const char* szToken = strtok(szString, ";"); while ( szToken ) { HOBJECT hObject; if ( LT_OK == FindNamedObject(szToken, hObject) ) { ahObjects[cGroupsWithObjects][iObject][cTokens++] = hObject; bGroupHasObjects = true; } szToken = strtok(NULL, ";"); } } }} if ( bGroupHasObjects ) { cGroupsWithObjects++; } }} // Remove the objects bool abRemoved[kMaxGroups]; memset(abRemoved, false, sizeof(bool)*kMaxGroups); int iSafety = 50000; int cRemove = cGroupsWithObjects-m_cGroupsToKeep; while ( (cRemove > 0) && (--iSafety > 0) ) { int iRemove = GetRandom(0, cGroupsWithObjects-1); if ( !abRemoved[iRemove] ) { for ( int iObject = 0 ; iObject < kMaxObjectsPerGroup ; iObject++ ) { for ( int iToken = 0 ; iToken < 128 ; iToken++ ) { if ( ahObjects[iRemove][iObject][iToken] ) { if ( IsAI(ahObjects[iRemove][iObject][iToken]) ) { ILTBaseClass *pAI = g_pLTServer->HandleToObject( ahObjects[iRemove][iObject][iToken] ); g_pCmdMgr->QueueMessage( this, pAI, "REMOVE" ); } else { g_pLTServer->RemoveObject(ahObjects[iRemove][iObject][iToken]); } } } } abRemoved[iRemove] = true; cRemove--; } } // Remove ourselves... g_pLTServer->RemoveObject(m_hObject); return true; }