class_name CharacterData ## Loads one character folder (see characters/_spec/CHARACTER_SPEC.md). ## The roster is whatever folders exist under characters/ — adding a ## fighter is dropping a folder in, no code changes. var id := "" var display_name := "" var health := 1000 var walk_speed := 3.0 var back_speed := 2.5 var jump_velocity := -13.5 var color := Color.WHITE var sprite_scale := 1.0 # draw scale; also scales all box coords var wardrobe_states: Array = [] # ordered, e.g. ["base", "torn"] var tear_below_hp := 0.0 # fraction; reaching it forces the last state var normals := {} # "P" -> move name, "6P" -> forward+P, "K" -> ... var command_moves: Array = [] # [{motion:[2,3,6], button:"P", move:"rush_palm"}] var moves := {} # name -> MoveData var portrait: Texture2D = null static func load_dir(dir_path: String) -> CharacterData: var c := CharacterData.new() var manifest_text := FileAccess.get_file_as_string(dir_path + "/manifest.json") if manifest_text.is_empty(): push_error("CharacterData: missing manifest.json in " + dir_path) return c var d = JSON.parse_string(manifest_text) c.id = d.get("id", dir_path.get_file()) c.display_name = d.get("name", c.id.to_upper()) c.health = int(d.get("health", 1000)) c.walk_speed = float(d.get("walk_speed", 3.0)) c.back_speed = float(d.get("back_speed", 2.5)) c.jump_velocity = float(d.get("jump_velocity", -13.5)) c.color = Color(d.get("color", "#ffffff")) c.sprite_scale = float(d.get("sprite_scale", 1.0)) var w = d.get("wardrobe", null) if w != null: c.wardrobe_states = w.get("states", []) c.tear_below_hp = float(w.get("tear_below_hp", 0.0)) c.normals = d.get("normals", {}) c.command_moves = d.get("command_moves", []) var moves_global := ProjectSettings.globalize_path(dir_path + "/moves") for move_dir in DirAccess.get_directories_at(moves_global): c.moves[move_dir] = MoveData.load_dir(dir_path + "/moves/" + move_dir) var portrait_path := ProjectSettings.globalize_path(dir_path + "/portrait.png") if FileAccess.file_exists(portrait_path): var img := Image.load_from_file(portrait_path) if img: c.portrait = ImageTexture.create_from_image(img) return c static func scan_roster(root := "res://characters") -> Array: var out: Array = [] var global := ProjectSettings.globalize_path(root) var dirs := Array(DirAccess.get_directories_at(global)) dirs.sort() for d in dirs: if d.begins_with("_") or d.begins_with("."): continue out.append(root + "/" + d) return out