convert skill combo'
This commit is contained in:
@@ -1071,11 +1071,12 @@ namespace BrewMonster
|
||||
{
|
||||
try
|
||||
{
|
||||
BMLogger.LogError("LoadUserConfigData: Start loading user config data");
|
||||
using (MemoryStream ms = new MemoryStream(pDataBuf, 0, iDataSize))
|
||||
using (BinaryReader reader = new BinaryReader(ms))
|
||||
{
|
||||
uint dwVer = reader.ReadUInt32();
|
||||
|
||||
|
||||
if (dwVer < 15)
|
||||
{
|
||||
DefaultUserConfigData();
|
||||
@@ -1115,9 +1116,9 @@ namespace BrewMonster
|
||||
// Note: Would need EC_Game reference
|
||||
// g_pGame->GetA3DGFXExMan()->SetPriority(m_vs.nEffect);
|
||||
// Send force attack to server
|
||||
/* byte forceAttack = glb_BuildPVPMask(false);
|
||||
byte refuseBless = glb_BuildRefuseBLSMask();
|
||||
UnityGameSession.Instance.c2s_CmdNotifyForceAttack(forceAttack, refuseBless);*/
|
||||
byte forceAttack = EC_Utility.glb_BuildPVPMask(false);
|
||||
byte refuseBless = EC_Utility.glb_BuildRefuseBLSMask();
|
||||
UnityGameSession.c2s_SendCmdNotifyForceAttack(forceAttack, refuseBless);
|
||||
}
|
||||
|
||||
public void SetSceneLoadRadius(float fRadius)
|
||||
|
||||
@@ -807,7 +807,7 @@ namespace BrewMonster.Scripts.Managers
|
||||
var pItem = new EC_IvtrItem(tid, expire_date);
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
object data = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
Debug.Log("Create item data: DataType: " + DataType);
|
||||
//Debug.Log("Create item data: DataType: " + DataType);
|
||||
switch(DataType)
|
||||
{
|
||||
case DATA_TYPE.DT_WEAPON_ESSENCE:
|
||||
|
||||
@@ -331,6 +331,16 @@ namespace CSNetwork.C2SCommand
|
||||
var cmdBuf = SerializeCommand(CommandID.CAST_POS_SKILL, cmd);
|
||||
return cmdBuf;
|
||||
}
|
||||
public static Octets CreateNotifyForceAttack(int iForceAttack, byte refuseBless)
|
||||
{
|
||||
var cmd = new cmd_notify_force_attack
|
||||
{
|
||||
force_attack = (byte)iForceAttack,
|
||||
refuse_bless = refuseBless
|
||||
};
|
||||
var cmdBuf = SerializeCommand(CommandID.NOTIFY_FORCE_ATTACK, cmd);
|
||||
return cmdBuf;
|
||||
}
|
||||
|
||||
public static short FloatToFix8(float x)
|
||||
{
|
||||
|
||||
@@ -2194,19 +2194,20 @@ namespace CSNetwork.GPDataType
|
||||
public int exp;
|
||||
};
|
||||
public _entry[] records;
|
||||
public bool CheckValid(int buf_size, out int sz)
|
||||
{ sz = 0;
|
||||
if (count < 0)
|
||||
return false;
|
||||
sz = Marshal.SizeOf<cmd_reincarnation_tome_info>() - Marshal.SizeOf<_entry[]>();
|
||||
sz += count * Marshal.SizeOf<_entry>();
|
||||
return buf_size >= sz;
|
||||
}
|
||||
};
|
||||
public bool CheckValid(int buf_size, out int sz)
|
||||
{
|
||||
sz = 0;
|
||||
if (count < 0)
|
||||
return false;
|
||||
sz = Marshal.SizeOf<cmd_reincarnation_tome_info>() - Marshal.SizeOf<_entry[]>();
|
||||
sz += count * Marshal.SizeOf<_entry>();
|
||||
return buf_size >= sz;
|
||||
}
|
||||
};
|
||||
|
||||
// Pet type
|
||||
public enum GP_PET_TYPE
|
||||
{
|
||||
{
|
||||
GP_PET_CLASS_INVALID = -1,
|
||||
GP_PET_CLASS_MOUNT = 0, // ���
|
||||
GP_PET_CLASS_COMBAT, // ս������
|
||||
@@ -2216,13 +2217,13 @@ namespace CSNetwork.GPDataType
|
||||
GP_PET_CLASS_EVOLUTION, // ������
|
||||
GP_PET_CLASS_MAX,
|
||||
};
|
||||
|
||||
|
||||
public struct PetSkill
|
||||
{
|
||||
public int skill;
|
||||
public int level;
|
||||
|
||||
}
|
||||
}
|
||||
public struct _evo_prop
|
||||
{
|
||||
public int r_attack;
|
||||
@@ -2234,29 +2235,29 @@ namespace CSNetwork.GPDataType
|
||||
}
|
||||
public enum GP_PET_SKILL_NUM
|
||||
{
|
||||
GP_PET_SKILL_NUM = 8
|
||||
GP_PET_SKILL_NUM = 8
|
||||
};
|
||||
public struct info_pet
|
||||
{
|
||||
public int honor_point; // �øж�
|
||||
public int hunger; // ������
|
||||
public int feed_time; // �ϴ�ι�������ڵ�ʱ��
|
||||
public int pet_tid; // ������ID
|
||||
public int pet_vis_tid; // ����Ŀɼ�ID�����Ϊ0�����ʾ������ɼ�ID��
|
||||
public int pet_egg_tid; // ���ﵰ��ID
|
||||
public int pet_class; // �������� ս�裬��裬���ͳ�
|
||||
public float hp_factor; // Ѫ��������������ջ�ʱʹ�ã� 0��Ϊ����
|
||||
public short level; // ���V��
|
||||
public ushort color; // ������ɫ�����λΪ1��ʾ��Ч��Ŀǰ���������Ч
|
||||
public int exp; // ���ﵱǰ����
|
||||
public int skill_point; // ʣ�༼�ܵ�
|
||||
public char is_bind; // �Ƿ����˺�һ��������һ��Mask��0x01 ���˺�һ��0x02 Ѱ�����ɽ���
|
||||
public char unused; // Ŀǰ������Ч
|
||||
public ushort name_len; // ���ֳ��� Ŀǰ������Ч����Ϊ��������������
|
||||
public char[] name; // ��������
|
||||
public PetSkill[] skills;
|
||||
{
|
||||
public int honor_point; // �øж�
|
||||
public int hunger; // ������
|
||||
public int feed_time; // �ϴ�ι�������ڵ�ʱ��
|
||||
public int pet_tid; // ������ID
|
||||
public int pet_vis_tid; // ����Ŀɼ�ID�����Ϊ0�����ʾ������ɼ�ID��
|
||||
public int pet_egg_tid; // ���ﵰ��ID
|
||||
public int pet_class; // �������� ս�裬��裬���ͳ�
|
||||
public float hp_factor; // Ѫ��������������ջ�ʱʹ�ã� 0��Ϊ����
|
||||
public short level; // ���V��
|
||||
public ushort color; // ������ɫ�����λΪ1��ʾ��Ч��Ŀǰ���������Ч
|
||||
public int exp; // ���ﵱǰ����
|
||||
public int skill_point; // ʣ�༼�ܵ�
|
||||
public char is_bind; // �Ƿ����˺�һ��������һ��Mask��0x01 ���˺�һ��0x02 Ѱ�����ɽ���
|
||||
public char unused; // Ŀǰ������Ч
|
||||
public ushort name_len; // ���ֳ��� Ŀǰ������Ч����Ϊ��������������
|
||||
public char[] name; // ��������
|
||||
public PetSkill[] skills;
|
||||
public _evo_prop evo_prop;
|
||||
public int[] reserved; // �
|
||||
public int[] reserved; // �
|
||||
public info_pet(bool isDefault = true)
|
||||
{
|
||||
honor_point = 0;
|
||||
@@ -2276,7 +2277,8 @@ namespace CSNetwork.GPDataType
|
||||
name_len = 0;
|
||||
name = new char[16];
|
||||
skills = new PetSkill[(int)GP_PET_SKILL_NUM.GP_PET_SKILL_NUM];
|
||||
evo_prop = new _evo_prop{
|
||||
evo_prop = new _evo_prop
|
||||
{
|
||||
r_attack = 0,
|
||||
r_defense = 0,
|
||||
r_hp = 0,
|
||||
@@ -2286,6 +2288,17 @@ namespace CSNetwork.GPDataType
|
||||
};
|
||||
reserved = new int[10];
|
||||
}
|
||||
};
|
||||
};
|
||||
public enum REFUSE_BLESS_MASK : byte
|
||||
{
|
||||
REFUSE_NEUTRAL_BLESS = 0x0001, // ²»½ÓÊÜÖÐÐÔ×£¸£
|
||||
REFUSE_NON_TEAMMATE_BLESS = 0x0002, // ²»½ÓÊܷǶÓÓÑ×£¸£
|
||||
};
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct cmd_notify_force_attack
|
||||
{
|
||||
public byte force_attack;
|
||||
public byte refuse_bless;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -364,11 +364,11 @@ namespace CSNetwork
|
||||
case ProtocolType.PROTOCOL_GETUICONFIG_RE: OnPrtcGetConfigRe(protocol); break;
|
||||
|
||||
case ProtocolType.PROTOCOL_AUTOTEAMSETGOAL_RE:
|
||||
{
|
||||
// CECAutoTeam pAutoTeam = CECGameRun.Instance.GetHostPlayer().GetAutoTeam();
|
||||
// if( pAutoTeam !=null)
|
||||
// pAutoTeam.OnPrtcAutoTeamSetGoalRe((AutoTeamSetGoal_Re)protocol);
|
||||
}
|
||||
{
|
||||
// CECAutoTeam pAutoTeam = CECGameRun.Instance.GetHostPlayer().GetAutoTeam();
|
||||
// if( pAutoTeam !=null)
|
||||
// pAutoTeam.OnPrtcAutoTeamSetGoalRe((AutoTeamSetGoal_Re)protocol);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -593,64 +593,64 @@ namespace CSNetwork
|
||||
#if UNITY_EDITOR
|
||||
BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE: {errRaw}");
|
||||
#endif
|
||||
cmd_error_msg pCmd = GPDataTypeHelper.FromBytes<cmd_error_msg>(pDataBuf);
|
||||
cmd_error_msg pCmd = GPDataTypeHelper.FromBytes<cmd_error_msg>(pDataBuf);
|
||||
#if UNITY_EDITOR
|
||||
BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE parsed iMessage={pCmd.iMessage}");
|
||||
#endif
|
||||
|
||||
if (pCmd.iMessage != 0)
|
||||
{
|
||||
// string szMsg = m_ErrorMsgs.GetWideString(pCmd.iMessage);
|
||||
// if (string.IsNullOrEmpty(szMsg))
|
||||
// BMLogger.LogError("SERVER - unknown error !");
|
||||
//else if (pCmd.iMessage != 2)
|
||||
//g_pGame.GetGameRun().AddChatMessage(szMsg, GP_CHAT_MISC);
|
||||
}
|
||||
if (pCmd.iMessage != 0)
|
||||
{
|
||||
// string szMsg = m_ErrorMsgs.GetWideString(pCmd.iMessage);
|
||||
// if (string.IsNullOrEmpty(szMsg))
|
||||
// BMLogger.LogError("SERVER - unknown error !");
|
||||
//else if (pCmd.iMessage != 2)
|
||||
//g_pGame.GetGameRun().AddChatMessage(szMsg, GP_CHAT_MISC);
|
||||
}
|
||||
|
||||
if (pCmd.iMessage == 2)
|
||||
{
|
||||
// Attack target is too far
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TARGETISFAR, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
}
|
||||
else if (pCmd.iMessage == 20)
|
||||
{
|
||||
// Failed to cast skill
|
||||
//pGameRun.PostMessage(MSG_PM_CASTSKILL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd);
|
||||
}
|
||||
else if (pCmd.iMessage == 133 || pCmd.iMessage == 134)
|
||||
{
|
||||
// deal failed
|
||||
//pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd);
|
||||
}
|
||||
else if (pCmd.iMessage == 158)
|
||||
{
|
||||
// µ±Ç°»ãÂʲ»¶Ô£¬ÖØÐÂÈ¡»ãÂÊ
|
||||
//c2s_CmdGetCashMoneyRate();
|
||||
}
|
||||
else if (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().IsInKingService()*/)
|
||||
{
|
||||
/* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan();
|
||||
if (pGameUI)
|
||||
pGameUI.EndNPCService();*/
|
||||
}
|
||||
else if
|
||||
(pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().GetOfflineShopCtrl().GetNPCSevFlag() != COfflineShopCtrl::NPCSEV_NULL*/
|
||||
)
|
||||
{
|
||||
/* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan();
|
||||
if (pGameUI)
|
||||
pGameUI.EndNPCService();*/
|
||||
}
|
||||
else if (pCmd.iMessage == 175)
|
||||
{
|
||||
//c2s_CmdQueryParallelWorld();
|
||||
}
|
||||
else if (pCmd.iMessage == 6)
|
||||
{
|
||||
//AP_ActionEvent(AP_EVENT_CANNOTPICKUP);
|
||||
}
|
||||
if (pCmd.iMessage == 2)
|
||||
{
|
||||
// Attack target is too far
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TARGETISFAR, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
|
||||
}
|
||||
else if (pCmd.iMessage == 20)
|
||||
{
|
||||
// Failed to cast skill
|
||||
//pGameRun.PostMessage(MSG_PM_CASTSKILL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd);
|
||||
}
|
||||
else if (pCmd.iMessage == 133 || pCmd.iMessage == 134)
|
||||
{
|
||||
// deal failed
|
||||
//pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd);
|
||||
}
|
||||
else if (pCmd.iMessage == 158)
|
||||
{
|
||||
// µ±Ç°»ãÂʲ»¶Ô£¬ÖØÐÂÈ¡»ãÂÊ
|
||||
//c2s_CmdGetCashMoneyRate();
|
||||
}
|
||||
else if (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().IsInKingService()*/)
|
||||
{
|
||||
/* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan();
|
||||
if (pGameUI)
|
||||
pGameUI.EndNPCService();*/
|
||||
}
|
||||
else if
|
||||
(pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().GetOfflineShopCtrl().GetNPCSevFlag() != COfflineShopCtrl::NPCSEV_NULL*/
|
||||
)
|
||||
{
|
||||
/* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan();
|
||||
if (pGameUI)
|
||||
pGameUI.EndNPCService();*/
|
||||
}
|
||||
else if (pCmd.iMessage == 175)
|
||||
{
|
||||
//c2s_CmdQueryParallelWorld();
|
||||
}
|
||||
else if (pCmd.iMessage == 6)
|
||||
{
|
||||
//AP_ActionEvent(AP_EVENT_CANNOTPICKUP);
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case CommandID.SELECT_TARGET:
|
||||
case CommandID.UNSELECT:
|
||||
@@ -719,7 +719,7 @@ namespace CSNetwork
|
||||
case CommandID.OBJECT_CAST_INSTANT_SKILL:
|
||||
case CommandID.OBJECT_CAST_POS_SKILL:
|
||||
{
|
||||
cmd_object_cast_skill pCmd2 = GPDataTypeHelper.FromBytes<cmd_object_cast_skill>(pDataBuf,true);
|
||||
cmd_object_cast_skill pCmd2 = GPDataTypeHelper.FromBytes<cmd_object_cast_skill>(pDataBuf, true);
|
||||
if (ISPLAYERID(pCmd2.caster))
|
||||
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
|
||||
else if (ISNPCID(pCmd2.caster))
|
||||
@@ -1121,6 +1121,12 @@ namespace CSNetwork
|
||||
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void c2s_SendCmdNotifyForceAttack(int iForceAttack, byte refuseBless)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateNotifyForceAttack(iForceAttack, refuseBless);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
public void c2s_SendCmdContinueAction()
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
@@ -1210,24 +1216,24 @@ namespace CSNetwork
|
||||
|
||||
// Get referral name for adding friend or other display
|
||||
//TODO: a Hung lam phan select role info di
|
||||
/* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo();
|
||||
if (info.referrer_role > 0)
|
||||
GetPlayerBriefInfo(1, info.referrer_role, 2);*/
|
||||
/* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo();
|
||||
if (info.referrer_role > 0)
|
||||
GetPlayerBriefInfo(1, info.referrer_role, 2);*/
|
||||
}
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
pHost.OnAllInitDataReady();
|
||||
|
||||
/* if (pHost.IsGM())
|
||||
{
|
||||
CDlgCountryMap pDlgCountryMap = (CDlgCountryMap)pGameUI.GetDialog("Win_CountryMap");
|
||||
pDlgCountryMap.GetConfig();
|
||||
}
|
||||
/* if (pHost.IsGM())
|
||||
{
|
||||
CDlgCountryMap pDlgCountryMap = (CDlgCountryMap)pGameUI.GetDialog("Win_CountryMap");
|
||||
pDlgCountryMap.GetConfig();
|
||||
}
|
||||
|
||||
g_pGame.GetConfigs().ApplyOptimizeSetting();
|
||||
g_pGame.GetConfigs().ApplyOptimizeSetting();
|
||||
|
||||
if (g_pGame.GetConfigs().IsMiniClient())
|
||||
CECMCDownload::GetInstance().SendGetDownloadOK();*/
|
||||
if (g_pGame.GetConfigs().IsMiniClient())
|
||||
CECMCDownload::GetInstance().SendGetDownloadOK();*/
|
||||
}
|
||||
}
|
||||
private void OnPrtcPlayerBaseInfoRe(Protocol pProtocol)
|
||||
@@ -1434,7 +1440,7 @@ namespace CSNetwork
|
||||
public void c2s_SendCmdTaskNotify(byte[] pData, uint dwDataSize)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateTaskNotifyCmd( pData, dwDataSize);
|
||||
gamedatasend.Data = C2SCommandFactory.CreateTaskNotifyCmd(pData, dwDataSize);
|
||||
BMLogger.Log($"[MH Task] c2s_SendCmdTaskNotify Command ID : {pData[0]} Size: {dwDataSize}");
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
@@ -1445,24 +1451,24 @@ namespace CSNetwork
|
||||
gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.STAND_UP);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
|
||||
|
||||
public void c2s_SendCmdAutoTeamSetGoal(int type, int goal_id, int op)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateAutoTeamSetGoalCommand(type,goal_id, op);
|
||||
gamedatasend.Data = C2SCommandFactory.CreateAutoTeamSetGoalCommand(type, goal_id, op);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
|
||||
public void c2s_CmdGoto(float x, float y, float z)
|
||||
{
|
||||
c2s_SendCmdGoto(x, y, z);
|
||||
c2s_SendCmdGoto(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
// Send C2S::GOTO command data
|
||||
void c2s_SendCmdGoto(float x, float y, float z)
|
||||
{
|
||||
gamedatasend gamedatasend = new gamedatasend();
|
||||
gamedatasend.Data = C2SCommandFactory.CreateGoToCommed( x, y, z);
|
||||
gamedatasend.Data = C2SCommandFactory.CreateGoToCommed(x, y, z);
|
||||
SendProtocol(gamedatasend);
|
||||
}
|
||||
|
||||
|
||||
@@ -316,6 +316,10 @@ namespace BrewMonster.Network
|
||||
public static void c2s_CmdNPCSevHeal()
|
||||
{
|
||||
|
||||
}
|
||||
public static void c2s_SendCmdNotifyForceAttack(int iForceAttack, byte refuseBless)
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdNotifyForceAttack(iForceAttack, refuseBless);
|
||||
}
|
||||
public static void c2s_CmdNPCSevAcceptTask(int idTask,int idStorage,int idRefreshItem)
|
||||
{
|
||||
|
||||
@@ -636,100 +636,100 @@ namespace BrewMonster
|
||||
break;
|
||||
}
|
||||
|
||||
/* case CECShortcut.ShortcutType.SCT_ITEM:
|
||||
{
|
||||
int iPack = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int iIvtrSlot = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int idItem = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
/* case CECShortcut.ShortcutType.SCT_ITEM:
|
||||
{
|
||||
int iPack = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int iIvtrSlot = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
int idItem = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
CECInventory pPack = pHost.GetPack(iPack);
|
||||
if (pPack == null)
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid inventory");
|
||||
return false;
|
||||
}
|
||||
CECInventory pPack = pHost.GetPack(iPack);
|
||||
if (pPack == null)
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid inventory");
|
||||
return false;
|
||||
}
|
||||
|
||||
CECIvtrItem pItem = pPack.GetItem(iIvtrSlot);
|
||||
if (pItem != null)
|
||||
CreateItemShortcut(iSlot, iPack, iIvtrSlot, pItem);
|
||||
CECIvtrItem pItem = pPack.GetItem(iIvtrSlot);
|
||||
if (pItem != null)
|
||||
CreateItemShortcut(iSlot, iPack, iIvtrSlot, pItem);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_SKILLGRP:
|
||||
{
|
||||
if (dwVer >= 3)
|
||||
{
|
||||
int iGroupIdx = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
case CECShortcut.ShortcutType.SCT_SKILLGRP:
|
||||
{
|
||||
if (dwVer >= 3)
|
||||
{
|
||||
int iGroupIdx = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iGroupIdx >= 0)
|
||||
CreateSkillGroupShortcut(iSlot, iGroupIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for skill group");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (iGroupIdx >= 0)
|
||||
CreateSkillGroupShortcut(iSlot, iGroupIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for skill group");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_PET:
|
||||
{
|
||||
if (dwVer >= 4)
|
||||
{
|
||||
int iPetIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
/*case CECShortcut.ShortcutType.SCT_PET:
|
||||
{
|
||||
if (dwVer >= 4)
|
||||
{
|
||||
int iPetIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iPetIndex >= 0)
|
||||
CreatePetShortcut(iSlot, iPetIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for pet");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (iPetIndex >= 0)
|
||||
CreatePetShortcut(iSlot, iPetIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for pet");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_AUTOFASHION:
|
||||
{
|
||||
if (dwVer >= 5)
|
||||
{
|
||||
int iAutoFashionIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
case CECShortcut.ShortcutType.SCT_AUTOFASHION:
|
||||
{
|
||||
if (dwVer >= 5)
|
||||
{
|
||||
int iAutoFashionIndex = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iAutoFashionIndex >= 0)
|
||||
CreateAutoFashionShortcut(iSlot, iAutoFashionIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for auto fashion");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (iAutoFashionIndex >= 0)
|
||||
CreateAutoFashionShortcut(iSlot, iAutoFashionIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for auto fashion");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CECShortcut.ShortcutType.SCT_SYSMODULE:
|
||||
{
|
||||
if (dwVer > 10)
|
||||
{
|
||||
int iSys = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
case CECShortcut.ShortcutType.SCT_SYSMODULE:
|
||||
{
|
||||
if (dwVer > 10)
|
||||
{
|
||||
int iSys = BitConverter.ToInt32(pDataBuf, offset);
|
||||
offset += sizeof(int);
|
||||
|
||||
if (iSys >= 0)
|
||||
CreateSystemModuleShortcut(iSlot, iSys);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for system module");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
if (iSys >= 0)
|
||||
CreateSystemModuleShortcut(iSlot, iSys);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("CECShortcutSet::LoadConfigData - Invalid version for system module");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}*/
|
||||
|
||||
/* default:
|
||||
//TODO: uncomment
|
||||
|
||||
@@ -0,0 +1,631 @@
|
||||
# Flow: Player Clicks Shortcut to Use Combo Skill
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the complete flow from when a player clicks on a combo skill shortcut in the UI until the combo skill sequence is executed.
|
||||
|
||||
---
|
||||
|
||||
## Complete Flow Diagram
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 1. PLAYER CLICKS COMBO SKILL SHORTCUT │
|
||||
│ (Mouse click on shortcut bar OR keyboard hotkey) │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 2. UI EVENT HANDLER │
|
||||
│ File: EC_GameUIEvent.cpp (line 173) │
|
||||
│ OR EC_GameUIMan.cpp (line 1320, 1344) │
|
||||
│ │
|
||||
│ CECShortcut* pSC = GetShortcutFromUI(); │
|
||||
│ pSC->Execute(); // ← Calls Execute() on shortcut │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 3. CECSCSkillGrp::Execute() │
|
||||
│ File: EC_Shortcut.cpp (line 712-716) │
|
||||
│ │
|
||||
│ bool CECSCSkillGrp::Execute() │
|
||||
│ { │
|
||||
│ CECHostPlayer* pHost = GetHostPlayer(); │
|
||||
│ pHost->ApplyComboSkill(m_iGroupIdx); // ← Group ID │
|
||||
│ return true; │
|
||||
│ } │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 4. CECHostPlayer::ApplyComboSkill() │
|
||||
│ File: EC_HostPlayer.cpp (line 7696-7721) │
|
||||
│ │
|
||||
│ bool ApplyComboSkill(int iGroup, ...) │
|
||||
│ { │
|
||||
│ ClearComboSkill(); // Clear any existing combo │
|
||||
│ │
|
||||
│ m_pComboSkill = new CECComboSkill; │
|
||||
│ │
|
||||
│ // Initialize combo skill with group index │
|
||||
│ m_pComboSkill->Init(this, iGroup, │
|
||||
│ m_idSelTarget, │
|
||||
│ bForceAttack, │
|
||||
│ bIgnoreAtkLoop); │
|
||||
│ │
|
||||
│ // Start first skill in combo │
|
||||
│ m_pComboSkill->Continue(m_bMelee); │
|
||||
│ │
|
||||
│ return true; │
|
||||
│ } │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 5. CECComboSkill::Init() │
|
||||
│ File: EC_ComboSkill.cpp (line 74-123) │
|
||||
│ │
|
||||
│ bool Init(CECHostPlayer* pHost, int iGroup, ...) │
|
||||
│ { │
|
||||
│ // Load combo skill data from configs │
|
||||
│ CECConfigs* pCfg = GetConfigs(); │
|
||||
│ m_cs = pCfg->GetVideoSettings() │
|
||||
│ .comboSkill[iGroup]; // ← Load combo │
|
||||
│ │
|
||||
│ // Find loop start flag (if any) │
|
||||
│ // Move cursor to first valid skill │
|
||||
│ StepCursor(true); │
|
||||
│ │
|
||||
│ return true; │
|
||||
│ } │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 6. CECComboSkill::Continue() - FIRST SKILL │
|
||||
│ File: EC_ComboSkill.cpp (line 128-217) │
|
||||
│ │
|
||||
│ bool Continue(bool bMeleeing) │
|
||||
│ { │
|
||||
│ int idSkill = GetNextSkill(); // Get skill ID │
|
||||
│ │
|
||||
│ if (idSkill > 0) // Regular skill │
|
||||
│ { │
|
||||
│ // Execute skill │
|
||||
│ bool bRet = m_pHost->ApplySkillShortcut( │
|
||||
│ idSkill, true, m_idTarget, ...); │
|
||||
│ │
|
||||
│ if (bRet) │
|
||||
│ { │
|
||||
│ StepCursor(false); // Move to next skill │
|
||||
│ return true; // Continue combo │
|
||||
│ } │
|
||||
│ } │
|
||||
│ else if (idSkill == SID_ATTACK) // Normal attack │
|
||||
│ { │
|
||||
│ m_pHost->CmdNormalAttack(...); │
|
||||
│ StepCursor(false); │
|
||||
│ return true; │
|
||||
│ } │
|
||||
│ │
|
||||
│ return false; // Combo stopped │
|
||||
│ } │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 7. SKILL EXECUTION │
|
||||
│ File: EC_HostPlayer.cpp │
|
||||
│ │
|
||||
│ ApplySkillShortcut() executes the skill: │
|
||||
│ - Checks if skill is ready │
|
||||
│ - Sends command to server │
|
||||
│ - Starts skill animation │
|
||||
│ - Updates cooldown timers │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 8. CONTINUE COMBO (After Skill Finishes) │
|
||||
│ File: EC_HostPlayer.cpp (line 4129-4135, 6244-6252) │
|
||||
│ │
|
||||
│ When skill finishes or melee state changes: │
|
||||
│ │
|
||||
│ if (m_pComboSkill && !m_pComboSkill->IsStop()) │
|
||||
│ { │
|
||||
│ // Post message to continue combo │
|
||||
│ PostMessage(MSG_HST_CONTINUECOMBOSKILL, │
|
||||
│ MAN_PLAYER, 0, │
|
||||
│ bMeleeing ? 1 : 0, │
|
||||
│ m_pComboSkill->GetGroupIndex()); │
|
||||
│ } │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 9. OnMsgContinueComboSkill() │
|
||||
│ File: EC_HostPlayer.cpp (line 6261-6268) │
|
||||
│ │
|
||||
│ void OnMsgContinueComboSkill(const ECMSG &Msg) │
|
||||
│ { │
|
||||
│ bool bMeleeing = (Msg.dwParam1 == 1); │
|
||||
│ int iGroupID = (int)Msg.dwParam2; │
|
||||
│ │
|
||||
│ if (m_pComboSkill && │
|
||||
│ m_pComboSkill->GetGroupIndex() == iGroupID && │
|
||||
│ !m_pComboSkill->IsStop()) │
|
||||
│ { │
|
||||
│ m_pComboSkill->Continue(bMeleeing); // ← Loop │
|
||||
│ } │
|
||||
│ } │
|
||||
└─────────────────┬───────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 10. REPEAT STEPS 6-9 │
|
||||
│ Until combo skill sequence completes or stops │
|
||||
│ │
|
||||
│ - Continue() executes next skill in sequence │
|
||||
│ - StepCursor() moves to next position │
|
||||
│ - If loop flag found, cursor jumps back │
|
||||
│ - If end reached, combo stops │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Detailed Step-by-Step Flow
|
||||
|
||||
### **STEP 1: Player Clicks Shortcut**
|
||||
**Trigger**:
|
||||
- Mouse click on shortcut bar UI element
|
||||
- OR Keyboard hotkey (1-9, Q, E, R, etc.)
|
||||
|
||||
**UI Elements**:
|
||||
- `DlgQuickBar` - Main shortcut bar dialog
|
||||
- `Item_01`, `Item_02`, ... - Shortcut slot UI controls
|
||||
|
||||
---
|
||||
|
||||
### **STEP 2: UI Event Handler**
|
||||
**File**: `EC_GameUIEvent.cpp` (line 163-174)
|
||||
|
||||
```cpp
|
||||
// Mouse click handler
|
||||
if (abs(x - m_ptLButtonDown.x) < 3 && abs(y - m_ptLButtonDown.y) < 3)
|
||||
{
|
||||
if (strstr(pDlgSrc->GetName(), "Win_Quickbar") ||
|
||||
0 == stricmp(pDlgSrc->GetName(), "Win_Action"))
|
||||
{
|
||||
CECShortcut* pSC = (CECShortcut*)pDlg->GetDataPtr();
|
||||
if (pSC)
|
||||
pSC->Execute(); // ← Execute shortcut
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**OR Keyboard Handler**:
|
||||
**File**: `EC_GameUIMan.cpp` (line 1316-1321)
|
||||
|
||||
```cpp
|
||||
// Keyboard shortcut handler
|
||||
int nCurPanel1 = CDlgQuickBar::GetCurPanel1();
|
||||
CECShortcutSet* pSCS = pHost->GetShortcutSet1(nCurPanel1 - 1);
|
||||
CECShortcut* pSC = pSCS->GetShortcut(iUsage - LKEY_UI_QUICK9_SC1);
|
||||
if (pSC)
|
||||
pSC->Execute(); // ← Execute shortcut
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **STEP 3: CECSCSkillGrp::Execute()**
|
||||
**File**: `EC_Shortcut.cpp` (line 712-716)
|
||||
|
||||
```cpp
|
||||
bool CECSCSkillGrp::Execute()
|
||||
{
|
||||
CECHostPlayer* pHost = g_pGame->GetGameRun()->GetHostPlayer();
|
||||
pHost->ApplyComboSkill(m_iGroupIdx); // ← Group index (0-EC_COMBOSKILL_NUM-1)
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- `m_iGroupIdx` is the combo skill group index (0, 1, 2, ...)
|
||||
- This was set when the shortcut was created from config data
|
||||
|
||||
---
|
||||
|
||||
### **STEP 4: CECHostPlayer::ApplyComboSkill()**
|
||||
**File**: `EC_HostPlayer.cpp` (line 7696-7721)
|
||||
|
||||
```cpp
|
||||
bool CECHostPlayer::ApplyComboSkill(int iGroup, bool bIgnoreAtkLoop, int iForceAtk)
|
||||
{
|
||||
// Clear any existing combo skill
|
||||
ClearComboSkill();
|
||||
|
||||
// Create new combo skill object
|
||||
if (!(m_pComboSkill = new CECComboSkill))
|
||||
return false;
|
||||
|
||||
// Determine force attack flag
|
||||
bool bForceAttack;
|
||||
if (iForceAtk < 0)
|
||||
bForceAttack = glb_GetForceAttackFlag(NULL);
|
||||
else
|
||||
bForceAttack = iForceAtk > 0 ? true : false;
|
||||
|
||||
// Initialize combo skill
|
||||
if (!(m_pComboSkill->Init(this, iGroup, m_idSelTarget, bForceAttack, bIgnoreAtkLoop)))
|
||||
{
|
||||
delete m_pComboSkill;
|
||||
m_pComboSkill = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start the combo skill sequence
|
||||
m_pComboSkill->Continue(m_bMelee);
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Clears any existing combo skill first
|
||||
- Creates new `CECComboSkill` object
|
||||
- Initializes with group index, target, force attack flag
|
||||
- Immediately calls `Continue()` to start first skill
|
||||
|
||||
---
|
||||
|
||||
### **STEP 5: CECComboSkill::Init()**
|
||||
**File**: `EC_ComboSkill.cpp` (line 74-123)
|
||||
|
||||
```cpp
|
||||
bool CECComboSkill::Init(CECHostPlayer* pHost, int iGroup, int idTarget,
|
||||
bool bForceAttack, bool bIgnoreAtkLoop)
|
||||
{
|
||||
if (iGroup < 0 || iGroup >= EC_COMBOSKILL_NUM)
|
||||
return false;
|
||||
|
||||
m_pHost = pHost;
|
||||
m_iGroup = iGroup;
|
||||
m_iCursor = 0;
|
||||
m_bStop = false;
|
||||
m_idTarget = idTarget;
|
||||
m_bForceAtk = bForceAttack;
|
||||
m_bIgnoreAtkLoop = bIgnoreAtkLoop;
|
||||
|
||||
// ★ KEY: Load combo skill data from configs
|
||||
CECConfigs* pCfg = g_pGame->GetConfigs();
|
||||
m_cs = pCfg->GetVideoSettings().comboSkill[iGroup];
|
||||
// m_cs contains:
|
||||
// - m_cs.nIcon: Icon index
|
||||
// - m_cs.idSkill[]: Array of skill IDs in sequence
|
||||
|
||||
// Find the last loop start flag (SID_LOOPSTART = -2)
|
||||
m_iLoopStart = -1;
|
||||
for (int i = 0; i < EC_COMBOSKILL_LEN; i++)
|
||||
{
|
||||
if (m_cs.idSkill[i] == SID_LOOPSTART)
|
||||
m_iLoopStart = i;
|
||||
}
|
||||
|
||||
// Validate loop start flag
|
||||
if (m_iLoopStart >= 0)
|
||||
{
|
||||
// Check if there's a valid skill after loop start
|
||||
// ... validation code ...
|
||||
}
|
||||
|
||||
// Move cursor to first valid skill position
|
||||
StepCursor(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Loads combo skill data from `EC_Configs::m_vs.comboSkill[iGroup]`
|
||||
- Finds loop start flag if present
|
||||
- Moves cursor to first valid skill
|
||||
|
||||
---
|
||||
|
||||
### **STEP 6: CECComboSkill::Continue() - Execute Skills**
|
||||
**File**: `EC_ComboSkill.cpp` (line 128-217)
|
||||
|
||||
```cpp
|
||||
bool CECComboSkill::Continue(bool bMeleeing)
|
||||
{
|
||||
// Check if combo should stop
|
||||
if (m_bStop || !m_cs.nIcon || !m_pHost ||
|
||||
m_iCursor < 0 || m_iCursor >= EC_COMBOSKILL_LEN ||
|
||||
(m_idTarget != m_pHost->GetSelectedTarget() && !m_bIgnoreAtkLoop))
|
||||
return false;
|
||||
|
||||
int idSkill = GetNextSkill(); // Get skill ID at current cursor position
|
||||
|
||||
if (idSkill > 0) // Regular skill
|
||||
{
|
||||
// Execute the skill
|
||||
bool bRet = m_pHost->ApplySkillShortcut(idSkill, true, m_idTarget,
|
||||
m_bForceAtk ? 1 : 0);
|
||||
|
||||
if (!bRet)
|
||||
{
|
||||
// Skill failed, try next skill
|
||||
StepCursor(false);
|
||||
if (!IsStop())
|
||||
{
|
||||
// Post message to continue combo
|
||||
g_pGame->GetGameRun()->PostMessage(MSG_HST_CONTINUECOMBOSKILL,
|
||||
MAN_PLAYER, 0,
|
||||
bMeleeing ? 1 : 0,
|
||||
m_iGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Combo finished
|
||||
AP_ActionEvent(AP_EVENT_COMBOFINISH);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skill executed successfully
|
||||
AP_ActionEvent(AP_EVENT_COMBOCONTINUE);
|
||||
}
|
||||
}
|
||||
else if (idSkill == SID_ATTACK) // Normal attack (-1)
|
||||
{
|
||||
if (!bMeleeing && !m_bIgnoreAtkLoop)
|
||||
{
|
||||
bool bRet = m_pHost->CmdNormalAttack(false, true, m_idTarget,
|
||||
m_bForceAtk ? 1 : 0);
|
||||
if (!bRet)
|
||||
{
|
||||
StepCursor(false);
|
||||
if (!IsStop())
|
||||
{
|
||||
g_pGame->GetGameRun()->PostMessage(MSG_HST_CONTINUECOMBOSKILL,
|
||||
MAN_PLAYER, 0,
|
||||
bMeleeing ? 1 : 0,
|
||||
m_iGroup);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move cursor to next skill
|
||||
StepCursor(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Gets next skill ID from `m_cs.idSkill[m_iCursor]`
|
||||
- Executes skill via `ApplySkillShortcut()`
|
||||
- Moves cursor forward with `StepCursor(false)`
|
||||
- If skill fails, posts message to try next skill
|
||||
|
||||
---
|
||||
|
||||
### **STEP 7: StepCursor() - Move Through Sequence**
|
||||
**File**: `EC_ComboSkill.cpp` (line 220-247)
|
||||
|
||||
```cpp
|
||||
void CECComboSkill::StepCursor(bool bFirst)
|
||||
{
|
||||
if (bFirst)
|
||||
m_iCursor = -1; // Start before first position
|
||||
|
||||
while (1)
|
||||
{
|
||||
m_iCursor++;
|
||||
|
||||
if (m_iCursor >= EC_COMBOSKILL_LEN) // Reached end
|
||||
{
|
||||
// If loop flag exists, jump back to loop start
|
||||
if (m_iLoopStart >= 0 && !m_bIgnoreAtkLoop)
|
||||
m_iCursor = m_iLoopStart;
|
||||
else
|
||||
{
|
||||
m_bStop = true; // Combo finished
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int id = m_cs.idSkill[m_iCursor];
|
||||
// Find next valid skill (id > 0) or attack (id == SID_ATTACK)
|
||||
if (id > 0 || (id == SID_ATTACK && !m_bIgnoreAtkLoop))
|
||||
break; // Found valid skill
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Moves cursor forward through skill array
|
||||
- Skips empty slots (id == 0)
|
||||
- If loop flag exists, jumps back to loop start
|
||||
- Sets `m_bStop = true` when combo ends
|
||||
|
||||
---
|
||||
|
||||
### **STEP 8: Continue Combo After Skill Finishes**
|
||||
**File**: `EC_HostPlayer.cpp` (line 4129-4135, 6244-6252)
|
||||
|
||||
When a skill finishes or melee state changes:
|
||||
|
||||
```cpp
|
||||
// After melee attack finishes
|
||||
if (m_bMelee && m_pComboSkill && !m_pComboSkill->IsStop())
|
||||
{
|
||||
if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled())
|
||||
g_pGame->GetGameRun()->PostMessage(MSG_HST_CONTINUECOMBOSKILL,
|
||||
MAN_PLAYER, 0, 1,
|
||||
m_pComboSkill->GetGroupIndex());
|
||||
else
|
||||
m_pComboSkill->Continue(true);
|
||||
}
|
||||
|
||||
// After other actions finish
|
||||
if (bDoOtherThing)
|
||||
{
|
||||
if (m_pComboSkill && !m_pComboSkill->IsStop())
|
||||
{
|
||||
if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled())
|
||||
g_pGame->GetGameRun()->PostMessage(MSG_HST_CONTINUECOMBOSKILL,
|
||||
MAN_PLAYER, 0, 0,
|
||||
m_pComboSkill->GetGroupIndex());
|
||||
else
|
||||
m_pComboSkill->Continue(false);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Posts `MSG_HST_CONTINUECOMBOSKILL` message to continue combo
|
||||
- Message includes melee state and group index
|
||||
- Allows combo to continue asynchronously
|
||||
|
||||
---
|
||||
|
||||
### **STEP 9: OnMsgContinueComboSkill()**
|
||||
**File**: `EC_HostPlayer.cpp` (line 6261-6268)
|
||||
|
||||
```cpp
|
||||
void CECHostPlayer::OnMsgContinueComboSkill(const ECMSG &Msg)
|
||||
{
|
||||
bool bMeleeing = (Msg.dwParam1 == 1);
|
||||
if (bMeleeing != m_bMelee)
|
||||
bMeleeing = m_bMelee; // Use current melee state
|
||||
|
||||
int iGroupID = (int)Msg.dwParam2;
|
||||
|
||||
// Verify combo is still active and matches group
|
||||
if (m_pComboSkill &&
|
||||
m_pComboSkill->GetGroupIndex() == iGroupID &&
|
||||
!m_pComboSkill->IsStop())
|
||||
{
|
||||
m_pComboSkill->Continue(bMeleeing); // Continue to next skill
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Points**:
|
||||
- Handles message to continue combo
|
||||
- Verifies combo is still active
|
||||
- Calls `Continue()` again to execute next skill
|
||||
|
||||
---
|
||||
|
||||
### **STEP 10: Loop Until Complete**
|
||||
|
||||
Steps 6-9 repeat until:
|
||||
- All skills in sequence are executed
|
||||
- Combo reaches end (no loop flag)
|
||||
- Combo is stopped (`m_bStop = true`)
|
||||
- Target changes (unless `bIgnoreAtkLoop` is true)
|
||||
|
||||
---
|
||||
|
||||
## Key Data Structures
|
||||
|
||||
### **EC_COMBOSKILL**
|
||||
```cpp
|
||||
struct EC_COMBOSKILL
|
||||
{
|
||||
BYTE nIcon; // Icon index (0-N)
|
||||
short idSkill[EC_COMBOSKILL_LEN]; // Array of skill IDs
|
||||
};
|
||||
```
|
||||
|
||||
**Special Skill IDs**:
|
||||
- `SID_ATTACK = -1`: Normal attack
|
||||
- `SID_LOOPSTART = -2`: Loop start flag
|
||||
- `0`: Empty slot (skipped)
|
||||
- `> 0`: Regular skill ID
|
||||
|
||||
### **CECComboSkill Member Variables**
|
||||
```cpp
|
||||
CECHostPlayer* m_pHost; // Host player
|
||||
EC_COMBOSKILL m_cs; // Combo skill data
|
||||
int m_iGroup; // Group index (0-EC_COMBOSKILL_NUM-1)
|
||||
int m_iCursor; // Current position in sequence
|
||||
bool m_bStop; // Stop flag
|
||||
int m_iLoopStart; // Loop start index (-1 if no loop)
|
||||
int m_idTarget; // Attack target
|
||||
bool m_bForceAtk; // Force attack flag
|
||||
bool m_bIgnoreAtkLoop; // Ignore attack loop flag
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Important Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `EC_GameUIEvent.cpp` | Handles mouse clicks on shortcuts |
|
||||
| `EC_GameUIMan.cpp` | Handles keyboard shortcuts |
|
||||
| `EC_Shortcut.cpp` | `CECSCSkillGrp::Execute()` - Entry point |
|
||||
| `EC_HostPlayer.cpp` | `ApplyComboSkill()` - Creates and starts combo |
|
||||
| `EC_ComboSkill.cpp` | `CECComboSkill` class - Manages combo sequence |
|
||||
| `EC_Configs.cpp` | Stores combo skill data in `m_vs.comboSkill[]` |
|
||||
|
||||
---
|
||||
|
||||
## For Unity Port
|
||||
|
||||
To implement this in Unity:
|
||||
|
||||
1. **Shortcut Click Handler**:
|
||||
```csharp
|
||||
public void OnShortcutClicked(int slotIndex)
|
||||
{
|
||||
CECShortcut shortcut = GetShortcut(slotIndex);
|
||||
if (shortcut != null && shortcut.GetType() == SCT_SKILLGRP)
|
||||
{
|
||||
CECSCSkillGrp skillGrp = (CECSCSkillGrp)shortcut;
|
||||
GetHostPlayer().ApplyComboSkill(skillGrp.GetGroupIndex());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **ApplyComboSkill**:
|
||||
```csharp
|
||||
public bool ApplyComboSkill(int groupIndex)
|
||||
{
|
||||
ClearComboSkill();
|
||||
|
||||
m_comboSkill = new CECComboSkill();
|
||||
if (!m_comboSkill.Init(this, groupIndex, m_selectedTarget,
|
||||
forceAttack, ignoreAtkLoop))
|
||||
return false;
|
||||
|
||||
m_comboSkill.Continue(m_isMeleeing);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Continue Combo**:
|
||||
```csharp
|
||||
// After skill finishes
|
||||
if (m_comboSkill != null && !m_comboSkill.IsStop())
|
||||
{
|
||||
StartCoroutine(ContinueComboAfterDelay());
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
**Complete Flow**:
|
||||
1. Player clicks shortcut → `pSC->Execute()`
|
||||
2. `CECSCSkillGrp::Execute()` → `ApplyComboSkill(groupIndex)`
|
||||
3. `ApplyComboSkill()` → Creates `CECComboSkill` and calls `Init()`
|
||||
4. `Init()` → Loads combo data from configs
|
||||
5. `Continue()` → Executes first skill
|
||||
6. After skill finishes → Posts `MSG_HST_CONTINUECOMBOSKILL`
|
||||
7. `OnMsgContinueComboSkill()` → Calls `Continue()` again
|
||||
8. Repeat until combo completes
|
||||
|
||||
**Key**: The combo skill data (`EC_COMBOSKILL`) is loaded from `EC_Configs::m_vs.comboSkill[groupIndex]`, which was loaded from server in `LoadUserConfigData()`.
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09b07dfdbdd8c094d9ded2ba81316847
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -23,6 +23,213 @@ namespace BrewMonster
|
||||
/// Apply for a license remove later
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
//public bool UpdateShortcuts()
|
||||
//{
|
||||
// CECShortcut pSC;
|
||||
// Image skillImage;
|
||||
// CECSCSkill pSCSkill;
|
||||
// int iIconFile, nMax;
|
||||
// AUIImagePicture pCell;
|
||||
// CECSkill pSkill = new CECSkill(-1, -1);
|
||||
// AUIClockIcon pClock;
|
||||
|
||||
|
||||
// int nCurPanel9 = GetCurPanel1();
|
||||
// int nCurPanel8 = GetCurPanel2();
|
||||
|
||||
// CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
// if (pHost == null) return false;
|
||||
// var a_pSCS = new List<CECShortcutSet>();
|
||||
// var a_pszPanel = new List<string>();
|
||||
// GetQuickBarNameAndSC(pHost, a_pszPanel, a_pSCS, nCurPanel9, nCurPanel8);
|
||||
|
||||
// for (int i = 0; i <= 1(int)a_pSCS.Count; i++)
|
||||
// {
|
||||
// if (a_pSCS[i] == null)
|
||||
// continue;
|
||||
|
||||
// CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
// if (!pQuickBar || !pQuickBar->IsShow()) continue;
|
||||
// int slotIndex = 0;
|
||||
// for (int j = 0; j < a_pSCS.Count; j++)
|
||||
// {
|
||||
// pCell = AUIImagePictureList[slotIndex];
|
||||
// pSC = a_pSCS[i].GetShortcut(j);
|
||||
// pClock = pCell.GetClockIcon();
|
||||
// pClock.SetProgressRange(0, 1);
|
||||
// pClock.SetProgressPos(1);
|
||||
// if (pSC != null)
|
||||
// {
|
||||
// if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILL)
|
||||
// {
|
||||
// iIconFile = (int)EC_GAMEUI_ICONS.ICONS_SKILL;
|
||||
// pSCSkill = (CECSCSkill)pSC;
|
||||
// pSkill = pSCSkill.GetSkill();
|
||||
// if (falsem_bDelGoblinSkillSC && GNET::ElementSkill::IsGoblinSkill(pSkill->GetSkillID()))
|
||||
// {
|
||||
// a_pSCS[i]->SetShortcut(j, NULL);
|
||||
// pSC = NULL;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (pSkill != null && pSkill.ReadyToCast() && pHost.GetPrepSkill() != pSkill)
|
||||
// {
|
||||
// if (ElementSkill.IsGoblinSkill((uint)pSkill.GetSkillID()))
|
||||
// {
|
||||
// if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (pHost.CheckSkillCastCondition(pSkill) == 0)
|
||||
// {
|
||||
// //pCell.SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //pCell.SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
// if (pSkill != null && (pSkill.GetCoolingTime() > 0 ||
|
||||
// pHost.GetPrepSkill() == pSkill))
|
||||
// {
|
||||
// pClock.SetProgressRange(0, pSkill.GetCoolingTime());
|
||||
// if (pHost.GetPrepSkill() == pSkill)
|
||||
// {
|
||||
// pClock.SetProgressPos(0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// pClock.SetProgressPos(pSkill.GetCoolingTime() - pSkill.GetCoolingCnt());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (pSC->GetType() == CECShortcut::SCT_ITEM)
|
||||
// {
|
||||
// iIconFile = CECGameUIMan::ICONS_INVENTORY;
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// pSCItem = (CECSCItem*)pSC;
|
||||
// pIvtr = GetHostPlayer()->GetPack(pSCItem->GetInventory());
|
||||
// pItem = pIvtr->GetItem(pSCItem->GetIvtrSlot());
|
||||
// if (pItem && pItem->GetCoolTime(&nMax) > 0)
|
||||
// {
|
||||
// pClock->SetProgressRange(0, nMax);
|
||||
// pClock->SetProgressPos(nMax - pItem->GetCoolTime());
|
||||
// pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
// }
|
||||
// if (pSCItem->GetInventory() == IVTRTYPE_EQUIPPACK)
|
||||
// pCell->SetColor(A3DCOLORRGBA(128, 128, 255, 128));
|
||||
// }
|
||||
// else if (pSC->GetType() == CECShortcut::SCT_PET)
|
||||
// {
|
||||
// pSCPet = (CECSCPet*)pSC;
|
||||
// CECPetData* pPet = pPetCorral->GetPetData(pSCPet->GetPetIndex());
|
||||
// iIconFile = CECGameUIMan::ICONS_INVENTORY;
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// if (pPet)
|
||||
// {
|
||||
// // dead combat pet
|
||||
// if ((pPet->GetClass() == GP_PET_CLASS_COMBAT || pPet->GetClass() == GP_PET_CLASS_EVOLUTION) && pPet->GetHPFactor() == 0.0f)
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
// }
|
||||
// // current active pet
|
||||
// else if (pSCPet->IsActivePet())
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 0));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else if (pSC->GetType() == CECShortcut::SCT_AUTOFASHION)
|
||||
// {
|
||||
// iIconFile = CECGameUIMan::ICONS_SUITE;
|
||||
// fashionCoolTime = pHost->GetCoolTime(GP_CT_EQUIP_FASHION_ITEM, &fashionCoolTimeMax);
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// if (fashionCoolTimeMax > 0)
|
||||
// {
|
||||
// pClock->SetProgressRange(0, fashionCoolTimeMax);
|
||||
// pClock->SetProgressPos(fashionCoolTimeMax - fashionCoolTime);
|
||||
// pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 175));
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// iIconFile = CECGameUIMan::ICONS_ACTION;
|
||||
// if (pSC->GetType() == CECShortcut::SCT_COMMAND)
|
||||
// {
|
||||
// CECSCCommand* pCommandSC = (CECSCCommand*)pSC;
|
||||
// if (GetHostPlayer()->IsInvisible())
|
||||
// {
|
||||
// if (pCommandSC->GetCommandID() == CECSCCommand::CMD_STARTTRADE ||
|
||||
// pCommandSC->GetCommandID() == CECSCCommand::CMD_SELLBOOTH ||
|
||||
// pCommandSC->GetCommandID() == CECSCCommand::CMD_BINDBUDDY)
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (pSC->GetCoolTime(&nMax) > 0)
|
||||
// {
|
||||
// pClock->SetProgressRange(0, nMax);
|
||||
// pClock->SetProgressPos(nMax - pSC->GetCoolTime());
|
||||
// pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
// }
|
||||
// }
|
||||
// if (pSC != null)
|
||||
// {
|
||||
// pCell.SetDataPtr(pSC, "ptr_CECShortcut");
|
||||
// if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILLGRP)
|
||||
// {
|
||||
// EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
// pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
// setting.comboSkill[((CECSCSkillGrp*)pSC)->GetGroupIndex()].nIcon + 1);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (pSkill != null)
|
||||
// {
|
||||
// slotIndex++;
|
||||
// //BMLogger.Log("HoangDev: QuickBar Set Skill Icon: " + (uint)pSkill.GetSkillID() + " : " + ElementSkill.GetIcon((uint)pSkill.GetSkillID()));
|
||||
// var nameskill = ElementSkill.GetIcon((uint)pSkill.GetSkillID());
|
||||
// GetGameUIMan().SetCover(pCell, nameskill, EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
// }
|
||||
// af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
// strFile.MakeLower();
|
||||
// pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
// GetGameUIMan()->m_IconMap[iIconFile][strFile]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// pCell->SetCover(NULL, -1);
|
||||
// pCell->SetText(_AL(""));
|
||||
// pCell->SetDataPtr(NULL);
|
||||
// pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
public bool UpdateShortcuts()
|
||||
{
|
||||
CECShortcut pSC;
|
||||
@@ -48,12 +255,12 @@ namespace BrewMonster
|
||||
if (a_pSCS[i] == null)
|
||||
continue;
|
||||
|
||||
/*CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
if (!pQuickBar || !pQuickBar->IsShow()) continue;*/
|
||||
int slotIndex = 0;
|
||||
for (int j = 0; j < a_pSCS.Count; j++)
|
||||
//*//*CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
//if (!pQuickBar || !pQuickBar->IsShow()) continue;*//*
|
||||
|
||||
for (int j = 0; j < AUIImagePictureList.Count; j++)
|
||||
{
|
||||
pCell = AUIImagePictureList[slotIndex];
|
||||
pCell = AUIImagePictureList[j];
|
||||
pSC = a_pSCS[i].GetShortcut(j);
|
||||
pClock = pCell.GetClockIcon();
|
||||
pClock.SetProgressRange(0, 1);
|
||||
@@ -67,8 +274,8 @@ namespace BrewMonster
|
||||
pSkill = pSCSkill.GetSkill();
|
||||
if (false/*m_bDelGoblinSkillSC && GNET::ElementSkill::IsGoblinSkill(pSkill->GetSkillID())*/)
|
||||
{
|
||||
/* a_pSCS[i]->SetShortcut(j, NULL);
|
||||
pSC = NULL;*/
|
||||
/* a_pSCS[i]->SetShortcut(j, NULL);
|
||||
pSC = NULL;*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -76,14 +283,14 @@ namespace BrewMonster
|
||||
{
|
||||
if (ElementSkill.IsGoblinSkill((uint)pSkill.GetSkillID()))
|
||||
{
|
||||
/* if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}*/
|
||||
/* if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -97,8 +304,8 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
}
|
||||
/* else
|
||||
pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));*/
|
||||
/*else
|
||||
pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));*/
|
||||
if (pSkill != null && (pSkill.GetCoolingTime() > 0 ||
|
||||
pHost.GetPrepSkill() == pSkill))
|
||||
{
|
||||
@@ -193,222 +400,20 @@ namespace BrewMonster
|
||||
pClock->SetProgressPos(nMax - pSC->GetCoolTime());
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
}*/
|
||||
}*//**/
|
||||
if (pSC != null)
|
||||
{
|
||||
BMLogger.LogError("HoangDev: QuickBar Set Skil");
|
||||
|
||||
pCell.SetDataPtr(pSC, "ptr_CECShortcut");
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILLGRP)
|
||||
{
|
||||
/* EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[((CECSCSkillGrp*)pSC)->GetGroupIndex()].nIcon + 1);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pSkill != null)
|
||||
{
|
||||
slotIndex++;
|
||||
//BMLogger.Log("HoangDev: QuickBar Set Skill Icon: " + (uint)pSkill.GetSkillID() + " : " + ElementSkill.GetIcon((uint)pSkill.GetSkillID()));
|
||||
var nameskill = ElementSkill.GetIcon((uint)pSkill.GetSkillID());
|
||||
GetGameUIMan().SetCover(pCell, nameskill, EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
}
|
||||
/*af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
strFile.MakeLower();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
GetGameUIMan()->m_IconMap[iIconFile][strFile]);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* pCell->SetCover(NULL, -1);
|
||||
pCell->SetText(_AL(""));
|
||||
pCell->SetDataPtr(NULL);
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* public bool UpdateShortcuts()
|
||||
{
|
||||
CECShortcut pSC;
|
||||
Image skillImage;
|
||||
CECSCSkill pSCSkill;
|
||||
int iIconFile, nMax;
|
||||
AUIImagePicture pCell;
|
||||
CECSkill pSkill = new CECSkill(-1, -1);
|
||||
AUIClockIcon pClock;
|
||||
|
||||
|
||||
int nCurPanel9 = GetCurPanel1();
|
||||
int nCurPanel8 = GetCurPanel2();
|
||||
|
||||
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
|
||||
if (pHost == null) return false;
|
||||
var a_pSCS = new List<CECShortcutSet>();
|
||||
var a_pszPanel = new List<string>();
|
||||
GetQuickBarNameAndSC(pHost, a_pszPanel, a_pSCS, nCurPanel9, nCurPanel8);
|
||||
|
||||
for (int i = 0; i <= 1*//*(int)a_pSCS.Count*//*; i++)
|
||||
{
|
||||
if (a_pSCS[i] == null)
|
||||
continue;
|
||||
|
||||
*//*CDlgQuickBar* pQuickBar = dynamic_cast<CDlgQuickBar*>(GetGameUIMan()->GetDialog(a_pszPanel[i]));
|
||||
if (!pQuickBar || !pQuickBar->IsShow()) continue;*//*
|
||||
|
||||
for (int j = 0; j < AUIImagePictureList.Count; j++)
|
||||
{
|
||||
pCell = AUIImagePictureList[j];
|
||||
pSC = a_pSCS[i].GetShortcut(j);
|
||||
pClock = pCell.GetClockIcon();
|
||||
pClock.SetProgressRange(0, 1);
|
||||
pClock.SetProgressPos(1);
|
||||
if (pSC != null)
|
||||
{
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILL)
|
||||
{
|
||||
iIconFile = (int)EC_GAMEUI_ICONS.ICONS_SKILL;
|
||||
pSCSkill = (CECSCSkill)pSC;
|
||||
pSkill = pSCSkill.GetSkill();
|
||||
if (false*//*m_bDelGoblinSkillSC && GNET::ElementSkill::IsGoblinSkill(pSkill->GetSkillID())*//*)
|
||||
{
|
||||
*//* a_pSCS[i]->SetShortcut(j, NULL);
|
||||
pSC = NULL;*//*
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pSkill != null && pSkill.ReadyToCast() && pHost.GetPrepSkill() != pSkill)
|
||||
{
|
||||
if (ElementSkill.IsGoblinSkill((uint)pSkill.GetSkillID()))
|
||||
{
|
||||
*//* if (pHostGoblin && !pHostGoblin->CheckSkillCastCondition(pSkill))
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}*//*
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pHost.CheckSkillCastCondition(pSkill) == 0)
|
||||
{
|
||||
//pCell.SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
else
|
||||
{
|
||||
//pCell.SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}
|
||||
}
|
||||
}
|
||||
*//* else
|
||||
pClock.SetColor(A3DCOLORRGBA(0, 0, 0, 128));*//*
|
||||
if (pSkill != null && (pSkill.GetCoolingTime() > 0 ||
|
||||
pHost.GetPrepSkill() == pSkill))
|
||||
{
|
||||
pClock.SetProgressRange(0, pSkill.GetCoolingTime());
|
||||
if (pHost.GetPrepSkill() == pSkill)
|
||||
{
|
||||
pClock.SetProgressPos(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pClock.SetProgressPos(pSkill.GetCoolingTime() - pSkill.GetCoolingCnt());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*//*else if (pSC->GetType() == CECShortcut::SCT_ITEM)
|
||||
{
|
||||
iIconFile = CECGameUIMan::ICONS_INVENTORY;
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
pSCItem = (CECSCItem*)pSC;
|
||||
pIvtr = GetHostPlayer()->GetPack(pSCItem->GetInventory());
|
||||
pItem = pIvtr->GetItem(pSCItem->GetIvtrSlot());
|
||||
if (pItem && pItem->GetCoolTime(&nMax) > 0)
|
||||
{
|
||||
pClock->SetProgressRange(0, nMax);
|
||||
pClock->SetProgressPos(nMax - pItem->GetCoolTime());
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
if (pSCItem->GetInventory() == IVTRTYPE_EQUIPPACK)
|
||||
pCell->SetColor(A3DCOLORRGBA(128, 128, 255, 128));
|
||||
}
|
||||
else if (pSC->GetType() == CECShortcut::SCT_PET)
|
||||
{
|
||||
pSCPet = (CECSCPet*)pSC;
|
||||
CECPetData* pPet = pPetCorral->GetPetData(pSCPet->GetPetIndex());
|
||||
iIconFile = CECGameUIMan::ICONS_INVENTORY;
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
if (pPet)
|
||||
{
|
||||
// dead combat pet
|
||||
if ((pPet->GetClass() == GP_PET_CLASS_COMBAT || pPet->GetClass() == GP_PET_CLASS_EVOLUTION) && pPet->GetHPFactor() == 0.0f)
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}
|
||||
// current active pet
|
||||
else if (pSCPet->IsActivePet())
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pSC->GetType() == CECShortcut::SCT_AUTOFASHION)
|
||||
{
|
||||
iIconFile = CECGameUIMan::ICONS_SUITE;
|
||||
fashionCoolTime = pHost->GetCoolTime(GP_CT_EQUIP_FASHION_ITEM, &fashionCoolTimeMax);
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
if (fashionCoolTimeMax > 0)
|
||||
{
|
||||
pClock->SetProgressRange(0, fashionCoolTimeMax);
|
||||
pClock->SetProgressPos(fashionCoolTimeMax - fashionCoolTime);
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 175));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iIconFile = CECGameUIMan::ICONS_ACTION;
|
||||
if (pSC->GetType() == CECShortcut::SCT_COMMAND)
|
||||
{
|
||||
CECSCCommand* pCommandSC = (CECSCCommand*)pSC;
|
||||
if (GetHostPlayer()->IsInvisible())
|
||||
{
|
||||
if (pCommandSC->GetCommandID() == CECSCCommand::CMD_STARTTRADE ||
|
||||
pCommandSC->GetCommandID() == CECSCCommand::CMD_SELLBOOTH ||
|
||||
pCommandSC->GetCommandID() == CECSCCommand::CMD_BINDBUDDY)
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(128, 128, 128));
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
if (pSC->GetCoolTime(&nMax) > 0)
|
||||
{
|
||||
pClock->SetProgressRange(0, nMax);
|
||||
pClock->SetProgressPos(nMax - pSC->GetCoolTime());
|
||||
pClock->SetColor(A3DCOLORRGBA(0, 0, 0, 128));
|
||||
}
|
||||
}*//*
|
||||
if (pSC != null)
|
||||
{
|
||||
pCell.SetDataPtr(pSC, "ptr_CECShortcut");
|
||||
if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILLGRP)
|
||||
{
|
||||
*//* EC_VIDEO_SETTING setting = GetGame()->GetConfigs()->GetVideoSettings();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[((CECSCSkillGrp*)pSC)->GetGroupIndex()].nIcon + 1);*//*
|
||||
BMLogger.LogError("HoangDev: QuickBar Set Skill Group Icon SCT_SKILLGRP");
|
||||
EC_VIDEO_SETTING setting = EC_Game.GetConfigs().GetVideoSettings();
|
||||
/* pCell.SetCover(GetGameUIMan()->m_pA2DSpriteIcons[CECGameUIMan::ICONS_SKILLGRP],
|
||||
setting.comboSkill[((CECSCSkillGrp)pSC).GetGroupIndex()].nIcon + 1);
|
||||
setting.comboSkill[((CECSCSkillGrp)pSC).GetGroupIndex()].nIcon + 1;*/
|
||||
GetGameUIMan().SetCover(pCell, "unknown", EC_GAMEUI_ICONS.ICONS_SKILLGRP);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -419,24 +424,24 @@ namespace BrewMonster
|
||||
var nameskill = ElementSkill.GetIcon((uint)pSkill.GetSkillID());
|
||||
GetGameUIMan().SetCover(pCell, nameskill, EC_GAMEUI_ICONS.ICONS_SKILL);
|
||||
}
|
||||
*//*af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
strFile.MakeLower();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
GetGameUIMan()->m_IconMap[iIconFile][strFile]);*//*
|
||||
/* af_GetFileTitle(pSC->GetIconFile(), strFile);
|
||||
strFile.MakeLower();
|
||||
pCell->SetCover(GetGameUIMan()->m_pA2DSpriteIcons[iIconFile],
|
||||
GetGameUIMan()->m_IconMap[iIconFile][strFile]); */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*//* pCell->SetCover(NULL, -1);
|
||||
pCell->SetText(_AL(""));
|
||||
/* pCell->SetCover(NULL, -1);
|
||||
pCell->SetText(_AL(""));
|
||||
pCell->SetDataPtr(NULL);
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255));*//*
|
||||
pCell->SetColor(A3DCOLORRGB(255, 255, 255)); */
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
private void GetQuickBarNameAndSC(CECHostPlayer pHost, List<string> pszPanel, List<CECShortcutSet> pSCS, int panel9, int panel8)
|
||||
{
|
||||
string dlgName;
|
||||
|
||||
@@ -6,8 +6,10 @@ using BrewMonster.UI;
|
||||
using CSNetwork;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.Protocols.RPCData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Unity.Cinemachine;
|
||||
using UnityEngine;
|
||||
@@ -300,7 +302,6 @@ public partial class CECGameRun
|
||||
dwRealLen = 0;
|
||||
}
|
||||
byte[] pData = pDataBuf;
|
||||
int dataOffset = offset;
|
||||
|
||||
if (dwVer >= 3)
|
||||
{
|
||||
@@ -343,7 +344,7 @@ public partial class CECGameRun
|
||||
}
|
||||
}
|
||||
//TODO: flow in update fix later
|
||||
Task.Run(() =>
|
||||
/* Task.Run(() =>
|
||||
{
|
||||
GameSession.Context.Post(_ =>
|
||||
{
|
||||
@@ -353,22 +354,21 @@ public partial class CECGameRun
|
||||
}
|
||||
m_pUIManager.GetCDlgQuickBar().UpdateShortcuts();
|
||||
}, null);
|
||||
});
|
||||
|
||||
});*/
|
||||
// TODO: Uncomment when UI manager is available
|
||||
// Load UI configs / 加载UI配置
|
||||
|
||||
CECGameUIMan pGameUI = m_pUIManager.GetInGameUIMan();
|
||||
/* if (pGameUI != null)
|
||||
{
|
||||
int iSize = dr.ReadInt();
|
||||
byte[] uiConfigData = dr.ReadData(iSize);
|
||||
if (!pGameUI.SetUserLayout(uiConfigData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
if (pGameUI != null)
|
||||
{
|
||||
int iSize = dr.ReadInt();
|
||||
byte[] uiConfigData = dr.ReadData(iSize);
|
||||
/*if (!pGameUI.SetUserLayout(uiConfigData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to set user layout");
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
|
||||
// Load user settings / 加载用户设置
|
||||
if (dwVer >= 2)
|
||||
@@ -376,11 +376,11 @@ public partial class CECGameRun
|
||||
// TODO: Uncomment when game configs are available
|
||||
int iSize = dr.ReadInt();
|
||||
byte[] settingsData = dr.ReadData(iSize);
|
||||
/* if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
|
||||
return false;
|
||||
}*/
|
||||
if (!EC_Game.GetConfigs().LoadUserConfigData(settingsData, iSize))
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, Failed to load user config data");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
|
||||
@@ -85,6 +85,21 @@ public static class EC_Utility
|
||||
{
|
||||
return new System.Numerics.Vector3(v.x, v.y, v.z);
|
||||
}
|
||||
public static byte glb_BuildRefuseBLSMask()
|
||||
{
|
||||
byte byMask = 0;
|
||||
|
||||
// const EC_GAME_SETTING &gs = g_pGame->GetConfigs()->GetGameSettings();
|
||||
var gs = EC_Game.GetConfigs().GetGameSettings();
|
||||
|
||||
if (gs.bBlsRefuse_Neutral)
|
||||
byMask |= (byte)REFUSE_BLESS_MASK.REFUSE_NEUTRAL_BLESS;
|
||||
|
||||
if (gs.bBlsRefuse_NonTeammate)
|
||||
byMask |= (byte)REFUSE_BLESS_MASK.REFUSE_NON_TEAMMATE_BLESS;
|
||||
|
||||
return byMask;
|
||||
}
|
||||
public static void Swap<T>(List<T> arr, int a, int b)
|
||||
{
|
||||
T tmp = arr[a];
|
||||
|
||||
Reference in New Issue
Block a user