Replace generic Resource usage with type-safe resources

This commit is contained in:
2026-03-21 10:28:43 +01:00
parent c55b59fcad
commit 52c23b194e
11 changed files with 85 additions and 100 deletions

View File

@@ -16,12 +16,12 @@ var _catalog_initialized: bool = false
func _ready() -> void:
_initialize_currency_catalog()
func get_known_currencies() -> Array[Resource]:
func get_known_currencies() -> Array[Currency]:
_initialize_currency_catalog_if_needed()
var result: Array[Resource] = []
var result: Array[Currency] = []
for raw_currency in _currency_by_id.values():
var currency: Resource = raw_currency as Resource
var currency: Currency = raw_currency as Currency
if currency != null:
result.append(currency)
return result
@@ -37,11 +37,11 @@ func get_known_currency_ids() -> Array[StringName]:
ids.append(currency_id)
return ids
func get_currency_id(currency: Resource) -> StringName:
func get_currency_id(currency: Currency) -> StringName:
if currency == null:
return &""
var raw_id: Variant = currency.get("id")
var raw_id: Variant = currency.id
if raw_id is StringName:
return _normalize_currency_id(raw_id)
return _normalize_currency_id(StringName(String(raw_id)))
@@ -66,7 +66,7 @@ func is_known_currency_id(currency_id: StringName) -> bool:
return false
return _currency_by_id.has(normalized_currency_id)
func get_currency_resource(currency_id: StringName) -> Resource:
func get_currency_resource(currency_id: StringName) -> Currency:
_initialize_currency_catalog_if_needed()
var normalized_currency_id: StringName = _normalize_currency_id(currency_id)
@@ -74,14 +74,14 @@ func get_currency_resource(currency_id: StringName) -> Resource:
return null
var raw_currency: Variant = _currency_by_id.get(normalized_currency_id)
if raw_currency is Resource:
if raw_currency is Currency:
return raw_currency
return null
func get_currency_name(currency_id: StringName) -> String:
var currency: Resource = get_currency_resource(currency_id)
var currency: Currency = get_currency_resource(currency_id)
if currency != null:
var display_name: String = String(currency.get("display_name")).strip_edges()
var display_name: String = String(currency.display_name).strip_edges()
if not display_name.is_empty():
return display_name
return _humanize_currency_id(currency_id)
@@ -91,7 +91,7 @@ func get_currency_icon(currency_id: StringName) -> Texture2D:
if currency == null:
return null
var raw_icon: Variant = currency.get("icon")
var raw_icon: Variant = currency.icon
if raw_icon is Texture2D:
return raw_icon
return null

View File

@@ -56,7 +56,7 @@ func _ready() -> void:
#func spend_gems(cost: BigNumber) -> bool:
#return spend_currency_by_id(GEMS_CURRENCY_ID, cost)
func get_known_currencies() -> Array[Resource]:
func get_known_currencies() -> Array[Currency]:
return CurrencyDatabase.get_known_currencies()
func get_currency_id(currency: Resource) -> StringName:

View File

