bool IsPointOnMyFlank(EntityId actorEntityID, const Vec3& actorPos, const Vec3& targetPos, const Vec3& pointPos)
	{
		CAIBattleFrontGroup* group = gGameAIEnv.battleFrontModule->GetGroupForEntity(actorEntityID);
		ASSERT_IS_NOT_NULL(group);
		if (!group || group->GetMemberCount() == 1)
			return true; // I'm alone so this is my flank

		const Vec3& groupAveragePos = group->GetAveragePosition();

		// Set up a coordinate system where Y corresponds to the direction
		// from the battle group's center position towards the target
		Vec3 Y = (targetPos - groupAveragePos);
		Vec3 X = Vec3(0,0,-1).Cross(Y);

		// Calculate flank side sign
		Vec3 vGroupAveragePosToActor = actorPos - groupAveragePos;
		float flankSideSign = (vGroupAveragePosToActor.Dot(X) > 0.0f) ? 1.0f : -1.0f; // Flank side sign (-1 for left, +1 for right)

		// Calculate how far the point is on the X-axis
		Vec3 groupAveragePosToPoint = pointPos - groupAveragePos;
		float pointDistOnXAxis = groupAveragePosToPoint.Dot(X);

		bool pointIsOnMyFlank = pointDistOnXAxis * flankSideSign > 0.0f;
		return pointIsOnMyFlank;
	}
bool OrE::Math::HitTest( Ellipsoid e1, Ellipsoid e2 )
{
	// Absolute squared distance vector from e2 to e1
	Vec3 vDist = e1.vMiddlePoint - e2.vMiddlePoint;
	vDist *= vDist;
	// Project ray to both ellipsoid surfaces. All what matters is,
	// the the sum of the distances to surface is smaller than the length of
	// the distance vector.
	// Vec3 vRSum = vDist * ( InvSqrt( vDist.Dot( vDist * e1.vRadiiInvSq ) ) + InvSqrt( vDist.Dot( vDist * e2.vRadiiInvSq ) ) );
	// return vRSum.LengthSq() >= vDist.LengthSq();
	return InvSqrt( vDist.Dot( e1.vRadiiInvSq ) ) + InvSqrt( vDist.Dot( e2.vRadiiInvSq ) ) >= 1.0f;
}
	EStatus Update(float timePassed)
	{
		if (IsTransitioningOut())
		{
			const float ROTATION_LERP_SPEED = 10.0f;

			//--- Blend body rotation to match current view
			Ang3 targetViewDir = m_player.GetAngles();
			Quat targetRotation = Quat::CreateRotationZ(targetViewDir.z);
			Quat newRotation = Quat::CreateNlerp(m_player.GetEntity()->GetRotation(), targetRotation, timePassed*ROTATION_LERP_SPEED);
			m_player.GetEntity()->SetRotation(newRotation);
		}
		else
		{
			static uint32 leanParamCRC = gEnv->pSystem->GetCrc32Gen()->GetCRC32Lowercase("SlideFactor");

			const Matrix34 &worldTM = m_player.GetEntity()->GetWorldTM();
			const Vec3 baseRgt = worldTM.GetColumn0();
			const Vec3 baseFwd = worldTM.GetColumn1();
			const Vec3 lookFwd = m_player.GetViewQuatFinal().GetColumn1();
			const float leanAngle = cry_acosf(baseFwd.Dot(lookFwd));

			float targetLeanFactor = clamp(leanAngle / MAX_LEAN_ANGLE, 0.0f, 1.0f);
			if (baseRgt.Dot(lookFwd) < 0.0f)
			{
				targetLeanFactor *= -1.0f;
			}
			CWeapon *pWeapon = m_player.GetWeapon(m_player.GetCurrentItemId());
			if (pWeapon)
			{
				IFireMode *pFiremode = pWeapon->GetFireMode(pWeapon->GetCurrentFireMode());
				if (pFiremode && (pFiremode->GetNextShotTime() > 0.0f))
				{
					targetLeanFactor = 0.0f;
				}
			}
			const float delta					= targetLeanFactor - m_leanFactor;
			const float step					= LEAN_RATE * timePassed;
			const float newLeanFactor	= (float)__fsel(delta, min(m_leanFactor + step, targetLeanFactor), max(m_leanFactor - step, targetLeanFactor));
			SWeightData weightData;
			weightData.weights[0] = newLeanFactor;
			SetParam(leanParamCRC, weightData);
			m_leanFactor = newLeanFactor;

			if (GetRootScope().IsDifferent(m_fragmentID, m_fragTags))
			{
				SetFragment(m_fragmentID, m_fragTags);
			}
		}

		return TPlayerAction::Update(timePassed);
	}
예제 #4
0
파일: transform.hpp 프로젝트: mini3d/mini3d
    static Transform LookAtRH(const Vec3 eye, const Vec3 at, const Vec3 up)
    {
        Vec3 n = (eye - at).Normalized();
        Vec3 u = up.Cross(n).Normalized();
        Vec3 v = n.Cross(u);

        float w = sqrtf(1.0f + u.x + v.y + n.z) * 0.5f;
        float w4 = 1.0f / (4.0f * w);
        
        return Transform(   Vec3(-u.Dot(eye), -v.Dot(eye), -n.Dot(eye)), // Position
                            Quat((v.z-n.y) * w4, (n.x-u.z) * w4, (u.y-v.x) * w4, -w).Normalized(), // Rotation
                            1); // Scale

    }
예제 #5
0
//------------------------------------------------------------------
void CLam::AdjustLaserFPDirection(CItem* parent, Vec3 &dir, Vec3 &pos)
{
    pos = parent->GetSlotHelperPos(eIGS_FirstPerson,m_laserHelperFP.c_str(),true);
    Quat   lamRot = Quat(parent->GetSlotHelperRotation(eIGS_FirstPerson,m_laserHelperFP.c_str(),true));
    dir = -lamRot.GetColumn0();

    if(!m_lamparams.isLamRifle)
        dir = lamRot.GetColumn1();

    CActor *pActor = parent->GetOwnerActor();
    IMovementController * pMC = pActor ? pActor->GetMovementController() : NULL;
    if (pMC)
    {
        SMovementState info;
        pMC->GetMovementState(info);


        CWeapon* pWep = static_cast<CWeapon*>(parent->GetIWeapon());
        if(pWep && (pWep->IsReloading() || (!pActor->CanFire() && !pWep->IsZoomed())))
            return;

        if(dir.Dot(info.fireDirection)<0.985f)
            return;

        CCamera& camera = gEnv->pSystem->GetViewCamera();
        pos = camera.GetPosition();
        dir = camera.GetMatrix().GetColumn1();
        dir.Normalize();
    }
}
예제 #6
0
    void UnderWaterGodRay::_updateProjector()
    {
        Plane p(Vec3(0, 1, 0), mWaterPosition);
        Vec3 sunDir = Environment::Instance()->GetEvParam()->SunDir;
        Vec3 sunPos = Environment::Instance()->GetEvParam()->SunPos;
        Ray r(sunPos, sunDir);

        RayIntersectionInfo info = r.Intersection(p);

        mEnable = info.iterscetion;

        mProjPosition = sunPos + sunDir * info.distance;

        Vec3 y(0, 1, 0);

        if (sunDir.Dot(y) < 0.001)
            y = Vec3(0, 0, -1);

        Vec3 x = y.Cross(sunDir);
        y = sunDir.Cross(x);
        
        mProjMatrix.MakeRotationAxis(x, y, sunDir);
        mProjMatrix._41 = mProjPosition.x;
        mProjMatrix._42 = mProjPosition.y;
        mProjMatrix._43 = mProjPosition.z;
    }
