# atlas_navigation_system.gd —— 40250 Atlas M 键全景大地图与 NPC 寻路导航光标系统 1:1 # 严格对照: # Client/Eternexus/root/uiminimap.py (AtlasWindow, MiniMap) # ClientVS22/source/UserInterface/PythonMiniMap.cpp, PythonMiniMap.h (AddSignalPoint, ClearAllSignalPoint) # Client/Eternexus/root/atlasinfo.txt extends RefCounted # 地图手绘全景 Atlas 纹理与尺寸映射 const MAP_ATLAS_REGISTRY := { "metin2_map_a1": { "name": "赤蛇国主城 (Yongan)", "size": Vector2(256, 256), "world_size": Vector2(4000, 4000) }, "metin2_map_b1": { "name": "白虎国主城 (Joan)", "size": Vector2(256, 256), "world_size": Vector2(4000, 4000) }, "metin2_map_c1": { "name": "苍龙国主城 (Pyungmoo)", "size": Vector2(256, 256), "world_size": Vector2(4000, 4000) }, "metin2_map_milgyo": { "name": "幽冥神殿 (Dark Temple)", "size": Vector2(256, 256), "world_size": Vector2(2000, 2000) }, "metin2_map_deviltower": { "name": "恶魔之塔 (Demon Tower)", "size": Vector2(256, 256), "world_size": Vector2(1000, 1000) }, } # 官方预设标准城镇 NPC 索引目录 (NPC VID -> 数据) const PRESET_TOWN_NPCS := [ { "vid": 20016, "name": "铁匠 (Blacksmith)", "category": "Smith", "pos": Vector2(580, 620) }, { "vid": 9001, "name": "武器商人 (Weapon Dealer)", "category": "Shop", "pos": Vector2(610, 630) }, { "vid": 9002, "name": "防具商人 (Armor Dealer)", "category": "Shop", "pos": Vector2(590, 650) }, { "vid": 9003, "name": "杂货商人 (General Store)", "category": "Shop", "pos": Vector2(630, 600) }, { "vid": 9005, "name": "仓库保管员 (Storekeeper)", "category": "Safebox", "pos": Vector2(550, 580) }, { "vid": 20084, "name": "生物学家采吉拉布 (Biologist)", "category": "Quest", "pos": Vector2(680, 520) }, { "vid": 20092, "name": "老行商 (Old Wanderer)", "category": "Special", "pos": Vector2(450, 710) }, { "vid": 20008, "name": "城门守卫 (City Guard)", "category": "Guard", "pos": Vector2(800, 800) }, { "vid": 20001, "name": "药店掌柜 (Alchemist)", "category": "Craft", "pos": Vector2(520, 640) }, { "vid": 20091, "name": "修仙道长 (Taoist)", "category": "Skill", "pos": Vector2(640, 750) }, ] # 状态变量 var is_atlas_visible: bool = false var current_map_id: String = "metin2_map_a1" var zoom_level: float = 1.0 # 滚轮缩放倍率 (0.5x ~ 3.0x) var pan_offset: Vector2 = Vector2.ZERO # 拖拽平移偏移 # 动态信标点列表 (1:1 CPythonMiniMap::m_SignalPointVector) var signal_points: Array = [] func _init(map_id: String = "metin2_map_a1") -> void: current_map_id = map_id is_atlas_visible = false zoom_level = 1.0 pan_offset = Vector2.ZERO signal_points.clear() # 1. M 键快捷切换全景大地图 (1:1 ToggleAtlasWindow) func toggle_atlas() -> bool: is_atlas_visible = !is_atlas_visible return is_atlas_visible func show_atlas() -> void: is_atlas_visible = true func hide_atlas() -> void: is_atlas_visible = false # 2. 切换当前地图与底图载入 (SetMapName) func set_map(map_id: String) -> bool: if not MAP_ATLAS_REGISTRY.has(map_id): return false current_map_id = map_id clear_all_signals() pan_offset = Vector2.ZERO zoom_level = 1.0 return true func get_current_map_info() -> Dictionary: return MAP_ATLAS_REGISTRY.get(current_map_id, {}) # 3. 缩放与平移控制 func set_zoom(zoom: float) -> void: zoom_level = clamp(zoom, 0.5, 3.0) func apply_pan(delta_offset: Vector2) -> void: pan_offset += delta_offset # 4. NPC 目录检索与过滤 func get_npcs(category_filter: String = "") -> Array: if category_filter.is_empty(): return PRESET_TOWN_NPCS var filtered: Array = [] for npc in PRESET_TOWN_NPCS: if npc.get("category") == category_filter: filtered.append(npc) return filtered func find_npc_by_vid(vid: int) -> Dictionary: for npc in PRESET_TOWN_NPCS: if npc.get("vid") == vid: return npc return {} # 5. 信标寻路导航点机制 (1:1 CPythonMiniMap::AddSignalPoint / ClearAllSignalPoint) func add_signal_point(target_x: float, target_y: float) -> Dictionary: var pt := { "x": target_x, "y": target_y, "active": true } signal_points.append(pt) return pt func clear_all_signals() -> void: signal_points.clear() # 6. 指南针方位角与距离计算 (角色与目标间的连线向量) func calculate_navigation_vector(player_pos: Vector2, target_pos: Vector2) -> Dictionary: var diff := target_pos - player_pos var dist := diff.length() var angle_rad := diff.angle() var angle_deg := rad_to_deg(angle_rad) return { "distance": dist, "direction_vector": diff.normalized() if dist > 0.001 else Vector2.ZERO, "angle_rad": angle_rad, "angle_deg": angle_deg, "arrived": (dist <= 30.0) # 30 码内视为到达目标 } # 7. 世界坐标至大地图 UI 局部像素坐标投影转换 func world_to_atlas_coord(world_pos: Vector2) -> Vector2: var map_info := get_current_map_info() var world_size: Vector2 = map_info.get("world_size", Vector2(4000, 4000)) var atlas_size: Vector2 = map_info.get("size", Vector2(256, 256)) var ratio_x := atlas_size.x / world_size.x var ratio_y := atlas_size.y / world_size.y var projected := Vector2(world_pos.x * ratio_x, world_pos.y * ratio_y) return (projected * zoom_level) + pan_offset