NEO-153: refresh faction standing on completion and show issue busy copy.

Match quest HUD completion refresh and accept-busy feedback for duplicate Shift+C presses.
pull/195/head
VinPropane 2026-06-28 17:58:04 -04:00
parent ad29b4e930
commit e783fa5441
2 changed files with 52 additions and 0 deletions

View File

@ -9,6 +9,7 @@ const PROTOTYPE_CONTRACT_TEMPLATE_ID := "prototype_contract_clear_combat_pocket"
const PROTOTYPE_CONTRACT_SEED_BUCKET := "prototype_contract_dev_seed"
const ISSUE_IDLE_HINT := "Contract issue: — (Shift+C prototype)"
const ISSUE_SENDING_HINT := "Contract issue: sending…"
const ISSUE_BUSY_HINT := "Contract issue: busy — try again"
const REWARD_HEADER := "Contract rewards:"
const ISSUE_DENY_COPY := {
"active_contract_exists": "Contract issue: denied — active contract already issued",
@ -101,6 +102,7 @@ func try_issue_key_input(event: InputEvent) -> bool:
):
return false
if bool(_contract_client.call("is_issue_busy")):
_render_issue_feedback_label(ISSUE_BUSY_HINT)
return true
_render_issue_feedback_label(ISSUE_SENDING_HINT)
var queued: bool = bool(
@ -204,6 +206,7 @@ func _detect_and_apply_completion_transitions(snapshot: Dictionary) -> void:
_last_reward_instance_id = iid
_last_reward_summary = summary.duplicate(true)
_refresh_economy_hud()
_refresh_faction_standing()
_previous_status_by_instance[iid] = new_status
@ -235,6 +238,14 @@ func _refresh_economy_hud() -> void:
_skill_progression_client.call("request_sync_from_server")
func _refresh_faction_standing() -> void:
if (
is_instance_valid(_faction_standing_client)
and _faction_standing_client.has_method("request_sync_from_server")
):
_faction_standing_client.call("request_sync_from_server")
func _render_active_label() -> void:
if not is_instance_valid(_active_label):
return

View File

@ -62,6 +62,14 @@ class PendingIssueHttpTransport:
return OK
class TrackingFactionClient:
extends Node
var sync_count: int = 0
func request_sync_from_server() -> void:
sync_count += 1
static func _active_snapshot() -> Dictionary:
return {
"schemaVersion": 1,
@ -169,6 +177,23 @@ func test_try_issue_key_input_handles_shift_c() -> void:
assert_str(built["issue_label"].text).contains("sending")
func test_try_issue_key_input_shows_busy_while_issue_in_flight() -> void:
# Arrange
var built: Dictionary = await _build_controller(
NoopHttpTransport.new(), PendingIssueHttpTransport.new()
)
var event := InputEventKey.new()
event.pressed = true
event.shift_pressed = true
event.keycode = KEY_C
built["controller"].call("try_issue_key_input", event)
# Act
var handled: bool = bool(built["controller"].call("try_issue_key_input", event))
# Assert
assert_bool(handled).is_true()
assert_str(built["issue_label"].text).contains("busy")
func test_active_label_shows_encounter_objective_id() -> void:
# Arrange
var built: Dictionary = await _build_controller(
@ -220,6 +245,22 @@ func test_reward_label_populates_on_active_to_completed_transition() -> void:
assert_str(built["reward_label"].text).contains("Salvage +15 XP")
func test_completion_transition_refreshes_faction_standing() -> void:
# Arrange
var built: Dictionary = await _build_controller(
NoopHttpTransport.new(), NoopHttpTransport.new()
)
var faction_client := TrackingFactionClient.new()
auto_free(faction_client)
add_child(faction_client)
built["controller"].set("_faction_standing_client", faction_client)
built["controller"].call("_on_contracts_received", _active_snapshot())
# Act
built["controller"].call("_on_contracts_received", _completed_snapshot())
# Assert
assert_int(faction_client.sync_count).is_equal(1)
func test_reward_label_populates_when_first_get_is_already_completed() -> void:
# Arrange — issue marks session active; encounter completes before GET returns active
var built: Dictionary = await _build_controller(