예제 #7
0
bool Plane::Inside( Vec3 p, const float radius ) const 
   {
   float distance = p.Dot( n ) + d;
   // we need to consider if the point is outside the plane, but its radius may compensate for it
   // -> we should test distance + radius >= 0
   return ( distance >= -radius );
   }
예제 #8
0
// ******************************************************************************** //
// The spherical interpolation applies only to normal vectors
Vec3 OrE::Math::Slerp(const Vec3& v1, const Vec3& v2, const float t)
{
	float fOmega = Arccos( Clamp(v1.Dot(v2), -1.0f, 1.0f) );
	float f1 = Sin( fOmega * (1.0f-t) );
	float f2 = Sin( fOmega * t );
	return Vec3( v1.x*f1+v2.x*f2, v1.y*f1+v2.y*f2, v1.z*f1+v2.z*f2 ).Normalize();
}
예제 #9
0
float CRateOfDeathHelper_Target::CalculateStayAliveTime_Direction( const CRateOfDeathHelper_AttackerInfo& attacker ) const
{
	CRY_ASSERT( m_pTarget );

	const float directionInc = RateOfDeath::GetDirectionInc();

	const Vec3& attackerPosition = attacker.GetPosition();
	const Vec3& targetPosition = m_pTarget->GetPos();
	Vec3 targetDirection = targetPosition - attackerPosition;
	const float targetDistance = targetDirection.NormalizeSafe();

	const float thr1 = cosf( DEG2RAD( 30.0f ) );
	const float thr2 = cosf( DEG2RAD( 95.0f ) );

	const Vec3& targetViewDirection = m_pTarget->GetViewDir();
	const float dot = -targetDirection.Dot( targetViewDirection );
	if ( dot < thr2 )
	{
		return directionInc * 2.0f;
	}
	else if ( dot < thr1 )
	{
		return directionInc;
	}

	return 0;
}
예제 #10
0
//------------------------------------------------------------------------
void CMelee::Hit(geom_contact *contact, const Vec3 &dir, float damageScale, bool remote)
{
	CActor *pOwner = m_pWeapon->GetOwnerActor();

	if (!pOwner)
	{
		return;
	}

	Vec3 view(0.0f, 1.0f, 0.0f);

	if (IMovementController *pMC = pOwner->GetMovementController())
	{
		SMovementState state;
		pMC->GetMovementState(state);
		view = state.eyeDirection;
	}

	// some corrections to make sure the impulse is always away from the camera, and is not a backface collision
	bool backface = dir.Dot(contact->n) > 0;
	bool away = dir.Dot(view.normalized()) > 0; // away from cam?
	Vec3 normal = contact->n;
	Vec3 ndir = dir;

	if (backface)
	{
		if (away)
		{
			normal = -normal;
		}
		else
		{
			ndir = -dir;
		}
	}
	else
	{
		if (!away)
		{
			ndir = -dir;
			normal = -normal;
		}
	}

	IPhysicalEntity *pCollider = gEnv->pPhysicalWorld->GetPhysicalEntityById(contact->iPrim[0]);
	Hit(contact->pt, ndir, normal, pCollider, contact->iPrim[1], 0, contact->id[1], damageScale, remote);
}
예제 #11
0
void CScriptProxy::OnCollision(CEntity* pTarget, int matId, const Vec3 &pt, const Vec3 &n, const Vec3 &vel, const Vec3 &targetVel, int partId, float mass)
{
	if (!CurrentState()->IsStateFunctionImplemented(ScriptState_OnCollision))
		return;

	FUNCTION_PROFILER( GetISystem(), PROFILE_ENTITY );

	if (!m_hitTable)
		m_hitTable.Create(gEnv->pScriptSystem);
	{
		Vec3               dir(0, 0, 0);
		CScriptSetGetChain chain(m_hitTable);
		chain.SetValue("normal", n);
		chain.SetValue("pos", pt);

		if (vel.GetLengthSquared() > 1e-6f)
		{
			dir = vel.GetNormalized();
			chain.SetValue("dir", dir);
		}

		chain.SetValue("velocity", vel);
		chain.SetValue("target_velocity", targetVel);
		chain.SetValue("target_mass", mass);
		chain.SetValue("partid", partId);
		chain.SetValue("backface", n.Dot(dir) >= 0);
		chain.SetValue("materialId", matId);

		if (pTarget)
		{
			ScriptHandle sh;
			sh.n = pTarget->GetId();

			if (pTarget->GetPhysics())
			{
				chain.SetValue("target_type", (int)pTarget->GetPhysics()->GetType());
			}
			else
			{
				chain.SetToNull("target_type");
			}

			chain.SetValue("target_id", sh);

			if (pTarget->GetScriptTable())
			{
				chain.SetValue("target", pTarget->GetScriptTable());
			}
		}
		else
		{
			chain.SetToNull("target_type");
			chain.SetToNull("target_id");
			chain.SetToNull("target");
		}
	}

	m_pScript->CallStateFunction( CurrentState(),m_pThis,ScriptState_OnCollision, m_hitTable);
}
Vec3 CAnimatedCharacter::RemovePenetratingComponent(const Vec3& v, const Vec3& n) const
{
	float penetration = n.Dot(v);
	if (penetration >= 0.0f)
		return v;

	return (v - n * penetration);
}
예제 #13
0
inline float AngleBetweenVectors( const Vec3 &v1,const Vec3 &v2 )
{
	float a = acos_tpl(v1.Dot(v2));
	Vec3 r = v1.Cross(v2);
	if (r.z < 0)
		a = -a;
	return a;
}
예제 #14
0
파일: Mat44.cpp 프로젝트: dontnod/fastbuild
// MakeLookAt
//------------------------------------------------------------------------------
void Mat44::MakeLookAt( const Vec3 & pos, const Vec3 & lookAt, const Vec3 & upVector )
{
    // generate the forward vector
    Vec3 forward( pos - lookAt );
    forward.Normalise();

    Vec3 right = upVector.Cross( forward );
    right.Normalise();

    Vec3 up = forward.Cross( right );
    up.Normalise();

    col0 = Vec4( right.x, up.x, forward.x, 0.0f );
    col1 = Vec4( right.y, up.y, forward.y, 0.0f ),
    col2 = Vec4( right.z, up.z, forward.z, 0.0f ),
    col3 = Vec4( -right.Dot( pos ), -up.Dot( pos ), -forward.Dot( pos ), 1.0f );
}
예제 #15
0
void CNetPlayerInput::UpdateErrorSnap(const Vec3 &entPos, const Vec3 &desiredPos, f32 netPosDist, const Vec3 &desPosOffset, const CTimeValue &curTime)
{
	if (g_pGameCVars->pl_velocityInterpAlwaysSnap)
	{
		//--- Snap to target
		m_pPlayer->GetEntity()->SetPos(desiredPos);
		m_passedNetPos = true;
		m_passedPredictionPos = true;
	}
	else if (curTime > m_nextBCTime && !(m_pPlayer->m_stats.inFreefall.Value() > 0))
	{
		//--- Breadcrumbs dropped for simulated annealing, whilst the player is blocked we reduce the maximum
		//--- allowed offset until the character is snapped to the last net position
		Vec3 prevOffset = entPos - m_breadCrumb;
		bool blocked = false;
		if (!m_passedNetPos)
		{
			float moveDist = prevOffset.Dot(desPosOffset) / netPosDist;
			float moveSpeed  = moveDist / k_timePerBC;
			blocked = ((moveSpeed / m_netLerpSpeed) <= k_BCMovingRatio);
		}
		if (blocked)
		{
			m_blockedTime += k_timePerBC;
		}
		else
		{
			m_blockedTime = 0.0f;
		}

		m_breadCrumb = entPos;
		m_nextBCTime = curTime+k_timePerBC;

		Vec3 v0(desiredPos.x, desiredPos.y, 0.0f);
		Vec3 v1(m_predictedPosition.x, m_predictedPosition.y, 0.0f);
		Vec3 pt(entPos.x, entPos.y, 0.0f);
		Lineseg validPath(v0, v1);
		float t;
		float distSqrXY = Distance::Point_LinesegSq(pt, validPath, t);

		float heightDiff = m_predictedPosition.z - entPos.z;
		float blockedFactor = (1.0f - (m_blockedTime / k_maxBlockTime));
		float maxDistXY = !m_passedNetPos ? blockedFactor * k_maxInterpolateDist : k_reachedTargetAllowedDeviation;
		float timeOnGround = m_pPlayer->GetActorStats()->onGround;
		float allowedHeightDiff = (float)__fsel(timeOnGround - k_onGroundTime, k_allowedHeightDiff, k_allowedHeightDiffInAir);
		if ((distSqrXY > (maxDistXY * maxDistXY)) || (cry_fabsf(heightDiff) > allowedHeightDiff))
		{
			//--- Snap to target
			m_pPlayer->GetEntity()->SetPos(desiredPos);
			m_passedNetPos = true;
			const bool isfallen = m_pPlayer->m_stats.inFreefall.Value()==1;
		}
	}
}
예제 #16
0
bool SkillKill::IsGotYourBackKill(CPlayer* pShooterPlayer, CPlayer* pTargetPlayer)
{
    //To use the new actor manager stuff when merged back to postalpha
    const float maxDistSq = sqr(g_pGameCVars->g_gotYourBackKill_targetDistFromFriendly);
    const float fovRange = cry_cosf(DEG2RAD(g_pGameCVars->g_gotYourBackKill_FOVRange));

    IActorIteratorPtr pActorIterator = g_pGame->GetIGameFramework()->GetIActorSystem()->CreateActorIterator();

    Vec3 targetLocation = pTargetPlayer->GetEntity()->GetWorldPos();
    SMovementState targetMovementState;
    pTargetPlayer->GetMovementController()->GetMovementState(targetMovementState);

    Vec3 targetAimDirection = targetMovementState.aimDirection;

    while(CActor* pActor = static_cast<CActor*>(pActorIterator->Next()))
        {
            if(pActor != pShooterPlayer && !pActor->IsDead() && pShooterPlayer->IsFriendlyEntity(pActor->GetEntityId()))
                {
                    Vec3 actorLocation = pActor->GetEntity()->GetWorldPos();
                    Vec3 distance = actorLocation - targetLocation;

                    if(distance.GetLengthSquared() < maxDistSq)
                        {
                            distance.Normalize();
                            if(distance.Dot(targetAimDirection) > fovRange)
                                {
                                    SMovementState actorMovementState;
                                    pActor->GetMovementController()->GetMovementState(actorMovementState);
                                    Vec3 actorAimDirection = actorMovementState.aimDirection;

                                    if(actorAimDirection.Dot(-distance) < fovRange)
                                        {
                                            return true;
                                        }
                                }
                        }
                }
        }

    return false;
}
예제 #17
0
//----------------------------------------------------------------------------
void BVSphere::Merge(const BoundingVolume* pBV)
{
	Vec3 dir = mCenter - pBV->GetCenter();
	Real distance = dir.Normalize();
	Vec3 myFar = mCenter + dir * mRadius;
	Vec3 otherFar = pBV->GetCenter() + dir * pBV->GetRadius();
	Real mydot = myFar.Dot(dir);
	Real otherdot = otherFar.Dot(dir);
	Vec3 mostFar0 = mydot > otherdot ? myFar : otherFar;

	dir = pBV->GetCenter() - mCenter;
	dir.Normalize();
	myFar = mCenter + dir * mRadius;
	otherFar = pBV->GetCenter() + dir * pBV->GetRadius();
	mydot = myFar.Dot(dir);
	otherdot = otherFar.Dot(dir);
	Vec3 mostFar1 = mydot > otherdot ? myFar : otherFar;

	mCenter = (mostFar0 + mostFar1) * .5f;
	mRadius = (mostFar0 - mostFar1).Length() * .5f;
}
예제 #18
0
파일: main.cpp 프로젝트: lanixXx/scratch
        inline Vec3 RotatedBy(Vec3 const &axisVec, double angleDegCCW)
        {
            if(!angleDegCCW)
            {   return Vec3(this->x,this->y,this->z);   }

            Vec3 rotatedVec;
            double angleRad = angleDegCCW*3.141592653589/180.0;
            rotatedVec = this->ScaledBy(cos(angleRad)) +
                         (axisVec.Cross(*this)).ScaledBy(sin(angleRad)) +
                         axisVec.ScaledBy(axisVec.Dot(*this)).ScaledBy(1-cos(angleRad));

            return rotatedVec;
        }
