extends Node signal resource_changed(resource_name: StringName, value: int) signal state_reset signal revision_changed(revision: int) signal world_tree_rank_changed(rank: int) const DEFAULT_RESOURCES := { &"gold": 5000, &"mana": 100, &"materials": 50, &"faith": 0, } var resources: Dictionary = DEFAULT_RESOURCES.duplicate(true) var world_tree_rank := 1 var active_layer := 0 var revision := 0 func reset() -> void: resources = DEFAULT_RESOURCES.duplicate(true) world_tree_rank = 1 active_layer = 0 revision = 0 state_reset.emit() for resource_name: StringName in resources: resource_changed.emit(resource_name, resources[resource_name]) func get_resource(resource_name: StringName) -> int: return int(resources.get(resource_name, 0)) func set_resource(resource_name: StringName, value: int) -> void: var next_value := maxi(value, 0) if get_resource(resource_name) == next_value: return resources[resource_name] = next_value _touch_revision() resource_changed.emit(resource_name, resources[resource_name]) func add_resource(resource_name: StringName, amount: int) -> int: set_resource(resource_name, get_resource(resource_name) + amount) return get_resource(resource_name) func can_afford(cost: Dictionary) -> bool: for resource_name: Variant in cost: if get_resource(StringName(resource_name)) < int(cost[resource_name]): return false return true func spend(cost: Dictionary) -> bool: if not can_afford(cost): return false var deltas := {} for resource_name: Variant in cost: deltas[StringName(resource_name)] = -int(cost[resource_name]) return apply_resource_deltas(deltas) func apply_resource_deltas(deltas: Dictionary) -> bool: var next_values := {} for resource_name: Variant in deltas: var normalized_name := StringName(resource_name) var next_value := get_resource(normalized_name) + int(deltas[resource_name]) if next_value < 0: return false next_values[normalized_name] = next_value if next_values.is_empty(): return true for resource_name: Variant in next_values: resources[resource_name] = next_values[resource_name] _touch_revision() for resource_name: Variant in next_values: resource_changed.emit(resource_name, int(next_values[resource_name])) return true func set_world_tree_rank(value: int) -> bool: if value < world_tree_rank or value < 1 or value > 7: return false if value == world_tree_rank: return true world_tree_rank = value _touch_revision() world_tree_rank_changed.emit(world_tree_rank) return true func create_snapshot() -> Dictionary: return { &"resources": resources.duplicate(true), &"world_tree_rank": world_tree_rank, &"active_layer": active_layer, &"revision": revision, } func restore_snapshot(snapshot: Dictionary) -> bool: if not snapshot.has(&"resources") or not snapshot[&"resources"] is Dictionary: return false var restored_resources: Dictionary = snapshot[&"resources"] for resource_name: Variant in restored_resources: if int(restored_resources[resource_name]) < 0: return false resources = restored_resources.duplicate(true) world_tree_rank = maxi(int(snapshot.get(&"world_tree_rank", 1)), 1) active_layer = clampi(int(snapshot.get(&"active_layer", 0)), 0, 1) revision = maxi(int(snapshot.get(&"revision", 0)), 0) state_reset.emit() for resource_name: Variant in resources: resource_changed.emit(StringName(resource_name), int(resources[resource_name])) revision_changed.emit(revision) return true func _touch_revision() -> void: revision += 1 revision_changed.emit(revision)