no message
This commit is contained in:
+22
-1
@@ -30,6 +30,8 @@ const STATE_MOTIONS := {
|
||||
"standup_back": ["BACK_STANDUP"],
|
||||
}
|
||||
const HitReaction = preload("res://ui/hit_reaction.gd")
|
||||
const MsaMotion = preload("res://ui/msa_motion.gd")
|
||||
const MOVE_STATES := ["walk", "run"]
|
||||
const HitCollision = preload("res://hit_collision.gd")
|
||||
|
||||
# CActorInstance::__SetMotion 尾:动作绑定完成。
|
||||
@@ -42,6 +44,7 @@ var _mesh_stem := ""
|
||||
var _hit := HitReaction.new()
|
||||
var _motions := {} # MOTION_NAME(String) -> 绝对 .msa 路径
|
||||
var _state := ""
|
||||
var _move_speed_ratio := 1.0
|
||||
var _last_resolution := {}
|
||||
var _audio: Node
|
||||
var _sound_instances: Array = []
|
||||
@@ -156,7 +159,25 @@ func set_anim_state(s: String) -> void:
|
||||
if msa == "":
|
||||
# 旧客户端 GetMotionKey 失败时 SetLoopMotion/InterceptMotion 直接返回:保留当前动作。
|
||||
return
|
||||
_bind(s, msa, s in HitReaction.LOOP_STATES, 1.0)
|
||||
_bind(s, msa, s in HitReaction.LOOP_STATES, _loop_speed(s))
|
||||
|
||||
# CActorInstance::SetMoveSpeed:m_fMovSpd = movSpd / 100,走 / 跑循环动作按它播放
|
||||
# (Move -> SetLoopMotion(WALK/RUN, 0.15, m_fMovSpd))。>1100 时参考端不走动作累计,
|
||||
# EntityStore 退回按 duration 插值,这里保持原速播放。
|
||||
func set_move_speed(moving_speed: int) -> void:
|
||||
_move_speed_ratio = 1.0 if moving_speed <= 0 or moving_speed > 1100 \
|
||||
else float(moving_speed) / 100.0
|
||||
if anim != null and _state in MOVE_STATES and not _hit.active:
|
||||
anim.set("time_scale", _hit.scale_for(_move_speed_ratio))
|
||||
|
||||
func _loop_speed(state: String) -> float:
|
||||
return _move_speed_ratio if state in MOVE_STATES else 1.0
|
||||
|
||||
## 走 / 跑动作的根运动速度(cm/s,movSpd 100):x = walk,y = run。0 = 取不到。
|
||||
## net_world 推给 EntityStore,远端移动按动作累计量推进(CActorInstance::AccumulationMovement)。
|
||||
func get_move_motion_speeds() -> Vector2:
|
||||
return Vector2(MsaMotion.move_speed(String(resolve_motion("walk").path)),
|
||||
MsaMotion.move_speed(String(resolve_motion("run").path)))
|
||||
|
||||
# CGraphicThingInstance::InsertDelay(fStiffenTime)
|
||||
func insert_delay(d: float) -> void:
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# MsaMotion —— 读 .msa 文本里的根运动:移动动作每秒位移(cm/s,movSpd 100 时)。
|
||||
#
|
||||
# MotionDuration 0.600000
|
||||
# Accumulation 0.00 -255.45 0.00
|
||||
#
|
||||
# 服务端 CHARACTER::GetMoveMotionSpeed = -Accumulation.y / MotionDuration;
|
||||
# 客户端 CActorInstance::AccumulationMovement 按同一累计量推进。这里取 xy 长度。
|
||||
extends RefCounted
|
||||
|
||||
static var _cache := {} # path -> float
|
||||
|
||||
static func move_speed(path: String) -> float:
|
||||
if path == "" or not path.to_lower().ends_with(".msa"):
|
||||
return 0.0
|
||||
if _cache.has(path):
|
||||
return float(_cache[path])
|
||||
var speed := 0.0
|
||||
var f := FileAccess.open(path, FileAccess.READ)
|
||||
if f:
|
||||
var duration := 0.0
|
||||
var accum := Vector2.ZERO
|
||||
while not f.eof_reached():
|
||||
var parts := _fields(f.get_line())
|
||||
if parts.size() < 2:
|
||||
continue
|
||||
match String(parts[0]):
|
||||
"MotionDuration":
|
||||
duration = String(parts[1]).to_float()
|
||||
"Accumulation":
|
||||
if parts.size() >= 3:
|
||||
accum = Vector2(String(parts[1]).to_float(), String(parts[2]).to_float())
|
||||
if duration > 0.0:
|
||||
speed = accum.length() / duration
|
||||
_cache[path] = speed
|
||||
return speed
|
||||
|
||||
static func _fields(line: String) -> PackedStringArray:
|
||||
return line.strip_edges().replace("\t", " ").split(" ", false)
|
||||
@@ -18,6 +18,8 @@ const FEMALE_RACES := [1, 3, 4, 6]
|
||||
const WEAPON_BONE := ["equip_right_hand", "equip_right", "equip_right", "equip_right"]
|
||||
const WEAPON_LEFT_BONE := ["", "equip_left", "", "equip_left"]
|
||||
const HitReaction = preload("res://ui/hit_reaction.gd")
|
||||
const MsaMotion = preload("res://ui/msa_motion.gd")
|
||||
const MOVE_STATES := ["walk", "run"]
|
||||
const HitCollision = preload("res://hit_collision.gd")
|
||||
# CRaceMotionData::MOTION_MODE_* -> playersettingmodule 注册动作用的目录(与 general 同级)
|
||||
const MOTION_MODE_DIRS := {1: "general", 2: "onehand_sword", 3: "twohand_sword", 4: "dualhand_sword",
|
||||
@@ -43,6 +45,7 @@ var anim: Node # Metin2AnimPlayer
|
||||
var motion_dir := ""
|
||||
var action_dir := ""
|
||||
var _state := ""
|
||||
var _move_speed_ratio := 1.0
|
||||
var _assets_root := ""
|
||||
var _audio: Node
|
||||
var _sound_instances: Array = []
|
||||
@@ -135,7 +138,27 @@ func set_anim_state(s: String) -> void:
|
||||
if not FileAccess.file_exists(msa):
|
||||
msa = motion_dir.path_join(s + ".gr2")
|
||||
if FileAccess.file_exists(msa):
|
||||
_bind(s, msa, s in HitReaction.LOOP_STATES, 1.0)
|
||||
_bind(s, msa, s in HitReaction.LOOP_STATES, _loop_speed(s))
|
||||
|
||||
# CActorInstance::SetMoveSpeed:m_fMovSpd = movSpd / 100,走 / 跑循环动作按它播放
|
||||
# (Move -> SetLoopMotion(WALK/RUN, 0.15, m_fMovSpd))。>1100 时参考端不走动作累计,
|
||||
# EntityStore 退回按 duration 插值,这里保持原速播放。
|
||||
func set_move_speed(moving_speed: int) -> void:
|
||||
_move_speed_ratio = 1.0 if moving_speed <= 0 or moving_speed > 1100 \
|
||||
else float(moving_speed) / 100.0
|
||||
if anim != null and _state in MOVE_STATES and not _hit.active:
|
||||
anim.set("time_scale", _hit.scale_for(_move_speed_ratio))
|
||||
|
||||
func _loop_speed(state: String) -> float:
|
||||
return _move_speed_ratio if state in MOVE_STATES else 1.0
|
||||
|
||||
## 走 / 跑动作的根运动速度(cm/s,movSpd 100):x = walk,y = run。0 = 取不到。
|
||||
## net_world 推给 EntityStore,远端移动按动作累计量推进(CActorInstance::AccumulationMovement)。
|
||||
func get_move_motion_speeds() -> Vector2:
|
||||
if motion_dir == "":
|
||||
return Vector2.ZERO
|
||||
return Vector2(MsaMotion.move_speed(motion_dir.path_join("walk.msa")),
|
||||
MsaMotion.move_speed(motion_dir.path_join("run.msa")))
|
||||
|
||||
# Play one of the 40250 CRaceMotionData one-shot motions. The protocol sends
|
||||
# the numeric motion id; paired emotions use the other entity's race to select
|
||||
|
||||
Reference in New Issue
Block a user