Files
code_of_conquest_dnd/client/scripts/state/game_state.gd
Phillip Tarrant 8a71671df7 feat(currency): purse_copper on GameState, with grant/take routing
One int holds all money. grant/take are the sole routing point — currency ids
go to the purse, everything else to inventory. Money is never an inventory row.

The 'coin' stand-in in the two unrelated inventory tests becomes
worn_shortsword; they were never about money.
2026-07-12 18:29:10 -05:00

80 lines
2.3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class_name GameState
extends RefCounted
## Luck-centric game state (spec decision 5). The SOLE home of numeric Luck,
## stats, world-NPC dispositions, and inventory — none of which enter the canon
## log (charter §7/§2). The log reads only luck_descriptor() from here.
var luck: int = 0
var luck_base: int = 0
var stats: Dictionary = {} # {str, dex, con, fth, mag}
var npc_dispositions: Dictionary = {} # world-npc id -> int (100..100)
var inventory: Dictionary = {} # item_id -> qty (NEVER money — see purse_copper)
var purse_copper: int = 0 # ALL money, in copper. One integer (§4.1 of the spec).
var revealed_topics: Dictionary = {} # topic_id -> true
var gifts_given: Dictionary = {} # item_id -> true (idempotency for give_item)
func set_luck(v: int) -> void:
luck = clampi(v, Luck.MIN, Luck.MAX)
func drift_luck(delta: int) -> void:
luck = Luck.drift(luck, luck_base, delta)
func luck_descriptor() -> String:
return Luck.descriptor(luck)
func set_npc_disposition(id: String, v: int) -> void:
npc_dispositions[id] = clampi(v, -100, 100)
func add_item(item_id: String, qty: int) -> void:
inventory[item_id] = int(inventory.get(item_id, 0)) + qty
func remove_item(item_id: String, qty: int) -> void:
var left := int(inventory.get(item_id, 0)) - qty
if left > 0:
inventory[item_id] = left
else:
inventory.erase(item_id)
func add_copper(amount: int) -> void:
purse_copper = maxi(0, purse_copper + amount)
func grant(item_id: String, qty: int) -> void:
# The single routing point (with take): currency lands in the purse, every
# other item in the inventory dict. Money is never an inventory row, so it
# can never surface in an inventory grid — exclusion by construction.
if Currency.is_currency(item_id):
add_copper(Currency.value(item_id) * qty)
else:
add_item(item_id, qty)
func take(item_id: String, qty: int) -> void:
if Currency.is_currency(item_id):
add_copper(-Currency.value(item_id) * qty)
else:
remove_item(item_id, qty)
func mark_revealed(topic_id: String) -> void:
revealed_topics[topic_id] = true
func is_revealed(topic_id: String) -> bool:
return revealed_topics.has(topic_id)
func mark_gift_given(item_id: String) -> void:
gifts_given[item_id] = true
func is_gift_given(item_id: String) -> bool:
return gifts_given.has(item_id)