#pragma once #include "CoreMinimal.h" #include "Components/ActorComponent.h" #include "InteractionComponent.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFocusedInteractableChanged, AActor*, NewFocused); UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class NAKEDDESIRE_API UInteractionComponent : public UActorComponent { GENERATED_BODY() public: UInteractionComponent(); virtual void BeginPlay() override; // Call from interact input — sends server RPC if not authority void Interact(); UFUNCTION(BlueprintPure) AActor* GetFocusedInteractable() const { return FocusedInteractable.Get(); } // Broadcasts whenever the focused (interactable) actor changes; nullptr = no target UPROPERTY(BlueprintAssignable) FOnFocusedInteractableChanged OnFocusedInteractableChanged; protected: // Actors within this radius receive a proximity outline UPROPERTY(EditDefaultsOnly, Category="Interaction") float ProximityRadius = 350.f; // Player must be within this distance to focus an interactable (must be <= ProximityRadius) UPROPERTY(EditDefaultsOnly, Category="Interaction") float InteractionDistance = 150.f; // Minimum dot product between look direction and direction to target. // cos(20°) ≈ 0.94 — lower values allow a wider look cone. UPROPERTY(EditDefaultsOnly, Category="Interaction") float LookDotThreshold = 0.9f; private: FTimerHandle InteractionTimerHandle; void UpdateInteraction(); TSet> NearbyInteractables; TWeakObjectPtr FocusedInteractable; // Physics scan → update NearbyInteractables set → manage proximity outlines void UpdateNearbyInteractables(); // Among nearby actors, find the one best matching look + distance conditions void UpdateFocusedInteractable(); bool GetOwnerViewPoint(FVector& OutLocation, FRotator& OutRotation) const; // Traces from the pawn's eye position (NOT the camera) to the target. // Returns true only if nothing blocks the line — prevents exploiting the // third-person camera to interact through walls by looking over them. bool HasLineOfSightFromPawn(AActor* Target) const; };