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 客户端对拍缺陷发现与修复工程指南
This commit is contained in:
shen
2026-09-19 08:51:25 -07:00
parent 1db9e9a129
commit 66d217b313
650 changed files with 53046 additions and 1586 deletions
+115
View File
@@ -0,0 +1,115 @@
# refine_effect_system.gd —— +7/+8/+9 装备强化专属发光特效(40250 官方 1:1 对齐)
# 对齐源码:
# - 40250 ClientVS22/source/UserInterface/InstanceBase.cpp:2698-2740 (AttachEffect, EFFECT_REFINED)
# - 40250 ClientVS22/source/UserInterface/InstanceBase.h:268-297 (EFFECT_REFINED_NUM)
# - 40250 root/playersettingmodule.py:391-416 (RegisterEffect, sword_7..9.mse, armor_7..9.mse)
class_name RefineEffectSystem
extends RefCounted
# 40250 官方发光分级常量
const REFINE_SHINE_START_LEVEL := 7 # 从 +7 开始出现发光特效
const SHINE_TIER_7 := 7
const SHINE_TIER_8 := 8
const SHINE_TIER_9 := 9
# 官方发光特效配置文件映射表 (40250 playersettingmodule.py:391-416)
const WEAPON_SHINE_EFFECTS := {
SHINE_TIER_7: "d:/ymir work/pc/common/effect/sword/sword_7.mse",
SHINE_TIER_8: "d:/ymir work/pc/common/effect/sword/sword_8.mse",
SHINE_TIER_9: "d:/ymir work/pc/common/effect/sword/sword_9.mse",
}
const ARMOR_SHINE_EFFECTS := {
SHINE_TIER_7: "d:/ymir work/pc/common/effect/armor/armor_7.mse",
SHINE_TIER_8: "d:/ymir work/pc/common/effect/armor/armor_8.mse",
SHINE_TIER_9: "d:/ymir work/pc/common/effect/armor/armor_9.mse",
}
# 66~70 级高级黑钢战甲特效 (armor-4-2-1.mse, armor-4-2-2.mse)
const SPECIAL_ARMOR_EFFECTS := {
SHINE_TIER_7: "d:/ymir work/pc/common/effect/armor/armor-4-2-1.mse",
SHINE_TIER_8: "d:/ymir work/pc/common/effect/armor/armor-4-2-2.mse",
SHINE_TIER_9: "d:/ymir work/pc/common/effect/armor/armor-4-2.mse",
}
# 骨骼挂载点定义 (InstanceBase.cpp:2698)
const ATTACH_BONE_WEAPON_RIGHT := "PART_WEAPON" # 右手武器
const ATTACH_BONE_WEAPON_LEFT := "PART_WEAPON_LEFT" # 左手武器(如双持匕首)
const ATTACH_BONE_ARMOR := "Bip01" # 盔甲躯干
# 发光色调配置(用于 Godot 动态粒子与材质 Emission
const SHINE_COLORS := {
SHINE_TIER_7: Color(0.9, 0.95, 1.0, 0.7), # +7: 浅白清冷光晕
SHINE_TIER_8: Color(0.3, 0.7, 1.0, 0.85), # +8: 亮蓝闪烁流光
SHINE_TIER_9: Color(1.0, 0.85, 0.2, 1.0), # +9: 强烈金黄/电光辉光
}
## 从物品 Vnum 解析强化等级 (Metin2 官方惯例:vnum % 10 为强化等级)
static func get_refine_level_from_vnum(vnum: int) -> int:
if vnum <= 0:
return 0
return vnum % 10
## 检查该物品是否具备 +7/+8/+9 专属发光
static func is_shining_item(vnum: int, item_type: int) -> bool:
if item_type not in [1, 2]: # 1: WEAPON, 2: ARMOR
return false
var lvl := get_refine_level_from_vnum(vnum)
return lvl >= REFINE_SHINE_START_LEVEL
## 获取发光特效数据配置
static func get_shine_spec(vnum: int, item_type: int, is_left_hand := false) -> Dictionary:
var lvl := get_refine_level_from_vnum(vnum)
if lvl < REFINE_SHINE_START_LEVEL:
return {"shining": false, "level": lvl}
var attach_bone := ""
var effect_path := ""
var color: Color = SHINE_COLORS.get(lvl, Color.WHITE)
if item_type == 1: # WEAPON
attach_bone = ATTACH_BONE_WEAPON_LEFT if is_left_hand else ATTACH_BONE_WEAPON_RIGHT
effect_path = WEAPON_SHINE_EFFECTS.get(lvl, "")
elif item_type == 2: # ARMOR
attach_bone = ATTACH_BONE_ARMOR
# 判断是否为 66 级以上黑钢特种战甲 (如 11290..11299)
if vnum >= 11290 and vnum <= 11899:
effect_path = SPECIAL_ARMOR_EFFECTS.get(lvl, "")
else:
effect_path = ARMOR_SHINE_EFFECTS.get(lvl, "")
return {
"shining": true,
"level": lvl,
"attach_bone": attach_bone,
"effect_path": effect_path,
"color": color,
"particle_rate": 15 if lvl == 7 else (30 if lvl == 8 else 60),
"light_energy": 0.8 if lvl == 7 else (1.5 if lvl == 8 else 3.0),
}
## 创建发光粒子节点(可在挂载模型时直接附加到 Skeleton3D)
static func create_shine_particles(spec: Dictionary) -> GPUParticles3D:
if not bool(spec.get("shining", false)):
return null
var particles := GPUParticles3D.new()
particles.name = "RefineShineParticles_L%d" % int(spec.get("level", 7))
particles.amount = int(spec.get("particle_rate", 20))
particles.lifetime = 0.6
particles.explosiveness = 0.05
particles.randomness = 0.2
# 创建材质
var mat := StandardMaterial3D.new()
mat.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
mat.albedo_color = spec.get("color", Color.WHITE)
mat.emission_enabled = true
mat.emission = spec.get("color", Color.WHITE)
mat.emission_energy_multiplier = float(spec.get("light_energy", 1.0))
var quad := QuadMesh.new()
quad.size = Vector2(0.12, 0.12)
quad.material = mat
particles.draw_pass_1 = quad
return particles