Fixes for placeable objects and inventory tabs

This commit is contained in:
2026-09-11 21:46:30 +02:00
parent a6c6ddcc63
commit d72a9c957a
61 changed files with 381 additions and 315 deletions

View File

@@ -11,6 +11,7 @@
#include "../Public/EleriPlayerController.h"
#include "../Public/MyCharacter.h"
#include "Engine/OverlapResult.h"
#include "LandscapeProxy.h"
// Sets default values for this component's properties
UMoveActorsComponent::UMoveActorsComponent()
@@ -18,8 +19,6 @@ UMoveActorsComponent::UMoveActorsComponent()
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
// ...
}
@@ -31,13 +30,19 @@ void UMoveActorsComponent::BeginPlay()
PlayerController = Cast<AEleriPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
PlayerCharacter = Cast<AMyCharacter>(GetOwner());
if (!PlayerCharacter)
{
return;
}
TArray<AActor*> OutActors;
PlayerCharacter->GetOverlappingActors(OutActors);
for (auto Actor : OutActors)
for (const AActor* Actor : OutActors)
{
if(PlantableAreaActorClass == Actor->GetClass())
if (Actor && PlantableAreaActorClass == Actor->GetClass())
{
bRemovalModePossible = true;
break;
}
}
}
@@ -48,114 +53,121 @@ void UMoveActorsComponent::TickComponent(float DeltaTime, ELevelTick TickType, F
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (!PlayerCharacter || !MovingActor) return;
if (!PlayerCharacter || !IsValid(MovingActor) || MovingActor->bPlaced) return;
if (!MovingActor->bPlaced)
FVector ForwardVec = PlayerCharacter->GetActorForwardVector();
if (PlayerController && PlayerController->PlayerCameraManager)
{
FVector ForwardVec;
if (APlayerCameraManager* CameraManager = UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0))
ForwardVec = PlayerController->PlayerCameraManager->GetCameraRotation().Vector();
ForwardVec.Z = 0.f;
}
// Prefer the per-actor tuning values, falling back to the component defaults.
const float Distance = MovingActor->DistanceFromActor > 0.f ? MovingActor->DistanceFromActor : PlacementDistance;
const float GridSnap = MovingActor->GridScale > 0.f ? MovingActor->GridScale : GridSnapSize;
FVector PosVector = PlayerCharacter->GetActorLocation() + (ForwardVec * Distance) + FVector(0.f, 0.f, PlacementHeightOffset);
if (bGridMovementActive)
{
PosVector = UKismetMathLibrary::Vector_SnappedToGrid(PosVector, GridSnap);
}
const FVector TargetScale = (MovingActor->ScaleOverride != FVector::ZeroVector) ? MovingActor->ScaleOverride : MovingActor->GetActorScale();
MovingActor->SetActorTransform(FTransform(MovingActor->GetActorRotation(), PosVector, TargetScale));
// Snap the object down onto the ground beneath it.
FCollisionObjectQueryParams QueryParams;
QueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
const FVector TraceEnd = MovingActor->GetActorLocation() + FVector(0.f, 0.f, -GroundTraceLength);
TArray<FHitResult> OutHits;
GetWorld()->LineTraceMultiByObjectType(OutHits, MovingActor->GetActorLocation(), TraceEnd, QueryParams);
MovingActor->bPlaceable = true;
MovingActor->IntersectingActors.Empty();
for (const FHitResult& HitResult : OutHits)
{
AActor* HitActor = HitResult.GetActor();
if (!HitActor || HitActor == MovingActor) continue;
MovingActor->IntersectingActors.Add(HitActor);
if (HitActor->IsA(ALandscapeProxy::StaticClass()))
{
ForwardVec = CameraManager->GetCameraRotation().Vector();
ForwardVec.Z = 0;
}
else
{
ForwardVec = PlayerCharacter->GetActorForwardVector();
}
//FVector PosVector = UKismetMathLibrary::Vector_SnappedToGrid(PlayerCharacter->GetActorLocation() + ((ForwardVec * MovingActor->DistanceFromActor) + FVector(0.f, 0.f, 100.f)), MovingActor->GridScale);
FVector PosVector = PlayerCharacter->GetActorLocation() + ((ForwardVec * 800.f) + FVector(0.f, 0.f, 100.f));
if (bGridMovementActive)
{
PosVector = UKismetMathLibrary::Vector_SnappedToGrid(PosVector, 250.f);
}
FTransform NewTransform = FTransform(MovingActor->GetActorRotation(), PosVector, (MovingActor->ScaleOverride != FVector::ZeroVector) ? MovingActor->ScaleOverride : MovingActor->GetActorScale());
MovingActor->SetActorTransform(NewTransform);
TArray<FHitResult> OutHits;
FCollisionObjectQueryParams QueryParams;
QueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic);
FVector TraceEnd = (MovingActor->GetActorLocation() + FVector(0.f, 0.f, -1000.f));
GetWorld()->LineTraceMultiByObjectType(OutHits, MovingActor->GetActorLocation(), TraceEnd, QueryParams);
MovingActor->bPlaceable = true;
MovingActor->IntersectingActors.Empty();
for (const FHitResult& HitResult : OutHits)
{
if (HitResult.GetActor() == MovingActor) continue;
MovingActor->IntersectingActors.Add(HitResult.GetActor());
if (HitResult.GetActor()->GetClass()->GetName() == FString("Landscape"))
{
MovingActor->SetActorLocation(HitResult.ImpactPoint);
}
}
//Check if moving object is overlapping
TArray<AActor*> OverlappingActors;
FVector Center, BoxExtent;
MovingActor->GetActorBounds(false, Center, BoxExtent);
BoxExtent *= 0.9f;
if (!MovingActor->BoxExtentOverride.IsNearlyZero())
{
BoxExtent = MovingActor->BoxExtentOverride;
}
TArray<FOverlapResult> OverlapResults;
FCollisionQueryParams QueryParams1;
QueryParams1.bTraceComplex = true;
QueryParams1.AddIgnoredActor(MovingActor);
QueryParams1.AddIgnoredActor(PlayerCharacter);
FCollisionObjectQueryParams ObjectQueryParams;
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldDynamic);
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel1);
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel2);
bool bHit = GetWorld()->OverlapMultiByObjectType(
OverlapResults,
MovingActor->GetActorLocation(),
FQuat::Identity,
ObjectQueryParams,
FCollisionShape::MakeBox(BoxExtent), // Or MakeSphere, MakeCapsule
QueryParams1
);
for (const FOverlapResult& OverlapResult : OverlapResults)
{
if (OverlapResult.GetActor())
OverlappingActors.Add(OverlapResult.GetActor());
}
//DrawDebugBox(GetWorld(), MovingActor->GetActorLocation(), BoxExtent, FColor::Red);
bool PlantableAreaFound = false;
for (auto OverlappingActor : OverlappingActors)
{
if (OverlappingActor->GetClass() == PlantableAreaActorClass)
{
PlantableAreaFound = true;
}
if (OverlappingActor->GetClass()->GetName() == FString("Landscape") ||
!OverlappingActor->GetClass()->IsChildOf(AStaticMeshActor::StaticClass())) continue;
if (!ActorsToIgnore.FindByPredicate([&OverlappingActor](const TSubclassOf<AActor>& ActorClass) { return OverlappingActor->GetClass() == ActorClass; }))
{
MovingActor->bPlaceable = false;
break;
}
}
if(!PlantableAreaFound)
MovingActor->bPlaceable = false;
if (MovingActor)
{
MovingActor->GetStaticMeshComponent()->SetOverlayMaterial((!MovingActor->bPlaceable) ? MovingActor->CantPlaceMaterial : MovingActor->CanPlaceMaterial);
MovingActor->K2_TogglePlaceableEffects(MovingActor->bPlaceable);
MovingActor->SetActorLocation(HitResult.ImpactPoint);
}
}
// Check whether the object overlaps anything that should block placement.
FVector Center, BoxExtent;
MovingActor->GetActorBounds(false, Center, BoxExtent);
BoxExtent *= OverlapBoxExtentMultiplier;
if (!MovingActor->BoxExtentOverride.IsNearlyZero())
{
BoxExtent = MovingActor->BoxExtentOverride;
}
FCollisionQueryParams OverlapQueryParams;
OverlapQueryParams.bTraceComplex = true;
OverlapQueryParams.AddIgnoredActor(MovingActor);
OverlapQueryParams.AddIgnoredActor(PlayerCharacter);
FCollisionObjectQueryParams ObjectQueryParams;
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldStatic);
ObjectQueryParams.AddObjectTypesToQuery(ECC_WorldDynamic);
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel1);
ObjectQueryParams.AddObjectTypesToQuery(ECC_GameTraceChannel2);
TArray<FOverlapResult> OverlapResults;
GetWorld()->OverlapMultiByObjectType(
OverlapResults,
MovingActor->GetActorLocation(),
MovingActor->GetActorQuat(),
ObjectQueryParams,
FCollisionShape::MakeBox(BoxExtent),
OverlapQueryParams
);
bool PlantableAreaFound = false;
for (const FOverlapResult& OverlapResult : OverlapResults)
{
AActor* OverlappingActor = OverlapResult.GetActor();
if (!OverlappingActor) continue;
if (PlantableAreaActorClass == OverlappingActor->GetClass())
{
PlantableAreaFound = true;
}
// Landscape and non-static-mesh actors don't block placement.
if (OverlappingActor->IsA(ALandscapeProxy::StaticClass()) || !OverlappingActor->GetClass()->IsChildOf(AStaticMeshActor::StaticClass()))
{
continue;
}
const bool bIsIgnored = ActorsToIgnore.ContainsByPredicate([&OverlappingActor](const TSubclassOf<AActor>& ActorClass)
{
return OverlappingActor->GetClass() == ActorClass;
});
if (!bIsIgnored)
{
MovingActor->bPlaceable = false;
break;
}
}
if (!PlantableAreaFound)
{
MovingActor->bPlaceable = false;
}
if (UStaticMeshComponent* MeshComponent = MovingActor->GetStaticMeshComponent())
{
MeshComponent->SetOverlayMaterial((!MovingActor->bPlaceable) ? MovingActor->CantPlaceMaterial : MovingActor->CanPlaceMaterial);
}
MovingActor->K2_TogglePlaceableEffects(MovingActor->bPlaceable);
}
void UMoveActorsComponent::ToggleGridMovement()
@@ -172,20 +184,21 @@ bool UMoveActorsComponent::PlaceableActionUsed(ERemovalAction ActionUsed)
switch (ActionUsed)
{
case ERemovalAction::NONE:
case ERemovalAction::MAX:
default:
break;
case ERemovalAction::START_MOVE:
if (AEleriPlayerController* PC = Cast<AEleriPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0)))
{
PickUpObjectForPlacing(HighligtedMovingActor);
return true;
}
break;
return PickUpObjectForPlacing(HighligtedMovingActor);
case ERemovalAction::PLACE:
if (PlayerController && MovingActor && MovingActor->IsPlaceable())
if (PlayerController && MovingActor->IsPlaceable())
{
FPrimaryAssetId ItemId = MovingActor->ItemStack.ItemId;
if (!ItemId.IsValid())
{
ItemId = MovingActor->DataAssetId;
}
if (ItemId.IsValid())
{
if (UInventoryComponent* Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(GetWorld()))
@@ -197,52 +210,50 @@ bool UMoveActorsComponent::PlaceableActionUsed(ERemovalAction ActionUsed)
return true;
}
break;
//Will place it in inventory
case ERemovalAction::REMOVE:
case ERemovalAction::EXIT:
if (UGameInstance* GI = UGameplayStatics::GetGameInstance(GetWorld()))
{
// A world object is returned to the player's inventory before it is removed.
if (MovingActor->DataAssetId.IsValid() && !MovingActor->bFromInventory)
{
if (UObjectPersistenceSubsystem* ObjectPersistenceSubsystem = GI->GetSubsystem<UObjectPersistenceSubsystem>())
if (UInventoryComponent* Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(GetWorld()))
{
Inventory->AddItemToInventory(MovingActor->DataAssetId, 1, false, false);
}
}
if (UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld()))
{
if (UObjectPersistenceSubsystem* ObjectPersistenceSubsystem = GameInstance->GetSubsystem<UObjectPersistenceSubsystem>())
{
if (MovingActor)
{
if (MovingActor->DataAssetId.IsValid() && !MovingActor->bFromInventory)
{
if (UInventoryComponent* Inventory = UMainBlueprintFunctionLibrary::GetPlayerInventory(GetWorld()))
{
Inventory->AddItemToInventory(MovingActor->DataAssetId, 1, false, false);
}
}
}
ObjectPersistenceSubsystem->RemoveActorFromLevel(MovingActor);
return true;
}
}
break;
/*if (MovingActor->InventoryRef)
// Fallback if the persistence subsystem is unavailable.
MovingActor->Destroy();
return true;
}
case ERemovalAction::EXIT:
{
// Cancel the current placement/move without committing it.
if (MovingActor->bFromInventory)
{
PlaceableActionUsed(ERemovalAction::REMOVE);
// A preview spawned from the inventory: return the item and destroy the preview.
MovingActor->ReturnToInventory();
MovingActor->Destroy();
}
else
{
// An existing world object: put it back where it was picked up from.
MovingActor->SetActorTransform(MovingActor->CurrentMemorizedTransform);
for (int32 i = 0; i < MovingActor->MeshMaterials.Num(); i++)
{
MovingActor->GetStaticMeshComponent()->SetMaterial(i, MovingActor->MeshMaterials[i]);
}
MovingActor->GetStaticMeshComponent()->SetOverlayMaterial(nullptr);
if (PlayerController)
{
PlaceObjectForPlacing();
}
return true;
}*/
break;
case ERemovalAction::MAX:
break;
default:
break;
}
return true;
}
}
return false;
}
@@ -253,7 +264,7 @@ void UMoveActorsComponent::ToggleRemovalModeOption(bool bNewRemoveModePossible)
bool UMoveActorsComponent::PickUpObjectForPlacing(ARemovableStaticMeshActor* Placable)
{
if (MovingActor || !Placable || !PlayerController) return false;
if (MovingActor || !IsValid(Placable) || !PlayerController) return false;
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
@@ -268,16 +279,14 @@ bool UMoveActorsComponent::PickUpObjectForPlacing(ARemovableStaticMeshActor* Pla
bool UMoveActorsComponent::PlaceObjectForPlacing()
{
if (!MovingActor) return false;
if (!IsValid(MovingActor)) return false;
if (MovingActor)
if (UStaticMeshComponent* MeshComponent = MovingActor->GetStaticMeshComponent())
{
if (MovingActor->GetStaticMeshComponent())
{
MovingActor->GetStaticMeshComponent()->SetOverlayMaterial(nullptr);
}
MovingActor->Place();
MeshComponent->SetOverlayMaterial(nullptr);
}
MovingActor->Place();
RemovalModePlacingStack--;
return RemoveObjectForPlacing();
}
@@ -290,9 +299,11 @@ bool UMoveActorsComponent::RemoveObjectForPlacing()
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
if (RemovalModePlacingStack <= 0)
{
Subsystem->RemoveMappingContext(PlayerController->RemoveModeContext);
}
}
MovingActor = nullptr;
return true;
}
@@ -300,9 +311,11 @@ bool UMoveActorsComponent::RemoveObjectForPlacing()
void UMoveActorsComponent::StartObjectRemoval(bool bStart, int32 Stack)
{
if (!PlayerCharacter) return;
if (!bStart)
{
PlayerCharacter->bAlreadyInteracting = bStart;
PlayerCharacter->bAlreadyInteracting = false;
}
PlayerCharacter->CurrentlyDoing = bStart ? ECurrentlyDoing::OBJECT_PLACING : ECurrentlyDoing::NOTHING;
@@ -312,29 +325,33 @@ void UMoveActorsComponent::StartObjectRemoval(bool bStart, int32 Stack)
if (!bStart)
{
PlayerCharacter->ZoomBack(0.5f);
}
else if (bStart)
else
{
PlayerCharacter->ZoomCamera(-500.f, 0.5f);
PlayerCharacter->ZoomCamera(500.f, 0.5f);
}
bRemovalMode = bStart;
OnRemovalModeToggled.Broadcast(bRemovalMode);
PlayerCharacter->SetNewCameraPitches(
bStart? PlayerCharacter->CameraPitchMin - 50 : PlayerCharacter->CameraPitchMin,
bStart? PlayerCharacter->CameraPitchMax + 5 : PlayerCharacter->CameraPitchMax);
bStart ? PlayerCharacter->CameraPitchMin - 50 : PlayerCharacter->CameraPitchMin,
bStart ? PlayerCharacter->CameraPitchMax + 5 : PlayerCharacter->CameraPitchMax);
if (PlayerController->GetMainGameWidget())
if (PlayerController && PlayerController->GetMainGameWidget())
{
PlayerController->GetMainGameWidget()->SwitchKeybindsDisplay(bRemovalMode ? 4 : 1);
}
// Get the Enhanced Input Local Player Subsystem from the Local Player related to our Player Controller.
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
if (PlayerController)
{
if (!bStart)
if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
{
Subsystem->RemoveMappingContext(PlayerController->RemoveModeContext);
if (!bStart)
{
Subsystem->RemoveMappingContext(PlayerController->RemoveModeContext);
}
}
}
@@ -343,38 +360,21 @@ void UMoveActorsComponent::StartObjectRemoval(bool bStart, int32 Stack)
bool UMoveActorsComponent::HighlightRemovableObject(ARemovableStaticMeshActor* Placable)
{
if (!bRemovalModePossible || !bRemovalMode) return false;
if (!bRemovalModePossible || !bRemovalMode || !IsValid(Placable)) return false;
if (!HighligtedMovingActor)
if (HighligtedMovingActor == Placable)
{
HighligtedMovingActor = Placable;
return true;
}
else
{
if (HighligtedMovingActor != Placable)
{
if (HighligtedMovingActor)
{
HighligtedMovingActor = Placable;
}
}
else
{
return true;
}
}
return false;
HighligtedMovingActor = Placable;
return true;
}
void UMoveActorsComponent::UnhighlightRemovableObject(ARemovableStaticMeshActor* Placable)
{
if (Placable)
if (Placable && HighligtedMovingActor == Placable)
{
if (HighligtedMovingActor == Placable)
{
HighligtedMovingActor = nullptr;
}
HighligtedMovingActor = nullptr;
}
}

