Fixes for seed planting
This commit is contained in:
@@ -12,11 +12,15 @@
|
||||
#include "Engine/StaticMesh.h"
|
||||
#include "Engine/World.h"
|
||||
#include "ItemContainer.h"
|
||||
#include "NiagaraComponent.h"
|
||||
#include "PaperSpriteComponent.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMaterialLibrary.h"
|
||||
#include "Materials/MaterialInstanceDynamic.h"
|
||||
#include "Materials/MaterialInterface.h"
|
||||
#include "ProjectEleri/Components/EleriPaperSpriteComponent.h"
|
||||
#include "ProjectEleri/Settings/EleriGameSettings.h"
|
||||
#include "NiagaraComponent.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -31,14 +35,14 @@ namespace
|
||||
}
|
||||
|
||||
/** Slots are created at runtime as well, so the components are created with stable, deterministic names */
|
||||
UPaperSpriteComponent* CreatePaperSpriteComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName, TSoftObjectPtr<UMaterialInterface> Material)
|
||||
UEleriPaperSpriteComponent* CreatePaperSpriteComponent(AActor* Owner, USceneComponent* AttachParent, FName ComponentName, TSoftObjectPtr<UMaterialInterface> Material)
|
||||
{
|
||||
if (!IsValid(Owner) || !IsValid(AttachParent))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UPaperSpriteComponent* SpriteComponent = NewObject<UPaperSpriteComponent>(Owner, ComponentName);
|
||||
UEleriPaperSpriteComponent* SpriteComponent = NewObject<UEleriPaperSpriteComponent>(Owner, ComponentName);
|
||||
if (!SpriteComponent)
|
||||
{
|
||||
return nullptr;
|
||||
@@ -46,10 +50,15 @@ namespace
|
||||
|
||||
SpriteComponent->SetMobility(EComponentMobility::Movable);
|
||||
SpriteComponent->SetupAttachment(AttachParent);
|
||||
SpriteComponent->DecalSize = FVector(150.f);
|
||||
SpriteComponent->DecalOffset = FVector(0.f, 0.f, 40.f);
|
||||
SpriteComponent->DecalMaterial = UEleriGameSettings::GetEleriGameSettings()->SpriteShadowMaterial;
|
||||
SpriteComponent->SetReceivesDecals(false);
|
||||
SpriteComponent->RegisterComponent();
|
||||
SpriteComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
SpriteComponent->SetVisibility(false);
|
||||
TWeakObjectPtr<UPaperSpriteComponent> SpriteComp = SpriteComponent;
|
||||
SpriteComponent->DecalComponent->SetVisibility(false);
|
||||
TWeakObjectPtr<UEleriPaperSpriteComponent> SpriteComp = SpriteComponent;
|
||||
if (Material.IsValid())
|
||||
{
|
||||
SpriteComp->SetMaterial(0, Material.Get());
|
||||
@@ -265,7 +274,7 @@ void ASeedBedActor::AdvanceSeedBedByHours(int32 Hours)
|
||||
// Every hour is applied on its own, a jump over several of them grows, dries and kills hour by hour
|
||||
for (int32 HourIndex = 0; HourIndex < Hours && SlotHasLivingPlant(SlotPair.Value); ++HourIndex)
|
||||
{
|
||||
ApplyHourPassedToSlot(SlotPair.Value, Now);
|
||||
ApplyHourPassedToSlot(SlotPair.Value, Now, SlotPair.Key);
|
||||
}
|
||||
|
||||
if (bWasAlive && !SlotHasLivingPlant(SlotPair.Value))
|
||||
@@ -283,9 +292,14 @@ void ASeedBedActor::AdvanceSeedBedByHours(int32 Hours)
|
||||
}
|
||||
}
|
||||
|
||||
void ASeedBedActor::ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now)
|
||||
void ASeedBedActor::ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now, const FIntVector2& SlotCoordinate)
|
||||
{
|
||||
FSeedBedSeedSlotData& SlotData = Slot.SlotData;
|
||||
|
||||
if (SlotData.bBloomed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The moisture of the soil drains with every in game hour, so the wetness is a clock of its own
|
||||
const bool bWasMoist = SlotData.MoistureHoursRemaining > 0;
|
||||
@@ -308,6 +322,11 @@ void ASeedBedActor::ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfD
|
||||
}
|
||||
|
||||
SlotData.SeedAgeHours = FMath::Min(SlotData.SeedAgeHours + 1, FMath::Max(0, SlotData.GrowTime) * SeedBedHoursPerDay);
|
||||
SlotData.bBloomed = SlotData.SeedAgeHours >= SlotData.GrowTime * SeedBedHoursPerDay;
|
||||
if (SlotData.bBloomed)
|
||||
{
|
||||
RefreshSlotVisual(SlotCoordinate);
|
||||
}
|
||||
}
|
||||
|
||||
void ASeedBedActor::ApplyOfflineProgression()
|
||||
@@ -604,6 +623,18 @@ FSeedBedSeedSlot& ASeedBedActor::CreateSlot(FIntVector2 SlotCoordinate, bool bRe
|
||||
{
|
||||
Slot.PlantSprite = CreatePaperSpriteComponent(this, GetRootComponent(), GetSlotComponentName(SlotCoordinate, TEXT("Plant")), DefaultPlantSpriteMaterial);
|
||||
}
|
||||
|
||||
Slot.NiagaraComponent = NewObject<UNiagaraComponent>(this, GetSlotComponentName(SlotCoordinate, TEXT("Vfx")));
|
||||
Slot.NiagaraComponent->SetMobility(EComponentMobility::Movable);
|
||||
Slot.NiagaraComponent->SetupAttachment(GetRootComponent());
|
||||
Slot.NiagaraComponent->SetAutoActivate(false);
|
||||
Slot.NiagaraComponent->RegisterComponent();
|
||||
Slot.NiagaraComponent->SetRelativeLocation(FVector(
|
||||
Offset.X + X + SeedBedDecalSize.Z,
|
||||
Offset.Y + Y + SeedBedDecalSize.Y,
|
||||
50.f));
|
||||
Slot.NiagaraComponent->SetVisibility(false);
|
||||
AddInstanceComponent(Slot.NiagaraComponent);
|
||||
|
||||
ApplySlotVisuals(SlotCoordinate, Slot);
|
||||
|
||||
@@ -638,6 +669,7 @@ 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);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -645,6 +677,13 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
FVector PlantScale = FVector(5.f);
|
||||
|
||||
const int32 StageIndex = ResolveGrowthStageIndex(Slot);
|
||||
if (StageIndex == INDEX_NONE)
|
||||
{
|
||||
Slot.PlantSprite->SetVisibility(false);
|
||||
Slot.PlantSprite->DecalComponent->SetVisibility(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const UItemDataAsset* SeedData = Slot.SlotData.ItemDataAsset;
|
||||
if (IsValid(SeedData) && SeedData->SeedStages.IsValidIndex(StageIndex))
|
||||
{
|
||||
@@ -654,11 +693,13 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
|
||||
Slot.PlantSprite->SetRelativeScale3D(PlantScale);
|
||||
Slot.PlantSprite->SetRelativeLocation(PlantOffset);
|
||||
Slot.PlantSprite->UpdateRelativeLocation(FVector(PlantOffset.X, PlantOffset.Y, 0.f));
|
||||
|
||||
if (SeedData->SeedStages[StageIndex].Sprite.IsValid())
|
||||
{
|
||||
Slot.PlantSprite->SetSprite(SeedData->SeedStages[StageIndex].Sprite.Get());
|
||||
Slot.PlantSprite->SetVisibility(true);
|
||||
Slot.PlantSprite->DecalComponent->SetVisibility(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -673,8 +714,36 @@ void ASeedBedActor::ApplySlotVisuals(FIntVector2 SlotCoordinate, FSeedBedSeedSlo
|
||||
Slot->PlantSprite->SetSprite(Sprite);
|
||||
}));
|
||||
}
|
||||
|
||||
if (Slot.SlotData.bBloomed && !Slot.NiagaraComponent->IsActive())
|
||||
{
|
||||
Slot.NiagaraComponent->SetAsset(nullptr);
|
||||
Slot.NiagaraComponent->Activate(false);
|
||||
|
||||
if (PlantBloomedVfx.IsValid())
|
||||
{
|
||||
Slot.NiagaraComponent->SetAsset(PlantBloomedVfx.Get());
|
||||
Slot.NiagaraComponent->Activate(true);
|
||||
Slot.NiagaraComponent->SetVisibility(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlantBloomedVfx.LoadAsync(FLoadSoftObjectPathAsyncDelegate::CreateWeakLambda(this, [this, SlotCoordinate](const FSoftObjectPath& Path, UObject* EffectObj)
|
||||
{
|
||||
FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate);
|
||||
if (!Slot || !IsValid(Slot->NiagaraComponent)) return;
|
||||
|
||||
UNiagaraSystem* NiagaraSystem = Cast<UNiagaraSystem>(EffectObj);
|
||||
if (!IsValid(NiagaraSystem)) return;
|
||||
|
||||
Slot->NiagaraComponent->SetAsset(NiagaraSystem);
|
||||
Slot->NiagaraComponent->ResetSystem();
|
||||
Slot->NiagaraComponent->SetVisibility(true);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
void ASeedBedActor::RefreshSlotVisual(FIntVector2 SlotCoordinate)
|
||||
void ASeedBedActor::RefreshSlotVisual(const FIntVector2& SlotCoordinate)
|
||||
{
|
||||
FSeedBedSeedSlot* Slot = SeedBedSeedSlotsMap.Find(SlotCoordinate);
|
||||
if (!Slot)
|
||||
@@ -698,7 +767,7 @@ void ASeedBedActor::RefreshAllSlotVisuals()
|
||||
bool ASeedBedActor::IsPlantableSeedData(const UItemDataAsset* SeedData)
|
||||
{
|
||||
// Only seeds of plants make it into a bed, the meshes are optional and fall back to DefaultPlantMesh
|
||||
return IsValid(SeedData) && SeedData->IsSeed;
|
||||
return IsValid(SeedData) && SeedData->ItemCategory == Category::Seed;
|
||||
}
|
||||
|
||||
void ASeedBedActor::HighlightSlot(FIntVector2 SlotCoordinate)
|
||||
@@ -816,7 +885,7 @@ int32 ASeedBedActor::ResolveGrowthStageIndex(const FSeedBedSeedSlot& Slot) const
|
||||
}
|
||||
|
||||
// Stages are set up per day while the age of a plant counts hours, so the last day that was reached wins
|
||||
int32 StageIndex = 0;
|
||||
int32 StageIndex = INDEX_NONE;
|
||||
|
||||
for (int32 Index = 0; Index < SeedData->SeedStages.Num(); ++Index)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include "ProjectEleri/System/TimeOfDayStruct.h"
|
||||
#include "SeedBedActor.generated.h"
|
||||
|
||||
class UNiagaraSystem;
|
||||
class UNiagaraComponent;
|
||||
class UEleriPaperSpriteComponent;
|
||||
class UPaperSpriteComponent;
|
||||
class ATimeOfDayManager;
|
||||
class UDecalComponent;
|
||||
@@ -81,7 +84,10 @@ struct FSeedBedSeedSlot
|
||||
UMaterialInstanceDynamic* SeedBedDynamicMat = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UPaperSpriteComponent* PlantSprite;
|
||||
UEleriPaperSpriteComponent* PlantSprite = nullptr;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
|
||||
UNiagaraComponent* NiagaraComponent = nullptr;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
@@ -143,6 +149,9 @@ public:
|
||||
/** Dimensions of the grid generated by GenerateSeedBedGrid, X = columns, Y = rows */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
||||
FIntVector2 GridSize = FIntVector2(3, 3);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Seed Bed|Setup")
|
||||
TSoftObjectPtr<UNiagaraSystem> PlantBloomedVfx;
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// HIGHLIGHT DECAL
|
||||
@@ -249,7 +258,7 @@ public:
|
||||
|
||||
/** Re-applies mesh, material and decal of a single slot */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed|Visuals")
|
||||
void RefreshSlotVisual(FIntVector2 SlotCoordinate);
|
||||
void RefreshSlotVisual(const FIntVector2& SlotCoordinate);
|
||||
|
||||
/** Re-applies mesh, material and decal of every slot of the bed */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed|Visuals")
|
||||
@@ -287,7 +296,7 @@ protected:
|
||||
void BindToTimeOfDay();
|
||||
|
||||
/** Applies one in game hour of growth, moisture handling and death checks to a single slot */
|
||||
void ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now);
|
||||
void ApplyHourPassedToSlot(FSeedBedSeedSlot& Slot, const FTimeOfDayData& Now, const FIntVector2& SlotCoordinate);
|
||||
|
||||
/** Catches the plants up on the in game time that passed while the bed was not in the world */
|
||||
void ApplyOfflineProgression();
|
||||
|
||||
Reference in New Issue
Block a user