Not errors and not regressions — Godot printed them on every script reload and they predate M4-b. Cleared so a real warning is not lost in the noise: - Redundant `const ContentDB`/`const NewGame` preloads that shadowed their own `class_name` globals (character_creation.gd, creation_draft.gd) — the class is already global, so the const bought nothing. - Two `log` locals shadowing the built-in `log()` — renamed to `out` (canon_log.from_dict) and `canon` (NewGame.construct); the "log" dict KEY is the public contract and is unchanged. - currency.format's copper->denomination division is integer BY DESIGN (the remainder is carried, not lost) — annotated `@warning_ignore` to say so. 319 client tests green; headless parse reports none of the four sites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
116 lines
3.3 KiB
GDScript
116 lines
3.3 KiB
GDScript
class_name CanonLog
|
|
extends RefCounted
|
|
## The §11 canon log: compact structured state code maintains and injects into
|
|
## every AI call. This container owns the container-level invariants; leaf rows
|
|
## own theirs. AI prose never writes here directly — mutators are called by code.
|
|
|
|
const SCHEMA_VERSION := 1
|
|
const MAX_RECENT_EVENTS := 5
|
|
|
|
var schema_version: int = SCHEMA_VERSION
|
|
var player: LogPlayer
|
|
var location: LogLocation
|
|
var party: Array[PartyMember] = []
|
|
var recent_events: Array[String] = []
|
|
var established_facts: Array[String] = []
|
|
var active_quests: Array[Quest] = []
|
|
var humiliations: Array[Humiliation] = []
|
|
|
|
|
|
func _init() -> void:
|
|
player = LogPlayer.new()
|
|
location = LogLocation.new()
|
|
|
|
|
|
# ── maintenance mutators (charter §11 maintenance table) ─────────────────────
|
|
|
|
func push_event(line: String) -> void:
|
|
recent_events.append(line)
|
|
while recent_events.size() > MAX_RECENT_EVENTS:
|
|
recent_events.pop_front()
|
|
|
|
|
|
func add_fact(text: String) -> void:
|
|
if text not in established_facts:
|
|
established_facts.append(text)
|
|
|
|
|
|
func add_humiliation(id: String, text: String, weight: int, turn: int) -> void:
|
|
humiliations.append(Humiliation.new(id, text, weight, turn))
|
|
|
|
|
|
func set_location(id: String, name: String) -> void:
|
|
location = LogLocation.new(id, name)
|
|
|
|
|
|
func party_member(id: String) -> PartyMember:
|
|
for m in party:
|
|
if m.id == id:
|
|
return m
|
|
return null
|
|
|
|
|
|
func adjust_disposition(id: String, delta: int) -> bool:
|
|
var m := party_member(id)
|
|
if m == null:
|
|
return false
|
|
m.set_disposition(m.disposition + delta)
|
|
return true
|
|
|
|
|
|
func has_quest(id: String) -> bool:
|
|
for q in active_quests:
|
|
if q.id == id:
|
|
return true
|
|
return false
|
|
|
|
|
|
func add_quest(id: String, name: String, objective: String) -> bool:
|
|
if has_quest(id):
|
|
return false
|
|
active_quests.append(Quest.new(id, name, "active", objective))
|
|
return true
|
|
|
|
|
|
func set_quest_status(id: String, status: String) -> bool:
|
|
for q in active_quests:
|
|
if q.id == id:
|
|
return q.set_status(status)
|
|
return false
|
|
|
|
|
|
# ── serialisation ────────────────────────────────────────────────────────────
|
|
|
|
func to_dict() -> Dictionary:
|
|
return {
|
|
"schema_version": schema_version,
|
|
"player": player.to_dict(),
|
|
"location": location.to_dict(),
|
|
"party": party.map(func(m): return m.to_dict()),
|
|
"recent_events": recent_events.duplicate(),
|
|
"established_facts": established_facts.duplicate(),
|
|
"active_quests": active_quests.map(func(q): return q.to_dict()),
|
|
"humiliations": humiliations.map(func(h): return h.to_dict()),
|
|
}
|
|
|
|
|
|
static func from_dict(d: Dictionary) -> CanonLog:
|
|
var v := int(d.get("schema_version", -1))
|
|
if v != SCHEMA_VERSION:
|
|
push_error("unsupported canon_log schema_version: %s" % v)
|
|
return null
|
|
var out := CanonLog.new()
|
|
out.player = LogPlayer.from_dict(d.get("player", {}))
|
|
out.location = LogLocation.from_dict(d.get("location", {}))
|
|
for m in d.get("party", []):
|
|
out.party.append(PartyMember.from_dict(m))
|
|
for e in d.get("recent_events", []):
|
|
out.push_event(e)
|
|
for f in d.get("established_facts", []):
|
|
out.add_fact(f)
|
|
for q in d.get("active_quests", []):
|
|
out.active_quests.append(Quest.from_dict(q))
|
|
for h in d.get("humiliations", []):
|
|
out.humiliations.append(Humiliation.from_dict(h))
|
|
return out
|