Improvements to watering and some stat forge fixes
This commit is contained in:
@@ -15,6 +15,7 @@ STATFORGE_MAKE_STAT(FriendPointsMultiplier)
|
||||
STATFORGE_MAKE_STAT(AlchemyMultiplier)
|
||||
STATFORGE_MAKE_STAT(BazarCustomerSpawnRate)
|
||||
STATFORGE_MAKE_STAT(BazarCustomerWill)
|
||||
STATFORGE_MAKE_STAT(WateringAreaScaleMultiplier)
|
||||
|
||||
STATFORGE_MAKE_STAT(AlchemyXp)
|
||||
STATFORGE_MAKE_STAT(BotanyXp)
|
||||
|
||||
@@ -17,6 +17,7 @@ STATFORGE_DECLARE_STAT(FriendPointsMultiplier)
|
||||
STATFORGE_DECLARE_STAT(AlchemyMultiplier)
|
||||
STATFORGE_DECLARE_STAT(BazarCustomerSpawnRate)
|
||||
STATFORGE_DECLARE_STAT(BazarCustomerWill)
|
||||
STATFORGE_DECLARE_STAT(WateringAreaScaleMultiplier)
|
||||
|
||||
STATFORGE_DECLARE_STAT(AlchemyXp)
|
||||
STATFORGE_DECLARE_STAT(BotanyXp)
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
|
||||
#include "WaterBall.h"
|
||||
#include "Kismet/GameplayStatics.h"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
#include "DrawDebugHelpers.h"
|
||||
#include "Engine/OverlapResult.h"
|
||||
#include "Engine/World.h"
|
||||
#include "ProjectEleri/Items/SeedCarousel.h"
|
||||
|
||||
#include "Helpers/StatForgeFunctionLibrary.h"
|
||||
#include "ProjectEleri/Data/StatDefinitions.h"
|
||||
|
||||
// Sets default values
|
||||
AWaterBall::AWaterBall()
|
||||
@@ -27,18 +25,14 @@ void AWaterBall::BeginPlay()
|
||||
Super::BeginPlay();
|
||||
PlayerCharacter = Cast<AMyCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
|
||||
PlayerCameraManager = Cast<APlayerCameraManager>(UGameplayStatics::GetPlayerCameraManager(GetWorld(), 0));
|
||||
MaxPitch = FMath::Abs(PlayerCameraManager->ViewPitchMin) + PlayerCameraManager->ViewPitchMax;
|
||||
if (MaxPitch == 0) MaxPitch = 1;
|
||||
|
||||
PitchOffset = FMath::Abs(PlayerCameraManager->ViewPitchMax);
|
||||
HighlightBox->SetStaticMesh(HighlightBoxMesh);
|
||||
HighlightBox->SetVisibility(true);
|
||||
HighlightBox->SetMaterial(0, HighlightBoxMaterial);
|
||||
HighlightBox->SetRelativeScale3D(FVector(10.0f, 10.0f, 10.0f));
|
||||
|
||||
const float ScaleMultiplier = FMath::Min(UStatForgeFunctionLibrary::GetStatValue(FStat::WateringAreaScaleMultiplier, PlayerCharacter), 1.f);
|
||||
HighlightBox->SetRelativeScale3D(FVector(5.0f * ScaleMultiplier));
|
||||
HighlightBox->SetCollisionEnabled(ECollisionEnabled::NoCollision);
|
||||
|
||||
ActorsToIgnore.Add(this);
|
||||
ActorsToIgnore.Add(PlayerCharacter);
|
||||
}
|
||||
|
||||
// Called every frame
|
||||
@@ -52,64 +46,14 @@ void AWaterBall::Tick(float DeltaTime)
|
||||
HighlightBox->SetVisibility(false);
|
||||
if (!PlayerCharacter->IsWatering()) return;
|
||||
|
||||
CurrentPitch = PlayerCharacter->Pitch;
|
||||
CurrentPitch += PitchOffset;
|
||||
if (CurrentPitch > 100.0f)
|
||||
{
|
||||
CurrentPitch -= 360.0f;
|
||||
}
|
||||
|
||||
FPredictProjectilePathParams PredictParams;
|
||||
|
||||
float Drag = FMath::Lerp(4.0f, 1.1f, FMath::Abs(CurrentPitch / MaxPitch));
|
||||
FVector ForwardVec = UKismetMathLibrary::FindLookAtRotation(PlayerCharacter->GetCameraWorldPosition(), PlayerCharacter->GetActorLocation()).Quaternion().GetForwardVector();
|
||||
FVector Offset = (ForwardVec * FVector(2000.f, 2000.f, 0.f));
|
||||
FVector EndLocation = PlayerCharacter->GetActorLocation() + Offset;
|
||||
FVector StartingLoc = PlayerCharacter->GetActorLocation();
|
||||
PredictParams.StartLocation = StartingLoc;
|
||||
LaunchVelocity =
|
||||
UKismetMathLibrary::GetDirectionUnitVector(StartingLoc, EndLocation) * FVector(500.0f * Drag, 500.0f * Drag, -30000.f);
|
||||
|
||||
PredictParams.LaunchVelocity = LaunchVelocity;
|
||||
PredictParams.MaxSimTime = 10.0f;
|
||||
PredictParams.bTraceWithCollision = true;
|
||||
PredictParams.SimFrequency = 10.0f;
|
||||
PredictParams.bTraceComplex = true;
|
||||
for (int32 i = 0; i < ActorsToIgnore.Num(); i++)
|
||||
{
|
||||
PredictParams.ActorsToIgnore.Add(ActorsToIgnore[i]);
|
||||
}
|
||||
FPredictProjectilePathResult PredictResults;
|
||||
UGameplayStatics::PredictProjectilePath(GetWorld(), PredictParams, PredictResults);
|
||||
|
||||
HighlightBox->SetVisibility(true);
|
||||
FVector HighlightBoxLocation = PredictResults.PathData[PredictResults.PathData.Num() - 1].Location;
|
||||
HighlightBoxLocation.Z += 5;
|
||||
HighlightBox->SetWorldLocation(HighlightBoxLocation);
|
||||
|
||||
const FVector ForwardVec = UKismetMathLibrary::FindLookAtRotation(PlayerCharacter->GetCameraWorldPosition(), PlayerCharacter->GetActorLocation()).Quaternion().GetForwardVector();
|
||||
const FVector Offset = (ForwardVec * FVector(700.f, 700.f, 0.f)) + FVector(0.f, 0.f, -115.f);
|
||||
|
||||
HighlightBox->SetWorldLocation(PlayerCharacter->GetActorLocation() + Offset);
|
||||
}
|
||||
|
||||
TArray<ASeedCarousel*> AWaterBall::GetOverlappingSeeds()
|
||||
{
|
||||
TArray<ASeedCarousel*> Seeds;
|
||||
TArray<FOverlapResult> OverlapResults;
|
||||
FCollisionObjectQueryParams OverlapParams;
|
||||
OverlapParams.AddObjectTypesToQuery(ECC_WorldDynamic);
|
||||
|
||||
FVector BoundsMin, BoundsMax;
|
||||
HighlightBox->GetLocalBounds(BoundsMin, BoundsMax);
|
||||
float Radius = (FVector::Distance(BoundsMin, BoundsMax) * HighlightBox->GetComponentScale().X) / PI;
|
||||
GetWorld()->OverlapMultiByObjectType(OverlapResults, HighlightBox->GetComponentLocation(), FQuat::Identity, OverlapParams, FCollisionShape::MakeSphere(Radius));
|
||||
//DrawDebugSphere(GetWorld(), HighlightBox->GetComponentLocation(), Radius, 16, FColor::Red, false, 5.f);
|
||||
for (const FOverlapResult& OverlapResult : OverlapResults)
|
||||
{
|
||||
if (ASeedCarousel* Carousel = Cast<ASeedCarousel>(OverlapResult.GetActor()))
|
||||
{
|
||||
Seeds.Add(Carousel);
|
||||
}
|
||||
}
|
||||
|
||||
return Seeds;
|
||||
}
|
||||
|
||||
void AWaterBall::ThrowBall_Implementation()
|
||||
{
|
||||
|
||||
@@ -36,10 +36,6 @@ protected:
|
||||
FVector LaunchVelocity;
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
TArray<AActor*> ActorsToIgnore;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
AMyCharacter* PlayerCharacter;
|
||||
|
||||
@@ -49,15 +45,6 @@ public:
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
|
||||
UMaterialInstance* HighlightBoxMaterial;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
float CurrentPitch;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
float PitchOffset;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
float MaxPitch;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
bool bThrowing;
|
||||
|
||||
@@ -79,6 +66,4 @@ public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
FVector GetLaunchVelocity() { return LaunchVelocity; }
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
TArray<ASeedCarousel*> GetOverlappingSeeds();
|
||||
};
|
||||
|
||||
@@ -357,6 +357,68 @@ void ASeedBedActor::WaterAllSeedSlots()
|
||||
WaterSeedInSlot(SlotCoordinate);
|
||||
}
|
||||
}
|
||||
|
||||
int32 ASeedBedActor::GatherSlotsInRadius(const FVector& WorldLocation, float Radius, TArray<FIntVector2>& OutSlotCoordinates) const
|
||||
{
|
||||
OutSlotCoordinates.Reset();
|
||||
|
||||
// A radius of zero only ever covers the point itself, so there is nothing to gather
|
||||
if (Radius <= 0.f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const float RadiusSquared = FMath::Square(Radius);
|
||||
|
||||
for (const TPair<FIntVector2, FSeedBedSeedSlot>& SlotPair : SeedBedSeedSlotsMap)
|
||||
{
|
||||
// Only living plants are watered, an empty or dead slot has nothing to soak up
|
||||
if (!SlotHasLivingPlant(SlotPair.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
FVector SlotWorldLocation;
|
||||
if (!GetSlotWorldLocation(SlotPair.Key, SlotWorldLocation))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only the plane of the bed counts, so watering from above or from uphill reaches the same slots
|
||||
if (FVector::DistSquaredXY(WorldLocation, SlotWorldLocation) > RadiusSquared)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OutSlotCoordinates.Add(SlotPair.Key);
|
||||
}
|
||||
|
||||
return OutSlotCoordinates.Num();
|
||||
}
|
||||
|
||||
int32 ASeedBedActor::WaterSlotsInRadius(const FVector& WorldLocation, float Radius)
|
||||
{
|
||||
// The slots are gathered first, a listener of the refresh is free to change the map while we water
|
||||
TArray<FIntVector2> SlotCoordinates;
|
||||
const int32 WateredSlotCount = GatherSlotsInRadius(WorldLocation, Radius, SlotCoordinates);
|
||||
|
||||
for (const FIntVector2& SlotCoordinate : SlotCoordinates)
|
||||
{
|
||||
WaterSeedInSlot(SlotCoordinate);
|
||||
}
|
||||
|
||||
// The cache is what the game state falls back to once the bed is streamed out, so it has to know
|
||||
// about the watering right away. Nothing was watered, so there is nothing to cache either.
|
||||
if (WateredSlotCount > 0)
|
||||
{
|
||||
if (AEleriGameState* GameState = Cast<AEleriGameState>(UGameplayStatics::GetGameState(this)))
|
||||
{
|
||||
GameState->CacheSeedData(SeedBedIndex, PrepareSeedSaveData());
|
||||
}
|
||||
}
|
||||
|
||||
return WateredSlotCount;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// GRID GENERATION
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@@ -623,7 +685,12 @@ void ASeedBedActor::HighlightSlot(FIntVector2 SlotCoordinate)
|
||||
|
||||
void ASeedBedActor::StopHighlightingSlot()
|
||||
{
|
||||
HighlightDecal->SetVisibility(false);
|
||||
// The decal only exists once BeginPlay created it, a highlight is stopped on beds that never got one as well
|
||||
if (IsValid(HighlightDecal))
|
||||
{
|
||||
HighlightDecal->SetVisibility(false);
|
||||
}
|
||||
|
||||
HighlightedSlotIndex = FIntVector2::NoneValue;
|
||||
}
|
||||
|
||||
@@ -650,6 +717,14 @@ int32 ASeedBedActor::GetFreeSlotCount() const
|
||||
return FreeSlotCount;
|
||||
}
|
||||
bool ASeedBedActor::FindClosestFreeSlot(const FVector& WorldLocation, FIntVector2& OutSlotCoordinate) const
|
||||
{
|
||||
float DistanceSquared = 0.f;
|
||||
|
||||
// The distance of the slot is only interesting for the planting highlight, the plain lookup ignores it
|
||||
return FindClosestFreeSlotWithDistance(WorldLocation, OutSlotCoordinate, DistanceSquared);
|
||||
}
|
||||
|
||||
bool ASeedBedActor::FindClosestFreeSlotWithDistance(const FVector& WorldLocation, FIntVector2& OutSlotCoordinate, float& OutDistanceSquared) const
|
||||
{
|
||||
bool bFoundSlot = false;
|
||||
float ClosestDistanceSquared = 0.f;
|
||||
@@ -667,7 +742,8 @@ bool ASeedBedActor::FindClosestFreeSlot(const FVector& WorldLocation, FIntVector
|
||||
continue;
|
||||
}
|
||||
|
||||
const float DistanceSquared = FVector::DistSquared(WorldLocation, SlotWorldLocation);
|
||||
// Only the plane of the bed counts, a player standing uphill has to reach the slot just as well
|
||||
const float DistanceSquared = FVector::DistSquaredXY(WorldLocation, SlotWorldLocation);
|
||||
if (!bFoundSlot || DistanceSquared < ClosestDistanceSquared)
|
||||
{
|
||||
bFoundSlot = true;
|
||||
@@ -676,6 +752,8 @@ bool ASeedBedActor::FindClosestFreeSlot(const FVector& WorldLocation, FIntVector
|
||||
}
|
||||
}
|
||||
|
||||
OutDistanceSquared = ClosestDistanceSquared;
|
||||
|
||||
return bFoundSlot;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,10 +196,24 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed")
|
||||
void WaterAllSeedSlots();
|
||||
|
||||
/** Waters every planted slot whose world location lies within the given radius around a world point.
|
||||
* Returns the number of slots that were watered and caches the new slot data into the game state. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed")
|
||||
int32 WaterSlotsInRadius(const FVector& WorldLocation, float Radius);
|
||||
|
||||
/** Collects the coordinates of every planted slot whose world location lies within the given radius.
|
||||
* Returns the number of collected slots, OutSlotCoordinates is emptied first. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed")
|
||||
int32 GatherSlotsInRadius(const FVector& WorldLocation, float Radius, TArray<FIntVector2>& OutSlotCoordinates) const;
|
||||
|
||||
/** Finds the free slot that is closest to the given world location */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed")
|
||||
bool FindClosestFreeSlot(const FVector& WorldLocation, FIntVector2& OutSlotCoordinate) const;
|
||||
|
||||
/** Same as FindClosestFreeSlot, but also reports how far away the slot is, as a squared distance in XY */
|
||||
UFUNCTION(BlueprintCallable, Category = "Seed Bed")
|
||||
bool FindClosestFreeSlotWithDistance(const FVector& WorldLocation, FIntVector2& OutSlotCoordinate, float& OutDistanceSquared) const;
|
||||
|
||||
/** World location a plant of the given slot is placed at */
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Seed Bed")
|
||||
bool GetSlotWorldLocation(FIntVector2 SlotCoordinate, FVector& OutWorldLocation) const;
|
||||
|
||||
@@ -23,7 +23,12 @@
|
||||
#include "Subsystem/InteractionSubsystem.h"
|
||||
#include "Interface/InteractableActorInterface.h"
|
||||
#include "EngineUtils.h"
|
||||
#include "Components/StatForgeComponent.h"
|
||||
#include "Helpers/StatForgeFunctionLibrary.h"
|
||||
#include "ProjectEleri/Data/StatDefinitions.h"
|
||||
#include "ProjectEleri/Items/SeedBedActor.h"
|
||||
#include "ProjectEleri/Settings/EleriGameSettings.h"
|
||||
#include "ProjectEleri/System/EleriGameplayTags.h"
|
||||
|
||||
AEleriPlayerController::AEleriPlayerController(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
@@ -53,6 +58,30 @@ void AEleriPlayerController::BeginPlay()
|
||||
AlchemyManager = Cast<AAlchemyManager>(UGameplayStatics::GetActorOfClass(GetWorld(), AAlchemyManager::StaticClass()));
|
||||
|
||||
SelectionManagerInventorySlots = NewObject<USelectionManager>();
|
||||
ToggleMovement(true);
|
||||
}
|
||||
|
||||
void AEleriPlayerController::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||
{
|
||||
ToggleMovement(true);
|
||||
|
||||
Super::EndPlay(EndPlayReason);
|
||||
}
|
||||
|
||||
void AEleriPlayerController::ToggleMovement(bool bActive)
|
||||
{
|
||||
UStatForgeComponent* StatForgeComponent = UMainBlueprintFunctionLibrary::GetStatForgeComponentFromPlayer(this);
|
||||
if (!StatForgeComponent) return;
|
||||
|
||||
if (bActive)
|
||||
{
|
||||
StatForgeComponent->RemoveGameplayStatEffect(MovementDisabledEffect);
|
||||
return;
|
||||
}
|
||||
|
||||
const UEleriGameSettings* GameSettings = UEleriGameSettings::GetEleriGameSettings();
|
||||
ensure(GameSettings);
|
||||
MovementDisabledEffect = StatForgeComponent->ApplyGameplayStatEffect(GameSettings->MovementDisableEffectClass, TMap<FName, float>());
|
||||
}
|
||||
|
||||
void AEleriPlayerController::Tick(float DeltaTime)
|
||||
@@ -332,19 +361,20 @@ void AEleriPlayerController::OnMove(const FInputActionValue &Value)
|
||||
if (IsInMenu())
|
||||
return;
|
||||
|
||||
FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();
|
||||
const FVector2D AnalogueValue = Value.Get<FInputActionValue::Axis2D>();
|
||||
MovementDirection = AnalogueValue;
|
||||
|
||||
if (PlayerCharacter)
|
||||
{
|
||||
FRotator CtrlRotation = GetControlRotation();
|
||||
FRotator YawRotation(0, CtrlRotation.Yaw, 0);
|
||||
if (UStatForgeFunctionLibrary::HasTag(CharacterState::MovementDisabled, PlayerCharacter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const float AppliedMovementVelocity = UStatForgeFunctionLibrary::GetStatValue(FStat::MovementSpeedMultiplier, PlayerCharacter);
|
||||
|
||||
// FVector ForwardFacing = UKismetMathLibrary::GetForwardVector(bFlying? PlayerCameraManager->GetCameraRotation() : CharRotForward);
|
||||
float AppliedMovementVelocity = 1.f; // MovementVelocity * (bFlying? 0.5f : 1.f);
|
||||
|
||||
FVector ForwardVec = PlayerCharacter->GetPlayerCamera()->GetForwardVector();
|
||||
FVector RightVec = PlayerCharacter->GetPlayerCamera()->GetRightVector();
|
||||
const FVector ForwardVec = PlayerCharacter->GetPlayerCamera()->GetForwardVector();
|
||||
const FVector RightVec = PlayerCharacter->GetPlayerCamera()->GetRightVector();
|
||||
|
||||
PlayerCharacter->AddMovementInput(ForwardVec, MovementDirection.Y * AppliedMovementVelocity);
|
||||
PlayerCharacter->AddMovementInput(RightVec, MovementDirection.X * AppliedMovementVelocity);
|
||||
@@ -446,10 +476,13 @@ void AEleriPlayerController::OnWateringActionStart(const FInputActionValue &Valu
|
||||
MainGameUI->IsAlchemyOpen() ||
|
||||
IsInMenu())
|
||||
return;
|
||||
|
||||
Watering = true;
|
||||
PlayerCharacter->BeginWatering();
|
||||
OnWatering.Broadcast(Watering);
|
||||
OnChangeInputContext.Broadcast(2);
|
||||
|
||||
ToggleMovement(false);
|
||||
}
|
||||
|
||||
void AEleriPlayerController::OnWateringActionEnd(const FInputActionValue &Value)
|
||||
@@ -463,6 +496,8 @@ void AEleriPlayerController::OnWateringActionEnd(const FInputActionValue &Value)
|
||||
PlayerCharacter->EndWatering();
|
||||
OnWatering.Broadcast(Watering);
|
||||
OnChangeInputContext.Broadcast(1);
|
||||
|
||||
ToggleMovement(true);
|
||||
}
|
||||
|
||||
void AEleriPlayerController::OnWateringThrowAction(const FInputActionValue &Value)
|
||||
|
||||
@@ -128,35 +128,50 @@ void AMyCharacter::Tick(float DeltaTime)
|
||||
|
||||
if (bIsPlanting)
|
||||
{
|
||||
// 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
|
||||
const float SlotReachSquared = FMath::Square(200.f);
|
||||
|
||||
ASeedBedActor* ClosestActor = nullptr;
|
||||
float ClosestDistance = 9999999999.f;
|
||||
FIntVector2 ClosestSlotCoordinate = FIntVector2::NoneValue;
|
||||
float ClosestSlotDistance = SlotReachSquared;
|
||||
const FVector PointToCheck = GetActorLocation() + (GetActorForwardVector() * 100.f);
|
||||
const float ThresholdDist = FMath::Pow(1000.f, 2.f);
|
||||
|
||||
|
||||
for (ASeedBedActor* SeedBeds : SeedBedActors)
|
||||
{
|
||||
const double Dist = FVector::DistSquaredXY(PointToCheck, SeedBeds->GetActorLocation());
|
||||
if (Dist <= ClosestDistance && Dist <= ThresholdDist)
|
||||
if (!IsValid(SeedBeds))
|
||||
{
|
||||
ClosestDistance = Dist;
|
||||
ClosestActor = SeedBeds;
|
||||
continue;
|
||||
}
|
||||
|
||||
FIntVector2 OutSlotCoordinate;
|
||||
float OutSlotDistance = 0.f;
|
||||
if (!SeedBeds->FindClosestFreeSlotWithDistance(PointToCheck, OutSlotCoordinate, OutSlotDistance))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// A bed is only a candidate while its closest free slot is in reach, the closest slot wins
|
||||
if (OutSlotDistance > ClosestSlotDistance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ClosestSlotDistance = OutSlotDistance;
|
||||
ClosestSlotCoordinate = OutSlotCoordinate;
|
||||
ClosestActor = SeedBeds;
|
||||
}
|
||||
|
||||
|
||||
if (LastClosestSeedBedActor)
|
||||
{
|
||||
LastClosestSeedBedActor->StopHighlightingSlot();
|
||||
}
|
||||
|
||||
|
||||
if (ClosestActor)
|
||||
{
|
||||
FIntVector2 OutSlotCoordinate;
|
||||
if (ClosestActor->FindClosestFreeSlot(PointToCheck, OutSlotCoordinate))
|
||||
{
|
||||
ClosestActor->HighlightSlot(OutSlotCoordinate);
|
||||
}
|
||||
ClosestActor->HighlightSlot(ClosestSlotCoordinate);
|
||||
}
|
||||
|
||||
|
||||
LastClosestSeedBedActor = ClosestActor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +101,9 @@ private:
|
||||
|
||||
UPROPERTY()
|
||||
USelectionManager* SelectionManagerInventorySlots;
|
||||
|
||||
UPROPERTY()
|
||||
FGuid MovementDisabledEffect;
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
@@ -108,8 +111,14 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
public:
|
||||
|
||||
// Enable or disable movement with a character tag
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void ToggleMovement(bool bActive);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure)
|
||||
FORCEINLINE USelectionManager* GetSelectionManagerInventorySlot() { return SelectionManagerInventorySlots; }
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ public:
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ability System|Effects")
|
||||
TSubclassOf<UGameplayStatEffect> ExpIncreaseEffectClass;
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ability System|Effects")
|
||||
TSubclassOf<UGameplayStatEffect> MovementDisableEffectClass;
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Ability System|Professions")
|
||||
TArray<float> ProfessionExpArray;
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
|
||||
#include "EleriGameplayTags.h"
|
||||
|
||||
namespace TimeOfDay {
|
||||
namespace CharacterState
|
||||
{
|
||||
UE_DEFINE_GAMEPLAY_TAG(MovementDisabled, TEXT("CharacterState.MovementDisabled"))
|
||||
}
|
||||
|
||||
namespace TimeOfDay
|
||||
{
|
||||
UE_DEFINE_GAMEPLAY_TAG(TimePassed, TEXT("TimeOfDay.TimePassed"))
|
||||
}
|
||||
|
||||
namespace Stats {
|
||||
namespace Stats
|
||||
{
|
||||
UE_DEFINE_GAMEPLAY_TAG(Energy, TEXT("Stats.Energy"))
|
||||
UE_DEFINE_GAMEPLAY_TAG(TimesEatenToday, TEXT("Stats.TimesEatenToday"))
|
||||
UE_DEFINE_GAMEPLAY_TAG(FriendPointsObtainAmount, TEXT("Stats.FriendPointsObtainAmount"))
|
||||
|
||||
@@ -2,14 +2,21 @@
|
||||
#pragma once
|
||||
#include "NativeGameplayTags.h"
|
||||
|
||||
namespace TimeOfDay {
|
||||
namespace CharacterState
|
||||
{
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(MovementDisabled)
|
||||
}
|
||||
|
||||
namespace TimeOfDay
|
||||
{
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TimePassed)
|
||||
}
|
||||
|
||||
namespace Stats {
|
||||
namespace Stats
|
||||
{
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Energy)
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TimesEatenToday)
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(FriendPointsObtainAmount)
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(GatheringDoubleDropChance)
|
||||
PROJECTELERI_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(GatheringHqDropChance)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user