Implement prototype: venue-driven simulation core, scenarios, tests, and playable entrance scene
CI / headless-tests (push) Canceled after 49s
CI / headless-tests (push) Canceled after 49s
- Godot 4.3 project scaffold with first-person guard, procedural world, interaction HUD, access inspection, radio forms, debug overlay, shift review - Simulation core: ShiftCoordinator, VenueScenario, EventScheduler, NPCController/FSM, AccessVerifier, EscalationManager, RadioSystem, IncidentRecorder, ReputationEvaluator, CrowdSystem, EventBus - Three authored scenarios (Hollywood Blvd building, The Joke Shop, TV studio) - Custom headless test runner (25 tests) replacing editor-dependent GUT, plus GitHub Actions CI - Documentation workflow live: README, PLAN (tech stack), TODO/DONE, MEMORY
This commit is contained in:
1 parent
e23f284ad4
commit
439e0a4281
45 files changed
+4368
-7
No files matched your search
@@ -0,0 +1,77 @@
|
||||
class_name ShiftReview
|
||||
extends CanvasLayer
|
||||
## End-of-shift review screen (PLAN.md: Evidence and Body Camera, Shift Review).
|
||||
|
||||
signal restart_requested()
|
||||
|
||||
var report_label: Label
|
||||
|
||||
func _init() -> void:
|
||||
name = "ShiftReview"
|
||||
layer = 30
|
||||
var dim := ColorRect.new()
|
||||
dim.color = Color(0.04, 0.05, 0.08, 0.92)
|
||||
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
add_child(dim)
|
||||
|
||||
var center := VBoxContainer.new()
|
||||
center.set_anchors_preset(Control.PRESET_CENTER)
|
||||
center.alignment = BoxContainer.ALIGNMENT_CENTER
|
||||
center.add_theme_constant_override("separation", 12)
|
||||
add_child(center)
|
||||
|
||||
var title := Label.new()
|
||||
title.text = "Shift Review"
|
||||
title.add_theme_font_size_override("font_size", 28)
|
||||
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
center.add_child(title)
|
||||
|
||||
report_label = Label.new()
|
||||
report_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
report_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
report_label.custom_minimum_size = Vector2(720, 0)
|
||||
center.add_child(report_label)
|
||||
|
||||
var restart := Button.new()
|
||||
restart.text = "Run another shift"
|
||||
restart.pressed.connect(func(): restart_requested.emit())
|
||||
restart.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
center.add_child(restart)
|
||||
|
||||
var quit_btn := Button.new()
|
||||
quit_btn.text = "Quit"
|
||||
quit_btn.pressed.connect(func(): get_tree().quit())
|
||||
quit_btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
|
||||
center.add_child(quit_btn)
|
||||
|
||||
func show_review(review: Dictionary, scenario: Resource) -> void:
|
||||
var reputation: Dictionary = review.get("reputation", {})
|
||||
var incidents: Dictionary = review.get("incidents", {})
|
||||
var crowd: Dictionary = review.get("crowd", {})
|
||||
var radio: Dictionary = review.get("radio", {})
|
||||
var incident_list: Array = incidents.get("incidents", [])
|
||||
var peaceful := 0
|
||||
for inc in incident_list:
|
||||
if inc.get("outcome", "") in ["peaceful", "left"]:
|
||||
peaceful += 1
|
||||
|
||||
var lines: Array[String] = [
|
||||
"Venue: %s" % (scenario.display_name if scenario else review.get("scenario_id", "")),
|
||||
"Grade: %s Score: %.0f/100" % [reputation.get("grade", "?"), reputation.get("rating", 0.0)],
|
||||
"Incidents handled: %d (peaceful %d)" % [incident_list.size(), peaceful],
|
||||
"NPCs encountered: %d" % review.get("spawned_count", 0),
|
||||
"Radio battery: %.0f%% emergency cooldown: %.0fs" % [radio.get("battery", 0.0), radio.get("emergency_cooldown_s", 0.0)],
|
||||
"Crowd mood: %.0f%% (panic: %s)" % [crowd.get("mood", 0.0) * 100.0, str(crowd.get("panic", false))],
|
||||
"",
|
||||
"Highlights:",
|
||||
]
|
||||
var mods: Array = reputation.get("modifiers", [])
|
||||
var shown := 0
|
||||
for mod in mods:
|
||||
var delta: float = float(mod.get("delta", 0.0))
|
||||
lines.append(" %s (%+.0f) %s" % [mod.get("category", ""), delta, mod.get("reason", "")])
|
||||
shown += 1
|
||||
if shown >= 12:
|
||||
break
|
||||
report_label.text = "\n".join(lines)
|
||||
visible = true
|
||||
Reference in new issue
Block a user