Fixes for seeds, add shadow to custom flipbook component
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/Materials/Sprite/MI_SpriteShadow_Inst.uasset
LFS
Normal file
BIN
Content/Materials/Sprite/MI_SpriteShadow_Inst.uasset
LFS
Normal file
Binary file not shown.
BIN
Content/Materials/Sprite/M_SpriteShadow.uasset
LFS
Normal file
BIN
Content/Materials/Sprite/M_SpriteShadow.uasset
LFS
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Content/UI/MainUI.uasset
LFS
BIN
Content/UI/MainUI.uasset
LFS
Binary file not shown.
23
Source/ProjectEleri/Components/EleriFlipbookComponent.cpp
Normal file
23
Source/ProjectEleri/Components/EleriFlipbookComponent.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "EleriFlipbookComponent.h"
|
||||||
|
|
||||||
|
#include "Components/DecalComponent.h"
|
||||||
|
|
||||||
|
void UEleriFlipbookComponent::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
DecalComponent = NewObject<UDecalComponent>(GetOwner(), UDecalComponent::StaticClass(), TEXT("Shadow Decal"));
|
||||||
|
DecalComponent->SetDecalMaterial(DecalMaterial);
|
||||||
|
DecalComponent->DecalSize = DecalSize;
|
||||||
|
DecalComponent->SetFadeScreenSize(0.f);
|
||||||
|
DecalComponent->SetupAttachment(GetOwner()->GetRootComponent());
|
||||||
|
DecalComponent->RegisterComponent();
|
||||||
|
DecalComponent->SetRelativeLocation(DecalOffset - FVector(0.f, 0.f, DecalSize.Z));
|
||||||
|
DecalComponent->SetUsingAbsoluteRotation(true);
|
||||||
|
DecalComponent->SetRelativeRotation(FRotator(-90.f, 0.f, 0.f));
|
||||||
|
|
||||||
|
SetCastShadow(false);
|
||||||
|
}
|
||||||
32
Source/ProjectEleri/Components/EleriFlipbookComponent.h
Normal file
32
Source/ProjectEleri/Components/EleriFlipbookComponent.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "PaperFlipbookComponent.h"
|
||||||
|
#include "EleriFlipbookComponent.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
|
||||||
|
class PROJECTELERI_API UEleriFlipbookComponent : public UPaperFlipbookComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
|
UMaterialInterface* DecalMaterial = nullptr;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
|
FVector DecalSize = FVector::OneVector;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
|
FVector DecalOffset = FVector::ZeroVector;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly)
|
||||||
|
UDecalComponent* DecalComponent = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -140,10 +140,6 @@ public:
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/** What part of the world grants faster growth and higher chance to harvest an HQ ingredient */
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book",EditCondition="ItemCategory==Category::Plant", EditConditionHides))
|
|
||||||
TArray<Geography> ItemGeography;
|
|
||||||
|
|
||||||
/** What base will the seed spawn when planting initiates */
|
/** 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::Plant", EditConditionHides))
|
||||||
BaseType TypeOfBase;
|
BaseType TypeOfBase;
|
||||||
@@ -157,32 +153,17 @@ public:
|
|||||||
int32 SeedCost;
|
int32 SeedCost;
|
||||||
|
|
||||||
/** Grow time for a seed in game days, if the seed is a tree or wine this is the growth for them */
|
/** 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, 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::Plant", EditConditionHides))
|
||||||
int32 GrowTimeSelf;
|
int32 GrowTimeSelf;
|
||||||
|
|
||||||
/** Only used on seeds that have wines or trees, after GrowTimeSelf has been reached
|
|
||||||
this is the amount of days that it takes for the plant to grow it's produce*/
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Inventory, Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides))
|
|
||||||
int32 GrowTimeProduct;
|
|
||||||
|
|
||||||
/** Stages of a plant, set a mesh for certain days */
|
/** 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::Plant", EditConditionHides))
|
||||||
TArray<FSeedStage> SeedStages;
|
TArray<FSeedStage> SeedStages;
|
||||||
|
|
||||||
/** In case of wine or tree this mesh will be used to display the produce that has beed grown
|
/** What is the preferred temperature in alchemy that the ingredient releases it's
|
||||||
every GrowTimeProduct days*/
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides))
|
|
||||||
TSoftObjectPtr<UStaticMesh> ProduceGrownMesh;
|
|
||||||
|
|
||||||
/** In case of wine or tree this mesh will be used to display the produce that has beed grown
|
|
||||||
every GrowTimeProduct days*/
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed", AssetRegistrySearchable, meta = (AssetBundles = "Book", EditCondition="ItemCategory==Category::Plant", EditConditionHides))
|
|
||||||
TSoftObjectPtr<UPaperSprite> ProduceGrownSprite;
|
|
||||||
|
|
||||||
/** What is the prefered temperature in alchemy that the ingredient releases it's
|
|
||||||
properties in the most effective way*/
|
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::Plant", EditConditionHides))
|
||||||
int32 PreferedTemperature;
|
int32 PreferredTemperature;
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|||||||
@@ -101,35 +101,20 @@ struct FItemDatabaseRow : public FTableRowBase
|
|||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
struct FSeedStage {
|
struct FSeedStage {
|
||||||
GENERATED_USTRUCT_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
||||||
TSoftObjectPtr<UStaticMesh> Mesh;
|
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
TSoftObjectPtr<UPaperSprite> Sprite;
|
TSoftObjectPtr<UPaperSprite> Sprite;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
float SpriteScale;
|
float SpriteScale = 1.f;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
FVector MeshOffset;
|
FVector Offset = FVector::ZeroVector;
|
||||||
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
|
||||||
FVector MeshScale;
|
|
||||||
|
|
||||||
/** In game days after planting at which this stage is shown, the seed bed ages its plants per hour and scales it */
|
/** In game days after planting at which this stage is shown, the seed bed ages its plants per hour and scales it */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
int32 ChangeOnDay;
|
int32 ChangeOnDay = 0;
|
||||||
|
|
||||||
FSeedStage()
|
|
||||||
{
|
|
||||||
Mesh = nullptr;
|
|
||||||
MeshOffset = FVector::ZeroVector;
|
|
||||||
MeshScale = FVector::OneVector;
|
|
||||||
ChangeOnDay = 0;
|
|
||||||
SpriteScale = 1.f;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
@@ -159,10 +144,6 @@ struct FItemBase {
|
|||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Ingredient", meta = (MultiLine = true))
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Ingredient", meta = (MultiLine = true))
|
||||||
TArray<FName> ItemDescriptionLevels;
|
TArray<FName> ItemDescriptionLevels;
|
||||||
|
|
||||||
/** What part of the world grants faster growth and higher chance to harvest an HQ ingredient */
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
|
||||||
Geography ItemGeography;
|
|
||||||
|
|
||||||
/** Category the item belongs to */
|
/** Category the item belongs to */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Info")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Info")
|
||||||
Category ItemCategory;
|
Category ItemCategory;
|
||||||
@@ -184,10 +165,6 @@ struct FItemBase {
|
|||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Ingredient")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Ingredient")
|
||||||
TArray<ItemProperty> Defects;
|
TArray<ItemProperty> Defects;
|
||||||
|
|
||||||
/** What base will the seed spawn when planting initiates */
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
|
||||||
BaseType TypeOfBase;
|
|
||||||
|
|
||||||
/** Icon of the item */
|
/** Icon of the item */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Info")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Info")
|
||||||
UTexture2D* ItemImage;
|
UTexture2D* ItemImage;
|
||||||
@@ -223,6 +200,10 @@ struct FItemBase {
|
|||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Potion")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Potion")
|
||||||
TArray<FName> RecipeItemsID;
|
TArray<FName> RecipeItemsID;
|
||||||
|
|
||||||
|
/** What part of the world grants faster growth and higher chance to harvest an HQ ingredient */
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
||||||
|
Geography ItemGeography;
|
||||||
|
|
||||||
/** Does this ingredient have a seed? Ignored in potions */
|
/** Does this ingredient have a seed? Ignored in potions */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
||||||
bool IsSeed;
|
bool IsSeed;
|
||||||
@@ -233,27 +214,12 @@ struct FItemBase {
|
|||||||
|
|
||||||
/** Grow time for a seed, if the seed is a tree or wine this is the growth for them */
|
/** Grow time for a seed, if the seed is a tree or wine this is the growth for them */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
||||||
int32 GrowTimeSelf;
|
int32 GrowTime;
|
||||||
|
|
||||||
/** Only used on seeds that have wines or trees, after GrowTimeSelf has been reached
|
|
||||||
this is the amount of days that it takes for the plant to grow it's produce*/
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
|
||||||
int32 GrowTimeProduct;
|
|
||||||
|
|
||||||
/** Stages of a plant, set a mesh for certain days */
|
/** Stages of a plant, set a mesh for certain days */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
||||||
TArray<FSeedStage> SeedStages;
|
TArray<FSeedStage> SeedStages;
|
||||||
|
|
||||||
/** In case of wine or tree this mesh will be used to display the produce that has beed grown
|
|
||||||
every GrowTimeProduct days*/
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
|
||||||
UStaticMesh* ProduceGrownMesh;
|
|
||||||
|
|
||||||
/** In case of wine or tree this mesh will be used to display the produce that has beed grown
|
|
||||||
every GrowTimeProduct days*/
|
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed")
|
|
||||||
UPaperSprite* ProduceGrownSprite;
|
|
||||||
|
|
||||||
/** What is the prefered temperature in alchemy that the ingredient releases it's
|
/** What is the prefered temperature in alchemy that the ingredient releases it's
|
||||||
properties in the most effective way*/
|
properties in the most effective way*/
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Ingredient")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Ingredient")
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ void UPlantItem::SetupData(UItemDataAsset* BaseItem, bool HighQualityItem)
|
|||||||
if (!IsValid(PlantAsset)) return;
|
if (!IsValid(PlantAsset)) return;
|
||||||
|
|
||||||
bHasSeed = PlantAsset->IsSeed;
|
bHasSeed = PlantAsset->IsSeed;
|
||||||
PreferedTemperature = PlantAsset->PreferedTemperature;
|
PreferedTemperature = PlantAsset->PreferredTemperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UPlantItem::SetupDataFromOtherItem(UItem* BaseItem)
|
void UPlantItem::SetupDataFromOtherItem(UItem* BaseItem)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Engine/StaticMesh.h"
|
#include "Engine/StaticMesh.h"
|
||||||
#include "Engine/World.h"
|
#include "Engine/World.h"
|
||||||
#include "ItemContainer.h"
|
#include "ItemContainer.h"
|
||||||
|
#include "PaperSpriteComponent.h"
|
||||||
#include "Kismet/GameplayStatics.h"
|
#include "Kismet/GameplayStatics.h"
|
||||||
#include "Kismet/KismetMaterialLibrary.h"
|
#include "Kismet/KismetMaterialLibrary.h"
|
||||||
#include "Materials/MaterialInstanceDynamic.h"
|
#include "Materials/MaterialInstanceDynamic.h"
|
||||||
@@ -23,32 +24,49 @@ namespace
|
|||||||
void DestroySlotComponents(FSeedBedSeedSlot& Slot)
|
void DestroySlotComponents(FSeedBedSeedSlot& Slot)
|
||||||
{
|
{
|
||||||
if (Slot.SeedBedDecal) Slot.SeedBedDecal->DestroyComponent();
|
if (Slot.SeedBedDecal) Slot.SeedBedDecal->DestroyComponent();
|
||||||
if (Slot.PlantStaticMesh) Slot.PlantStaticMesh->DestroyComponent();
|
if (Slot.PlantSprite) Slot.PlantSprite->DestroyComponent();
|
||||||
|
|
||||||
Slot.SeedBedDecal = nullptr;
|
Slot.SeedBedDecal = nullptr;
|
||||||
Slot.PlantStaticMesh = nullptr;
|
Slot.PlantSprite = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Slots are created at runtime as well, so the components are created with stable, deterministic names */
|
/** Slots are created at runtime as well, so the components are created with stable, deterministic names */
|
||||||
UStaticMeshComponent* CreateSlotMeshComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName)
|
UPaperSpriteComponent* CreatePaperSpriteComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName, TSoftObjectPtr<UMaterialInterface> Material)
|
||||||
{
|
{
|
||||||
if (!IsValid(Owner) || !IsValid(AttachParent))
|
if (!IsValid(Owner) || !IsValid(AttachParent))
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
UStaticMeshComponent* MeshComponent = NewObject<UStaticMeshComponent>(Owner, ComponentName);
|
UPaperSpriteComponent* SpriteComponent = NewObject<UPaperSpriteComponent>(Owner, ComponentName);
|
||||||
if (!MeshComponent)
|
if (!SpriteComponent)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshComponent->SetMobility(EComponentMobility::Movable);
|
SpriteComponent->SetMobility(EComponentMobility::Movable);
|
||||||
MeshComponent->SetupAttachment(AttachParent);
|
SpriteComponent->SetupAttachment(AttachParent);
|
||||||
MeshComponent->RegisterComponent();
|
SpriteComponent->RegisterComponent();
|
||||||
Owner->AddInstanceComponent(MeshComponent);
|
SpriteComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||||
|
SpriteComponent->SetVisibility(false);
|
||||||
|
TWeakObjectPtr<UPaperSpriteComponent> SpriteComp = SpriteComponent;
|
||||||
|
if (Material.IsValid())
|
||||||
|
{
|
||||||
|
SpriteComp->SetMaterial(0, Material.Get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Material.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(Owner, [Owner, SpriteComp](const FSoftObjectPath& Path, UObject* MaterialObj)
|
||||||
|
{
|
||||||
|
if (SpriteComp.IsValid())
|
||||||
|
{
|
||||||
|
SpriteComp->SetMaterial(0, Cast<UMaterialInterface>(MaterialObj));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
Owner->AddInstanceComponent(SpriteComponent);
|
||||||
|
|
||||||
return MeshComponent;
|
return SpriteComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
UDecalComponent* CreateSlotDecalComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName)
|
UDecalComponent* CreateSlotDecalComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName)
|
||||||
@@ -73,18 +91,6 @@ namespace
|
|||||||
return DecalComponent;
|
return DecalComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Soft references are filled in by hand, an unset mesh or material must never break the visuals */
|
|
||||||
template <typename TObjectType>
|
|
||||||
TObjectType* ResolveSoftObject(TSoftObjectPtr<TObjectType> SoftObject)
|
|
||||||
{
|
|
||||||
if (SoftObject.IsNull())
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SoftObject.Get() ? SoftObject.Get() : SoftObject.LoadSynchronous();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A slot counts as planted as soon as an asset or its id is stored, saves may only restore the id */
|
/** A slot counts as planted as soon as an asset or its id is stored, saves may only restore the id */
|
||||||
bool SlotHasPlant(const FSeedBedSeedSlot& Slot)
|
bool SlotHasPlant(const FSeedBedSeedSlot& Slot)
|
||||||
{
|
{
|
||||||
@@ -128,7 +134,21 @@ void ASeedBedActor::BeginPlay()
|
|||||||
HighlightDecal->SetVisibility(false);
|
HighlightDecal->SetVisibility(false);
|
||||||
HighlightDecal->SetRelativeRotation(HighlightDecalRotation);
|
HighlightDecal->SetRelativeRotation(HighlightDecalRotation);
|
||||||
AddInstanceComponent(HighlightDecal);
|
AddInstanceComponent(HighlightDecal);
|
||||||
HighlightDecal->SetDecalMaterial(ResolveSoftObject(HighlightDecalMaterial));
|
TWeakObjectPtr<UDecalComponent> WeakDecal = HighlightDecal;
|
||||||
|
if (HighlightDecalMaterial.IsValid())
|
||||||
|
{
|
||||||
|
HighlightDecal->SetDecalMaterial(HighlightDecalMaterial.Get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HighlightDecalMaterial.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [WeakDecal](const FSoftObjectPath& Path, UObject* MaterialObj)
|
||||||
|
{
|
||||||
|
if (WeakDecal.IsValid())
|
||||||
|
{
|
||||||
|
WeakDecal->SetDecalMaterial(Cast<UMaterialInterface>(MaterialObj));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearSeedBedGrid();
|
ClearSeedBedGrid();
|
||||||
@@ -550,8 +570,24 @@ FSeedBedSeedSlot& ASeedBedActor::CreateSlot(FIntVector2 SlotCoordinate, bool bRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
Slot.SeedBedDecal = CreateSlotDecalComponent(this, GetRootComponent(), GetSlotComponentName(SlotCoordinate, TEXT("Slot")));
|
Slot.SeedBedDecal = CreateSlotDecalComponent(this, GetRootComponent(), GetSlotComponentName(SlotCoordinate, TEXT("Slot")));
|
||||||
Slot.SeedBedDynamicMat = UKismetMaterialLibrary::CreateDynamicMaterialInstance(this, ResolveSoftObject(SeedBedDecalMaterial), NAME_None, EMIDCreationFlags::Transient);
|
if (SeedBedDecalMaterial.IsValid())
|
||||||
Slot.SeedBedDecal->SetDecalMaterial(Slot.SeedBedDynamicMat);
|
{
|
||||||
|
Slot.SeedBedDynamicMat = UKismetMaterialLibrary::CreateDynamicMaterialInstance(this, SeedBedDecalMaterial.Get(), NAME_None, EMIDCreationFlags::Transient);
|
||||||
|
Slot.SeedBedDecal->SetDecalMaterial(Slot.SeedBedDynamicMat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SeedBedDecalMaterial.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* MaterialObj)
|
||||||
|
{
|
||||||
|
FSeedBedSeedSlot& Slot = SeedBedSeedSlotsMap.FindOrAdd(SlotCoordinate);
|
||||||
|
if (Slot.SeedBedDecal)
|
||||||
|
{
|
||||||
|
Slot.SeedBedDynamicMat = UKismetMaterialLibrary::CreateDynamicMaterialInstance(this, SeedBedDecalMaterial.Get(), NAME_None, EMIDCreationFlags::Transient);
|
||||||
|
Slot.SeedBedDecal->SetDecalMaterial(Slot.SeedBedDynamicMat);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
Slot.SeedBedDecal->DecalSize = SeedBedDecalSize;
|
Slot.SeedBedDecal->DecalSize = SeedBedDecalSize;
|
||||||
Slot.SeedBedDecal->SetRelativeRotation(SeedBedDecalRotation);
|
Slot.SeedBedDecal->SetRelativeRotation(SeedBedDecalRotation);
|
||||||
const FVector2D Offset = FVector2D(GridSize.X * SeedBedDecalSize.Z, GridSize.Y * SeedBedDecalSize.Y) * -1.f;
|
const FVector2D Offset = FVector2D(GridSize.X * SeedBedDecalSize.Z, GridSize.Y * SeedBedDecalSize.Y) * -1.f;
|
||||||
@@ -564,14 +600,9 @@ FSeedBedSeedSlot& ASeedBedActor::CreateSlot(FIntVector2 SlotCoordinate, bool bRe
|
|||||||
0.f));
|
0.f));
|
||||||
|
|
||||||
// The plant mesh of a slot lives as long as the slot does, the visuals only ever show or hide it
|
// The plant mesh of a slot lives as long as the slot does, the visuals only ever show or hide it
|
||||||
if (!IsValid(Slot.PlantStaticMesh))
|
if (!IsValid(Slot.PlantSprite))
|
||||||
{
|
{
|
||||||
Slot.PlantStaticMesh = CreateSlotMeshComponent(this, GetRootComponent(), GetSlotComponentName(SlotCoordinate, TEXT("Plant")));
|
Slot.PlantSprite = CreatePaperSpriteComponent(this, GetRootComponent(), GetSlotComponentName(SlotCoordinate, TEXT("Plant")), DefaultPlantSpriteMaterial);
|
||||||
if (IsValid(Slot.PlantStaticMesh))
|
|
||||||
{
|
|
||||||
Slot.PlantStaticMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
|
||||||
Slot.PlantStaticMesh->SetVisibility(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplySlotVisuals(SlotCoordinate, Slot);
|
ApplySlotVisuals(SlotCoordinate, Slot);
|
||||||
@@ -598,44 +629,50 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PLANT ----------------------------------------------------------------------------------------
|
// PLANT ----------------------------------------------------------------------------------------
|
||||||
const bool bHasPlant = SlotHasLivingPlant(Slot);
|
if (!IsValid(Slot.PlantSprite))
|
||||||
|
|
||||||
if (!IsValid(Slot.PlantStaticMesh))
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bHasPlant)
|
if (!SlotHasLivingPlant(Slot))
|
||||||
{
|
{
|
||||||
// A plant that died or was harvested keeps its mesh, the slot is only emptied when it is cleared for real
|
// A plant that died or was harvested keeps its mesh, the slot is only emptied when it is cleared for real
|
||||||
Slot.PlantStaticMesh->SetVisibility(false);
|
Slot.PlantSprite->SetVisibility(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UStaticMesh* PlantMesh = nullptr;
|
FVector PlantOffset = GetSlotRelativeLocation(SlotCoordinate) + FVector(0.f, 0.f, 75.f);
|
||||||
FVector PlantOffset = FVector::ZeroVector;
|
FVector PlantScale = FVector(5.f);
|
||||||
FVector PlantScale = FVector::OneVector;
|
|
||||||
|
|
||||||
const int32 StageIndex = ResolveGrowthStageIndex(Slot);
|
const int32 StageIndex = ResolveGrowthStageIndex(Slot);
|
||||||
const UItemDataAsset* SeedData = Slot.SlotData.ItemDataAsset;
|
const UItemDataAsset* SeedData = Slot.SlotData.ItemDataAsset;
|
||||||
if (IsValid(SeedData) && SeedData->SeedStages.IsValidIndex(StageIndex))
|
if (IsValid(SeedData) && SeedData->SeedStages.IsValidIndex(StageIndex))
|
||||||
{
|
{
|
||||||
const FSeedStage& Stage = SeedData->SeedStages[StageIndex];
|
PlantScale *= FVector(SeedData->SeedStages[StageIndex].SpriteScale);
|
||||||
PlantMesh = ResolveSoftObject(Stage.Mesh);
|
PlantOffset += SeedData->SeedStages[StageIndex].Offset;
|
||||||
PlantOffset = Stage.MeshOffset;
|
|
||||||
PlantScale = SanitizeScale(Stage.MeshScale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A seed without stage meshes still has to show up, the fallback keeps the plant visible
|
Slot.PlantSprite->SetRelativeScale3D(PlantScale);
|
||||||
if (!PlantMesh)
|
Slot.PlantSprite->SetRelativeLocation(PlantOffset);
|
||||||
|
|
||||||
|
if (SeedData->SeedStages[StageIndex].Sprite.IsValid())
|
||||||
{
|
{
|
||||||
PlantMesh = ResolveSoftObject(DefaultPlantMesh);
|
Slot.PlantSprite->SetSprite(SeedData->SeedStages[StageIndex].Sprite.Get());
|
||||||
|
Slot.PlantSprite->SetVisibility(true);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SeedData->SeedStages[StageIndex].Sprite.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* SpriteObj)
|
||||||
|
{
|
||||||
|
FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate);
|
||||||
|
if (!Slot || !IsValid(Slot->PlantSprite)) return;
|
||||||
|
|
||||||
Slot.PlantStaticMesh->SetStaticMesh(PlantMesh);
|
UPaperSprite* Sprite = Cast<UPaperSprite>(SpriteObj);
|
||||||
Slot.PlantStaticMesh->SetRelativeLocation(SlotLocation + PlantOffset);
|
if (!Sprite) return;
|
||||||
Slot.PlantStaticMesh->SetRelativeScale3D(PlantScale);
|
|
||||||
Slot.PlantStaticMesh->SetVisibility(PlantMesh != nullptr);
|
Slot->PlantSprite->SetSprite(Sprite);
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void ASeedBedActor::RefreshSlotVisual(FIntVector2 SlotCoordinate)
|
void ASeedBedActor::RefreshSlotVisual(FIntVector2 SlotCoordinate)
|
||||||
{
|
{
|
||||||
@@ -654,7 +691,7 @@ void ASeedBedActor::RefreshAllSlotVisuals()
|
|||||||
{
|
{
|
||||||
for (TPair<FIntVector2, FSeedBedSeedSlot>& SlotPair : SeedBedSeedSlotsMap)
|
for (TPair<FIntVector2, FSeedBedSeedSlot>& SlotPair : SeedBedSeedSlotsMap)
|
||||||
{
|
{
|
||||||
ApplySlotVisuals(SlotPair.Key, SlotPair.Value);
|
RefreshSlotVisual(SlotPair.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "ProjectEleri/System/TimeOfDayStruct.h"
|
#include "ProjectEleri/System/TimeOfDayStruct.h"
|
||||||
#include "SeedBedActor.generated.h"
|
#include "SeedBedActor.generated.h"
|
||||||
|
|
||||||
|
class UPaperSpriteComponent;
|
||||||
class ATimeOfDayManager;
|
class ATimeOfDayManager;
|
||||||
class UDecalComponent;
|
class UDecalComponent;
|
||||||
class UMaterialInstanceDynamic;
|
class UMaterialInstanceDynamic;
|
||||||
@@ -80,7 +81,7 @@ struct FSeedBedSeedSlot
|
|||||||
UMaterialInstanceDynamic* SeedBedDynamicMat = nullptr;
|
UMaterialInstanceDynamic* SeedBedDynamicMat = nullptr;
|
||||||
|
|
||||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||||
UStaticMeshComponent* PlantStaticMesh;
|
UPaperSpriteComponent* PlantSprite;
|
||||||
};
|
};
|
||||||
|
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
@@ -137,7 +138,7 @@ public:
|
|||||||
|
|
||||||
/** Fallback mesh used when the planted seed has no growth stage set up */
|
/** Fallback mesh used when the planted seed has no growth stage set up */
|
||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
||||||
TSoftObjectPtr<UStaticMesh> DefaultPlantMesh;
|
TSoftObjectPtr<UMaterialInterface> DefaultPlantSpriteMaterial;
|
||||||
|
|
||||||
/** Dimensions of the grid generated by GenerateSeedBedGrid, X = columns, Y = rows */
|
/** Dimensions of the grid generated by GenerateSeedBedGrid, X = columns, Y = rows */
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "Components/CapsuleComponent.h"
|
#include "Components/CapsuleComponent.h"
|
||||||
#include "Components/StatForgeComponent.h"
|
#include "Components/StatForgeComponent.h"
|
||||||
#include "GameFramework/SpringArmComponent.h"
|
#include "GameFramework/SpringArmComponent.h"
|
||||||
|
#include "ProjectEleri/Components/EleriFlipbookComponent.h"
|
||||||
#include "ProjectEleri/Items/SeedBedActor.h"
|
#include "ProjectEleri/Items/SeedBedActor.h"
|
||||||
#include "Subsystem/InteractionSubsystem.h"
|
#include "Subsystem/InteractionSubsystem.h"
|
||||||
|
|
||||||
@@ -38,6 +39,8 @@ AMyCharacter::AMyCharacter()
|
|||||||
PrimaryActorTick.bCanEverTick = true;
|
PrimaryActorTick.bCanEverTick = true;
|
||||||
|
|
||||||
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>(TEXT("StatForgeComponent"));
|
StatForgeComponent = CreateDefaultSubobject<UStatForgeComponent>(TEXT("StatForgeComponent"));
|
||||||
|
SpriteComponent = CreateDefaultSubobject<UEleriFlipbookComponent>(TEXT("Sprite Component"));
|
||||||
|
SpriteComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AMyCharacter::IsEditor() const {
|
bool AMyCharacter::IsEditor() const {
|
||||||
|
|||||||
@@ -469,6 +469,26 @@ float ATimeOfDayManager::GetMinutesPassedSoFar() const
|
|||||||
(GetYear() * 60.f * 24.f * 28.f * 4.f);
|
(GetYear() * 60.f * 24.f * 28.f * 4.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FText ATimeOfDayManager::GetFormattedTime() const
|
||||||
|
{
|
||||||
|
// AddMinutes() clamps to 0..24 / 0..60 while a step is being applied, so the displayed values are
|
||||||
|
// clamped here too and a transient "24:60" never reaches the UI.
|
||||||
|
const int32 DisplayHours = FMath::Clamp(currentHours, 0, 23);
|
||||||
|
const int32 DisplayMinutes = FMath::Clamp(static_cast<int32>(currentMinutes), 0, 59);
|
||||||
|
|
||||||
|
// MinimumIntegralDigits pads single digit values with a leading zero, so "7:5" becomes "07:05".
|
||||||
|
FNumberFormattingOptions TwoDigitOptions;
|
||||||
|
TwoDigitOptions.SetUseGrouping(false);
|
||||||
|
TwoDigitOptions.SetMinimumIntegralDigits(2);
|
||||||
|
TwoDigitOptions.SetMaximumIntegralDigits(2);
|
||||||
|
|
||||||
|
FFormatNamedArguments Arguments;
|
||||||
|
Arguments.Add(TEXT("Hours"), FText::AsNumber(DisplayHours, &TwoDigitOptions));
|
||||||
|
Arguments.Add(TEXT("Minutes"), FText::AsNumber(DisplayMinutes, &TwoDigitOptions));
|
||||||
|
|
||||||
|
return FText::Format(NSLOCTEXT("TimeOfDayManager", "ClockTimeFormat", "{Hours}:{Minutes}"), Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
void ATimeOfDayManager::GetDateMinusDays(int32 days, int32 &daysOut, int32 &monthsOut, int32 &yearsOut)
|
void ATimeOfDayManager::GetDateMinusDays(int32 days, int32 &daysOut, int32 &monthsOut, int32 &yearsOut)
|
||||||
{
|
{
|
||||||
int32 currDays = GetDaysPassed() - days;
|
int32 currDays = GetDaysPassed() - days;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "MyCharacter.generated.h"
|
#include "MyCharacter.generated.h"
|
||||||
|
|
||||||
|
class UEleriFlipbookComponent;
|
||||||
class ASeedBedActor;
|
class ASeedBedActor;
|
||||||
class USpringArmComponent;
|
class USpringArmComponent;
|
||||||
class UStatForgeComponent;
|
class UStatForgeComponent;
|
||||||
@@ -79,6 +80,9 @@ protected:
|
|||||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
UStatForgeComponent* StatForgeComponent;
|
UStatForgeComponent* StatForgeComponent;
|
||||||
|
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
|
||||||
|
UEleriFlipbookComponent* SpriteComponent;
|
||||||
|
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
TObjectPtr<UCameraComponent> CameraRef;
|
TObjectPtr<UCameraComponent> CameraRef;
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
|
|||||||
@@ -309,6 +309,11 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Time of day")
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Time of day")
|
||||||
inline int32 GetYear() const { return currentYear; }
|
inline int32 GetYear() const { return currentYear; }
|
||||||
|
|
||||||
|
/** Clock time formatted for display. Both fields are always two digits wide, so a clock reading
|
||||||
|
* 7 hours and 5 minutes is shown as "07:05". */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Time of day")
|
||||||
|
FText GetFormattedTime() const;
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Time of day")
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Time of day")
|
||||||
inline int32 GetAllDaysPassed() const
|
inline int32 GetAllDaysPassed() const
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user