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;
}
示例#2
0
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;
}