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); }
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 }
//------------------------------------------------------------------ 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(); } }
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; }
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 ); }
// ******************************************************************************** // // 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(); }
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; }
//------------------------------------------------------------------------ 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); }
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); }
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; }
// 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 ); }
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; } } }
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; }
//---------------------------------------------------------------------------- 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; }
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); }
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; } }
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); }
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; }
//-------------------------------------------------------------------------------------------------- // 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); } } } } } }//-------------------------------------------------------------------------------------------------
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)); }
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); }
//-------------------------------------------------------------------------------------------------- // 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); } } } } }//-------------------------------------------------------------------------------------------------
//------------------------------------------- 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); }
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; } }