void ATurret::CheckAutoAttack() { if (!IsValid(currentTarget) || !IsValid(GetController()) || !currentTarget->IsAlive() || !currentTarget->IsTargetable()) { StopAutoAttack(); TargetOutofRange(); return; } float distance = (GetActorLocation() - currentTarget->GetActorLocation()).Size2D(); if (distance > statsManager->GetCurrentValueForStat(EStat::ES_AARange)) { StopAutoAttack(); TargetOutofRange(); } else if (!bAutoAttackLaunching && !bAutoAttackOnCooldown) { float scale = statsManager->GetCurrentValueForStat(EStat::ES_AtkSp) / statsManager->GetBaseValueForStat(EStat::ES_AtkSp); //AllPlayAnimMontage(autoAttackManager->GetCurrentAttackAnimation(), scale); GetWorldTimerManager().SetTimer(aaLaunchTimer, this, &AGameCharacter::LaunchAutoAttack, autoAttackManager->GetAutoAttackLaunchTime() / scale); bAutoAttackLaunching = true; } }
void ATurret::TargetOutofRange() { if (!IsValid(this)) return; TArray<FHitResult> hits; FVector start = GetActorLocation(); FVector end = start; end.Z += 5.f; TArray<AGameCharacter*> possibleTargets; GetWorld()->SweepMultiByChannel(hits, start, end, GetActorRotation().Quaternion(), ECC_Visibility, FCollisionShape::MakeSphere(GetCurrentValueForStat(EStat::ES_AARange))); for (FHitResult hit : hits) { AGameCharacter* gc = Cast<AGameCharacter>(hit.GetActor()); if (IsValid(gc) && gc->IsAlive() && GetTeamIndex() != gc->GetTeamIndex()) possibleTargets.AddUnique(gc); } //first aggro any minions first for (AGameCharacter* gc : possibleTargets) { if (gc->IsA(AMinionCharacter::StaticClass())) { SetCurrentTarget(gc); StartAutoAttack(); return; } } //then aggro an objective if we can for (AGameCharacter* gc : possibleTargets) { if (gc->IsA(ARealmObjective::StaticClass())) { SetCurrentTarget(gc); StartAutoAttack(); return; } } //lastly aggro any mythos for (AGameCharacter* gc : possibleTargets) { if (gc->IsA(APlayerCharacter::StaticClass())) { SetCurrentTarget(gc); StartAutoAttack(); return; } } StopAutoAttack(); }
void ATurret::TargetOutofRange() { float leastDistance = -1.f; int32 leastInd = -1; if (!IsValid(this)) return; inRangeTargets.Empty(); for (TActorIterator<AGameCharacter> chritr(GetWorld()); chritr; ++chritr) { AGameCharacter* gc = *chritr; if (IsValid(gc) && gc->IsAlive() && gc != this && gc->GetTeamIndex() != GetTeamIndex()) { float dist = (gc->GetActorLocation() - GetActorLocation()).Size(); if (dist <= GetCurrentValueForStat(EStat::ES_AARange)) inRangeTargets.AddUnique(gc); } } //if we should priortize Mythos AGameCharacter* otherTarget = nullptr; for (int32 i = 0; i < inRangeTargets.Num(); i++) { if (inRangeTargets[i]->IsA(AMinionCharacter::StaticClass())) continue; float distanceSq = (inRangeTargets[i]->GetActorLocation() - GetActorLocation()).SizeSquared2D(); if (!inRangeTargets[i]->IsAlive() || distanceSq > FMath::Square(710.f)) { inRangeTargets.RemoveAt(i); continue; } if (leastDistance == -1.f) { leastDistance = distanceSq; leastInd = i; continue; } if (distanceSq < leastDistance) { leastDistance = distanceSq; leastInd = i; } } if (bPrioritizeMythos) { if (leastInd >= 0) { currentTarget = inRangeTargets[leastInd]; StartAutoAttack(); return; } } else { if (leastInd >= 0) otherTarget = inRangeTargets[leastInd]; } leastDistance = -1.f; leastInd = -1; for (int32 i = 0; i < inRangeTargets.Num(); i++) { if (!inRangeTargets[i]->IsA(AMinionCharacter::StaticClass())) continue; float distanceSq = (inRangeTargets[i]->GetActorLocation() - GetActorLocation()).SizeSquared2D(); if (!inRangeTargets[i]->IsAlive() || distanceSq > FMath::Square(710.f)) { inRangeTargets.RemoveAt(i); continue; } if (leastDistance == -1.f) { leastDistance = distanceSq; leastInd = i; continue; } if (distanceSq < leastDistance) { leastDistance = distanceSq; leastInd = i; } } if (leastInd >= 0) { currentTarget = inRangeTargets[leastInd]; StartAutoAttack(); return; } if (otherTarget) { currentTarget = otherTarget; StartAutoAttack(); } else { currentTarget = nullptr; StopAutoAttack(); } }