LTBOOL CAISenseSeeEnemy::Update(HOBJECT hStimulus, LTFLOAT fTimeDelta) { if ( !IsCharacter(hStimulus) ) return LTFALSE; if ( m_pAI->GetCharacterClass() == NEUTRAL ) { // If we're innocent, we only consider someone an enemy if they have a gun CCharacter* pCharacter = (CCharacter*)g_pLTServer->HandleToObject(hStimulus); if ( !pCharacter->HasDangerousWeapon() ) { return LTFALSE; } } // Instead of looking right at the center of the target, we at a grid of points. // The grid is a plane with normal equal to the forward vector of the object, // in the center of the object, clipped to the objects dims. We scan the grid // at a given resolution and simply advance our scan col/row every frame. Note // that the grid is aligned with the objects rotation, not the bounding boxes, // since all the bounding boxes are axis aligned. int nXRange = m_rngGridX.GetMax() - m_rngGridX.GetMin(); int nYRange = m_rngGridY.GetMax() - m_rngGridY.GetMin(); LTVector vDims; g_pLTServer->GetObjectDims(hStimulus, &vDims); LTFLOAT fX = vDims.x * ((LTFLOAT)m_nGridX/(LTFLOAT)nXRange); LTFLOAT fY = vDims.y * ((LTFLOAT)m_nGridY/(LTFLOAT)nYRange); LTVector vPosition; g_pLTServer->GetObjectPos(hStimulus, &vPosition); LTRotation rRot; g_pLTServer->GetObjectRotation(hStimulus, &rRot); LTVector vUp, vRight, vForward; g_pLTServer->GetRotationVectors(&rRot, &vUp, &vRight, &vForward); vPosition += vRight*fX; vPosition += vUp*fY; // Update the point LTFLOAT fDistanceSqr; LTBOOL bVisible; if ( m_pAI->CanSeeThrough() ) { bVisible = m_pAI->IsObjectPositionVisibleFromEye(CAI::SeeThroughFilterFn, CAI::SeeThroughPolyFilterFn, hStimulus, vPosition, (m_fDistanceSqr), LTTRUE, &fDistanceSqr); } else { bVisible = m_pAI->IsObjectPositionVisibleFromEye(CAI::DefaultFilterFn, NULL, hStimulus, vPosition, (m_fDistanceSqr), LTTRUE, &fDistanceSqr); } if ( bVisible ) { if ( fDistanceSqr > g_pAIButeMgr->GetSenses()->fInstantSeeDistanceSqr ) { LTFLOAT fRateModifier = (1.0f - fDistanceSqr/m_fDistanceSqr); IncreaseStimulation(fTimeDelta, (fRateModifier)); } else { IncreaseStimulation(fTimeDelta, 99999999.0f); } } // Update our grid col/row values if ( ++m_nGridX > m_rngGridX.GetMax() ) { m_nGridX = m_rngGridX.GetMin(); if ( ++m_nGridY > m_rngGridY.GetMax() ) { m_nGridY = m_rngGridY.GetMin(); } } return bVisible; }
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; }