From 11f051c830dd4a7855130836640d09c4b59afca0 Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 18 May 2026 13:27:25 -0700 Subject: [PATCH] Add MVP respawn command --- AGRARIAN_DEVELOPMENT_ROADMAP.md | 6 ++- Scripts/verify_mvp_respawn_rules.py | 36 +++++++++++++++++ .../AgrarianGamePlayerController.cpp | 39 +++++++++++++++++++ .../AgrarianGamePlayerController.h | 6 +++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 Scripts/verify_mvp_respawn_rules.py diff --git a/AGRARIAN_DEVELOPMENT_ROADMAP.md b/AGRARIAN_DEVELOPMENT_ROADMAP.md index d4a0e44..cb00b5f 100644 --- a/AGRARIAN_DEVELOPMENT_ROADMAP.md +++ b/AGRARIAN_DEVELOPMENT_ROADMAP.md @@ -660,7 +660,11 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe `LastDeathReason` state, health depletion latches death, ordinary healing cannot revive a dead character, `Revive` provides an explicit respawn/admin hook, and debug HUD/console survival output show alive/dead state. -- [ ] Add respawn rules for MVP. +- [x] Add respawn rules for MVP. Added server-authoritative + `AgrarianRespawn`, available only after death, that returns the character to + the Ground Zero MVP spawn/home location, revives with partial health, + stabilizes hunger/thirst/body temperature, clears acute injury conditions, + and leaves family/inheritance respawn for later generational milestones. - [ ] Add corpse/backpack placeholder if needed. - [ ] Add replicated death feedback. diff --git a/Scripts/verify_mvp_respawn_rules.py b/Scripts/verify_mvp_respawn_rules.py new file mode 100644 index 0000000..b7f366e --- /dev/null +++ b/Scripts/verify_mvp_respawn_rules.py @@ -0,0 +1,36 @@ +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" / "AgrarianGamePlayerController.h" + source = ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp" + roadmap = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md" + + require(header, "void AgrarianRespawn();") + require(header, "void ServerAgrarianRespawn();") + require(source, "void AAgrarianGamePlayerController::AgrarianRespawn()") + require(source, "void AAgrarianGamePlayerController::ServerAgrarianRespawn_Implementation()") + require(source, "if (!SurvivalComponent->IsDead())") + require(source, "AgrarianRespawn is only available after death") + require(source, "StopMovementImmediately();") + require(source, "SetActorLocation(GroundZeroDeveloperTravelHomeLocation") + require(source, "SurvivalComponent->Revive(60.0f);") + require(source, "SurvivalComponent->ReduceBleeding(100.0f);") + require(source, "SurvivalComponent->ReduceSprain(100.0f);") + require(source, "Agrarian MVP respawn complete") + require(roadmap, "[x] Add respawn rules for MVP.") + + print("PASS: MVP respawn rules are present.") + + +if __name__ == "__main__": + main() diff --git a/Source/AgrarianGame/AgrarianGamePlayerController.cpp b/Source/AgrarianGame/AgrarianGamePlayerController.cpp index 0b8b3a9..7d70b96 100644 --- a/Source/AgrarianGame/AgrarianGamePlayerController.cpp +++ b/Source/AgrarianGame/AgrarianGamePlayerController.cpp @@ -169,6 +169,11 @@ void AAgrarianGamePlayerController::AgrarianHeal() ServerAgrarianHeal(); } +void AAgrarianGamePlayerController::AgrarianRespawn() +{ + ServerAgrarianRespawn(); +} + void AAgrarianGamePlayerController::AgrarianDropItem(FName ItemId, int32 Quantity) { if (ItemId == NAME_None || Quantity <= 0) @@ -333,6 +338,40 @@ void AAgrarianGamePlayerController::ServerAgrarianHeal_Implementation() ClientMessage(TEXT("Agrarian survival restored.")); } +void AAgrarianGamePlayerController::ServerAgrarianRespawn_Implementation() +{ + AAgrarianGameCharacter* AgrarianCharacter = GetPawn(); + UAgrarianSurvivalComponent* SurvivalComponent = AgrarianCharacter ? AgrarianCharacter->GetSurvivalComponent() : nullptr; + if (!AgrarianCharacter || !SurvivalComponent) + { + ClientMessage(TEXT("No Agrarian character/survival component found.")); + return; + } + + if (!SurvivalComponent->IsDead()) + { + ClientMessage(TEXT("AgrarianRespawn is only available after death. Use AgrarianHeal for admin recovery.")); + return; + } + + if (UCharacterMovementComponent* MovementComponent = AgrarianCharacter->GetCharacterMovement()) + { + MovementComponent->StopMovementImmediately(); + } + + AgrarianCharacter->SetActorLocation(GroundZeroDeveloperTravelHomeLocation, false, nullptr, ETeleportType::TeleportPhysics); + SurvivalComponent->Revive(60.0f); + SurvivalComponent->AddFood(35.0f); + SurvivalComponent->AddWater(35.0f); + SurvivalComponent->ReduceExhaustion(100.0f); + SurvivalComponent->ReduceInjury(100.0f); + SurvivalComponent->ReduceBleeding(100.0f); + SurvivalComponent->ReduceSprain(100.0f); + SurvivalComponent->ReduceSickness(100.0f); + SurvivalComponent->AddWarmth(37.0f - SurvivalComponent->Survival.BodyTemperature); + ClientMessage(TEXT("Agrarian MVP respawn complete: returned to Ground Zero with acute conditions stabilized.")); +} + void AAgrarianGamePlayerController::ServerAgrarianDropItem_Implementation(FName ItemId, int32 Quantity) { AAgrarianGameCharacter* AgrarianCharacter = GetPawn(); diff --git a/Source/AgrarianGame/AgrarianGamePlayerController.h b/Source/AgrarianGame/AgrarianGamePlayerController.h index 83e31f2..fbce13d 100644 --- a/Source/AgrarianGame/AgrarianGamePlayerController.h +++ b/Source/AgrarianGame/AgrarianGamePlayerController.h @@ -66,6 +66,9 @@ public: UFUNCTION(Exec) void AgrarianHeal(); + UFUNCTION(Exec) + void AgrarianRespawn(); + UFUNCTION(Exec) void AgrarianDropItem(FName ItemId, int32 Quantity); @@ -100,6 +103,9 @@ protected: UFUNCTION(Server, Reliable) void ServerAgrarianHeal(); + UFUNCTION(Server, Reliable) + void ServerAgrarianRespawn(); + UFUNCTION(Server, Reliable) void ServerAgrarianDropItem(FName ItemId, int32 Quantity);