void CAIVolume::EnumerateSearchNodes(uint32* aiSearchNodes, uint32* pcSearchNodes, const uint32 nMaxSearchNodes) const { for ( uint32 iNode = 0 ; iNode < g_pAINodeMgr->GetNumNodes() && *pcSearchNodes < nMaxSearchNodes ; iNode++ ) { CAINode* pNode = g_pAINodeMgr->GetNode(iNode); if ( pNode && pNode->IsSearchable() && Inside(pNode->GetPos(), 53.0f) ) { aiSearchNodes[(*pcSearchNodes)++] = pNode->GetID(); } } }
void CAIHelicopterStateGoto::HandleNameValuePair(char *szName, char *szValue) { CAIHelicopterState::HandleNameValuePair(szName, szValue); if ( !_stricmp(szName, "PT") ) { sscanf(szValue, "%f,%f,%f", &m_vDest.x, &m_vDest.y, &m_vDest.z); m_cNodes = 0; } else if ( !_stricmp(szName, "PTS") ) { m_cNodes = 0; char *szPoint = strtok(szValue, ","); while ( szPoint ) { if ( m_cNodes == kMaxGotoNodes ) { g_pLTServer->CPrint("Max # Goto waypoints exceeded %s=%s", szName, szValue); } CAINode* pNode = g_pAINodeMgr->GetNode(szPoint); if ( pNode ) { m_adwNodes[m_cNodes++] = pNode->GetID(); } else { g_pLTServer->CPrint("Unknown Goto waypoint ''%s''", szPoint); } szPoint = strtok(NULL, ","); } } else if ( !_stricmp(szName, "LOOP") ) { m_bLoop = IsTrueChar(*szValue); } }
void CAIBrain::GetDodgeStatus(DodgeStatus* peDodgeStatus, Direction* peDirection, DodgeAction* peDodgeAction, uint32* pdwNode) { if ( !GetAI()->HasTarget() || !GetAI()->HasLastVolume() ) { *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; return; } if ( g_pLTServer->GetTime() >= m_fDodgeStatusCheckTimeVector ) { m_fDodgeStatusCheckTimeVector = g_pLTServer->GetTime() + LOWER_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckTime); if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fDodgeVectorCheckChance) ) { if ( GetAI()->GetTarget()->IsVisiblePartially() ) { CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(GetAI()->GetTarget()->GetObject()); if ( pCharacter->HasDangerousWeapon() ) { LTRotation rRot; LTVector vNull, vForward; g_pLTServer->GetObjectRotation(GetAI()->GetTarget()->GetObject(), &rRot); g_pMathLT->GetRotationVectors(rRot, vNull, vNull, vForward); LTVector vDir; vDir = GetAI()->GetPosition() - GetAI()->GetTarget()->GetPosition(); vDir.y = 0; vDir.Norm(); // TODO: bute this const static LTFLOAT fThreshhold = 0.95f; if ( (vDir.Dot(vForward) > fThreshhold) && (GetAI()->GetForwardVector().Dot(vForward) < -fThreshhold) ) { LTFLOAT fCheckDistance; LTFLOAT fRandom = GetRandom(0.0f, 1.0f); if ( fRandom > m_pBrain->fDodgeVectorCoverChance ) { if ( fRandom > (m_pBrain->fDodgeVectorCoverChance + m_pBrain->fDodgeVectorRollChance) ) { *peDodgeAction = eDodgeActionShuffle; fCheckDistance = 109.0f; } else { *peDodgeAction = eDodgeActionRoll; fCheckDistance = 140.0f; } // MAKE SURE WE WON'T DODGE OUT OF THE VOLUME if ( GetAI()->GetLastVolume()->Inside2d(GetAI()->GetPosition()+GetAI()->GetRightVector()*fCheckDistance, GetAI()->GetRadius()) ) { *peDirection = eDirectionRight; *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector; return; } else if ( GetAI()->GetLastVolume()->Inside2d(GetAI()->GetPosition()-GetAI()->GetRightVector()*fCheckDistance, GetAI()->GetRadius()) ) { *peDirection = eDirectionLeft; *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector; return; } else { *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; return; } } else { CAINode* pNode = g_pAINodeMgr->FindNearestCoverFromThreat(GetAI()->GetPosition(), GetAI()->GetTarget()->GetObject()); if ( pNode ) { *peDodgeAction = eDodgeActionCover; *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusVector; *pdwNode = pNode->GetID(); } else { *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; } return; } } } } } } if ( g_pLTServer->GetTime() >= m_fDodgeStatusCheckTimeProjectile ) { m_fDodgeStatusCheckTimeProjectile = g_pLTServer->GetTime() + RAISE_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckTime); if ( GetRandom(0.0f, 1.0f) <= RAISE_BY_DIFFICULTY(m_pBrain->fDodgeProjectileCheckChance) ) { CGrenade* pGrenade; if ( FindGrenadeDangerPosition(GetAI()->GetPosition(), 40000.0f, &m_vDodgeProjectilePosition, &pGrenade) ) { FREE_HSTRING(m_hstrDodgeProjectileName); // $STRING m_hstrDodgeProjectileName = g_pLTServer->CreateString(g_pLTServer->GetObjectName(pGrenade->m_hObject)); *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusProjectile; *peDodgeAction = eDodgeActionFlee; return; } } } *peDodgeStatus = m_eDodgeStatusLast = eDodgeStatusOk; return; }
void CAIVolume::Init(int32 iVolume, const AIVolume& vol) { char szName[128]; g_pLTServer->GetObjectName(vol.m_hObject, szName, 127); m_hstrName = g_pLTServer->CreateString(szName); m_iVolume = iVolume; LTVector vVolumePos; LTVector vVolumeDims; g_pLTServer->GetObjectPos(vol.m_hObject, &vVolumePos); g_pLTServer->GetObjectDims(vol.m_hObject, &vVolumeDims); m_vFrontTopRight = vVolumePos + LTVector(vVolumeDims.x, vVolumeDims.y, vVolumeDims.z); m_vFrontTopLeft = vVolumePos + LTVector(-vVolumeDims.x, vVolumeDims.y, vVolumeDims.z); m_vBackTopRight = vVolumePos + LTVector(vVolumeDims.x, vVolumeDims.y, -vVolumeDims.z); m_vBackTopLeft = vVolumePos + LTVector(-vVolumeDims.x, vVolumeDims.y, -vVolumeDims.z); m_vFrontBottomRight = vVolumePos + LTVector(vVolumeDims.x, -vVolumeDims.y, vVolumeDims.z); m_vFrontBottomLeft = vVolumePos + LTVector(-vVolumeDims.x, -vVolumeDims.y, vVolumeDims.z); m_vBackBottomRight = vVolumePos + LTVector(vVolumeDims.x, -vVolumeDims.y, -vVolumeDims.z); m_vBackBottomLeft = vVolumePos + LTVector(-vVolumeDims.x, -vVolumeDims.y, -vVolumeDims.z); // Get the view volumes for ( uint32 iViewNode = 0 ; iViewNode < kMaxViewNodes ; iViewNode++ ) { if ( vol.GetViewNode(iViewNode) ) { CAINode* pNode = g_pAINodeMgr->GetNode(vol.GetViewNode(iViewNode)); if ( pNode ) { m_adwViewNodes[iViewNode] = pNode->GetID(); } else { g_pLTServer->CPrint("********** Volume ''%s'' has a view node that does not exist!", GetName()); } } } // Find any doors located in our volume HCLASS hDoor = g_pLTServer->GetClass("Door"); HCLASS hSwitch = g_pLTServer->GetClass("Switch"); HOBJECT hCurObject = LTNULL; while (hCurObject = g_pLTServer->GetNextObject(hCurObject)) { if (g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hDoor) && !g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hSwitch)) { Door* pDoor = (Door*)g_pLTServer->HandleToObject(hCurObject); if ( !pDoor->IsAITriggerable() ) continue; LTVector vPos; LTVector vDims; g_pLTServer->GetObjectPos(hCurObject, &vPos); g_pLTServer->GetObjectDims(hCurObject, &vDims); if ( Inside(vPos, vDims.y*2.0f) ) { if ( m_cDoors == cm_nMaxDoors ) { _ASSERT(!"Max number of doors in a volume exceeded!!!!"); g_pLTServer->CPrint("Max number of doors in a volume exceeded!!!!"); } else { m_bHadDoors = LTTRUE; g_pAIVolumeMgr->Link(hCurObject); m_ahDoors[m_cDoors++] = hCurObject; } } } } hCurObject = LTNULL; while (hCurObject = g_pLTServer->GetNextInactiveObject(hCurObject)) { if (g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hDoor) && !g_pLTServer->IsKindOf(g_pLTServer->GetObjectClass(hCurObject), hSwitch)) { Door* pDoor = (Door*)g_pLTServer->HandleToObject(hCurObject); if ( !pDoor->IsAITriggerable() ) continue; LTVector vPos; LTVector vDims; g_pLTServer->GetObjectPos(hCurObject, &vPos); g_pLTServer->GetObjectDims(hCurObject, &vDims); if ( Inside(vPos, vDims.y*2.0f) ) { if ( m_cDoors == cm_nMaxDoors ) { _ASSERT(!"Max number of doors in a volume exceeded!!!!"); g_pLTServer->CPrint("Max number of doors in a volume exceeded!!!!"); } else { m_bHadDoors = LTTRUE; g_pAIVolumeMgr->Link(hCurObject); m_ahDoors[m_cDoors++] = hCurObject; } } } } // Validate volume dims. Must be 64x64 if there's no doors. One side must be <= 128 if there are doors #ifndef _FINAL // Don't spam multiplayer server with warnings... if ( m_cDoors == 0 ) { if ( vVolumeDims.x < 32 ) g_pLTServer->CPrint("WARNING: Volume \"%s\" is only %d units wide/x (should be at least 64)", GetName(), (int)vVolumeDims.x*2); if ( vVolumeDims.z < 32 ) g_pLTServer->CPrint("WARNING: Volume \"%s\" is only %d units deep/z (should be at least 64)", GetName(), (int)vVolumeDims.z*2); } else // if ( m_cDoors != 0 ) { if ( vVolumeDims.x >= 128 && vVolumeDims.z >= 128 ) g_pLTServer->CPrint("WARNING: Volume \"%s\" is a suspiciously large door volume!", GetName()); } #endif // Misc flags that have been set m_bStairs = vol.HasStairs(); m_vStairsDir = vol.GetStairsDir(); m_bLedge = vol.HasLedge(); m_vLedgeDir = vol.GetLedgeDir(); m_bVertical = vol.IsVertical(); }