Files
mtgodot-poc/formats/msa.h
T

77 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// .msa —— Metin2 动作描述(文本,ScriptType MotionData)。M2 T1。
#pragma once
#include <string>
#include <vector>
namespace fmt {
struct MotionEvent {
int type = 0; // MotionEventType10=effect, 4/5=sound, ...
float start_time = 0; // StartingTime
std::string effect_file; // EffectFileNametype 10
std::string sound_file; // SoundFileName
float position[3] = {0, 0, 0};
};
struct Msa {
std::string motion_gr2; // MotionFileName(原样,含 d:\... 前缀)
float duration = 0; // MotionDuration
float accumulation[3] = {0,0,0};// Accumulationroot motion 位移)
std::vector<MotionEvent> events;
bool has_loop_data = false; // LoopData 是片段循环,不等同于整段播放模式
int motion_loop_count = 0; // -1 无限;原客户端仅在 >1 或 -1 时回绕片段
bool loop_cancel_enable = false;
float loop_start_time = 0;
float loop_end_time = 0;
// Group ComboInputData —— 连击输入时间窗(EterGrnLib CGrannyMotion::LoadMotionData →
// CRaceMotionData::TComboInputData)。攻击节奏来自这里,不是硬编码间隔。
// PreInputTime → fInputStartTime 连击输入窗开始(可提前缓存下一击)
// DirectInputTime→ fNextComboTime 直接输入阈值 / 下一段连击起点(= 普攻节奏)
// InputLimitTime → fInputEndTime 连击输入窗关闭(超时归零)
// LinkTime → fComboLinkTime 段间衔接时间
bool has_combo_input = false;
float combo_pre_input_time = 0;
float combo_direct_input_time = 0;
float combo_input_limit_time = 0;
float combo_link_time = 0;
// Group AttackingData —— 命中判定窗(GameLib GameType.cpp NRaceData::TMotionAttackData)。
// 两种写法:老式(组内直接 AttackingStartTime/…/List HitPosition,无 HitDataCount=
// 单个命中窗;新式(AttackType + MotionType + HitDataCount N + Group HitData00..0N=
// N 个命中窗(多段挥击 / 旋风斩)。命中帧 / 硬直 / 无敌帧由动作数据驱动。
bool has_attacking_data = false;
int attacking_type = 0; // AttackType / AttackingTypeSAttackData::iAttackType
int motion_type = 0; // MotionType(缺省回退到 attacking_type
int hitting_type = 0; // HittingType
float stiffen_time = 0; // StiffenTime(受击硬直,喂给 §3.7 / 受击方)
float invisible_time = 0; // InvisibleTime(攻击者无敌帧)
float external_force = 0; // ExternalForce(击退力度)
int hit_limit_count = 0; // HitLimitCount0 = 不限)
// HitPosition 单个采样:time + 上一帧位置(xyz) + 当前帧位置(xyz),用于挥击扫掠球判定。
struct HitSample {
float time = 0;
float last_pos[3] = {0, 0, 0};
float pos[3] = {0, 0, 0};
};
// 一个命中窗(NRaceData::THitData)。
struct HitWindow {
float start_time = 0; // AttackingStartTime
float end_time = 0; // AttackingEndTime
std::string bone_name; // AttackingBone
float weapon_length = 0; // WeaponLength
std::vector<HitSample> samples; // List HitPosition
};
std::vector<HitWindow> hit_windows; // = THitDataContainer;老式写法长度为 1
// 兼容旧调用方:第一个命中窗的起止时间(无命中窗时为 0)。
float attack_start_time = 0;
float attack_end_time = 0;
};
bool parse_msa(const std::string& text, Msa& out, std::string* err);
bool parse_msa_file(const std::string& path, Msa& out, std::string* err);
} // namespace fmt