// Copyright Pacificao. All Rights Reserved. #include "AgrarianSurvivalComponent.h" #include "AgrarianGameState.h" #include "Engine/World.h" #include "Net/UnrealNetwork.h" UAgrarianSurvivalComponent::UAgrarianSurvivalComponent() { PrimaryComponentTick.bCanEverTick = true; SetIsReplicatedByDefault(true); } void UAgrarianSurvivalComponent::BeginPlay() { Super::BeginPlay(); ClampSurvival(); BroadcastSurvivalChanged(); } void UAgrarianSurvivalComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (!GetOwner() || !GetOwner()->HasAuthority() || !IsAlive()) { return; } const float Minutes = DeltaTime / 60.0f; Survival.Hunger -= HungerDecayPerMinute * Minutes; Survival.Thirst -= ThirstDecayPerMinute * Minutes; Survival.Stamina += StaminaRecoveryPerSecond * DeltaTime; if (const UWorld* World = GetWorld()) { if (const AAgrarianGameState* AgrarianGameState = World->GetGameState()) { const float ExposureDelta = (AgrarianGameState->AmbientTemperatureC - 18.0f) * 0.002f * DeltaTime; Survival.BodyTemperature += FMath::Clamp(ExposureDelta, -0.035f, 0.02f); } } if (Survival.Hunger <= 0.0f) { Survival.Health -= StarvationDamagePerMinute * Minutes; } if (Survival.Thirst <= 0.0f) { Survival.Health -= DehydrationDamagePerMinute * Minutes; } if (Survival.BodyTemperature < 35.0f) { Survival.Health -= ColdDamagePerMinute * Minutes; } ClampSurvival(); BroadcastSurvivalChanged(); } void UAgrarianSurvivalComponent::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME(UAgrarianSurvivalComponent, Survival); } bool UAgrarianSurvivalComponent::IsAlive() const { return Survival.Health > 0.0f; } void UAgrarianSurvivalComponent::ApplyDamage(float Amount) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.Health -= FMath::Max(0.0f, Amount); ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::RestoreHealth(float Amount) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.Health += FMath::Max(0.0f, Amount); ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::AddFood(float Amount) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.Hunger += FMath::Max(0.0f, Amount); ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::AddWater(float Amount) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.Thirst += FMath::Max(0.0f, Amount); ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::AddWarmth(float DegreesCelsius) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.BodyTemperature += DegreesCelsius; ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::AddInjury(float Severity) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.InjurySeverity += FMath::Max(0.0f, Severity); Survival.Health -= Severity * 5.0f; ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::SpendStamina(float Amount) { if (GetOwner() && GetOwner()->HasAuthority()) { Survival.Stamina -= FMath::Max(0.0f, Amount); ClampSurvival(); BroadcastSurvivalChanged(); } } void UAgrarianSurvivalComponent::OnRep_Survival() { BroadcastSurvivalChanged(); } void UAgrarianSurvivalComponent::ClampSurvival() { Survival.Health = FMath::Clamp(Survival.Health, 0.0f, 100.0f); Survival.Stamina = FMath::Clamp(Survival.Stamina, 0.0f, 100.0f); Survival.Hunger = FMath::Clamp(Survival.Hunger, 0.0f, 100.0f); Survival.Thirst = FMath::Clamp(Survival.Thirst, 0.0f, 100.0f); Survival.BodyTemperature = FMath::Clamp(Survival.BodyTemperature, 30.0f, 42.0f); Survival.InjurySeverity = FMath::Clamp(Survival.InjurySeverity, 0.0f, 100.0f); } void UAgrarianSurvivalComponent::BroadcastSurvivalChanged() { OnSurvivalChanged.Broadcast(Survival); }