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:
151
Source/ItemWorld/Public/HeldItemComponent.h
Normal file
151
Source/ItemWorld/Public/HeldItemComponent.h
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright ExByte Studios. Item Interaction Ecosystem.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Components/ActorComponent.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "ItemEnums.h"
|
||||
#include "ItemInstanceData.h"
|
||||
#include "ItemInteractionInterfaces.h"
|
||||
#include "HeldItemComponent.generated.h"
|
||||
|
||||
class APickupItemActor;
|
||||
|
||||
/** Replicated snapshot of what the character is currently holding (section 11.1). */
|
||||
USTRUCT(BlueprintType)
|
||||
struct ITEMWORLD_API FHeldItemState
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
bool bHasHeldItem = false;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
FGuid InstanceId;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
FName ItemId;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
EHeldItemMode Mode = EHeldItemMode::None;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
TObjectPtr<AActor> HeldWorldActor = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
FName HoldSocket = NAME_None;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
float MoveSpeedMultiplier = 1.f;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
bool bBlocksSprint = false;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
bool bBlocksClimb = false;
|
||||
|
||||
/** Snapshot of the carried item (so we can drop/install it without the actor). */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Held")
|
||||
FItemInstanceData Item;
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHeldItemChanged, const FHeldItemState&, NewState);
|
||||
|
||||
/**
|
||||
* Physically carries one bulky item attached to the character (section 11.2-11.3).
|
||||
*
|
||||
* This is the "two-handed carry" path for batteries, canisters, wheels, crates,
|
||||
* corpses, etc. - distinct from equipment (which keeps the item in the inventory
|
||||
* and only spawns a visual). Server-authoritative; visuals/penalties apply on all
|
||||
* clients via OnRep. Implements IHeldItemInterface so the resolver can build
|
||||
* held+target interactions.
|
||||
*/
|
||||
UCLASS(ClassGroup = (Inventory), meta = (BlueprintSpawnableComponent))
|
||||
class ITEMWORLD_API UHeldItemComponent : public UActorComponent, public IHeldItemInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UHeldItemComponent();
|
||||
|
||||
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Held")
|
||||
FName CarrySocket = FName("CarrySocket");
|
||||
|
||||
/** Hold distance in front of the view for physics-handle carry (section 11.4). */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Held")
|
||||
float PhysicsHoldDistance = 200.f;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "Held")
|
||||
FOnHeldItemChanged OnHeldItemChanged;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Held")
|
||||
bool HasHeldItemBP() const { return HeldItem.bHasHeldItem; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Held")
|
||||
const FHeldItemState& GetHeldItemState() const { return HeldItem; }
|
||||
|
||||
UFUNCTION(BlueprintPure, Category = "Held")
|
||||
bool CanHoldItem(const FItemInstanceData& Item) const;
|
||||
|
||||
/** Client entry: ask the server to drop the carried item (bind to the Drop input). */
|
||||
UFUNCTION(BlueprintCallable, Category = "Held")
|
||||
void RequestDrop();
|
||||
|
||||
// --- Server entry points (section 11.1) ---
|
||||
|
||||
/** Server: pick up and carry a world item actor attached to a socket (World -> Held). */
|
||||
bool ServerHoldWorldItem(AActor* WorldItem);
|
||||
|
||||
/** Server: carry a world item via a physics handle instead of a fixed socket (section 11.4). */
|
||||
bool ServerHoldWorldItemPhysics(AActor* WorldItem);
|
||||
|
||||
/** Server: drop the carried item back into the world (Held -> World). */
|
||||
bool ServerDropHeldItem();
|
||||
|
||||
/** Server: relinquish the carried item without spawning a drop (e.g. on install). */
|
||||
bool ServerConsumeHeldItem(FItemInstanceData& OutItem);
|
||||
|
||||
/**
|
||||
* Server: hand off the carried item AND its actor to a new owner (e.g. a world
|
||||
* slot) without destroying the actor. Clears the held state. Returns false if
|
||||
* nothing was held.
|
||||
*/
|
||||
bool ServerHandOffHeldItem(FItemInstanceData& OutItem, AActor*& OutActor);
|
||||
|
||||
/** Server: update the carried item's data in place (e.g. after pouring out fuel). */
|
||||
bool ServerUpdateHeldItem(const FItemInstanceData& NewItem);
|
||||
|
||||
//~ IHeldItemInterface
|
||||
virtual bool GetHeldItem(FItemInstanceData& OutItem) const override;
|
||||
virtual bool HasHeldItem() const override { return HeldItem.bHasHeldItem; }
|
||||
|
||||
protected:
|
||||
UPROPERTY(ReplicatedUsing = OnRep_HeldItem)
|
||||
FHeldItemState HeldItem;
|
||||
|
||||
UFUNCTION(Server, Reliable)
|
||||
void Server_Drop();
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_HeldItem(FHeldItemState OldState);
|
||||
|
||||
/** Applies/removes the movement-speed penalty on the owning character. */
|
||||
void ApplyMovementState();
|
||||
|
||||
bool HasAuthority() const;
|
||||
|
||||
private:
|
||||
/** Owning character's unmodified MaxWalkSpeed, captured the first time we modify it. */
|
||||
UPROPERTY(Transient)
|
||||
float CachedBaseWalkSpeed = 0.f;
|
||||
|
||||
/** Created on demand for physics-handle carry. */
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<class UPhysicsHandleComponent> PhysicsHandle = nullptr;
|
||||
|
||||
void UpdatePhysicsCarryTarget();
|
||||
};
|
||||
Reference in New Issue
Block a user