extends Node signal productions_update(p: Array[Production]) @warning_ignore("unused_signal") signal production_log(producer: Currency, p: Production) @warning_ignore("unused_signal") signal log(s: String) @export var currencies: Array[Production] @export var members: Array signal census(p: Production, all) @onready var events: Array[Event] = load_events() func spawn_friendlies(): if GameState.spawns_good == null: spawn_friendlies.call_deferred() return for currency in get_all_sentient_currencies(): var p := Production.new() p.currency = currency p.amount = 0 var all: Array[Node2D] = [] census.emit(p, []) var delta := get_currency_amount(currency) - p.amount if delta > 0: for i in range(delta): spawn_currency_avatar(currency, true) elif delta < 0: all.shuffle() for i in range(min(delta, all.size()-1)): all[i].queue_free() func spawn_baddies(): if GameState.spawns_good == null: spawn_friendlies.call_deferred() return for currency in get_all_sentient_currencies(): var delta := get_currency_amount(currency) for i in range(delta): spawn_currency_avatar(currency, false) func spawn_currency_avatar(currency, good: bool): var troup := preload("res://Troup.tscn").instantiate() var spawns if good: spawns = GameState.spawns_good else: spawns = GameState.spawns_bad var spawn: Node2D = spawns.get_children().pick_random() troup.top_level = true troup.position = spawn.global_position var sprite: CurrencyMemberSprite = troup.sprite() sprite.currency = currency if good: sprite.allegiance = preload("res://allegiance/good.tres") else: sprite.allegiance = preload("res://allegiance/bad.tres") get_tree().root.add_child(troup) func load_events() -> Array[Event]: var dir := "res://random events" var es: Array[Event] = [] for event_name in ResourceLoader.list_directory(dir): var event: Event = load(dir + "/" + event_name) es.push_back(event) return es func get_currency(c: Currency) -> Production: sync_currency.call_deferred() for p in currencies: if c == p.currency: return p var p := Production.new() p.currency = c p.amount = 0 currencies.append(p) return p func do_bribing(p: Production) -> bool: if get_currency_amount(p.currency) < p.amount: return false produce(negate_production(p)) return true func negate_production(p: Production) -> Production: var pp := p.duplicate() pp.amount = -pp.amount return pp func sync_currency(): var did_remove := true while did_remove: did_remove = false for i in range(len(currencies)): var p: Production = currencies[i] if p.amount == 0: currencies.remove_at(i) did_remove = true break productions_update.emit(currencies) func get_currency_amount(currency: Currency) -> int: var c := get_currency(currency) return c.amount func can_consume(production: Production) -> bool: return get_currency_amount(production.currency) >= production.amount func produce(production: Production): sync_currency.call_deferred() var c := get_currency(production.currency) c.amount += production.amount c.amount = clamp(c.amount, 0, 9999) func update_currencies(): productions_update.emit.call_deferred(currencies) for c in currencies: for p in c.currency.production: var pp := Production.new() pp.currency = p.currency pp.amount = c.amount * p.amount produce(pp) func simulate(): update_currencies() for e in events: if e.requirements_satisfied() and e.will_happen(): if e.game_over_timeline != null: get_tree().change_scene_to_file("res://game_over.tscn") Dialogic.start(e.game_over_timeline) return if e.log_message != "" and not e.skip_log: Economy.log.emit(e.log_message) var outcome := e.outcome() for o in outcome: if o == null: continue produce(o) if e.log_message == "" and not e.skip_log: production_log.emit(null, o) if e.timeline != null: GameState.add_letter.emit(e.into_letter()) if randf() < 0.01: LetterGeneration.try_generate_offer() spawn_friendlies() func get_all_currencies_in(dir: StringName): var reses := ResourceLoader.list_directory(dir) var resources := [] for res in reses: if res.ends_with(".tres"): resources.append(load(dir + "/" + res)) return resources func get_all_sentient_currencies() -> Array: return get_all_currencies_in("res://currency/sentient") func get_all_inanimate_currencies() -> Array: return get_all_currencies_in("res://currency/inanimate") func _ready() -> void: %SimulateTickTimer.start() update_currencies() log.emit.call_deferred("Welcome to your kingdom!") func _on_timer_timeout() -> void: if get_tree().current_scene.scene_file_path != "res://game.tscn": %SimulateTickTimer.start() return if Dialogic.current_timeline != null: %SimulateTickTimer.start() return simulate()