Cleanup
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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))
|
||||
|
||||
21
currency_tile.tscn
Normal file
21
currency_tile.tscn
Normal file
@@ -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"]
|
||||
197
game_state.gd
197
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
13
generator/secondary_generator.tres
Normal file
13
generator/secondary_generator.tres
Normal file
@@ -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"
|
||||
66
generator_container.gd
Normal file
66
generator_container.gd
Normal file
@@ -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)
|
||||
1
generator_container.gd.uid
Normal file
1
generator_container.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://es14nqk6vrrk
|
||||
64
generator_container.tscn
Normal file
64
generator_container.tscn
Normal file
@@ -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"]
|
||||
53
generator_museum.tscn
Normal file
53
generator_museum.tscn
Normal file
@@ -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")
|
||||
Reference in New Issue
Block a user