Files
mtgodot-poc/project/intro_create_phase.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

133 lines
4.0 KiB
GDScript

# intro_create_phase.gd —— 40250 3D 角色塑形创建系统 1:1
# 严格对照:
# Client/Eternexus/root/introcreate.py (CreateCharacterWindow)
# ClientVS22/source/UserInterface/InstanceBaseTransform.cpp
# metin2/src/server/game/src/player.cpp
extends RefCounted
const JOB_WARRIOR := 0
const JOB_ASSASSIN := 1
const JOB_SURA := 2
const JOB_SHAMAN := 3
const GENDER_MALE := 0 # MAN
const GENDER_FEMALE := 1 # WOMAN
const SHAPE_0 := 0 # 经典外观 1 (SHAPE0)
const SHAPE_1 := 1 # 经典外观 2 (SHAPE1)
# 40250 官方职业初始四维属性分配表 (CON, INT, STR, DEX)
# 对应 introcreate.py: START_STAT
const START_STAT_TABLE := {
JOB_WARRIOR: { "con": 4, "int": 3, "str": 6, "dex": 3 }, # 战士
JOB_ASSASSIN: { "con": 3, "int": 3, "str": 4, "dex": 6 }, # 刺客
JOB_SURA: { "con": 3, "int": 5, "str": 5, "dex": 3 }, # 修罗
JOB_SHAMAN: { "con": 4, "int": 6, "str": 3, "dex": 3 }, # 萨满
}
# 违禁词简易过滤器
const BANNED_NAME_PATTERNS := ["[GM]", "admin", "null", "fuck", "shit"]
# 当前创建器状态
var selected_job: int = JOB_WARRIOR
var selected_gender: int = GENDER_MALE
var selected_shape: int = SHAPE_0
var turntable_rotation_deg: float = 0.0 # 360° 转盘旋转角度
func _init(p_job: int = JOB_WARRIOR, p_gender: int = GENDER_MALE) -> void:
selected_job = p_job
selected_gender = p_gender
selected_shape = SHAPE_0
turntable_rotation_deg = 0.0
# 1. 切换职业与属性联动
func select_job(job_id: int) -> bool:
if not START_STAT_TABLE.has(job_id):
return false
selected_job = job_id
return true
# 2. 切换性别
func select_gender(gender_id: int) -> bool:
if gender_id != GENDER_MALE and gender_id != GENDER_FEMALE:
return false
selected_gender = gender_id
return true
# 3. 切换外观 (Shape 0 / Shape 1)
func select_shape(shape_id: int) -> bool:
if shape_id != SHAPE_0 and shape_id != SHAPE_1:
return false
selected_shape = shape_id
return true
# 4. 旋转展示台 (360 度循环)
func rotate_turntable(delta_deg: float) -> float:
turntable_rotation_deg = fposmod(turntable_rotation_deg + delta_deg, 360.0)
return turntable_rotation_deg
# 5. 获取当前职业的基础四维属性
func get_current_stats() -> Dictionary:
return START_STAT_TABLE.get(selected_job, { "con": 4, "int": 3, "str": 6, "dex": 3 })
# 6. 角色名称合规性校验
func validate_character_name(name_str: String) -> Dictionary:
var res := { "valid": false, "error_code": "OK", "message": "" }
if name_str.is_empty():
res["error_code"] = "EMPTY_NAME"
res["message"] = "角色名称不能为空。"
return res
var length := name_str.length()
if length < 2 or length > 12:
res["error_code"] = "INVALID_NAME_LENGTH"
res["message"] = "角色名称长度需在 2 到 12 字符之间。"
return res
if name_str.contains(" ") or name_str.contains("\t"):
res["error_code"] = "NAME_CONTAINS_SPACE"
res["message"] = "角色名称中不能包含空格。"
return res
var lower_name := name_str.to_lower()
for banned in BANNED_NAME_PATTERNS:
if lower_name.contains(banned.to_lower()):
res["error_code"] = "NAME_CONTAINS_BANNED_WORD"
res["message"] = "角色名称中包含非法或保留字符。"
return res
res["valid"] = true
return res
# 7. 确认创建角色并打包角色初始数据
func create_character(name_str: String, empire_id: int = 1) -> Dictionary:
var val = validate_character_name(name_str)
if not val["valid"]:
return { "success": false, "error_code": val["error_code"], "message": val["message"] }
var stats: Dictionary = get_current_stats()
var char_data := {
"name": name_str,
"empire": empire_id,
"level": 1,
"exp": 0,
"job": selected_job,
"gender": selected_gender,
"shape": selected_shape,
"cur_hp": 1000,
"max_hp": 1000,
"cur_sp": 500,
"max_sp": 500,
"stats": stats,
"horse_level": 0,
"playtime_min": 0,
"delete_code": "1234567" # 默认 7 位删除安全码
}
return {
"success": true,
"character": char_data,
"message": "角色 %s 创建成功!" % name_str
}