// © 2025 Naked People Team. All Rights Reserved. #include "LocationTrigger.h" #include "Components/BoxComponent.h" #include "LocationSubsystem.h" #include "NakedDesire/Player/NakedDesireCharacter.h" #include "TimerManager.h" ALocationTrigger::ALocationTrigger() { PrimaryActorTick.bCanEverTick = false; BoxTrigger = CreateDefaultSubobject("Box Trigger"); RootComponent = BoxTrigger; } ULocationData* ALocationTrigger::GetLocationData() const { return LocationData; } void ALocationTrigger::BeginPlay() { Super::BeginPlay(); BoxTrigger->OnComponentBeginOverlap.AddDynamic(this, &ALocationTrigger::OnTriggerBeginOverlap); BoxTrigger->OnComponentEndOverlap.AddDynamic(this, &ALocationTrigger::OnTriggerEndOverlap); // Defer to next tick so the player pawn is spawned and positioned and physics overlaps // have been computed before we check whether it started out inside this volume. GetWorld()->GetTimerManager().SetTimerForNextTick(this, &ALocationTrigger::SeedInitialPlayerOverlap); } void ALocationTrigger::OnConstruction(const FTransform& Transform) { Super::OnConstruction(Transform); BoxTrigger->SetBoxExtent(TriggerSize); } void ALocationTrigger::OnTriggerBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) { if (!OtherActor || !OtherActor->IsA()) return; SetPlayerInside(true); } void ALocationTrigger::OnTriggerEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) { if (!OtherActor || !OtherActor->IsA()) return; // Another of the player's components may still overlap the box (capsule vs. mesh); only // report the exit once the player has fully left, so we fire exactly one Exit per Enter. if (IsPlayerOverlapping()) return; SetPlayerInside(false); } void ALocationTrigger::SeedInitialPlayerOverlap() { if (IsPlayerOverlapping()) SetPlayerInside(true); } void ALocationTrigger::SetPlayerInside(const bool bInside) { if (bInside == bPlayerInside) return; bPlayerInside = bInside; if (ULocationSubsystem* Locations = GetWorld()->GetSubsystem()) { if (bInside) Locations->EnterLocation(LocationData); else Locations->ExitLocation(LocationData); } } bool ALocationTrigger::IsPlayerOverlapping() const { TArray Overlapping; BoxTrigger->GetOverlappingActors(Overlapping, ANakedDesireCharacter::StaticClass()); return Overlapping.Num() > 0; }