Remove dialogue tone-of-voice system, add Gitea Actions full build, add venue cycling
Full build / Import + headless tests (push) Successful in 2m25s
Full build / Full desktop build + optional release (push) Skipped

- Delete Rules.Tone/TONE_NAMES, NpcProfile.tone_modifiers, tone params on
  NPCController.roll_reaction/apply_player_action; dialogue_lines flattened
  to Array[String]; HUD tone label, T binding, and hud.tone_prefix removed
- Docs updated everywhere (PLAN, README, DONE, MEMORY); PLAN section heading
  'Tone and Design Direction' -> 'Design Direction'
- Add .gitea/workflows/build.yml: checks job (import+tests) on push/PR; full
  build job (export templates, Linux/Windows/macOS exports, artifact upload,
  and tag-based Gitea release publish via GITEA_TOKEN) on tags/dispatch
- Remove old .github/workflows/ci.yml to avoid double runs
- Add venue cycling (V) across all three scenarios with hud.venue_switched
- Refresh README screenshots to match the new HUD
- 53/53 tests pass, boot smoke clean
This commit is contained in:
zwitschi committed 2026-10-31 13:08:20 +01:00
1 parent f7486d7539
commit a3768c2ce4
21 files changed
+230 -185

No files matched your search

+5 -11
View File
@@ -8,7 +8,7 @@ const FSM := preload("res://src/core/fsm.gd")
## reaction logic. The presentation layer adds a visual avatar and navigation.
## RefCounted on purpose: headless tests and CI do not need a scene tree.
signal interacted(level: int, tone: int)
signal interacted(level: int)
var npc_id: String = ""
var profile: NpcProfile = null
@@ -61,15 +61,10 @@ func _build_fsm(initial_state: String) -> void:
fsm.add_transition("THREATENING", "FORCING_ENTRY")
fsm.start(initial_state)
func roll_reaction(level: int, tone: int) -> int:
## Weighted pick from profile's reaction table for `level`, adjusted for tone.
func roll_reaction(level: int) -> int:
## Weighted pick from profile's reaction table for `level`.
highest_escalation_received = maxi(highest_escalation_received, level)
var weights: Dictionary = profile.pickup_reactions_per_level(level).duplicate()
var tone_mod: float = profile.tone_modifiers.get(tone, 0.0)
if tone_mod > 0.0 and weights.has(Rules.Reaction.COMPLY):
# Shift weight mass toward compliance proportionally.
var transferable: float = float(weights[Rules.Reaction.COMPLY]) * tone_mod
weights[Rules.Reaction.COMPLY] += transferable * 0.5
var roll_value := rng.randf()
var total := 0.0
for key in weights.keys():
@@ -83,16 +78,15 @@ func roll_reaction(level: int, tone: int) -> int:
return key
return Rules.Reaction.LEAVE
func apply_player_action(level: int, tone: int) -> Dictionary:
func apply_player_action(level: int) -> Dictionary:
## Returns reaction to the player's action and updates FSM when needed.
var performed_reaction := roll_reaction(level, tone)
var performed_reaction := roll_reaction(level)
reaction = performed_reaction
reaction_set = true
_update_state_for_reaction(performed_reaction)
return {
"npc_id": npc_id,
"level_used": level,
"tone": tone,
"reaction": performed_reaction,
"reaction_name": Rules.Reaction.find_key(performed_reaction),
"new_state": fsm.current_state,