Cleanup goal unlocks behaviour
This commit is contained in:
@@ -36,7 +36,7 @@ Resource class for generator balancing data.
|
||||
@export var name: String = "" # Display name
|
||||
@export var starts_unlocked: bool = true # Visible at game start
|
||||
@export var purchase_currency: Currency # What to spend
|
||||
@export var unlock_goal: GoalData # Goal to unlock this
|
||||
@export var unlock_goal: GoalData # Goal to unlock this (behavior defined in GoalData)
|
||||
|
||||
# Cost formula: cost = base * coefficient^owned
|
||||
@export var initial_cost: float = 10.0 # Base cost
|
||||
@@ -90,7 +90,7 @@ Runtime node instance attached to generator scenes.
|
||||
signal purchase_completed(amount, total_owned, total_purchased, total_cost)
|
||||
signal production_tick(amount, cycle_count, total_owned)
|
||||
signal buff_purchased(buff_id, new_level, cost, cost_currency_id)
|
||||
signal goal_achieved(generator_id, goal_id)
|
||||
signal goal_achieved(generator_id, goal_id) # Emitted when generator unlocks from goal
|
||||
```
|
||||
|
||||
### Key Methods
|
||||
@@ -102,6 +102,10 @@ func buy_max() -> int
|
||||
func get_cost_for_amount(amount: int) -> BigNumber
|
||||
func can_buy(amount: int) -> bool
|
||||
|
||||
# Goal-based unlock (automatic when goal completes)
|
||||
# Generator listens to GameState.goal_completed signal
|
||||
```
|
||||
|
||||
# Production
|
||||
func grant_currency(amount: BigNumber)
|
||||
func get_effective_auto_run_multiplier() -> float
|
||||
@@ -184,6 +188,22 @@ UI component showing generator information.
|
||||
- `production_tick` - Update production display
|
||||
- `generator_buff_level_changed` - Refresh buff rows
|
||||
|
||||
## Goal-Based Unlock
|
||||
|
||||
Generators with `unlock_goal` automatically listen to `GameState.goal_completed` signal:
|
||||
- When goal completes, generator unlocks automatically
|
||||
- Goal's `unlock_behavior` (AUTOMATIC/MANUAL) controls when goal completes
|
||||
- Manual goals require player to click "Unlock" button first
|
||||
|
||||
```gdscript
|
||||
# In CurrencyGenerator._ready():
|
||||
GameState.goal_completed.connect(_on_goal_completed)
|
||||
|
||||
func _on_goal_completed(goal_id: StringName) -> void:
|
||||
if data.has_unlock_goal() and data.get_unlock_goal_id() == goal_id:
|
||||
unlock_generator()
|
||||
```
|
||||
|
||||
## Prestige Integration
|
||||
|
||||
Generators automatically apply prestige multipliers:
|
||||
|
||||
@@ -100,11 +100,9 @@ func _ready() -> void:
|
||||
|
||||
GameState.currency_changed.connect(_on_currency_changed)
|
||||
GameState.generator_state_changed.connect(_on_generated_state_changed)
|
||||
GameState.goal_completed.connect(_on_goal_completed)
|
||||
|
||||
# Register with default state first, then evaluate unlock goal
|
||||
_ensure_registered()
|
||||
if data != null and data.unlocks_automatically_from_goal():
|
||||
_evaluate_generator_unlock_goal(false)
|
||||
|
||||
## Updates click cooldown/click grants and runs automatic production cycles.
|
||||
func _process(delta: float) -> void:
|
||||
@@ -322,9 +320,6 @@ func reset_runtime_state_for_prestige() -> void:
|
||||
cycle_progress_seconds = 0.0
|
||||
_remaining_click_cooldown_seconds = 0.0
|
||||
_ensure_registered()
|
||||
if data != null and data.unlocks_automatically_from_goal():
|
||||
_evaluate_generator_unlock_goal(false)
|
||||
#_evaluate_buff_unlock_goals()
|
||||
visible = is_available_to_player()
|
||||
|
||||
func get_manual_click_multiplier() -> float:
|
||||
@@ -583,35 +578,19 @@ func _try_unlock_buff_from_goal(buff: GeneratorBuffData) -> void:
|
||||
|
||||
func _on_currency_changed(_changed_currency_id: StringName, _new_amount: BigNumber) -> void:
|
||||
GameState.evaluate_all_goals()
|
||||
if data != null and data.unlocks_automatically_from_goal():
|
||||
_evaluate_generator_unlock_goal(false)
|
||||
|
||||
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
|
||||
func _on_goal_completed(goal_id: StringName) -> void:
|
||||
if data == null or not data.has_unlock_goal():
|
||||
return
|
||||
if data.get_unlock_goal_id() != goal_id:
|
||||
return
|
||||
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
|
||||
|
||||
var goal_id: StringName = data.get_unlock_goal_id()
|
||||
if goal_id.is_empty():
|
||||
return false
|
||||
|
||||
var goal_completed: bool = GameState.is_goal_completed(goal_id)
|
||||
if not goal_completed:
|
||||
return false
|
||||
return
|
||||
|
||||
GameState.set_generator_unlocked(_generator_id, true)
|
||||
GameState.set_generator_available(_generator_id, true)
|
||||
goal_achieved.emit(_generator_id, goal_id)
|
||||
_on_generated_state_changed(_generator_id, GameState._get_generator_state(_generator_id))
|
||||
return true
|
||||
|
||||
## Default unlocked state loaded from generator data.
|
||||
func _default_unlocked_state() -> bool:
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
class_name CurrencyGeneratorData
|
||||
extends Resource
|
||||
|
||||
enum UnlockGoalBehavior {
|
||||
AUTOMATIC,
|
||||
MANUAL_BUTTON,
|
||||
}
|
||||
|
||||
@export var id: StringName = &""
|
||||
@export var name: String = ""
|
||||
@export var starts_unlocked: bool = true
|
||||
@@ -13,7 +8,6 @@ enum UnlockGoalBehavior {
|
||||
@export var initial_owned: int = 0
|
||||
@export var purchase_currency: Currency
|
||||
@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
|
||||
@@ -43,12 +37,6 @@ func has_unlock_goal() -> bool:
|
||||
|
||||
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 &""
|
||||
@@ -59,9 +47,6 @@ func get_unlock_goal_id() -> StringName:
|
||||
|
||||
return StringName(goal_id_text)
|
||||
|
||||
func unlocks_automatically_from_goal() -> bool:
|
||||
return unlock_goal_behavior == UnlockGoalBehavior.AUTOMATIC
|
||||
|
||||
## Returns cost of next generator
|
||||
func cost_next(owned: int) -> float:
|
||||
return cost_for_amount(owned, 1)
|
||||
|
||||
@@ -84,16 +84,6 @@ func get_unlock_goal_currency() -> Currency:
|
||||
|
||||
return requirement_resource.currency
|
||||
|
||||
func is_unlock_goal_met() -> bool:
|
||||
if unlock_goal == null:
|
||||
return false
|
||||
|
||||
var goal_id: StringName = unlock_goal.id
|
||||
if goal_id.is_empty():
|
||||
return false
|
||||
|
||||
return GameState.is_goal_completed(goal_id)
|
||||
|
||||
func can_purchase_next_level(current_level: int) -> bool:
|
||||
if max_level < 0:
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user