Import initial du projet Survival (UE 5.8)
Boucle de jeu complète : récolte, inventaire, consommation, stats de survie, mort et respawn. Gameplay en C++, Blueprints réservés au câblage d'assets. Assets binaires (.uasset, .umap, textures, audio) suivis via Git LFS. Binaries/, Intermediate/, Saved/ et DerivedDataCache/ sont ignorés : régénérés au build, ils pèsent 3 Go pour 1,3 Go de contenu utile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "PickupItem.h"
|
||||
|
||||
#include "Components/SphereComponent.h"
|
||||
#include "Components/StaticMeshComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "ItemDataAsset.h"
|
||||
|
||||
#define LOCTEXT_NAMESPACE "PickupItem"
|
||||
|
||||
APickupItem::APickupItem()
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = false;
|
||||
|
||||
Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
|
||||
SetRootComponent(Mesh);
|
||||
// Purement decoratif : c'est la sphere qui porte la collision.
|
||||
Mesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
|
||||
// Le trace d'interaction passe par le canal Visibility. On ne bloque QUE
|
||||
// ce canal : le pickup reste traversable par le joueur et les projectiles.
|
||||
InteractionSphere = CreateDefaultSubobject<USphereComponent>(TEXT("InteractionSphere"));
|
||||
InteractionSphere->SetupAttachment(Mesh);
|
||||
InteractionSphere->InitSphereRadius(50.f);
|
||||
InteractionSphere->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
|
||||
InteractionSphere->SetCollisionResponseToAllChannels(ECR_Ignore);
|
||||
InteractionSphere->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
}
|
||||
|
||||
void APickupItem::InitPickup(UItemDataAsset* InItemData, int32 InQuantity, int32 InRemainingUses)
|
||||
{
|
||||
ItemData = InItemData;
|
||||
Quantity = FMath::Max(1, InQuantity);
|
||||
RemainingUses = InRemainingUses;
|
||||
}
|
||||
|
||||
void APickupItem::OnConstruction(const FTransform& Transform)
|
||||
{
|
||||
Super::OnConstruction(Transform);
|
||||
|
||||
// Confort d'edition : le mesh suit l'objet choisi, tu vois immediatement
|
||||
// dans le viewport ce que tu es en train de poser. Vaut aussi a l'execution
|
||||
// pour les objets jetes, puisque OnConstruction s'execute a FinishSpawning.
|
||||
if (bUseMeshFromItemData && ItemData && ItemData->WorldMesh)
|
||||
{
|
||||
Mesh->SetStaticMesh(ItemData->WorldMesh);
|
||||
}
|
||||
}
|
||||
|
||||
FText APickupItem::GetInteractionPrompt_Implementation() const
|
||||
{
|
||||
if (!ItemData)
|
||||
{
|
||||
return LOCTEXT("PickupUnconfigured", "Objet non configure");
|
||||
}
|
||||
|
||||
if (Quantity > 1)
|
||||
{
|
||||
return FText::Format(LOCTEXT("PickupPromptStack", "Ramasser {0} x{1}"),
|
||||
ItemData->DisplayName, FText::AsNumber(Quantity));
|
||||
}
|
||||
|
||||
return FText::Format(LOCTEXT("PickupPrompt", "Ramasser {0}"), ItemData->DisplayName);
|
||||
}
|
||||
|
||||
bool APickupItem::CanInteract_Implementation(AActor* Interactor) const
|
||||
{
|
||||
// Un pickup sans donnee est une erreur de configuration : on le rend
|
||||
// inerte plutot que de laisser le joueur ramasser du vide.
|
||||
return ItemData != nullptr;
|
||||
}
|
||||
|
||||
void APickupItem::Interact_Implementation(AActor* Interactor)
|
||||
{
|
||||
UInventoryComponent* Inventory = Interactor ? Interactor->FindComponentByClass<UInventoryComponent>() : nullptr;
|
||||
if (!Inventory)
|
||||
{
|
||||
UE_LOG(LogTemp, Warning, TEXT("APickupItem : %s n'a pas d'UInventoryComponent."), *GetNameSafe(Interactor));
|
||||
return;
|
||||
}
|
||||
|
||||
const int32 Leftover = Inventory->AddItem(ItemData, Quantity, RemainingUses);
|
||||
const int32 Added = Quantity - Leftover;
|
||||
|
||||
// Inventaire plein : on ne detruit surtout pas le tas, on retire seulement
|
||||
// ce qui est rentre. Le joueur peut revenir chercher le reste.
|
||||
if (Added <= 0)
|
||||
{
|
||||
if (GEngine)
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Red, TEXT("Inventaire plein"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Retour temporaire, le temps que l'UI d'inventaire existe.
|
||||
if (GEngine)
|
||||
{
|
||||
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Green,
|
||||
FString::Printf(TEXT("+%d %s (total : %d, slots : %d/%d)"),
|
||||
Added,
|
||||
*ItemData->DisplayName.ToString(),
|
||||
Inventory->GetItemCount(ItemData),
|
||||
Inventory->GetUsedSlotCount(),
|
||||
Inventory->GetTotalSlotCount()));
|
||||
}
|
||||
|
||||
if (Leftover > 0)
|
||||
{
|
||||
Quantity = Leftover;
|
||||
return;
|
||||
}
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void APickupItem::OnBeginFocus_Implementation()
|
||||
{
|
||||
if (bHighlightOnFocus)
|
||||
{
|
||||
Mesh->SetRenderCustomDepth(true);
|
||||
}
|
||||
}
|
||||
|
||||
void APickupItem::OnEndFocus_Implementation()
|
||||
{
|
||||
if (bHighlightOnFocus)
|
||||
{
|
||||
Mesh->SetRenderCustomDepth(false);
|
||||
}
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
Reference in New Issue
Block a user