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.
80 lines
2.3 KiB
GDScript
80 lines
2.3 KiB
GDScript
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)
|