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); } } }
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); }
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); } }
//-------------------------------------------------------------------------------------------------- // 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 ¶ms, 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; }
//------------------------------------------------------------------------- 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; } } }
//------------------------------------------------------------------------- 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; } } } } }