// Fill out your copyright notice in the Description page of Project Settings. #include "WaveSubsystem.h" #include "Kismet/GameplayStatics.h" void UWaveSubsystem::Init(const TArray InWaves, const int32 CurrWave = 0) { CurrentWave = CurrWave; Waves = InWaves; } int32 UWaveSubsystem::SpawnWave(const float InVerticalSpacing, const float InHorizontalOffset, const int InNumRows) { NumRows = InNumRows; HorizontalOffset = InHorizontalOffset; VerticalSpacing = InVerticalSpacing; SpawnQueue = Waves[CurrentWave]->GetUnits(); const auto NumUnits = SpawnQueue.Num(); CurrentColumn = 0; LastSpawnIndex = 0; TArray SpawnPoints; UGameplayStatics::GetAllActorsWithTag(GetWorld(), "EnemySpawn", SpawnPoints); SpawnPoint = SpawnPoints[0]; SpawnUnits(); GetWorld()->GetTimerManager().SetTimer( SpawnTimerHandle, this, &UWaveSubsystem::SpawnUnits, 0.5f, true); CurrentWave++; return NumUnits; } void UWaveSubsystem::SpawnUnits() { for(auto i = 0; i < NumRows; i++) { if(i + LastSpawnIndex >= SpawnQueue.Num()) { GetWorld()->GetTimerManager().ClearTimer(SpawnTimerHandle); LastSpawnIndex += i; return; } FActorSpawnParameters SpawnActorParameters = {}; SpawnActorParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; FVector Location = SpawnPoint->GetActorLocation() + FVector(i * -VerticalSpacing, -HorizontalOffset * CurrentColumn, 300); FRotator Rotation = FRotator(0,-90.0f, 0); AActor* NewEnemy = GetWorld()->SpawnActor(SpawnQueue[i + LastSpawnIndex]->GetCharacterClass(), &Location, &Rotation, SpawnActorParameters); if(NewEnemy != nullptr) { NewEnemy->Tags.Add(TEXT("enemy")); USkeletalMeshComponent* Mesh = NewEnemy->FindComponentByClass(); Mesh->SetCollisionObjectType(ECC_GameTraceChannel2); } FHitResult Hit; FVector TraceStart = NewEnemy->GetActorLocation(); FVector TraceEnd = -NewEnemy->GetActorUpVector() * 10000.0f; FCollisionQueryParams QueryParams; QueryParams.AddIgnoredActor(NewEnemy); NewEnemy->GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_WorldStatic, QueryParams); if(Hit.bBlockingHit) { NewEnemy->SetActorLocation(Hit.Location, true, nullptr, ETeleportType::ResetPhysics); } } LastSpawnIndex += NumRows; CurrentColumn++; }