コード例 #1
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
void CPlayerStateJump::Land( CPlayer &player, const bool isHeavyWeapon, float frameTime )
{
	if(gEnv->bMultiplayer && IsJumping())
	{
		m_jumpLock = min(g_pGameCVars->pl_jump_baseTimeAddedPerJump + (m_jumpLock * g_pGameCVars->pl_jump_currentTimeMultiplierOnJump), g_pGameCVars->pl_jump_maxTimerValue);
	}

	const float fHeightofEntity = player.GetEntity()->GetWorldPos().z;

	if (player.IsClient())
	{
		CPlayerStateUtil::ApplyFallDamage( player, m_startFallingHeight, fHeightofEntity );
	}

	// TODO: Physics sync.
	const float fallSpeed = player.m_stats.fallSpeed;
	Landed(player, isHeavyWeapon, fabsf(player.GetActorPhysics().velocityDelta.z)); // fallspeed might be incorrect on a dedicated server (pos is synced from client, but also smoothed).

	player.m_stats.wasHit = false;

	SetJumpState(player, JState_None);
	
	if(player.m_stats.fallSpeed)
	{
		player.m_stats.fallSpeed = 0.0f;

		const float worldWaterLevel = player.m_playerStateSwim_WaterTestProxy.GetWaterLevel();
		if(fHeightofEntity < worldWaterLevel)
		{
			player.CreateScriptEvent("jump_splash", worldWaterLevel-fHeightofEntity);
		}

	}
}
コード例 #2
0
ファイル: PlayerStateUtil.cpp プロジェクト: Xydrel/Infected
bool CPlayerStateUtil::ShouldJump( CPlayer& player, const SActorFrameMovementParams& movement )
{
	const bool allowJump = movement.jump && !player.IsJumping(); //m_playerStateJump.IsJumping();
 	if (allowJump)
	{
		// TODO: We need a TryJump (stephenn).

		// This is needed when jumping while standing directly under something that causes an immediate land,
		// before and without even being airborne for one frame.
		// PlayerMovement set m_stats.onGround=0.0f when the jump is triggered,
		// which prevents the on ground timer from before the jump to be inherited
		// and incorrectly and prematurely used to identify landing in MP.

		const SPlayerStats& stats = *player.GetActorStats();
		const SActorPhysics& actorPhysics = player.GetActorPhysics();
		const float fUnconstrainedZ = actorPhysics.velocityUnconstrained.z;
		bool jumpFailed = (stats.onGround > 0.0f) && (fUnconstrainedZ <= 0.0f);

		const float onGroundTime = 0.2f;
		if( ((stats.onGround > onGroundTime) || player.IsRemote()) ) // && !jumpFailed )
		{
			return true;
		}
		else
		{
			CCCPOINT_IF(true, PlayerMovement_PressJumpWhileNotAllowedToJump);
		}
	}
	return false;
}
コード例 #3
0
ファイル: PlayerStateSwim.cpp プロジェクト: aronarts/FireNET
bool CPlayerStateSwim::DetectJump( CPlayer& player, const SActorFrameMovementParams& movement, float frameTime, float* pVerticalSpeedModifier) const
{
	const float minInWaterTime = 0.35f;
	const CPlayerStateSwim_WaterTestProxy& waterProxy = player.m_playerStateSwim_WaterTestProxy;
	const bool allowJump = waterProxy.GetSwimmingTimer() > minInWaterTime;
	if (allowJump)
	{
		// we broke the surface at a velocity enough to dolphin jump.
		if( !m_onSurface && (waterProxy.GetRelativeWaterLevel() > -GetSwimParams().m_swimDolphinJumpDepth) )
		{
			const float velZ = player.GetActorPhysics().velocity.z;

			if( (velZ > GetSwimParams().m_swimDolphinJumpThresholdSpeed) )
			{
				if( pVerticalSpeedModifier )
				{
					*pVerticalSpeedModifier = GetSwimParams().m_swimDolphinJumpSpeedModification;
				}

				return true;
			}
		}
	}

	return false;
}
コード例 #4
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
bool CPlayerStateJump::UpdateCommon( CPlayer& player, const bool isHeavyWeapon, const Vec3 &move, float frameTime, Vec3* pDesiredVel )
{
	GetDesiredVelocity(move, player, pDesiredVel);

	const SActorPhysics& actorPhysics = player.GetActorPhysics();

	// generate stats.
	if (actorPhysics.velocity*actorPhysics.gravity>0.0f)
	{
		const float fHeightofEntity = player.GetEntity()->GetWorldTM().GetTranslation().z;
		m_startFallingHeight= (float)__fsel(-player.m_stats.fallSpeed, fHeightofEntity, max(m_startFallingHeight, fHeightofEntity));
		player.m_stats.fallSpeed = -actorPhysics.velocity.z;
	}

	if (!gEnv->bMultiplayer && player.IsInPickAndThrowMode() && (player.m_stats.fallSpeed > 10.f))
		player.ExitPickAndThrow();

	// inAir is set to 0.0f if we're swimming later - before refactoring this test happened *after* that, hence this test is here.
	m_jumpLock = (float)__fsel(-fabsf(player.m_stats.inAir), max(0.0f, m_jumpLock - frameTime), m_jumpLock);

	return true;
}
コード例 #5
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
const Vec3 CPlayerStateJump::CalculateInAirJumpExtraVelocity( const CPlayer& player, const Vec3& desiredVelocity ) const
{
	const SPlayerStats& stats = player.m_stats;
	const float speedUpFactor = 0.175f;

	Vec3 jumpExtraVelocity(0.0f, 0.0f, 0.0f);

	const SActorPhysics& actorPhysics = player.GetActorPhysics();
	if (actorPhysics.velocity.z > 0.0f)
	{
		//Note: Desired velocity is flat (not 'z' component), so jumpHeight should not be altered
		jumpExtraVelocity = desiredVelocity * speedUpFactor;
	}
	else
	{
		//Note: this makes the jump feel less 'floaty', by accelerating the player slightly down
		//      and compensates the extra traveled distance when going up 
		const float g = actorPhysics.gravity.len();
		if (g > 0.0f)
		{
			const float jumpHeightScale = 1.0f;
			const float jumpHeight = player.m_params.jumpHeight * jumpHeightScale;

			const float estimatedLandTime = sqrt_tpl(2.0f*jumpHeight*(1.0f/g)) * (1.0f - speedUpFactor);
			assert(estimatedLandTime > 0.0f);
			if (estimatedLandTime > 0.0f)
			{
				const float requiredGravity = (2.0f*jumpHeight)/(estimatedLandTime * estimatedLandTime);
				const float initialAccelerationScale = clamp_tpl((-actorPhysics.velocity.z * 0.6f), 0.0f, 1.0f);
				jumpExtraVelocity = (requiredGravity - g) * actorPhysics.gravity.GetNormalized() * initialAccelerationScale;
			}
		}
	}

	return jumpExtraVelocity;
}
コード例 #6
0
ファイル: PlayerStateUtil.cpp プロジェクト: Xydrel/Infected
void CPlayerStateUtil::ApplyFallDamage( CPlayer& player, const float startFallingHeight, const float fHeightofEntity )
{
	CRY_ASSERT(player.IsClient());

	// Zero downwards impact velocity used for fall damage calculations if player was in water within the last 0.5 seconds.
	// Strength jumping straight up and down should theoretically land with a safe velocity, 
	// but together with the water surface stickyness the velocity can sometimes go above the safe impact velocity threshold.

	// DEPRECATED: comment left for prosterity in case dedicated server problems re-appear (author cannot test it).
	// On dedicated server the player can still be flying this frame as well, 
	// since synced pos from client is interpolated/smoothed and will not land immediately,
	// even though the velocity is set to zero.
	// Thus we need to use the velocity change instead of landing to identify impact.

	// DT: 12475: Falling a huge distance to a ledge grab results in no damage.
	// Now using the last velocity because when ledge grabbing the velocity is unchanged for this frame, thus zero damage is applied.
	// Assuming this a physics lag issue, using the last good velocity should be more-or-less ok.
	const float downwardsImpactSpeed = -(float)__fsel(-(player.m_playerStateSwim_WaterTestProxy.GetSwimmingTimer() + 0.5f), player.GetActorPhysics().velocityUnconstrainedLast.z, 0.0f);

	const SPlayerStats& stats = *player.GetActorStats();

	CRY_ASSERT(NumberValid(downwardsImpactSpeed));
	const float MIN_FALL_DAMAGE_DISTANCE = 3.0f;
	const float fallDist = startFallingHeight - fHeightofEntity;
	if ((downwardsImpactSpeed > 0.0f) && (fallDist > MIN_FALL_DAMAGE_DISTANCE))
	{
		const SPlayerHealth& healthCVars = g_pGameCVars->pl_health;

		float velSafe = healthCVars.fallDamage_SpeedSafe;
		float velFatal = healthCVars.fallDamage_SpeedFatal;
		float velFraction = (float)__fsel(-(velFatal - velSafe), 1.0f , (downwardsImpactSpeed - velSafe) * (float)__fres(velFatal - velSafe));

		CRY_ASSERT(NumberValid(velFraction));

		if (velFraction > 0.0f)
		{
			//Stop crouching after taking falling damage
			if(player.GetStance() == STANCE_CROUCH)
			{
				static_cast<CPlayerInput*>(player.GetPlayerInput())->ClearCrouchAction();
			}

			velFraction = powf(velFraction, gEnv->bMultiplayer ? healthCVars.fallDamage_CurveAttackMP : healthCVars.fallDamage_CurveAttack);

			const float maxHealth = player.GetMaxHealth();
			const float currentHealth  = player.GetHealth();

			HitInfo hit;
			hit.dir.zero();
			hit.type = CGameRules::EHitType::Fall;
			hit.shooterId = hit.targetId = hit.weaponId = player.GetEntityId();

			const float maxDamage = (float)__fsel(velFraction - 1.0f, maxHealth, max(0.0f, (gEnv->bMultiplayer?maxHealth:currentHealth) - healthCVars.fallDamage_health_threshold));

			hit.damage = velFraction * maxDamage;

			g_pGame->GetGameRules()->ClientHit(hit);

#ifdef PLAYER_MOVEMENT_DEBUG_ENABLED
			player.GetMovementDebug().LogFallDamage(player.GetEntity(), velFraction, downwardsImpactSpeed, hit.damage);
		}
		else
		{
			player.GetMovementDebug().LogFallDamageNone(player.GetEntity(), downwardsImpactSpeed);
		}
#else
		}
#endif
	}
