#!/usr/bin/env python3 """Verify the MVP survival-pressure death QA gate is covered.""" from pathlib import Path ROOT = Path(__file__).resolve().parents[1] ROADMAP = ROOT / "AGRARIAN_DEVELOPMENT_ROADMAP.md" QA_DOC = ROOT / "Docs" / "QA" / "MvpQaGates.md" TYPES_H = ROOT / "Source" / "AgrarianGame" / "AgrarianTypes.h" SURVIVAL_H = ROOT / "Source" / "AgrarianGame" / "AgrarianSurvivalComponent.h" SURVIVAL_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianSurvivalComponent.cpp" HUD_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianDebugHUD.cpp" CONTROLLER_CPP = ROOT / "Source" / "AgrarianGame" / "AgrarianGamePlayerController.cpp" DEATH_VERIFY = ROOT / "Scripts" / "verify_death_state.py" REPLICATED_DEATH_VERIFY = ROOT / "Scripts" / "verify_replicated_death_feedback.py" RESPAWN_VERIFY = ROOT / "Scripts" / "verify_mvp_death_respawn_ui.py" STAT_SAVE_VERIFY = ROOT / "Scripts" / "verify_stat_save_load_support.py" REQUIRED = { QA_DOC: [ "## Survival Pressure Death", "Starvation, dehydration, cold exposure, sickness, and bleeding", "UpdateDeathState", "LastDeathReason", "death/respawn panel", ], TYPES_H: [ "bool bIsDead = false;", "FName LastDeathReason = NAME_None;", ], SURVIVAL_H: [ "float StarvationDamagePerMinute = 3.0f;", "float DehydrationDamagePerMinute = 5.0f;", "float ColdDamagePerMinute = 4.0f;", "float SicknessDamagePerMinute = 1.5f;", "float BleedingDamagePerMinute = 2.0f;", "void UpdateDeathState();", ], SURVIVAL_CPP: [ "Survival.Health -= StarvationDamagePerMinute * Minutes;", "Survival.Health -= DehydrationDamagePerMinute * Minutes;", "Survival.Health -= ColdDamagePerMinute * Minutes", "Survival.Health -= SicknessDamagePerMinute * (Survival.SicknessSeverity / 100.0f) * Minutes;", "Survival.Health -= BleedingDamagePerMinute * BleedingRatio * Minutes;", "UpdateDeathState();", "Survival.bIsDead = true;", "Survival.LastDeathReason = FName(TEXT(\"health_depleted\"));", "OnDeathStateChanged.Broadcast(Survival.bIsDead, Survival.LastDeathReason);", ], HUD_CPP: [ "YOU DID NOT SURVIVE", "Cause: %s", "State DEAD", ], CONTROLLER_CPP: [ "ServerAgrarianRespawn_Implementation", "SurvivalComponent->Revive", ], DEATH_VERIFY: ["PASS: death state is present."], REPLICATED_DEATH_VERIFY: ["replicated death feedback"], RESPAWN_VERIFY: ["MVP death/respawn UI verification"], STAT_SAVE_VERIFY: ["SavedPlayer.Survival", "ApplySavedState"], ROADMAP: [ "[x] Can die from survival pressure.", ], } def main() -> None: missing: list[str] = [] for path, snippets in REQUIRED.items(): text = path.read_text(encoding="utf-8") for snippet in snippets: if snippet not in text: missing.append(f"{path.relative_to(ROOT)} missing {snippet!r}") if missing: raise SystemExit("FAILED: " + "; ".join(missing)) print("OK: survival-pressure death QA gate is tied to damage, death, HUD, respawn, and persistence coverage.") if __name__ == "__main__": main()