Initial commit: Item Interaction Ecosystem plugin (UE5.7)
Server-authoritative, data-driven item/inventory/interaction/carry/equipment/ world-slot/placement/crafting framework. 8 modules, compiles against UE 5.7. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
86
Source/ItemInteraction/Private/InteractionTraceComponent.cpp
Normal file
86
Source/ItemInteraction/Private/InteractionTraceComponent.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
// Copyright ExByte Studios. Item Interaction Ecosystem.
|
||||
|
||||
#include "InteractionTraceComponent.h"
|
||||
#include "InteractableComponent.h"
|
||||
#include "GameFramework/Pawn.h"
|
||||
#include "GameFramework/PlayerController.h"
|
||||
#include "Engine/World.h"
|
||||
|
||||
UInteractionTraceComponent::UInteractionTraceComponent()
|
||||
{
|
||||
PrimaryComponentTick.bCanEverTick = true;
|
||||
PrimaryComponentTick.TickInterval = 0.1f; // 10 Hz is plenty for prompts
|
||||
SetIsReplicatedByDefault(false); // purely local
|
||||
}
|
||||
|
||||
void UInteractionTraceComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||
{
|
||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||
TickTrace();
|
||||
}
|
||||
|
||||
bool UInteractionTraceComponent::GetViewPoint(FVector& OutLocation, FRotator& OutRotation) const
|
||||
{
|
||||
const APawn* Pawn = Cast<APawn>(GetOwner());
|
||||
const APlayerController* PC = Pawn ? Cast<APlayerController>(Pawn->GetController()) : nullptr;
|
||||
if (!PC || !PC->IsLocalController())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
PC->GetPlayerViewPoint(OutLocation, OutRotation);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UInteractionTraceComponent::TickTrace()
|
||||
{
|
||||
FVector ViewLoc;
|
||||
FRotator ViewRot;
|
||||
if (!GetViewPoint(ViewLoc, ViewRot))
|
||||
{
|
||||
SetTarget(nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
const FVector End = ViewLoc + ViewRot.Vector() * TraceDistance;
|
||||
|
||||
FCollisionQueryParams Params(SCENE_QUERY_STAT(InteractionTrace), false, GetOwner());
|
||||
Params.bTraceComplex = false;
|
||||
|
||||
FHitResult Hit;
|
||||
const bool bHit = GetWorld()->SweepSingleByChannel(
|
||||
Hit, ViewLoc, End, FQuat::Identity, TraceChannel,
|
||||
FCollisionShape::MakeSphere(TraceRadius), Params);
|
||||
|
||||
AActor* HitActor = bHit ? Hit.GetActor() : nullptr;
|
||||
UInteractableComponent* Interactable = HitActor ? HitActor->FindComponentByClass<UInteractableComponent>() : nullptr;
|
||||
|
||||
if (Interactable)
|
||||
{
|
||||
// Distance gate against the component's own reach.
|
||||
const float DistSq = FVector::DistSquared(ViewLoc, Hit.ImpactPoint);
|
||||
if (DistSq > FMath::Square(Interactable->InteractionDistance))
|
||||
{
|
||||
Interactable = nullptr;
|
||||
HitActor = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HitActor = nullptr;
|
||||
}
|
||||
|
||||
LastHitLocation = Hit.ImpactPoint;
|
||||
LastHitNormal = Hit.ImpactNormal;
|
||||
SetTarget(HitActor, Interactable);
|
||||
}
|
||||
|
||||
void UInteractionTraceComponent::SetTarget(AActor* NewTarget, UInteractableComponent* NewInteractable)
|
||||
{
|
||||
if (CurrentTarget == NewTarget && CurrentInteractable == NewInteractable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
CurrentTarget = NewTarget;
|
||||
CurrentInteractable = NewInteractable;
|
||||
OnTargetChanged.Broadcast(NewTarget, NewInteractable);
|
||||
}
|
||||
Reference in New Issue
Block a user