コード例 #7
0
ファイル: PlayerStateUtil.cpp プロジェクト: Xydrel/Infected
void CPlayerStateUtil::UpdateRemotePlayersInterpolation( CPlayer& player, const SActorFrameMovementParams& movement, SCharacterMoveRequest& frameRequest )
{
	if (!gEnv->bMultiplayer)
		return;

	//////////////////////////////////////////////////////////////////////////
	/// Interpolation for remote players

	const bool isRemoteClient = player.IsRemote();
	const bool doVelInterpolation = isRemoteClient && player.GetPlayerInput();

	if (doVelInterpolation)
	{
		if (g_pGameCVars->pl_clientInertia >= 0.0f)
		{
			player.m_inertia = g_pGameCVars->pl_clientInertia;
		}
		player.m_inertiaAccel = player.m_inertia;

		const bool isNetJumping = g_pGameCVars->pl_velocityInterpSynchJump && movement.jump && isRemoteClient;

		if (isNetJumping)
		{
#ifdef STATE_DEBUG
			if (g_pGameCVars->pl_debugInterpolation)
			{
				CryWatch("SetVel (%f, %f, %f)", player.m_jumpVel.x, player.m_jumpVel.y, player.m_jumpVel.z);
			}
#endif //_RELEASE
			frameRequest.velocity = player.m_jumpVel;
			frameRequest.type = eCMT_JumpAccumulate;
		}
		else
		{
			CNetPlayerInput *playerInput = static_cast<CNetPlayerInput*>(player.GetPlayerInput());
			Vec3 interVel, desiredVel; 

			bool inAir;
			desiredVel = playerInput->GetDesiredVelocity(inAir);
			interVel = desiredVel;

			IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics();
			CRY_ASSERT_MESSAGE(pPhysEnt, "Entity not physicalised! TomB would like to look at this.");

			const bool isPlayerInAir = player.IsInAir();
			if (inAir && isPlayerInAir)
			{
				if (pPhysEnt && (g_pGameCVars->pl_velocityInterpAirDeltaFactor < 1.0f))
				{
					pe_status_dynamics dynStat;
					pPhysEnt->GetStatus(&dynStat);

					Vec3  velDiff = interVel - dynStat.v;
					interVel = dynStat.v + (velDiff * g_pGameCVars->pl_velocityInterpAirDeltaFactor);
					frameRequest.velocity.z = interVel.z;
					frameRequest.velocity.z -= player.GetActorPhysics().gravity.z*gEnv->pTimer->GetFrameTime();
					frameRequest.type = eCMT_Fly; 
				}
			}
			frameRequest.velocity.x = interVel.x;
			frameRequest.velocity.y = interVel.y;


#ifdef STATE_DEBUG
			if (pPhysEnt && g_pGameCVars->pl_debugInterpolation)
			{
				pe_status_dynamics dynStat;
				pPhysEnt->GetStatus(&dynStat);

				CryWatch("Cur: (%f %f %f) Des: (%f %f %f)", dynStat.v.x, dynStat.v.y, dynStat.v.z, desiredVel.x, desiredVel.y, desiredVel.z);
				CryWatch("Req: (%f %f %f) Type (%d)", frameRequest.velocity.x, frameRequest.velocity.y, frameRequest.velocity.z, frameRequest.type);
			}
#endif //!_RELEASE
		}
	}
}
コード例 #8
0
ファイル: PlayerStateUtil.cpp プロジェクト: Xydrel/Infected
bool CPlayerStateUtil::IsOnGround( CPlayer& player )
{
	return( !player.GetActorPhysics().flags.AreAnyFlagsActive(SActorPhysics::EActorPhysicsFlags_Flying) );
}
コード例 #9
0
void CPlayerStateGround::OnPrePhysicsUpdate( CPlayer& player, const SActorFrameMovementParams &movement, float frameTime, const bool isHeavyWeapon, const bool isPlayer )
{
	const Matrix34A baseMtx = Matrix34A(player.GetBaseQuat());
	Matrix34A baseMtxZ(baseMtx * Matrix33::CreateScale(Vec3Constants<float>::fVec3_OneZ));
	baseMtxZ.SetTranslation(Vec3Constants<float>::fVec3_Zero);

	const CAutoAimManager& autoAimManager = g_pGame->GetAutoAimManager();
	const EntityId closeCombatTargetId = autoAimManager.GetCloseCombatSnapTarget();
	const IActor* pCloseCombatTarget = isPlayer && closeCombatTargetId && player.IsClient() ? g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(closeCombatTargetId) : NULL;

	if (pCloseCombatTarget)
	{
		ProcessAlignToTarget(autoAimManager, player, pCloseCombatTarget);
	}
	else
	{
		// This is to restore inertia if the ProcessAlignToTarget set it previously.
		if( m_inertiaIsZero )
		{
			CPlayerStateUtil::RestorePlayerPhysics( player );

			m_inertiaIsZero = false;
		}

		//process movement
		const bool isRemote = isPlayer && !player.IsClient();

		Vec3 move(ZERO);
		CPlayerStateUtil::CalculateGroundOrJumpMovement( player, movement, isHeavyWeapon, move );
		player.GetMoveRequest().type = eCMT_Normal;






		//apply movement
		Vec3 desiredVel(ZERO);
		Vec3 entityPos = player.GetEntity()->GetWorldPos();
		Vec3 entityRight(player.GetBaseQuat().GetColumn0());

		hwvec3 xmDesiredVel = HWV3Zero();

		hwmtx33 xmBaseMtxZ;
		HWMtx33LoadAligned(xmBaseMtxZ, baseMtxZ);
		hwmtx33 xmBaseMtxZOpt = HWMtx33GetOptimized(xmBaseMtxZ);

		hwvec3 xmMove					= HWVLoadVecUnaligned(&move);	
		simdf fGroundNormalZ;

#ifdef STATE_DEBUG
		bool debugJumping = (g_pGameCVars->pl_debug_jumping != 0);
#endif

		const SPlayerStats& stats = *player.GetActorStats();

		{
			xmDesiredVel = xmMove;

			Vec3 groundNormal = player.GetActorPhysics().groundNormal;

			if(!gEnv->bMultiplayer)
			{
				if (player.IsAIControlled())
					fGroundNormalZ = SIMDFLoadFloat(square(groundNormal.z));
				else
					fGroundNormalZ = SIMDFLoadFloat(groundNormal.z);
			}
			else
			{
				//If the hill steepness is greater than our minimum threshold
				if(groundNormal.z > 1.f - cosf(g_pGameCVars->pl_movement.mp_slope_speed_multiplier_minHill))
				{
					//Check if we are trying to move up or downhill
					groundNormal.z = 0.f;
					groundNormal.Normalize();

					Vec3 moveDir = move;
					moveDir.z = 0.f;
					moveDir.Normalize();

					float normalDotMove = groundNormal.Dot(moveDir);
					//Apply speed multiplier based on moving up/down hill and hill steepness
					float multiplier = normalDotMove < 0.f ? g_pGameCVars->pl_movement.mp_slope_speed_multiplier_uphill : g_pGameCVars->pl_movement.mp_slope_speed_multiplier_downhill;
					fGroundNormalZ = SIMDFLoadFloat(1.f - (1.f - player.GetActorPhysics().groundNormal.z) * multiplier);
				}
				else
				{
					fGroundNormalZ = SIMDFLoadFloat(1.0f);
				}
			}

			const float depthHi = g_pGameCVars->cl_shallowWaterDepthHi;
			const float depthLo = g_pGameCVars->cl_shallowWaterDepthLo;
			const float relativeBottomDepth = player.m_playerStateSwim_WaterTestProxy.GetRelativeBottomDepth();

			if( relativeBottomDepth > depthLo )
			{ // Shallow water speed slowdown
				float shallowWaterMultiplier = 1.0f;

				shallowWaterMultiplier = isPlayer
					? g_pGameCVars->cl_shallowWaterSpeedMulPlayer
					: g_pGameCVars->cl_shallowWaterSpeedMulAI;

				shallowWaterMultiplier = max(shallowWaterMultiplier, 0.1f);
				assert(shallowWaterMultiplier <= 1.0f);


				float shallowWaterDepthSpan = (depthHi - depthLo);
				shallowWaterDepthSpan = max(0.1f, shallowWaterDepthSpan);

				float slowdownFraction = (relativeBottomDepth - depthLo) / shallowWaterDepthSpan;
				slowdownFraction = clamp_tpl(slowdownFraction, 0.0f, 1.0f);
				shallowWaterMultiplier = LERP(1.0f, shallowWaterMultiplier, slowdownFraction);

				//avoid branch if m_stats.relativeBottomDepth <= 0.0f;
				shallowWaterMultiplier = (float)__fsel(-relativeBottomDepth, 1.0f, shallowWaterMultiplier);

				simdf vfShallowWaterMultiplier = SIMDFLoadFloat(shallowWaterMultiplier);

				xmDesiredVel = HWVMultiplySIMDF(xmDesiredVel, vfShallowWaterMultiplier);
			}
		}





		// Slow down on sloped terrain, simply proportional to the slope. 
		xmDesiredVel = HWVMultiplySIMDF(xmDesiredVel, fGroundNormalZ);

		//be sure desired velocity is flat to the ground
		hwvec3 vDesiredVelVert = HWMtx33RotateVecOpt(xmBaseMtxZOpt, xmDesiredVel);

		xmDesiredVel = HWVSub(xmDesiredVel, vDesiredVelVert);

		HWVSaveVecUnaligned(&desiredVel, xmDesiredVel);

		if (isPlayer)
		{
			Vec3 modifiedSlopeNormal = player.GetActorPhysics().groundNormal;
			float h = Vec2(modifiedSlopeNormal.x, modifiedSlopeNormal.y).GetLength(); // TODO: OPT: sqrt(x*x+y*y)
			float v = modifiedSlopeNormal.z;
			float slopeAngleCur = RAD2DEG(atan2_tpl(h, v));

			const float divisorH = (float)__fsel(-h, 1.0f, h);
			const float divisorV = (float)__fsel(-v, 1.0f, v);

			const float invV = __fres(divisorV);
			const float invH = __fres(divisorH);

			const float slopeAngleHor = 10.0f;
			const float slopeAngleVer = 50.0f;
			float slopeAngleFraction = clamp_tpl((slopeAngleCur - slopeAngleHor) * __fres(slopeAngleVer - slopeAngleHor), 0.0f, 1.0f);

			slopeAngleFraction = slopeAngleFraction * slopeAngleFraction * slopeAngleFraction;

			float slopeAngleMod = LERP(0.0f, 90.0f, slopeAngleFraction);

			float s, c;

			sincos_tpl(DEG2RAD(slopeAngleMod), &s, &c);

			const float hMultiplier = (float)__fsel(-h, 1.0f, s * invH);
			const float vMultiplier = (float)__fsel(-v, 1.0f, c * invV);

			modifiedSlopeNormal.x *= hMultiplier;
			modifiedSlopeNormal.y *= hMultiplier;
			modifiedSlopeNormal.z *= vMultiplier;

			//Normalize the slope normal if possible
			const float fSlopeNormalLength = modifiedSlopeNormal.len();
			const float fSlopeNormalLengthSafe = (float)__fsel(fSlopeNormalLength - 0.000001f, fSlopeNormalLength, 1.0f);
			modifiedSlopeNormal = modifiedSlopeNormal * __fres(fSlopeNormalLengthSafe);

			float alignment = min(modifiedSlopeNormal * desiredVel, 0.0f);

			// Also affect air control (but not as much), to prevent jumping up against steep slopes.

			alignment *= (float)__fsel(-fabsf(stats.onGround), LERP(0.7f, 1.0f, 1.0f - clamp_tpl(modifiedSlopeNormal.z * 100.0f, 0.0f, 1.0f)), 1.0f);

			modifiedSlopeNormal.z = modifiedSlopeNormal.z;

			desiredVel -= modifiedSlopeNormal * alignment;


#ifdef STATE_DEBUG
			if (debugJumping)
			{
				player.DebugGraph_AddValue("GroundSlope", slopeAngleCur);
				player.DebugGraph_AddValue("GroundSlopeMod", slopeAngleMod);
			}
#endif
		}





		Vec3 newVelocity = desiredVel;

		const float fNewSpeed = newVelocity.len();

		const float fVelocityMultiplier = (float)__fsel(fNewSpeed - 22.0f, __fres(fNewSpeed+FLT_EPSILON) * 22.0f, 1.0f);

		// TODO: Maybe we should tell physics about this new velocity ? Or maybe SPlayerStats::velocity ? (stephenn).
		player.GetMoveRequest().velocity = newVelocity * (stats.flashBangStunMult * fVelocityMultiplier);

#ifdef STATE_DEBUG
		if(g_pGameCVars->pl_debug_movement > 0)
		{
			const char* filter = g_pGameCVars->pl_debug_filter->GetString();
			const char* name = player.GetEntity()->GetName();
			if ((strcmp(filter, "0") == 0) || (strcmp(filter, name) == 0))
			{
				float white[] = {1.0f,1.0f,1.0f,1.0f};
				gEnv->pRenderer->Draw2dLabel(20, 450, 2.0f, white, false, "Speed: %.3f m/s", player.GetMoveRequest().velocity.len());

				if(g_pGameCVars->pl_debug_movement > 1)
				{
					gEnv->pRenderer->Draw2dLabel(35, 470, 1.8f, white, false, "Stance Speed: %.3f m/s - (%sSprinting)", player.GetStanceMaxSpeed(player.GetStance()), player.IsSprinting() ? "" : "Not ");
				}
			}
		}
#endif


























	}

	if( isPlayer )
	{
		CheckForVaultTrigger(player, frameTime);
	}
}
コード例 #10
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
void CPlayerStateJump::StartJump( CPlayer& player, const bool isHeavyWeapon, const float fVerticalSpeedModifier )
{
	const SActorPhysics& actorPhysics = player.GetActorPhysics();
	const SPlayerStats& stats = *player.GetActorStats();
	const float onGroundTime = 0.2f;

	float g = actorPhysics.gravity.len();

	const float jumpHeightScale = 1.0f;
	const float jumpHeight = player.GetActorParams().jumpHeight * jumpHeightScale;

	float playerZ = player.GetEntity()->GetWorldPos().z;
	float expectedJumpEndHeight = playerZ + jumpHeight;

	pe_player_dimensions dimensions;
	IPhysicalEntity *pPhysics = player.GetEntity()->GetPhysics();
	if (pPhysics && pPhysics->GetParams(&dimensions))
	{
		float physicsBottom = dimensions.heightCollider - dimensions.sizeCollider.z;
		if (dimensions.bUseCapsule)
		{
			physicsBottom -= dimensions.sizeCollider.x;
		}
		expectedJumpEndHeight += physicsBottom;
	}

	float jumpSpeed = 0.0f;

 	if (g > 0.0f)
	{
		jumpSpeed = sqrt_tpl(2.0f*jumpHeight*(1.0f/g)) * g;

		if( isHeavyWeapon )
		{
			jumpSpeed *= g_pGameCVars->pl_movement.nonCombat_heavy_weapon_speed_scale;
		}
	}

	//this is used to easily find steep ground
	float slopeDelta = (Vec3Constants<float>::fVec3_OneZ - actorPhysics.groundNormal).len();

	SetJumpState(player, JState_Jump);

	Vec3 jumpVec(ZERO);

	bool bNormalJump = true;
	
	player.PlaySound(CPlayer::ESound_Jump);

	OnSpecialMove(player, IPlayerEventListener::eSM_Jump);

	CCCPOINT_IF( player.IsClient(),   PlayerMovement_LocalPlayerNormalJump);
	CCCPOINT_IF(!player.IsClient(), PlayerMovement_NonLocalPlayerNormalJump);

	{
		// This was causing the vertical jumping speed to be much slower.
		float verticalMult = max(1.0f - m_jumpLock, 0.3f);

		const Quat baseQuat = player.GetBaseQuat();
		jumpVec += baseQuat.GetColumn2() * jumpSpeed * verticalMult;
		jumpVec.z += fVerticalSpeedModifier;

#ifdef STATE_DEBUG
		if (g_pGameCVars->pl_debugInterpolation > 1)
		{
			CryWatch("Jumping: vec from player BaseQuat only = (%f, %f, %f)", jumpVec.x, jumpVec.y, jumpVec.z);
		}
#endif
		
		if (g_pGameCVars->pl_adjustJumpAngleWithFloorNormal && actorPhysics.groundNormal.len2() > 0.0f)
		{
			float vertical = clamp_tpl((actorPhysics.groundNormal.z - 0.25f) / 0.5f, 0.0f, 1.0f);
			Vec3 modifiedJumpDirection = LERP(actorPhysics.groundNormal, Vec3(0,0,1), vertical);
			jumpVec = modifiedJumpDirection * jumpVec.len();
		}

#ifdef STATE_DEBUG
		if (g_pGameCVars->pl_debugInterpolation > 1)
		{
			CryWatch("Jumping (%f, %f, %f)", jumpVec.x, jumpVec.y, jumpVec.z);
		}
#endif
	}

	NETINPUT_TRACE(player.GetEntityId(), jumpVec);

	FinalizeVelocity( player, jumpVec );

	if (!player.IsRemote())
	{
		player.HasJumped(player.GetMoveRequest().velocity);
	}

	IPhysicalEntity* pPhysEnt = player.GetEntity()->GetPhysics();
	if (pPhysEnt != NULL)
	{
		SAnimatedCharacterParams params = player.m_pAnimatedCharacter->GetParams();
		pe_player_dynamics pd;
		pd.kAirControl = player.GetAirControl()* g_pGameCVars->pl_jump_control.air_control_scale;
		pd.kAirResistance = player.GetAirResistance() * g_pGameCVars->pl_jump_control.air_resistance_scale;

		params.inertia = player.GetInertia() * g_pGameCVars->pl_jump_control.air_inertia_scale;

		if(player.IsRemote() && (g_pGameCVars->pl_velocityInterpAirControlScale > 0))
		{
			pd.kAirControl = g_pGameCVars->pl_velocityInterpAirControlScale;
		}

		pPhysEnt->SetParams(&pd);

		// Let Animated character handle the inertia
		player.SetAnimatedCharacterParams(params);
	}

#if 0
	if (debugJumping)
	{
		Vec3 entityPos = m_player.GetEntity()->GetWorldPos();
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(entityPos, ColorB(255,255,255,255), entityPos, ColorB(255,255,0,255), 2.0f);
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(entityPos+Vec3(0,0,2), ColorB(255,255,255,255), entityPos+Vec3(0,0,2) + desiredVel, ColorB(0,255,0,255), 2.0f);
		gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(entityPos, ColorB(255,255,255,255), entityPos + jumpVec, ColorB(0,255,255,255), 2.0f);
		gEnv->pRenderer->DrawLabel(entityPos - entityRight * 1.0f + Vec3(0,0,3.0f), 1.5f, "Velo[%2.3f = %2.3f, %2.3f, %2.3f]", m_request.velocity.len(), m_request.velocity.x, m_request.velocity.y, m_request.velocity.z);
	}
#endif

	m_expectedJumpEndHeight = expectedJumpEndHeight;
	m_bSprintJump = player.IsSprinting();
}
コード例 #11
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
void CPlayerStateJump::GetDesiredVelocity( const Vec3 & move, const CPlayer &player, Vec3* pDesiredVel ) const
{
	// Generate jump velocity.
	SIMDFConstant(xmfMaxMove, 1.0f);

	simdf fGroundNormalZ = xmfMaxMove;

	hwvec3 xmMove  = HWVLoadVecUnaligned(&move);	
	if( move.len2() > 0.01f )
	{
		const Matrix34A baseMtx = Matrix34A(player.GetBaseQuat());
		Matrix34A baseMtxZ(baseMtx * Matrix33::CreateScale(Vec3(0,0,1)));
		baseMtxZ.SetTranslation(Vec3(0,0,0));

		hwmtx33 xmBaseMtxZ;
		HWMtx33LoadAligned(xmBaseMtxZ, baseMtxZ);
		hwmtx33 xmBaseMtxZOpt = HWMtx33GetOptimized(xmBaseMtxZ);

		hwvec3 xmDesiredVel = HWV3Zero();
		if (player.IsRemote())
		{
			xmDesiredVel = xmMove;
		}
		else
		{
			hwvec3 xmVelocity = HWVLoadVecUnaligned(&player.GetActorPhysics().velocity);

			SIMDFConstant(xmfZero, 0.0f);
			SIMDFConstant(xmfDiffMultiplier, 0.3f);
			SIMDFConstant(xmfMaxDiff, 0.1f);
			SIMDFConstant(xmfMinMove, 0.5f);
			SIMDFConstant(xmfOnePointFive, 1.5f);

			hwvec3 xmMoveFlat		= HWVSub(xmMove, 		HWMtx33RotateVecOpt(xmBaseMtxZOpt, xmMove));
			hwvec3 xmCurrVelFlat	= HWVSub(xmVelocity,	HWMtx33RotateVecOpt(xmBaseMtxZOpt, xmVelocity));

			simdf xmfCurrVelSizeSq	= HWV3LengthSq(xmCurrVelFlat);

			hwvec3 xmMoveFlatNormalized		= HWV3Normalize(xmMoveFlat);
			hwvec3 xmCurDirFlatTemp			= HWV3Normalize(xmCurrVelFlat);

			hwvec3 xmCurVelFlatNormalized	= HWVSelectSIMDF(xmCurDirFlatTemp, HWV3Zero(), SIMDFLessThanEqual(xmfCurrVelSizeSq, xmfZero));

			simdf fDot = HWV3Dot(xmMoveFlatNormalized, xmCurVelFlatNormalized);

			hwvec3 xmScaledMoveFlat = HWVMultiplySIMDF(xmMoveFlat, SIMDFClamp(fDot, xmfMinMove, xmfMaxMove));
			simdf fMoveMult = SIMDFMax(SIMDFMult(SIMDFAbs(fDot), xmfDiffMultiplier), xmfMaxDiff);

			hwvec3 xmReducedMove = HWVMultiplySIMDF(HWVSub(xmMoveFlat, xmCurrVelFlat), fMoveMult);

			xmDesiredVel = HWVSelectSIMDF( xmScaledMoveFlat, xmReducedMove, SIMDFLessThan( fDot, xmfZero ));

			simdf xmfDesiredVelSizeSq = HWV3LengthSq(xmDesiredVel);

			hwvec3 xmDesiredVelNorm = HWV3Normalize(xmDesiredVel);

			hwvec3 xmClampedVel = HWVMultiplySIMDF(xmDesiredVelNorm, SIMDFMax( xmfOnePointFive, SIMDFSqrt(xmfCurrVelSizeSq)));

			xmDesiredVel = HWVSelectSIMDF( xmClampedVel, xmDesiredVel, SIMDFLessThan( xmfDesiredVelSizeSq, xmfCurrVelSizeSq));
		}

		HWVSaveVecUnaligned(pDesiredVel, xmDesiredVel);
	}
}
コード例 #12
0
ファイル: PlayerStateJump.cpp プロジェクト: aronarts/FireNET
void CPlayerStateJump::Landed(CPlayer& player, const bool isHeavyWeapon, float fallSpeed)
{
#ifdef STATE_DEBUG
	bool remoteControlled = false;
	IVehicle* pVehicle = player.GetLinkedVehicle();
	if(pVehicle)
	{
		IVehicleSeat* pVehicleSeat = pVehicle->GetSeatForPassenger(player.GetEntityId());
		if(pVehicleSeat && pVehicleSeat->IsRemoteControlled())
		{
			remoteControlled = true;
		}
	}
	CRY_ASSERT_MESSAGE( player.GetLinkedEntity()==NULL || remoteControlled, "Cannot 'land' when you're linked to another entity!" );
#endif

	const SPlayerStats& stats = player.m_stats;

	Vec3 playerPosition = player.GetEntity()->GetWorldPos();
	IPhysicalEntity *phys = player.GetEntity()->GetPhysics();
	IMaterialEffects *mfx = gEnv->pGame->GetIGameFramework()->GetIMaterialEffects();

	const SActorPhysics& actorPhysics = player.GetActorPhysics();
	int matID = actorPhysics.groundMaterialIdx != -1 ? actorPhysics.groundMaterialIdx : mfx->GetDefaultSurfaceIndex();

	const float fHeightofEntity = playerPosition.z;
	const float worldWaterLevel = player.m_playerStateSwim_WaterTestProxy.GetWaterLevel();
	
	TMFXEffectId effectId = mfx->GetEffectId("bodyfall", matID);
	if (effectId != InvalidEffectId)
	{
		SMFXRunTimeEffectParams params;
		Vec3 direction = Vec3(0,0,0);
		if (IMovementController *pMV = player.GetMovementController())
		{
			SMovementState state;
			pMV->GetMovementState(state);
			direction = state.aimDirection;
		}
		params.pos = playerPosition + direction;
		//params.soundSemantic = eSoundSemantic_Player_Foley;

		float landFallParamVal = (float)__fsel( -(fallSpeed - 7.5f), 0.25f, 0.75f);
		params.AddAudioRtpc("landfall", landFallParamVal);

		const float speedParamVal = min(fabsf((actorPhysics.velocity.z * 0.1f)), 1.0f);
		params.AddAudioRtpc("speed", speedParamVal);

		mfx->ExecuteEffect(effectId, params);
	}

	bool heavyLanded = false;

	IItem* pCurrentItem = player.GetCurrentItem();
	CWeapon* pCurrentWeapon = pCurrentItem ? static_cast<CWeapon*>(pCurrentItem->GetIWeapon()) : NULL;

	if (fallSpeed > 0.0f && player.IsPlayer())
	{
		if(!gEnv->bMultiplayer)
		{
			const float verticalSpeed = fabs(fallSpeed);
			const float speedForHeavyLand = g_pGameCVars->pl_health.fallSpeed_HeavyLand;
			if ((verticalSpeed >= speedForHeavyLand) && (player.GetPickAndThrowEntity() == 0) && !player.IsDead())
			{
				if ( !isHeavyWeapon )
				{
					if (pCurrentWeapon)
					{
						pCurrentWeapon->FumbleGrenade();
						pCurrentWeapon->CancelCharge();
					}

					player.StartInteractiveActionByName("HeavyLand", false);
				}
				heavyLanded = true;
			}
		}
	}

	if(player.m_isClient)
	{
		if (fallSpeed > 0.0f)
		{
			const float fallIntensityMultiplier = stats.wasHit ? g_pGameCVars->pl_fall_intensity_hit_multiplier : g_pGameCVars->pl_fall_intensity_multiplier;
			const float fallIntensityMax = g_pGameCVars->pl_fall_intensity_max;
			const float fallTimeMultiplier = g_pGameCVars->pl_fall_time_multiplier;
			const float fallTimeMax = g_pGameCVars->pl_fall_time_max;
			const float zoomMultiplayer = (pCurrentWeapon && pCurrentWeapon->IsZoomed()) ? 0.2f : 1.0f;
			const float direction = ((cry_rand()%2)==0) ? -1.0f : 1.0f;
			const float intensity = clamp_tpl(fallIntensityMultiplier*fallSpeed*zoomMultiplayer, 0.0f, fallIntensityMax);
			const float shakeTime = clamp_tpl(fallTimeMultiplier*fallSpeed*zoomMultiplayer, 0.0f, fallTimeMax);
			const Vec3 rotation = Vec3(-0.5f, 0.15f*direction, 0.05f*direction);

			if (CScreenEffects* pGameScreenEffects = g_pGame->GetScreenEffects())
			{
				pGameScreenEffects->CamShake(rotation*intensity, Vec3(0, 0, 0), shakeTime, shakeTime, 0.05f, CScreenEffects::eCS_GID_Player);
			}

			IForceFeedbackSystem* pForceFeedback = g_pGame->GetIGameFramework()->GetIForceFeedbackSystem();
			assert(pForceFeedback);

			ForceFeedbackFxId fxId = pForceFeedback->GetEffectIdByName("landFF");
			pForceFeedback->PlayForceFeedbackEffect(fxId, SForceFeedbackRuntimeParams(intensity, 0.0f));

			if(fallSpeed > 7.0f)
			{
				player.PlaySound(CPlayer::ESound_Fall_Drop);
			}

			CPlayer::EPlayerSounds playerSound = heavyLanded ? CPlayer::ESound_Gear_HeavyLand : CPlayer::ESound_Gear_Land;
			player.PlaySound(playerSound, true);
		}
		CCCPOINT(PlayerMovement_LocalPlayerLanded);
	}
	
	if( gEnv->pAISystem )
	{
		// Notify AI
		//If silent feet active, ignore here
		const float noiseSupression = 0.0f;
		const float fAISoundRadius = (g_pGameCVars->ai_perception.landed_baseRadius + (g_pGameCVars->ai_perception.landed_speedMultiplier * fallSpeed)) * (1.0f - noiseSupression);
		SAIStimulus stim(AISTIM_SOUND, AISOUND_MOVEMENT_LOUD, player.GetEntityId(), 0,
			player.GetEntity()->GetWorldPos() + player.GetEyeOffset(), ZERO, fAISoundRadius);
		gEnv->pAISystem->RegisterStimulus(stim);
	}

	// Record 'Land' telemetry stats.

	CStatsRecordingMgr::TryTrackEvent(&player, eGSE_Land, fallSpeed);

	if (fallSpeed > 0.0f)
	{
		player.CreateScriptEvent( heavyLanded ? "heavylanded" : "landed",stats.fallSpeed);
	}
}
コード例 #13
0
ファイル: PlayerStateSwim.cpp プロジェクト: aronarts/FireNET
bool CPlayerStateSwim::OnPrePhysicsUpdate( CPlayer& player, const SActorFrameMovementParams& movement, float frameTime )
{
	const CPlayerStateSwim_WaterTestProxy& waterProxy = player.m_playerStateSwim_WaterTestProxy;

	CPlayerStateUtil::PhySetFly( player );

	const SPlayerStats& stats = player.m_stats;

#ifdef STATE_DEBUG
	const bool debug = (g_pGameCVars->cl_debugSwimming != 0);
#endif
	
	const Vec3 entityPos = player.GetEntity()->GetWorldPos();
	const Quat baseQuat = player.GetBaseQuat();
	const Vec3 vRight(baseQuat.GetColumn0());
	
	Vec3 velocity = player.GetActorPhysics().velocity;

	// Underwater timer, sounds update and surface wave speed.
	if (waterProxy.IsHeadUnderWater())
	{
		m_headUnderWaterTimer += frameTime;
		if (m_headUnderWaterTimer <= -0.0f && !m_onSurface )
		{
			player.PlaySound(CPlayer::ESound_DiveIn, true, "speed", velocity.len());
			m_headUnderWaterTimer = 0.0f;
		}

		player.PlaySound(CPlayer::ESound_Underwater, true);
	}
	else
	{
		m_headUnderWaterTimer -= frameTime;			
		if (m_headUnderWaterTimer >= 0.0f && (waterProxy.IsHeadComingOutOfWater() || m_onSurface))
		{
			player.PlaySound(CPlayer::ESound_DiveOut, true, "speed", velocity.len());
			m_headUnderWaterTimer = 0.0f;
		}

		player.PlaySound(CPlayer::ESound_Underwater, false);
	}
	m_headUnderWaterTimer = clamp_tpl( m_headUnderWaterTimer, -0.2f, 0.2f );

	// Apply water flow velocity to the player
	Vec3 gravity;
	pe_params_buoyancy buoyancy[s_maxWaterVolumesToConsider];
	if (int count = gEnv->pPhysicalWorld->CheckAreas(entityPos, gravity, &buoyancy[0], s_maxWaterVolumesToConsider))
	{
		for(int i = 0; i < count && i < s_maxWaterVolumesToConsider; ++i)
		{
			// 0 is water
			if( buoyancy[i].iMedium == 0 )
			{
				velocity += (buoyancy[i].waterFlow * frameTime);
			}
		}
	}

	// Calculate desired acceleration (user input)	
	Vec3 desiredWorldVelocity(ZERO);

	Vec3 acceleration(ZERO);
	{
		Vec3 desiredLocalNormalizedVelocity(ZERO);
		Vec3 desiredLocalVelocity(ZERO);

		const Quat viewQuat = player.GetViewQuat();

		const float backwardMultiplier = (float)__fsel(movement.desiredVelocity.y, 1.0f, g_pGameCVars->pl_swimBackSpeedMul);
		desiredLocalNormalizedVelocity.x = movement.desiredVelocity.x * g_pGameCVars->pl_swimSideSpeedMul;
		desiredLocalNormalizedVelocity.y = movement.desiredVelocity.y * backwardMultiplier;

		float sprintMultiplier = 1.0f;
		if ((player.IsSprinting()) && !player.IsCinematicFlagActive(SPlayerStats::eCinematicFlag_RestrictMovement))
		{
			sprintMultiplier = GetSwimParams().m_swimSprintSpeedMul;

			// Higher speed multiplier when sprinting while looking up
			const float upFraction = clamp_tpl(viewQuat.GetFwdZ(), 0.0f, 1.0f);
			sprintMultiplier *= LERP(1.0f, GetSwimParams().m_swimUpSprintSpeedMul, upFraction);
		}

		const float baseSpeed = player.GetStanceMaxSpeed(STANCE_SWIM);
		desiredLocalVelocity.x = desiredLocalNormalizedVelocity.x * sprintMultiplier * baseSpeed;
		desiredLocalVelocity.y = desiredLocalNormalizedVelocity.y * sprintMultiplier * baseSpeed;
		desiredLocalVelocity.z = desiredLocalNormalizedVelocity.z * g_pGameCVars->pl_swimVertSpeedMul * baseSpeed;

		// The desired movement is applied in view-space, not in entity-space, since entity does not necessarily pitch while swimming.
		desiredWorldVelocity += viewQuat.GetColumn0() * desiredLocalVelocity.x;
		desiredWorldVelocity += viewQuat.GetColumn1() * desiredLocalVelocity.y;

		// though, apply up/down in world space.
		desiredWorldVelocity.z += desiredLocalVelocity.z;

#ifdef STATE_DEBUG
		if (debug)
		{
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.8f), 1.5f, "BaseSpeed %1.3f", baseSpeed);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,1.0f), 1.5f, "SprintMul %1.2f", sprintMultiplier);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.6f), 1.5f, "MoveN[%1.3f, %1.3f, %1.3f]", desiredLocalNormalizedVelocity.x, desiredLocalNormalizedVelocity.y, desiredLocalNormalizedVelocity.z);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.5f), 1.5f, "VeloL[%1.3f, %1.3f, %1.3f]", desiredLocalVelocity.x, desiredLocalVelocity.y, desiredLocalVelocity.z);
			gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.4f), 1.5f, "VeloW[%1.3f, %1.3f, %1.3f]", desiredWorldVelocity.x, desiredWorldVelocity.y, desiredWorldVelocity.z);
		}