Vec3 RapidTrajectoryGenerator::GetOmega(double t, double timeStep) const
{
  //Calculates the body rates necessary at time t, to rotate the normal vector.
  //The result is coordinated in the world frame, i.e. would have to be rotated into a
  //body frame.
	const Vec3 n0 = GetNormalVector(t);
	const Vec3 n1 = GetNormalVector(t + timeStep);

	const Vec3 crossProd = n0.Cross(n1); //direction of omega, in inertial axes

	if (crossProd.GetNorm2()) return  (acos(n0.Dot(n1))/timeStep)*crossProd.GetUnitVector();
	else return Vec3(0, 0, 0);
}
예제 #20
0
void CCameraTracking::UpdateAutoFollow(const SViewParams &viewParams, const CPlayer &hero)
{
	if(g_pGameCVars->cl_cam_auto_follow_rate > 0.0f) //auto-tracking
	{
		//if there is an obstacle nearby, don't try to rotate into it
		float lastObstacleDist = (m_vLastObstaclePos - viewParams.position).len();

		if(lastObstacleDist < g_fAutoTrackObstacleDistance)
			return;

		if(hero.GetActorStats()->speedFlat < g_pGameCVars->cl_cam_auto_follow_movement_speed)
		{
			//only rotate when player moves
			m_fAutoRotateSpeed = 0.0f;
			return;
		}

		//get camera direction
		Vec3 camDir = -m_pCamRayScan->GetRayDir(eRAY_CENTER);
		camDir.z = 0.0f;
		camDir.Normalize();
		//get Player direction
		Vec3 heroDirection = (hero.GetAnimatedCharacter()->GetAnimLocation().q * FORWARD_DIRECTION);

		//compute angle between directions
		float dt = camDir.Dot(heroDirection);
		dt = clamp(dt, -1.0f, 1.0f);
		float angle = cry_acosf(dt);

		//check angle being bigger than threshold
		if(angle > g_pGameCVars->cl_cam_auto_follow_threshold)
		{
			float moveSpeed = max(0.002f, gf_PI*m_fFrameTime*g_pGameCVars->cl_cam_auto_follow_rate);
			m_fAutoRotateSpeed = InterpolateTo(max(0.002f, m_fAutoRotateSpeed), moveSpeed, 0.2f);

			//compute rotation direction by taking height part of cross-prod
			float dirVal = camDir.x * heroDirection.y - camDir.y * heroDirection.x;

			CCameraInputHelper *const pCamHelper = hero.GetCameraInputHelper();
			CRY_ASSERT(pCamHelper);

			if(dirVal > 0) //rotate right
				pCamHelper->SetTrackingDelta(-m_fAutoRotateSpeed, 0.0f);
			else //rotate left
				pCamHelper->SetTrackingDelta(m_fAutoRotateSpeed, 0.0f);
		}
		else
			m_fAutoRotateSpeed = 0.0f;
	}
}
예제 #21
0
파일: bot.cpp 프로젝트: DenMSC/qfusion
bool Bot::MayKeepRunningInCombat() const
{
    if (!HasEnemy())
        FailWith("MayKeepRunningInCombat(): there is no enemy");

    Vec3 enemyToBotDir = Vec3(self->s.origin) - EnemyOrigin();
    bool enemyMayHit = true;
    if (IsEnemyAStaticSpot())
    {
        enemyMayHit = false;
    }
    else if (EnemyFireDelay() > 300)
    {
        enemyMayHit = false;
    }
    else
    {
        Vec3 enemyLookDir = EnemyLookDir();
        float squaredDistance = enemyToBotDir.SquaredLength();
        if (squaredDistance > 1)
        {
            float distance = 1.0f / Q_RSqrt(squaredDistance);
            enemyToBotDir *= 1.0f / distance;
            // Compute a cosine of angle between enemy look dir and enemy to bot dir
            float cosPhi = enemyLookDir.Dot(enemyToBotDir);
            // Be aware of RL splash on this range
            if (distance < 150.0f)
                enemyMayHit = cosPhi > 0.3;
            else if (cosPhi <= 0.3)
                enemyMayHit = false;
            else
            {
                float cotPhi = Q_RSqrt((1.0f / (cosPhi * cosPhi)) - 1);
                float sideMiss = distance / cotPhi;
                // Use hitbox height plus a bit as a worst case
                float hitboxLargestSectionSide = 8.0f + playerbox_stand_maxs[2] - playerbox_stand_mins[2];
                enemyMayHit = sideMiss < hitboxLargestSectionSide;
            }
        }
    }

    if (enemyMayHit)
        return false;

    vec3_t botLookDir;
    AngleVectors(self->s.angles, botLookDir, nullptr, nullptr);
    // Check whether the bot may hit while running
    return ((-enemyToBotDir).Dot(botLookDir) > 0.99);
}
예제 #22
0
bool OrE::Math::HitDetection( Ellipsoid e1, Ellipsoid e2, Vec3& _vFeedbackLocation )
{
	// Absolute squared distance vector from e2 to e1
	Vec3 vDist = e1.vMiddlePoint - e2.vMiddlePoint;
	Vec3 vDistSq = vDist * vDist;
	// Determine the point in the middle between both surfaces.
	// Point on surface from e1, which is nearest to the center of e2 is p1 = r1 * -vDist + e1.m.
	// Point on surface from e2, which is nearest to the center of e1 is p2 = r2 * vDist + e2.m.
	// The point between them is (p1+p2)/2 = ((r2-r1) * vDist + e1.m+e2.m)/2
	float r1 = InvSqrt( vDistSq.Dot( e1.vRadiiInvSq ) );
	float r2 = InvSqrt( vDistSq.Dot( e2.vRadiiInvSq ) );
	_vFeedbackLocation = 0.5f*((r2-r1) * vDist + e1.vMiddlePoint + e2.vMiddlePoint);

	// Same as in HitTest
	return r1+r2 >= 1.0f;
}
예제 #23
0
//--------------------------------------------------------------------------------------------------
// Name: MergeFragmentTriangles
// Desc: Merges connected triangles into a single fragment list
//--------------------------------------------------------------------------------------------------
void CBreakableGlassSystem::MergeFragmentTriangles(mesh_data* pPhysMesh, const int tri, const Vec3& thinRow, TGlassFragmentIndexArray& touchedTris, TGlassFragmentIndexArray& fragTris)
{
	// Check for limits
	if (touchedTris.size() < touchedTris.max_size())
	{
		// Search for existing term
		const uint size = touchedTris.size();
		int index = -1;

		for (uint i = 0; i < size; ++i)
		{
			if (touchedTris[i] == tri)
			{ 
				index = i;
				break;
			}
		}

		if (index == -1)
		{
			touchedTris.push_back(tri);

			// Only support (fairly) flat surfaces
			const float flatThresh = 0.95f;

			if (thinRow.Dot(pPhysMesh->pNormals[tri]) >= flatThresh)
			{
				// Merge fragment
				fragTris.push_back(tri);

				// Recursively merge all connected triangles
				for (int i = 0; i < 3; ++i)
				{
					const int buddy = pPhysMesh->pTopology[tri].ibuddy[i];
					if (buddy >= 0)
					{
						MergeFragmentTriangles(pPhysMesh, buddy, thinRow, touchedTris, fragTris);
					}
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------
예제 #24
0
void CVehicleMovementAerodynamic::UpdateWing(SWing *_pWing,float _fAngle,float _fDeltaTime)
{
	Matrix34 matWing = m_pEntity->GetWorldTM() * Matrix33::CreateRotationXYZ(Ang3(DEG2RAD(_pWing->fAngleX),
																																								DEG2RAD(_pWing->fAngleY),
																																								DEG2RAD(_pWing->fAngleZ))).GetInverted();

	Vec3 vRight	= matWing.GetColumn(0);
	Vec3 vLook	= matWing.GetColumn(1);
	Vec3 vUp		= matWing.GetColumn(2);

	pe_status_dynamics StatusDynamics;
	GetPhysics()->GetStatus(&StatusDynamics);

	// v(relativepoint) = v + w^(relativepoint-center)
	Vec3 vVelocity = StatusDynamics.v + StatusDynamics.w.Cross(m_pEntity->GetWorldTM().TransformVector(_pWing->vPos));
	Vec3 vVelocityNormalized = vVelocity.GetNormalizedSafe(vLook);

	// TODO:

	float fAngleOfAttack = RAD2DEG(asin(vRight.Dot(vVelocityNormalized.Cross(vLook))));

	DumpText("AoA=%f",fAngleOfAttack);

	fAngleOfAttack += _fAngle;

	float Cl = GetCoefficient(_pWing->pLiftPointsMap,fAngleOfAttack) * _pWing->fCl;
	float Cd = GetCoefficient(_pWing->pDragPointsMap,fAngleOfAttack) * _pWing->fCd;

	Vec3 vVelocityNormal = vRight.Cross(vVelocityNormalized).GetNormalized();

	float fVelocitySquared = vVelocity.len2();

	const float c_fDynamicPressure = 1.293f;

	float fLift = 0.5f * c_fDynamicPressure * _pWing->fSurface * Cl * fVelocitySquared * _fDeltaTime;
	float fDrag = 0.5f * c_fDynamicPressure * _pWing->fSurface * Cd * fVelocitySquared * _fDeltaTime;

	Vec3 vLiftImpulse = +fLift * vVelocityNormal;
	Vec3 vDragImpulse = -fDrag * vVelocityNormalized;

	AddForce(&vLiftImpulse,&_pWing->vPos,ColorF(0,1,0,1));
	AddForce(&vDragImpulse,&_pWing->vPos,ColorF(1,0,1,1));
}
예제 #25
0
void WatchMeProcess::VOnUpdate(unsigned long deltaMs)
{
    StrongActorPtr pTarget = MakeStrongPtr(g_pApp->m_pGame->VGetActor(m_target));
	StrongActorPtr pMe = MakeStrongPtr(g_pApp->m_pGame->VGetActor(m_me));

    shared_ptr<TransformComponent> pTargetTransform = MakeStrongPtr(pTarget->GetComponent<TransformComponent>(TransformComponent::g_Name));
    shared_ptr<TransformComponent> pMyTransform = MakeStrongPtr(pMe->GetComponent<TransformComponent>(TransformComponent::g_Name));

	if (!pTarget || !pMe || !pTargetTransform || !pMyTransform)
	{
		GCC_ERROR("This shouldn't happen");
		Fail();
	}

	Vec3 targetPos = pTargetTransform->GetPosition();
	Mat4x4 myTransform = pMyTransform->GetTransform();
	Vec3 myDir = myTransform.GetDirection();
	myDir = Vec3(0.0f, 0.0f, 1.0f);
	Vec3 myPos = pMyTransform->GetPosition();

	Vec3 toTarget = targetPos - myPos;
	toTarget.Normalize();

	float dotProduct = myDir.Dot(toTarget);
	Vec3 crossProduct = myDir.Cross(toTarget);

	float angleInRadians = acos(dotProduct);

	if (crossProduct.y < 0)
		angleInRadians = -angleInRadians;
	
	Mat4x4 rotation;
	rotation.BuildRotationY(angleInRadians);
	rotation.SetPosition(myPos);
	pMyTransform->SetTransform(rotation);
}
예제 #26
0
//--------------------------------------------------------------------------------------------------
// Name: SpawnScreenExplosionEffect
// Desc: Spawns screen explosion effect
//--------------------------------------------------------------------------------------------------
void CExplosionGameEffect::SpawnScreenExplosionEffect(const SExplosionContainer &explosionContainer)
{
	// Disclaimer: this code was originally from GameRulesClientServer::ProcessClientExplosionScreenFX()

	const ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo;

	if(explosionInfo.pressure < 1.0f)
		return;

	IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor();
	if(pClientActor != NULL && !pClientActor->IsDead())
	{
		CPlayer* pPlayer = static_cast<CPlayer*>(pClientActor);
		bool hasFlashBangEffect = explosionInfo.blindAmount > 0.0f;

		// Flashbang friends and self?...
		if(hasFlashBangEffect)
		{
			bool flashBangSelf = true;
			bool flashBangFriends = false;
#ifndef _RELEASE
			flashBangSelf = g_pGameCVars->g_flashBangSelf != 0;
			flashBangFriends = g_pGameCVars->g_flashBangFriends != 0;
#endif
			bool ownFlashBang = pPlayer->GetEntityId() == explosionInfo.shooterId;
			if((!flashBangSelf && ownFlashBang) || // FlashBang self?
				((g_pGame->GetGameRules()->GetFriendlyFireRatio()<=0.0f) && (!flashBangFriends) && (!ownFlashBang) && pPlayer->IsFriendlyEntity(explosionInfo.shooterId))) // FlashBang friends?
			{
				return;
			}
		}

		// Distance
		float dist = (pClientActor->GetEntity()->GetWorldPos() - explosionInfo.pos).len();

		// Is the explosion in Player's FOV (let's suppose the FOV a bit higher, like 80)
		SMovementState state;
		if(IMovementController *pMV = pClientActor->GetMovementController())
		{
			pMV->GetMovementState(state);
		}

		Vec3 eyeToExplosion = explosionInfo.pos - state.eyePosition;
		Vec3 eyeDir = pClientActor->GetLinkedVehicle() ? pPlayer->GetVehicleViewDir() : state.eyeDirection;
		eyeToExplosion.Normalize();
		float eyeDirectionDP = eyeDir.Dot(eyeToExplosion);
		bool inFOV = (eyeDirectionDP > 0.68f);

		// All explosions have radial blur (default 30m radius)
		const float maxBlurDistance = (explosionInfo.maxblurdistance >0.0f) ? explosionInfo.maxblurdistance : 30.0f;
		if((maxBlurDistance > 0.0f) && (g_pGameCVars->g_radialBlur > 0.0f) && (explosionInfo.radius > 0.5f))
		{		
			if (inFOV && (dist < maxBlurDistance))
			{
				const int intersectionObjTypes = ent_static | ent_terrain;
				const unsigned int intersectionFlags = rwi_stop_at_pierceable|rwi_colltype_any;

				m_deferredScreenEffects.RequestRayCast(CDeferredExplosionEffect::eDET_RadialBlur, 
														explosionInfo.pos, -eyeToExplosion, dist, maxBlurDistance, intersectionObjTypes, intersectionFlags, NULL, 0);
			}
		}

		// Flashbang effect 
		if(hasFlashBangEffect && ((dist < (explosionInfo.radius*g_pGameCVars->g_flashBangNotInFOVRadiusFraction)) 
			|| (inFOV && (dist < explosionInfo.radius))))
		{
			ray_hit hit;
			const int intersectionObjTypes = ent_static | ent_terrain;
			const unsigned int intersectionFlags = rwi_stop_at_pierceable|rwi_colltype_any;
			const int intersectionMaxHits = 1;

			int collision = gEnv->pPhysicalWorld->RayWorldIntersection(	explosionInfo.pos, 
																																	-eyeToExplosion*dist, 
																																	intersectionObjTypes, 
																																	intersectionFlags, 
																																	&hit, 
																																	intersectionMaxHits);

			// If there was no obstacle between flashbang grenade and player
			if(!collision)
			{
				bool enabled = true;
				if(enabled)
				{
					CCCPOINT (FlashBang_Explode_BlindLocalPlayer);
					float timeScale = max(0.0f, 1 - (dist/explosionInfo.radius));
					float lookingAt = max(g_pGameCVars->g_flashBangMinFOVMultiplier, (eyeDirectionDP + 1)*0.5f);

					float time = explosionInfo.flashbangScale * timeScale *lookingAt;	// time is determined by distance to explosion		

					CRY_ASSERT_MESSAGE(pClientActor->IsPlayer(),"Effect shouldn't be spawned if not a player");

					SPlayerStats* pStats = static_cast<SPlayerStats*>(pPlayer->GetActorStats());

					NET_BATTLECHATTER(BC_Blinded, pPlayer);

					if(pClientActor->GetEntityId() == explosionInfo.shooterId)
					{
						g_pGame->GetPersistantStats()->IncrementClientStats(EIPS_BlindSelf);
					}
					else
					{
						g_pGame->GetGameRules()->SuccessfulFlashBang(explosionInfo, time);
					}

					pPlayer->StartFlashbangEffects(time, explosionInfo.shooterId);

					gEnv->p3DEngine->SetPostEffectParam("Flashbang_Time", time);
					gEnv->p3DEngine->SetPostEffectParam("FlashBang_BlindAmount", explosionInfo.blindAmount);
					gEnv->p3DEngine->SetPostEffectParam("Flashbang_DifractionAmount", time);
					gEnv->p3DEngine->SetPostEffectParam("Flashbang_Active", 1.0f);

					CRecordingSystem *pRecordingSystem = g_pGame->GetRecordingSystem();
					if (pRecordingSystem)
					{
						pRecordingSystem->OnPlayerFlashed(time, explosionInfo.blindAmount);
					}
				}
			}
			else
			{
				CCCPOINT (FlashBang_Explode_NearbyButBlockedByGeometry);
			}
		}
		else if(inFOV && (dist < explosionInfo.radius))
		{
			if(explosionInfo.damage>10.0f || explosionInfo.pressure>100.0f)
			{
				// Add some angular impulse to the client actor depending on distance, direction...
				float dt = (1.0f - dist/explosionInfo.radius);
				dt = dt * dt;
				float angleZ = gf_PI*0.15f*dt;
				float angleX = gf_PI*0.15f*dt;

				if (pClientActor)
				{
					static_cast<CActor*>(pClientActor)->AddAngularImpulse(Ang3(cry_random(-angleX*0.5f,angleX),0.0f,cry_random(-angleZ,angleZ)),0.0f,dt*2.0f);
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------
예제 #27
0
//-------------------------------------------
void CGameRules::ProcessClientExplosionScreenFX(const ExplosionInfo &explosionInfo)
{
	IActor *pClientActor = g_pGame->GetIGameFramework()->GetClientActor();
	if (pClientActor)
	{
		//Distance
		float dist = (pClientActor->GetEntity()->GetWorldPos() - explosionInfo.pos).len();

		//Is the explosion in Player's FOV (let's suppose the FOV a bit higher, like 80)
		CActor *pActor = (CActor *)pClientActor;
		SMovementState state;
		if (IMovementController *pMV = pActor->GetMovementController())
		{
			pMV->GetMovementState(state);
		}

		Vec3 eyeToExplosion = explosionInfo.pos - state.eyePosition;
		eyeToExplosion.Normalize();
		bool inFOV = (state.eyeDirection.Dot(eyeToExplosion) > 0.68f);
		
		// if in a vehicle eyeDirection is wrong
		if(pActor && pActor->GetLinkedVehicle())
		{
			Vec3 eyeDir = static_cast<CPlayer*>(pActor)->GetVehicleViewDir();
			inFOV = (eyeDir.Dot(eyeToExplosion) > 0.68f);
		}

		//All explosions have radial blur (default 30m radius, to make Sean happy =))
		float maxBlurDistance = (explosionInfo.maxblurdistance>0.0f)?explosionInfo.maxblurdistance:30.0f;
		if (maxBlurDistance>0.0f && g_pGameCVars->g_radialBlur>0.0f && m_explosionScreenFX && explosionInfo.radius>0.5f)
		{		
			if (inFOV && dist < maxBlurDistance)
			{
				ray_hit hit;
				int col = gEnv->pPhysicalWorld->RayWorldIntersection(explosionInfo.pos , -eyeToExplosion*dist, ent_static | ent_terrain, rwi_stop_at_pierceable|rwi_colltype_any, &hit, 1);

				//If there was no obstacle between flashbang grenade and player
				if(!col)
				{
					if (CScreenEffects* pSE = pActor->GetScreenEffects())
					{
						float blurRadius = (-1.0f/maxBlurDistance)*dist + 1.0f;

						gEnv->p3DEngine->SetPostEffectParam("FilterRadialBlurring_Radius", blurRadius);
						gEnv->p3DEngine->SetPostEffectParam("FilterRadialBlurring_Amount", 1.0f);

						IBlendedEffect *pBlur	= CBlendedEffect<CPostProcessEffect>::Create(CPostProcessEffect(pClientActor->GetEntityId(),"FilterRadialBlurring_Amount", 0.0f));
						IBlendType   *pLinear = CBlendType<CLinearBlend>::Create(CLinearBlend(1.0f));
						pSE->StartBlend(pBlur, pLinear, 1.0f, CScreenEffects::eSFX_GID_RBlur);
						pSE->SetUpdateCoords("FilterRadialBlurring_ScreenPosX","FilterRadialBlurring_ScreenPosY", explosionInfo.pos);
					}

					float distAmp = 1.0f - (dist / maxBlurDistance);
					if (gEnv->pInput) 
						gEnv->pInput->ForceFeedbackEvent( SFFOutputEvent(eDI_XI, eFF_Rumble_Basic, 0.5f, distAmp*3.0f, 0.0f));
				}
			}
		}

		//Flashbang effect 
		if(dist<explosionInfo.radius && inFOV &&
			(!strcmp(explosionInfo.effect_class,"flashbang") || !strcmp(explosionInfo.effect_class,"FlashbangAI")))
		{
			ray_hit hit;
			int col = gEnv->pPhysicalWorld->RayWorldIntersection(explosionInfo.pos , -eyeToExplosion*dist, ent_static | ent_terrain, rwi_stop_at_pierceable|rwi_colltype_any, &hit, 1);

			//If there was no obstacle between flashbang grenade and player
			if(!col)
			{
				float power = explosionInfo.flashbangScale;
				power *= max(0.0f, 1 - (dist/explosionInfo.radius));
				float lookingAt = (eyeToExplosion.Dot(state.eyeDirection.normalize()) + 1)*0.5f;
				power *= lookingAt;

				SAFE_GAMEAUDIO_SOUNDMOODS_FUNC(AddSoundMood(SOUNDMOOD_EXPLOSION,MIN(power*40.0f,100.0f)));

				gEnv->p3DEngine->SetPostEffectParam("Flashbang_Time", 1.0f + (power * 4));
				gEnv->p3DEngine->SetPostEffectParam("FlashBang_BlindAmount",explosionInfo.blindAmount);
				gEnv->p3DEngine->SetPostEffectParam("Flashbang_DifractionAmount", (power * 2));
				gEnv->p3DEngine->SetPostEffectParam("Flashbang_Active", 1);
			}
		}
		else if(inFOV && (dist < explosionInfo.radius))
		{
			if (explosionInfo.damage>10.0f || explosionInfo.pressure>100.0f)
			{
				//Add some angular impulse to the client actor depending on distance, direction...
				float dt = (1.0f - dist/explosionInfo.radius);
				dt = dt * dt;
				float angleZ = gf_PI*0.15f*dt;
				float angleX = gf_PI*0.15f*dt;

				pActor->AddAngularImpulse(Ang3(Random(-angleX*0.5f,angleX),0.0f,Random(-angleZ,angleZ)),0.0f,dt*2.0f);
			}
		}


		float fDist2=(pClientActor->GetEntity()->GetWorldPos()-explosionInfo.pos).len2();
		if (fDist2<250.0f*250.0f)
		{		
			if (fDist2<sqr(SAFE_GAMEAUDIO_BATTLESTATUS_FUNC_RET(GetBattleRange())))
				SAFE_GAMEAUDIO_BATTLESTATUS_FUNC(TickBattleStatus(1.0f));
		}
	}

}
bool CIntersectionAssistanceUnit::GetHighestScoringLastKnownGoodPosition( const QuatT& baseOrientation, QuatT& outQuat ) const
{
    bool bFlippedIsBest = false;

    if(!m_lastKnownGoodPositions.empty())
        {
            // Higher is better
            float fBestScore = 0.0f;
            int bestIndex = -1;
            Vec3 vBaseUpDir = baseOrientation.q.GetColumn2().GetNormalized();
            for(uint8 i = 0; i < m_lastKnownGoodPositions.size(); ++i)
                {
                    const QuatT& qLastKnownGood = m_lastKnownGoodPositions[i];
                    if(IsPositionWithinAcceptedLimits(qLastKnownGood.t, baseOrientation.t, kDistanceTolerance))
                        {
                            // Generate [0.0f,1.0f] score for distance
                            const Vec3 distVec = (qLastKnownGood.t - baseOrientation.t);

                            const float length = max(distVec.GetLengthFast(),0.0001f);
                            const float distanceScore = max(1.0f - (length * kInverseDistanceTolerance) * kDistanceWeight, 0.0f);

                            Vec3 vUpDir		 = qLastKnownGood.q.GetColumn2();

                            const float regularOrientationScore = vBaseUpDir.Dot(vUpDir);
                            const float flippedOrientationScore = vBaseUpDir.Dot(-vUpDir);

                            float orientationScore = max(regularOrientationScore, flippedOrientationScore);
                            orientationScore *= kOrientationWeight;

                            const float fCandidateScore = distanceScore + orientationScore;

#ifndef _RELEASE
                            if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled == 2)
                                {
                                    CryWatch("[INDEX(%d)] : D[%.3f] O[%.3f] T[%.3f] (%s)", i, distanceScore, orientationScore, fCandidateScore, flippedOrientationScore > regularOrientationScore ? "*F*" : "R");
                                }
#endif //#ifndef _RELEASE

                            if(fCandidateScore > fBestScore)
                                {
                                    bestIndex	 = i;
                                    fBestScore = fCandidateScore;
                                    bFlippedIsBest = (flippedOrientationScore > regularOrientationScore);
                                }
                        }
                }

            if(bestIndex >= 0)
                {
                    outQuat = m_lastKnownGoodPositions[bestIndex];
                    if(bFlippedIsBest)
                        {
                            Matrix34 wMat(outQuat);
                            Vec3 vFlippedUpDir = -outQuat.q.GetColumn2().GetNormalized();
                            Vec3 vForwardDir	 = outQuat.q.GetColumn1().GetNormalized();
                            Vec3 vSideDir			 = -outQuat.q.GetColumn0().GetNormalized();
                            Matrix34 wFlippedMat;
                            wFlippedMat = Matrix34::CreateFromVectors(vSideDir, vForwardDir, vFlippedUpDir, wMat.GetTranslation());
                            outQuat = QuatT(wFlippedMat);

                            // Adjust pos (rotating around OOBB centre effectively)
                            const IEntity* pSubjectEntity = gEnv->pEntitySystem->GetEntity(m_subjectEntityId);
                            if(pSubjectEntity)
                                {
                                    AABB entAABB;
                                    OBB  entOBB;
                                    pSubjectEntity->GetLocalBounds(entAABB);
                                    entOBB.SetOBBfromAABB(Quat(IDENTITY), entAABB);

                                    Vec3 Centre = wMat.TransformPoint(entOBB.c);
                                    Vec3 toCentre = Centre - outQuat.t;
                                    outQuat.t += (toCentre * 2.0f);
                                }
                        }

#ifndef _RELEASE
                    if(g_pGameCVars->pl_pickAndThrow.intersectionAssistDebugEnabled == 2)
                        {
                            m_currentBestIndex = bestIndex;
                            CryWatch("[BEST INDEX] : %d", bestIndex);
                        }
#endif // ifndef _RELEASE

                    return true;
                }
        }

#ifndef _RELEASE
    m_currentBestIndex = -1;
#endif // ifndef _RELEASE

    return false;
}
//////////////////////////////////////////////////////////////////////////
// IsMountedWeaponUsableWithTarget
// A piece of game-code moved from CryAction when scriptbind_AI moved to the AI system
//////////////////////////////////////////////////////////////////////////
int CScriptBind_Game::IsMountedWeaponUsableWithTarget(IFunctionHandler *pH)
{
	int paramCount = pH->GetParamCount();
	if(paramCount<2)
	{
		GameWarning("%s: too few parameters.", __FUNCTION__);
		return pH->EndFunction();
	}

	GET_ENTITY(1);

	if(!pEntity)
	{
		GameWarning("%s: wrong entity id in parameter 1.", __FUNCTION__);
		return pH->EndFunction();
	}

	IAIObject* pAI = pEntity->GetAI();
	if (!pAI)
	{
		GameWarning("%s: Entity '%s' does not have AI.",__FUNCTION__,  pEntity->GetName());
		return pH->EndFunction();
	}

	EntityId itemEntityId;
	ScriptHandle hdl2;

	if(!pH->GetParam(2,hdl2))
	{
		GameWarning("%s: wrong parameter 2 format.", __FUNCTION__);
		return pH->EndFunction();
	}

	itemEntityId = (EntityId)hdl2.n;

	if (!itemEntityId)
	{
		GameWarning("%s: wrong entity id in parameter 2.", __FUNCTION__);
		return pH->EndFunction();
	}
	
	IGameFramework *pGameFramework = gEnv->pGame->GetIGameFramework();
	IItem* pItem = pGameFramework->GetIItemSystem()->GetItem(itemEntityId);
	if (!pItem)
	{
		//gEnv->pAISystem->Warning("<CScriptBind> ", "entity in parameter 2 is not an item/weapon");
		GameWarning("%s: entity in parameter 2 is not an item/weapon.", __FUNCTION__);
		return pH->EndFunction();
	}

	float minDist = 7;
	bool bSkipTargetCheck = false;
	Vec3 targetPos(ZERO);

	if(paramCount > 2)
	{
		for(int i=3;i <= paramCount ; i++)
		{
			if(pH->GetParamType(i) == svtBool)
				pH->GetParam(i,bSkipTargetCheck);
			else if(pH->GetParamType(i) == svtNumber)
				pH->GetParam(i,minDist);
			else if(pH->GetParamType(i) == svtObject)
				pH->GetParam(i,targetPos);
		}
	}

	IAIActor* pAIActor = CastToIAIActorSafe(pAI);
	if (!pAIActor)
	{
		GameWarning("%s: entity '%s' in parameter 1 is not an AI actor.", __FUNCTION__, pEntity->GetName());
		return pH->EndFunction();
	}


	IEntity* pItemEntity = pItem->GetEntity();
	if(!pItemEntity)
		return pH->EndFunction();


	if(!pItem->GetOwnerId())
	{
		// weapon is not used, check if it is on a vehicle
		IEntity* pParentEntity = pItemEntity->GetParent();
		if(pParentEntity)
		{
			IAIObject* pParentAI = pParentEntity->GetAI();
			if(pParentAI && pParentAI->GetAIType()==AIOBJECT_VEHICLE)
			{
				// (MATT) Feature was cut and code was tricky, hence ignore weapons in vehicles  {2008/02/15:11:08:51}
				return pH->EndFunction();
			}
		}
	}
	else if( pItem->GetOwnerId()!= pEntity->GetId()) // item is used by someone else?
		return pH->EndFunction(false);

	// check target
	if(bSkipTargetCheck)
		return pH->EndFunction(true);

	IAIObject* pTarget = pAIActor->GetAttentionTarget();
	if(targetPos.IsZero())
	{
		if(!pTarget)
			return pH->EndFunction();
		targetPos = pTarget->GetPos();
	}

	Vec3 targetDir(targetPos - pItemEntity->GetWorldPos());
	Vec3 targetDirXY(targetDir.x, targetDir.y, 0);

	float length2D = targetDirXY.GetLength();
	if(length2D < minDist || length2D<=0)
		return pH->EndFunction();

	targetDirXY /= length2D;//normalize

	IWeapon* pWeapon = pItem->GetIWeapon(); 
	bool vehicleGun = pWeapon && pWeapon->GetHostId();

	if (!vehicleGun)
	{
		Vec3 mountedAngleLimits(pItem->GetMountedAngleLimits());

		float yawRange = DEG2RAD(mountedAngleLimits.z);
		if(yawRange > 0 && yawRange < gf_PI)
		{
			float deltaYaw = pItem->GetMountedDir().Dot(targetDirXY);
			if(deltaYaw < cosf(yawRange))
				return pH->EndFunction(false);
		}

		float minPitch = DEG2RAD(mountedAngleLimits.x);
		float maxPitch = DEG2RAD(mountedAngleLimits.y);

		//maxPitch = (maxPitch - minPitch)/2;
		//minPitch = -maxPitch;

		float pitch = atanf(targetDir.z / length2D);

		if ( pitch < minPitch || pitch > maxPitch )
			return pH->EndFunction(false);
	}

	if(pTarget)
	{
		IEntity* pTargetEntity = pTarget->GetEntity();
		if(pTargetEntity)
		{
			// check target distance and where he's going
			IPhysicalEntity *phys = pTargetEntity->GetPhysics();
			if(phys)
			{
				pe_status_dynamics	dyn;
				phys->GetStatus(&dyn);
				Vec3 velocity ( dyn.v);
				velocity.z = 0;

				float speed = velocity.GetLength2D();
				if(speed>0)
				{
					//velocity /= speed;
					if(length2D< minDist * 0.75f && velocity.Dot(targetDirXY)<=0)
						return pH->EndFunction(false);
				}
			}
		}
	}
	return pH->EndFunction(true);

}
예제 #30
0
void CNetPlayerInput::InitialiseInterpolation(f32 netPosDist, const Vec3 &desPosOffset, const Vec3 &desiredVelocity, const CTimeValue	&curTime)
{
	m_newInterpolation = false;

	//--- Don't trigger a fresh interpolation for minor adjustments if the player is on the ground & stopping or 
	//--- would be moving against the local player's velocity
	bool isStatic = (m_pPlayer->GetActorStats()->onGround > 0.1f) && ((m_netDesiredSpeed < k_staticSpeed) || (desPosOffset.Dot(desiredVelocity) < 0.0f));
	const float minDist = isStatic ? k_minDistStatic : k_minDistMoving;

	if (g_pGameCVars->pl_debugInterpolation)
	{
		CryWatch("NewInterp NetPosDist: %f MinDist: %f)", netPosDist, minDist);
	}

	m_netLastUpdate = curTime;

	if (netPosDist > minDist)
	{
		if (m_netDesiredSpeed > k_staticSpeed)
		{
			m_initialDir = desiredVelocity / m_netDesiredSpeed;
		}
		else
		{
			m_initialDir = desPosOffset / netPosDist;
		}

		// Always set position when an update is first received.
		m_passedNetPos = false;
		m_passedPredictionPos = false;
	}
}