53 lines
2.1 KiB
GDScript
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)
|