All
This commit is contained in:
parent
7a8ee29dcb
commit
0fe23420ab
800 changed files with 16547 additions and 0 deletions
218
resources/UnlockDataResource.gd
Normal file
218
resources/UnlockDataResource.gd
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
class_name UnlockDataResource
|
||||
extends Resource
|
||||
|
||||
@export var unlock_id: int = 0
|
||||
@export var unlock_name: String = ""
|
||||
@export var unlock_description: String = ""
|
||||
@export var base_cost: int = 0
|
||||
@export var is_unlocked: bool = false
|
||||
|
||||
@export_group("Scaling Settings")
|
||||
@export var is_scaling: bool = false
|
||||
@export var current_rank: int = 0
|
||||
@export var max_rank: int = -1 # -1 means infinite scaling
|
||||
|
||||
@export_subgroup("Cost Scaling")
|
||||
@export_enum("Linear", "Exponential") var cost_scaling_type: int = 1 # Default to Exponential
|
||||
@export var cost_scaling_multiplier: float = 1.5 # Exponential: multiplier per rank, Linear: flat increase
|
||||
@export var cost_linear_increase: int = 100 # Only used if cost_scaling_type is Linear
|
||||
|
||||
@export_subgroup("Effect Scaling")
|
||||
@export_enum("Linear", "Exponential") var effect_scaling_type: int = 1 # Default to Exponential
|
||||
@export var effect_scaling_multiplier: float = 1.2 # Exponential: multiplier per rank
|
||||
@export var effect_linear_increase: float = 0.1 # Linear: flat increase per rank (e.g., 0.1 = +10% per rank)
|
||||
|
||||
@export_group("Base Modifiers")
|
||||
@export var base_modifiers: Dictionary = {}
|
||||
|
||||
## Returns the cost for the next rank/unlock
|
||||
func get_next_cost() -> int:
|
||||
if not is_scaling:
|
||||
return base_cost
|
||||
|
||||
# Cost scaling should start from rank 0 (first purchase at base_cost)
|
||||
if cost_scaling_type == 0: # Linear
|
||||
return base_cost + (cost_linear_increase * current_rank)
|
||||
else: # Exponential
|
||||
return int(base_cost * pow(cost_scaling_multiplier, current_rank))
|
||||
|
||||
## Returns the current modifiers based on rank
|
||||
func get_current_modifiers() -> Dictionary:
|
||||
# If not unlocked yet, return empty modifiers
|
||||
if not is_unlocked or current_rank == 0:
|
||||
return {}
|
||||
|
||||
# Rank 1 should give base modifiers without scaling
|
||||
if current_rank == 1:
|
||||
return base_modifiers.duplicate()
|
||||
|
||||
# Rank 2+ applies scaling
|
||||
return get_modifiers_at_rank(current_rank)
|
||||
|
||||
## Returns modifiers for a specific rank (useful for preview)
|
||||
func get_modifiers_at_rank(rank: int) -> Dictionary:
|
||||
if not is_scaling or rank == 0:
|
||||
return base_modifiers.duplicate()
|
||||
|
||||
# Rank 1 returns base modifiers without scaling
|
||||
if rank == 1:
|
||||
return base_modifiers.duplicate()
|
||||
|
||||
var scaled_modifiers = {}
|
||||
for key in base_modifiers.keys():
|
||||
var base_value = base_modifiers[key]
|
||||
|
||||
if effect_scaling_type == 0: # Linear scaling
|
||||
# Linear: add flat increase per rank above 1
|
||||
# e.g., base 1.5 (+50%), linear 0.1 (+10%), rank 2 = 1.6 (+60%), rank 3 = 1.7 (+70%)
|
||||
var additional_ranks = rank - 1
|
||||
scaled_modifiers[key] = base_value + (effect_linear_increase * additional_ranks)
|
||||
else: # Exponential scaling
|
||||
# Exponential: scale the bonus part from rank 1
|
||||
# The bonus at rank 1 is (base_value - 1.0)
|
||||
# At higher ranks, multiply this bonus by multiplier^(rank-1)
|
||||
var base_bonus = base_value - 1.0
|
||||
var scaled_bonus = base_bonus * pow(effect_scaling_multiplier, rank - 1)
|
||||
scaled_modifiers[key] = 1.0 + scaled_bonus
|
||||
|
||||
return scaled_modifiers
|
||||
|
||||
## Convert a modifier value to a percentage string
|
||||
func _modifier_to_percentage(value: float) -> String:
|
||||
var percentage = (value - 1.0) * 100.0
|
||||
if percentage >= 0:
|
||||
return "+%.1f%%" % percentage
|
||||
else:
|
||||
return "%.1f%%" % percentage
|
||||
|
||||
## Get a formatted string of current modifiers with percentages
|
||||
func get_current_modifiers_string() -> String:
|
||||
var modifiers = get_current_modifiers()
|
||||
if modifiers.is_empty():
|
||||
return "No modifiers"
|
||||
|
||||
var lines = []
|
||||
for key in modifiers.keys():
|
||||
var display_name = key.replace("_", " ").capitalize()
|
||||
var percentage = _modifier_to_percentage(modifiers[key])
|
||||
lines.append("%s: %s" % [display_name, percentage])
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
## Get a formatted string of next rank modifiers with percentages
|
||||
func get_next_modifiers_string() -> String:
|
||||
if not can_rank_up():
|
||||
return "Max rank reached"
|
||||
|
||||
var next_rank = get_next_rank()
|
||||
var modifiers = get_modifiers_at_rank(next_rank)
|
||||
|
||||
if modifiers.is_empty():
|
||||
return "No modifiers"
|
||||
|
||||
var lines = []
|
||||
for key in modifiers.keys():
|
||||
var display_name = key.replace("_", " ").capitalize()
|
||||
var percentage = _modifier_to_percentage(modifiers[key])
|
||||
lines.append("%s: %s" % [display_name, percentage])
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
## Get comparison string showing current -> next modifiers
|
||||
func get_modifiers_comparison_string() -> String:
|
||||
if not can_rank_up():
|
||||
return get_current_modifiers_string()
|
||||
|
||||
var current = get_current_modifiers()
|
||||
var next_rank = get_next_rank()
|
||||
var next = get_modifiers_at_rank(next_rank)
|
||||
|
||||
# If no current modifiers (not unlocked yet), show next only
|
||||
if current.is_empty():
|
||||
var lines = []
|
||||
for key in next.keys():
|
||||
var display_name = key.replace("_", " ").capitalize()
|
||||
var next_pct = _modifier_to_percentage(next[key])
|
||||
lines.append("%s: %s" % [display_name, next_pct])
|
||||
return "\n".join(lines)
|
||||
|
||||
var lines = []
|
||||
for key in current.keys():
|
||||
var display_name = key.replace("_", " ").capitalize()
|
||||
var current_pct = _modifier_to_percentage(current[key])
|
||||
var next_pct = _modifier_to_percentage(next[key])
|
||||
lines.append("%s: %s → %s" % [display_name, current_pct, next_pct])
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
## Get a single-line summary of modifiers
|
||||
func get_modifiers_summary() -> String:
|
||||
var modifiers = get_current_modifiers()
|
||||
if modifiers.is_empty():
|
||||
return "No effects"
|
||||
|
||||
var parts = []
|
||||
for key in modifiers.keys():
|
||||
var display_name = key.replace("_modifier", "").replace("_", " ").capitalize()
|
||||
var percentage = _modifier_to_percentage(modifiers[key])
|
||||
parts.append("%s %s" % [display_name, percentage])
|
||||
|
||||
return ", ".join(parts)
|
||||
|
||||
## Check if the unlock can be purchased/ranked up
|
||||
func can_rank_up() -> bool:
|
||||
# Non-scaling: can only unlock once
|
||||
if not is_scaling:
|
||||
return not is_unlocked
|
||||
|
||||
# Scaling: check if we haven't hit max rank
|
||||
if max_rank > 0 and current_rank >= max_rank:
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
## Check if this is a one-off unlock (non-scaling)
|
||||
func is_one_off() -> bool:
|
||||
return not is_scaling
|
||||
|
||||
## Check if max rank has been reached (for scaling unlocks)
|
||||
func is_max_rank() -> bool:
|
||||
if not is_scaling:
|
||||
return is_unlocked
|
||||
|
||||
if max_rank <= 0: # Infinite scaling
|
||||
return false
|
||||
|
||||
return current_rank >= max_rank
|
||||
|
||||
## Unlock or rank up the unlock
|
||||
func unlock() -> bool:
|
||||
if not can_rank_up():
|
||||
return false
|
||||
|
||||
if not is_scaling:
|
||||
# Simple one-off unlock
|
||||
is_unlocked = true
|
||||
current_rank = 1
|
||||
else:
|
||||
# Scaling unlock - increase rank
|
||||
current_rank += 1
|
||||
is_unlocked = true
|
||||
|
||||
return true
|
||||
|
||||
## Get the next rank number (for display purposes)
|
||||
func get_next_rank() -> int:
|
||||
if not is_scaling:
|
||||
return 1 if not is_unlocked else 1
|
||||
return current_rank + 1
|
||||
|
||||
## Get display text for current status
|
||||
func get_rank_display() -> String:
|
||||
if not is_scaling:
|
||||
return "Unlocked" if is_unlocked else "Locked"
|
||||
|
||||
if max_rank > 0:
|
||||
return "Rank %d/%d" % [current_rank, max_rank]
|
||||
else:
|
||||
return "Rank %d" % current_rank
|
||||
Loading…
Add table
Add a link
Reference in a new issue