Add replicated death feedback

This commit is contained in:
2026-05-18 13:37:11 -07:00
parent e8f4acb98d
commit dce4f77d93
5 changed files with 56 additions and 1 deletions
+4 -1
View File
@@ -670,7 +670,10 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
inventory loss is not active yet. Future corpse/backpack recovery is reserved inventory loss is not active yet. Future corpse/backpack recovery is reserved
as a persistent, server-owned, interaction-gated death-recovery record once as a persistent, server-owned, interaction-gated death-recovery record once
inventory loss and decay rules exist. inventory loss and decay rules exist.
- [ ] Add replicated death feedback. - [x] Add replicated death feedback. Survival now exposes
`OnDeathStateChanged` for UI/audio/animation hooks when replicated
alive/dead state or death reason changes, and the debug HUD shows the
replicated death reason while dead.
## 0.1.K Wildlife Prototype ## 0.1.K Wildlife Prototype
@@ -0,0 +1,34 @@
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:
header = ROOT / "Source" / "AgrarianGame" / "AgrarianSurvivalComponent.h"
source = ROOT / "Source" / "AgrarianGame" / "AgrarianSurvivalComponent.cpp"
hud = ROOT / "Source" / "AgrarianGame" / "AgrarianDebugHUD.cpp"
roadmap = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md"
require(header, "DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAgrarianDeathStateChangedSignature")
require(header, "FAgrarianDeathStateChangedSignature OnDeathStateChanged;")
require(header, "bool bLastBroadcastDeathState = false;")
require(header, "FName LastBroadcastDeathReason = NAME_None;")
require(source, "OnSurvivalChanged.Broadcast(Survival);")
require(source, "bLastBroadcastDeathState != Survival.bIsDead")
require(source, "LastBroadcastDeathReason != Survival.LastDeathReason")
require(source, "OnDeathStateChanged.Broadcast(Survival.bIsDead, Survival.LastDeathReason);")
require(hud, "Death: %s")
require(roadmap, "[x] Add replicated death feedback.")
print("PASS: replicated death feedback is present.")
if __name__ == "__main__":
main()
+4
View File
@@ -336,6 +336,10 @@ void AAgrarianDebugHUD::DrawSurvival(const UAgrarianSurvivalComponent* SurvivalC
DrawLine(FString::Printf(TEXT("Thirst: %.0f"), Survival.Thirst), X, Y); DrawLine(FString::Printf(TEXT("Thirst: %.0f"), Survival.Thirst), X, Y);
DrawLine(FString::Printf(TEXT("Temp: %.1f C"), Survival.BodyTemperature), X, Y); DrawLine(FString::Printf(TEXT("Temp: %.1f C"), Survival.BodyTemperature), X, Y);
DrawLine(FString::Printf(TEXT("State: %s"), Survival.bIsDead ? TEXT("DEAD") : TEXT("ALIVE")), X, Y, Survival.bIsDead ? FColor::Red : FColor::Green); DrawLine(FString::Printf(TEXT("State: %s"), Survival.bIsDead ? TEXT("DEAD") : TEXT("ALIVE")), X, Y, Survival.bIsDead ? FColor::Red : FColor::Green);
if (Survival.bIsDead)
{
DrawLine(FString::Printf(TEXT("Death: %s"), *Survival.LastDeathReason.ToString()), X, Y, FColor::Red);
}
DrawLine(FString::Printf(TEXT("Shelter: %.0f%%"), SurvivalComponent->CurrentWeatherProtection * 100.0f), X, Y); 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("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("Injury: %.0f"), Survival.InjurySeverity), X, Y);
@@ -482,6 +482,13 @@ void UAgrarianSurvivalComponent::ClampCareHistory()
void UAgrarianSurvivalComponent::BroadcastSurvivalChanged() void UAgrarianSurvivalComponent::BroadcastSurvivalChanged()
{ {
OnSurvivalChanged.Broadcast(Survival); OnSurvivalChanged.Broadcast(Survival);
if (bLastBroadcastDeathState != Survival.bIsDead || LastBroadcastDeathReason != Survival.LastDeathReason)
{
bLastBroadcastDeathState = Survival.bIsDead;
LastBroadcastDeathReason = Survival.LastDeathReason;
OnDeathStateChanged.Broadcast(Survival.bIsDead, Survival.LastDeathReason);
}
} }
void UAgrarianSurvivalComponent::UpdateDeathState() void UAgrarianSurvivalComponent::UpdateDeathState()
@@ -8,6 +8,7 @@
#include "AgrarianSurvivalComponent.generated.h" #include "AgrarianSurvivalComponent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAgrarianSurvivalChangedSignature, const FAgrarianSurvivalSnapshot&, Snapshot); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAgrarianSurvivalChangedSignature, const FAgrarianSurvivalSnapshot&, Snapshot);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FAgrarianDeathStateChangedSignature, bool, bIsDead, FName, DeathReason);
UCLASS(ClassGroup = (Agrarian), BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent)) UCLASS(ClassGroup = (Agrarian), BlueprintType, Blueprintable, meta = (BlueprintSpawnableComponent))
class UAgrarianSurvivalComponent : public UActorComponent class UAgrarianSurvivalComponent : public UActorComponent
@@ -24,6 +25,9 @@ public:
UPROPERTY(BlueprintAssignable, Category = "Agrarian|Survival") UPROPERTY(BlueprintAssignable, Category = "Agrarian|Survival")
FAgrarianSurvivalChangedSignature OnSurvivalChanged; FAgrarianSurvivalChangedSignature OnSurvivalChanged;
UPROPERTY(BlueprintAssignable, Category = "Agrarian|Survival")
FAgrarianDeathStateChangedSignature OnDeathStateChanged;
UPROPERTY(EditAnywhere, BlueprintReadOnly, ReplicatedUsing = OnRep_Survival, Category = "Agrarian|Survival") UPROPERTY(EditAnywhere, BlueprintReadOnly, ReplicatedUsing = OnRep_Survival, Category = "Agrarian|Survival")
FAgrarianSurvivalSnapshot Survival; FAgrarianSurvivalSnapshot Survival;
@@ -164,4 +168,7 @@ protected:
void ClampCareHistory(); void ClampCareHistory();
void UpdateDeathState(); void UpdateDeathState();
void BroadcastSurvivalChanged(); void BroadcastSurvivalChanged();
bool bLastBroadcastDeathState = false;
FName LastBroadcastDeathReason = NAME_None;
}; };