示例#1
0
void CActionCoopAnimation::Install()
{
	TPlayerAction::Install();

	IActionController* pTargetActionController = m_target.GetAnimatedCharacter()->GetActionController();
	if(pTargetActionController)
	{
		m_player.GetAnimatedCharacter()->GetActionController()->SetSlaveController(*pTargetActionController, PlayerMannequin.contextIDs.SlaveChar, true, m_piOptionalTargetDatabase);
		CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
		if (pRecordingSystem)
		{
			pRecordingSystem->OnMannequinSetSlaveController(m_rootScope->GetEntityId(), m_target.GetEntityId(), PlayerMannequin.contextIDs.SlaveChar, true, m_piOptionalTargetDatabase);
		}
	}
	else
	{
		IEntity* pTargetEnt = m_target.GetEntity();
		if (pTargetEnt)
		{
			IEntity& targetEnt = *pTargetEnt;

			m_player.GetAnimatedCharacter()->GetActionController()->SetScopeContext(PlayerMannequin.contextIDs.SlaveChar, targetEnt, targetEnt.GetCharacter(0), m_piOptionalTargetDatabase);
		}
	}

	m_player.GetAnimatedCharacter()->GetActionController()->GetContext().state.Set(m_targetTagID, true);
}
void CMountedGunController::OnLeave( )
{
    CRY_ASSERT_MESSAGE(m_pControlledPlayer, "Controlled player not initialized");

    ICharacterInstance* pCharacter = m_pControlledPlayer->IsThirdPerson() ? m_pControlledPlayer->GetEntity()->GetCharacter(0) : m_pControlledPlayer->GetShadowCharacter();
    if (pCharacter)
        {
            if(m_pMovementAction)
                {
                    m_pMovementAction->ForceFinish();
                    SAFE_RELEASE(m_pMovementAction);
                }

            CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
            if (pRecordingSystem)
                {
                    pRecordingSystem->OnMountedGunLeave(m_pControlledPlayer);
                }

            IAnimatedCharacter* pAnimatedCharacter = m_pControlledPlayer->GetAnimatedCharacter();
            CRY_ASSERT(pAnimatedCharacter);

            pAnimatedCharacter->ForceRefreshPhysicalColliderMode();
            pAnimatedCharacter->RequestPhysicalColliderMode(eColliderMode_Undefined, eColliderModeLayer_Game, "CMountedGunController::OnLeave");
            pAnimatedCharacter->SetNoMovementOverride(false);

            if (gEnv->bMultiplayer || m_pControlledPlayer->IsPlayer())
                pAnimatedCharacter->DisableRigidCollider();

            pAnimatedCharacter->GetGroundAlignmentParams().SetFlag(eGA_AllowWithNoCollision, true);

            m_pControlledPlayer->GetActorParams().mountedWeaponCameraTarget.zero();
        }
}
void CLocalPlayerComponent::UpdateFreeFallDeath( const float frameTime )
{
	if(m_bIsInFreeFallDeath)
	{
		m_rPlayer.m_pPlayerRotation->SetForceLookAt(m_freeFallLookTarget);

		m_freeFallDeathFadeTimer += frameTime;

		if(m_rPlayer.m_stats.isRagDoll ||  (m_freeFallDeathFadeTimer > g_pGameCVars->pl_freeFallDeath_fadeTimer))
		{
			CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
			if (!pRecordingSystem || !pRecordingSystem->IsPlayingBack())	// Don't do the fade screen effect if in killcam
			{
				TriggerFadeToBlack(); 
			}

			m_rPlayer.m_pPlayerRotation->SetForceLookAt(ZERO);
			m_bIsInFreeFallDeath = false;
		}
	}
	else
	{
		m_freeFallDeathFadeTimer = 0.0f;
	}
}
void CMountedGunController::OnEnter(EntityId mountedGunId)
{
    CRY_ASSERT_MESSAGE(m_pControlledPlayer, "Controlled player not initialized");

    ICharacterInstance* pCharacter = m_pControlledPlayer->IsThirdPerson() ? m_pControlledPlayer->GetEntity()->GetCharacter(0) : m_pControlledPlayer->GetShadowCharacter();
    if (pCharacter)
        {
            CItem* pWeapon = static_cast<CItem*>(g_pGame->GetIGameFramework()->GetIItemSystem()->GetItem(mountedGunId));
            assert(pWeapon);

            IActionController* pActionController = m_pControlledPlayer->GetAnimatedCharacter()->GetActionController();
            if (pActionController && m_pMannequinParams)
                {
                    SAFE_RELEASE(m_pMovementAction);

                    m_pMovementAction = new TPlayerAction(PP_PlayerAction, m_pMannequinParams->fragmentIDs.MotionMounted);
                    m_pMovementAction->AddRef();
                    pActionController->Queue(m_pMovementAction);
                }

            //////////////////////////////////////////////////////////////////////////
            // NOTE: This should go through mannequin
            CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
            if (pRecordingSystem)
                {
                    const SParams& pWeaponParams = pWeapon->GetParams();

                    IAnimationSet* pAnimationSet = pCharacter->GetIAnimationSet();
                    const int upAnimId = pAnimationSet->GetAnimIDByName(pWeaponParams.mountedTPAimAnims[MountedTPAimAnim::Up].c_str());
                    const int downAnimId = pAnimationSet->GetAnimIDByName(pWeaponParams.mountedTPAimAnims[MountedTPAimAnim::Down].c_str());

                    pRecordingSystem->OnMountedGunEnter(m_pControlledPlayer, upAnimId, downAnimId);
                }

            //////////////////////////////////////////////////////////////////////////

            IAnimatedCharacter* pAnimatedCharacter = m_pControlledPlayer->GetAnimatedCharacter();
            CRY_ASSERT(pAnimatedCharacter);

            pAnimatedCharacter->RequestPhysicalColliderMode(eColliderMode_Disabled, eColliderModeLayer_Game, "CMountedGunController::OnEnter");
            pAnimatedCharacter->SetNoMovementOverride(true);

            if (gEnv->bMultiplayer)
                pAnimatedCharacter->EnableRigidCollider(0.5f);
            else if (m_pControlledPlayer->IsPlayer())
                pAnimatedCharacter->EnableRigidCollider(1.5f);

            pAnimatedCharacter->GetGroundAlignmentParams().SetFlag(eGA_AllowWithNoCollision, true);

            BATTLECHATTER(BC_WatchMyBack, m_pControlledPlayer->GetEntityId());
        }
}
void CInteractiveObjectRegistry::ApplyInteractionToObject(IEntity *pEntity, const TagID interactionTypeTag, const int interactionIndex) const
{
	if (m_pDatabaseObject && m_pControllerDef)
	{
		IMannequin &mannequinSys = gEnv->pGame->GetIGameFramework()->GetMannequinInterface();
		SAnimationContext animContext(*m_pControllerDef);

		IActionController *pActionController = mannequinSys.CreateActionController(pEntity, animContext);

		int scopeContextID = m_pControllerDef->m_scopeContexts.Find("SlaveObject");
		pActionController->SetScopeContext(scopeContextID, *pEntity, pEntity->GetCharacter(0), m_pDatabaseObject);
		TagState fragTags = TAG_STATE_EMPTY;
		const CTagDefinition *pTagDef = m_pControllerDef->GetFragmentTagDef(m_interactFragID);
		if (pTagDef)
		{
			pTagDef->Set(fragTags, interactionTypeTag, true);
		}
		IAction *pAction = new TAction<SAnimationContext>(0, m_interactFragID, fragTags);
		pAction->SetOptionIdx(interactionIndex);
		pActionController->Queue(pAction);

		// Set the time increments to non-zero to force the ActionController::Update() to drive the animation to the end.
		// When time increment is zero, animation position will not update. This will be changed to a simpler process by Tom Berry at some point.
		const uint32 totalScopes = pActionController->GetTotalScopes();
		for(uint32 s=0; s<totalScopes; ++s)
		{
			pActionController->GetScope(s)->IncrementTime(0.001f);
		}
		pActionController->Update(1000.0f);
		// "false" here leaves the anim on the transition queue in the animation system so it isn't cleared on pActionController->Release().
		pActionController->ClearScopeContext(scopeContextID, false);

		pActionController->Release();

		CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
		if (pRecordingSystem)
		{
			pRecordingSystem->OnInteractiveObjectFinishedUse(pEntity->GetId(), interactionTypeTag, interactionIndex);
		}

	}
}
示例#6
0
void CActionCoopAnimation::Enter()
{
	TPlayerAction::Enter();

	QuatT targetPos(m_rootScope->GetEntity().GetPos(), m_rootScope->GetEntity().GetRotation());

	SetParam("TargetPos", targetPos);
	CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
	if (pRecordingSystem)
	{
		pRecordingSystem->OnMannequinSetParam(m_rootScope->GetEntityId(), "TargetPos", targetPos);
	}

	IAnimatedCharacter* pAnimChar				= m_player.GetAnimatedCharacter();
	IAnimatedCharacter* pAnimCharTarget = m_target.GetAnimatedCharacter();

	if( pAnimChar )
	{
		pAnimChar->SetMovementControlMethods(eMCM_Animation, eMCM_Animation);
		pAnimChar->RequestPhysicalColliderMode(eColliderMode_Disabled, eColliderModeLayer_Game, "CActionStealthKill::Enter()");
	}
	if (pAnimCharTarget)
	{
		pAnimCharTarget->SetMovementControlMethods(eMCM_Animation, eMCM_Animation);
		pAnimCharTarget->RequestPhysicalColliderMode(eColliderMode_Disabled, eColliderModeLayer_Game, "CActionStealthKill::Enter()");
	}

	PlayerCameraAnimationSettings cameraAnimationSettings;
	cameraAnimationSettings.positionFactor = 1.0f;
	cameraAnimationSettings.rotationFactor = 1.0f;
	cameraAnimationSettings.stableBlendOff = true;
	m_player.PartialAnimationControlled( true, cameraAnimationSettings );
	m_player.GetActorStats()->animationControlledID = m_target.GetEntityId();
	m_player.HolsterItem(true);

	// Update visibility to change render mode of 1st person character
	m_player.RefreshVisibilityState();

	// Mannequin can't set the tag's correctly on the exit, so we have to do it immediately after we started instead :)
	// the tags are set, but Exit() is called too late for our purposes, it is needed during the resolve of the next action
	m_rootScope->GetActionController().GetContext().state.Set(m_targetTagID, false);
}
示例#7
0
void CActionCoopAnimation::RemoveTargetFromSlaveContext()
{
	IAnimatedCharacter* pTargetAnimChar = m_targetEntityID ? m_target.GetAnimatedCharacter() : NULL;
	IActionController* pTargetActionController = pTargetAnimChar ? pTargetAnimChar->GetActionController() : NULL;

	if(pTargetActionController)
	{
		IAnimatedCharacter* pAnimChar = m_player.GetAnimatedCharacter();
		IActionController* pActionController = pAnimChar->GetActionController();
		pActionController->SetSlaveController(*pTargetActionController, PlayerMannequin.contextIDs.SlaveChar, false, m_piOptionalTargetDatabase);

		CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
		if (pRecordingSystem)
		{
			pRecordingSystem->OnMannequinSetSlaveController(m_rootScope->GetEntityId(), pTargetActionController->GetEntityId(), PlayerMannequin.contextIDs.SlaveChar, false, m_piOptionalTargetDatabase);
		}
	}
	else
	{
		m_rootScope->GetActionController().ClearScopeContext(PlayerMannequin.contextIDs.SlaveChar);
	}
}
示例#8
0
//--------------------------------------------------------------------------------------------------
// Name: SpawnScreenExplosionEffect
// Desc: Spawns screen explosion effect
//--------------------------------------------------------------------------------------------------
void CExplosionGameEffect::SpawnScreenExplosionEffect(const SExplosionContainer &explosionContainer)
{
	// Disclaimer: this code was originally from GameRulesClientServer::ProcessClientExplosionScreenFX()

	const ExplosionInfo& explosionInfo = explosionContainer.m_explosionInfo;

	if(explosionInfo.pressure < 1.0f)
		return;

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

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

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

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

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

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

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

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

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

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

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

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

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

					NET_BATTLECHATTER(BC_Blinded, pPlayer);

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

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

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

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

				if (pClientActor)
				{
					static_cast<CActor*>(pClientActor)->AddAngularImpulse(Ang3(cry_random(-angleX*0.5f,angleX),0.0f,cry_random(-angleZ,angleZ)),0.0f,dt*2.0f);
				}
			}
		}
	}
}//-------------------------------------------------------------------------------------------------
void CGameRulesMPActorAction::OnActorAction(IActor *pActor, const ActionId& actionId, int activationMode, float value)
{
	CActor *pActorImpl = static_cast<CActor *>(pActor);
	if (pActorImpl)
	{
		EntityId  pid = pActor->GetEntityId();  // player id

		CGameRules *pGameRules = g_pGame->GetGameRules();
		IGameRulesSpectatorModule *specmod = pGameRules->GetSpectatorModule();

		if (!specmod || (pActorImpl->GetSpectatorMode() <= 0))
		{
			// Not in spectator mode

			if (pActorImpl->IsDead())
			{
				// if dead 

				CRecordingSystem *crs = g_pGame->GetRecordingSystem();

				if (crs != NULL && crs->IsPlayingBack())
				{
					// Recording system playing back 
					if (actionId == g_pGame->Actions().spectate_gen_skipdeathcam && g_pGameCVars->kc_canSkip )
						crs->StopPlayback();
				}
				else if ((actionId == g_pGame->Actions().spectate_gen_spawn || actionId == g_pGame->Actions().hud_mouseclick) && activationMode == eAAM_OnPress && pActorImpl->GetSpectatorState() != CActor::eASS_SpectatorMode)
				{
					// Revive requested.
					//	This may happen immediately or not at all.

					if (IGameRulesSpawningModule* pSpawningModule=pGameRules->GetSpawningModule())
					{
						IGameRulesStateModule*  stateModule = pGameRules->GetStateModule();
						if (!stateModule || (stateModule->GetGameState() != IGameRulesStateModule::EGRS_PostGame))
						{
							CryLog("CGameRulesMPActorAction::OnActorAction() Requesting revive");
							pSpawningModule->ClRequestRevive(pActor->GetEntityId());
						}
					}
				}
				else if ((specmod != NULL && specmod->CanChangeSpectatorMode(pid)) && (((actionId == g_pGame->Actions().spectate_gen_nextmode) || (actionId == g_pGame->Actions().spectate_gen_prevmode)) && (activationMode == eAAM_OnPress)))  
				{
					// get into spectate mode
					if (!crs || !crs->IsPlayingOrQueued())
					{
						specmod->ChangeSpectatorModeBestAvailable(pActor, false);
					}
				}
			}
		}
		else
		{
			// is spectating

			int  curspecmode = pActorImpl->GetSpectatorMode();
			int  curspecstate = pActorImpl->GetSpectatorState();

			const CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
			// actions general across almost all spectator modes
			if( (curspecmode == CActor::eASM_Killer && !g_pGameCVars->g_killercam_canSkip) || (pRecordingSystem && pRecordingSystem->IsPlayingBack()) )
			{
				// Can't change mode or respawn-request, when in KillerCam mode or watching Killcam.
			}
			else if ((actionId == g_pGame->Actions().spectate_gen_spawn) && (activationMode == eAAM_OnPress) && pActorImpl->GetSpectatorState() != CActor::eASS_SpectatorMode)
			{
				IGameRulesSpawningModule *pSpawningModule = pGameRules->GetSpawningModule();
				if (pSpawningModule)
				{
					IGameRulesStateModule*  stateModule = pGameRules->GetStateModule();
					if (!stateModule || (stateModule->GetGameState() != IGameRulesStateModule::EGRS_PostGame))
					{
						CryLog("CGameRulesMPActorAction::OnActorAction() Spectating, received spectate_gen_spawn action, requesting revive");
						pSpawningModule->ClRequestRevive(pActor->GetEntityId());
					}			
				}			
			}
			else if (((actionId == g_pGame->Actions().spectate_gen_nextmode) || (actionId == g_pGame->Actions().spectate_gen_prevmode)) && (activationMode == eAAM_OnPress))
			{
				CryLog("[tlh] > changemode button pressed");
				if (specmod->CanChangeSpectatorMode(pid))
				{
					CryLog("[tlh] > can change");
					int  mode;
					EntityId  othEntId;
					mode = specmod->GetNextMode(pid, ((actionId == g_pGame->Actions().spectate_gen_nextmode) ? 1 : -1), &othEntId);
					if (mode != curspecmode)
					{
						CryLog("[tlh] > changing to mode %d with othEnt %d",mode,othEntId);
						specmod->ChangeSpectatorMode(pActor, mode, othEntId, false);
					}
				}
			}
			else
			{
				// actions specific to individual spectator modes

				if (specmod->CanChangeSpectatorMode(pid))  // "CanChangeSpectatorMode?" is essentially "CanInteractWithSpectatorMode?" - ie. we don't want to be able to do any of this on the Join Game screen
				{
					if (curspecmode == CActor::eASM_Fixed)
					{
						int  changeCam = 0;

						if (((actionId == g_pGame->Actions().spectate_cctv_nextcam) || (actionId == g_pGame->Actions().spectate_cctv_prevcam)) && (activationMode == eAAM_OnPress))
						{
							changeCam = (actionId == g_pGame->Actions().spectate_cctv_nextcam ? 1 : -1);
						}
						else if (actionId == g_pGame->Actions().spectate_cctv_changecam_xi)
						{
							if (value >= 1.f)
							{
								changeCam = 1;
							}
							else if (value <= -1.f)
							{
								changeCam = -1;
							}
						}

						if (changeCam != 0)
						{
							EntityId  locationId;

							if (changeCam > 0)
							{
								locationId = specmod->GetNextSpectatorLocation(pActorImpl);
							}
							else
							{
								locationId = specmod->GetPrevSpectatorLocation(pActorImpl);
							}

							pActorImpl->SetSpectatorFixedLocation(locationId);
						}
					}
					else if (curspecmode == CActor::eASM_Free)
					{
						;  // none
					}
					else if (curspecmode == CActor::eASM_Follow)
					{
						int  change = 0;

						const CGameActions& actions = g_pGame->Actions();

						if (((actionId == actions.spectate_3rdperson_nextteammate) || (actionId == actions.spectate_3rdperson_prevteammate)) && (activationMode == eAAM_OnPress))
						{
							change = ((actionId == actions.spectate_3rdperson_nextteammate) ? 1 : -1);
						}
						else if (actionId == actions.spectate_3rdperson_changeteammate_xi)
						{
							if (value >= 1.f)
							{
								change = 1;
							}
							else if (value <= -1.f)
							{
								change = -1;
							}
						}
						else if(actionId == actions.xi_rotateyaw && pActorImpl->CanSpectatorOrbitYaw())
						{
							pActorImpl->SetSpectatorOrbitYawSpeed(fabs(value) > 0.2f ? value : 0.f, false);
						}
						else if(actionId == actions.rotateyaw && pActorImpl->CanSpectatorOrbitYaw())
						{
							pActorImpl->SetSpectatorOrbitYawSpeed(value * g_pGameCVars->g_spectate_follow_orbitMouseSpeedMultiplier, true);
						}
						else if(actionId == actions.xi_rotatepitch && pActorImpl->CanSpectatorOrbitPitch())
						{
							float val = fabs(value) > 0.2f ? value : 0.f;
							if(val && g_pGameCVars->cl_invertController)
							{
								val = -value;
							}
							pActorImpl->SetSpectatorOrbitPitchSpeed(val, false);
						}
						else if(actionId == actions.rotatepitch && pActorImpl->CanSpectatorOrbitPitch())
						{
							float val = fabs(value) > 0.2f ? value : 0.f;
							if(val && g_pGameCVars->cl_invertMouse)
							{
								val = -val;
							}
							pActorImpl->SetSpectatorOrbitPitchSpeed(val * g_pGameCVars->g_spectate_follow_orbitMouseSpeedMultiplier, true);
						}
						else if(actionId == actions.spectate_gen_nextcamera)
						{
							pActorImpl->ChangeCurrentFollowCameraSettings(true);
						}

						if (change != 0)
						{
							if (EntityId newTargetId=specmod->GetNextSpectatorTarget(pid, change))
							{
								pActorImpl->SetSpectatorTarget(newTargetId);
							}
						}
					}
					else if (curspecmode == CActor::eASM_Killer)
					{
						;  // none
					}
				}
			}
		}

		pGameRules->ActorActionInformOnAction(actionId, activationMode, value);
	}
}
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);
        }
}
//------------------------------------------------------------------------
int CTracerManager::EmitTracer(const STracerParams &params, const EntityId bulletId)
{
	if(!gEnv->IsClient())
		return -1;

	CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
	if (pRecordingSystem)
	{
		if (!pRecordingSystem->OnEmitTracer(params))
		{
			return -1;
		}
	}

	int idx = 0;

	if(m_numActiveTracers < kMaxNumTracers)
	{
		//Add to end of array
		idx = m_numActiveTracers;
		m_tracerPool[idx].CreateEntity();
		m_tracerPool[idx].Reset(params.position, params.destination);
		m_numActiveTracers++;
	}
	else
	{
		//Find the oldest existing tracer and remove
		assert(!"Too many tracers in existence! Removing oldest");

		float oldest = 0.0f;

		for(int i = 0; i < kMaxNumTracers; i++)
		{
			CryPrefetchUnsafe(&m_tracerPool[i+4]);
			if(m_tracerPool[i].m_age > oldest)
			{
				oldest = m_tracerPool[i].m_age;
				idx = i;
			}
		}

		m_tracerPool[idx].Reset(params.position, params.destination);
	}

	CTracer& tracer = m_tracerPool[idx];

	tracer.m_boundToBulletId = bulletId;
	tracer.m_tracerFlags = kTracerFlag_active;
	tracer.m_effectSlot = -1;
	tracer.m_geometryOpacity = params.geometryOpacity;
	if (params.geometry && params.geometry[0])
	{
		tracer.SetGeometry(params.geometry, params.scale);
		tracer.m_tracerFlags |= kTracerFlag_useGeometry;
	}

	tracer.SetLifeTime(params.lifetime);

	tracer.m_speed = params.speed;
	tracer.m_pos = params.position;
	tracer.m_startingPos = params.position;
	tracer.m_dest = params.destination;
	tracer.m_fadeOutTime = params.delayBeforeDestroy;
	
	if(params.scaleToDistance)
	{
		tracer.m_tracerFlags |= kTracerFlag_scaleToDistance;
	}

  if(params.dontTranslate)
  {
    tracer.m_tracerFlags |= kTracerFlag_dontTranslate;
  }

	if(params.updateDestPosFromBullet)
	{
		tracer.m_tracerFlags |= kTracerFlag_updateDestFromBullet;
	}
	
	tracer.m_startFadeOutTime = params.startFadeOutTime;
	tracer.m_scale = params.scale;
	tracer.m_slideFrac = params.slideFraction;

	if (IEntity *pEntity=gEnv->pEntitySystem->GetEntity(tracer.m_entityId))
	{
		pEntity->Hide(0);
	}

	// set effect after unhiding the entity, or else the particle emitter is created hidden
	if (params.effect && params.effect[0])
		tracer.SetEffect(params.effect, params.scale);

	return idx;
}
示例#12
0
//-------------------------------------------------------------------------
void CGameRulesStandardState::EnterPostGameState( EPostGameState state )
{
#ifndef _RELEASE
	if(g_pGameCVars->g_hud_postgame_debug)
	{
		CryLog("HUD PostGame - Entering new state %i from %i after %.2f seconds", (int)state, (int)m_postGameState, m_timeInCurrentPostGameState);
	}
#endif

	m_timeInCurrentPostGameState = 0.f;
	m_postGameState = state;

	switch (m_postGameState)
	{
		case ePGS_FinalKillcam:
		{
			if (g_pGameCVars->kc_enableWinningKill)
			{
				CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
				if (pRecordingSystem)
				{
					if(pRecordingSystem->IsPlaybackQueued())
					{
						if(!pRecordingSystem->PlayWinningKillcam())
						{
							CRY_ASSERT_MESSAGE(false, "There should be a Winning Kill queued up when we get here...");
						}
					}
					else
					{
						CRY_ASSERT_MESSAGE(false, "There should be a Winning Kill queued up when we get here...");
					}
				}
			}
			break;
		}
		case ePGS_HighlightReel:
		{
			bool canPlayHighlightReel = false;

			//Reset to standard style
			SHUDEvent postEvent(eHUDEvent_ResetHUDStyle);
			CHUDEventDispatcher::CallEvent(postEvent);

			CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
			if (pRecordingSystem)
			{
				if (!(pRecordingSystem->IsPlayingBack() || pRecordingSystem->IsPlaybackQueued()))
				{
					canPlayHighlightReel = pRecordingSystem->PlayAllHighlights(false);
#ifndef _RELEASE
					if(g_pGameCVars->g_hud_postgame_debug)
					{
						CryLog("HUD PostGame - Could play highlight reel = %s", canPlayHighlightReel ? "True" : "False");
					}
#endif
				}
			}

			//Change to fixed spectator mode
			IActor* pLocalActor = g_pGame->GetIGameFramework()->GetClientActor();
			IGameRulesSpectatorModule* pSpecMod = g_pGame->GetGameRules()->GetSpectatorModule();
			EntityId specEntity = 0;
			if(pLocalActor && pSpecMod && pSpecMod->ModeIsAvailable(pLocalActor->GetEntityId(), CActor::eASM_Fixed, &specEntity))
			{
				pSpecMod->ChangeSpectatorMode(pLocalActor, CActor::eASM_Fixed, specEntity, true, true);
			}
#ifndef _RELEASE
			else if(g_pGameCVars->g_hud_postgame_debug)
			{
				CryLog("HUD PostGame - Failed to change spectator mode when entering highlight reel");
			}
#endif

			if(canPlayHighlightReel)
			{
				m_bHasShownHighlightReel = true;
			}
			break;
		}
		case ePGS_Top3:
		{
			g_pGame->GetUI()->ActivateDefaultState();

			SHUDEvent scoreboardVisibleEvent( eHUDEvent_MakeMatchEndScoreboardVisible );
			scoreboardVisibleEvent.AddData(true);
			CHUDEventDispatcher::CallEvent(scoreboardVisibleEvent);

			break;
		}
		case ePGS_Scoreboard:
		{
			CryLog("HUD PostGame - Activating default state for scoreboard");
			// Activating the default state while in this postgame state will cause the scoreboard to show
			g_pGame->GetUI()->ActivateDefaultState();
			break;
		}
	}
}
示例#13
0
//-------------------------------------------------------------------------
void CGameRulesStandardState::Update( float frameTime )
{
	if (gEnv->bServer)
	{
		if(m_state == EGRS_Intro)
		{
			// We assume there is an intro, if we reach this point and an intro hasnt been registered, we know there isn't one. Onwards and upwards. 
			if(!m_pGameRules->IsIntroSequenceRegistered())
			{
				ChangeState(EGRS_PreGame); 
			}
		}

		if (m_state == EGRS_PreGame)
		{
			if (m_isStarting)
			{
				const float remainingTime = m_pGameRules->GetRemainingStartTimer();
				if (remainingTime <= 0.f)
				{
					CryLog("CGameRulesStandardState::Update(), starting game");

					ChangeState(EGRS_InGame);
				}
			}
			else
			{
				bool bOk = true;
				CGameLobby* pGameLobby = g_pGame->GetGameLobby();
				const int numPlayers = m_pGameRules->GetPlayerCount(true);

				if (pGameLobby)
				{
					if (m_isWaitingForOverrideTimer)
					{
						//-- test override timer
						m_startTimerOverrideWait -= frameTime;
						bOk = (m_startTimerOverrideWait <= 0.0f);

						if (!bOk)
						{
							bOk = true;

							//-- testing min player count doesn't apply to private games
							const bool publicGame = !pGameLobby->IsPrivateGame();
							const bool onlineGame = pGameLobby->IsOnlineGame();
							if (publicGame && onlineGame)
							{
								// Start only when we have enough players
								if (m_pGameRules->GetTeamCount() > 1)
								{
									//-- team game, insist at least 1 player per team
									const int numPlayersPerTeamMin = g_pGameCVars->g_gameRules_startTimerMinPlayersPerTeam;
									const int numPlayersTeam1 = m_pGameRules->GetTeamPlayerCount(1, true);
									const int numPlayersTeam2 = m_pGameRules->GetTeamPlayerCount(2, true);

									bOk = ((numPlayersTeam1 >= numPlayersPerTeamMin) && (numPlayersTeam2 >= numPlayersPerTeamMin));
								}
								else
								{
									//-- not a team game, so just insist on minimum 2 players
									const int numPlayersMin = g_pGameCVars->g_gameRules_startTimerMinPlayers;
									bOk = (numPlayers >= numPlayersMin);
								}
								const int numPlayersInLobby = pGameLobby->GetSessionNames().Size();
								bOk |= (numPlayersInLobby == numPlayers);
							}

							if (bOk)
							{
								//-- Enforce a percentage of lobby players in game before starting countdown
								bOk = (!gEnv->IsClient() || (g_pGame->GetClientActorId() != 0)) && CheckInitialChannelPlayers();
							}
						}
					}
					else
					{
						bOk = false;

						if (numPlayers)
						{
							//-- Start the override timer. 
							m_startTimerOverrideWait = g_pGameCVars->g_gameRules_startTimerOverrideWait;
							m_isWaitingForOverrideTimer = true;
						}
					}
				}

				if (bOk)
				{
					CryLog("CGameRulesStandardState::Update(), we have %i players, starting the game", numPlayers);
					float startTimeLength = 
#if !defined(_RELEASE)
						g_pGameCVars->g_gameRules_skipStartTimer ? 0.0f : 
#endif
						g_pGameCVars->g_gameRules_startTimerLength;

#if USE_PC_PREMATCH
					bool bDoPCPrematch = false;

					CGameRules::EPrematchState prematchState = m_pGameRules->GetPrematchState();
					if (prematchState==CGameRules::ePS_Prematch)
					{
						int numRequiredPlayers = g_pGameCVars->g_minPlayersForRankedGame - m_pGameRules->GetPlayerCount(true);
						if ((numRequiredPlayers > 0) || (pGameLobby && pGameLobby->UseLobbyTeamBalancing() && !pGameLobby->IsGameBalanced()))
						{
							bDoPCPrematch = true;

							CPlaylistManager *pPlaylistManager = g_pGame->GetPlaylistManager();
							if (pGameLobby && pPlaylistManager)
							{
								if (!pGameLobby->IsRankedGame() || pPlaylistManager->IsUsingCustomVariant())
								{
									// Private games don't do prematch
									bDoPCPrematch = false;
								}
							}

							if (bDoPCPrematch)
							{
								// If we are waiting for players on pc, spawn ingame and set a prematch state which waits for players.
								m_pGameRules->StartPrematch();
								startTimeLength = 0.f;
							}
						}

						if (!bDoPCPrematch)
						{
							m_pGameRules->SkipPrematch();
						}
					}
#endif

					m_pGameRules->ResetGameStartTimer(startTimeLength);
					StartCountdown(true);
				}
			}
		}
		else if (m_state == EGRS_PostGame)
		{
			const float prevUpdateStamp = m_timeInPostGame;
			const float timeInPost = (prevUpdateStamp + frameTime);

			const float timeToShowHUDMessage = g_pGameCVars->g_gameRules_postGame_HUDMessageTime;
			const float timeToShowTop3 = g_pGameCVars->g_gameRules_postGame_Top3Time;
			const float timeToShowScoreboard = g_pGameCVars->g_gameRules_postGame_ScoreboardTime;
			float killcamLength = m_pGameRules->GameEndedByWinningKill() ? g_pGameCVars->kc_length : 0.f;
			if (g_pGameCVars->kc_showHighlightsAtEndOfGame)
			{
				CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
				if(pRecordingSystem)
				{
					killcamLength += pRecordingSystem->GetHighlightsReelLength();
					killcamLength = min(killcamLength, 20.f);
				}
			}

			const float totalPostGameTime = timeToShowHUDMessage + timeToShowTop3 + timeToShowScoreboard + killcamLength;

			if (timeInPost > totalPostGameTime)
			{
				CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
				if (!pRecordingSystem || (!pRecordingSystem->IsPlaybackQueued() && !pRecordingSystem->IsPlayingBack()))
				{
					CGameLobby *pGameLobby = g_pGame->GetGameLobby();
					if (pGameLobby)
					{
						CryLog("[GameRules] Server trying to return to lobby");
						pGameLobby->SvFinishedGame(frameTime);
					}
				}
				else if(pRecordingSystem)
				{
					pRecordingSystem->StopHighlightReel();
				}
			}

			m_timeInPostGame = timeInPost;
		}
	}

	CPlayer * pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetClientActor());
	if((pPlayer && pPlayer->ShouldPlayIntro() || gEnv->bServer) && m_pGameRules->IsIntroSequenceRegistered() && !m_bHaveNotifiedIntroListeners)
	{
		// All flowgraph nodes that want to listen, should be created at this point
		OnIntroStart_NotifyListeners();
	}
	

