// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Interactable.h" #include "PickupItem.generated.h" class UItemDataAsset; class USphereComponent; class UStaticMeshComponent; /** * Un objet pose dans le monde. Il ne DECRIT pas l'objet, il ne fait que * pointer vers son UItemDataAsset et porter une quantite. * * Consequence pratique : pour creer un nouveau type de ramassable, tu n'as * plus besoin d'un Blueprint par objet. Un seul BP_Pickup suffit, tu changes * juste l'ItemData sur chaque instance posee dans le niveau. */ UCLASS() class SURVIVAL_PROJET_API APickupItem : public AActor, public IInteractable { GENERATED_BODY() public: APickupItem(); virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; /** * Configure un pickup engendre a l'execution (objet jete au sol). * A appeler entre SpawnActorDeferred() et FinishSpawning() pour que * OnConstruction ait deja les bonnes donnees et pose le bon mesh. * * A n'appeler que sur le SERVEUR : c'est lui qui engendre les acteurs du * monde, les clients recoivent l'acteur deja configure par replication. */ UFUNCTION(BlueprintCallable, Category = "Item") void InitPickup(UItemDataAsset* InItemData, int32 InQuantity, int32 InRemainingUses = -1); // --- IInteractable --- virtual FText GetInteractionPrompt_Implementation(AActor* Interactor) const override; virtual bool CanInteract_Implementation(AActor* Interactor) const override; virtual void Interact_Implementation(AActor* Interactor) override; virtual void OnBeginFocus_Implementation() override; virtual void OnEndFocus_Implementation() override; protected: /** * Sans garde WITH_EDITOR : on veut aussi que le mesh se pose correctement * sur les pickups engendres a l'execution quand on jette un objet. */ virtual void OnConstruction(const FTransform& Transform) override; /** Visuel uniquement, sans collision. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item") TObjectPtr Mesh; /** * Volume que le trace d'interaction vient toucher. * Volontairement separe du mesh : beaucoup de meshes d'asset packs, * en particulier la vegetation, n'ont aucune geometrie de collision. * Avec une sphere dediee, le pickup fonctionne quel que soit le visuel. */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Item") TObjectPtr InteractionSphere; /** * Quel objet ce pickup represente. A assigner sur chaque instance. * * ReplicatedUsing et non simplement Replicated : chez un client, l'acteur * est construit AVANT que ses proprietes arrivent. OnConstruction s'execute * donc avec ItemData a nullptr et ne pose aucun mesh -- l'objet resterait * invisible pour tout le monde sauf l'hote. C'est OnRep qui repose le visuel * au moment ou la donnee arrive vraiment. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, ReplicatedUsing = OnRep_ItemData, Category = "Item") TObjectPtr ItemData; /** * Combien d'exemplaires ce tas contient. * Replique parce que le prompt l'affiche ("Ramasser Branche x3") et qu'un * ramassage partiel, inventaire plein, le fait diminuer sous les yeux de tous. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Item") int32 Quantity = 1; /** * Charges restantes pour un objet a usages multiples. * -1 = plein, ce qui est le cas de tout objet pose a la main dans le niveau. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Item") int32 RemainingUses = -1; /** Repose le mesh quand la donnee de l'objet arrive chez un client. */ UFUNCTION() void OnRep_ItemData(); /** * Applique le visuel decrit par l'ItemData. Partage par OnConstruction et * OnRep_ItemData : deux copies finiraient par diverger, et le symptome * serait un objet correct dans l'editeur mais nu en jeu. */ void ApplyItemVisuals(); /** * Reprend automatiquement le WorldMesh de l'ItemData dans l'editeur. * Decoche pour imposer un mesh different sur une instance precise. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item") bool bUseMeshFromItemData = true; /** Active le Custom Depth quand l'objet est vise. */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item") bool bHighlightOnFocus = true; };