# 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)