Add generator buffs (additional test required)
This commit is contained in:
116
game_state.gd
116
game_state.gd
@@ -6,6 +6,7 @@ extends Node
|
|||||||
# ==========================================
|
# ==========================================
|
||||||
signal currency_changed(currency_id: StringName, new_amount: BigNumber)
|
signal currency_changed(currency_id: StringName, new_amount: BigNumber)
|
||||||
signal generator_state_changed(generator_id: StringName, state: Dictionary)
|
signal generator_state_changed(generator_id: StringName, state: Dictionary)
|
||||||
|
signal generator_buff_level_changed(generator_id: StringName, buff_id: StringName, new_level: int)
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# STATE VARIABLES
|
# STATE VARIABLES
|
||||||
@@ -14,6 +15,7 @@ var _current_currency: Dictionary = {}
|
|||||||
var _total_currency_acquired: Dictionary = {}
|
var _total_currency_acquired: Dictionary = {}
|
||||||
|
|
||||||
var generator_states: Dictionary = {}
|
var generator_states: Dictionary = {}
|
||||||
|
var generator_buff_levels: Dictionary = {}
|
||||||
|
|
||||||
var last_save_time: int = 0 # Unix timestamp
|
var last_save_time: int = 0 # Unix timestamp
|
||||||
|
|
||||||
@@ -25,9 +27,12 @@ const GENERATOR_OWNED_KEY: String = "owned"
|
|||||||
const GENERATOR_PURCHASED_COUNT_KEY: String = "purchased_count"
|
const GENERATOR_PURCHASED_COUNT_KEY: String = "purchased_count"
|
||||||
const GENERATOR_UNLOCKED_KEY: String = "unlocked"
|
const GENERATOR_UNLOCKED_KEY: String = "unlocked"
|
||||||
const GENERATOR_AVAILABLE_KEY: String = "available"
|
const GENERATOR_AVAILABLE_KEY: String = "available"
|
||||||
|
const GENERATOR_STATES_KEY: String = "generator_states"
|
||||||
|
const GENERATOR_BUFF_LEVELS_KEY: String = "generator_buff_levels"
|
||||||
const CURRENCIES_KEY: String = "currencies"
|
const CURRENCIES_KEY: String = "currencies"
|
||||||
const CURRENT_KEY: String = "current"
|
const CURRENT_KEY: String = "current"
|
||||||
const TOTAL_KEY: String = "total"
|
const TOTAL_KEY: String = "total"
|
||||||
|
const LAST_SAVE_TIME_KEY: String = "last_save_time"
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_initialize_currency_maps()
|
_initialize_currency_maps()
|
||||||
@@ -192,14 +197,61 @@ func set_generator_available(generator_id: StringName, value: bool) -> void:
|
|||||||
state[GENERATOR_AVAILABLE_KEY] = value
|
state[GENERATOR_AVAILABLE_KEY] = value
|
||||||
_set_generator_state(generator_id, state)
|
_set_generator_state(generator_id, state)
|
||||||
|
|
||||||
|
func register_generator_buff(generator_id: StringName, buff_id: StringName, initial_level: int = 0) -> void:
|
||||||
|
var generator_key: String = String(generator_id)
|
||||||
|
var buff_key: String = String(buff_id)
|
||||||
|
if generator_key.is_empty() or buff_key.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var levels: Dictionary = _get_generator_buff_levels_ref(generator_id)
|
||||||
|
if levels.has(buff_key):
|
||||||
|
var existing_level: int = _to_non_negative_int(levels.get(buff_key, initial_level), initial_level)
|
||||||
|
if int(levels.get(buff_key, initial_level)) != existing_level:
|
||||||
|
levels[buff_key] = existing_level
|
||||||
|
generator_buff_levels[generator_key] = levels
|
||||||
|
generator_buff_level_changed.emit(StringName(generator_key), StringName(buff_key), existing_level)
|
||||||
|
return
|
||||||
|
|
||||||
|
var sanitized_level: int = _to_non_negative_int(initial_level, 0)
|
||||||
|
levels[buff_key] = sanitized_level
|
||||||
|
generator_buff_levels[generator_key] = levels
|
||||||
|
generator_buff_level_changed.emit(StringName(generator_key), StringName(buff_key), sanitized_level)
|
||||||
|
|
||||||
|
func get_generator_buff_level(generator_id: StringName, buff_id: StringName) -> int:
|
||||||
|
var buff_key: String = String(buff_id)
|
||||||
|
if buff_key.is_empty():
|
||||||
|
return 0
|
||||||
|
|
||||||
|
var levels: Dictionary = _get_generator_buff_levels_ref(generator_id)
|
||||||
|
return _to_non_negative_int(levels.get(buff_key, 0), 0)
|
||||||
|
|
||||||
|
func set_generator_buff_level(generator_id: StringName, buff_id: StringName, value: int) -> void:
|
||||||
|
var generator_key: String = String(generator_id)
|
||||||
|
var buff_key: String = String(buff_id)
|
||||||
|
if generator_key.is_empty() or buff_key.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var levels: Dictionary = _get_generator_buff_levels_ref(generator_id)
|
||||||
|
var next_level: int = _to_non_negative_int(value, 0)
|
||||||
|
if int(levels.get(buff_key, -1)) == next_level:
|
||||||
|
return
|
||||||
|
|
||||||
|
levels[buff_key] = next_level
|
||||||
|
generator_buff_levels[generator_key] = levels
|
||||||
|
generator_buff_level_changed.emit(StringName(generator_key), StringName(buff_key), next_level)
|
||||||
|
|
||||||
|
func get_generator_buff_levels(generator_id: StringName) -> Dictionary:
|
||||||
|
return _get_generator_buff_levels_ref(generator_id).duplicate(true)
|
||||||
|
|
||||||
# ==========================================
|
# ==========================================
|
||||||
# PERSISTENCE (Save/Load)
|
# PERSISTENCE (Save/Load)
|
||||||
# ==========================================
|
# ==========================================
|
||||||
func save_game() -> void:
|
func save_game() -> void:
|
||||||
var save_data = {
|
var save_data = {
|
||||||
CURRENCIES_KEY: _serialize_currency_balances(),
|
CURRENCIES_KEY: _serialize_currency_balances(),
|
||||||
"generator_states": _serialize_generator_states(),
|
GENERATOR_STATES_KEY: _serialize_generator_states(),
|
||||||
"last_save_time": Time.get_unix_time_from_system()
|
GENERATOR_BUFF_LEVELS_KEY: _serialize_generator_buff_levels(),
|
||||||
|
LAST_SAVE_TIME_KEY: Time.get_unix_time_from_system()
|
||||||
}
|
}
|
||||||
|
|
||||||
var file: FileAccess = FileAccess.open(file_name, FileAccess.WRITE)
|
var file: FileAccess = FileAccess.open(file_name, FileAccess.WRITE)
|
||||||
@@ -218,8 +270,9 @@ func load_game() -> void:
|
|||||||
if parsed_data.has(CURRENCIES_KEY):
|
if parsed_data.has(CURRENCIES_KEY):
|
||||||
_load_currency_balances(parsed_data.get(CURRENCIES_KEY, {}))
|
_load_currency_balances(parsed_data.get(CURRENCIES_KEY, {}))
|
||||||
|
|
||||||
generator_states = _deserialize_generator_states(parsed_data.get("generator_states", {}))
|
generator_states = _deserialize_generator_states(parsed_data.get(GENERATOR_STATES_KEY, {}))
|
||||||
last_save_time = parsed_data.get("last_save_time", Time.get_unix_time_from_system())
|
generator_buff_levels = _deserialize_generator_buff_levels(parsed_data.get(GENERATOR_BUFF_LEVELS_KEY, {}))
|
||||||
|
last_save_time = parsed_data.get(LAST_SAVE_TIME_KEY, Time.get_unix_time_from_system())
|
||||||
|
|
||||||
func _load_currency_balances(raw_currencies: Variant) -> void:
|
func _load_currency_balances(raw_currencies: Variant) -> void:
|
||||||
if not (raw_currencies is Dictionary):
|
if not (raw_currencies is Dictionary):
|
||||||
@@ -378,6 +431,32 @@ func _set_generator_state(generator_id: StringName, state: Dictionary) -> void:
|
|||||||
generator_states[key] = sanitized
|
generator_states[key] = sanitized
|
||||||
generator_state_changed.emit(StringName(key), sanitized.duplicate(true))
|
generator_state_changed.emit(StringName(key), sanitized.duplicate(true))
|
||||||
|
|
||||||
|
func _get_generator_buff_levels_ref(generator_id: StringName) -> Dictionary:
|
||||||
|
var key: String = String(generator_id)
|
||||||
|
if key.is_empty():
|
||||||
|
return {}
|
||||||
|
|
||||||
|
var existing_raw: Variant = generator_buff_levels.get(key, {})
|
||||||
|
if existing_raw is Dictionary:
|
||||||
|
var sanitized: Dictionary = _sanitize_generator_buff_levels(existing_raw)
|
||||||
|
generator_buff_levels[key] = sanitized
|
||||||
|
return sanitized
|
||||||
|
|
||||||
|
var fallback: Dictionary = {}
|
||||||
|
generator_buff_levels[key] = fallback
|
||||||
|
return fallback
|
||||||
|
|
||||||
|
func _sanitize_generator_buff_levels(raw_levels: Dictionary) -> Dictionary:
|
||||||
|
var sanitized_levels: Dictionary = {}
|
||||||
|
for buff_key_variant in raw_levels.keys():
|
||||||
|
var buff_key: String = String(buff_key_variant)
|
||||||
|
if buff_key.is_empty():
|
||||||
|
continue
|
||||||
|
|
||||||
|
sanitized_levels[buff_key] = _to_non_negative_int(raw_levels.get(buff_key_variant, 0), 0)
|
||||||
|
|
||||||
|
return sanitized_levels
|
||||||
|
|
||||||
func _serialize_generator_states() -> Dictionary:
|
func _serialize_generator_states() -> Dictionary:
|
||||||
var result: Dictionary = {}
|
var result: Dictionary = {}
|
||||||
for key_variant in generator_states.keys():
|
for key_variant in generator_states.keys():
|
||||||
@@ -405,6 +484,35 @@ func _deserialize_generator_states(raw_value: Variant) -> Dictionary:
|
|||||||
result[key] = _deserialize_generator_state_entry(entry)
|
result[key] = _deserialize_generator_state_entry(entry)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
func _serialize_generator_buff_levels() -> Dictionary:
|
||||||
|
var result: Dictionary = {}
|
||||||
|
for generator_key_variant in generator_buff_levels.keys():
|
||||||
|
var generator_key: String = String(generator_key_variant)
|
||||||
|
if generator_key.is_empty():
|
||||||
|
continue
|
||||||
|
|
||||||
|
var raw_levels: Variant = generator_buff_levels.get(generator_key_variant)
|
||||||
|
if raw_levels is Dictionary:
|
||||||
|
result[generator_key] = _sanitize_generator_buff_levels(raw_levels)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
func _deserialize_generator_buff_levels(raw_value: Variant) -> Dictionary:
|
||||||
|
var result: Dictionary = {}
|
||||||
|
if not (raw_value is Dictionary):
|
||||||
|
return result
|
||||||
|
|
||||||
|
for generator_key_variant in raw_value.keys():
|
||||||
|
var generator_key: String = String(generator_key_variant)
|
||||||
|
if generator_key.is_empty():
|
||||||
|
continue
|
||||||
|
|
||||||
|
var raw_levels: Variant = raw_value.get(generator_key_variant)
|
||||||
|
if raw_levels is Dictionary:
|
||||||
|
result[generator_key] = _sanitize_generator_buff_levels(raw_levels)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
func _serialize_generator_state_entry(raw_state: Dictionary) -> Dictionary:
|
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 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 purchased_value: int = _to_non_negative_int(raw_state.get(GENERATOR_PURCHASED_COUNT_KEY, owned_value), owned_value)
|
||||||
|
|||||||
14
generator/buffs/knowledge_auto_treatise.tres
Normal file
14
generator/buffs/knowledge_auto_treatise.tres
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[gd_resource type="Resource" script_class="GeneratorBuffData" format=3 uid="uid://b4ne724qqo4d8"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dnhocfsuvmeyb" path="res://generator/generator_buff_data.gd" id="1_4w6kt"]
|
||||||
|
[ext_resource type="Resource" uid="uid://bnhqk8b31mm4e" path="res://currency/knowledge.tres" id="2_hk5d2"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_4w6kt")
|
||||||
|
id = &"knowledge_auto_treatise"
|
||||||
|
text = "Ancient Treatise"
|
||||||
|
max_level = 35
|
||||||
|
effect_increment = 0.2
|
||||||
|
cost_currency = ExtResource("2_hk5d2")
|
||||||
|
base_cost_mantissa = 40.0
|
||||||
|
cost_multiplier = 1.75
|
||||||
15
generator/buffs/knowledge_click_notes.tres
Normal file
15
generator/buffs/knowledge_click_notes.tres
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[gd_resource type="Resource" script_class="GeneratorBuffData" format=3 uid="uid://l5a300wieavc"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dnhocfsuvmeyb" path="res://generator/generator_buff_data.gd" id="1_l4lhm"]
|
||||||
|
[ext_resource type="Resource" uid="uid://bnhqk8b31mm4e" path="res://currency/knowledge.tres" id="2_9xja7"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_l4lhm")
|
||||||
|
id = &"knowledge_click_notes"
|
||||||
|
kind = 1
|
||||||
|
text = "Quick Notes"
|
||||||
|
max_level = 25
|
||||||
|
effect_increment = 0.25
|
||||||
|
cost_currency = ExtResource("2_9xja7")
|
||||||
|
base_cost_mantissa = 15.0
|
||||||
|
cost_multiplier = 1.6
|
||||||
19
generator/buffs/knowledge_grant_program.tres
Normal file
19
generator/buffs/knowledge_grant_program.tres
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
[gd_resource type="Resource" script_class="GeneratorBuffData" format=3 uid="uid://dxljqpqhdfqn6"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dnhocfsuvmeyb" path="res://generator/generator_buff_data.gd" id="1_8ee3d"]
|
||||||
|
[ext_resource type="Resource" uid="uid://brqaojindcxa5" path="res://currency/magic.tres" id="2_j7l8a"]
|
||||||
|
[ext_resource type="Resource" uid="uid://bnhqk8b31mm4e" path="res://currency/knowledge.tres" id="3_ynr4x"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_8ee3d")
|
||||||
|
id = &"knowledge_grant_program"
|
||||||
|
kind = 2
|
||||||
|
text = "Research Grant"
|
||||||
|
max_level = 20
|
||||||
|
effect_increment = 0.0
|
||||||
|
cost_currency = ExtResource("2_j7l8a")
|
||||||
|
base_cost_mantissa = 90.0
|
||||||
|
cost_multiplier = 1.8
|
||||||
|
resource_target_currency = ExtResource("3_ynr4x")
|
||||||
|
resource_purchase_base_mantissa = 8.0
|
||||||
|
resource_purchase_increment_multiplier = 1.35
|
||||||
14
generator/buffs/magic_auto_flux.tres
Normal file
14
generator/buffs/magic_auto_flux.tres
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[gd_resource type="Resource" script_class="GeneratorBuffData" format=3 uid="uid://ceugcxmassmpk"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dnhocfsuvmeyb" path="res://generator/generator_buff_data.gd" id="1_r7ak1"]
|
||||||
|
[ext_resource type="Resource" uid="uid://brqaojindcxa5" path="res://currency/magic.tres" id="2_h3we5"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_r7ak1")
|
||||||
|
id = &"magic_auto_flux"
|
||||||
|
text = "Arcane Dynamo"
|
||||||
|
max_level = 40
|
||||||
|
effect_increment = 0.15
|
||||||
|
cost_currency = ExtResource("2_h3we5")
|
||||||
|
base_cost_mantissa = 25.0
|
||||||
|
cost_multiplier = 1.7
|
||||||
15
generator/buffs/magic_click_focus.tres
Normal file
15
generator/buffs/magic_click_focus.tres
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[gd_resource type="Resource" script_class="GeneratorBuffData" format=3 uid="uid://6i3fcygusuqf"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dnhocfsuvmeyb" path="res://generator/generator_buff_data.gd" id="1_1wyaq"]
|
||||||
|
[ext_resource type="Resource" uid="uid://brqaojindcxa5" path="res://currency/magic.tres" id="2_0j56j"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_1wyaq")
|
||||||
|
id = &"magic_click_focus"
|
||||||
|
kind = 1
|
||||||
|
text = "Apprentice Gloves"
|
||||||
|
max_level = 30
|
||||||
|
effect_increment = 0.35
|
||||||
|
cost_currency = ExtResource("2_0j56j")
|
||||||
|
base_cost_mantissa = 8.0
|
||||||
|
cost_multiplier = 1.55
|
||||||
18
generator/buffs/magic_supply_cache.tres
Normal file
18
generator/buffs/magic_supply_cache.tres
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[gd_resource type="Resource" script_class="GeneratorBuffData" format=3 uid="uid://cluds3cw1d65q"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://dnhocfsuvmeyb" path="res://generator/generator_buff_data.gd" id="1_fvte4"]
|
||||||
|
[ext_resource type="Resource" uid="uid://brqaojindcxa5" path="res://currency/magic.tres" id="2_ea8w5"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_fvte4")
|
||||||
|
id = &"magic_supply_cache"
|
||||||
|
kind = 2
|
||||||
|
text = "Mana Cache"
|
||||||
|
max_level = 25
|
||||||
|
effect_increment = 0.0
|
||||||
|
cost_currency = ExtResource("2_ea8w5")
|
||||||
|
base_cost_mantissa = 12.0
|
||||||
|
cost_multiplier = 1.6
|
||||||
|
resource_target_currency = ExtResource("2_ea8w5")
|
||||||
|
resource_purchase_base_mantissa = 12.0
|
||||||
|
resource_purchase_increment_multiplier = 1.45
|
||||||
@@ -13,6 +13,10 @@ signal purchase_completed(amount: int, total_owned: int, total_purchased: int, t
|
|||||||
signal purchase_failed(requested_amount: int, required_cost: BigNumber, available_currency: BigNumber)
|
signal purchase_failed(requested_amount: int, required_cost: BigNumber, available_currency: BigNumber)
|
||||||
## Emitted when one or more automatic production cycles complete.
|
## Emitted when one or more automatic production cycles complete.
|
||||||
signal production_tick(amount: BigNumber, cycle_count: int, total_owned: int)
|
signal production_tick(amount: BigNumber, cycle_count: int, total_owned: int)
|
||||||
|
## Emitted after a successful buff purchase.
|
||||||
|
signal buff_purchased(buff_id: StringName, new_level: int, cost: BigNumber, cost_currency_id: StringName)
|
||||||
|
## Emitted when a buff purchase cannot be paid.
|
||||||
|
signal buff_purchase_failed(buff_id: StringName, required_cost: BigNumber, cost_currency_id: StringName)
|
||||||
|
|
||||||
## Sentinel exponent used when cost math overflows float range.
|
## Sentinel exponent used when cost math overflows float range.
|
||||||
const HUGE_COST_EXPONENT: int = 1000000
|
const HUGE_COST_EXPONENT: int = 1000000
|
||||||
@@ -119,7 +123,8 @@ func _grant_cycle_income(cycle_count: int) -> void:
|
|||||||
if data == null or cycle_count <= 0:
|
if data == null or cycle_count <= 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
var per_cycle: float = data.production_per_cycle(owned, run_multiplier, purchased_count)
|
var effective_run_multiplier: float = run_multiplier * get_automatic_production_multiplier()
|
||||||
|
var per_cycle: float = data.production_per_cycle(owned, effective_run_multiplier, purchased_count)
|
||||||
if per_cycle <= 0.0:
|
if per_cycle <= 0.0:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -195,6 +200,89 @@ func buy_max() -> int:
|
|||||||
return 0
|
return 0
|
||||||
return best if buy(best) else 0
|
return best if buy(best) else 0
|
||||||
|
|
||||||
|
func get_buffs() -> Array[GeneratorBuffData]:
|
||||||
|
if data == null:
|
||||||
|
return []
|
||||||
|
return data.buffs
|
||||||
|
|
||||||
|
func get_buff_level(buff_id: StringName) -> int:
|
||||||
|
_ensure_registered()
|
||||||
|
return GameState.get_generator_buff_level(_generator_id, buff_id)
|
||||||
|
|
||||||
|
func get_buff_cost(buff_id: StringName) -> BigNumber:
|
||||||
|
var buff: GeneratorBuffData = _find_buff(buff_id)
|
||||||
|
if buff == null:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
|
||||||
|
var level: int = get_buff_level(buff.id)
|
||||||
|
return buff.get_cost_for_level(level)
|
||||||
|
|
||||||
|
func get_buff_cost_currency_id(buff_id: StringName) -> StringName:
|
||||||
|
var buff: GeneratorBuffData = _find_buff(buff_id)
|
||||||
|
if buff == null:
|
||||||
|
return &""
|
||||||
|
return _resolve_buff_cost_currency_id(buff)
|
||||||
|
|
||||||
|
func can_buy_buff(buff_id: StringName) -> bool:
|
||||||
|
if not is_available_to_player():
|
||||||
|
return false
|
||||||
|
|
||||||
|
var buff: GeneratorBuffData = _find_buff(buff_id)
|
||||||
|
if buff == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var current_level: int = get_buff_level(buff.id)
|
||||||
|
if not buff.can_purchase_next_level(current_level):
|
||||||
|
return false
|
||||||
|
|
||||||
|
var cost_currency_id: StringName = _resolve_buff_cost_currency_id(buff)
|
||||||
|
if cost_currency_id == &"":
|
||||||
|
return false
|
||||||
|
|
||||||
|
var cost: BigNumber = buff.get_cost_for_level(current_level)
|
||||||
|
var current_amount: BigNumber = GameState.get_currency_amount_by_id(cost_currency_id)
|
||||||
|
return current_amount.is_greater_than(cost) or current_amount.is_equal_to(cost)
|
||||||
|
|
||||||
|
func buy_buff(buff_id: StringName) -> bool:
|
||||||
|
if not is_available_to_player():
|
||||||
|
return false
|
||||||
|
|
||||||
|
var buff: GeneratorBuffData = _find_buff(buff_id)
|
||||||
|
if buff == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var current_level: int = get_buff_level(buff.id)
|
||||||
|
if not buff.can_purchase_next_level(current_level):
|
||||||
|
return false
|
||||||
|
|
||||||
|
var cost: BigNumber = buff.get_cost_for_level(current_level)
|
||||||
|
var cost_currency_id: StringName = _resolve_buff_cost_currency_id(buff)
|
||||||
|
if cost_currency_id == &"":
|
||||||
|
return false
|
||||||
|
|
||||||
|
if not _spend_currency_by_id(cost_currency_id, cost):
|
||||||
|
buff_purchase_failed.emit(buff.id, cost, cost_currency_id)
|
||||||
|
return false
|
||||||
|
|
||||||
|
var next_level: int = current_level + 1
|
||||||
|
GameState.set_generator_buff_level(_generator_id, buff.id, next_level)
|
||||||
|
_apply_resource_purchase_buff(buff, next_level)
|
||||||
|
buff_purchased.emit(buff.id, next_level, cost, cost_currency_id)
|
||||||
|
return true
|
||||||
|
|
||||||
|
func is_buff_maxed(buff_id: StringName) -> bool:
|
||||||
|
var buff: GeneratorBuffData = _find_buff(buff_id)
|
||||||
|
if buff == null:
|
||||||
|
return true
|
||||||
|
|
||||||
|
return not buff.can_purchase_next_level(get_buff_level(buff.id))
|
||||||
|
|
||||||
|
func get_automatic_production_multiplier() -> float:
|
||||||
|
return _get_multiplier_for_buff_kind(GeneratorBuffData.BuffKind.AUTO_PRODUCTION_MULTIPLIER)
|
||||||
|
|
||||||
|
func get_manual_click_multiplier() -> float:
|
||||||
|
return _get_multiplier_for_buff_kind(GeneratorBuffData.BuffKind.MANUAL_CLICK_MULTIPLIER)
|
||||||
|
|
||||||
## Handles external "pressed" interaction: buy if configured, otherwise click-grant.
|
## Handles external "pressed" interaction: buy if configured, otherwise click-grant.
|
||||||
func _on_pressed() -> void:
|
func _on_pressed() -> void:
|
||||||
if not is_available_to_player():
|
if not is_available_to_player():
|
||||||
@@ -235,7 +323,13 @@ func _try_grant_click_currency() -> void:
|
|||||||
func _get_click_value() -> BigNumber:
|
func _get_click_value() -> BigNumber:
|
||||||
if data == null:
|
if data == null:
|
||||||
return BigNumber.from_float(0.0)
|
return BigNumber.from_float(0.0)
|
||||||
return BigNumber.new(data.click_mantissa, data.click_exponent)
|
|
||||||
|
var click_multiplier: float = get_manual_click_multiplier()
|
||||||
|
if click_multiplier <= 0.0:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
|
||||||
|
var base_click: BigNumber = BigNumber.new(data.click_mantissa, data.click_exponent)
|
||||||
|
return base_click.multiply(BigNumber.from_float(click_multiplier))
|
||||||
|
|
||||||
## Resolves click cooldown from data.
|
## Resolves click cooldown from data.
|
||||||
func _get_click_cooldown_seconds() -> float:
|
func _get_click_cooldown_seconds() -> float:
|
||||||
@@ -268,6 +362,12 @@ func _add_currency(amount: BigNumber) -> void:
|
|||||||
|
|
||||||
GameState.add_currency(currency, amount)
|
GameState.add_currency(currency, amount)
|
||||||
|
|
||||||
|
func _add_currency_by_id(currency_id: StringName, amount: BigNumber) -> void:
|
||||||
|
if currency_id == &"":
|
||||||
|
return
|
||||||
|
|
||||||
|
GameState.add_currency_by_id(currency_id, amount)
|
||||||
|
|
||||||
## Attempts to spend target currency; returns false when insufficient.
|
## Attempts to spend target currency; returns false when insufficient.
|
||||||
func _spend_currency(cost: BigNumber) -> bool:
|
func _spend_currency(cost: BigNumber) -> bool:
|
||||||
if currency == null:
|
if currency == null:
|
||||||
@@ -276,6 +376,12 @@ func _spend_currency(cost: BigNumber) -> bool:
|
|||||||
|
|
||||||
return GameState.spend_currency(currency, cost)
|
return GameState.spend_currency(currency, cost)
|
||||||
|
|
||||||
|
func _spend_currency_by_id(currency_id: StringName, cost: BigNumber) -> bool:
|
||||||
|
if currency_id == &"":
|
||||||
|
return false
|
||||||
|
|
||||||
|
return GameState.spend_currency_by_id(currency_id, cost)
|
||||||
|
|
||||||
## Returns the current amount for the configured currency type.
|
## Returns the current amount for the configured currency type.
|
||||||
func _get_currency_amount() -> BigNumber:
|
func _get_currency_amount() -> BigNumber:
|
||||||
if currency == null:
|
if currency == null:
|
||||||
@@ -300,6 +406,59 @@ func _big_number_to_float(value: BigNumber) -> float:
|
|||||||
return 0.0
|
return 0.0
|
||||||
return value.mantissa * pow(10.0, float(value.exponent))
|
return value.mantissa * pow(10.0, float(value.exponent))
|
||||||
|
|
||||||
|
func _find_buff(buff_id: StringName) -> GeneratorBuffData:
|
||||||
|
if data == null:
|
||||||
|
return null
|
||||||
|
return data.find_buff(buff_id)
|
||||||
|
|
||||||
|
func _resolve_buff_cost_currency_id(buff: GeneratorBuffData) -> StringName:
|
||||||
|
if buff == null:
|
||||||
|
return &""
|
||||||
|
|
||||||
|
var cost_currency: Resource = buff.cost_currency if buff.cost_currency != null else currency
|
||||||
|
if cost_currency == null:
|
||||||
|
return &""
|
||||||
|
|
||||||
|
return GameState.get_currency_id(cost_currency)
|
||||||
|
|
||||||
|
func _resolve_buff_target_currency_id(buff: GeneratorBuffData) -> StringName:
|
||||||
|
if buff == null:
|
||||||
|
return &""
|
||||||
|
|
||||||
|
var target_currency: Resource = buff.resource_target_currency if buff.resource_target_currency != null else currency
|
||||||
|
if target_currency == null:
|
||||||
|
return &""
|
||||||
|
|
||||||
|
return GameState.get_currency_id(target_currency)
|
||||||
|
|
||||||
|
func _get_multiplier_for_buff_kind(kind: GeneratorBuffData.BuffKind) -> float:
|
||||||
|
var multiplier: float = 1.0
|
||||||
|
for buff in get_buffs():
|
||||||
|
if buff == null:
|
||||||
|
continue
|
||||||
|
if buff.kind != kind:
|
||||||
|
continue
|
||||||
|
|
||||||
|
multiplier *= buff.get_effect_multiplier(get_buff_level(buff.id))
|
||||||
|
|
||||||
|
return maxf(multiplier, 0.0)
|
||||||
|
|
||||||
|
func _apply_resource_purchase_buff(buff: GeneratorBuffData, level: int) -> void:
|
||||||
|
if buff == null:
|
||||||
|
return
|
||||||
|
if buff.kind != GeneratorBuffData.BuffKind.RESOURCE_PURCHASE:
|
||||||
|
return
|
||||||
|
|
||||||
|
var target_currency_id: StringName = _resolve_buff_target_currency_id(buff)
|
||||||
|
if target_currency_id == &"":
|
||||||
|
return
|
||||||
|
|
||||||
|
var purchased_amount: BigNumber = buff.get_resource_purchase_amount_for_level(level)
|
||||||
|
if purchased_amount.mantissa <= 0.0:
|
||||||
|
return
|
||||||
|
|
||||||
|
_add_currency_by_id(target_currency_id, purchased_amount)
|
||||||
|
|
||||||
## Builds a stable state id from data id, node name, or fallback string.
|
## Builds a stable state id from data id, node name, or fallback string.
|
||||||
func _resolve_generator_id() -> StringName:
|
func _resolve_generator_id() -> StringName:
|
||||||
if data != null:
|
if data != null:
|
||||||
@@ -323,8 +482,20 @@ func _ensure_registered() -> void:
|
|||||||
return
|
return
|
||||||
|
|
||||||
GameState.register_generator(_generator_id, _default_unlocked_state(), _default_available_state())
|
GameState.register_generator(_generator_id, _default_unlocked_state(), _default_available_state())
|
||||||
|
_register_buffs()
|
||||||
_is_registered = true
|
_is_registered = true
|
||||||
|
|
||||||
|
func _register_buffs() -> void:
|
||||||
|
for buff in get_buffs():
|
||||||
|
if buff == null:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var buff_id_text: String = String(buff.id).strip_edges()
|
||||||
|
if buff_id_text.is_empty():
|
||||||
|
continue
|
||||||
|
|
||||||
|
GameState.register_generator_buff(_generator_id, StringName(buff_id_text), 0)
|
||||||
|
|
||||||
## Default unlocked state loaded from generator data.
|
## Default unlocked state loaded from generator data.
|
||||||
func _default_unlocked_state() -> bool:
|
func _default_unlocked_state() -> bool:
|
||||||
if data == null:
|
if data == null:
|
||||||
@@ -345,9 +516,6 @@ func _on_area_2d_mouse_entered() -> void:
|
|||||||
func _on_area_2d_mouse_exited() -> void:
|
func _on_area_2d_mouse_exited() -> void:
|
||||||
_mouse_entered = false
|
_mouse_entered = false
|
||||||
|
|
||||||
func _on_generated_state_changed(generator_id: StringName, state: Dictionary) -> void:
|
func _on_generated_state_changed(generator_id: StringName, _state: Dictionary) -> void:
|
||||||
if generator_id == _generator_id:
|
if generator_id == _generator_id:
|
||||||
print(_generator_id)
|
|
||||||
print(state)
|
|
||||||
visible = true
|
visible = true
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,22 @@ extends Resource
|
|||||||
@export var click_exponent: int = 0
|
@export var click_exponent: int = 0
|
||||||
@export var click_cooldown_seconds: float = 0.2
|
@export var click_cooldown_seconds: float = 0.2
|
||||||
|
|
||||||
|
## Data-driven buffs purchasable for this generator.
|
||||||
|
@export var buffs: Array[GeneratorBuffData] = []
|
||||||
|
|
||||||
|
func find_buff(buff_id: StringName) -> GeneratorBuffData:
|
||||||
|
var expected_id: String = String(buff_id).strip_edges()
|
||||||
|
if expected_id.is_empty():
|
||||||
|
return null
|
||||||
|
|
||||||
|
for buff in buffs:
|
||||||
|
if buff == null:
|
||||||
|
continue
|
||||||
|
if String(buff.id) == expected_id:
|
||||||
|
return buff
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
## Returns cost of next generator
|
## Returns cost of next generator
|
||||||
func cost_next(owned: int) -> float:
|
func cost_next(owned: int) -> float:
|
||||||
return cost_for_amount(owned, 1)
|
return cost_for_amount(owned, 1)
|
||||||
|
|||||||
95
generator/generator_buff_data.gd
Normal file
95
generator/generator_buff_data.gd
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
class_name GeneratorBuffData
|
||||||
|
extends Resource
|
||||||
|
|
||||||
|
enum BuffKind {
|
||||||
|
AUTO_PRODUCTION_MULTIPLIER,
|
||||||
|
MANUAL_CLICK_MULTIPLIER,
|
||||||
|
RESOURCE_PURCHASE,
|
||||||
|
}
|
||||||
|
|
||||||
|
const HUGE_EXPONENT: int = 1000000
|
||||||
|
|
||||||
|
@export var id: StringName = &""
|
||||||
|
@export var kind: BuffKind = BuffKind.AUTO_PRODUCTION_MULTIPLIER
|
||||||
|
@export_multiline var text: String = ""
|
||||||
|
@export var icon: Texture2D
|
||||||
|
@export var max_level: int = -1
|
||||||
|
|
||||||
|
@export_group("Effect")
|
||||||
|
@export var base_effect: float = 1.0
|
||||||
|
@export var effect_increment: float = 0.1
|
||||||
|
|
||||||
|
@export_group("Cost")
|
||||||
|
@export var cost_currency: Resource
|
||||||
|
@export var base_cost_mantissa: float = 10.0
|
||||||
|
@export var base_cost_exponent: int = 0
|
||||||
|
@export var cost_multiplier: float = 1.5
|
||||||
|
|
||||||
|
@export_group("Resource Purchase")
|
||||||
|
@export var resource_target_currency: Resource
|
||||||
|
@export var resource_purchase_base_mantissa: float = 10.0
|
||||||
|
@export var resource_purchase_base_exponent: int = 0
|
||||||
|
@export var resource_purchase_increment_multiplier: float = 1.2
|
||||||
|
|
||||||
|
func can_purchase_next_level(current_level: int) -> bool:
|
||||||
|
if max_level < 0:
|
||||||
|
return true
|
||||||
|
return maxi(current_level, 0) < max_level
|
||||||
|
|
||||||
|
func get_effect_multiplier(level: int) -> float:
|
||||||
|
var safe_level: int = maxi(level, 0)
|
||||||
|
return maxf(base_effect + (effect_increment * float(safe_level)), 0.0)
|
||||||
|
|
||||||
|
func get_cost_for_level(level: int) -> BigNumber:
|
||||||
|
var safe_level: int = maxi(level, 0)
|
||||||
|
var base_cost: BigNumber = BigNumber.new(base_cost_mantissa, base_cost_exponent)
|
||||||
|
if base_cost.mantissa <= 0.0:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
|
||||||
|
if cost_multiplier <= 0.0:
|
||||||
|
return BigNumber.new(1.0, HUGE_EXPONENT)
|
||||||
|
|
||||||
|
var growth: float = 1.0
|
||||||
|
if not is_equal_approx(cost_multiplier, 1.0):
|
||||||
|
growth = pow(cost_multiplier, float(safe_level))
|
||||||
|
if not is_finite(growth):
|
||||||
|
return BigNumber.new(1.0, HUGE_EXPONENT)
|
||||||
|
|
||||||
|
return _scale_big_number(base_cost, growth)
|
||||||
|
|
||||||
|
func get_resource_purchase_amount_for_level(level: int) -> BigNumber:
|
||||||
|
var safe_level: int = maxi(level, 0)
|
||||||
|
var base_amount: BigNumber = BigNumber.new(resource_purchase_base_mantissa, resource_purchase_base_exponent)
|
||||||
|
if base_amount.mantissa <= 0.0:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
|
||||||
|
if resource_purchase_increment_multiplier <= 0.0:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
|
||||||
|
var growth: float = 1.0
|
||||||
|
if not is_equal_approx(resource_purchase_increment_multiplier, 1.0):
|
||||||
|
growth = pow(resource_purchase_increment_multiplier, float(safe_level))
|
||||||
|
if not is_finite(growth):
|
||||||
|
return BigNumber.new(1.0, HUGE_EXPONENT)
|
||||||
|
|
||||||
|
return _scale_big_number(base_amount, growth)
|
||||||
|
|
||||||
|
func get_effect_description(level: int) -> String:
|
||||||
|
var safe_level: int = maxi(level, 0)
|
||||||
|
match kind:
|
||||||
|
BuffKind.AUTO_PRODUCTION_MULTIPLIER, BuffKind.MANUAL_CLICK_MULTIPLIER:
|
||||||
|
return "x%.2f" % get_effect_multiplier(safe_level)
|
||||||
|
BuffKind.RESOURCE_PURCHASE:
|
||||||
|
return "+%s" % get_resource_purchase_amount_for_level(safe_level).to_string_suffix(2)
|
||||||
|
_:
|
||||||
|
return "-"
|
||||||
|
|
||||||
|
func _scale_big_number(base_amount: BigNumber, scale: float) -> BigNumber:
|
||||||
|
if base_amount.mantissa <= 0.0:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
if scale <= 0.0:
|
||||||
|
return BigNumber.from_float(0.0)
|
||||||
|
if not is_finite(scale):
|
||||||
|
return BigNumber.new(1.0, HUGE_EXPONENT)
|
||||||
|
|
||||||
|
return base_amount.multiply(BigNumber.from_float(scale))
|
||||||
1
generator/generator_buff_data.gd.uid
Normal file
1
generator/generator_buff_data.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dnhocfsuvmeyb
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
[gd_resource type="Resource" script_class="CurrencyGeneratorData" format=3 uid="uid://co0mcc2kvcpo5"]
|
[gd_resource type="Resource" script_class="CurrencyGeneratorData" format=3 uid="uid://co0mcc2kvcpo5"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://b00tqsuhxdy0d" path="res://generator/currency_generator_data.gd" id="1_c6y77"]
|
[ext_resource type="Script" uid="uid://b00tqsuhxdy0d" path="res://generator/currency_generator_data.gd" id="1_c6y77"]
|
||||||
|
[ext_resource type="Resource" path="res://generator/buffs/magic_auto_flux.tres" id="2_x505b"]
|
||||||
|
[ext_resource type="Resource" path="res://generator/buffs/magic_click_focus.tres" id="3_fsxdm"]
|
||||||
|
[ext_resource type="Resource" path="res://generator/buffs/magic_supply_cache.tres" id="4_x2byu"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_c6y77")
|
script = ExtResource("1_c6y77")
|
||||||
@@ -8,4 +11,5 @@ id = &"Magic"
|
|||||||
name = "Magic Orb"
|
name = "Magic Orb"
|
||||||
initial_time = 0.6
|
initial_time = 0.6
|
||||||
initial_productivity = 1.67
|
initial_productivity = 1.67
|
||||||
|
buffs = [ExtResource("2_x505b"), ExtResource("3_fsxdm"), ExtResource("4_x2byu")]
|
||||||
metadata/_custom_type_script = "uid://b00tqsuhxdy0d"
|
metadata/_custom_type_script = "uid://b00tqsuhxdy0d"
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
[gd_resource type="Resource" script_class="CurrencyGeneratorData" format=3 uid="uid://04pmc034qupd"]
|
[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"]
|
[ext_resource type="Script" uid="uid://b00tqsuhxdy0d" path="res://generator/currency_generator_data.gd" id="1_s3g28"]
|
||||||
|
[ext_resource type="Resource" path="res://generator/buffs/knowledge_auto_treatise.tres" id="2_kxvfc"]
|
||||||
|
[ext_resource type="Resource" path="res://generator/buffs/knowledge_click_notes.tres" id="3_q64x8"]
|
||||||
|
[ext_resource type="Resource" path="res://generator/buffs/knowledge_grant_program.tres" id="4_l77sg"]
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
script = ExtResource("1_s3g28")
|
script = ExtResource("1_s3g28")
|
||||||
@@ -12,4 +15,5 @@ initial_cost = 60.0
|
|||||||
initial_time = 3.0
|
initial_time = 3.0
|
||||||
initial_revenue = 60.0
|
initial_revenue = 60.0
|
||||||
initial_productivity = 20.0
|
initial_productivity = 20.0
|
||||||
|
buffs = [ExtResource("2_kxvfc"), ExtResource("3_q64x8"), ExtResource("4_l77sg")]
|
||||||
metadata/_custom_type_script = "uid://b00tqsuhxdy0d"
|
metadata/_custom_type_script = "uid://b00tqsuhxdy0d"
|
||||||
|
|||||||
48
generator_buff_tile.gd
Normal file
48
generator_buff_tile.gd
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
class_name GeneratorBuffTile
|
||||||
|
extends HBoxContainer
|
||||||
|
|
||||||
|
signal buy_pressed(buff_id: StringName)
|
||||||
|
|
||||||
|
@onready var _icon: TextureRect = $Icon
|
||||||
|
@onready var _text_label: Label = $TextLabel
|
||||||
|
@onready var _level_label: Label = $LevelLabel
|
||||||
|
@onready var _effect_label: Label = $EffectLabel
|
||||||
|
@onready var _cost_label: Label = $CostLabel
|
||||||
|
@onready var _buy_button: Button = $BuyButton
|
||||||
|
|
||||||
|
var _buff_id: StringName = &""
|
||||||
|
|
||||||
|
func set_buff(buff: GeneratorBuffData) -> void:
|
||||||
|
if buff == null:
|
||||||
|
_buff_id = &""
|
||||||
|
_icon.texture = null
|
||||||
|
_icon.visible = false
|
||||||
|
_text_label.text = "Unknown Buff"
|
||||||
|
return
|
||||||
|
|
||||||
|
var buff_id_text: String = String(buff.id).strip_edges()
|
||||||
|
_buff_id = StringName(buff_id_text)
|
||||||
|
|
||||||
|
_icon.texture = buff.icon
|
||||||
|
_icon.visible = buff.icon != null
|
||||||
|
_text_label.text = buff.text if not buff.text.strip_edges().is_empty() else buff_id_text
|
||||||
|
|
||||||
|
func set_runtime(level: int, effect_text: String, cost_text: String, can_buy: bool, is_maxed: bool) -> void:
|
||||||
|
_level_label.text = "Lv %d" % maxi(level, 0)
|
||||||
|
_effect_label.text = effect_text
|
||||||
|
|
||||||
|
if is_maxed:
|
||||||
|
_cost_label.text = "Max level"
|
||||||
|
_buy_button.text = "Max"
|
||||||
|
_buy_button.disabled = true
|
||||||
|
return
|
||||||
|
|
||||||
|
_cost_label.text = cost_text
|
||||||
|
_buy_button.text = "Buy"
|
||||||
|
_buy_button.disabled = not can_buy
|
||||||
|
|
||||||
|
func _on_buy_button_pressed() -> void:
|
||||||
|
if _buff_id == &"":
|
||||||
|
return
|
||||||
|
|
||||||
|
buy_pressed.emit(_buff_id)
|
||||||
1
generator_buff_tile.gd.uid
Normal file
1
generator_buff_tile.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bsu10r1nhmhw1
|
||||||
41
generator_buff_tile.tscn
Normal file
41
generator_buff_tile.tscn
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
[gd_scene format=3 uid="uid://g1w168ancuxi"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://bsu10r1nhmhw1" path="res://generator_buff_tile.gd" id="1_wdw66"]
|
||||||
|
|
||||||
|
[node name="GeneratorBuffTile" type="HBoxContainer" unique_id=50960329]
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_constants/separation = 8
|
||||||
|
script = ExtResource("1_wdw66")
|
||||||
|
|
||||||
|
[node name="Icon" type="TextureRect" parent="." unique_id=1130513269]
|
||||||
|
visible = false
|
||||||
|
custom_minimum_size = Vector2(18, 18)
|
||||||
|
layout_mode = 2
|
||||||
|
stretch_mode = 5
|
||||||
|
|
||||||
|
[node name="TextLabel" type="Label" parent="." unique_id=2066010368]
|
||||||
|
custom_minimum_size = Vector2(140, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Buff"
|
||||||
|
|
||||||
|
[node name="LevelLabel" type="Label" parent="." unique_id=1101640559]
|
||||||
|
custom_minimum_size = Vector2(50, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Lv 0"
|
||||||
|
|
||||||
|
[node name="EffectLabel" type="Label" parent="." unique_id=976763452]
|
||||||
|
custom_minimum_size = Vector2(90, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "x1.00"
|
||||||
|
|
||||||
|
[node name="CostLabel" type="Label" parent="." unique_id=246779202]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "0"
|
||||||
|
|
||||||
|
[node name="BuyButton" type="Button" parent="." unique_id=1815270585]
|
||||||
|
custom_minimum_size = Vector2(68, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Buy"
|
||||||
|
|
||||||
|
[connection signal="pressed" from="BuyButton" to="." method="_on_buy_button_pressed"]
|
||||||
@@ -1,5 +1,15 @@
|
|||||||
extends VBoxContainer
|
extends VBoxContainer
|
||||||
|
|
||||||
|
const GENERATOR_BUFF_TILE_SCENE: PackedScene = preload("res://generator_buff_tile.tscn")
|
||||||
|
|
||||||
|
class BuffRow extends RefCounted:
|
||||||
|
var buff: GeneratorBuffData
|
||||||
|
var tile: GeneratorBuffTile
|
||||||
|
|
||||||
|
func _init(row_buff: GeneratorBuffData, row_tile: GeneratorBuffTile) -> void:
|
||||||
|
buff = row_buff
|
||||||
|
tile = row_tile
|
||||||
|
|
||||||
@export var _generator: CurrencyGenerator
|
@export var _generator: CurrencyGenerator
|
||||||
|
|
||||||
@onready var _buy_button: Button = $HBoxContainerGenerators/BuyOneButton
|
@onready var _buy_button: Button = $HBoxContainerGenerators/BuyOneButton
|
||||||
@@ -8,16 +18,28 @@ extends VBoxContainer
|
|||||||
@onready var _owned_value: Label = $GeneratorStatsGrid/OwnedValue
|
@onready var _owned_value: Label = $GeneratorStatsGrid/OwnedValue
|
||||||
@onready var _next_cost_value: Label = $GeneratorStatsGrid/NextCostValue
|
@onready var _next_cost_value: Label = $GeneratorStatsGrid/NextCostValue
|
||||||
@onready var _production_value: Label = $GeneratorStatsGrid/ProductionValue
|
@onready var _production_value: Label = $GeneratorStatsGrid/ProductionValue
|
||||||
|
@onready var _buffs_section: VBoxContainer = $BuffsSection
|
||||||
|
@onready var _buffs_list: VBoxContainer = $BuffsSection/BuffsList
|
||||||
|
|
||||||
|
var _buff_rows: Array[BuffRow] = []
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
if _generator == null:
|
||||||
|
push_warning("GeneratorContainer '%s' has no generator assigned." % String(name))
|
||||||
|
return
|
||||||
|
|
||||||
_generator.purchase_completed.connect(_on_generator_updated)
|
_generator.purchase_completed.connect(_on_generator_updated)
|
||||||
_generator.production_tick.connect(_on_generator_updated)
|
_generator.production_tick.connect(_on_generator_updated)
|
||||||
_generator.purchase_failed.connect(_on_generator_updated)
|
_generator.purchase_failed.connect(_on_generator_updated)
|
||||||
|
_generator.buff_purchased.connect(_on_generator_updated)
|
||||||
|
_generator.buff_purchase_failed.connect(_on_generator_updated)
|
||||||
GameState.currency_changed.connect(_on_currency_changed)
|
GameState.currency_changed.connect(_on_currency_changed)
|
||||||
|
|
||||||
GameState.generator_state_changed.connect(_on_generator_state_changed)
|
GameState.generator_state_changed.connect(_on_generator_state_changed)
|
||||||
|
GameState.generator_buff_level_changed.connect(_on_generator_buff_level_changed)
|
||||||
|
|
||||||
_name_label.text = _generator.data.name if _generator.data != null else "Generator"
|
_name_label.text = _generator.data.name if _generator.data != null else "Generator"
|
||||||
|
_build_buff_rows()
|
||||||
_refresh_generator_ui()
|
_refresh_generator_ui()
|
||||||
|
|
||||||
func _on_buy_pressed() -> void:
|
func _on_buy_pressed() -> void:
|
||||||
@@ -32,9 +54,7 @@ func _on_debug_income_pressed() -> void:
|
|||||||
_generator.grant_currency(BigNumber.from_float(100.0))
|
_generator.grant_currency(BigNumber.from_float(100.0))
|
||||||
_refresh_generator_ui()
|
_refresh_generator_ui()
|
||||||
|
|
||||||
func _on_currency_changed(changed_currency_id: StringName, _new_value: BigNumber) -> void:
|
func _on_currency_changed(_changed_currency_id: StringName, _new_value: BigNumber) -> void:
|
||||||
if changed_currency_id != _generator.get_currency_id():
|
|
||||||
return
|
|
||||||
_refresh_generator_ui()
|
_refresh_generator_ui()
|
||||||
|
|
||||||
func _on_generator_updated(_a = null, _b = null, _c = null, _d = null) -> void:
|
func _on_generator_updated(_a = null, _b = null, _c = null, _d = null) -> void:
|
||||||
@@ -44,6 +64,63 @@ func _on_generator_state_changed(generator_id: StringName, _state: Dictionary) -
|
|||||||
if generator_id == _generator.get_generator_id():
|
if generator_id == _generator.get_generator_id():
|
||||||
visible = true
|
visible = true
|
||||||
_refresh_generator_ui()
|
_refresh_generator_ui()
|
||||||
|
|
||||||
|
func _on_generator_buff_level_changed(generator_id: StringName, _buff_id: StringName, _new_level: int) -> void:
|
||||||
|
if generator_id != _generator.get_generator_id():
|
||||||
|
return
|
||||||
|
|
||||||
|
_refresh_generator_ui()
|
||||||
|
|
||||||
|
func _on_buy_buff_pressed(buff_id: StringName) -> void:
|
||||||
|
_generator.buy_buff(buff_id)
|
||||||
|
_refresh_generator_ui()
|
||||||
|
|
||||||
|
func _build_buff_rows() -> void:
|
||||||
|
_buff_rows.clear()
|
||||||
|
for child in _buffs_list.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
|
||||||
|
for buff in _generator.get_buffs():
|
||||||
|
if buff == null:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var buff_id_text: String = String(buff.id).strip_edges()
|
||||||
|
if buff_id_text.is_empty():
|
||||||
|
continue
|
||||||
|
|
||||||
|
var tile: GeneratorBuffTile = GENERATOR_BUFF_TILE_SCENE.instantiate() as GeneratorBuffTile
|
||||||
|
if tile == null:
|
||||||
|
push_warning("Failed to instantiate GeneratorBuffTile for buff '%s'." % buff_id_text)
|
||||||
|
continue
|
||||||
|
|
||||||
|
_buffs_list.add_child(tile)
|
||||||
|
tile.set_buff(buff)
|
||||||
|
tile.buy_pressed.connect(_on_buy_buff_pressed)
|
||||||
|
_buff_rows.append(BuffRow.new(buff, tile))
|
||||||
|
|
||||||
|
func _refresh_buff_rows(can_interact: bool) -> void:
|
||||||
|
_buffs_section.visible = not _buff_rows.is_empty()
|
||||||
|
if _buff_rows.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
for row in _buff_rows:
|
||||||
|
if row == null or row.buff == null or row.tile == null:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var buff: GeneratorBuffData = row.buff
|
||||||
|
var level: int = _generator.get_buff_level(buff.id)
|
||||||
|
var effect_text: String = buff.get_effect_description(level)
|
||||||
|
|
||||||
|
if _generator.is_buff_maxed(buff.id):
|
||||||
|
row.tile.set_runtime(level, effect_text, "", false, true)
|
||||||
|
continue
|
||||||
|
|
||||||
|
var cost: BigNumber = _generator.get_buff_cost(buff.id)
|
||||||
|
var cost_currency_id: StringName = _generator.get_buff_cost_currency_id(buff.id)
|
||||||
|
var currency_label: String = GameState.get_currency_name(cost_currency_id)
|
||||||
|
var cost_text: String = "%s %s" % [cost.to_string_suffix(2), currency_label]
|
||||||
|
var can_buy: bool = can_interact and _generator.can_buy_buff(buff.id)
|
||||||
|
row.tile.set_runtime(level, effect_text, cost_text, can_buy, false)
|
||||||
|
|
||||||
func _refresh_generator_ui() -> void:
|
func _refresh_generator_ui() -> void:
|
||||||
var can_interact: bool = _generator.is_available_to_player()
|
var can_interact: bool = _generator.is_available_to_player()
|
||||||
@@ -57,8 +134,9 @@ func _refresh_generator_ui() -> void:
|
|||||||
if _generator.data != null and can_interact:
|
if _generator.data != null and can_interact:
|
||||||
production_per_second = _generator.data.production_per_second(
|
production_per_second = _generator.data.production_per_second(
|
||||||
_generator.owned,
|
_generator.owned,
|
||||||
_generator.run_multiplier,
|
_generator.run_multiplier * _generator.get_automatic_production_multiplier(),
|
||||||
_generator.purchased_count
|
_generator.purchased_count
|
||||||
)
|
)
|
||||||
|
|
||||||
_production_value.text = BigNumber.from_float(production_per_second).to_string_suffix(2)
|
_production_value.text = BigNumber.from_float(production_per_second).to_string_suffix(2)
|
||||||
|
_refresh_buff_rows(can_interact)
|
||||||
|
|||||||
@@ -60,5 +60,16 @@ text = "Production / sec"
|
|||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "0"
|
text = "0"
|
||||||
|
|
||||||
|
[node name="BuffsSection" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="BuffsTitle" type="Label" parent="BuffsSection"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Buffs"
|
||||||
|
|
||||||
|
[node name="BuffsList" type="VBoxContainer" parent="BuffsSection"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 4
|
||||||
|
|
||||||
[connection signal="pressed" from="HBoxContainerGenerators/BuyOneButton" to="." method="_on_buy_pressed"]
|
[connection signal="pressed" from="HBoxContainerGenerators/BuyOneButton" to="." method="_on_buy_pressed"]
|
||||||
[connection signal="pressed" from="HBoxContainerGenerators/BuyMaxButton" to="." method="_on_buy_max_pressed"]
|
[connection signal="pressed" from="HBoxContainerGenerators/BuyMaxButton" to="." method="_on_buy_max_pressed"]
|
||||||
|
|||||||
@@ -41,18 +41,18 @@ currency = ExtResource("6_gemsc")
|
|||||||
[node name="MagicGeneratorContainer" parent="UI" unique_id=1129190041 node_paths=PackedStringArray("_generator") instance=ExtResource("3_pw2a0")]
|
[node name="MagicGeneratorContainer" parent="UI" unique_id=1129190041 node_paths=PackedStringArray("_generator") instance=ExtResource("3_pw2a0")]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
offset_left = -19.0
|
offset_left = -19.0
|
||||||
offset_top = 53.0
|
offset_top = 50.5
|
||||||
offset_right = 245.0
|
offset_right = 422.0
|
||||||
offset_bottom = 218.0
|
offset_bottom = 316.0
|
||||||
_generator = NodePath("../../MagicGenerator")
|
_generator = NodePath("../../MagicGenerator")
|
||||||
|
|
||||||
[node name="KnowledgeGeneratorContainer" parent="UI" unique_id=1999544736 node_paths=PackedStringArray("_generator") instance=ExtResource("3_pw2a0")]
|
[node name="KnowledgeGeneratorContainer" parent="UI" unique_id=1999544736 node_paths=PackedStringArray("_generator") instance=ExtResource("3_pw2a0")]
|
||||||
visible = false
|
visible = false
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
offset_left = -17.0
|
offset_left = -16.0
|
||||||
offset_top = 215.0
|
offset_top = 352.0
|
||||||
offset_right = 247.0
|
offset_right = 417.0
|
||||||
offset_bottom = 380.0
|
offset_bottom = 626.0
|
||||||
_generator = NodePath("../../KnowledgeGenerator")
|
_generator = NodePath("../../KnowledgeGenerator")
|
||||||
|
|
||||||
[node name="GoalsDebugUI" parent="UI" unique_id=4710697 instance=ExtResource("4_63gjq")]
|
[node name="GoalsDebugUI" parent="UI" unique_id=4710697 instance=ExtResource("4_63gjq")]
|
||||||
|
|||||||
Reference in New Issue
Block a user