From 246cf6a05f6edfb6be071d816567caf3e9221786 Mon Sep 17 00:00:00 2001 From: Michele Rossi Date: Fri, 13 Mar 2026 00:36:52 +0100 Subject: [PATCH] Cleanup --- big_number_museum.gd | 46 +------ big_number_museum.tscn | 105 ++++---------- currency_label.gd | 15 +- currency_tile.tscn | 21 +++ game_state.gd | 197 +++++++++++++++++++++++++++ generator/currency_generator.gd | 92 ++++++++++++- generator/currency_generator_data.gd | 2 + generator/secondary_generator.tres | 13 ++ generator_container.gd | 66 +++++++++ generator_container.gd.uid | 1 + generator_container.tscn | 64 +++++++++ generator_museum.tscn | 53 +++++++ 12 files changed, 549 insertions(+), 126 deletions(-) create mode 100644 currency_tile.tscn create mode 100644 generator/secondary_generator.tres create mode 100644 generator_container.gd create mode 100644 generator_container.gd.uid create mode 100644 generator_container.tscn create mode 100644 generator_museum.tscn diff --git a/big_number_museum.gd b/big_number_museum.gd index e52cdc6..adb5f7f 100644 --- a/big_number_museum.gd +++ b/big_number_museum.gd @@ -1,49 +1,5 @@ extends Control -@onready var _generator: CurrencyGenerator = $VBoxContainer2/HBoxContainerGenerators/BuyOneButton -@onready var _name_label: Label = $VBoxContainer2/Label -@onready var _owned_value: Label = $VBoxContainer2/GeneratorStatsGrid/OwnedValue -@onready var _next_cost_value: Label = $VBoxContainer2/GeneratorStatsGrid/NextCostValue -@onready var _production_value: Label = $VBoxContainer2/GeneratorStatsGrid/ProductionValue func _ready() -> void: - _generator.purchase_completed.connect(_on_generator_updated) - _generator.production_tick.connect(_on_generator_updated) - _generator.purchase_failed.connect(_on_generator_updated) - - match _generator.currency: - GameState.CurrencyType.gold: - GameState.gold_changed.connect(_on_currency_changed) - GameState.CurrencyType.gems: - GameState.gems_changed.connect(_on_currency_changed) - - _name_label.text = _generator.data.name - _refresh_generator_ui() - -func _on_buy_max_pressed() -> void: - _generator.buy_max() - _refresh_generator_ui() - -func _on_debug_income_pressed() -> void: - _generator.grant_currency(BigNumber.from_float(100.0)) - _refresh_generator_ui() - -func _on_currency_changed(_new_value: BigNumber) -> void: - _refresh_generator_ui() - -func _on_generator_updated(_a = null, _b = null, _c = null, _d = null) -> void: - _refresh_generator_ui() - -func _refresh_generator_ui() -> void: - _owned_value.text = str(_generator.owned) - _next_cost_value.text = _generator.get_next_cost().to_string_suffix(2) - - var production_per_second: float = 0.0 - if _generator.data != null: - production_per_second = _generator.data.production_per_second( - _generator.owned, - _generator.run_multiplier, - _generator.purchased_count - ) - - _production_value.text = BigNumber.from_float(production_per_second).to_string_suffix(2) + pass diff --git a/big_number_museum.tscn b/big_number_museum.tscn index f09d8d6..86f040c 100644 --- a/big_number_museum.tscn +++ b/big_number_museum.tscn @@ -1,9 +1,8 @@ [gd_scene format=3 uid="uid://b11eevc8qj18p"] -[ext_resource type="Script" uid="uid://dtbxopw6ulhl8" path="res://generator/currency_generator.gd" id="1_h2bxk"] [ext_resource type="Script" uid="uid://coasop1lyw5rh" path="res://big_number_museum.gd" id="1_muwei"] -[ext_resource type="Script" uid="uid://sp67wcb6s5nw" path="res://currency_label.gd" id="2_a7k0t"] -[ext_resource type="Resource" uid="uid://co0mcc2kvcpo5" path="res://generator/primary_generator.tres" id="3_m5m0g"] +[ext_resource type="PackedScene" uid="uid://btkxru2gdjsgc" path="res://currency_tile.tscn" id="2_a7k0t"] +[ext_resource type="PackedScene" uid="uid://ckos7f22pnmyh" path="res://generator_container.tscn" id="2_h2bxk"] [node name="BigNumberMuseum" type="Control" unique_id=1249411984] layout_mode = 3 @@ -14,81 +13,37 @@ grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_muwei") -[node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=1937517070] +[node name="CurrencyTile" parent="." unique_id=1440583137 instance=ExtResource("2_a7k0t")] layout_mode = 0 offset_right = 404.0 -offset_bottom = 267.0 +offset_bottom = 31.0 -[node name="HBoxContainerCurrency" type="HBoxContainer" parent="VBoxContainer" unique_id=93448794] -layout_mode = 2 -theme_override_constants/separation = 12 - -[node name="Label" type="Label" parent="VBoxContainer/HBoxContainerCurrency" unique_id=1951729878] -layout_mode = 2 -text = "Gold:" - -[node name="CurrencyValueLabel" type="Label" parent="VBoxContainer/HBoxContainerCurrency" unique_id=1036299287] -layout_mode = 2 -text = "0" -script = ExtResource("2_a7k0t") - -[node name="DebugIncomeButton" type="Button" parent="VBoxContainer/HBoxContainerCurrency" unique_id=780351266] -layout_mode = 2 -text = "+100 Gold" - -[node name="VBoxContainer2" type="VBoxContainer" parent="." unique_id=1163554471] +[node name="GoldGeneratorContainer" parent="." unique_id=1129190041 instance=ExtResource("2_h2bxk")] layout_mode = 0 -offset_left = 2.0 -offset_top = 138.0 -offset_right = 266.0 -offset_bottom = 303.0 +anchors_preset = 0 +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +offset_left = 0.0 +offset_top = 81.0 +offset_right = 264.0 +offset_bottom = 246.0 +grow_horizontal = 1 +grow_vertical = 1 -[node name="Label" type="Label" parent="VBoxContainer2" unique_id=2116890422] -layout_mode = 2 -text = "Generator" +[node name="GemsGeneratorContainer" parent="." unique_id=1519618562 instance=ExtResource("2_h2bxk")] +layout_mode = 0 +anchors_preset = 0 +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +offset_left = 0.0 +offset_top = 246.0 +offset_right = 264.0 +offset_bottom = 411.0 +grow_horizontal = 1 +grow_vertical = 1 -[node name="HBoxContainerGenerators" type="HBoxContainer" parent="VBoxContainer2" unique_id=1759912851] -layout_mode = 2 -theme_override_constants/separation = 8 - -[node name="BuyOneButton" type="Button" parent="VBoxContainer2/HBoxContainerGenerators" unique_id=2126082317] -layout_mode = 2 -text = "Buy x1" -script = ExtResource("1_h2bxk") -data = ExtResource("3_m5m0g") - -[node name="BuyMaxButton" type="Button" parent="VBoxContainer2/HBoxContainerGenerators" unique_id=171532995] -layout_mode = 2 -text = "Buy Max" - -[node name="GeneratorStatsGrid" type="GridContainer" parent="VBoxContainer2" unique_id=88353659] -layout_mode = 2 -columns = 2 - -[node name="OwnedTitle" type="Label" parent="VBoxContainer2/GeneratorStatsGrid" unique_id=1743705746] -layout_mode = 2 -text = "Owned" - -[node name="OwnedValue" type="Label" parent="VBoxContainer2/GeneratorStatsGrid" unique_id=890804662] -layout_mode = 2 -text = "0" - -[node name="NextCostTitle" type="Label" parent="VBoxContainer2/GeneratorStatsGrid" unique_id=990792129] -layout_mode = 2 -text = "Next Cost" - -[node name="NextCostValue" type="Label" parent="VBoxContainer2/GeneratorStatsGrid" unique_id=1296617914] -layout_mode = 2 -text = "0" - -[node name="ProductionTitle" type="Label" parent="VBoxContainer2/GeneratorStatsGrid" unique_id=698748759] -layout_mode = 2 -text = "Production / sec" - -[node name="ProductionValue" type="Label" parent="VBoxContainer2/GeneratorStatsGrid" unique_id=1059520776] -layout_mode = 2 -text = "0" - -[connection signal="pressed" from="VBoxContainer/HBoxContainerCurrency/DebugIncomeButton" to="." method="_on_debug_income_pressed"] -[connection signal="pressed" from="VBoxContainer2/HBoxContainerGenerators/BuyOneButton" to="VBoxContainer2/HBoxContainerGenerators/BuyOneButton" method="_on_pressed"] -[connection signal="pressed" from="VBoxContainer2/HBoxContainerGenerators/BuyMaxButton" to="." method="_on_buy_max_pressed"] +[editable path="GemsGeneratorContainer"] diff --git a/currency_label.gd b/currency_label.gd index faeca72..048d4f7 100644 --- a/currency_label.gd +++ b/currency_label.gd @@ -1,9 +1,15 @@ -class_name CurrencyLabel -extends Label +class_name CurrencyTile +extends HBoxContainer @export var currency: GameState.CurrencyType +@export var data: CurrencyGeneratorData + +@onready var _label: Label = $Label +@onready var _currency_label: Label = $CurrencyValueLabel +@onready var _debug_button: Button = $DebugIncomeButton func _ready() -> void: + _label.text = data.name match currency: GameState.CurrencyType.gold: GameState.gold_changed.connect(_on_currency_changed) @@ -11,6 +17,7 @@ func _ready() -> void: GameState.gems_changed.connect(_on_currency_changed) func _on_currency_changed(currency: BigNumber) -> void: - text = currency.to_string_suffix(2) + _currency_label.text = currency.to_string_suffix(2) - +func _on_debug_income_button_pressed() -> void: + GameState.add_gold(BigNumber.from_float(100)) diff --git a/currency_tile.tscn b/currency_tile.tscn new file mode 100644 index 0000000..02ddfd2 --- /dev/null +++ b/currency_tile.tscn @@ -0,0 +1,21 @@ +[gd_scene format=3 uid="uid://btkxru2gdjsgc"] + +[ext_resource type="Script" uid="uid://sp67wcb6s5nw" path="res://currency_label.gd" id="1_0hv07"] + +[node name="CurrencyTile" type="HBoxContainer" unique_id=1440583137] +theme_override_constants/separation = 12 +script = ExtResource("1_0hv07") + +[node name="Label" type="Label" parent="." unique_id=89234840] +layout_mode = 2 +text = "Gold:" + +[node name="CurrencyValueLabel" type="Label" parent="." unique_id=1469960585] +layout_mode = 2 +text = "0" + +[node name="DebugIncomeButton" type="Button" parent="." unique_id=662695248] +layout_mode = 2 +text = "+100 Gold" + +[connection signal="pressed" from="DebugIncomeButton" to="." method="_on_debug_income_button_pressed"] diff --git a/game_state.gd b/game_state.gd index 22dbdc4..e61aede 100644 --- a/game_state.gd +++ b/game_state.gd @@ -6,6 +6,7 @@ extends Node # ========================================== signal gold_changed(new_amount: BigNumber) signal gems_changed(new_amount: BigNumber) +signal generator_state_changed(generator_id: StringName, state: Dictionary) enum CurrencyType { gold, gems } @@ -14,11 +15,17 @@ enum CurrencyType { gold, gems } # ========================================== var gold: BigNumber = BigNumber.from_float(0.0) var gems: BigNumber = BigNumber.from_float(0.0) +var generator_states: Dictionary = {} var last_save_time: int = 0 # Unix timestamp static var file_name: String = "user://idle_save.json" +const GENERATOR_OWNED_KEY: String = "owned" +const GENERATOR_PURCHASED_COUNT_KEY: String = "purchased_count" +const GENERATOR_UNLOCKED_KEY: String = "unlocked" +const GENERATOR_AVAILABLE_KEY: String = "available" + func _ready() -> void: load_game() @@ -49,6 +56,76 @@ func spend_gems(cost: BigNumber) -> bool: return true return false +func register_generator(generator_id: StringName, unlocked: bool = false, available: bool = false) -> void: + var key: String = String(generator_id) + if key.is_empty(): + return + + if generator_states.has(key): + var existing_raw: Variant = generator_states.get(key) + if existing_raw is Dictionary: + generator_states[key] = _sanitize_generator_state(existing_raw, unlocked, available) + return + + var new_state: Dictionary = _default_generator_state(unlocked, available) + generator_states[key] = new_state + generator_state_changed.emit(StringName(key), new_state.duplicate(true)) + +func get_generator_state(generator_id: StringName) -> Dictionary: + return _get_generator_state(generator_id).duplicate(true) + +func get_generator_owned(generator_id: StringName) -> int: + var state: Dictionary = _get_generator_state(generator_id) + return int(state.get(GENERATOR_OWNED_KEY, 0)) + +func set_generator_owned(generator_id: StringName, value: int) -> void: + var state: Dictionary = _get_generator_state(generator_id) + var next_owned: int = maxi(value, 0) + if int(state.get(GENERATOR_OWNED_KEY, 0)) == next_owned: + return + + state[GENERATOR_OWNED_KEY] = next_owned + state[GENERATOR_PURCHASED_COUNT_KEY] = maxi(int(state.get(GENERATOR_PURCHASED_COUNT_KEY, 0)), next_owned) + _set_generator_state(generator_id, state) + +func get_generator_purchased_count(generator_id: StringName) -> int: + var state: Dictionary = _get_generator_state(generator_id) + return int(state.get(GENERATOR_PURCHASED_COUNT_KEY, 0)) + +func set_generator_purchased_count(generator_id: StringName, value: int) -> void: + var state: Dictionary = _get_generator_state(generator_id) + var min_purchased: int = int(state.get(GENERATOR_OWNED_KEY, 0)) + var next_purchased: int = maxi(value, min_purchased) + if int(state.get(GENERATOR_PURCHASED_COUNT_KEY, 0)) == next_purchased: + return + + state[GENERATOR_PURCHASED_COUNT_KEY] = next_purchased + _set_generator_state(generator_id, state) + +func is_generator_unlocked(generator_id: StringName) -> bool: + var state: Dictionary = _get_generator_state(generator_id) + return bool(state.get(GENERATOR_UNLOCKED_KEY, false)) + +func set_generator_unlocked(generator_id: StringName, value: bool) -> void: + var state: Dictionary = _get_generator_state(generator_id) + if bool(state.get(GENERATOR_UNLOCKED_KEY, false)) == value: + return + + state[GENERATOR_UNLOCKED_KEY] = value + _set_generator_state(generator_id, state) + +func is_generator_available(generator_id: StringName) -> bool: + var state: Dictionary = _get_generator_state(generator_id) + return bool(state.get(GENERATOR_AVAILABLE_KEY, false)) + +func set_generator_available(generator_id: StringName, value: bool) -> void: + var state: Dictionary = _get_generator_state(generator_id) + if bool(state.get(GENERATOR_AVAILABLE_KEY, false)) == value: + return + + state[GENERATOR_AVAILABLE_KEY] = value + _set_generator_state(generator_id, state) + # ========================================== # PERSISTENCE (Save/Load) # ========================================== @@ -56,6 +133,7 @@ func save_game() -> void: var save_data = { "gold": gold.serialize(), "gems": gems.serialize(), + "generator_states": _serialize_generator_states(), "last_save_time": Time.get_unix_time_from_system() } @@ -73,4 +151,123 @@ func load_game() -> void: if parsed is Dictionary: gold = BigNumber.deserialize(parsed.get("gold", {})) gems = BigNumber.deserialize(parsed.get("gems", {})) + generator_states = _deserialize_generator_states(parsed.get("generator_states", {})) last_save_time = parsed.get("last_save_time", Time.get_unix_time_from_system()) + +func _default_generator_state(unlocked: bool, available: bool) -> Dictionary: + return { + GENERATOR_OWNED_KEY: 0, + GENERATOR_PURCHASED_COUNT_KEY: 0, + GENERATOR_UNLOCKED_KEY: unlocked, + GENERATOR_AVAILABLE_KEY: available, + } + +func _get_generator_state(generator_id: StringName) -> Dictionary: + var key: String = String(generator_id) + if key.is_empty(): + return _default_generator_state(false, false) + + if not generator_states.has(key): + register_generator(generator_id) + + var existing_raw: Variant = generator_states.get(key, _default_generator_state(false, false)) + if existing_raw is Dictionary: + var state: Dictionary = existing_raw + var sanitized: Dictionary = _sanitize_generator_state(state, false, false) + generator_states[key] = sanitized + return sanitized + + var fallback: Dictionary = _default_generator_state(false, false) + generator_states[key] = fallback + return fallback + +func _set_generator_state(generator_id: StringName, state: Dictionary) -> void: + var key: String = String(generator_id) + if key.is_empty(): + return + + var sanitized: Dictionary = _sanitize_generator_state(state, false, false) + generator_states[key] = sanitized + generator_state_changed.emit(StringName(key), sanitized.duplicate(true)) + +func _serialize_generator_states() -> Dictionary: + var result: Dictionary = {} + for key_variant in generator_states.keys(): + var key: String = String(key_variant) + if key.is_empty(): + continue + + var value: Variant = generator_states.get(key_variant) + if value is Dictionary: + result[key] = _serialize_generator_state_entry(value) + return result + +func _deserialize_generator_states(raw_value: Variant) -> Dictionary: + var result: Dictionary = {} + if not (raw_value is Dictionary): + return result + + for key_variant in raw_value.keys(): + var key: String = String(key_variant) + if key.is_empty(): + continue + + var entry: Variant = raw_value.get(key_variant) + if entry is Dictionary: + result[key] = _deserialize_generator_state_entry(entry) + return result + +func _serialize_generator_state_entry(raw_state: Dictionary) -> Dictionary: + var owned_value: int = _to_non_negative_int(raw_state.get(GENERATOR_OWNED_KEY, 0), 0) + var purchased_value: int = _to_non_negative_int(raw_state.get(GENERATOR_PURCHASED_COUNT_KEY, owned_value), owned_value) + + var serialized_state: Dictionary = { + GENERATOR_OWNED_KEY: owned_value, + GENERATOR_PURCHASED_COUNT_KEY: maxi(purchased_value, owned_value), + } + + if raw_state.has(GENERATOR_UNLOCKED_KEY) and raw_state.get(GENERATOR_UNLOCKED_KEY) is bool: + serialized_state[GENERATOR_UNLOCKED_KEY] = raw_state.get(GENERATOR_UNLOCKED_KEY) + if raw_state.has(GENERATOR_AVAILABLE_KEY) and raw_state.get(GENERATOR_AVAILABLE_KEY) is bool: + serialized_state[GENERATOR_AVAILABLE_KEY] = raw_state.get(GENERATOR_AVAILABLE_KEY) + + return serialized_state + +func _deserialize_generator_state_entry(raw_state: Dictionary) -> Dictionary: + var owned_value: int = _to_non_negative_int(raw_state.get(GENERATOR_OWNED_KEY, 0), 0) + var purchased_value: int = _to_non_negative_int(raw_state.get(GENERATOR_PURCHASED_COUNT_KEY, owned_value), owned_value) + + var parsed_state: Dictionary = { + GENERATOR_OWNED_KEY: owned_value, + GENERATOR_PURCHASED_COUNT_KEY: maxi(purchased_value, owned_value), + } + + if raw_state.has(GENERATOR_UNLOCKED_KEY) and raw_state.get(GENERATOR_UNLOCKED_KEY) is bool: + parsed_state[GENERATOR_UNLOCKED_KEY] = raw_state.get(GENERATOR_UNLOCKED_KEY) + if raw_state.has(GENERATOR_AVAILABLE_KEY) and raw_state.get(GENERATOR_AVAILABLE_KEY) is bool: + parsed_state[GENERATOR_AVAILABLE_KEY] = raw_state.get(GENERATOR_AVAILABLE_KEY) + + return parsed_state + +func _sanitize_generator_state(raw_state: Dictionary, default_unlocked: bool, default_available: bool) -> Dictionary: + var owned_value: int = _to_non_negative_int(raw_state.get(GENERATOR_OWNED_KEY, 0), 0) + var purchased_value: int = _to_non_negative_int(raw_state.get(GENERATOR_PURCHASED_COUNT_KEY, owned_value), owned_value) + + return { + GENERATOR_OWNED_KEY: owned_value, + GENERATOR_PURCHASED_COUNT_KEY: maxi(purchased_value, owned_value), + GENERATOR_UNLOCKED_KEY: _to_bool(raw_state.get(GENERATOR_UNLOCKED_KEY, default_unlocked), default_unlocked), + GENERATOR_AVAILABLE_KEY: _to_bool(raw_state.get(GENERATOR_AVAILABLE_KEY, default_available), default_available), + } + +func _to_non_negative_int(value: Variant, fallback: int = 0) -> int: + if value is int: + return maxi(value, 0) + if value is float: + return maxi(int(value), 0) + return maxi(fallback, 0) + +func _to_bool(value: Variant, fallback: bool) -> bool: + if value is bool: + return value + return fallback diff --git a/generator/currency_generator.gd b/generator/currency_generator.gd index 29005a2..b3685e5 100644 --- a/generator/currency_generator.gd +++ b/generator/currency_generator.gd @@ -12,21 +12,59 @@ const HUGE_COST_EXPONENT: int = 1000000 @export var is_automatic: bool = true @export var press_buys_generator: bool = true @export var run_multiplier: float = 1.0 +@export var starts_unlocked: bool = true +@export var starts_available: bool = true ## Manual click fallback when no data is assigned. @export var click_mantissa: float = 1.0 @export var click_exponent: int = 0 -var owned: int = 0 -var purchased_count: int = 0 +var owned: int: + get: + _ensure_registered() + return GameState.get_generator_owned(_generator_id) + set(value): + _ensure_registered() + GameState.set_generator_owned(_generator_id, value) + +var purchased_count: int: + get: + _ensure_registered() + return GameState.get_generator_purchased_count(_generator_id) + set(value): + _ensure_registered() + GameState.set_generator_purchased_count(_generator_id, value) + +var is_unlocked: bool: + get: + _ensure_registered() + return GameState.is_generator_unlocked(_generator_id) + set(value): + _ensure_registered() + GameState.set_generator_unlocked(_generator_id, value) + +var is_available: bool: + get: + _ensure_registered() + return GameState.is_generator_available(_generator_id) + set(value): + _ensure_registered() + GameState.set_generator_available(_generator_id, value) + var cycle_progress_seconds: float = 0.0 +var _generator_id: StringName = &"" +var _is_registered: bool = false func _ready() -> void: + _generator_id = _resolve_generator_id() + _ensure_registered() cycle_progress_seconds = 0.0 func _process(delta: float) -> void: if not is_automatic: return + if not is_available_to_player(): + return if data == null or owned <= 0: return @@ -63,6 +101,9 @@ func get_cost_for_amount(amount: int = 1) -> BigNumber: return _float_to_big_number(raw_cost) func can_buy(amount: int = 1) -> bool: + if not is_available_to_player(): + return false + var cost: BigNumber = get_cost_for_amount(amount) var current: BigNumber = _get_currency_amount() return current.is_greater_than(cost) or current.is_equal_to(cost) @@ -70,6 +111,8 @@ func can_buy(amount: int = 1) -> bool: func buy(amount: int = 1) -> bool: if data == null: return false + if not is_available_to_player(): + return false var safe_amount: int = maxi(amount, 1) var total_cost: BigNumber = get_cost_for_amount(safe_amount) @@ -85,6 +128,8 @@ func buy(amount: int = 1) -> bool: func buy_max() -> int: if data == null: return 0 + if not is_available_to_player(): + return 0 var available_currency: float = _big_number_to_float(_get_currency_amount()) var estimated_max: int = data.max_affordable(owned, available_currency) @@ -108,6 +153,9 @@ func buy_max() -> int: return best if buy(best) else 0 func _on_pressed() -> void: + if not is_available_to_player(): + return + if data != null and press_buys_generator: buy(1) return @@ -117,6 +165,13 @@ func _on_pressed() -> void: func grant_currency(amount: BigNumber) -> void: _add_currency(amount) +func get_generator_id() -> StringName: + _ensure_registered() + return _generator_id + +func is_available_to_player() -> bool: + return is_unlocked and is_available + func _add_currency(amount: BigNumber) -> void: match currency: GameState.CurrencyType.gold: @@ -160,3 +215,36 @@ func _big_number_to_float(value: BigNumber) -> float: if value.exponent < -308: return 0.0 return value.mantissa * pow(10.0, float(value.exponent)) + +func _resolve_generator_id() -> StringName: + if data != null: + var data_id: String = String(data.id) + if not data_id.is_empty(): + return StringName(data_id) + + if not String(name).is_empty(): + return StringName(String(name)) + + return &"generator" + +func _ensure_registered() -> void: + if _is_registered: + return + + if _generator_id == &"": + _generator_id = _resolve_generator_id() + if _generator_id == &"": + return + + GameState.register_generator(_generator_id, _default_unlocked_state(), _default_available_state()) + _is_registered = true + +func _default_unlocked_state() -> bool: + if data != null: + return data.starts_unlocked + return starts_unlocked + +func _default_available_state() -> bool: + if data != null: + return data.starts_available + return starts_available diff --git a/generator/currency_generator_data.gd b/generator/currency_generator_data.gd index d6806ba..f60fdc3 100644 --- a/generator/currency_generator_data.gd +++ b/generator/currency_generator_data.gd @@ -3,6 +3,8 @@ extends Resource @export var id: StringName = &"" @export var name: String = "" +@export var starts_unlocked: bool = true +@export var starts_available: bool = true ## Base cost and exponential growth (part I): cost_next = b * r^owned @export var initial_cost: float = 10.0 diff --git a/generator/secondary_generator.tres b/generator/secondary_generator.tres new file mode 100644 index 0000000..f4c7a05 --- /dev/null +++ b/generator/secondary_generator.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="CurrencyGeneratorData" format=3 uid="uid://04pmc034qupd"] + +[ext_resource type="Script" uid="uid://b00tqsuhxdy0d" path="res://generator/currency_generator_data.gd" id="1_s3g28"] + +[resource] +script = ExtResource("1_s3g28") +id = &"Gems" +name = "Gems Mine" +initial_cost = 60.0 +initial_time = 3.0 +initial_revenue = 60.0 +initial_productivity = 20.0 +metadata/_custom_type_script = "uid://b00tqsuhxdy0d" diff --git a/generator_container.gd b/generator_container.gd new file mode 100644 index 0000000..6f5a717 --- /dev/null +++ b/generator_container.gd @@ -0,0 +1,66 @@ +extends VBoxContainer + +@export var _generator: CurrencyGenerator + +@onready var _buy_button: Button = $HBoxContainerGenerators/BuyOneButton +@onready var _buy_max_button: Button = $HBoxContainerGenerators/BuyMaxButton +@onready var _name_label: Label = $Label +@onready var _owned_value: Label = $GeneratorStatsGrid/OwnedValue +@onready var _next_cost_value: Label = $GeneratorStatsGrid/NextCostValue +@onready var _production_value: Label = $GeneratorStatsGrid/ProductionValue + +func _ready() -> void: + _generator.purchase_completed.connect(_on_generator_updated) + _generator.production_tick.connect(_on_generator_updated) + _generator.purchase_failed.connect(_on_generator_updated) + + match _generator.currency: + GameState.CurrencyType.gold: + GameState.gold_changed.connect(_on_currency_changed) + GameState.CurrencyType.gems: + GameState.gems_changed.connect(_on_currency_changed) + + GameState.generator_state_changed.connect(_on_generator_state_changed) + + _name_label.text = _generator.data.name if _generator.data != null else "Generator" + _refresh_generator_ui() + +func _on_buy_pressed() -> void: + _generator.buy(1) + _refresh_generator_ui() + +func _on_buy_max_pressed() -> void: + _generator.buy_max() + _refresh_generator_ui() + +func _on_debug_income_pressed() -> void: + _generator.grant_currency(BigNumber.from_float(100.0)) + _refresh_generator_ui() + +func _on_currency_changed(_new_value: BigNumber) -> void: + _refresh_generator_ui() + +func _on_generator_updated(_a = null, _b = null, _c = null, _d = null) -> void: + _refresh_generator_ui() + +func _on_generator_state_changed(generator_id: StringName, _state: Dictionary) -> void: + if generator_id == _generator.get_generator_id(): + _refresh_generator_ui() + +func _refresh_generator_ui() -> void: + var can_interact: bool = _generator.is_available_to_player() + _buy_button.disabled = not can_interact + _buy_max_button.disabled = not can_interact + + _owned_value.text = str(_generator.owned) + _next_cost_value.text = _generator.get_next_cost().to_string_suffix(2) if can_interact else "-" + + var production_per_second: float = 0.0 + if _generator.data != null and can_interact: + production_per_second = _generator.data.production_per_second( + _generator.owned, + _generator.run_multiplier, + _generator.purchased_count + ) + + _production_value.text = BigNumber.from_float(production_per_second).to_string_suffix(2) diff --git a/generator_container.gd.uid b/generator_container.gd.uid new file mode 100644 index 0000000..375be21 --- /dev/null +++ b/generator_container.gd.uid @@ -0,0 +1 @@ +uid://es14nqk6vrrk diff --git a/generator_container.tscn b/generator_container.tscn new file mode 100644 index 0000000..8b8da7e --- /dev/null +++ b/generator_container.tscn @@ -0,0 +1,64 @@ +[gd_scene format=3 uid="uid://ckos7f22pnmyh"] + +[ext_resource type="Script" uid="uid://es14nqk6vrrk" path="res://generator_container.gd" id="1_8wouw"] + +[node name="GeneratorContainer" type="VBoxContainer" unique_id=1129190041] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -132.0 +offset_top = -82.5 +offset_right = 132.0 +offset_bottom = 82.5 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_8wouw") + +[node name="Label" type="Label" parent="." unique_id=1867673612] +layout_mode = 2 +text = "Generator" + +[node name="HBoxContainerGenerators" type="HBoxContainer" parent="." unique_id=2033456807] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="BuyOneButton" type="Button" parent="HBoxContainerGenerators" unique_id=1171095139] +layout_mode = 2 +text = "Buy x1" + +[node name="BuyMaxButton" type="Button" parent="HBoxContainerGenerators" unique_id=871628534] +layout_mode = 2 +text = "Buy Max" + +[node name="GeneratorStatsGrid" type="GridContainer" parent="." unique_id=745078076] +layout_mode = 2 +columns = 2 + +[node name="OwnedTitle" type="Label" parent="GeneratorStatsGrid" unique_id=891417119] +layout_mode = 2 +text = "Owned" + +[node name="OwnedValue" type="Label" parent="GeneratorStatsGrid" unique_id=549086894] +layout_mode = 2 +text = "0" + +[node name="NextCostTitle" type="Label" parent="GeneratorStatsGrid" unique_id=303459589] +layout_mode = 2 +text = "Next Cost" + +[node name="NextCostValue" type="Label" parent="GeneratorStatsGrid" unique_id=50480604] +layout_mode = 2 +text = "0" + +[node name="ProductionTitle" type="Label" parent="GeneratorStatsGrid" unique_id=2139535774] +layout_mode = 2 +text = "Production / sec" + +[node name="ProductionValue" type="Label" parent="GeneratorStatsGrid" unique_id=938669936] +layout_mode = 2 +text = "0" + +[connection signal="pressed" from="HBoxContainerGenerators/BuyOneButton" to="." method="_on_buy_pressed"] +[connection signal="pressed" from="HBoxContainerGenerators/BuyMaxButton" to="." method="_on_buy_max_pressed"] diff --git a/generator_museum.tscn b/generator_museum.tscn new file mode 100644 index 0000000..66eb8ba --- /dev/null +++ b/generator_museum.tscn @@ -0,0 +1,53 @@ +[gd_scene format=3 uid="uid://cfryecxmcg8hw"] + +[ext_resource type="Script" uid="uid://dtbxopw6ulhl8" path="res://generator/currency_generator.gd" id="1_pl17p"] +[ext_resource type="Resource" uid="uid://co0mcc2kvcpo5" path="res://generator/primary_generator.tres" id="2_x5lt1"] +[ext_resource type="Resource" uid="uid://04pmc034qupd" path="res://generator/secondary_generator.tres" id="3_dc82g"] +[ext_resource type="PackedScene" uid="uid://ckos7f22pnmyh" path="res://generator_container.tscn" id="3_pw2a0"] +[ext_resource type="PackedScene" uid="uid://btkxru2gdjsgc" path="res://currency_tile.tscn" id="3_x5lt1"] + +[node name="GeneratorMuseum" type="Node2D" unique_id=1219373683] + +[node name="GoldGenerator" type="Node2D" parent="." unique_id=964187690] +script = ExtResource("1_pl17p") +data = ExtResource("2_x5lt1") + +[node name="GemsGenerator" type="Node2D" parent="." unique_id=931294956] +script = ExtResource("1_pl17p") +data = ExtResource("3_dc82g") + +[node name="UI" type="Control" parent="." unique_id=452530906] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="GoldCurrencyTile" parent="UI" unique_id=1440583137 instance=ExtResource("3_x5lt1")] +layout_mode = 0 +offset_right = 160.0 +offset_bottom = 31.0 +data = ExtResource("2_x5lt1") + +[node name="GemsCurrencyTile" parent="UI" unique_id=1977342362 instance=ExtResource("3_x5lt1")] +layout_mode = 0 +offset_top = 28.0 +offset_right = 160.0 +offset_bottom = 59.0 +currency = 1 +data = ExtResource("3_dc82g") + +[node name="GoldGeneratorContainer" parent="UI" unique_id=1129190041 node_paths=PackedStringArray("_generator") instance=ExtResource("3_pw2a0")] +layout_mode = 1 +offset_left = -19.0 +offset_top = 53.0 +offset_right = 245.0 +offset_bottom = 218.0 +_generator = NodePath("../../GoldGenerator") + +[node name="GemsGeneratorContainer" parent="UI" unique_id=1999544736 node_paths=PackedStringArray("_generator") instance=ExtResource("3_pw2a0")] +layout_mode = 1 +offset_left = -17.0 +offset_top = 215.0 +offset_right = 247.0 +offset_bottom = 380.0 +_generator = NodePath("../../GemsGenerator")