Implement 40250 classic client port
This commit is contained in:
@@ -17,6 +17,7 @@ const FEMALE_RACES := [1, 3, 4, 6]
|
||||
var model: Node # Metin2Model
|
||||
var anim: Node # Metin2AnimPlayer
|
||||
var motion_dir := ""
|
||||
var action_dir := ""
|
||||
var _state := ""
|
||||
var _forward := ["weapon_gr2", "shield_gr2", "gr2_path", "hair_gr2", "hair_skin", "specular_power"]
|
||||
|
||||
@@ -33,6 +34,7 @@ func build(assets_root: String, race: int, pump := Callable()) -> bool:
|
||||
if base == "":
|
||||
return false
|
||||
motion_dir = base.path_join("general")
|
||||
action_dir = base.path_join("action")
|
||||
|
||||
model = ClassDB.instantiate("Metin2Model")
|
||||
model.name = "Metin2Model"
|
||||
@@ -54,6 +56,8 @@ func build(assets_root: String, race: int, pump := Callable()) -> bool:
|
||||
anim.set("loop", true)
|
||||
anim.set("blend_time", 0.15)
|
||||
add_child(anim)
|
||||
if anim.has_signal("playback_finished"):
|
||||
anim.playback_finished.connect(_on_playback_finished)
|
||||
if pump.is_valid(): pump.call()
|
||||
set_anim_state("wait") # 重:解 .msa
|
||||
if pump.is_valid(): pump.call()
|
||||
@@ -71,6 +75,86 @@ func set_anim_state(s: String) -> void:
|
||||
anim.set("loop", s in ["wait", "walk", "run"])
|
||||
anim.set("anim_path", 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
|
||||
# kiss/french-kiss variants, exactly like ActDualEmotion in the native client.
|
||||
func set_motion_id(motion: int, target_race: int = -1) -> bool:
|
||||
if anim == null:
|
||||
return false
|
||||
var name := ""
|
||||
if motion == 305:
|
||||
name = "clap"
|
||||
elif motion == 306:
|
||||
name = "cheers_1"
|
||||
elif motion == 307:
|
||||
name = "cheers_2"
|
||||
elif motion >= 308 and motion <= 311:
|
||||
var job := motion - 308
|
||||
if motion == 308 and target_race >= 0:
|
||||
job = target_race & 3
|
||||
name = "kiss_with_" + CLASS_OF[clampi(job, 0, 3)]
|
||||
elif motion >= 312 and motion <= 315:
|
||||
var french_job := motion - 312
|
||||
if motion == 312 and target_race >= 0:
|
||||
french_job = target_race & 3
|
||||
name = "french_kiss_with_" + CLASS_OF[clampi(french_job, 0, 3)]
|
||||
elif motion >= 316 and motion <= 319:
|
||||
name = "slap_hit"
|
||||
elif motion >= 320 and motion <= 323:
|
||||
name = "slap_hurt"
|
||||
elif motion == 324:
|
||||
name = "dig"
|
||||
elif motion >= 325 and motion <= 340:
|
||||
name = "dance_%d" % (motion - 324)
|
||||
elif motion == 341:
|
||||
name = "congratulation"
|
||||
elif motion == 342:
|
||||
name = "forgive"
|
||||
elif motion == 343:
|
||||
name = "angry"
|
||||
elif motion == 344:
|
||||
name = "attractive"
|
||||
elif motion == 345:
|
||||
name = "sad"
|
||||
elif motion == 346:
|
||||
name = "shy"
|
||||
elif motion == 347:
|
||||
name = "cheerup"
|
||||
elif motion == 348:
|
||||
name = "banter"
|
||||
elif motion == 349:
|
||||
name = "joy"
|
||||
elif motion == 5 or motion == 6 or motion == 8 or motion == 9:
|
||||
set_anim_state("damage")
|
||||
return true
|
||||
elif motion == 11 or motion == 12:
|
||||
set_anim_state("dead")
|
||||
return true
|
||||
elif motion >= 13 and motion <= 21:
|
||||
set_anim_state("attack")
|
||||
return true
|
||||
else:
|
||||
return false
|
||||
|
||||
var msa := action_dir.path_join(name + ".msa")
|
||||
if not FileAccess.file_exists(msa):
|
||||
msa = motion_dir.path_join(name + ".msa")
|
||||
if not FileAccess.file_exists(msa):
|
||||
return false
|
||||
_state = "__motion"
|
||||
anim.set("loop", false)
|
||||
# A repeated command can name the same clip; clear first because the native
|
||||
# player treats assigning the current anim_path as a no-op.
|
||||
if String(anim.get("anim_path")) == msa:
|
||||
anim.set("anim_path", "")
|
||||
anim.set("anim_path", msa)
|
||||
return true
|
||||
|
||||
func _on_playback_finished() -> void:
|
||||
if _state == "__motion":
|
||||
_state = ""
|
||||
set_anim_state("wait")
|
||||
|
||||
func _set(prop: StringName, val: Variant) -> bool:
|
||||
if String(prop) in _forward and model:
|
||||
model.set(prop, val)
|
||||
|
||||
Reference in New Issue
Block a user