- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
169 lines
5.4 KiB
GDScript
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()
|