void CPlayerStateSwim_WaterTestProxy::DebugDraw(const CPlayer& player, const Vec3& referencePosition) { // DEBUG RENDERING const SPlayerStats& stats = *player.GetActorStats(); const bool debugSwimming = (g_pGameCVars->cl_debugSwimming != 0); if (debugSwimming && (m_playerWaterLevel > -10.0f) && (m_playerWaterLevel < 10.0f)) { const Vec3 surfacePosition(referencePosition.x, referencePosition.y, m_waterLevel); const Vec3 vRight(player.GetBaseQuat().GetColumn0()); const static ColorF referenceColor(1,1,1,1); const static ColorF surfaceColor1(0,0.5f,1,1); const static ColorF surfaceColor0(0,0,0.5f,0); const static ColorF bottomColor(0,0.5f,0,1); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(referencePosition, 0.1f, referenceColor); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(referencePosition, surfaceColor1, surfacePosition, surfaceColor1, 2.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(surfacePosition, 0.2f, surfaceColor1); gEnv->pRenderer->DrawLabel(referencePosition + vRight * 0.5f, 1.5f, "WaterLevel %3.2f (Head underwater: %d)", m_playerWaterLevel, m_headUnderwater ? 1 : 0); const static int lines = 16; const static float radius0 = 0.5f; const static float radius1 = 1.0f; const static float radius2 = 2.0f; for (int i = 0; i < lines; ++i) { float radians = ((float)i / (float)lines) * gf_PI2; Vec3 offset0(radius0 * cos_tpl(radians), radius0 * sin_tpl(radians), 0); Vec3 offset1(radius1 * cos_tpl(radians), radius1 * sin_tpl(radians), 0); Vec3 offset2(radius2 * cos_tpl(radians), radius2 * sin_tpl(radians), 0); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(surfacePosition+offset0, surfaceColor0, surfacePosition+offset1, surfaceColor1, 2.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(surfacePosition+offset1, surfaceColor1, surfacePosition+offset2, surfaceColor0, 2.0f); } if (m_bottomLevel > 0.0f) { const Vec3 bottomPosition(referencePosition.x, referencePosition.y, m_bottomLevel); gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(referencePosition, bottomColor, bottomPosition, bottomColor, 2.0f); gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(bottomPosition, 0.2f, bottomColor); gEnv->pRenderer->DrawLabel(bottomPosition + Vec3(0,0,0.5f) - vRight * 0.5f, 1.5f, "BottomDepth %3.3f", m_waterLevel - m_bottomLevel); } } }
void UpdateLookTarget() { const SLookAroundParams& params = GetParams(); //--- TODO! Context use of random number generator! float yaw = cry_random(params.yawMin, params.yawMax); float pitch = cry_random(params.pitchMin, params.pitchMax); m_lookOffset.Set(sin_tpl(yaw), cos_tpl(yaw), 0.0f); m_lookAroundTime = cry_random(params.timeMin, params.timeMax); }
static void DrawDisc(const Vec3& center, Vec3 axis, float innerRadius, float outerRadius, const ColorB& innerColor, const ColorB& outerColor) { axis.NormalizeSafe(Vec3Constants<float>::fVec3_OneZ); Vec3 u = ((axis * Vec3Constants<float>::fVec3_OneZ) > 0.5f) ? Vec3Constants<float>::fVec3_OneY : Vec3Constants<float>::fVec3_OneZ; Vec3 v = u.cross(axis); u = v.cross(axis); float sides = ceil_tpl(3.0f * (float)g_PI * outerRadius); //sides = 20.0f; float step = 1.0f / sides; for (float i = 0.0f; i < 0.99f; i += step) { float a0 = i * 2.0f * (float)g_PI; float a1 = (i+step) * 2.0f * (float)g_PI; Vec3 i0 = center + innerRadius * (u*cos_tpl(a0) + v*sin_tpl(a0)); Vec3 i1 = center + innerRadius * (u*cos_tpl(a1) + v*sin_tpl(a1)); Vec3 o0 = center + outerRadius * (u*cos_tpl(a0) + v*sin_tpl(a0)); Vec3 o1 = center + outerRadius * (u*cos_tpl(a1) + v*sin_tpl(a1)); gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangle(i0, innerColor, i1, innerColor, o1, outerColor); gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangle(i0, innerColor, o1, outerColor, o0, outerColor); } }
void CRecoil::UpdateRecoil(float recoilScale, float maxRecoil, bool weaponFired, bool weaponFiring, float frameTime) { if (m_recoil_time > 0.0f) { m_recoil_time -= frameTime; m_recoil += (m_attack * frameTime) / m_recoilParams.recoil_time; } const bool isFiring = m_singleShot ? weaponFired : weaponFiring; const float decay = isFiring ? m_recoilParams.decay : m_recoilParams.end_decay; const float frameDecay = (float)__fsel(-decay, 0.0f, frameTime * recoilScale * maxRecoil * __fres(decay+FLT_EPSILON)); m_recoil = clamp(m_recoil - frameDecay, 0.0f, maxRecoil); const float t = (float)__fsel(-maxRecoil, 0.0f, m_recoil * __fres(maxRecoil+FLT_EPSILON)); const Vec3 new_offset = Vec3( m_recoil_dir.x * sin_tpl(DEG2RAD(m_recoilParams.max.x)), m_recoil_dir.y * sin_tpl(DEG2RAD(m_recoilParams.max.y)), m_recoil_dir.z) * t; m_recoil_offset = (new_offset * 0.66f) + (m_recoil_offset * 0.33f); CRecoilDebugDraw::DebugRecoil(t, m_recoil_offset); }
void CBirdsFlock::UpdateLandingPoints() { int numPoints = m_boids.size() * 3 / 2; if (m_LandingPoints.size() < (size_t)numPoints) { if (!m_landCollisionInfo.IsRequestingRayCast()) { float maxradius = m_bc.fSpawnRadius * 0.6f; Vec3 origin(m_bc.flockPos); float angle = Boid::Frand() * gf_PI; float radius = (Boid::Frand() + 1) / 2 * maxradius; origin += Vec3(cos_tpl(angle) * radius, sin_tpl(angle) * radius, 5.f); Vec3 vDir = Vec3(0, 0, -10); m_landCollisionInfo.QueueRaycast(m_pEntity->GetId(), origin, vDir, &m_landCollisionCallback); } } }
bool CPlayerStateUtil::IsMovingForward( const CPlayer& player, const SActorFrameMovementParams& movement ) { const float fSpeedFlatSelector = player.GetActorStats()->speedFlat - 0.1f; bool movingForward = (fSpeedFlatSelector > 0.1f); if (!gEnv->bMultiplayer || player.IsClient()) { // IsMovingForward() doesn't return particularly reliable results for client players in MP, I think because of interpolation innacuracies on the Y velocity. this was causing client players to // incorrectly report that they're no longer moving forwards, whereas all that had happened was they had stopped sprinting - and this in turn was messing up the MP sprint stamina regeneration delays. // client players have also been seen to stop sprinting due to turning lightly, whereas on their local machine they were still sprinting fine... // so i've tried changing it so IsMovingForward() is only taken into account on local clients (and in SP!). [tlh] const float thresholdSinAngle = sin_tpl((3.141592f * 0.5f) - DEG2RAD(g_pGameCVars->pl_power_sprint.foward_angle)); const float currentSinAngle = movement.desiredVelocity.y; movingForward = movingForward && (currentSinAngle > thresholdSinAngle); } return movingForward; }
void CMountedGunController::Update(EntityId mountedGunID, float frameTime) { CRY_ASSERT_MESSAGE(m_pControlledPlayer, "Controlled player not initialized"); CItem* pMountedGun = static_cast<CItem*>(gEnv->pGame->GetIGameFramework()->GetIItemSystem()->GetItem(mountedGunID)); bool canUpdateMountedGun = (pMountedGun != NULL) && (pMountedGun->GetStats().mounted); if (canUpdateMountedGun) { IMovementController * pMovementController = m_pControlledPlayer->GetMovementController(); assert(pMovementController); SMovementState info; pMovementController->GetMovementState(info); IEntity* pMountedGunEntity = pMountedGun->GetEntity(); const Matrix34& lastMountedGunWorldTM = pMountedGunEntity->GetWorldTM(); Vec3 desiredAimDirection = info.aimDirection.GetNormalized(); // AI can switch directions too fast, prevent snapping if(!m_pControlledPlayer->IsPlayer()) { const Vec3 currentDir = lastMountedGunWorldTM.GetColumn1(); const float dot = clamp(currentDir.Dot(desiredAimDirection), -1.0f, 1.0f); const float reqAngle = cry_acosf(dot); const float maxRotSpeed = 2.0f; const float maxAngle = frameTime * maxRotSpeed; if(fabs(reqAngle) > maxAngle) { const Vec3 axis = currentDir.Cross(desiredAimDirection); if(axis.GetLengthSquared() > 0.001f) // current dir and new dir are enough different { desiredAimDirection = currentDir.GetRotated(axis.GetNormalized(),sgn(reqAngle)*maxAngle); } } } bool isUserClient = m_pControlledPlayer->IsClient(); IEntity* pMountedGunParentEntity = pMountedGunEntity->GetParent(); IVehicle *pVehicle = NULL; if(pMountedGunParentEntity && m_pControlledPlayer) pVehicle = m_pControlledPlayer->GetLinkedVehicle(); CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem(); //For client update always, for others only when there is notable change if (!pVehicle && (isUserClient || (!desiredAimDirection.IsEquivalent(lastMountedGunWorldTM.GetColumn1(), 0.003f)))) { Quat rotation = Quat::CreateRotationVDir(desiredAimDirection, 0.0f); pMountedGunEntity->SetRotation(rotation); if (isUserClient && pRecordingSystem) { // Only record the gun position if you're using the gun. pRecordingSystem->OnMountedGunRotate(pMountedGunEntity, rotation); } } const Vec3 vInitialAimDirection = GetMountDirection(pMountedGun, pMountedGunParentEntity); assert( vInitialAimDirection.IsUnit() ); //Adjust gunner position and animations UpdateGunnerLocation(pMountedGun, pMountedGunParentEntity, vInitialAimDirection); const float aimrad = Ang3::CreateRadZ(Vec2(vInitialAimDirection),Vec2(-desiredAimDirection)); const float pitchLimit = sin_tpl(DEG2RAD(30.0f)); const float animHeight = fabs_tpl(clamp(desiredAimDirection.z * (float)__fres(pitchLimit), -1.0f, 1.0f)); const float aimUp = (float)__fsel(-desiredAimDirection.z, 0.0f, animHeight); const float aimDown = (float)__fsel(desiredAimDirection.z, 0.0f, animHeight); if (pRecordingSystem) { pRecordingSystem->OnMountedGunUpdate(m_pControlledPlayer, aimrad, aimUp, aimDown); } if(!m_pControlledPlayer->IsThirdPerson()) { UpdateFirstPersonAnimations(pMountedGun, desiredAimDirection); } if(m_pMovementAction) { const float aimUpParam = aimUp; const float aimDownParam = aimDown; const float aimMovementParam = CalculateAnimationTime(aimrad); m_pMovementAction->SetParam(MountedGunCRCs.aimUpParam, aimUpParam); m_pMovementAction->SetParam(MountedGunCRCs.aimDownParam, aimDownParam); m_pMovementAction->SetParam(MountedGunCRCs.aimMovementParam, aimMovementParam); } UpdateIKMounted(pMountedGun); } }
void CAnimatedCharacter::SetDesiredLocalLocation( ISkeletonAnim* pSkeletonAnim, const QuatT& desiredLocalLocation, float fDeltaTime) { CRY_ASSERT(desiredLocalLocation.IsValid()); { uint32 NumAnimsInQueue = pSkeletonAnim->GetNumAnimsInFIFO(0); uint32 nMaxActiveInQueue=MAX_EXEC_QUEUE; if (nMaxActiveInQueue>NumAnimsInQueue) nMaxActiveInQueue=NumAnimsInQueue; if (NumAnimsInQueue>nMaxActiveInQueue) NumAnimsInQueue=nMaxActiveInQueue; uint32 active=0; for (uint32 a=0; a<NumAnimsInQueue; a++) { const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a); active += anim.IsActivated() ? 1 : 0; } if (active>nMaxActiveInQueue) active=nMaxActiveInQueue; nMaxActiveInQueue=active; const SParametricSampler *pLMG = NULL; for (int32 a=nMaxActiveInQueue-1; (a >= 0) && !pLMG; --a) { const CAnimation& anim = pSkeletonAnim->GetAnimFromFIFO(0,a); pLMG = anim.GetParametricSampler(); } } const Vec3 dir = desiredLocalLocation.GetColumn1(); float turnAngle = atan2f(-dir.x, dir.y); float turnSpeed = turnAngle / fDeltaTime; const Vec2 deltaVector(desiredLocalLocation.t.x, desiredLocalLocation.t.y); const float travelDist = deltaVector.GetLength(); const Vec2 deltaDir = (travelDist > 0.0f) ? (deltaVector / travelDist) : Vec2(0,0); float travelAngle = (deltaDir.x == 0.0f && deltaDir.y == 0.0f ? 0.0f : atan2f(-deltaDir.x, deltaDir.y)); float travelSpeed; if (gEnv->bMultiplayer) { travelSpeed = travelDist / fDeltaTime; } else { const float cosGroundSlope = fabsf(cosf(m_fGroundSlopeMoveDirSmooth)); travelSpeed = (cosGroundSlope > FLT_EPSILON) ? (travelDist / (fDeltaTime * cosGroundSlope)) : (travelDist / fDeltaTime); } // TravelAngle smoothing { const Vec2 newStrafe = Vec2(-sin_tpl(travelAngle), cos_tpl(travelAngle)); if (CAnimationGraphCVars::Get().m_enableTurnAngleSmoothing) { SmoothCD(m_fDesiredStrafeSmoothQTX, m_fDesiredStrafeSmoothRateQTX, fDeltaTime, newStrafe, 0.10f); } else { m_fDesiredStrafeSmoothQTX=newStrafe; m_fDesiredStrafeSmoothRateQTX.zero(); } travelAngle = Ang3::CreateRadZ(Vec2(0,1),m_fDesiredStrafeSmoothQTX); } const bool modulateTurnSpeedByTravelAngle = true; if (modulateTurnSpeedByTravelAngle) { static float minimum = DEG2RAD(10.0f); // do not change turnSpeed when travelAngle is below this static float maximum = DEG2RAD(40.0f); // force turnspeed to zero when travelAngle is above this const float turnSpeedScale = 1.0f - clamp_tpl( fabsf(travelAngle) - minimum, 0.0f, maximum - minimum ) / ( maximum - minimum ); turnSpeed *= turnSpeedScale; } // TurnSpeed smoothing { if (CAnimationGraphCVars::Get().m_enableTurnSpeedSmoothing) { SmoothCD(m_fDesiredTurnSpeedSmoothQTX, m_fDesiredTurnSpeedSmoothRateQTX, fDeltaTime, turnSpeed, 0.40f); } else { m_fDesiredTurnSpeedSmoothQTX = turnSpeed; m_fDesiredTurnSpeedSmoothRateQTX = 0.0f; } } // TravelSpeed smoothing { if (CAnimationGraphCVars::Get().m_enableTravelSpeedSmoothing) { SmoothCD(m_fDesiredMoveSpeedSmoothQTX, m_fDesiredMoveSpeedSmoothRateQTX, fDeltaTime, travelSpeed, 0.04f); } else { m_fDesiredMoveSpeedSmoothQTX = travelSpeed; m_fDesiredMoveSpeedSmoothRateQTX = 0.0f; } } SetMotionParam(pSkeletonAnim, eMotionParamID_TravelSpeed, m_fDesiredMoveSpeedSmoothQTX); SetMotionParam(pSkeletonAnim, eMotionParamID_TurnSpeed, m_fDesiredTurnSpeedSmoothQTX * CAnimationGraphCVars::Get().m_turnSpeedParamScale); SetMotionParam(pSkeletonAnim, eMotionParamID_TravelAngle, travelAngle); // eMotionParamID_TravelSlope SetMotionParam(pSkeletonAnim, eMotionParamID_TurnAngle, turnAngle); // eMotionParamID_TravelDist SetMotionParam(pSkeletonAnim, eMotionParamID_StopLeg, 0); }
//------------------------------------------------------------------------ void CScriptControlledPhysics::OnPostStep(EventPhysPostStep *pPostStep) { pe_action_set_velocity av; const bool moving = m_moving; const bool rotating = m_rotating; const float deltaTime = pPostStep->dt; if (m_moving) { const Vec3 current = pPostStep->pos; const Vec3 target = m_moveTarget; const Vec3 delta = target - current; const float distanceSq = delta.len2(); if (distanceSq <= sqr(0.025f) || (delta.dot(m_lastVelocity) < 0.0f)) { m_speed = 0.0f; m_moving = false; m_lastVelocity.zero(); pPostStep->pos = target; av.v = ZERO; } else { float velocity = m_speed; float acceleration = m_acceleration; Vec3 direction = delta; const float distanceToEnd = direction.NormalizeSafe(); // Accelerate velocity = std::min(velocity + acceleration * deltaTime, m_maxSpeed); // Calculate acceleration and time needed to stop const float accelerationNeededToStop = (-(velocity*velocity) / distanceToEnd) / 2; if (fabsf(accelerationNeededToStop) > 0.0f) { const float timeNeededToStop = sqrtf((distanceToEnd / 0.5f) / fabsf(accelerationNeededToStop)); if (timeNeededToStop < m_stopTime) { acceleration = accelerationNeededToStop; } } // Prevent overshooting if ((velocity * deltaTime) > distanceToEnd) { const float multiplier = distanceToEnd / fabsf(velocity * deltaTime); velocity *= multiplier; acceleration *= multiplier; } m_acceleration = acceleration; m_speed = velocity; m_lastVelocity = direction * velocity; av.v = direction * velocity; } } if (m_rotating) { Quat current=pPostStep->q; Quat target=m_rotationTarget; Quat rotation=target*!current; float angle=acos_tpl(CLAMP(rotation.w, -1.0f, 1.0f))*2.0f; float original=angle; if (angle>gf_PI) angle=angle-gf_PI2; else if (angle<-gf_PI) angle=angle+gf_PI2; if (fabs_tpl(angle)<0.01f) { m_rotationSpeed=0.0f; m_rotating=false; pPostStep->q=m_rotationTarget; av.w=ZERO; } else { float a=m_rotationSpeed/m_rotationStopTime; float d=m_rotationSpeed*m_stopTime-0.5f*a*m_rotationStopTime*m_rotationStopTime; if (fabs_tpl(angle)<d+0.001f) m_rotationAcceleration=(angle-m_rotationSpeed*m_rotationStopTime)/(m_rotationStopTime*m_rotationStopTime); m_rotationSpeed=m_rotationSpeed+sgn(angle)*m_rotationAcceleration*deltaTime; if (fabs_tpl(m_rotationSpeed*deltaTime)>fabs_tpl(angle)) m_rotationSpeed=angle/deltaTime; else if (fabs_tpl(m_rotationSpeed)<0.001f) m_rotationSpeed=sgn(m_rotationSpeed)*0.001f; else if (fabs_tpl(m_rotationSpeed)>=m_rotationMaxSpeed) { m_rotationSpeed=sgn(m_rotationSpeed)*m_rotationMaxSpeed; m_rotationAcceleration=0.0f; } } if(fabs_tpl(angle)>=0.001f) av.w=(rotation.v/sin_tpl(original*0.5f)).normalized(); av.w*=m_rotationSpeed; } if (moving || rotating) { if (IPhysicalEntity *pPE=GetEntity()->GetPhysics()) pPE->Action(&av, 1); } /* if ((moving && !m_moving) || (rotating && !m_rotating)) GetEntity()->SetWorldTM(Matrix34::Create(GetEntity()->GetScale(), pPostStep->q, pPostStep->pos)); */ }