// Fill out your copyright notice in the Description page of Project Settings. #include "PartySubsystem.h" #include "Kismet/GameplayStatics.h" void UPartySubsystem::AddToParty(UUnitInfo* UnitInfo) { for (FPartyMember &Unit : Members) { if(Unit.UnitInfo == UnitInfo) { const bool UpdateAllocated = GetMemberAvailable(Unit) == GetMemberAllocated(Unit); SetMemberAvailable(Unit, GetMemberAvailable(Unit) + 1); if (UpdateAllocated) { AllocateMember(Unit); } return; } } } TArray UPartySubsystem::GetMembers() { return Members; } int32 UPartySubsystem::SpawnParty(const float InVerticalSpacing, const float InHorizontalOffset, const float InHorizontalSpacing, const int InNumRows) { this->VerticalSpacing = InVerticalSpacing; this->HorizontalOffset = InHorizontalOffset; this->NumRows = InNumRows; this->HorizontalSpacing = InHorizontalSpacing; CurrentColumn = 0; LastSpawnIndex = 0; SpawnQueue.Empty(); TArray SpawnPoints; UGameplayStatics::GetAllActorsWithTag(GetWorld(), "PlayerSpawn", SpawnPoints); SpawnPoint = SpawnPoints[0]; for (FPartyMember &Unit : GetMembers()) { const int32 Allocated = GetMemberAllocated(Unit); for(auto i = 0; i < Allocated; i++) { SpawnQueue.Add(GetMemberUnitInfo(Unit)->GetCharacterClass()); } } const int32 NumUnits = SpawnQueue.Num(); SpawnUnits(); GetWorld()->GetTimerManager().SetTimer( SpawnTimerHandle, this, &UPartySubsystem::SpawnUnits, 0.5f, true); return NumUnits; } void UPartySubsystem::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 + FMath::RandRange(-500.0f, 500.0f), -HorizontalOffset * CurrentColumn + FMath::RandRange(-500.0f, 500.0f), 300); FRotator Rotation = FRotator(0, 90.0f, 0); AActor* NewActor = GetWorld()->SpawnActor(SpawnQueue[i + LastSpawnIndex], &Location, &Rotation, SpawnActorParameters); if(NewActor != nullptr) { NewActor->Tags.Add(TEXT("player")); } FHitResult Hit; FVector TraceStart = NewActor->GetActorLocation(); FVector TraceEnd = -NewActor->GetActorUpVector() * 10000.0f; FCollisionQueryParams QueryParams; QueryParams.AddIgnoredActor(NewActor); NewActor->GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_WorldStatic, QueryParams); if(Hit.bBlockingHit) { NewActor->SetActorLocation(Hit.Location, true, nullptr, ETeleportType::ResetPhysics); } } LastSpawnIndex += NumRows; CurrentColumn++; } TArray UPartySubsystem::GetUnitsByTier(const int32 Tier) const { TArray TierMembers; for(FPartyMember Member : Members) { if(GetMemberUnitInfo(Member)->GetTier() == Tier) { TierMembers.Add(GetMemberUnitInfo(Member)); } } return TierMembers; } void UPartySubsystem::SetCredits(const int32 Amount) { Credits = Amount; } bool UPartySubsystem::AllocateMember(FPartyMember& Member) { Member.Allocated++; if(Member.Allocated > Member.Available) { Member.Allocated = Member.Available; return false; } return true; } bool UPartySubsystem::DeallocateMember(FPartyMember &Member) { Member.Allocated--; if (Member.Allocated < 0) { Member.Allocated = 0; return false; } return true; } void UPartySubsystem::SetMemberMax(FPartyMember& Member) { Member.Allocated = Member.Available; } void UPartySubsystem::ClearMember(FPartyMember& Member) { Member.Allocated = 0; } int32 UPartySubsystem::GetMemberAllocated(FPartyMember& Member) const { return Member.Allocated; } int32 UPartySubsystem::GetMemberAvailable(FPartyMember& Member) const { return Member.Available; } void UPartySubsystem::SetMemberAvailable(FPartyMember& Member, int32 const Amount) { Member.Available = Amount; } void UPartySubsystem::SetMemberUnitInfo(FPartyMember& Member, UUnitInfo* InUnitInfo) { Member.UnitInfo = InUnitInfo; } UUnitInfo* UPartySubsystem::GetMemberUnitInfo(FPartyMember& Member) const { return Member.UnitInfo; } int32 UPartySubsystem::GetTotalAvailablePartyMembers() { int32 Total = 0; for(auto const Member : Members) { Total += Member.Available; } return Total; } int32 UPartySubsystem::GetTotalAllocatedPartyMembers() { int32 Total = 0; for(auto const Member : Members) { Total += Member.Allocated; } return Total; }