# intro_select_phase.gd —— 40250 3D 角色选择大厅系统 1:1 # 严格对照: # Client/Eternexus/root/introselect.py (SelectCharacterWindow) # ClientVS22/source/UserInterface/InstanceBaseMotion.cpp (MOTION_INTRO_SELECTED) # metin2/src/server/game/src/char.cpp extends RefCounted const SLOT_COUNT := 4 # 官方 4 槽位 const SLOT_ROTATION := [135.0, 225.0, 315.0, 45.0] # 官方 4 槽位旋转视角 (度数) const JOB_WARRIOR := 0 const JOB_ASSASSIN := 1 const JOB_SURA := 2 const JOB_SHAMAN := 3 const JOB_NAMES := { JOB_WARRIOR: "战士 (Warrior)", JOB_ASSASSIN: "刺客 (Assassin)", JOB_SURA: "修罗 (Sura)", JOB_SHAMAN: "萨满 (Shaman)", } # 4 个角色槽位存储 (slot 0..3 -> CharacterData or null) var character_slots: Array = [null, null, null, null] var selected_slot_index: int = 0 var is_character_stepped_forward: bool = false func _init() -> void: character_slots = [null, null, null, null] selected_slot_index = 0 is_character_stepped_forward = false # 1. 注册/载入角色槽位数据 func set_character_slot(slot_idx: int, char_data: Dictionary) -> bool: if slot_idx < 0 or slot_idx >= SLOT_COUNT: return false character_slots[slot_idx] = char_data.duplicate(true) return true # 2. 选中角色槽位与踏步迈出动画 (1:1 SelectCharacterWindow.SelectSlot) func select_slot(slot_idx: int) -> Dictionary: var res := { "success": false, "slot_idx": slot_idx, "is_empty_slot": true, "character": null, "rotation_deg": 0.0, "action": "" } if slot_idx < 0 or slot_idx >= SLOT_COUNT: return res selected_slot_index = slot_idx res["rotation_deg"] = SLOT_ROTATION[slot_idx] if character_slots[slot_idx] == null: is_character_stepped_forward = false res["is_empty_slot"] = true res["action"] = "PROMPT_CREATE" else: is_character_stepped_forward = true # 触发 MOTION_INTRO_SELECTED 迈步出列动画 res["is_empty_slot"] = false res["character"] = character_slots[slot_idx] res["action"] = "READY_TO_START" res["success"] = true return res # 3. 开始游戏进入世界 (1:1 SelectCharacterWindow.StartGame) func start_game() -> Dictionary: var res := { "success": false, "character": null, "error_code": "OK", "message": "" } if character_slots[selected_slot_index] == null: res["error_code"] = "EMPTY_SLOT" res["message"] = "当前选中槽位为空,无法开始游戏。" return res res["success"] = true res["character"] = character_slots[selected_slot_index] res["message"] = "进入游戏世界..." return res # 4. 删除角色与 7 位安全防删 PIN 码校验 (1:1 SelectCharacterWindow.DeleteCharacter) func delete_character(slot_idx: int, delete_pin_code: String) -> Dictionary: var res := { "success": false, "error_code": "OK", "message": "" } if slot_idx < 0 or slot_idx >= SLOT_COUNT or character_slots[slot_idx] == null: res["error_code"] = "CHARACTER_NOT_FOUND" res["message"] = "未找到待删除的角色。" return res # 官方安全码格式验证 (必须为 7 位字符) if delete_pin_code.length() != 7: res["error_code"] = "INVALID_PIN_LENGTH" res["message"] = "防误删安全码必须为 7 位数字。" return res var target_char: Dictionary = character_slots[slot_idx] var expected_pin: String = str(target_char.get("delete_code", "1234567")) if delete_pin_code != expected_pin: res["error_code"] = "WRONG_DELETE_PIN" res["message"] = "安全码校验失败,删除角色请求被拒绝。" return res # 删除成功 var char_name: String = target_char.get("name", "Unknown") character_slots[slot_idx] = null if selected_slot_index == slot_idx: is_character_stepped_forward = false res["success"] = true res["message"] = "角色 %s 已永久删除。" % char_name return res # 5. 获取当前选中槽位的角色卡片详情 func get_selected_character_card() -> Dictionary: if character_slots[selected_slot_index] == null: return {} var c: Dictionary = character_slots[selected_slot_index] var job_idx: int = c.get("job", 0) return { "name": c.get("name", ""), "level": c.get("level", 1), "job_name": JOB_NAMES.get(job_idx, "未知职业"), "horse_level": c.get("horse_level", 0), "playtime_min": c.get("playtime_min", 0), "stats": c.get("stats", { "con": 4, "int": 3, "str": 6, "dex": 3 }) }