void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo ) { switch (event) { case eFE_Initialize: { CGameRules* pGameRules = g_pGame->GetGameRules(); if(pGameRules) pGameRules->AddGameRulesListener(this); CPlayer* pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetClientActor()); if(pPlayer) m_localPlayerSpectatorMode = pPlayer->GetSpectatorMode(); m_actInfo = *pActInfo; } break; case eFE_Activate: break; case eFE_Update: { CPlayer* pPlayer = static_cast<CPlayer*>(g_pGame->GetIGameFramework()->GetClientActor()); if(!pPlayer) return; // first check: tac weapons trigger endgamenear / endgameinvalid if(m_MDList.empty() && m_endGameNear) { // if less than 3 min remaining don't return to normal bool cancel = true; if(g_pGame && g_pGame->GetGameRules() && g_pGame->GetGameRules()->IsTimeLimited() && m_timeRemainingTriggered) { float timeRemaining = g_pGame->GetGameRules()->GetRemainingGameTime(); if(timeRemaining < GetPortFloat(pActInfo, EIP_GameEndTime) ) cancel = false; } if(cancel) { if(g_pGame->GetCVars()->i_debug_mp_flowgraph != 0) { CryLog("MP flowgraph: EndGameInvalid"); } ActivateOutput(&m_actInfo, EOP_EndGameInvalid, true); m_endGameNear = false; } } else if(!m_MDList.empty()) { // go through the list of tac/sing weapons and check if they are still present std::list<EntityId>::iterator next; std::list<EntityId>::iterator it = m_MDList.begin(); for(; it != m_MDList.end(); it = next) { next = it; ++next; if(gEnv->pEntitySystem->GetEntity(*it)) { // entity exists so trigger loud music if not already done if(!m_endGameNear) { if(g_pGame->GetCVars()->i_debug_mp_flowgraph != 0) { CryLog("--MP flowgraph: EndGameNear"); } ActivateOutput(&m_actInfo, EOP_EndGameNear, true); m_endGameNear = true; } // in the case of tanks, entity isn't removed for quite some time after destruction. // Check vehicle health directly here... IVehicle* pVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(*it); if(pVehicle && pVehicle->IsDestroyed()) { m_MDList.erase(it); } } else { // entity no longer exists - remove from list. m_MDList.erase(it); } } } // get the remaining time from game rules if(!m_timeRemainingTriggered && g_pGame->GetGameRules() && g_pGame->GetGameRules()->IsTimeLimited() && pPlayer->GetSpectatorMode() == 0 && !m_endGameNear) { float timeRemaining = g_pGame->GetGameRules()->GetRemainingGameTime(); if(timeRemaining < GetPortFloat(pActInfo, EIP_GameEndTime) ) { if(g_pGame->GetCVars()->i_debug_mp_flowgraph != 0) { CryLog("--MP flowgraph: EndGameNear"); } ActivateOutput(&m_actInfo, EOP_EndGameNear, timeRemaining); m_timeRemainingTriggered = true; m_endGameNear = true; } } // also check whether the local player is in game yet if(pPlayer->GetSpectatorMode() == 0 && m_localPlayerSpectatorMode != 0) { if(g_pGame->GetCVars()->i_debug_mp_flowgraph != 0) { CryLog("--MP flowgraph: EnteredGame"); } ActivateOutput(&m_actInfo, EOP_EnteredGame, true); m_localPlayerSpectatorMode = pPlayer->GetSpectatorMode(); } } break; } }
//----------------------------------------------------------------------------- void CHomingMissile::UpdateControlledMissile(float frameTime) { bool isServer = gEnv->bServer; bool isClient = gEnv->IsClient(); CActor *pClientActor=0; if(gEnv->IsClient()) pClientActor=static_cast<CActor *>(g_pGame->GetIGameFramework()->GetClientActor()); bool isOwner = ((!m_ownerId && isServer) || (isClient && pClientActor && (pClientActor->GetEntityId() == m_ownerId) && pClientActor->IsPlayer())); IRenderer *pRenderer = gEnv->pRenderer; IRenderAuxGeom *pGeom = pRenderer->GetIRenderAuxGeom(); float color[4] = {1,1,1,1}; const static float step = 15.f; float y = 20.f; bool bDebug = g_pGameCVars->i_debug_projectiles > 0; if(isOwner || isServer) { //If there's a target, follow the target if(isServer) { if(m_targetId) { if(m_lockedTimer>0.0f) m_lockedTimer=m_lockedTimer-frameTime; else { // If we are here, there's a target IEntity *pTarget = gEnv->pEntitySystem->GetEntity(m_targetId); if(pTarget) { AABB box; pTarget->GetWorldBounds(box); Vec3 finalDes = box.GetCenter(); SetDestination(finalDes); //SetDestination( box.GetCenter() ); if(bDebug) pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "Target Entity: %s", pTarget->GetName()); } m_lockedTimer+=0.05f; } } else if(m_autoControlled) return; } if(m_controlled && !m_autoControlled && isOwner && !m_targetId) { //Check if the weapon is still selected CWeapon *pWeapon = GetWeapon(); if(!pWeapon || !pWeapon->IsSelected()) return; if(m_controlledTimer>0.0f) m_controlledTimer=m_controlledTimer-frameTime; else if(pClientActor && pClientActor->IsPlayer()) //Follow the crosshair { if(IMovementController *pMC=pClientActor->GetMovementController()) { Vec3 eyePos(ZERO); Vec3 eyeDir(ZERO); IVehicle *pVehicle = pClientActor->GetLinkedVehicle(); if(!pVehicle) { SMovementState state; pMC->GetMovementState(state); eyePos = state.eyePosition; eyeDir = state.eyeDirection; } else { SViewParams viewParams; pVehicle->UpdateView(viewParams, pClientActor->GetEntityId()); eyePos = viewParams.position; eyeDir = viewParams.rotation * Vec3(0,1,0); //eyeDir = (viewParams.targetPos - viewParams.position).GetNormalizedSafe(); } static const int objTypes = ent_all; static const int flags = (geom_colltype_ray << rwi_colltype_bit) | rwi_colltype_any | (7 & rwi_pierceability_mask) | (geom_colltype14 << rwi_colltype_bit); IPhysicalWorld *pWorld = gEnv->pPhysicalWorld; static IPhysicalEntity *pSkipEnts[10]; int numSkip = CSingle::GetSkipEntities(pWeapon, pSkipEnts, 10); ray_hit hit; int hits = 0; hits = pWorld->RayWorldIntersection(eyePos + 1.5f*eyeDir, eyeDir*m_maxTargetDistance, objTypes, flags, &hit, 1, pSkipEnts, numSkip); DestinationParams params; if(hits) params.pt=hit.pt; else params.pt=(eyePos+m_maxTargetDistance*eyeDir); //Some point in the sky... GetGameObject()->InvokeRMI(SvRequestDestination(), params, eRMI_ToServer); if(bDebug) { pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "PlayerView eye direction: %.3f %.3f %.3f", eyeDir.x, eyeDir.y, eyeDir.z); pRenderer->Draw2dLabel(5.0f, y+=step, 1.5f, color, false, "PlayerView Target: %.3f %.3f %.3f", hit.pt.x, hit.pt.y, hit.pt.z); pRenderer->GetIRenderAuxGeom()->DrawCone(m_destination, Vec3(0,0,-1), 2.5f, 7.f, ColorB(255,0,0,255)); } } m_controlledTimer+=0.0f; } } } //This code is shared by both modes above (auto and controlled) if(!m_destination.IsZero()) { pe_status_dynamics status; if(!GetEntity()->GetPhysics()->GetStatus(&status)) { CryLogAlways("couldn't get physics status!"); return; } pe_status_pos pos; if(!GetEntity()->GetPhysics()->GetStatus(&pos)) { CryLogAlways("couldn't get physics pos!"); return; } float currentSpeed = status.v.len(); if(currentSpeed>0.001f) { Vec3 currentVel = status.v; Vec3 currentPos = pos.pos; Vec3 goalDir(ZERO); assert(!_isnan(currentSpeed)); assert(!_isnan(currentVel.x) && !_isnan(currentVel.y) && !_isnan(currentVel.z)); //Just a security check if((currentPos-m_destination).len2()<(m_detonationRadius*m_detonationRadius)) { Explode(true, true, m_destination, -currentVel.normalized(), currentVel, m_targetId); return; } goalDir = m_destination - currentPos; goalDir.Normalize(); //Turn more slowly... currentVel.Normalize(); if(bDebug) { pRenderer->Draw2dLabel(50,55,2.0f,color,false, " Destination: %.3f, %.3f, %.3f",m_destination.x,m_destination.y,m_destination.z); pRenderer->Draw2dLabel(50,80,2.0f,color,false, " Current Dir: %.3f, %.3f, %.3f",currentVel.x,currentVel.y,currentVel.z); pRenderer->Draw2dLabel(50,105,2.0f,color,false," Goal Dir: %.3f, %.3f, %.3f",goalDir.x,goalDir.y,goalDir.z); } float cosine = currentVel.Dot(goalDir); cosine = CLAMP(cosine,-1.0f,1.0f); float totalAngle = RAD2DEG(cry_acosf(cosine)); assert(totalAngle>=0); if(cosine<0.99) { float maxAngle = m_turnSpeed*frameTime; if(maxAngle>totalAngle) maxAngle=totalAngle; float t=(maxAngle/totalAngle)*m_lazyness; assert(t>=0.0 && t<=1.0); goalDir = Vec3::CreateSlerp(currentVel, goalDir, t); goalDir.Normalize(); } if(bDebug) pRenderer->Draw2dLabel(50,180,2.0f,color,false,"Corrected Dir: %.3f, %.3f, %.3f",goalDir.x,goalDir.y,goalDir.z); pe_action_set_velocity action; action.v = goalDir * currentSpeed; GetEntity()->GetPhysics()->Action(&action); } } }
void CPlayerRotation::Process(IItem* pCurrentItem, const SActorFrameMovementParams& movement, const SAimAccelerationParams& verticalAcceleration, float frameTime) { FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); // reset to the new impulse. m_angularImpulseDelta = m_angularImpulse; m_deltaAngles = movement.deltaAngles; PR_CHECKQNAN_FLT(m_deltaAngles); // Store the previous rotation to get the correct rotation for linked actors. const Quat previousBaseQuat = m_baseQuat; const Quat previousViewQuat = m_viewQuat; ProcessForcedLookDirection(m_viewQuatFinal, frameTime); ProcessAngularImpulses( frameTime ); ProcessLeanAndPeek( movement ); ProcessNormalRoll( frameTime ); bool shouldProcessTargetAssistance = ShouldProcessTargetAssistance(); if (shouldProcessTargetAssistance) { ProcessTargetAssistance( pCurrentItem ); } #if TALOS if(stricmp(g_pGameCVars->pl_talos->GetString(), m_player.GetEntity()->GetName()) == 0) { IMovementController* pMovementController = m_player.GetMovementController(); CRY_ASSERT(pMovementController); SMovementState moveState; pMovementController->GetMovementState(moveState); Vec3 playerView[4] = { m_viewQuat.GetColumn0(), // Right m_viewQuat.GetColumn1(), // Forward m_viewQuat.GetColumn2(), // Up moveState.eyePosition // Pos }; GetTalosInput(this, m_player, m_deltaAngles.x, m_deltaAngles.z, playerView, frameTime); } #endif float minAngle,maxAngle; GetStanceAngleLimits(verticalAcceleration, pCurrentItem, minAngle, maxAngle); ClampAngles( minAngle, maxAngle ); ProcessNormal( frameTime ); if(shouldProcessTargetAssistance) { IVehicle* pVehicle = m_player.GetLinkedVehicle(); if (pVehicle && GetCurrentItem(true)) { if (m_deltaAngles.x!=0.f) pVehicle->OnAction(eVAI_RotatePitchAimAssist, eAAM_Always, m_deltaAngles.x, m_player.GetEntity()->GetId()); if (m_deltaAngles.z!=0.f) pVehicle->OnAction(eVAI_RotateYawAimAssist, eAAM_Always, m_deltaAngles.z, m_player.GetEntity()->GetId()); } } //update freelook when linked to an entity ProcessLinkedState(m_player.m_linkStats, previousBaseQuat, previousViewQuat); //Recoil/Zoom sway offset for local player ProcessFinalViewEffects( minAngle, maxAngle ); m_frameViewAnglesOffset.Set(0.0f, 0.0f, 0.0f); m_forceLookVector.zero(); m_externalAngles.Set(0.f, 0.f, 0.f); NormalizeQuats(); }
//--------------------------------------------------------------------------- void CVehicleWeapon::CheckForFriendlyAI(float frameTime) { CActor* pOwner = GetOwnerActor(); if(pOwner && m_pVehicle && pOwner->IsPlayer() && !gEnv->bMultiplayer) { m_timeToUpdate-=frameTime; if(m_timeToUpdate>0.0f) return; m_timeToUpdate = 0.15f; if(IMovementController* pMC = pOwner->GetMovementController()) { SMovementState info; pMC->GetMovementState(info); LowerWeapon(false); //Try with boxes first bool success = false; //Try ray hit if(!success) { ray_hit rayhit; IPhysicalEntity* pSkipEnts[10]; int nSkip = CSingle::GetSkipEntities(this, pSkipEnts, 10); int intersect = gEnv->pPhysicalWorld->RayWorldIntersection(info.weaponPosition, info.aimDirection * 150.0f, ent_all, rwi_stop_at_pierceable|rwi_colltype_any, &rayhit, 1, pSkipEnts, nSkip); IEntity* pLookAtEntity = NULL; if(intersect && rayhit.pCollider) pLookAtEntity = m_pEntitySystem->GetEntityFromPhysics(rayhit.pCollider); if(pLookAtEntity && pLookAtEntity->GetAI() && pOwner->GetEntity() && pLookAtEntity->GetId()!=GetEntityId()) { bool bFriendlyVehicle = false; if( pLookAtEntity && pLookAtEntity->GetId() ) { IVehicle *pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(pLookAtEntity->GetId()); if ( pVehicle ) { if ( pOwner->GetEntity() && pVehicle->HasFriendlyPassenger( pOwner->GetEntity() ) ) bFriendlyVehicle = true; } } if(bFriendlyVehicle||!pLookAtEntity->GetAI()->IsHostile(pOwner->GetEntity()->GetAI(),false)) { LowerWeapon(true); StopFire();//Just in case success = true; m_pLookAtEnemy = NULL; } } else if(pLookAtEntity) { //Special case (Animated objects), check for script table value "bFriendly" SmartScriptTable props; IScriptTable* pScriptTable = pLookAtEntity->GetScriptTable(); if(!pScriptTable || !pScriptTable->GetValue("Properties", props)) return; int isFriendly = 0; if(props->GetValue("bNoFriendlyFire", isFriendly) && isFriendly!=0) { LowerWeapon(true); StopFire();//Just in case success = true; m_pLookAtEnemy = NULL; } } else if(!pLookAtEntity) m_pLookAtEnemy = NULL; } } } }