#ifndef _RELEASE
	if(g_pGameCVars->g_hud_postgame_debug)
	{
		const char* stateName = "";
		switch(m_state)
		{
		case EGRS_Reset: { stateName = "EGRS_Reset"; break;}
		case EGRS_Intro: { stateName = "EGRS_Intro"; break;}
		case EGRS_PreGame: { stateName = "EGRS_PreGame"; break;}
		case EGRS_InGame: { stateName = "EGRS_InGame"; break;}
		case EGRS_PostGame: { stateName = "EGRS_PostGame"; break;}
		case EGRS_MAX: { stateName = "EGRS_MAX"; break;}
		}
		CryWatch("GameRulesStandardState - State = %s", stateName);

		if(m_state == EGRS_PostGame)
		{
			const char* postGameStateName = "";
			switch(m_postGameState)
			{
			case ePGS_Unknown: { postGameStateName = "ePGS_Unknown"; break; }
			case ePGS_Starting: { postGameStateName = "ePGS_Starting"; break; }
			case ePGS_HudMessage: { postGameStateName = "ePGS_HudMessage"; break; }
			case ePGS_FinalKillcam: { postGameStateName = "ePGS_FinalKillcam"; break; }
			case ePGS_HighlightReel: { postGameStateName = "ePGS_HighlightReel"; break; }
			case ePGS_Top3: { postGameStateName = "ePGS_Top3"; break; }
			case ePGS_Scoreboard: { postGameStateName = "ePGS_Scoreboard"; break; }
			}
			CryWatch("GameRulesStandardState -PostGameState = %s", postGameStateName);

		}
	}
