Implement NPC perception, returning trespassers, responder dispatch, wand screening, and accessibility polish
CI / headless-tests (push) Successful in 2m11s
CI / headless-tests (push) Successful in 2m11s
This commit is contained in:
1 parent
439e0a4281
commit
81b5d5ce5a
22 files changed
+879
-73
No files matched your search
+96
-1
@@ -4,6 +4,7 @@ extends CanvasLayer
|
||||
## event log, access inspection panel, and a debug overlay.
|
||||
|
||||
const Rules := preload("res://src/core/rules.gd")
|
||||
const Strings := preload("res://src/core/strings.gd")
|
||||
|
||||
var top_label: Label
|
||||
var time_label: Label
|
||||
@@ -14,6 +15,12 @@ var debug_label: Label
|
||||
var inspect_panel: PanelContainer
|
||||
var inspect_text: Label
|
||||
var inspect_meta: Label
|
||||
var radio_cooldown_label: Label
|
||||
var wand_panel: PanelContainer
|
||||
var wand_text: Label
|
||||
var wand_meta: Label
|
||||
var tone_label: Label
|
||||
var escalation_label: Label
|
||||
|
||||
var _debug_enabled := false
|
||||
var _log_lines: Array[String] = []
|
||||
@@ -72,11 +79,32 @@ func _init() -> void:
|
||||
vbox.add_child(bottom_spacer)
|
||||
|
||||
var controls := Label.new()
|
||||
controls.text = "Q polite direction · 1-3 simple gestures · 4 warning · 5 block · 6 assist · R emergency · E inspect / close · A allow · D deny · F debug"
|
||||
controls.text = Strings.lookup("hud.controls")
|
||||
controls.add_theme_font_size_override("font_size", 12)
|
||||
controls.modulate = Color(0.8, 0.8, 0.85)
|
||||
vbox.add_child(controls)
|
||||
|
||||
# --- emergency radio cooldown indicator ---
|
||||
radio_cooldown_label = Label.new()
|
||||
radio_cooldown_label.text = ""
|
||||
radio_cooldown_label.add_theme_font_size_override("font_size", 13)
|
||||
radio_cooldown_label.modulate = Color(1, 0.55, 0.45)
|
||||
vbox.add_child(radio_cooldown_label)
|
||||
|
||||
# --- dialogue tone indicator ---
|
||||
tone_label = Label.new()
|
||||
tone_label.text = "Tone: Professional"
|
||||
tone_label.add_theme_font_size_override("font_size", 13)
|
||||
tone_label.modulate = Color(0.7, 0.85, 1.0)
|
||||
vbox.add_child(tone_label)
|
||||
|
||||
# --- escalation level indicator (color-coded) ---
|
||||
escalation_label = Label.new()
|
||||
escalation_label.text = "Escalation: Observation"
|
||||
escalation_label.add_theme_font_size_override("font_size", 13)
|
||||
escalation_label.modulate = Color(0.6, 0.9, 0.6)
|
||||
vbox.add_child(escalation_label)
|
||||
|
||||
# --- inspect panel (popup center) ---
|
||||
inspect_panel = PanelContainer.new()
|
||||
inspect_panel.visible = false
|
||||
@@ -97,6 +125,25 @@ func _init() -> void:
|
||||
ivbox.add_child(insp_hint)
|
||||
add_child(inspect_panel)
|
||||
|
||||
# --- wand screening panel (popup center) ---
|
||||
wand_panel = PanelContainer.new()
|
||||
wand_panel.visible = false
|
||||
wand_panel.set_anchors_preset(Control.PRESET_CENTER)
|
||||
var wvbox := VBoxContainer.new()
|
||||
wand_panel.add_child(wvbox)
|
||||
wand_text = Label.new()
|
||||
wand_text.add_theme_font_size_override("font_size", 15)
|
||||
wvbox.add_child(wand_text)
|
||||
wand_meta = Label.new()
|
||||
wand_meta.add_theme_font_size_override("font_size", 12)
|
||||
wand_meta.modulate = Color(0.8, 0.85, 1.0)
|
||||
wvbox.add_child(wand_meta)
|
||||
var wand_hint := Label.new()
|
||||
wand_hint.text = "A = admit D = refuse entry"
|
||||
wand_hint.add_theme_font_size_override("font_size", 12)
|
||||
wvbox.add_child(wand_hint)
|
||||
add_child(wand_panel)
|
||||
|
||||
# --- debug overlay ---
|
||||
debug_label = Label.new()
|
||||
debug_label.visible = false
|
||||
@@ -116,6 +163,14 @@ func set_shift_state(coordinator: Object, scenario: Resource) -> void:
|
||||
coordinator.reputation.rating,
|
||||
coordinator.crowd.mood * 100.0,
|
||||
]
|
||||
_update_radio_cooldown(coordinator)
|
||||
|
||||
func _update_radio_cooldown(coordinator: Object) -> void:
|
||||
var remaining: float = coordinator.radio.emergency_cooldown_remaining
|
||||
if remaining > 0.0:
|
||||
radio_cooldown_label.text = Strings.fmt("hud.cooldown", [remaining])
|
||||
else:
|
||||
radio_cooldown_label.text = ""
|
||||
|
||||
func set_target_label(text: String) -> void:
|
||||
target_label.text = text
|
||||
@@ -123,6 +178,24 @@ func set_target_label(text: String) -> void:
|
||||
func set_action_hint(text: String) -> void:
|
||||
hint_label.text = text
|
||||
|
||||
func set_tone(tone_name: String) -> void:
|
||||
tone_label.text = Strings.fmt("hud.tone_prefix", [tone_name])
|
||||
|
||||
## Color-coded escalation feedback (PLAN.md: Polish and Accessibility).
|
||||
## Green → yellow → orange → red as the escalation level rises.
|
||||
func set_escalation(level: int) -> void:
|
||||
var name: String = Rules.LEVEL_NAMES.get(level, "Observation")
|
||||
escalation_label.text = Strings.fmt("hud.escalation_prefix", [name])
|
||||
match level:
|
||||
Rules.Level.OBSERVATION, Rules.Level.SIMPLE_DETERRENCE:
|
||||
escalation_label.modulate = Color(0.6, 0.9, 0.6)
|
||||
Rules.Level.FORMAL_WARNING:
|
||||
escalation_label.modulate = Color(0.95, 0.9, 0.4)
|
||||
Rules.Level.BLOCKING:
|
||||
escalation_label.modulate = Color(1.0, 0.65, 0.3)
|
||||
Rules.Level.RADIO_ASSIST, Rules.Level.EMERGENCY:
|
||||
escalation_label.modulate = Color(1.0, 0.35, 0.3)
|
||||
|
||||
func log(text: String) -> void:
|
||||
_log_lines.append(text)
|
||||
if _log_lines.size() > 8:
|
||||
@@ -166,3 +239,25 @@ func show_inspection(controller: Object, artifacts: Array, result: Dictionary) -
|
||||
|
||||
func hide_inspection() -> void:
|
||||
inspect_panel.visible = false
|
||||
|
||||
func show_wand(controller: Object, result: Dictionary) -> void:
|
||||
var profile: Object = controller.profile
|
||||
var npc_display: String = (profile.display_name if profile else "Person")
|
||||
var alert: bool = result.get("alert", false)
|
||||
wand_text.text = "Wand check — %s\nAlert: %s" % [npc_display, "YES" if alert else "none"]
|
||||
var lines: Array[String] = []
|
||||
if alert:
|
||||
var item: String = result.get("item", "")
|
||||
if result.get("prohibited", false):
|
||||
lines.append("The wand alerts on a suspicious item (%s)." % item)
|
||||
lines.append("Ask the guest to identify it before deciding.")
|
||||
else:
|
||||
lines.append("The wand alerts on a harmless item (%s)." % item)
|
||||
lines.append("Likely a false alarm — keys, belt, or phone.")
|
||||
else:
|
||||
lines.append("No alert. The guest appears clear.")
|
||||
wand_meta.text = "\n".join(lines)
|
||||
wand_panel.visible = true
|
||||
|
||||
func hide_wand() -> void:
|
||||
wand_panel.visible = false
|
||||
Reference in new issue
Block a user