virtual void GetClosestApproachTarget()
	{
		float dist = FLT_MAX;
		const AUVec3f& refPos = m_pOwner->GetEntity()->GetPosition();

		GetClosestTarget( m_pBBIndividual->visible_infected, refPos, dist, &m_pApproachTarget );
		GetClosestTarget( m_pBBIndividual->visible_viruses, refPos, dist, &m_pApproachTarget );
	}
	void GetClosestAvoidTarget()
	{
		float dist = FLT_MAX;
		const AUVec3f& refPos = m_pOwner->GetEntity()->GetPosition();

		GetClosestTarget( m_pBBIndividual->visible_wbc, refPos, dist, &m_pAvoidTarget );
		
		if ( m_pAvoidTarget && m_pAvoidTarget->GetThreatRating() < m_pOwner->GetThreatRating() )
		{
			m_pAvoidTarget = 0;
		}
	}
// Called every frame
void UAd_CharacterAIComponent::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
{
	Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
	//if (!isAI) return;// OwningPawn == PlayersPawn) return;
	if (!Cast<AAdder_DodgeBallCharacter>(OwningPawn)->isAI) return;
	// ...
	AITimer = AITimer - DeltaTime;
	
	if (AITimer < 0) {
		if (!Cast<AAdder_DodgeBallCharacter>(OwningPawn)->isAlive && Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall) {
			Cast<AAdder_DodgeBallCharacter>(OwningPawn)->ThrowBall();
			Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall = false;
			return;
		}
		targetPoint += FVector(rand() % 511 - 255, rand() % 511 - 255, 0);
		//UE_LOG(LogTemp, Warning, TEXT("Iterating"));
		bool gettingPowerUp = false;
		if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)->currentPowerup == PowerUp::PowerUpType::none)
		{
			for (TActorIterator<APowerUpPickUp> Tai(GetWorld()); Tai; ++Tai) {
				if (IsClosestToTarget(*Tai)) {
					FVector PUpPoint = Tai->GetActorLocation();
					if (PUpPoint.X < boundsPoint.X + boundsVector.X && PUpPoint.X > boundsPoint.X - boundsVector.X
						&&PUpPoint.Y < boundsPoint.Y + boundsVector.Y && PUpPoint.Y > boundsPoint.Y - boundsVector.Y) {
						targetPoint = PUpPoint;
						gettingPowerUp = true;
					}
				}
			}
		}
		targetActor = nullptr;
		if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall || !gettingPowerUp) {
			
			FVector UserPoint = OwningPawn->GetTransform().GetLocation();
			for (TActorIterator<AMyBallClass> Tai(GetWorld()); Tai; ++Tai) {
				if (Tai->ActorHasTag("Ball"))
				{
					if (Tai->GetAttachParentActor() == GetOwner()) {// || Tai->OwningActor == GetOwner()) {
						//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("BallOwner")));
						targetActor = GetClosestTarget();
						if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)) {
							//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("hasBall")));
							Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall = true;
							Cast<AAdder_DodgeBallCharacter>(OwningPawn)->ballRef = *Tai;
							if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)->throwPower > 0.75f) {
								Cast<AAdder_DodgeBallCharacter>(OwningPawn)->ThrowBall();
								Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall = false;
							}
						}
						if (targetActor != nullptr) {
							targetPoint = targetActor->GetActorLocation();
						} else GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("nullTarget")));
					} else {
						//targetActor = nullptr;
						if (IsClosestToTarget(*Tai)) {
							//chase the ball if it's on AI side of the court
							FVector BallPoint = Tai->GetActorLocation();
							if (BallPoint.X < boundsPoint.X + boundsVector.X && BallPoint.X > boundsPoint.X - boundsVector.X
								&&BallPoint.Y < boundsPoint.Y + boundsVector.Y && BallPoint.Y > boundsPoint.Y - boundsVector.Y) {
								//targetPoint = BallPoint;
								targetPoint = BallPoint + Tai->GetVelocity()* FVector::Dist(BallPoint, UserPoint) * 0.003f;
							}
							//run from the ball if it's flying
							FVector BallVelocity = Tai->GetVelocity();
							bool IsDeadly = Cast<AMyBallClass>(*Tai)->GetIsDeadly();
							//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("BallVector: %f"), BallVelocity.Size()));
							if (BallVelocity.Size() > 120.0f && IsDeadly) {
								FVector MovePoint = (OwningPawn->GetTransform().GetLocation() - BallPoint);
								MovePoint.Normalize();
								targetPoint = UserPoint + (MovePoint * 180);
							}
						}
					}
				}
			}
		}
		if (targetPoint.X > boundsPoint.X + boundsVector.X) targetPoint.X -= 255;// = boundsPoint.X + boundsVector.X;
		if (targetPoint.X < boundsPoint.X - boundsVector.X) targetPoint.X += 255;// = boundsPoint.X - boundsVector.X;
		if (targetPoint.Y > boundsPoint.Y + boundsVector.Y) targetPoint.Y -= 255;// = boundsPoint.Y + boundsVector.Y;
		if (targetPoint.Y < boundsPoint.Y - boundsVector.Y) targetPoint.Y += 255;// = boundsPoint.Y - boundsVector.Y;
		if(Cast<AAdder_DodgeBallCharacter>(OwningPawn))
		if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall == true && targetActor != nullptr) {
			targetPoint = targetActor->GetActorLocation();
		}
		targetPoint.Z = OwningPawn->GetTransform().GetLocation().Z;
		AITimer = AITimer + AITimeStep + (rand() % 100) / 250.0f;
	}
	if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)) {
		if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall) {
			if (targetActor == nullptr) {
				targetActor = GetClosestTarget();
				if (targetActor != nullptr) targetPoint = targetActor->GetActorLocation();
			}
	//		if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)) {
				Cast<AAdder_DodgeBallCharacter>(OwningPawn)->WindUp();
	//			if (Cast<AAdder_DodgeBallCharacter>(OwningPawn)->throwPower > 0.95f) {
	//				Cast<AAdder_DodgeBallCharacter>(OwningPawn)->ThrowBall();
	//				Cast<AAdder_DodgeBallCharacter>(OwningPawn)->hasBall = false;
	//			}
	//		}
		}// else if (targetActor != nullptr) { }
	}
	if (FMath::Abs(FVector::Dist(targetPoint, OwningPawn->GetTransform().GetLocation())) > 32) {
		//OwningPawn->AddMovementInput(targetPoint - OwningPawn->GetTransform().GetLocation(), 1, false);
		OwningPawn->GetMovementComponent()->AddInputVector(targetPoint - OwningPawn->GetTransform().GetLocation(), false);
	}
}
Beispiel #4
0
//------------------------------------------------------------------------
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);
	}
}