View File

@@ -47,6 +47,21 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<AActor> PlantableAreaActorClass;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
float PlacementDistance = 800.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
float PlacementHeightOffset = 100.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
float GridSnapSize = 250.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement")
float GroundTraceLength = 1000.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Placement", meta = (ClampMin = "0.0", ClampMax = "1.0"))
float OverlapBoxExtentMultiplier = 0.9f;
UPROPERTY(BlueprintAssignable)
FOnRemovalModeToggled OnRemovalModeToggled;
@@ -84,9 +99,9 @@ public:
FORCEINLINE bool IsGridMovementActive() const { return bGridMovementActive; }
UFUNCTION(BlueprintCallable, BlueprintPure)
inline bool IsRemovingModePossible() { return bRemovalModePossible; }
bool IsRemovingModePossible() const { return bRemovalModePossible; }
UFUNCTION(BlueprintCallable, BlueprintPure)
inline bool IsRemovingMode() { return bRemovalMode; }
bool IsRemovingMode() const { return bRemovalMode; }
UFUNCTION(BlueprintCallable)

View File

@@ -13,18 +13,61 @@
ARemovableStaticMeshActor::ARemovableStaticMeshActor()
{
PrimaryActorTick.bCanEverTick = true;
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
SetRootComponent(RootComponent);
WidgetComponent = CreateDefaultSubobject<UInteractionWidgetComponent>(TEXT("WidgetComponent"));
WidgetComponent->SetupAttachment(RootComponent);
OverlapBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapBoxComponent"));
OverlapBoxComponent->SetupAttachment(RootComponent);
// Detection only: the box never blocks anything, it only reports overlaps.
OverlapBoxComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
OverlapBoxComponent->SetCollisionObjectType(OverlapBoxObjectType);
OverlapBoxComponent->SetCollisionResponseToAllChannels(ECR_Overlap);
OverlapBoxComponent->SetCollisionResponseToChannel(ECC_Visibility, ECR_Ignore);
OverlapBoxComponent->SetGenerateOverlapEvents(true);
OverlapBoxComponent->SetCanEverAffectNavigation(false);
}
void ARemovableStaticMeshActor::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
UpdateOverlapBoxExtent();
}
void ARemovableStaticMeshActor::UpdateOverlapBoxExtent()
{
if (!OverlapBoxComponent)
{
return;
}
OverlapBoxComponent->SetCollisionObjectType(OverlapBoxObjectType);
UStaticMeshComponent* MeshComponent = GetStaticMeshComponent();
if (!MeshComponent || !MeshComponent->GetStaticMesh())
{
OverlapBoxComponent->SetBoxExtent(FVector::ZeroVector);
return;
}
// GetLocalBounds returns the mesh' bounding box in its own local space.
FVector BoundsMin, BoundsMax;
MeshComponent->GetLocalBounds(BoundsMin, BoundsMax);
OverlapBoxComponent->SetRelativeLocation((BoundsMin + BoundsMax) * 0.5f);
OverlapBoxComponent->SetBoxExtent(!BoxExtentOverride.IsNearlyZero()
? BoxExtentOverride
: (BoundsMax - BoundsMin) * 0.5f);
}
void ARemovableStaticMeshActor::BeginPlay()
{
Super::BeginPlay();
// Keep the detection box in sync with the mesh that is actually assigned at runtime.
UpdateOverlapBoxExtent();
PlayerRef = UGameplayStatics::GetActorOfClass(GetWorld(), AMyCharacter::StaticClass());
if (PlayerRef) {
MoveableComponent = PlayerRef->GetComponentByClass<UMoveActorsComponent>();

View File

@@ -6,6 +6,7 @@
#include "Engine/StaticMeshActor.h"
#include "../Public/InventoryComponent.h"
#include "Components/InteractionWidgetComponent.h"
#include "Components/BoxComponent.h"
#include "Interface/InteractableActorInterface.h"
#include "RemovableStaticMeshActor.generated.h"
@@ -28,6 +29,8 @@ public:
ARemovableStaticMeshActor();
virtual void BeginPlay() override;
virtual void OnConstruction(const FTransform& Transform) override;
virtual void ToggleInteractableUI_Implementation(bool bActive) override;
virtual bool IsInteractable_Implementation() const override;
@@ -76,11 +79,24 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Removable Object")
FPrimaryAssetId DataAssetId;
/** Overlap only collision box that always fits the static mesh' bounding box.
* It never blocks anything, it only reports what the object currently overlaps. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Removable Object")
UBoxComponent* OverlapBoxComponent;
/** Collision object type of OverlapBoxComponent. Defaults to the project's "RemovableStaticMEsh" channel. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Removable Object")
TEnumAsByte<ECollisionChannel> OverlapBoxObjectType = ECC_GameTraceChannel2;
/** Resizes OverlapBoxComponent so it fits the mesh' bounding box (or BoxExtentOverride when that one is set). */
UFUNCTION(BlueprintCallable, Category = "Removable Object")
void UpdateOverlapBoxExtent();
//Used for movable actors to override their box extent for checking collision
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Removable Object")
FVector BoxExtentOverride = FVector::ZeroVector;
UFUNCTION(BlueprintCallable, BLueprintPure)
UFUNCTION(BlueprintCallable, BlueprintPure)
FORCEINLINE bool IsPlaceable() const { return bPlaceable; }
UFUNCTION(BlueprintCallable, BLueprintPure)
FORCEINLINE bool FromInventory() const { return InventoryRef != nullptr; }

View File

@@ -33,7 +33,7 @@ public class ProjectEleri : ModuleRules
"InteractionSystem"
});
PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", "OnlineSubsystemUtils" });
PrivateDependencyModuleNames.AddRange(new string[] { "OnlineSubsystem", "OnlineSubsystemUtils", "Landscape" });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });

View File

@@ -3,7 +3,6 @@
#include "ObjectPersistenceSubsystem.h"
#include "Interface/RemovableActorInterface.h"
#include "../../Components/PlacableActorComponent.h"
#include "Kismet/GameplayStatics.h"
#include "../../Public/EleriSaveGame.h"
#include "../GameObjects/RemovableStaticMeshActor.h"
@@ -27,16 +26,10 @@ void UObjectPersistenceSubsystem::RemoveActorFromLevel(AActor* ActorToRemove)
//Check if actor existed meaning we're placing it for the first time
int32 ActorIndex = ActorExistsInList(ActorToRemove);
if (ActorIndex == -1)
{
if (UPlacableActorComponent* Placeable = ActorToRemove->GetComponentByClass<UPlacableActorComponent>())
{
//Placeable->ReturnToInventory();
}
}
else
if (ActorIndex != INDEX_NONE)
{
PlacedActors.RemoveAt(ActorIndex);
}
ActorToRemove->Destroy();

View File

@@ -6,7 +6,6 @@
#include "Subsystems/GameInstanceSubsystem.h"
#include "ObjectPersistenceSubsystem.generated.h"
class UPlacableActorComponent;
class UEleriSaveGame;
USTRUCT(BlueprintType)