Files
mtgodot-poc/project/map_name_shower_system.gd
T
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight
  - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程
  - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题
  - 新增 test_bridge_height_parity.gd 自动化对拍测试
- 40250 怪物击杀经验动效:
  - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附
- 40250 客户端全系统功能对齐(Batches 1-31):
  - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试
- 文档沉淀:
  - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00

169 lines
5.4 KiB
GDScript

# map_name_shower_system.gd
# 40250 官方 1:1 地图切换横幅渐显与魔塔/恶魔陵墓楼层识别系统
# 对照: uimapnameshower.py, locale_game.txt
class_name MapNameShowerSystem
extends RefCounted
enum State {
STATE_HIDE = 0,
STATE_FADE_IN = 1,
STATE_SHOW = 2,
STATE_FADE_OUT = 3
}
const MAP_NAME_IMAGES: Dictionary = {
"metin2_map_a1": "locale/ui/mapname/a1.tga",
"map_a2": "locale/ui/mapname/a2.tga",
"metin2_map_a3": "locale/ui/mapname/a3.tga",
"metin2_map_b1": "locale/ui/mapname/b1.tga",
"map_b2": "locale/ui/mapname/b2.tga",
"metin2_map_b3": "locale/ui/mapname/b3.tga",
"metin2_map_c1": "locale/ui/mapname/c1.tga",
"map_c2": "locale/ui/mapname/c2.tga",
"metin2_map_c3": "locale/ui/mapname/c3.tga",
"map_n_snowm_01": "locale/ui/mapname/snow1.tga",
"metin2_map_deviltower1": "locale/ui/mapname/devil1_title.tga",
"metin2_map_n_flame_01": "locale/ui/mapname/frame1.tga",
"metin2_map_n_desert_01": "locale/ui/mapname/desert1.tga",
"metin2_map_milgyo": "locale/ui/mapname/milgyo.tga",
"metin2_map_monkeydungeon": "locale/ui/mapname/monkey1.tga",
"metin2_map_monkeydungeon_02": "locale/ui/mapname/monkey2.tga",
"metin2_map_monkeydungeon_03": "locale/ui/mapname/monkey3.tga",
"metin2_map_guild_01": "locale/ui/mapname/guild1.tga",
"metin2_map_guild_02": "locale/ui/mapname/guild2.tga",
"metin2_map_guild_03": "locale/ui/mapname/guild3.tga",
"metin2_map_trent": "locale/ui/mapname/trent.tga",
"metin2_map_trent02": "locale/ui/mapname/trent02.tga",
"metin2_map_devilsCatacomb": "locale/ui/mapname/devil_basement.tga",
"metin2_map_spiderdungeon": "locale/ui/mapname/spider1.tga",
"metin2_map_spiderdungeon_02": "locale/ui/mapname/spider1.tga",
"metin2_map_spiderdungeon_03": "locale/ui/mapname/spider1.tga"
}
var current_map_name: String = ""
var current_image_path: String = ""
var current_floor_image: String = ""
var current_floor_number: int = 0
var current_x: float = 0.0
var current_y: float = 0.0
var state: State = State.STATE_HIDE
var cur_alpha: float = 0.0
var fade_start_time: float = 0.0
var pos_x: int = 0
var pos_y: int = 80
signal map_name_triggered(map_name: String, image_path: String, floor_num: int)
signal state_changed(new_state: State, alpha: float)
signal banner_hidden()
# 40250 官方通天魔塔 9 层空间识别算法
func get_devil_tower_floor(x: float, y: float) -> int:
if x > 10000 and y > 58000 and x < 25000 and y < 72000:
return 1
elif x > 10000 and y > 35000 and x < 25000 and y < 50000:
return 2
elif x > 10000 and y > 10000 and x < 25000 and y < 25000:
return 3
elif x > 35000 and y > 61000 and x < 43500 and y < 70500:
return 4
elif x > 35000 and y > 38000 and x < 43500 and y < 48000:
return 5
elif x > 14000 and y > 14000 and x < 43500 and y < 24500:
return 6
elif x > 56000 and y > 60000 and x < 68000 and y < 73000:
return 7
elif x > 56000 and y > 38000 and x < 68000 and y < 49000:
return 8
elif x > 56000 and y > 13000 and x < 68000 and y < 23000:
return 9
return 0
# 40250 官方恶魔地下陵墓 7 层空间识别算法
func get_devil_catacomb_base(x: float, y: float) -> int:
if x > 3000 and y > 4500 and x < 45000 and y < 45000:
return 1
elif x > 54000 and y > 3900 and x < 100000 and y < 46200:
return 2
elif x > 104800 and y > 3500 and x < 145500 and y < 45800:
return 3
elif x > 3100 and y > 54100 and x < 56400 and y < 105800:
return 4
elif x > 65000 and y > 54000 and x < 105000 and y < 95500:
return 5
elif x > 117500 and y > 57600 and x < 142000 and y < 81000:
return 6
elif x > 5000 and y > 104900 and x < 15000 and y < 122000:
return 7
return 0
func show_map_name(map_name: String, x: float, y: float, now_time: float) -> bool:
if not MAP_NAME_IMAGES.has(map_name):
return false
current_map_name = map_name
current_image_path = MAP_NAME_IMAGES[map_name]
current_x = x
current_y = y
current_floor_image = ""
current_floor_number = 0
pos_x = 0
pos_y = 80
if map_name == "metin2_map_deviltower1":
pos_x = -60
current_floor_number = get_devil_tower_floor(x, y)
if current_floor_number > 0:
current_floor_image = "locale/ui/mapname/devil1_%df.tga" % current_floor_number
elif map_name == "metin2_map_devilsCatacomb":
pos_x = -75
current_floor_number = get_devil_catacomb_base(x, y)
if current_floor_number > 0:
current_floor_image = "locale/ui/mapname/devil1_%df.tga" % current_floor_number
cur_alpha = 0.0
state = State.STATE_FADE_IN
fade_start_time = now_time + 1.0
map_name_triggered.emit(map_name, current_image_path, current_floor_number)
state_changed.emit(state, cur_alpha)
return true
func update_step(now_time: float) -> void:
if state == State.STATE_HIDE:
return
if state == State.STATE_FADE_IN:
if now_time >= fade_start_time:
cur_alpha = minf(1.0, cur_alpha + 0.05)
if cur_alpha >= 0.9:
state = State.STATE_SHOW
fade_start_time = now_time + 5.0
state_changed.emit(state, cur_alpha)
elif state == State.STATE_SHOW:
if now_time >= fade_start_time:
state = State.STATE_FADE_OUT
state_changed.emit(state, cur_alpha)
elif state == State.STATE_FADE_OUT:
cur_alpha = maxf(0.0, cur_alpha - 0.05)
if cur_alpha < 0.0001:
cur_alpha = 0.0
state = State.STATE_HIDE
current_floor_image = ""
state_changed.emit(state, cur_alpha)
banner_hidden.emit()
else:
state_changed.emit(state, cur_alpha)
func hide_banner() -> void:
state = State.STATE_HIDE
cur_alpha = 0.0
current_floor_image = ""
state_changed.emit(state, cur_alpha)
banner_hidden.emit()