SessionZero-Client/sessionzero-client/scripts/datapacks/other/formula_resolver.gd

53 lines
2.1 KiB
GDScript

# formula_resolver.gd
class_name FormulaResolver
extends RefCounted
var _expression: Expression = Expression.new()
## Internal helper to replace named variables with their numerical values.
## NOTE: This simple approach sorts keys by length descending (Max_HP before HP)
## to prevent incorrect substitution of substrings.
func _substitute_variables(raw_expression: String, context: Dictionary) -> String:
var result = raw_expression
# Sort keys by length descending to prevent shorter names (like 'HP') from matching
# before longer names that contain them (like 'Max_HP').
var keys = context.keys()
keys.sort_custom(func(a, b): return len(a) > len(b))
for key in keys:
if raw_expression.find(key) != -1:
var value = str(context[key])
# Replace the variable name with its numerical value string
result = result.replace(key, value)
return result
## Resolves the final value of the formula given a set of variable values.
## Handles variable substitution, parsing, and execution in one step.
func resolve_formula(raw_expression: String, context: Dictionary) -> float:
# 1. Substitute variables with their numerical values
var numerical_expression = _substitute_variables(raw_expression, context)
# 2. Parse the new numerical expression
# The expression must be re-parsed every time, as its text content changes.
var error: Error = _expression.parse(numerical_expression, PackedStringArray([]))
if error != OK:
push_error("FormulaResolver: Substitution/Parse failed. Expression: '%s'. Numerical: '%s'. Error: %s" % [raw_expression, numerical_expression, _expression.get_error_text()])
return 0.0
# 3. Execute the expression (inputs: empty array, base_instance: null, show_error: true)
var result = _expression.execute([], null, true)
if _expression.has_execute_failed():
push_error("FormulaResolver: Execution failed for numerical expression: %s" % numerical_expression)
return 0.0
# 4. Check type and return
if typeof(result) != TYPE_FLOAT and typeof(result) != TYPE_INT:
push_error("FormulaResolver: Expression result was not a number. Got type: %s" % typeof(result))
return 0.0
return float(result)