@@ -4,16 +4,13 @@ signal goal_achieved(goal_id: StringName, target_generator_id: StringName)
class GeneratorUnlockGoal extends RefCounted:
var target_generator_id: StringName
var goal: Resource
var goal: GoalData
func _init(target_id: StringName, goal_data: Resource) -> void:
func _init(target_id: StringName, goal_data: GoalData) -> void:
target_generator_id = target_id
goal = goal_data
const GOAL_DATA_SCRIPT: Script = preload("res://core/goals/goal_data.gd")
const GENERATOR_UNLOCK_GOAL_DATA_SCRIPT: Script = preload("res://core/generator-unlock-goals/generator_unlock_goal_data.gd")
@export var goals: Array[Resource] = []
@export var goals: Array[GeneratorUnlockGoalData] = []
var _runtime_goals: Array[GeneratorUnlockGoal] = []
var _known_generator_ids: Dictionary = {}
@@ -60,13 +57,11 @@ func _evaluate_goal(runtime_goal: GeneratorUnlockGoal) -> bool:
return false
if runtime_goal.goal == null:
return false
if runtime_goal.goal.get_script() != GOAL_DATA_SCRIPT:
return false
if _is_goal_completed(runtime_goal):
return false
if not _can_resolve_target(runtime_goal.target_generator_id):
return false
if not bool(runtime_goal.goal.call("is_met")):
if not bool(runtime_goal.goal.is_met()):
return false
var goal_id: StringName = _extract_goal_id(runtime_goal.goal)
@@ -76,11 +71,11 @@ func _evaluate_goal(runtime_goal: GeneratorUnlockGoal) -> bool:
print("[UnlockSystem] Goal completed: %s -> %s" % [String(goal_id), String(runtime_goal.target_generator_id)])
return true
func _extract_goal_id(goal: Resource) -> StringName:
func _extract_goal_id(goal: GoalData) -> StringName:
if goal == null:
return &""
var goal_id_text: String = String(goal.get("id")).strip_edges()
var goal_id_text: String = String(goal.id).strip_edges()
if goal_id_text.is_empty():
return &""
@@ -109,27 +104,25 @@ func _load_goals() -> void:
_runtime_goals.clear()
var seen_goal_ids: Dictionary = {}
for goal_resource in goals:
if goal_resource == null:
for generator_unlock_goal_data in goals:
if generator_unlock_goal_data == null:
continue
if goal_resource.get_script() != GENERATOR_UNLOCK_GOAL_DATA_SCRIPT:
continue
var goal_data: Resource = goal_resource
var goal_data: GeneratorUnlockGoalData = generator_unlock_goal_data
if goal_data == null:
continue
var target_generator_id: String = String(goal_data.get("target_generator_id")).strip_edges()
var target_generator_id: String = String(goal_data.target_generator_id).strip_edges()
if target_generator_id.is_empty():
push_warning("Skipping unlock goal resource: missing target_generator_id")
continue
var resolved_goal: Resource = goal_data.call("get_goal_data")
var resolved_goal: GoalData = generator_unlock_goal_data.get_goal_data()
if resolved_goal == null:
push_warning("Skipping unlock goal for target '%s': goal is null" % target_generator_id)
continue
if not bool(resolved_goal.call("is_valid")):
if not bool(resolved_goal.is_valid()):
push_warning("Skipping unlock goal for target '%s': goal is invalid" % target_generator_id)
continue
var goal_key: String = String(resolved_goal.get("id"))
var goal_key: String = String(resolved_goal.id)
if seen_goal_ids.has(goal_key):
push_warning("Duplicate unlock goal id skipped: '%s'" % goal_key)
continue

View File

@@ -23,6 +23,7 @@ texture = ExtResource("4_ruf1h")
shape = SubResource("RectangleShape2D_y5m1q")
[node name="GeneratorPanel" parent="." unique_id=1129190041 node_paths=PackedStringArray("_generator") instance=ExtResource("5_bb14m")]
visible = false
offset_left = 64.0
offset_top = -64.0
offset_right = 505.0

View File

