Connect movement speed modifiers
This commit is contained in:
@@ -67,6 +67,8 @@ void AAgrarianGameCharacter::Tick(float DeltaSeconds)
|
||||
{
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
ApplyMovementSpeed();
|
||||
|
||||
if (!HasAuthority() || !bWantsToSprint)
|
||||
{
|
||||
return;
|
||||
@@ -80,7 +82,8 @@ void AAgrarianGameCharacter::Tick(float DeltaSeconds)
|
||||
|
||||
if (GetVelocity().SizeSquared2D() > KINDA_SMALL_NUMBER && SurvivalComponent)
|
||||
{
|
||||
SurvivalComponent->SpendStamina(SprintStaminaCostPerSecond * DeltaSeconds);
|
||||
const float EffectiveEndurance = FMath::Max(0.25f, EnduranceMultiplier);
|
||||
SurvivalComponent->SpendStamina((SprintStaminaCostPerSecond / EffectiveEndurance) * DeltaSeconds);
|
||||
if (!CanSprint())
|
||||
{
|
||||
SetWantsToSprint(false);
|
||||
@@ -92,6 +95,11 @@ void AAgrarianGameCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty
|
||||
{
|
||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||
DOREPLIFETIME(AAgrarianGameCharacter, bWantsToSprint);
|
||||
DOREPLIFETIME(AAgrarianGameCharacter, AgeYears);
|
||||
DOREPLIFETIME(AAgrarianGameCharacter, PhysicalConditionMultiplier);
|
||||
DOREPLIFETIME(AAgrarianGameCharacter, StrengthMultiplier);
|
||||
DOREPLIFETIME(AAgrarianGameCharacter, EnduranceMultiplier);
|
||||
DOREPLIFETIME(AAgrarianGameCharacter, TerrainMovementMultiplier);
|
||||
}
|
||||
|
||||
void AAgrarianGameCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
|
||||
@@ -235,14 +243,116 @@ bool AAgrarianGameCharacter::IsSprinting() const
|
||||
return bWantsToSprint && CanSprint();
|
||||
}
|
||||
|
||||
float AAgrarianGameCharacter::GetCurrentCarryWeight() const
|
||||
{
|
||||
return InventoryComponent ? InventoryComponent->GetTotalWeight() : 0.0f;
|
||||
}
|
||||
|
||||
float AAgrarianGameCharacter::GetCurrentMovementSpeedMultiplier() const
|
||||
{
|
||||
return CalculateMovementSpeedMultiplier();
|
||||
}
|
||||
|
||||
void AAgrarianGameCharacter::SetTerrainMovementMultiplier(float NewTerrainMovementMultiplier)
|
||||
{
|
||||
TerrainMovementMultiplier = FMath::Clamp(NewTerrainMovementMultiplier, 0.25f, 1.25f);
|
||||
ApplyMovementSpeed();
|
||||
}
|
||||
|
||||
void AAgrarianGameCharacter::ApplyMovementSpeed()
|
||||
{
|
||||
if (UCharacterMovementComponent* MovementComponent = GetCharacterMovement())
|
||||
{
|
||||
MovementComponent->MaxWalkSpeed = IsSprinting() ? SprintSpeed : WalkSpeed;
|
||||
const float BaseSpeed = IsSprinting() ? SprintSpeed : WalkSpeed;
|
||||
MovementComponent->MaxWalkSpeed = FMath::Max(0.0f, BaseSpeed * CalculateMovementSpeedMultiplier());
|
||||
}
|
||||
}
|
||||
|
||||
float AAgrarianGameCharacter::CalculateMovementSpeedMultiplier() const
|
||||
{
|
||||
const float TraitMultiplier = FMath::Clamp(PhysicalConditionMultiplier, 0.25f, 1.25f)
|
||||
* FMath::Clamp(EnduranceMultiplier, 0.25f, 2.0f);
|
||||
|
||||
return FMath::Clamp(
|
||||
CalculateAgeMovementMultiplier()
|
||||
* TraitMultiplier
|
||||
* CalculateSurvivalMovementMultiplier()
|
||||
* CalculateCarryWeightMovementMultiplier()
|
||||
* FMath::Clamp(TerrainMovementMultiplier, 0.25f, 1.25f),
|
||||
0.15f,
|
||||
1.35f);
|
||||
}
|
||||
|
||||
float AAgrarianGameCharacter::CalculateAgeMovementMultiplier() const
|
||||
{
|
||||
if (AgeYears < 13.0f)
|
||||
{
|
||||
return 0.65f;
|
||||
}
|
||||
|
||||
if (AgeYears < 18.0f)
|
||||
{
|
||||
return FMath::GetMappedRangeValueClamped(FVector2D(13.0f, 18.0f), FVector2D(0.8f, 1.0f), AgeYears);
|
||||
}
|
||||
|
||||
if (AgeYears <= 50.0f)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (AgeYears <= 70.0f)
|
||||
{
|
||||
return FMath::GetMappedRangeValueClamped(FVector2D(50.0f, 70.0f), FVector2D(1.0f, 0.75f), AgeYears);
|
||||
}
|
||||
|
||||
return 0.65f;
|
||||
}
|
||||
|
||||
float AAgrarianGameCharacter::CalculateSurvivalMovementMultiplier() const
|
||||
{
|
||||
if (!SurvivalComponent || !SurvivalComponent->IsAlive())
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const FAgrarianSurvivalSnapshot& Survival = SurvivalComponent->Survival;
|
||||
const float HungerMultiplier = Survival.Hunger >= 50.0f
|
||||
? 1.0f
|
||||
: FMath::GetMappedRangeValueClamped(FVector2D(0.0f, 50.0f), FVector2D(0.85f, 1.0f), Survival.Hunger);
|
||||
const float ThirstMultiplier = Survival.Thirst >= 50.0f
|
||||
? 1.0f
|
||||
: FMath::GetMappedRangeValueClamped(FVector2D(0.0f, 50.0f), FVector2D(0.75f, 1.0f), Survival.Thirst);
|
||||
const float InjuryMultiplier = FMath::GetMappedRangeValueClamped(
|
||||
FVector2D(0.0f, 100.0f),
|
||||
FVector2D(1.0f, 0.5f),
|
||||
Survival.InjurySeverity);
|
||||
|
||||
return HungerMultiplier * ThirstMultiplier * InjuryMultiplier;
|
||||
}
|
||||
|
||||
float AAgrarianGameCharacter::CalculateCarryWeightMovementMultiplier() const
|
||||
{
|
||||
const float Strength = FMath::Clamp(StrengthMultiplier, 0.25f, 2.0f);
|
||||
const float EffectiveComfortWeight = ComfortableCarryWeight * Strength;
|
||||
const float EffectiveHeavyWeight = HeavyCarryWeight * Strength;
|
||||
const float CurrentCarryWeight = GetCurrentCarryWeight();
|
||||
|
||||
if (CurrentCarryWeight <= EffectiveComfortWeight || EffectiveHeavyWeight <= EffectiveComfortWeight)
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (CurrentCarryWeight >= EffectiveHeavyWeight)
|
||||
{
|
||||
return 0.45f;
|
||||
}
|
||||
|
||||
return FMath::GetMappedRangeValueClamped(
|
||||
FVector2D(EffectiveComfortWeight, EffectiveHeavyWeight),
|
||||
FVector2D(1.0f, 0.65f),
|
||||
CurrentCarryWeight);
|
||||
}
|
||||
|
||||
void AAgrarianGameCharacter::OnRep_SprintState()
|
||||
{
|
||||
ApplyMovementSpeed();
|
||||
|
||||
@@ -101,6 +101,34 @@ protected:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0", ClampMax = "100"))
|
||||
float MinSprintStamina = 5.0f;
|
||||
|
||||
/** Age hook used by movement until full lifecycle/aging systems own it. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0"))
|
||||
float AgeYears = 25.0f;
|
||||
|
||||
/** General physical condition scalar reserved for care, illness, sleep, and long-term state. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "1.25"))
|
||||
float PhysicalConditionMultiplier = 1.0f;
|
||||
|
||||
/** Strength scalar that mainly offsets carried-weight penalties. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "2.0"))
|
||||
float StrengthMultiplier = 1.0f;
|
||||
|
||||
/** Endurance scalar that improves stamina efficiency and movement resilience. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "2.0"))
|
||||
float EnduranceMultiplier = 1.0f;
|
||||
|
||||
/** Comfort carry capacity before speed penalties, in item-weight units. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0"))
|
||||
float ComfortableCarryWeight = 25.0f;
|
||||
|
||||
/** Severe carry capacity where movement is heavily reduced, in item-weight units. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0"))
|
||||
float HeavyCarryWeight = 60.0f;
|
||||
|
||||
/** Terrain hook for later surface/volume systems. Values below one slow the character. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0.25", ClampMax = "1.25"))
|
||||
float TerrainMovementMultiplier = 1.0f;
|
||||
|
||||
/** Third-person spring arm distance used when returning from first person. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Camera", meta = (ClampMin = "0"))
|
||||
float ThirdPersonCameraDistance = 400.0f;
|
||||
@@ -162,6 +190,13 @@ protected:
|
||||
/** Applies current walk or sprint speed to character movement. */
|
||||
void ApplyMovementSpeed();
|
||||
|
||||
/** Calculates the current multiplier from survival, carried weight, terrain, and placeholder traits. */
|
||||
float CalculateMovementSpeedMultiplier() const;
|
||||
|
||||
float CalculateAgeMovementMultiplier() const;
|
||||
float CalculateSurvivalMovementMultiplier() const;
|
||||
float CalculateCarryWeightMovementMultiplier() const;
|
||||
|
||||
UFUNCTION()
|
||||
void OnRep_SprintState();
|
||||
|
||||
@@ -195,6 +230,15 @@ public:
|
||||
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
||||
bool IsSprinting() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
||||
float GetCurrentCarryWeight() const;
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
||||
float GetCurrentMovementSpeedMultiplier() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Agrarian|Movement")
|
||||
void SetTerrainMovementMultiplier(float NewTerrainMovementMultiplier);
|
||||
|
||||
/** Server-authoritative interaction entry point. */
|
||||
UFUNCTION(Server, Reliable)
|
||||
void ServerInteract(AActor* TargetActor);
|
||||
|
||||
@@ -33,6 +33,16 @@ int32 UAgrarianInventoryComponent::GetItemCount(FName ItemId) const
|
||||
return Count;
|
||||
}
|
||||
|
||||
float UAgrarianInventoryComponent::GetTotalWeight() const
|
||||
{
|
||||
float TotalWeight = 0.0f;
|
||||
for (const FAgrarianItemStack& Stack : Items)
|
||||
{
|
||||
TotalWeight += FMath::Max(0.0f, Stack.UnitWeight) * FMath::Max(0, Stack.Quantity);
|
||||
}
|
||||
return TotalWeight;
|
||||
}
|
||||
|
||||
bool UAgrarianInventoryComponent::AddItem(const FAgrarianItemStack& Stack)
|
||||
{
|
||||
if (!GetOwner() || !GetOwner()->HasAuthority() || !Stack.IsValidStack())
|
||||
|
||||
@@ -34,6 +34,9 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Inventory")
|
||||
int32 GetItemCount(FName ItemId) const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Inventory")
|
||||
float GetTotalWeight() const;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Inventory")
|
||||
bool AddItem(const FAgrarianItemStack& Stack);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user