extends RefCounted class_name ModeConfig # ModeConfig - Schema-driven validation for game mode settings # Task [036]: Consolidates duplicated/inconsistent option toggles # Schema definition for all mode-specific settings const SCHEMA = { "Freemode": { "match_duration": {"type": TYPE_INT, "default": 180, "min": 60, "max": 600}, "randomize_spawn": {"type": TYPE_BOOL, "default": false}, "enable_cycle_timer": {"type": TYPE_BOOL, "default": false}, "scarcity_mode": {"type": TYPE_STRING, "default": "Normal", "allowed": ["Normal", "Aggressive", "Chaos"]} }, "Stop n Go": { "match_duration": {"type": TYPE_INT, "default": 180, "min": 60, "max": 600}, "sng_go_duration": {"type": TYPE_INT, "default": 20, "min": 10, "max": 60}, "sng_stop_duration": {"type": TYPE_INT, "default": 4, "min": 2, "max": 10}, "sng_required_goals": {"type": TYPE_INT, "default": 8, "min": 3, "max": 20} }, "Tekton Doors": { "match_duration": {"type": TYPE_INT, "default": 180, "min": 60, "max": 600}, "doors_swap_time": {"type": TYPE_INT, "default": 15, "min": 10, "max": 30}, "doors_refresh_time": {"type": TYPE_INT, "default": 25, "min": 15, "max": 40}, "doors_required_goals": {"type": TYPE_INT, "default": 8, "min": 5, "max": 12} }, "Candy Pump Survival": { "match_duration": {"type": TYPE_INT, "default": 180, "min": 60, "max": 600}, "gauntlet_growth_interval": {"type": TYPE_FLOAT, "default": 3.0, "min": 1.0, "max": 10.0}, "gauntlet_cells_per_tick": {"type": TYPE_DICTIONARY, "default": {"phase1": [4, 6], "phase2": [6, 8], "phase3": [8, 10]}} } } # Get default config for a mode static func get_defaults(mode: String) -> Dictionary: if not SCHEMA.has(mode): push_error("ModeConfig: Unknown mode '%s'" % mode) return {} var defaults = {} for key in SCHEMA[mode]: defaults[key] = SCHEMA[mode][key]["default"] return defaults # Validate a single setting static func validate_setting(mode: String, key: String, value: Variant) -> Dictionary: if not SCHEMA.has(mode): return {"valid": false, "error": "Unknown mode: %s" % mode} if not SCHEMA[mode].has(key): return {"valid": false, "error": "Unknown setting '%s' for mode '%s'" % [key, mode]} var schema = SCHEMA[mode][key] # Type check if typeof(value) != schema["type"]: return {"valid": false, "error": "Setting '%s' expects type %s, got %s" % [key, schema["type"], typeof(value)]} # Range check for numbers if schema["type"] == TYPE_INT or schema["type"] == TYPE_FLOAT: if schema.has("min") and value < schema["min"]: return {"valid": false, "error": "Setting '%s' must be >= %s" % [key, schema["min"]]} if schema.has("max") and value > schema["max"]: return {"valid": false, "error": "Setting '%s' must be <= %s" % [key, schema["max"]]} # Allowed values check for strings if schema["type"] == TYPE_STRING and schema.has("allowed"): if value not in schema["allowed"]: return {"valid": false, "error": "Setting '%s' must be one of %s" % [key, schema["allowed"]]} return {"valid": true} # Validate entire config for a mode static func validate_config(mode: String, config: Dictionary) -> Dictionary: if not SCHEMA.has(mode): return {"valid": false, "error": "Unknown mode: %s" % mode} var errors = [] for key in config: var result = validate_setting(mode, key, config[key]) if not result["valid"]: errors.append(result["error"]) if errors.is_empty(): return {"valid": true} else: return {"valid": false, "errors": errors} # Get all settings for a mode static func get_mode_settings(mode: String) -> Array: if not SCHEMA.has(mode): return [] return SCHEMA[mode].keys() # Get schema for a specific setting static func get_setting_schema(mode: String, key: String) -> Dictionary: if not SCHEMA.has(mode) or not SCHEMA[mode].has(key): return {} return SCHEMA[mode][key] # Check if a mode has a specific setting static func has_setting(mode: String, key: String) -> bool: return SCHEMA.has(mode) and SCHEMA[mode].has(key) # Get all supported modes static func get_supported_modes() -> Array: return SCHEMA.keys()