void CNetworkPlayer::UpdateAim( bool bAiming ) { DEBUG_TRACE("CNetworkPlayer::UpdateAim"); // Is the playerped not valid? if( !m_pPlayerPed ) return; // Should we start aiming? if( bAiming && !IsAiming() ) { // Terminate the old aim object if it's valid if ( m_pAimObject ) m_pAimObject->Terminate (); // Delete the old aim object SAFE_DELETE( m_pAimObject ); // Create the initial aim sync object if needed m_pAimObject = new CM2SyncObject( m_pPlayerPed->AimAt( GetLookAt() ) ); // Mark as aiming SetAiming( true ); } // Should we stop aiming? else if( !bAiming && IsAiming() ) { // Terminate the old aim object if it's valid if ( m_pAimObject ) m_pAimObject->Terminate (); // Delete the old aim sync object SAFE_DELETE( m_pAimObject ); // Mark as not aiming SetAiming( false ); } // Should we update the aim position else if( bAiming && IsAiming() ) { // Is the aim sync object valid? if( m_pAimObject && !m_pAimObject->IsDone() ) { // Update the aim position m_pAimObject->SetTarget( GetLookAt(), eTargetType::E_TYPE_AIM ); } else if( m_pAimObject && m_pAimObject->IsDone() ) { // Mark as not aiming to rebuild the object next pulse SetAiming( false ); } } }
void CNetworkPlayer::UpdateShot( bool bShooting ) { DEBUG_TRACE("CNetworkPlayer::UpdateShot"); // Is the playerped not valid? if( !m_pPlayerPed ) return; // Should we start shooting? if( bShooting && !IsShooting() ) { // Terminate the old shot object if it's valid if ( m_pShootObject ) m_pShootObject->Terminate (); // Delete the old shoot object SAFE_DELETE( m_pShootObject ); // Terminate the old aim object if it's valid if ( m_pAimObject ) m_pAimObject->Terminate (); // Delete the old aim object SAFE_DELETE( m_pAimObject ); // Create the initial shoot sync object if needed m_pShootObject = new CM2SyncObject( m_pPlayerPed->ShootAt( GetLookAt() ) ); // Mark as shooting SetShooting( true ); } // Should we stop shooting? else if( !bShooting && IsShooting() ) { // Terminate the old shot object if it's valid if ( m_pShootObject ) m_pShootObject->Terminate (); // Delete the old aim sync object SAFE_DELETE( m_pShootObject ); // Mark as not shooting SetShooting( false ); // Are we aiming? if( IsAiming() ) { // Mark as not aiming SetAiming( false ); // Update the aim now! UpdateAim( true ); } } // Should we update the aim position else if( bShooting && IsShooting() ) { // Is the aim sync object valid? if( m_pShootObject && !m_pShootObject->IsDone() ) { // Update the aim position m_pShootObject->SetTarget( GetLookAt(), eTargetType::E_TYPE_SHOOT ); } else if( m_pShootObject && m_pShootObject->IsDone() ) { // Mark as not shooting SetShooting( false ); } } }
//------------------------------------------------------------------------ void CGunTurret::ServerUpdate(SEntityUpdateContext &ctx, int update) { //update parameters. SNH: cache these in MP since they never change. if(!gEnv->bMultiplayer) { UpdateEntityProperties(); } IEntity *pCurrentTarget = gEnv->pEntitySystem->GetEntity(m_targetId); IActor *pCurrentActor = GetActor(m_targetId); bool mg=false; bool rocket=false; if(IsOperational()) { bool renew_target = false; //do this before, cause it's more important if(m_turretparams.TAC_check_time != 0.f) { if(m_checkTACTimer>m_turretparams.TAC_check_time) { m_checkTACTimer = 0.0f; IEntity *pClosest = GetClosestTACShell(); if(pClosest) { ChangeTargetTo(pClosest); pCurrentTarget = pClosest; } } else m_checkTACTimer += ctx.fFrameTime; } //actually if(...), break at end while(pCurrentTarget) { if(InternalIsFiring(false)) m_burstTimer += ctx.fFrameTime; else m_burstTimer = 0.f; ETargetClass t_class = GetTargetClass(pCurrentTarget); bool validClass = (t_class!=eTC_NotATarget); Vec3 tpos = PredictTargetPos(pCurrentTarget,false); bool inrange = IsInRange(tpos, t_class); if(m_rayTimer <= 0.f) { m_canShoot = IsTargetShootable(pCurrentTarget); m_rayTimer = (m_canShoot) ? 0.5f : 0.2f; } else m_rayTimer -= ctx.fFrameTime; if(!(validClass && inrange && m_canShoot)) { m_abandonTargetTimer += ctx.fFrameTime; } else m_abandonTargetTimer = 0.0f; if(m_abandonTargetTimer > m_turretparams.abandon_target_time + m_randoms[eRV_AbandonTarget].val) { renew_target = true; m_randoms[eRV_AbandonTarget].New(); break; } bool aim = inrange&&m_canShoot&&IsAiming(tpos, m_turretparams.aim_tolerance); mg = aim && !m_turretparams.search_only && IsTargetMGable(tpos); bool burst = (m_turretparams.burst_time == 0.f || UpdateBurst(ctx.fFrameTime)); mg &= burst; // a bit less tolerant for rockets aim=aim&&IsAiming(tpos, m_turretparams.aim_tolerance*0.5f); rocket = aim && !m_turretparams.search_only && m_fm2 && t_class == eTC_Vehicle && IsTargetRocketable(tpos); if(g_pGameCVars->i_debug_turrets) { IRenderer *pRenderer = gEnv->pRenderer; static float white[4] = {1,1,1,1}; float x = 5.f, y = 50.f, step1 = 15.f, /*step2 = 20.f, */size=1.3f; pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "Target: %s", pCurrentTarget->GetName()); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "InRange: %i", inrange); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "CanShoot: %i", m_canShoot); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "IsAiming: %i", aim); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "Burst: %i", burst); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "MG: %i", mg); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "BurstTimer: %.2f", m_burstTimer); //pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "Rocket: %i", rocket); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "TargetPos: %.1f %.1f %.1f", tpos.x, tpos.y, tpos.z); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "Abandon: %.2f", m_abandonTargetTimer); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "Update: %.2f", m_updateTargetTimer); pRenderer->Draw2dLabel(x, y+=step1, size, white, false, "GoalYaw: %.2f, GoalPitch: %.2f", m_goalYaw, m_goalPitch); } break; } m_updateTargetTimer += ctx.fFrameTime; if(renew_target || m_updateTargetTimer > m_turretparams.update_target_time+m_randoms[eRV_UpdateTarget].Val()) { IEntity *pClosestTAC = GetClosestTACShell(); IEntity *pClosest = (pClosestTAC) ? pClosestTAC : GetClosestTarget(); // change target if tac shell, or other target closer than current // otherwise, only change after abandoning time is exceeded if(pClosestTAC || (pClosest && pClosest->GetId()!=m_targetId) || (!pClosest && !(m_abandonTargetTimer>0.f && m_abandonTargetTimer<=m_turretparams.abandon_target_time))) { ChangeTargetTo(pClosest); pCurrentTarget = pClosest; } m_updateTargetTimer = 0.f; m_randoms[eRV_UpdateTarget].New(); } if(pCurrentTarget) { if(m_turretparams.surveillance || IsTargetShootable(pCurrentTarget)) UpdateGoal(pCurrentTarget, ctx.fFrameTime); } else { if(m_turretparams.searching) { UpdateSearchingGoal(ctx.fFrameTime); } } } if(m_fm && mg != InternalIsFiring(false)) { if(mg) InternalStartFire(false); else InternalStopFire(false); } if(m_fm2 && rocket != InternalIsFiring(true)) { if(rocket) InternalStartFire(true); else InternalStopFire(true); } }