Files
mtgodot-poc/formats/msa.h
T
shenandshen c93894313a fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
2026-09-21 16:38:59 -07:00

109 lines
4.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; // MotionEventType1=effect, 4=special attack, 6=fly, ...
float start_time = 0; // StartingTime
float duration_time = 0; // DuringTimeSCREEN_WAVING / SPECIAL_ATTACKING
std::string effect_file; // EffectFileNametype 1/10
std::string sound_file; // SoundFileName
std::string attaching_bone;
bool attaching = false;
bool following = false;
bool independent = false;
bool fishing_effect = false;
float position[3] = {0, 0, 0};
// FLY 的字段不能复用 EFFECT 的 EffectFileName/EffectPosition40250
// 在 MotionEventDataEvent.h 中使用另一套 FlyFileName/FlyPosition。
std::string fly_file;
std::string fly_attaching_bone;
bool fly_attaching = false;
float fly_position[3] = {0, 0, 0};
// SCREEN_WAVING 参数(GameEventManager::ProcessEventScreenWaving)。
int power = 0;
int affecting_range = 0;
// SPECIAL_ATTACKING 参数(TMotionAttackingEventData)。
bool enable_hit_process = true; // 40250 缺省值为 TRUE
int attack_type = 0;
int hitting_type = 0;
float stiffen_time = 0;
float invisible_time = 0;
float external_force = 0;
int hit_limit_count = 0;
int collision_type = 0;
struct CollisionSphere {
float radius = 0;
float position[3] = {0, 0, 0};
};
std::vector<CollisionSphere> collision_spheres;
};
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