@@ -8,8 +8,6 @@ enum BuffKind {
}
const HUGE_EXPONENT: int = 1000000
const GOAL_DATA_SCRIPT: Script = preload("res://core/goals/goal_data.gd")
const GOAL_REQUIREMENT_SCRIPT: Script = preload("res://core/goals/goal_requirement_data.gd")
@export var id: StringName = &""
@export var kind: BuffKind = BuffKind.AUTO_PRODUCTION_MULTIPLIER
@@ -19,20 +17,20 @@ const GOAL_REQUIREMENT_SCRIPT: Script = preload("res://core/goals/goal_requireme
@export_group("Unlock")
@export var unlocked: bool = false
@export var unlock_goal: Resource
@export var unlock_goal: GoalData
@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 cost_currency: Currency
@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_target_currency: Currency
@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
@@ -40,56 +38,44 @@ const GOAL_REQUIREMENT_SCRIPT: Script = preload("res://core/goals/goal_requireme
func has_unlock_goal() -> bool:
if unlock_goal == null:
return false
if unlock_goal.get_script() != GOAL_DATA_SCRIPT:
return false
return bool(unlock_goal.call("is_valid"))
return bool(unlock_goal.is_valid())
func get_unlock_goal_amount() -> BigNumber:
if unlock_goal == null:
return BigNumber.from_float(0.0)
if unlock_goal.get_script() != GOAL_DATA_SCRIPT:
return BigNumber.from_float(0.0)
var valid_requirements: Array[Resource] = unlock_goal.call("get_valid_requirements")
var valid_requirements: Array[GoalRequirementData] = unlock_goal.get_valid_requirements()
if valid_requirements.is_empty():
return BigNumber.from_float(0.0)
var requirement_resource: Resource = valid_requirements[0]
var requirement_resource: GoalRequirementData = valid_requirements[0]
if requirement_resource == null:
return BigNumber.from_float(0.0)
if requirement_resource.get_script() != GOAL_REQUIREMENT_SCRIPT:
return BigNumber.from_float(0.0)
var required_amount: Variant = requirement_resource.call("get_amount")
var required_amount: Variant = requirement_resource.get_amount()
if required_amount is BigNumber:
return required_amount
return BigNumber.from_float(0.0)
func get_unlock_goal_currency() -> Resource:
func get_unlock_goal_currency() -> Currency:
if unlock_goal == null:
return null
if unlock_goal.get_script() != GOAL_DATA_SCRIPT:
return null
var valid_requirements: Array[Resource] = unlock_goal.call("get_valid_requirements")
var valid_requirements: Array[GoalRequirementData] = unlock_goal.get_valid_requirements()
if valid_requirements.is_empty():
return null
var requirement_resource: Resource = valid_requirements[0]
var requirement_resource: GoalRequirementData = valid_requirements[0]
if requirement_resource == null:
return null
if requirement_resource.get_script() != GOAL_REQUIREMENT_SCRIPT:
return null
return requirement_resource.get("currency")
return requirement_resource.currency
func is_unlock_goal_met() -> bool:
if unlock_goal == null:
return false
if unlock_goal.get_script() != GOAL_DATA_SCRIPT:
return false
return bool(unlock_goal.call("is_met"))
return bool(unlock_goal.is_met())
func can_purchase_next_level(current_level: int) -> bool:
if max_level < 0:

View File

@@ -7,12 +7,12 @@ extends Resource
func has_id() -> bool:
return not String(id).strip_edges().is_empty()
func get_valid_requirements() -> Array[Resource]:
var result: Array[Resource] = []
func get_valid_requirements() -> Array[GoalRequirementData]:
var result: Array[GoalRequirementData] = []
for requirement_resource in requirements:
if requirement_resource == null:
continue
if not bool(requirement_resource.call("is_valid")):
if not bool(requirement_resource.is_valid()):
continue
result.append(requirement_resource)
@@ -26,18 +26,18 @@ func is_valid() -> bool:
return not get_valid_requirements().is_empty()
func is_met() -> bool:
var valid_requirements: Array[Resource] = get_valid_requirements()
var valid_requirements: Array[GoalRequirementData] = get_valid_requirements()
if valid_requirements.is_empty():
return false
for requirement_resource in valid_requirements:
if not bool(requirement_resource.call("is_met")):
if not bool(requirement_resource.is_met()):
return false
return true
func get_first_requirement_summary() -> String:
var valid_requirements: Array[Resource] = get_valid_requirements()
var valid_requirements: Array[GoalRequirementData] = get_valid_requirements()
if valid_requirements.is_empty():
return ""
return String(valid_requirements[0].call("get_summary_text"))
return String(valid_requirements[0].get_summary_text())

View File

@@ -1,7 +1,7 @@
class_name GoalRequirementData
extends Resource
@export var currency: Resource
@export var currency: Currency
@export var amount_mantissa: float = 0.0
@export var amount_exponent: int = 0