Pawn/Pawn_Unreal/Source/Pawn/Private/GameplayModes/PwnGameplayModeSubsystem.cpp

106 lines
3.8 KiB
C++

#include "GameplayModes/PwnGameplayModeSubsystem.h"
#include "Components/SplineComponent.h"
#include "GameplayModes/Combat/PwnCombatPlatformerPath.h"
#include "Utils/EngineUtils.h"
UPwnGameplayModeSubsystem& UPwnGameplayModeSubsystem::Get(const UObject* WorldContextObject) {
const UWorld* World = GEngine->GetWorldFromContextObjectChecked(WorldContextObject);
UPwnGameplayModeSubsystem* GameplayModeSubsystem = World->GetSubsystem<UPwnGameplayModeSubsystem>();
check(GameplayModeSubsystem);
return *GameplayModeSubsystem;
}
void UPwnGameplayModeSubsystem::Initialize(FSubsystemCollectionBase& Collection) {
Super::Initialize(Collection);
CurrentGameplayMode = EPwnGameplayMode::Narrative;
}
void UPwnGameplayModeSubsystem::Deinitialize() {
Super::Deinitialize();
}
void UPwnGameplayModeSubsystem::SetGameplayMode(EPwnGameplayMode GameplayMode) {
if (GameplayMode != CurrentGameplayMode) {
CurrentGameplayMode = GameplayMode;
if (OnGameplayModeChanged.IsBound()) {
OnGameplayModeChanged.Broadcast(CurrentGameplayMode);
}
}
}
EPwnGameplayMode UPwnGameplayModeSubsystem::GetCurrentGameplayMode() const {
return CurrentGameplayMode;
}
bool UPwnGameplayModeSubsystem::IsNarrativeMode() const {
return CurrentGameplayMode == EPwnGameplayMode::Narrative;
}
bool UPwnGameplayModeSubsystem::IsCombatMode() const {
return CurrentGameplayMode == EPwnGameplayMode::Combat;
}
void UPwnGameplayModeSubsystem::RegisterCombatPath(APwnCombatPlatformerPath* CombatPath) {
CombatPaths.Add(CombatPath);
}
void UPwnGameplayModeSubsystem::UnregisterCombatPath(APwnCombatPlatformerPath* CombatPath) {
CombatPaths.Remove(CombatPath);
}
bool UPwnGameplayModeSubsystem::FindClosestCombatPathLocation(const FVector& Location, APwnCombatPlatformerPath*& OutCombatPath, FVector& ClosestLocation) const {
float BestDistanceAlongTheSpline = -1;
float ShortestZOffset = FLT_MAX;
APwnCombatPlatformerPath* ClosestCombatPath = nullptr;
const FVector Location2D = FVector(Location.X, Location.Y, 0.0f);
for (APwnCombatPlatformerPath* CombatPath : CombatPaths) {
const USplineComponent* CurrentSpline = CombatPath->Spline;
CombatPath->UpdateFlattenSpline(CombatPath->Spline->FindInputKeyClosestToWorldLocation(Location));
const FVector FlattenedLocation = CombatPath->FlattenedSpline->FindLocationClosestToWorldLocation(Location, ESplineCoordinateSpace::World);
const float CurrentKey = CurrentSpline->FindInputKeyClosestToWorldLocation(FlattenedLocation);
const float CurrentDistance = CurrentSpline->GetDistanceAlongSplineAtSplineInputKey(CurrentKey);
float BestDistance = -1;
float ShortestDistanceForThisPath = FLT_MAX;
for (int i = -700; i <= 700; i += 5) {
const float SubStepDistance = CurrentDistance + i;
const FVector SubStepLocation = CurrentSpline->GetLocationAtDistanceAlongSpline(SubStepDistance, ESplineCoordinateSpace::World);
if (SubStepLocation.Z < Location.Z) {
continue;
}
FVector SubStepLocation2D = FVector(SubStepLocation.X, SubStepLocation.Y, 0.0f);
const float Distance = FVector::DistSquared(Location2D, SubStepLocation2D);
if (Distance < ShortestDistanceForThisPath) {
ShortestDistanceForThisPath = Distance;
BestDistance = SubStepDistance;
}
}
if (BestDistance < 0) {
continue;
}
const FVector BestLocation = CurrentSpline->GetLocationAtDistanceAlongSpline(BestDistance, ESplineCoordinateSpace::World);
const float ZOffset = BestLocation.Z - Location.Z;
if (ZOffset < ShortestZOffset) {
ClosestCombatPath = CombatPath;
BestDistanceAlongTheSpline = BestDistance;
ShortestZOffset = ZOffset;
}
}
if (ClosestCombatPath != nullptr) {
OutCombatPath = ClosestCombatPath;
ClosestLocation = OutCombatPath->Spline->GetLocationAtDistanceAlongSpline(BestDistanceAlongTheSpline, ESplineCoordinateSpace::World);
return true;
}
return false;
}