Files
mtgodot-poc/formats/combo_table.h
T

93 lines
4.1 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.
// combo_table —— PC 连击段表(CRaceData::TComboAttackDataMap 的等价)。M2 §3.5。
//
// 参考端的 PC 连击段表**不在** .msm 里(.msm 只有 BaseModelFileName + HairData)。
// 它由 playersettingmodule.py 的 chrmgr.ReserveComboAttackNew / RegisterComboAttackNew
// 调用在 CRaceData 上建起来(UserInterface/PythonCharacterManagerModule.cpp →
// CRaceData::ReserveComboAttack / RegisterComboAttackGameLib/RaceData.cpp)。
// 本解析器就把那批调用读成同一张表。
//
// NPC/怪物的连击段走另一条路(RaceManager.cpp __LoadRaceMotionList 读 motlist.txt
// 只在 MODE_GENERAL 下登记 NAME_COMBO_ATTACK_1/2/3,没有段号向量),不在这里。
#pragma once
#include <cstdint>
#include <map>
#include <string>
#include <vector>
namespace fmt {
// CRaceMotionData::EModechr.MOTION_MODE_*)。combo key 的高 16 位。
enum ComboMotionMode : uint16_t {
COMBO_MODE_RESERVED = 0,
COMBO_MODE_GENERAL = 1,
COMBO_MODE_ONEHAND_SWORD = 2,
COMBO_MODE_TWOHAND_SWORD = 3,
COMBO_MODE_DUALHAND_SWORD = 4,
COMBO_MODE_BOW = 5,
COMBO_MODE_FAN = 6,
COMBO_MODE_BELL = 7,
COMBO_MODE_FISHING = 8,
COMBO_MODE_HORSE = 9,
COMBO_MODE_HORSE_ONEHAND_SWORD = 10,
COMBO_MODE_HORSE_TWOHAND_SWORD = 11,
COMBO_MODE_HORSE_DUALHAND_SWORD = 12,
COMBO_MODE_HORSE_BOW = 13,
COMBO_MODE_HORSE_FAN = 14,
COMBO_MODE_HORSE_BELL = 15,
COMBO_MODE_WEDDING_DRESS = 16,
};
// CRaceMotionData::EName 的攻击段(chr.MOTION_NORMAL_ATTACK / chr.MOTION_COMBO_ATTACK_*)。
// ComboIndexVector 里存的就是这些段号。
enum : uint16_t {
COMBO_NAME_NORMAL_ATTACK = 13,
COMBO_NAME_COMBO_ATTACK_1 = 14,
COMBO_NAME_COMBO_ATTACK_8 = 21,
};
// RaceData.h: MAKE_COMBO_KEY(motion_mode, combo_type)
inline uint32_t make_combo_key(uint16_t motion_mode, uint16_t combo_type) {
return (static_cast<uint32_t>(motion_mode) << 16) | static_cast<uint32_t>(combo_type);
}
inline uint16_t combo_key_mode(uint32_t key) { return static_cast<uint16_t>((key >> 16) & 0xFFFF); }
inline uint16_t combo_key_type(uint32_t key) { return static_cast<uint16_t>(key & 0xFFFF); }
// playersettingmodule.py 按 __LoadGame<Class>Ex(race, path) 分四块,男女同一函数体
// (连击段表与性别无关),所以这里按职业收,不按 race。
enum ComboClass : int {
COMBO_CLASS_WARRIOR = 0,
COMBO_CLASS_ASSASSIN = 1,
COMBO_CLASS_SURA = 2,
COMBO_CLASS_SHAMAN = 3,
COMBO_CLASS_COUNT = 4,
};
// CRaceData::TComboAttackDataMap 的等价:MAKE_COMBO_KEY -> ComboIndexVector。
struct ComboTable {
// key = make_combo_key(mode, type)value = 有序的 COMBO_NAME_COMBO_ATTACK_* 段号,
// 下标即 dwComboArrayIndexm_dwcurComboIndex - 1)。
std::map<uint32_t, std::vector<uint16_t>> combos;
// GetComboDataPointer:命中返回段号向量指针,否则 nullptr。
const std::vector<uint16_t>* get(uint16_t motion_mode, uint16_t combo_type) const;
bool empty() const { return combos.empty(); }
size_t key_count() const { return combos.size(); }
};
struct PlayerComboTables {
ComboTable per_class[COMBO_CLASS_COUNT];
// 越界返回一张空表(不抛)。
const ComboTable& klass(int combo_class) const;
};
// 解析 playersettingmodule.py 里的 chrmgr.ReserveComboAttackNew / RegisterComboAttackNew
// 调用,按 def __LoadGame<Class>Ex 分块填 per_class。照 CRaceData 语义:
// Reserve -> combos[key] = vector(count, 0)(重复 key 不覆盖,同 std::map::insert
// Register -> combos[key][index] = motionkey 未 Reserve 或 index 越界则跳过)
// 认得的符号:chr.MOTION_MODE_*、chr.MOTION_COMBO_ATTACK_N=13+N)、
// chr.MOTION_NORMAL_ATTACK=13)、COMBO_TYPE_N=N-1)、COMBO_INDEX_N=N-1)、裸整数。
bool parse_player_combo_tables(const std::string& py_text, PlayerComboTables& out, std::string* err);
bool parse_player_combo_tables_file(const std::string& path, PlayerComboTables& out, std::string* err);
} // namespace fmt