// © 2025 Naked People Team. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "LocationTrigger.generated.h" class ULocationData; class UBoxComponent; // A tagged volume. On player overlap it reports enter / leave to ULocationSubsystem, which is the // single authority on where the player is. Everything (session boundary, commission location // constraints, etc.) consumes the subsystem — the trigger itself has no consumer-specific logic. UCLASS() class NAKEDDESIRE_API ALocationTrigger : public AActor { GENERATED_BODY() UPROPERTY(BlueprintReadOnly, meta = (AllowPrivateAccess)) UBoxComponent* BoxTrigger; UPROPERTY(EditAnywhere) ULocationData* LocationData; UPROPERTY(EditAnywhere) FVector TriggerSize; public: ALocationTrigger(); virtual void OnConstruction(const FTransform& Transform) override; ULocationData* GetLocationData() const; protected: virtual void BeginPlay() override; private: UFUNCTION() void OnTriggerBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult); UFUNCTION() void OnTriggerEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex); // A pawn that spawns already inside this volume (e.g. the apartment at game start) gets no // begin-overlap event, so seed the state one tick after BeginPlay once the world settles. void SeedInitialPlayerOverlap(); // Forwards a single enter/exit to ULocationSubsystem on a real transition. Idempotent so the // seed above can't double-count against a begin-overlap the engine does deliver. void SetPlayerInside(bool bInside); bool IsPlayerOverlapping() const; bool bPlayerInside = false; };