// 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);
}
}
}