Use GoalData for everything

This commit is contained in:
2026-03-21 12:11:38 +01:00
parent 52c23b194e
commit 471a7b10f7
15 changed files with 205 additions and 417 deletions

View File

@@ -17,6 +17,8 @@ signal production_tick(amount: BigNumber, cycle_count: int, total_owned: int)
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)
## Emitted when this generator unlock goal transitions to completed.
signal goal_achieved(generator_id: StringName, goal_id: StringName)
## Sentinel exponent used when cost math overflows float range.
const HUGE_COST_EXPONENT: int = 1000000
@@ -97,6 +99,7 @@ func _ready() -> void:
GameState.currency_changed.connect(_on_currency_changed)
GameState.generator_state_changed.connect(_on_generated_state_changed)
_evaluate_generator_unlock_goal(false)
## Updates click cooldown/click grants and runs automatic production cycles.
func _process(delta: float) -> void:
@@ -542,8 +545,29 @@ func _try_unlock_buff_from_goal(buff: GeneratorBuffData) -> void:
GameState.set_generator_buff_unlocked(_generator_id, buff_id, true)
func _on_currency_changed(_changed_currency_id: StringName, _new_amount: BigNumber) -> void:
_evaluate_generator_unlock_goal(false)
_evaluate_buff_unlock_goals()
func try_unlock_from_goal() -> bool:
return _evaluate_generator_unlock_goal(true)
func _evaluate_generator_unlock_goal(allow_manual_unlock: bool) -> bool:
if data == null:
return false
if is_available_to_player():
return false
if not data.has_unlock_goal():
return false
if not data.unlocks_automatically_from_goal() and not allow_manual_unlock:
return false
if not data.is_unlock_goal_met():
return false
GameState.set_generator_unlocked(_generator_id, true)
GameState.set_generator_available(_generator_id, true)
goal_achieved.emit(_generator_id, data.get_unlock_goal_id())
return true
## Default unlocked state loaded from generator data.
func _default_unlocked_state() -> bool:
if data == null:

View File

@@ -1,10 +1,17 @@
class_name CurrencyGeneratorData
extends Resource
enum UnlockGoalBehavior {
AUTOMATIC,
MANUAL_BUTTON,
}
@export var id: StringName = &""
@export var name: String = ""
@export var starts_unlocked: bool = true
@export var starts_available: bool = true
@export var unlock_goal: GoalData
@export var unlock_goal_behavior: UnlockGoalBehavior = UnlockGoalBehavior.AUTOMATIC
## Base cost and exponential growth (part I): cost_next = b * r^owned
@export var initial_cost: float = 10.0
@@ -31,6 +38,31 @@ extends Resource
## Data-driven buffs purchasable for this generator.
@export var buffs: Array[GeneratorBuffData] = []
func has_unlock_goal() -> bool:
if unlock_goal == null:
return false
return bool(unlock_goal.is_valid())
func is_unlock_goal_met() -> bool:
if not has_unlock_goal():
return false
return bool(unlock_goal.is_met())
func get_unlock_goal_id() -> StringName:
if not has_unlock_goal():
return &""
var goal_id_text: String = String(unlock_goal.id).strip_edges()
if goal_id_text.is_empty():
return &""
return StringName(goal_id_text)
func unlocks_automatically_from_goal() -> bool:
return unlock_goal_behavior == UnlockGoalBehavior.AUTOMATIC
func find_buff(buff_id: StringName) -> GeneratorBuffData:
var expected_id: String = String(buff_id).strip_edges()
if expected_id.is_empty():