Add item pickup actor
This commit is contained in:
@@ -490,7 +490,10 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
||||
- [x] Create item definition data asset.
|
||||
- [x] Create item stack structure.
|
||||
- [x] Create inventory component.
|
||||
- [ ] Add item pickup.
|
||||
- [x] Add item pickup. Added native `AAgrarianItemPickup` interactable world
|
||||
actor with definition-backed or inline stack data, server-authoritative
|
||||
inventory add, prompt text, and destroy-on-success behavior so failed pickups
|
||||
remain available.
|
||||
- [ ] Add item drop.
|
||||
- [ ] Add stack splitting.
|
||||
- [ ] Add item use.
|
||||
|
||||
@@ -91,6 +91,14 @@ and save-game `FAgrarianItemStack` records, and a server-authoritative
|
||||
splitting, item use, equipment, carry capacity, persistence, and UI work should
|
||||
extend that contract rather than inventing parallel inventory state.
|
||||
|
||||
World pickups use `AAgrarianItemPickup`, an interactable replicated actor with a
|
||||
static mesh and either a definition-backed or inline `FAgrarianItemStack`.
|
||||
Player interaction already routes to the server through the Agrarian character,
|
||||
so pickups validate authority, produce a valid stack, add it to the player's
|
||||
inventory, and only then remove the pickup by destroying the world pickup actor.
|
||||
If the inventory is full or the stack is invalid, the pickup remains in the
|
||||
world for another attempt.
|
||||
|
||||
## Time And Environment
|
||||
|
||||
The MVP gameplay calendar target is:
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FILES = {
|
||||
"AgrarianItemPickup.h": ROOT / "Source" / "AgrarianGame" / "AgrarianItemPickup.h",
|
||||
"AgrarianItemPickup.cpp": ROOT / "Source" / "AgrarianGame" / "AgrarianItemPickup.cpp",
|
||||
"InventoryDataModel.md": ROOT / "Docs" / "InventoryDataModel.md",
|
||||
"TechnicalDesignDocument.md": ROOT / "Docs" / "TechnicalDesignDocument.md",
|
||||
"AGRARIAN_DEVELOPMENT_ROADMAP.md": ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md",
|
||||
}
|
||||
|
||||
EXPECTED = {
|
||||
"AgrarianItemPickup.h": [
|
||||
"class AGRARIANGAME_API AAgrarianItemPickup : public AActor, public IAgrarianInteractable",
|
||||
"TObjectPtr<UStaticMeshComponent> Mesh;",
|
||||
"FAgrarianItemStack PickupStack;",
|
||||
"TObjectPtr<UAgrarianItemDefinitionAsset> ItemDefinition;",
|
||||
"int32 Quantity = 1;",
|
||||
"virtual FText GetInteractionText_Implementation",
|
||||
"virtual bool CanInteract_Implementation",
|
||||
"virtual void Interact_Implementation",
|
||||
"FAgrarianItemStack MakePickupStack() const;",
|
||||
],
|
||||
"AgrarianItemPickup.cpp": [
|
||||
"bReplicates = true;",
|
||||
"Mesh->SetCollisionProfileName(TEXT(\"BlockAll\"));",
|
||||
"ItemDefinition->MakeStack(Quantity)",
|
||||
"MakePickupStack().IsValidStack()",
|
||||
"if (!HasAuthority() || !Interactor)",
|
||||
"Interactor->GetInventoryComponent()",
|
||||
"Inventory->AddItem(Stack)",
|
||||
"Destroy();",
|
||||
],
|
||||
"InventoryDataModel.md": [
|
||||
"Pickup:",
|
||||
"world item validates range, authority, stack data, and available",
|
||||
],
|
||||
"TechnicalDesignDocument.md": [
|
||||
"`AAgrarianItemPickup`",
|
||||
"definition-backed or inline `FAgrarianItemStack`",
|
||||
"destroying the world pickup actor",
|
||||
],
|
||||
"AGRARIAN_DEVELOPMENT_ROADMAP.md": [
|
||||
"[x] Add item pickup.",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
missing = []
|
||||
for label, path in FILES.items():
|
||||
text = path.read_text(encoding="utf-8")
|
||||
for snippet in EXPECTED[label]:
|
||||
if snippet not in text:
|
||||
missing.append(f"{label}: {snippet}")
|
||||
|
||||
if missing:
|
||||
raise RuntimeError("Item pickup verification failed: " + "; ".join(missing))
|
||||
|
||||
print("Agrarian item pickup verification complete.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright Pacificao. All Rights Reserved.
|
||||
|
||||
#include "AgrarianItemPickup.h"
|
||||
#include "AgrarianGameCharacter.h"
|
||||
#include "AgrarianInventoryComponent.h"
|
||||
#include "AgrarianItemDefinitionAsset.h"
|
||||
#include "Components/StaticMeshComponent.h"
|
||||
|
||||
AAgrarianItemPickup::AAgrarianItemPickup()
|
||||
{
|
||||
bReplicates = true;
|
||||
|
||||
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||
RootComponent = Mesh;
|
||||
Mesh->SetCollisionProfileName(TEXT("BlockAll"));
|
||||
|
||||
PickupStack.ItemId = TEXT("wood");
|
||||
PickupStack.DisplayName = FText::FromString(TEXT("Wood"));
|
||||
PickupStack.Quantity = 1;
|
||||
PickupStack.UnitWeight = 1.0f;
|
||||
InteractionVerb = FText::FromString(TEXT("Pick up"));
|
||||
}
|
||||
|
||||
FText AAgrarianItemPickup::GetInteractionText_Implementation(const AAgrarianGameCharacter* Interactor) const
|
||||
{
|
||||
const FAgrarianItemStack Stack = MakePickupStack();
|
||||
const FText DisplayName = Stack.DisplayName.IsEmpty() ? FText::FromName(Stack.ItemId) : Stack.DisplayName;
|
||||
const FString Verb = InteractionVerb.IsEmpty() ? FString(TEXT("Pick up")) : InteractionVerb.ToString();
|
||||
|
||||
if (Stack.Quantity > 1)
|
||||
{
|
||||
return FText::FromString(FString::Printf(TEXT("%s %s x%d"), *Verb, *DisplayName.ToString(), Stack.Quantity));
|
||||
}
|
||||
|
||||
return FText::FromString(FString::Printf(TEXT("%s %s"), *Verb, *DisplayName.ToString()));
|
||||
}
|
||||
|
||||
bool AAgrarianItemPickup::CanInteract_Implementation(const AAgrarianGameCharacter* Interactor) const
|
||||
{
|
||||
return Interactor != nullptr && MakePickupStack().IsValidStack();
|
||||
}
|
||||
|
||||
void AAgrarianItemPickup::Interact_Implementation(AAgrarianGameCharacter* Interactor)
|
||||
{
|
||||
if (!HasAuthority() || !Interactor)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UAgrarianInventoryComponent* Inventory = Interactor->GetInventoryComponent();
|
||||
if (!Inventory)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const FAgrarianItemStack Stack = MakePickupStack();
|
||||
if (Inventory->AddItem(Stack))
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
FAgrarianItemStack AAgrarianItemPickup::MakePickupStack() const
|
||||
{
|
||||
if (ItemDefinition)
|
||||
{
|
||||
return ItemDefinition->MakeStack(Quantity);
|
||||
}
|
||||
|
||||
FAgrarianItemStack Stack = PickupStack;
|
||||
if (Quantity > 0)
|
||||
{
|
||||
Stack.Quantity = Quantity;
|
||||
}
|
||||
return Stack;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright Pacificao. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "AgrarianInteractable.h"
|
||||
#include "AgrarianTypes.h"
|
||||
#include "AgrarianItemPickup.generated.h"
|
||||
|
||||
class AAgrarianGameCharacter;
|
||||
class UAgrarianItemDefinitionAsset;
|
||||
class UStaticMeshComponent;
|
||||
|
||||
UCLASS(Blueprintable)
|
||||
class AGRARIANGAME_API AAgrarianItemPickup : public AActor, public IAgrarianInteractable
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
AAgrarianItemPickup();
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Agrarian|Pickup")
|
||||
TObjectPtr<UStaticMeshComponent> Mesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Pickup")
|
||||
FAgrarianItemStack PickupStack;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Pickup")
|
||||
TObjectPtr<UAgrarianItemDefinitionAsset> ItemDefinition;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Pickup", meta = (ClampMin = "1"))
|
||||
int32 Quantity = 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Pickup")
|
||||
FText InteractionVerb;
|
||||
|
||||
virtual FText GetInteractionText_Implementation(const AAgrarianGameCharacter* Interactor) const override;
|
||||
virtual bool CanInteract_Implementation(const AAgrarianGameCharacter* Interactor) const override;
|
||||
virtual void Interact_Implementation(AAgrarianGameCharacter* Interactor) override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Pickup")
|
||||
FAgrarianItemStack MakePickupStack() const;
|
||||
};
|
||||
Reference in New Issue
Block a user