Add bleeding survival placeholder
This commit is contained in:
@@ -641,7 +641,10 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
||||
## 0.1.J Injury And Basic Survival Consequences
|
||||
|
||||
- [x] Add generic injury state.
|
||||
- [ ] Add bleeding placeholder.
|
||||
- [x] Add bleeding placeholder. Survival now tracks replicated
|
||||
`BleedingSeverity`, applies lightweight health/exhaustion pressure while
|
||||
bleeding, adds bleeding from generic injuries, exposes add/reduce hooks, and
|
||||
shows bleeding in debug HUD and console survival output.
|
||||
- [ ] Add sprain or movement penalty placeholder.
|
||||
- [x] Add cold exposure damage.
|
||||
- [x] Add starvation damage.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def require(path: Path, snippet: str) -> None:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
if snippet not in text:
|
||||
raise SystemExit(f"{path.relative_to(ROOT)} missing {snippet!r}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
types = ROOT / "Source" / "AgrarianGame" / "AgrarianTypes.h"
|
||||
header = ROOT / "Source" / "AgrarianGame" / "AgrarianSurvivalComponent.h"
|
||||
source = ROOT / "Source" / "AgrarianGame" / "AgrarianSurvivalComponent.cpp"
|
||||
hud = ROOT / "Source" / "AgrarianGame" / "AgrarianDebugHUD.cpp"
|
||||
controller = ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp"
|
||||
roadmap = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md"
|
||||
|
||||
require(types, "float BleedingSeverity = 0.0f;")
|
||||
require(header, "float BleedingDamagePerMinute = 2.0f;")
|
||||
require(header, "float BleedingExhaustionPerSecond = 0.04f;")
|
||||
require(header, "void AddBleeding(float Severity);")
|
||||
require(header, "void ReduceBleeding(float Amount);")
|
||||
require(source, "Survival.Health -= BleedingDamagePerMinute * BleedingRatio * Minutes;")
|
||||
require(source, "Survival.Exhaustion += BleedingExhaustionPerSecond * BleedingRatio * DeltaTime;")
|
||||
require(source, "Survival.BleedingSeverity += PositiveSeverity * 0.35f;")
|
||||
require(source, "void UAgrarianSurvivalComponent::AddBleeding")
|
||||
require(source, "void UAgrarianSurvivalComponent::ReduceBleeding")
|
||||
require(source, "Survival.BleedingSeverity = FMath::Clamp(Survival.BleedingSeverity, 0.0f, 100.0f);")
|
||||
require(hud, "Bleeding")
|
||||
require(hud, "Bleed:")
|
||||
require(controller, "Bleeding %.1f")
|
||||
require(roadmap, "[x] Add bleeding placeholder.")
|
||||
|
||||
print("PASS: bleeding placeholder is present.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -109,6 +109,7 @@ void AAgrarianDebugHUD::DrawCriticalStats(const UAgrarianSurvivalComponent* Surv
|
||||
DrawScaledLine(FString::Printf(TEXT("Expose x%.2f %+3.1f C"), SurvivalComponent->CurrentWeatherExposureMultiplier, SurvivalComponent->CurrentWeatherTemperatureOffsetC), X, Y, CriticalStatsTextScale, SurvivalComponent->CurrentWeatherExposureMultiplier > 1.0f ? WarningColor : StableColor);
|
||||
DrawScaledLine(FString::Printf(TEXT("Exhaust %3.0f"), Survival.Exhaustion), X, Y, CriticalStatsTextScale, StatusColor(Survival.Exhaustion, true));
|
||||
DrawScaledLine(FString::Printf(TEXT("Injury %3.0f"), Survival.InjurySeverity), X, Y, CriticalStatsTextScale, StatusColor(Survival.InjurySeverity, true));
|
||||
DrawScaledLine(FString::Printf(TEXT("Bleeding %3.0f"), Survival.BleedingSeverity), X, Y, CriticalStatsTextScale, StatusColor(Survival.BleedingSeverity, true));
|
||||
DrawScaledLine(FString::Printf(TEXT("Sickness %3.0f"), Survival.SicknessSeverity), X, Y, CriticalStatsTextScale, StatusColor(Survival.SicknessSeverity, true));
|
||||
}
|
||||
|
||||
@@ -335,6 +336,7 @@ void AAgrarianDebugHUD::DrawSurvival(const UAgrarianSurvivalComponent* SurvivalC
|
||||
DrawLine(FString::Printf(TEXT("Shelter: %.0f%%"), SurvivalComponent->CurrentWeatherProtection * 100.0f), X, Y);
|
||||
DrawLine(FString::Printf(TEXT("Expose: x%.2f %+3.1f C"), SurvivalComponent->CurrentWeatherExposureMultiplier, SurvivalComponent->CurrentWeatherTemperatureOffsetC), X, Y);
|
||||
DrawLine(FString::Printf(TEXT("Injury: %.0f"), Survival.InjurySeverity), X, Y);
|
||||
DrawLine(FString::Printf(TEXT("Bleed: %.0f"), Survival.BleedingSeverity), X, Y);
|
||||
DrawLine(FString::Printf(TEXT("Sick: %.0f"), Survival.SicknessSeverity), X, Y);
|
||||
const FAgrarianCareHistorySnapshot& Care = SurvivalComponent->CareHistory;
|
||||
DrawLine(FString::Printf(TEXT("Care N/S/T: %.2f %.2f %.2f"), Care.NutritionQuality, Care.SleepQuality, Care.TreatmentQuality), X, Y, FColor::Silver);
|
||||
|
||||
@@ -147,7 +147,7 @@ void AAgrarianGamePlayerController::AgrarianSurvival()
|
||||
|
||||
const FAgrarianSurvivalSnapshot& Survival = SurvivalComponent->Survival;
|
||||
ClientMessage(FString::Printf(
|
||||
TEXT("Health %.1f | Stamina %.1f | Exhaustion %.1f | Hunger %.1f | Thirst %.1f | Temp %.1fC | Injury %.1f | Sickness %.1f"),
|
||||
TEXT("Health %.1f | Stamina %.1f | Exhaustion %.1f | Hunger %.1f | Thirst %.1f | Temp %.1fC | Injury %.1f | Bleeding %.1f | Sickness %.1f"),
|
||||
Survival.Health,
|
||||
Survival.Stamina,
|
||||
Survival.Exhaustion,
|
||||
@@ -155,6 +155,7 @@ void AAgrarianGamePlayerController::AgrarianSurvival()
|
||||
Survival.Thirst,
|
||||
Survival.BodyTemperature,
|
||||
Survival.InjurySeverity,
|
||||
Survival.BleedingSeverity,
|
||||
Survival.SicknessSeverity));
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,14 @@ void UAgrarianSurvivalComponent::TickComponent(float DeltaTime, ELevelTick TickT
|
||||
}
|
||||
}
|
||||
|
||||
if (Survival.BleedingSeverity > 0.0f)
|
||||
{
|
||||
const float BleedingRatio = Survival.BleedingSeverity / 100.0f;
|
||||
Survival.Health -= BleedingDamagePerMinute * BleedingRatio * Minutes;
|
||||
Survival.Exhaustion += BleedingExhaustionPerSecond * BleedingRatio * DeltaTime;
|
||||
CareHistory.InjuryBurden += BleedingRatio * 0.001f * DeltaTime;
|
||||
}
|
||||
|
||||
if (const UWorld* World = GetWorld())
|
||||
{
|
||||
if (const AAgrarianGameState* AgrarianGameState = World->GetGameState<AAgrarianGameState>())
|
||||
@@ -170,9 +178,11 @@ void UAgrarianSurvivalComponent::AddInjury(float Severity)
|
||||
{
|
||||
if (GetOwner() && GetOwner()->HasAuthority())
|
||||
{
|
||||
Survival.InjurySeverity += FMath::Max(0.0f, Severity);
|
||||
CareHistory.InjuryBurden += FMath::Max(0.0f, Severity) / 100.0f;
|
||||
Survival.Health -= Severity * 5.0f;
|
||||
const float PositiveSeverity = FMath::Max(0.0f, Severity);
|
||||
Survival.InjurySeverity += PositiveSeverity;
|
||||
Survival.BleedingSeverity += PositiveSeverity * 0.35f;
|
||||
CareHistory.InjuryBurden += PositiveSeverity / 100.0f;
|
||||
Survival.Health -= PositiveSeverity * 5.0f;
|
||||
ClampSurvival();
|
||||
ClampCareHistory();
|
||||
BroadcastSurvivalChanged();
|
||||
@@ -189,6 +199,29 @@ void UAgrarianSurvivalComponent::ReduceInjury(float Amount)
|
||||
}
|
||||
}
|
||||
|
||||
void UAgrarianSurvivalComponent::AddBleeding(float Severity)
|
||||
{
|
||||
if (GetOwner() && GetOwner()->HasAuthority())
|
||||
{
|
||||
const float PositiveSeverity = FMath::Max(0.0f, Severity);
|
||||
Survival.BleedingSeverity += PositiveSeverity;
|
||||
CareHistory.InjuryBurden += PositiveSeverity / 200.0f;
|
||||
ClampSurvival();
|
||||
ClampCareHistory();
|
||||
BroadcastSurvivalChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void UAgrarianSurvivalComponent::ReduceBleeding(float Amount)
|
||||
{
|
||||
if (GetOwner() && GetOwner()->HasAuthority())
|
||||
{
|
||||
Survival.BleedingSeverity -= FMath::Max(0.0f, Amount);
|
||||
ClampSurvival();
|
||||
BroadcastSurvivalChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void UAgrarianSurvivalComponent::AddSickness(float Severity)
|
||||
{
|
||||
if (GetOwner() && GetOwner()->HasAuthority())
|
||||
@@ -362,6 +395,7 @@ void UAgrarianSurvivalComponent::ClampSurvival()
|
||||
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);
|
||||
Survival.BleedingSeverity = FMath::Clamp(Survival.BleedingSeverity, 0.0f, 100.0f);
|
||||
Survival.SicknessSeverity = FMath::Clamp(Survival.SicknessSeverity, 0.0f, 100.0f);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,12 @@ public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Survival|Rates", meta = (ClampMin = "0"))
|
||||
float SicknessRecoveryPerSecond = 0.02f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Survival|Rates", meta = (ClampMin = "0"))
|
||||
float BleedingDamagePerMinute = 2.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Survival|Rates", meta = (ClampMin = "0"))
|
||||
float BleedingExhaustionPerSecond = 0.04f;
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Survival")
|
||||
bool IsAlive() const;
|
||||
|
||||
@@ -96,6 +102,12 @@ public:
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Survival")
|
||||
void ReduceInjury(float Amount);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Survival")
|
||||
void AddBleeding(float Severity);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Survival")
|
||||
void ReduceBleeding(float Amount);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category = "Agrarian|Survival")
|
||||
void AddSickness(float Severity);
|
||||
|
||||
|
||||
@@ -354,6 +354,9 @@ struct FAgrarianSurvivalSnapshot
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Survival")
|
||||
float InjurySeverity = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Survival")
|
||||
float BleedingSeverity = 0.0f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Agrarian|Survival")
|
||||
float SicknessSeverity = 0.0f;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user