// Filename : CECCastSkillWhenMove.cs // Creator : Xu Wenbin // Date : 2014/8/1 // Converted to C# from C++ by AI Assistant using BrewMonster.Scripts.Skills; using System.Linq; namespace BrewMonster { // Constants from EC_RoleTypes.h public static class RoleTypes { // 职业 // Profession public const int PROF_WARRIOR = 0; // 武侠 // Warrior public const int PROF_MAGE = 1; // 法师 // Mage public const int PROF_MONK = 2; // 巫师 // Monk public const int PROF_HAG = 3; // 妖精 // Hag public const int PROF_ORC = 4; // 妖兽 // Orc public const int PROF_GHOST = 5; // 刺客 // Ghost public const int PROF_ARCHOR = 6; // 羽芒 // Archer public const int PROF_ANGEL = 7; // 羽灵 // Angel public const int PROF_JIANLING = 8; // 剑灵 // Jianling public const int PROF_MEILING = 9; // 魅灵 // Meiling public const int PROF_YEYING = 10; // 夜影 // Yeying public const int PROF_YUEXIAN = 11; // 月仙 // Yuexian public const int NUM_PROFESSION = 12; // 性别 // Gender public const int GENDER_MALE = 0; public const int GENDER_FEMALE = 1; public const int NUM_GENDER = 2; } // Constants from EC_Player.h public static class PlayerModelType { public const int PLAYERMODEL_MAJOR = 0; // 主模型 // Major model public const int PLAYERMODEL_PROFESSION = 1; // 职业变身 // Profession transformation public const int PLAYERMODEL_DUMMYTYPE2 = 2; // Buff相关 // Buff related public const int PLAYERMODEL_DUMMYTYPE3 = 3; // 未使用 // Not used public const int PLAYERMODEL_MAX = 4; public const int PLAYERMODEL_TYPEALL = unchecked((int)0xffffffff); } // Constants from EC_Resource.h public static class ResourceModel { public const int RES_MOD_YUEXIAN_M = 0; // 月仙男标准模型 // Yuexian male standard model public const int RES_MOD_YUEXIAN_F = 1; // 月仙女标准模型 // Yuexian female standard model public const int RES_MOD_YUEXIAN_RESHAPE_M = 2; // 月仙男职业变身 // Yuexian male profession reshape public const int RES_MOD_YUEXIAN_RESHAPE_F = 3; // 月仙女职业变身 // Yuexian female profession reshape } /// /// 移动施法管理类 // Cast Skill When Move Manager /// public class CECCastSkillWhenMove : Singleton { // 朦胧 // Oboro // 标准男性 UpperBody // Standard male upper body bones private static readonly string[] s_szOboroMaleStandardUpperBodyBonesName = { "Bip01 shangshen", "Bip01 Spine", "Bip01 Spine1", "Bip01 Spine2", "Bip01 Neck", "Bip01 Head", "Bip01 L Clavicle", "Bip01 L UpperArm", "Bip01 L Forearm", "Bip01 L Hand", "Bip01 L Finger0", "Bip01 L Finger01", "Bip01 L Finger1", "Bip01 L Finger11", "Bip01 R Clavicle", "Bip01 R UpperArm", "Bip01 R Forearm", "Bip01 R Hand", "Bip01 R Finger0", "Bip01 R Finger01", "Bip01 R Finger1", "Bip01 R Finger11", "Bone05", }; // 标准男性 LowerBody // Standard male lower body bones private static readonly string[] s_szOboroMaleStandardLowerBodyBonesName = { "Bip01", "Bip01 Pelvis", "Bip01 xiashen", "Bip01 L Thigh", "Bip01 L Calf", "Bip01 L Foot", "Bip01 L Toe0", "Bip01 R Thigh", "Bip01 R Calf", "Bip01 R Foot", "Bip01 R Toe0", "Bone01", "Bone02", "Bone03", "Bone04", }; // 职业变身男性 UpperBody // Profession reshape male upper body bones private static readonly string[] s_szOboroMaleShape1UpperBodyBonesName = { "Bip01 shangshen", "Bip01 Spine", "Bip01 Spine1", "Bip01 Spine2", "Bip01 Neck", "Bip01 Head", "Bip01 L Clavicle", "Bip01 L UpperArm", "Bip01 L Forearm", "Bip01 L Hand", "Bip01 L Finger0", "Bip01 L Finger01", "Bip01 L Finger1", "Bip01 L Finger11", "Bip01 R Clavicle", "Bip01 R UpperArm", "Bip01 R Forearm", "Bip01 R Hand", "Bip01 R Finger0", "Bip01 R Finger01", "Bip01 R Finger1", "Bip01 R Finger11", "Bone05", "Bone13", "Bone14", "Bone15", "Bone16", "Bone17", "Bone18", }; // 职业变身男性 LowerBody // Profession reshape male lower body bones private static readonly string[] s_szOboroMaleShape1LowerBodyBonesName = { "Bip01", "Bip01 Pelvis", "Bip01 xiashen", "Bip01 L Thigh", "Bip01 L Calf", "Bip01 L Foot", "Bip01 L Toe0", "Bip01 R Thigh", "Bip01 R Calf", "Bip01 R Foot", "Bip01 R Toe0", "Bone06", "Bone07", "Bone08", "Bone09", "Bone10", "Bone11", "Bone12", "Bone19", "Bone20", "Bone21", }; // 标准女性 UpperBody // Standard female upper body bones private static readonly string[] s_szOboroFemaleStandardUpperBodyBonesName = { "Bip01 Spine shangshen", "Bip01 Spine", "Bip01 Spine1", "Bip01 Spine2", "Bip01 Neck", "Bip01 Head", "Bip01 Ponytail1", "Bip01 Ponytail11", "Bip01 Ponytail12", "Bip01 L Clavicle", "Bip01 L UpperArm", "Bip01 L Forearm", "Bip01 L Hand", "Bip01 L Finger0", "Bip01 L Finger01", "Bip01 L Finger1", "Bip01 L Finger11", "Bip01 R Clavicle", "Bip01 R UpperArm", "Bip01 R Forearm", "Bip01 R Hand", "Bip01 R Finger0", "Bip01 R Finger01", "Bip01 R Finger1", "Bip01 R Finger11", "Bone05", "Bone01", }; // 标准女性 LowerBody // Standard female lower body bones private static readonly string[] s_szOboroFemaleStandardLowerBodyBonesName = { "Bip01", "Bip01 Pelvis", "Bip01 Spine xiashen", "Bip01 L Thigh", "Bip01 L Calf", "Bip01 L Foot", "Bip01 L Toe0", "Bip01 R Thigh", "Bip01 R Calf", "Bip01 R Foot", "Bip01 R Toe0", "Bone08", "Bone09", "Bone10", "Bone02", "Bone03", "Bone04", }; // 职业变身女性 UpperBody // Profession reshape female upper body bones private static readonly string[] s_szOboroFemaleShape1UpperBodyBonesName = { "Bip01 Spine shangshen", "Bip01 Spine", "Bip01 Spine1", "Bip01 Spine2", "Bip01 Neck", "Bip01 Head", "Bip01 Ponytail1", "Bip01 Ponytail11", "Bip01 Ponytail12", "Bip01 L Clavicle", "Bip01 L UpperArm", "Bip01 L Forearm", "Bip01 L Hand", "Bip01 L Finger0", "Bip01 L Finger01", "Bip01 L Finger1", "Bip01 L Finger11", "Bip01 R Clavicle", "Bip01 R UpperArm", "Bip01 R Forearm", "Bip01 R Hand", "Bip01 R Finger0", "Bip01 R Finger01", "Bip01 R Finger1", "Bip01 R Finger11", "Bone05", "Bone01", "Bone14", "Bone15", "Bone16", "Bone17", "Bone18", "Bone19", "Bone20", "Bone21", "Bone22", "Bone23", "Bone24", }; // 职业变身女性 LowerBody // Profession reshape female lower body bones private static readonly string[] s_szOboroFemaleShape1LowerBodyBonesName = { "Bip01", "Bip01 Pelvis", "Bip01 Spine xiashen", "Bip01 L Thigh", "Bip01 L Calf", "Bip01 L Foot", "Bip01 L Toe0", "Bip01 R Thigh", "Bip01 R Calf", "Bip01 R Foot", "Bip01 R Toe0", "Bone08", "Bone09", "Bone10", "Bone02", "Bone03", "Bone04", "Bone06", "Bone07", "Bone11", "Bone12", "Bone13", }; /// /// 玩家信息 // Player information /// public class PlayerInfo { public int profession; // 职业 // Profession public int gender; // 性别 // Gender public int shapeType; // 变身类型 // Shape type public int shapeID; // 变身ID // Shape ID public PlayerInfo(int profession, int gender, int shapeType, int shapeID) { this.profession = profession; this.gender = gender; this.shapeType = shapeType; this.shapeID = shapeID; } public PlayerInfo(CECPlayer pPlayer) { if (pPlayer != null) { this.profession = pPlayer.GetProfession(); this.gender = pPlayer.GetGender(); this.shapeType = pPlayer.GetShapeType(); this.shapeID = pPlayer.GetShapeID(); } } } // Singleton instance private static readonly object s_lock = new object(); // Private constructor for singleton public CECCastSkillWhenMove() { } /// /// 获取单例实例 // Get singleton instance /// /// /// 检查模型是否支持移动施法 // Check if model supports casting while moving /// private bool HasModelSupport(PlayerInfo player) { if (player.profession == RoleTypes.PROF_YUEXIAN) { switch (player.shapeType) { case PlayerModelType.PLAYERMODEL_MAJOR: // 标准模型 // Standard model return true; case PlayerModelType.PLAYERMODEL_PROFESSION: // 职业变身模型 // Profession reshape model if (player.gender == RoleTypes.GENDER_MALE) { return player.shapeID == ResourceModel.RES_MOD_YUEXIAN_RESHAPE_M; // 男职业变身 // Male profession reshape } else { return player.shapeID == ResourceModel.RES_MOD_YUEXIAN_RESHAPE_F; // 女职业变身 // Female profession reshape } } } // 支持移动施法的ecm模型 // ecm models that support casting while moving // 注意夜影 PROF_YEYING 模型也支持,但他们没有任何移动施法的技能,故此处不加,以避免不必要的开销 // Note: PROF_YEYING models also support this, but they don't have any moving cast skills, so not added here to avoid unnecessary overhead return false; } /// /// 检查技能是否支持移动施法 // Check if skill supports casting while moving /// private bool IsSkillSupported(int idSkill, PlayerInfo player) { // 支持移动施法的技能ID // Skill IDs that support casting while moving return ElementSkill.IsMovingSkill((uint)idSkill); } /// /// 检查技能动作是否支持移动施法 // Check if skill action supports casting while moving /// private bool HasActionSupport(int idSkill, PlayerInfo player) { if (HasModelSupport(player)) { const int SKILL_COUNT = 19; int[] s_skills = new int[SKILL_COUNT] { 2571, 2572, 2579, 2580, 2588, 2591, // 2571素罗闪 2572朱雀闪 2579辞诗箫 2580沐仙曲 2588霜雪铃 2591夕月飞星 2627, 2619, 2620, 2621, 2622, 2787, // 2627镜花水月 2619天·素罗闪 2620地·素罗闪 2621天·朱雀闪 2622地·朱雀闪 2787天·辞诗箫 2788, 2789, 2790, 2805, 2806, 2811, // 2788地·辞诗箫 2789天·沐仙曲 2790地·沐仙曲 2805天·霜雪铃 2806地·霜雪铃 2811天·夕月飞星 2812 // 2812地·夕月飞星 }; return s_skills.Contains(idSkill); } return false; } /// /// 获取上半身骨骼名称 // Get upper body bones name /// private bool GetUpperBodyBonesName(PlayerInfo player, out int bonesNameCount, out string[] szBonesName) { bonesNameCount = 0; szBonesName = null; bool result = false; if (HasModelSupport(player)) { switch (player.shapeType) { case PlayerModelType.PLAYERMODEL_MAJOR: if (RoleTypes.GENDER_MALE == player.gender) { szBonesName = s_szOboroMaleStandardUpperBodyBonesName; bonesNameCount = s_szOboroMaleStandardUpperBodyBonesName.Length; } else { szBonesName = s_szOboroFemaleStandardUpperBodyBonesName; bonesNameCount = s_szOboroFemaleStandardUpperBodyBonesName.Length; } break; case PlayerModelType.PLAYERMODEL_PROFESSION: if (RoleTypes.GENDER_MALE == player.gender) { if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_M == player.shapeID) { szBonesName = s_szOboroMaleShape1UpperBodyBonesName; bonesNameCount = s_szOboroMaleShape1UpperBodyBonesName.Length; } } else { if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_F == player.shapeID) { szBonesName = s_szOboroFemaleShape1UpperBodyBonesName; bonesNameCount = s_szOboroFemaleShape1UpperBodyBonesName.Length; } } break; default: // ASSERT(false); break; } result = true; } return result; } /// /// 获取下半身骨骼名称 // Get lower body bones name /// private bool GetLowerBodyBonesName(PlayerInfo player, out int bonesNameCount, out string[] szBonesName) { bonesNameCount = 0; szBonesName = null; bool result = false; if (HasModelSupport(player)) { switch (player.shapeType) { case PlayerModelType.PLAYERMODEL_MAJOR: if (RoleTypes.GENDER_MALE == player.gender) { szBonesName = s_szOboroMaleStandardLowerBodyBonesName; bonesNameCount = s_szOboroMaleStandardLowerBodyBonesName.Length; } else { szBonesName = s_szOboroFemaleStandardLowerBodyBonesName; bonesNameCount = s_szOboroFemaleStandardLowerBodyBonesName.Length; } break; case PlayerModelType.PLAYERMODEL_PROFESSION: if (RoleTypes.GENDER_MALE == player.gender) { if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_M == player.shapeID) { szBonesName = s_szOboroMaleShape1LowerBodyBonesName; bonesNameCount = s_szOboroMaleShape1LowerBodyBonesName.Length; } } else { if (ResourceModel.RES_MOD_YUEXIAN_RESHAPE_F == player.shapeID) { szBonesName = s_szOboroFemaleShape1LowerBodyBonesName; bonesNameCount = s_szOboroFemaleShape1LowerBodyBonesName.Length; } } break; default: // ASSERT(false); break; } result = true; } return result; } // Public methods that accept CECPlayer /// /// 检查玩家模型是否支持移动施法 // Check if player model supports casting while moving /// public bool HasModelSupport(CECPlayer pPlayer) { return pPlayer != null && HasModelSupport(new PlayerInfo(pPlayer)); } /// /// 检查技能是否支持移动施法 // Check if skill supports casting while moving /// public bool IsSkillSupported(int idSkill, CECPlayer pPlayer) { return pPlayer != null && IsSkillSupported(idSkill, new PlayerInfo(pPlayer)); } /// /// 检查技能动作是否支持移动施法 // Check if skill action supports casting while moving /// public bool HasActionSupport(int idSkill, CECPlayer pPlayer) { return pPlayer != null && HasActionSupport(idSkill, new PlayerInfo(pPlayer)); } /// /// 获取玩家上半身骨骼名称 // Get player upper body bones name /// public bool GetUpperBodyBonesName(CECPlayer pPlayer, out int bonesNameCount, out string[] szBonesName) { bonesNameCount = 0; szBonesName = null; return pPlayer != null && GetUpperBodyBonesName(new PlayerInfo(pPlayer), out bonesNameCount, out szBonesName); } /// /// 获取玩家下半身骨骼名称 // Get player lower body bones name /// public bool GetLowerBodyBonesName(CECPlayer pPlayer, out int bonesNameCount, out string[] szBonesName) { bonesNameCount = 0; szBonesName = null; return pPlayer != null && GetLowerBodyBonesName(new PlayerInfo(pPlayer), out bonesNameCount, out szBonesName); } } }