#endif

		//Remove a bit of control when entering the water
		const float userControlFraction = (float)__fsel(0.3f - waterProxy.GetSwimmingTimer(), 0.2f, 1.0f); 
		acceleration += desiredWorldVelocity * userControlFraction;
	}

	// Apply acceleration (frame-rate independent)
	const float accelerateDelayInv = 3.333f;
	velocity += acceleration * (frameTime * accelerateDelayInv);

#ifdef STATE_DEBUG
	if( debug )
	{
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.2f), 1.5f, " Axx[%1.3f, %1.3f, %1.3f]", acceleration.x, acceleration.y, acceleration.z);
	}
#endif

	//--------------------

	const float relativeWaterLevel = waterProxy.GetRelativeWaterLevel() + 0.1f;
	const float surfaceDistanceFraction = clamp_tpl(fabsf(relativeWaterLevel), 0.0f, 1.0f);
	float surfaceProximityInfluence = 1.0f - surfaceDistanceFraction;
	const float verticalVelocityFraction = clamp_tpl((fabsf(desiredWorldVelocity.z) - 0.3f) * 2.5f, 0.0f, 1.0f);
	surfaceProximityInfluence = surfaceProximityInfluence * (1.0f - verticalVelocityFraction);

	// Apply velocity dampening (frame-rate independent)
	Vec3 damping(ZERO);

	const float zSpeedPreDamping = velocity.z;

	{
		damping.x = fabsf(velocity.x);
		damping.y = fabsf(velocity.y);

		// Vertical damping is special, to allow jumping out of water with higher speed, 
		// and also not sink too deep when falling down ito the water after jump or such.
		float zDamp = 1.0f + (6.0f * clamp_tpl((-velocity.z - 1.0f) * 0.333f, 0.0f, 1.0f));
		zDamp *= 1.0f - surfaceProximityInfluence;

		damping.z = fabsf(velocity.z) * zDamp;

		const float stopDelayInv = 3.333f;
		damping *= (frameTime * stopDelayInv);
		velocity.x = (float)__fsel((fabsf(velocity.x) - damping.x), (velocity.x - fsgnf(velocity.x) * damping.x), 0.0f);
		velocity.y = (float)__fsel((fabsf(velocity.y) - damping.y), (velocity.y - fsgnf(velocity.y) * damping.y), 0.0f);
		velocity.z = (float)__fsel((fabsf(velocity.z) - damping.z), (velocity.z - fsgnf(velocity.z) * damping.z), 0.0f);
		
		//Make sure you can not swim above the surface
		if ((relativeWaterLevel >= 0.0f) && (velocity.z > 0.0f))
		{
			velocity.z = 0.0f;
		}
	}

	// Decide if we're on the surface and therefore need to be kept there..
	if( relativeWaterLevel > -0.2f && relativeWaterLevel < 1.0f && fabs_tpl( zSpeedPreDamping ) < 0.5f )
	{
		if( !waterProxy.IsHeadUnderWater() )
		{
			m_onSurface = true;
		}
	}
	else
	{
		// we only leave the surface if the player moves, otherwise we try and keep the 
		// player on the surface, even if they currently arent
		m_onSurface = false;
	}

	// Calculate and apply surface movement to the player.
	float speedDelta = 0.0f;
	if( m_onSurface )
	{
		const float newWaterLevel = waterProxy.GetWaterLevel();
		const float waterLevelDelta = clamp_tpl(newWaterLevel - m_lastWaterLevel, -1.0f, 1.0f );
		const float newCheckedTime = waterProxy.GetWaterLevelTimeUpdated();
		const float timeDelta = newCheckedTime - m_lastWaterLevelTime;

		if( timeDelta > FLT_EPSILON )
		{
			speedDelta = waterLevelDelta/timeDelta;

			velocity.z += speedDelta;
		}

		m_lastWaterLevel = newWaterLevel;
		m_lastWaterLevelTime = newCheckedTime;
	}

	// Set request type and velocity
	player.GetMoveRequest().type = eCMT_Fly;
	player.GetMoveRequest().velocity = velocity;

#ifdef STATE_DEBUG
	// DEBUG VELOCITY
	if (debug)
	{
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.0f), 1.5f, "Velo[%1.3f, %1.3f, %1.3f]", velocity.x, velocity.y, velocity.z);
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.4f), 1.5f, "Damp[%1.3f, %1.3f, %1.3f]", damping.x, damping.y, damping.z);
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f - Vec3(0,0,0.6f), 1.5f, "FrameTime %1.4f", frameTime);
		gEnv->pRenderer->DrawLabel(entityPos - vRight * 1.5f + Vec3(0,0,0.3f), 1.5f, "DeltaSpeed[%1.3f]", speedDelta );
		//if (bNewSwimJumping)
			//gEnv->pRenderer->DrawLabel(entityPos - vRight * 0.15f + Vec3(0,0,0.6f), 2.0f, "JUMP");
	}
#endif

	return true;
}