Audit and fix NPC, door-staff and UI dialogue
Full build / Import + headless tests (push) Successful in 40s
Full build / Full desktop build + optional release (push) Skipped

- Route the Reason verb through authored reason contexts and give every shared archetype an in-character answer.
- Add Hollywood wristband and TV Studio ticket/credential door-staff lines.
- Clarify radio cancellation, Ask terminology, start hints and campaign-reset copy.
- Record the dialogue audit and length findings in docs/ui-copy.md; add regression tests.
This commit is contained in:
Gig Line Dev committed 2026-11-02 14:44:01 +01:00
1 parent daf0926d91
commit 98c31fe44c
15 files changed
+232 -30

No files matched your search

+11
View File
@@ -18,6 +18,17 @@ func test_context_lines_are_deterministic_and_fallback() -> bool:
"unknown context with no fallback is empty")
return d and e and f
func test_every_shared_profile_answers_reason() -> bool:
var rng := RandomNumberGenerator.new()
rng.seed = 11
var problems: Array[String] = []
for profile in ScenarioFactory.shared_profiles():
var reply := profile.line_for("reason", rng)
if reply.strip_edges() == "":
problems.append(str(profile.id))
return TestUtils.check(problems.is_empty(),
"every shared profile has an in-character reason answer (%s)" % str(problems))
func test_request_reason_uses_reason_context() -> bool:
var profile := ScenarioFactory.hollywood_building().profile_for(0)
var controller := NpcController.new()
+12
View File
@@ -58,6 +58,18 @@ func test_request_reason_uses_dialogue_lines() -> bool:
npc = null
return a and b and c
func test_request_reason_prefers_the_reason_context() -> bool:
var p := _profile("Visitor", ["I have a ticket for tonight."])
p.context_lines = {"reason": ["I'm here for the show."]}
var npc := NPCController.new()
npc.setup("npc_reason", p, "enter", 4242)
var a := TestUtils.check_eq(npc.request_reason(), "I'm here for the show.",
"reason context overrides the generic dialogue lines")
var b := TestUtils.check_eq(npc.last_reason_reply, "I'm here for the show.",
"the selected reason is stored for the timeline")
npc = null
return a and b
func test_request_reason_silent_without_lines() -> bool:
var npc := NPCController.new()
npc.setup("npc_2", _profile("Silent"), "enter", 7)
+7 -2
View File
@@ -75,7 +75,12 @@ func test_door_staff_lines_available() -> bool:
var a := TestUtils.check(ok, "all joke-shop contexts have a door-staff line")
var b := TestUtils.check_eq(scenario.door_staff_line("unknown_context", rng), "", "unknown context returns empty")
var b_country := ScenarioFactory.hollywood_building()
var c := TestUtils.check_eq(b_country.door_staff_line("refusal", rng), "", "venue without lines returns empty")
var c := TestUtils.check_eq(b_country.door_staff_line("refusal", rng), "", "venue without that context returns empty")
var e := TestUtils.check(b_country.door_staff_line("wristband_check", rng) != "",
"Hollywood has a wristband door line")
var studio := ScenarioFactory.tv_studio()
var f := TestUtils.check(studio.door_staff_line("ticket_check", rng) != "",
"Studio has a ticket/credential door line")
# Same seed picks the same line.
var r0 := RandomNumberGenerator.new()
r0.seed = 11
@@ -85,7 +90,7 @@ func test_door_staff_lines_available() -> bool:
scenario.door_staff_line("wand_check", r0),
scenario.door_staff_line("wand_check", r1),
"seeded door-staff pick is deterministic")
return a and b and c and d
return a and b and c and d and e and f
func test_protester_archetype_present() -> bool:
var profiles := ScenarioFactory.shared_profiles()