#endif

	if (gEnv->IsClient())
	{
		if (m_state == EGRS_PreGame)
		{
			if( !gEnv->IsDedicated() )
			{
				if (m_isStarting)
				{
					const float timeTillStartInSeconds = m_pGameRules->GetRemainingStartTimer();
					SHUDEventWrapper::UpdateGameStartCountdown( ePreGameCountdown_MatchStarting, timeTillStartInSeconds );
				}
				else
				{
					SHUDEventWrapper::UpdateGameStartCountdown( ePreGameCountdown_WaitingForPlayers, 0.0f );
				}
			}
		}
		else if (m_state == EGRS_InGame && !gEnv->IsDedicated() )
		{
			if (m_introMessageShown == false)	// Show only once
			{
				CGameRules *pGameRules = g_pGame->GetGameRules();
				if (pGameRules && pGameRules->HasGameActuallyStarted())
				{
					if (EntityId localPlayerId = g_pGame->GetIGameFramework()->GetClientActorId())
					{
						int teamId = g_pGame->GetGameRules()->GetTeam(localPlayerId);
						bool bTeamGame = (pGameRules->GetTeamCount() > 1);

						IActor *pActor = g_pGame->GetIGameFramework()->GetClientActor();
						if (pActor->GetSpectatorMode()==CActor::eASM_None && !pActor->IsDead() && (!bTeamGame || teamId!=0))
						{
							if (IGameRulesPlayerStatsModule *statsModule = pGameRules->GetPlayerStatsModule())
							{
								const SGameRulesPlayerStat *stats = statsModule->GetPlayerStats(localPlayerId);
								if (stats->deaths <= 0) // Not died ever
								{
									if (m_startMatchString.empty() == false)
									{
										const char* gamemodeName = g_pGame->GetGameRules()->GetEntity()->GetClass()->GetName();

										CryFixedStringT<32> strSignalName;
										strSignalName.Format("StartGame%s", gamemodeName);
										TAudioSignalID signalId = g_pGame->GetGameAudio()->GetSignalID(strSignalName);

										CryFixedStringT<64> localisedStartString = CHUDUtils::LocalizeString( m_startMatchString.c_str() );

										if (bTeamGame)
										{
											CryFixedStringT<16> strTeamName;
											strTeamName.Format("@ui_hud_team_%d", teamId);
											
											SHUDEventWrapper::TeamMessage(strTeamName.c_str(), teamId, SHUDEventWrapper::SMsgAudio(signalId), false, true);
											SHUDEventWrapper::SimpleBannerMessage(localisedStartString.c_str(), SHUDEventWrapper::kMsgAudioNULL);
										}
										else
										{
											SHUDEventWrapper::RoundMessageNotify(localisedStartString.c_str(), SHUDEventWrapper::SMsgAudio(signalId));
										}
									}
								}
							}

							m_introMessageShown = true; // Or not if has already died, but don't check again anyway.
						}
					}
				}
			}
		}
		else if(m_state == EGRS_PostGame && !gEnv->IsDedicated())
		{
			if (!gEnv->bServer)
			{
				m_timeInPostGame += frameTime;
			}

			m_timeInCurrentPostGameState += frameTime;

			switch (m_postGameState)
			{
				case ePGS_Starting:
				{
					CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
					if (pRecordingSystem != NULL && (pRecordingSystem->IsPlayingBack() || pRecordingSystem->IsPlaybackQueued()))
					{
						// Currently showing a killcam, skip to the killcam stage of the postgame flow
						EnterPostGameState(ePGS_FinalKillcam);
					}
					else
					{
						if (m_pGameRules->GetRoundsModule())
						{
							EnterPostGameState(ePGS_Top3);
						}
						else
						{
							EnterPostGameState(ePGS_HudMessage);
						}
					}
					break;
				}
				case ePGS_HudMessage:
				{
					if (m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_HUDMessageTime)
					{
						EnterPostGameState(ePGS_FinalKillcam);
					}
					break;
				}
				case ePGS_FinalKillcam:
				{
					CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
					if (!pRecordingSystem || !(pRecordingSystem->IsPlayingBack() || (pRecordingSystem->IsPlaybackQueued() && pRecordingSystem->HasWinningKillcam())))
					{
						EnterPostGameState(ePGS_Top3);
					}
#ifndef _RELEASE
					else if(g_pGameCVars->g_hud_postgame_debug && pRecordingSystem)
					{
						CryWatch("PostGameState - Waiting for final killcam to end:"); 
						CryWatch("IsPlaybackQueued: %s, IsPlayingBack: %s", 
							pRecordingSystem->IsPlaybackQueued() ? "True" : "False", pRecordingSystem->IsPlayingBack() ? "True" : "False");
					}
#endif
					break;
				}
				case ePGS_HighlightReel:
				{
					CRecordingSystem* pRecordingSystem = g_pGame->GetRecordingSystem();
					if (!pRecordingSystem || (!pRecordingSystem->IsPlaybackQueued() && !pRecordingSystem->IsPlayingBack()))
					{
						CGameLobby *pGameLobby = g_pGame->GetGameLobby();
						if (pGameLobby)
						{
							CryLog("[GameRules] Client trying to return to lobby");
							pGameLobby->SvFinishedGame(frameTime);
							EnterPostGameState(ePGS_LeavingGame);
						}
					}
#ifndef _RELEASE
					else if(g_pGameCVars->g_hud_postgame_debug && pRecordingSystem)
					{
						CryWatch("PostGameState - Waiting for highlight reel to end:");
						CryWatch("IsPlaybackQueued: %s, IsPlayingBack: %s, IsPlayingHighlightsReel: %s", 
							pRecordingSystem->IsPlaybackQueued() ? "True" : "False", pRecordingSystem->IsPlayingBack() ? "True" : "False", pRecordingSystem->IsPlayingHighlightsReel() ? "True" : "False");
					}
#endif
					break;
				}
				case ePGS_Top3:
				{
					if (m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_Top3Time)
					{
						EnterPostGameState(ePGS_Scoreboard);
					}
					break;
				}
				case ePGS_Scoreboard:
				{
					if(m_timeInCurrentPostGameState > g_pGameCVars->g_gameRules_postGame_ScoreboardTime)
					{
						if(!m_bHasShownHighlightReel && g_pGameCVars->kc_showHighlightsAtEndOfGame)
						{
							EnterPostGameState(ePGS_HighlightReel);
						}
						else
						{
							CGameLobby *pGameLobby = g_pGame->GetGameLobby();
							if (pGameLobby)
							{
								CryLog("[GameRules] Client trying to return to lobby [No highlight reel]");
								pGameLobby->SvFinishedGame(frameTime);
							}
						}
					}
					break;
				}
			}
		}
	}
}