Author the missing scenario content from the PLAN lists
Joke Shop - Reservation list without ID (guest list valid, ID missing) — denied. - Borrowed/mismatched ID (ID valid but mismatched) — denied. - Guest who refuses the wand screen: new `refuses_screening` event flag, copied onto NPCController, handled in _toggle_wand_screening (logs wand.refused, records a wand_refused event, small prop hit, panel stays closed). - Late arrival during the performance (ID + ticket, "arrive" intent). Studio - Filming-boundary event and a later repeat, both using the new `film_boundary` intent which maps to `steps_end` so the influencer stands past the posted line. - Celebrity arrival now pulls in a small crowd via a new `extra_spawns` event field (two tourists + an influencer), spawned through the normal path. Building - Filming-boundary event whose hint points at the body camera and request-reason verbs, plus an unclear-intent event that hints at asking for a reason. Engine support - Events may carry `hint` (string key logged on spawn), `extra_spawns`, and `refuses_screening`; 9 new localized hint strings. Tests/docs - Headless suite 139 -> 149 (test_scenario_content.gd) and a new smoke_scenario_content.gd that spawns the refusal and celebrity events through the real signal path. - README, TODO section moved to DONE, MEMORY. Version 0.2.13.
This commit is contained in:
1 parent
922a990c7a
commit
a2a0ded527
12 files changed
+426
-18
No files matched your search
@@ -479,8 +479,19 @@ func _spawn_npc(profile: NpcProfile, intent: String, npc_id: String, event: Dict
|
||||
# Authored events stay for the whole shift; routine traffic cycles out.
|
||||
avatar.ephemeral = event.get("kind", "routine") == "routine"
|
||||
avatar.lifetime_s = 45.0 + float((npc_counter * 17) % 60)
|
||||
avatar.get_npc_controller().refuses_screening = bool(event.get("refuses_screening", false))
|
||||
scene_root.add_child(avatar)
|
||||
npcs.append(avatar)
|
||||
# Authored events can point the player at the right verb (PLAN.md verbs).
|
||||
if event.has("hint") and hud:
|
||||
hud.log(Strings.lookup(str(event["hint"])))
|
||||
# Celebrity arrivals draw extra bystanders, not just one avatar.
|
||||
for extra in event.get("extra_spawns", []):
|
||||
var extra_profile := selected_scenario.profile_for(extra.get("npc_type", Rules.NpcType.TOURIST))
|
||||
if extra_profile == null or npcs.size() >= MAX_LIVE_NPCS:
|
||||
continue
|
||||
_spawn_npc(extra_profile, str(extra.get("intent", "photo")),
|
||||
"%s_w%d" % [npc_id, npcs.size()], {"kind": "routine"})
|
||||
|
||||
## Drop references to freed avatars so the cap and Tab cycling stay accurate.
|
||||
func _purge_npcs() -> void:
|
||||
@@ -1238,6 +1249,16 @@ func _toggle_wand_screening() -> void:
|
||||
var controller: Object = _targeted_controller()
|
||||
if controller == null:
|
||||
return
|
||||
if controller.refuses_screening:
|
||||
# Authored event: this guest refuses the screen (Joke Shop content).
|
||||
hud.set_wand_icon(false)
|
||||
hud.log(Strings.fmt("wand.refused", [controller.profile.display_name if controller.profile else "The guest"]))
|
||||
coordinator.recorder.add_event(controller.npc_id, {
|
||||
"type": "wand_refused",
|
||||
"outcome": "refused",
|
||||
})
|
||||
coordinator.reputation.apply("prop", -1.0, "guest refused screening")
|
||||
return
|
||||
var profile: Object = controller.profile
|
||||
var items: Array = profile.carried_items if profile else []
|
||||
var result: Dictionary = wand_screener.screen(items)
|
||||
|
||||
Reference in new issue
Block a user