diff --git a/Content/GameData/Items/Seeds/I_Lavender_Seed.uasset b/Content/GameData/Items/Seeds/I_Lavender_Seed.uasset new file mode 100644 index 00000000..1508d172 --- /dev/null +++ b/Content/GameData/Items/Seeds/I_Lavender_Seed.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7705da197aa7a68fb4d2823da721300e463b438374cffad24f6b8a331254289e +size 7259 diff --git a/Content/Scripts/InventorySystem/UI/InventoryScreenWrapper.uasset b/Content/Scripts/InventorySystem/UI/InventoryScreenWrapper.uasset index eb670bdd..9fa98f93 100644 --- a/Content/Scripts/InventorySystem/UI/InventoryScreenWrapper.uasset +++ b/Content/Scripts/InventorySystem/UI/InventoryScreenWrapper.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:666c3e913038a3fb0e253478f6f261f3384a48562d67515a42a6f30a284a5026 -size 1320948 +oid sha256:7c9f44bd50c5d07fffb018fb5149c565ccdfa96c6842d7275c5b80d33d2d0102 +size 1299366 diff --git a/Content/ThirdPersonBP/Blueprints/BP_ThirdPersonCharacter.uasset b/Content/ThirdPersonBP/Blueprints/BP_ThirdPersonCharacter.uasset index bda62878..ce0ae83d 100644 --- a/Content/ThirdPersonBP/Blueprints/BP_ThirdPersonCharacter.uasset +++ b/Content/ThirdPersonBP/Blueprints/BP_ThirdPersonCharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82ea51056008589c45388f7031ec00f1aff22efc41d026cd8f0437143b65e679 -size 1138869 +oid sha256:12525ff3177a0eb7e2907ba41ba900ab4dd2aa2e4674034dc12c5ef94f8b5d6f +size 1123718 diff --git a/Content/VFX/NI_CropReady.uasset b/Content/VFX/NI_CropReady.uasset index a180b3ba..058a255b 100644 --- a/Content/VFX/NI_CropReady.uasset +++ b/Content/VFX/NI_CropReady.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e13c6ecc22be5eaf271784ebb41b38cb2eb69ab3d683be1be8dedc554dcaff74 -size 361282 +oid sha256:a1ee42129700d4288faa7d51bd2393253b1d22a8f3e5d29d1dee38c9ad5b39a8 +size 362700 diff --git a/Source/ProjectEleri/Items/DataAssets/ItemDataAsset.h b/Source/ProjectEleri/Items/DataAssets/ItemDataAsset.h index ebbf052e..c68e29c8 100644 --- a/Source/ProjectEleri/Items/DataAssets/ItemDataAsset.h +++ b/Source/ProjectEleri/Items/DataAssets/ItemDataAsset.h @@ -141,28 +141,28 @@ public: /*--------------------------------------------------------------------------------------------------------------------------*/ /** What base will the seed spawn when planting initiates */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides)) + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Seed", EditConditionHides)) BaseType TypeOfBase; /** Does this ingredient have a seed? Ignored in potions */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides)) + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Seed", EditConditionHides)) bool IsSeed = true; /** What is the base cost of the seed for this ingredient, ignored in potions */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Inventory, Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides)) + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Inventory, Book", EditCondition="ItemCategory==Category::Seed", EditConditionHides)) int32 SeedCost; /** Grow time for a seed in game days, if the seed is a tree or wine this is the growth for them */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, DisplayName = "Grow Time", Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Inventory, Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides)) + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, DisplayName = "Grow Time", Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Inventory, Book", EditCondition="ItemCategory==Category::Seed", EditConditionHides)) int32 GrowTimeSelf; /** Stages of a plant, set a mesh for certain days */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides)) + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Seed", EditConditionHides)) TArray SeedStages; /** What is the preferred temperature in alchemy that the ingredient releases it's properties in the most effective way*/ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides)) + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Seed", EditConditionHides)) int32 PreferredTemperature; /*-------------------------------------------------------------------------------------------------------------------------*/ diff --git a/Source/ProjectEleri/Items/ItemContainer.h b/Source/ProjectEleri/Items/ItemContainer.h index 0a3343ae..f1117036 100644 --- a/Source/ProjectEleri/Items/ItemContainer.h +++ b/Source/ProjectEleri/Items/ItemContainer.h @@ -6,6 +6,7 @@ #include "Engine/DataAsset.h" #include "PaperSprite.h" #include "Engine/DataTable.h" +#include "Engine/StaticMesh.h" #include "ItemContainer.generated.h" @@ -106,6 +107,12 @@ struct FSeedStage { UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) TSoftObjectPtr Sprite; + /** Mesh this stage is shown with. A stage that has one is placed as a mesh actor on the seed bed and never shows + the sprite of the stage, a stage without one keeps showing its sprite. The mesh stands on the slot, the offset + of the stage moves it and SpriteScale sizes it. */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) + TSoftObjectPtr StageMesh; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly) float SpriteScale = 1.f; diff --git a/Source/ProjectEleri/Items/ItemDatabase.cpp b/Source/ProjectEleri/Items/ItemDatabase.cpp index 1fa28073..b6f2dc3b 100644 --- a/Source/ProjectEleri/Items/ItemDatabase.cpp +++ b/Source/ProjectEleri/Items/ItemDatabase.cpp @@ -12,6 +12,11 @@ #include "ProjectEleri/Settings/EleriGameSettings.h" #include "ProjectEleri/System/MainBlueprintFunctionLibrary.h" +UItemDatabase* UItemDatabase::Get(const UObject* WorldContext) +{ + return UGameplayStatics::GetGameInstance(WorldContext)->GetSubsystem(); +} + UWorld* UItemDatabase::GetWorld() const { if (const UGameInstance* GameInstance = GetGameInstance()) { return GameInstance->GetWorld(); diff --git a/Source/ProjectEleri/Items/ItemDatabase.h b/Source/ProjectEleri/Items/ItemDatabase.h index 3e2ff4f6..0020bbb2 100644 --- a/Source/ProjectEleri/Items/ItemDatabase.h +++ b/Source/ProjectEleri/Items/ItemDatabase.h @@ -41,6 +41,8 @@ class PROJECTELERI_API UItemDatabase : public UGameInstanceSubsystem GENERATED_BODY() public: + + static UItemDatabase* Get(const UObject* WorldContext); UPROPERTY(EditDefaultsOnly) UItemContainer* ItemDatabase; diff --git a/Source/ProjectEleri/Items/SeedBedActor.cpp b/Source/ProjectEleri/Items/SeedBedActor.cpp index 69fbbd2f..58996643 100644 --- a/Source/ProjectEleri/Items/SeedBedActor.cpp +++ b/Source/ProjectEleri/Items/SeedBedActor.cpp @@ -10,6 +10,7 @@ #include "Components/StaticMeshComponent.h" #include "DataAssets/ItemDataAsset.h" #include "Engine/StaticMesh.h" +#include "Engine/StaticMeshActor.h" #include "Engine/World.h" #include "ItemContainer.h" #include "NiagaraComponent.h" @@ -24,14 +25,18 @@ namespace { - /** Destroys the components of a slot and clears the pointers so nothing stale is left in the map */ + /** Destroys the components and the plant mesh actor of a slot and clears the pointers so nothing stale is left */ void DestroySlotComponents(FSeedBedSeedSlot& Slot) { if (Slot.SeedBedDecal) Slot.SeedBedDecal->DestroyComponent(); if (Slot.PlantSprite) Slot.PlantSprite->DestroyComponent(); + + // The plant mesh is an actor of its own, it does not go away with the components of the slot + if (IsValid(Slot.PlantMeshActor)) Slot.PlantMeshActor->Destroy(); Slot.SeedBedDecal = nullptr; Slot.PlantSprite = nullptr; + Slot.PlantMeshActor = nullptr; } /** Slots are created at runtime as well, so the components are created with stable, deterministic names */ @@ -218,6 +223,17 @@ void ASeedBedActor::EndPlay(const EEndPlayReason::Type EndPlayReason) GameState->CacheSeedData(SeedBedIndex, PrepareSeedSaveData()); } + // The plant meshes are actors of their own, they are taken down together with the bed. This runs for destroyed, + // for streamed out and for shut down beds alike, so no plant mesh is ever left behind in the world + for (TPair& SlotPair : SeedBedSeedSlotsMap) + { + if (IsValid(SlotPair.Value.PlantMeshActor)) + { + SlotPair.Value.PlantMeshActor->Destroy(); + SlotPair.Value.PlantMeshActor = nullptr; + } + } + Super::EndPlay(EndPlayReason); } @@ -670,6 +686,9 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo // A plant that died or was harvested keeps its mesh, the slot is only emptied when it is cleared for real Slot.PlantSprite->SetVisibility(false); Slot.PlantSprite->DecalComponent->SetVisibility(false); + + // A slot without a living plant has no stage at all, so the mesh actor of the slot is hidden as well + ApplySlotPlantMesh(SlotCoordinate, Slot, nullptr); return; } @@ -681,29 +700,42 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo { Slot.PlantSprite->SetVisibility(false); Slot.PlantSprite->DecalComponent->SetVisibility(false); + + ApplySlotPlantMesh(SlotCoordinate, Slot, nullptr); return; } const UItemDataAsset* SeedData = Slot.SlotData.ItemDataAsset; + const FSeedStage* Stage = nullptr; if (IsValid(SeedData) && SeedData->SeedStages.IsValidIndex(StageIndex)) { - PlantScale *= FVector(SeedData->SeedStages[StageIndex].SpriteScale); - PlantOffset += SeedData->SeedStages[StageIndex].Offset; + Stage = &SeedData->SeedStages[StageIndex]; } + if (Stage) + { + PlantScale *= FVector(Stage->SpriteScale); + PlantOffset += Stage->Offset; + } + + // A stage that carries a mesh is placed as a mesh actor of its own, its sprite stays the fallback of mesh stages + // whose mesh is still streaming in, so a stage with a mesh never flashes the sprite of another stage + const bool bStageHasMesh = Stage != nullptr && !Stage->StageMesh.IsNull(); + ApplySlotPlantMesh(SlotCoordinate, Slot, Stage); + Slot.PlantSprite->SetRelativeScale3D(PlantScale); Slot.PlantSprite->SetRelativeLocation(PlantOffset); Slot.PlantSprite->UpdateRelativeLocation(FVector(PlantOffset.X, PlantOffset.Y, 0.f)); - if (SeedData->SeedStages[StageIndex].Sprite.IsValid()) + if (Stage->Sprite.IsValid()) { - Slot.PlantSprite->SetSprite(SeedData->SeedStages[StageIndex].Sprite.Get()); - Slot.PlantSprite->SetVisibility(true); - Slot.PlantSprite->DecalComponent->SetVisibility(true); + Slot.PlantSprite->SetSprite(Stage->Sprite.Get()); + Slot.PlantSprite->SetVisibility(!bStageHasMesh); + Slot.PlantSprite->DecalComponent->SetVisibility(!bStageHasMesh); } else { - SeedData->SeedStages[StageIndex].Sprite.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* SpriteObj) + Stage->Sprite.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* SpriteObj) { FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate); if (!Slot || !IsValid(Slot->PlantSprite)) return; @@ -715,6 +747,23 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo })); } + // The mesh of a stage that carries one is streamed in like the sprite and re-resolves the visuals of the slot, + // so it is placed, scaled and shown the moment it is there. A stage without a mesh keeps the sprite alone + if (Stage && !Stage->StageMesh.IsValid()) + { + Stage->StageMesh.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* MeshObj) + { + FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate); + if (!Slot) return; + + UStaticMesh* StageMesh = Cast(MeshObj); + if (!IsValid(StageMesh)) return; + + // The slot may have moved on to another stage while the mesh streamed in, so the visuals are re-resolved + ApplySlotVisuals(SlotCoordinate, *Slot); + })); + } + if (Slot.SlotData.bBloomed && !Slot.NiagaraComponent->IsActive()) { Slot.NiagaraComponent->SetAsset(nullptr); @@ -743,6 +792,69 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo } } } +void ASeedBedActor::ApplySlotPlantMesh(FIntVector2 SlotCoordinate, FSeedBedSeedSlot& Slot, const FSeedStage* Stage) +{ + UStaticMesh* StageMesh = Stage ? Stage->StageMesh.Get() : nullptr; + + // A slot without a stage, or with a stage whose mesh has not streamed in yet, shows nothing but its sprite + if (!IsValid(StageMesh)) + { + if (IsValid(Slot.PlantMeshActor)) + { + Slot.PlantMeshActor->SetActorHiddenInGame(true); + } + + return; + } + + UWorld* World = GetWorld(); + if (!World) + { + return; + } + + const FRotator PlantRotation = GetActorRotation(); + const FVector PlantLocation = GetActorTransform().TransformPosition(GetSlotRelativeLocation(SlotCoordinate) + Stage->Offset); + + if (!IsValid(Slot.PlantMeshActor)) + { + FActorSpawnParameters SpawnParams; + SpawnParams.Owner = this; + SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn; + + // The mesh is spawned once for the slot and stays with it, every later stage only swaps the mesh it shows + Slot.PlantMeshActor = World->SpawnActor(AStaticMeshActor::StaticClass(), FTransform(PlantRotation, PlantLocation), SpawnParams); + if (!IsValid(Slot.PlantMeshActor)) + { + return; + } + + // A plant appears and disappears while the game runs, so the actor can never keep the static mobility it spawns with + Slot.PlantMeshActor->SetMobility(EComponentMobility::Movable); + Slot.PlantMeshActor->AttachToActor(this, FAttachmentTransformRules::KeepWorldTransform); + + if (UStaticMeshComponent* MeshComponent = Slot.PlantMeshActor->GetStaticMeshComponent()) + { + // The plant is decoration only, it blocks nothing, moves no navigation and catches none of the bed decals + MeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision); + MeshComponent->SetCanEverAffectNavigation(false); + MeshComponent->SetReceivesDecals(false); + } + } + + UStaticMeshComponent* MeshComponent = Slot.PlantMeshActor->GetStaticMeshComponent(); + if (!MeshComponent) + { + return; + } + + MeshComponent->SetStaticMesh(StageMesh); + + // The mesh stands on the slot itself, the offset of the stage moves it and the sprite scale of the stage sizes it + Slot.PlantMeshActor->SetActorLocationAndRotation(PlantLocation, PlantRotation); + Slot.PlantMeshActor->SetActorScale3D(FVector(Stage->SpriteScale)); + Slot.PlantMeshActor->SetActorHiddenInGame(false); +} void ASeedBedActor::RefreshSlotVisual(const FIntVector2& SlotCoordinate) { FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate); diff --git a/Source/ProjectEleri/Items/SeedBedActor.h b/Source/ProjectEleri/Items/SeedBedActor.h index afed8830..4325b83c 100644 --- a/Source/ProjectEleri/Items/SeedBedActor.h +++ b/Source/ProjectEleri/Items/SeedBedActor.h @@ -17,7 +17,9 @@ class UMaterialInstanceDynamic; class UMaterialInterface; class UStaticMesh; class UStaticMeshComponent; +class AStaticMeshActor; class UItemDataAsset; +struct FSeedStage; /** In game time units the seed bed works with, the seed data itself stays authored in days */ constexpr int32 SeedBedHoursPerDay = 24; @@ -85,6 +87,11 @@ struct FSeedBedSeedSlot UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UEleriPaperSpriteComponent* PlantSprite = nullptr; + + /** Mesh actor of a slot that reached a stage which brings a mesh, it is created once for such a stage and only + hidden or re-used after that, a stage without a mesh leaves the slot to its sprite */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly) + AStaticMeshActor* PlantMeshActor = nullptr; UPROPERTY(VisibleAnywhere, BlueprintReadOnly) UNiagaraComponent* NiagaraComponent = nullptr; @@ -284,6 +291,10 @@ protected: /** Re-applies material, plant mesh and highlight decal of a slot */ void ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlot& Slot); + /** Places, moves or hides the mesh actor of a slot, a null stage or a stage whose mesh has not streamed in yet + hides it. The actor is created once for the first stage that brings a mesh and re-used by every later stage */ + void ApplySlotPlantMesh(FIntVector2 SlotCoordinate, FSeedBedSeedSlot& Slot, const FSeedStage* Stage); + /** Resolves which growth stage mesh of the planted seed has to be shown */ int32 ResolveGrowthStageIndex(const FSeedBedSeedSlot& Slot) const; diff --git a/Source/ProjectEleri/Private/EleriPlayerController.cpp b/Source/ProjectEleri/Private/EleriPlayerController.cpp index 55ee196f..f374cd09 100644 --- a/Source/ProjectEleri/Private/EleriPlayerController.cpp +++ b/Source/ProjectEleri/Private/EleriPlayerController.cpp @@ -1184,14 +1184,13 @@ void AEleriPlayerController::OnHarvestSeed(const FInputActionValue &Value) // PLANTING -void AEleriPlayerController::SetSeedToPlant(UItemDataAsset *SeedData, bool bHighQuality) +void AEleriPlayerController::SetSeedToPlant(const FItemStack& Stack) { // Anything that is not a seed that fits into a seed bed is rejected, the UI cannot leave us in a bad state - SeedToPlant = ASeedBedActor::IsPlantableSeedData(SeedData) ? SeedData : nullptr; - bSeedToPlantHighQuality = IsValid(SeedToPlant) && bHighQuality; + SeedToPlant = Stack; // Selecting a seed is what starts the planting, the beds in range light up for it right away - if (IsValid(SeedToPlant)) + if (SeedToPlant.ItemId.IsValid()) { SetPlantingMode(true); } @@ -1199,12 +1198,7 @@ void AEleriPlayerController::SetSeedToPlant(UItemDataAsset *SeedData, bool bHigh void AEleriPlayerController::ClearSeedToPlant() { - if (!IsValid(SeedToPlant) && !bSeedToPlantHighQuality) - return; - - SeedToPlant = nullptr; - bSeedToPlantHighQuality = false; - + SeedToPlant = FItemStack(); // Nothing is being planted anymore, so the beds stop being highlighted if (IsPlantingModeActive()) { @@ -1231,7 +1225,8 @@ void AEleriPlayerController::TryPlantSelectedSeed() return; // A seed that is not plantable anymore, for example when the inventory was emptied, drops out of planting - if (!ASeedBedActor::IsPlantableSeedData(SeedToPlant)) + UItemDataAsset* Item = UItemDatabase::Get(this)->GetDataAssetFromId(SeedToPlant.ItemId); + if (!ASeedBedActor::IsPlantableSeedData(Item)) { ClearSeedToPlant(); return; @@ -1240,9 +1235,7 @@ void AEleriPlayerController::TryPlantSelectedSeed() ASeedBedActor *SeedBed = PlayerCharacter->GetClosestSeedBedActor(); if (!IsValid(SeedBed)) return; - - const FVector PlayerLocation = PlayerCharacter->GetActorLocation(); - + FIntVector2 SlotCoordinate = SeedBed->GetHighlightedSlotIndex(); if (SlotCoordinate == FIntVector2::NoneValue) return; @@ -1252,16 +1245,15 @@ void AEleriPlayerController::TryPlantSelectedSeed() return; // The seed is paid for before it is planted, so a slot can never hold a seed the inventory never had - const FPrimaryAssetId SeedAssetId = SeedToPlant->GetPrimaryAssetId(); - if (Inventory->HasItem(SeedAssetId, true) <= 0) + if (Inventory->HasItem(SeedToPlant.ItemId, SeedToPlant.HQ) <= 0) return; - if (!SeedBed->PlantSeedInSlot(SlotCoordinate, SeedToPlant, bSeedToPlantHighQuality)) + if (!SeedBed->PlantSeedInSlot(SlotCoordinate, Item, SeedToPlant.HQ)) return; - Inventory->RemoveItemFromInventory(SeedAssetId, 1, true); + Inventory->RemoveItemFromInventory(SeedToPlant.ItemId, 1, SeedToPlant.HQ); - if (Inventory->HasItem(SeedAssetId, true) == INDEX_NONE) + if (Inventory->HasItem(SeedToPlant.ItemId, SeedToPlant.HQ) == INDEX_NONE) { ClearSeedToPlant(); } diff --git a/Source/ProjectEleri/Private/MyCharacter.cpp b/Source/ProjectEleri/Private/MyCharacter.cpp index 4d487229..75de327d 100644 --- a/Source/ProjectEleri/Private/MyCharacter.cpp +++ b/Source/ProjectEleri/Private/MyCharacter.cpp @@ -129,7 +129,7 @@ void AMyCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); - if (bIsPlanting) + if (GetIsPlanting()) { // The reach is measured from the closest free slot and not from the center of the bed: a bed is as big as // its grid, so its outer slots sit up to 1273 units away from that center and would never be in reach @@ -354,9 +354,9 @@ void AMyCharacter::InitiateLoad() void AMyCharacter::SetPlanting(bool bActive) { - bIsPlanting = bActive; + CurrentlyDoing = bActive? ECurrentlyDoing::PLANTING : ECurrentlyDoing::NOTHING; - if (bIsPlanting) + if (GetIsPlanting()) { // Planting takes over the interact input, so keep the plugin's interaction UI out of the way. // The plugin knows nothing about planting - it just holds/releases a generic UI block. diff --git a/Source/ProjectEleri/Public/EleriPlayerController.h b/Source/ProjectEleri/Public/EleriPlayerController.h index 94d54247..3846a494 100644 --- a/Source/ProjectEleri/Public/EleriPlayerController.h +++ b/Source/ProjectEleri/Public/EleriPlayerController.h @@ -386,17 +386,14 @@ public: // PLANTING /** Seed the player selected in the inventory, it is what the planting action plants */ UFUNCTION(BlueprintCallable) - void SetSeedToPlant(UItemDataAsset* SeedData, bool bHighQuality = false); + void SetSeedToPlant(const FItemStack& Stack); /** Forgets the selected seed, the seed beds stop being highlighted for it */ UFUNCTION(BlueprintCallable) void ClearSeedToPlant(); UFUNCTION(BlueprintCallable, BlueprintPure) - UItemDataAsset* GetSeedToPlant() const { return SeedToPlant; } - - UFUNCTION(BlueprintCallable, BlueprintPure) - bool IsSeedToPlantHighQuality() const { return bSeedToPlantHighQuality; } + const FItemStack& GetSeedToPlant() const { return SeedToPlant; } /** Plants the selected seed into the closest free slot of the closest seed bed, removes it from the inventory */ UFUNCTION(BlueprintCallable) @@ -411,10 +408,7 @@ public: void SetPlantingMode(bool bActive); UPROPERTY(BlueprintReadOnly, Category = "Planting") - UItemDataAsset* SeedToPlant; - - UPROPERTY(BlueprintReadOnly, Category = "Planting") - bool bSeedToPlantHighQuality = false; + FItemStack SeedToPlant; void OnPlantSeedAction(const FInputActionValue& Value); diff --git a/Source/ProjectEleri/Public/MyCharacter.h b/Source/ProjectEleri/Public/MyCharacter.h index bef76418..d35231ed 100644 --- a/Source/ProjectEleri/Public/MyCharacter.h +++ b/Source/ProjectEleri/Public/MyCharacter.h @@ -55,8 +55,6 @@ protected: //PLANTING STUFF START UPROPERTY() - bool bIsPlanting = false; - UPROPERTY() TArray SeedBedActors; UPROPERTY() ASeedBedActor* LastClosestSeedBedActor = nullptr; @@ -243,7 +241,7 @@ public: ASeedBedActor* GetClosestSeedBedActor() { return LastClosestSeedBedActor; } UFUNCTION(BlueprintCallable, BlueprintPure) - inline bool GetIsPlanting() { return bIsPlanting; } + inline bool GetIsPlanting() const { return CurrentlyDoing == ECurrentlyDoing::PLANTING; } void BeginWatering(); void EndWatering() const;