/* * FILE: CECShortcutSet.cs * * DESCRIPTION: Shortcut set management * * CREATED BY: Duyuxin, 2005/1/5 * CONVERTED TO C#: 2025 * * HISTORY: * * Copyright (c) 2005 Archosaur Studio, All Rights Reserved. */ using static BrewMonster.CECSCCommand.CommandID; using static BrewMonster.Scripts.RoleExpression; using static BrewMonster.Scripts.DescriptipionMsg; using BrewMonster.Assets.PerfectWorld.Scripts.Skills; using BrewMonster.Network; using BrewMonster.Scripts; using BrewMonster.Scripts.Skills; using static BrewMonster.Scripts.FixedMsg; using CSNetwork.C2SCommand; using CSNetwork.GPDataType; using CSNetwork.S2CCommand; using System; using System.Collections.Generic; using UnityEngine; using static BrewMonster.EC_Resource; using static BrewMonster.IconResourceType; namespace BrewMonster { /// /// Manages a set of shortcuts for quick access to items, skills, commands, etc. /// public class CECShortcutSet { #region Fields private List m_aShortcuts; // Shortcut array #endregion #region Constructor and Destructor public CECShortcutSet() { m_aShortcuts = new List(); } #endregion #region Initialization and Release /// /// Initialize the shortcut set with a specified size /// /// Number of shortcut slots /// True if successful public bool Init(int iSize) { m_aShortcuts = new List(iSize); for (int i = 0; i < iSize; i++) { m_aShortcuts.Add(null); } return true; } public CECShortcutSet Clone() { var temp = new CECShortcutSet(); temp.m_aShortcuts = new List(m_aShortcuts); return temp; } /// /// Release all shortcuts and clear the set /// public void Release() { // Clear all shortcuts for (int i = 0; i < m_aShortcuts.Count; i++) { if (m_aShortcuts[i] != null) { // In C#, we don't need explicit deletion, just clear references m_aShortcuts[i] = null; } } m_aShortcuts.Clear(); } #endregion #region Shortcut Creation Methods /// /// Create an item shortcut at specified position /// /* public bool CreateItemShortcut(int iSlot, int iIvtr, int iIvtrSlot, CECIvtrItem pItem) { CECSCItem pItemSC = new CECSCItem(); if (pItemSC == null) return false; if (!pItemSC.Init(iIvtr, iIvtrSlot, pItem)) { Debug.LogError("CECShortcutSet::CreateItemShortcut, Failed to initialize item shortcut"); return false; } SetShortcut(iSlot, pItemSC); return true; }*/ /// /// Create a skill shortcut at specified position /// public bool CreateSkillShortcut(int iSlot, CECSkill pSkill) { CECSCSkill pSkillSC = new CECSCSkill(); if (pSkillSC == null) return false; if (!pSkillSC.Init(pSkill)) { Debug.LogError("CECShortcutSet::CreateSkillShortcut, Failed to initialize skill shortcut"); return false; } SetShortcut(iSlot, pSkillSC); return true; } /// /// Create a skill group shortcut at specified position /// public bool CreateSkillGroupShortcut(int iSlot, int iGroupIdx) { CECSCSkillGrp pSkillGrpSC = new CECSCSkillGrp(); if (pSkillGrpSC == null) return false; if (!pSkillGrpSC.Init(iGroupIdx)) { Debug.LogError("CECShortcutSet::CreateSkillGroupShortcut, Failed to initialize skill group shortcut"); return false; } SetShortcut(iSlot, pSkillGrpSC); return true; } /// /// Create a pet shortcut at specified position /// /* public bool CreatePetShortcut(int iSlot, int iPetIndex) { CECSCPet pPetSC = new CECSCPet(); if (pPetSC == null) return false; if (!pPetSC.Init(iPetIndex)) { Debug.LogError("CECShortcutSet::CreatePetShortcut, Failed to initialize pet shortcut"); return false; } SetShortcut(iSlot, pPetSC); return true; }*/ /// /// Create an auto fashion shortcut at specified position /// // public bool CreateAutoFashionShortcut(int iSlot, int iFashionIdx) // { // CECSCAutoFashion pAutoFashionSC = new CECSCAutoFashion(); // if (pAutoFashionSC == null) // return false; // // if (!pAutoFashionSC.Init(iFashionIdx)) // { // Debug.LogError("CECShortcutSet::CreateAutoFashionShortcut, Failed to initialize auto fashion shortcut"); // return false; // } // // SetShortcut(iSlot, pAutoFashionSC); // return true; // } /// /// Create a system module shortcut at specified position /// public bool CreateSystemModuleShortcut(int iSlot, int iSys) { CECSCSysModule pSysModule = new CECSCSysModule(); if (pSysModule == null) return false; if (!pSysModule.Init(iSys)) { Debug.LogError("CECShortcutSet::CreateSystemModuleShortcut, Failed to initialize system module shortcut"); return false; } SetShortcut(iSlot, pSysModule); return true; } /// /// Duplicate a shortcut to specified position /// /* public bool CreateClonedShortcut(int iSlot, CECShortcut pShortcut) { CECShortcut pDest = pShortcut.Clone(); if (pDest == null) return false; SetShortcut(iSlot, pDest); return true; }*/ #endregion #region Shortcut Management /// /// Put a shortcut into set and return the old shortcut at that position /// /// Slot index /// Shortcut to place /// Previous shortcut at that position public CECShortcut PutShortcut(int iSlot, CECShortcut pShortcut) { if (iSlot < 0 || iSlot >= m_aShortcuts.Count) return null; CECShortcut pOldShortcut = m_aShortcuts[iSlot]; m_aShortcuts[iSlot] = pShortcut; return pOldShortcut; } /// /// Get a shortcut from set /// /// Slot index /// If true, remove the shortcut from the set /// Shortcut at the specified position public CECShortcut GetShortcut(int iSlot, bool bRemove = false) { if (iSlot < 0 || iSlot >= m_aShortcuts.Count) return null; CECShortcut pShortcut = m_aShortcuts[iSlot]; if (bRemove) m_aShortcuts[iSlot] = null; return pShortcut; } /// /// Set a shortcut into set and release old shortcut at this position automatically /// public void SetShortcut(int iSlot, CECShortcut pShortcut) { if (iSlot < 0 || iSlot >= m_aShortcuts.Count) return; // Clear old shortcut (C# garbage collection will handle cleanup) if (m_aShortcuts[iSlot] != null) { m_aShortcuts[iSlot] = null; } // BMLogger.LogError("SetShortcut iSlot= " + iSlot); m_aShortcuts[iSlot] = pShortcut; } /// /// Exchange shortcuts in two slots /// public void ExchangeShortcut(int iSlot1, int iSlot2) { if (iSlot1 < 0 || iSlot1 >= m_aShortcuts.Count || iSlot2 < 0 || iSlot2 >= m_aShortcuts.Count) return; if (iSlot1 != iSlot2) { CECShortcut pShortcut = m_aShortcuts[iSlot1]; m_aShortcuts[iSlot1] = m_aShortcuts[iSlot2]; m_aShortcuts[iSlot2] = pShortcut; } } /// /// Remove all shortcuts /// public void RemoveAllShortcuts() { for (int i = 0; i < m_aShortcuts.Count; i++) { if (m_aShortcuts[i] != null) { m_aShortcuts[i] = null; } } } /// /// Remove skill and skill group shortcuts /// public void RemoveSkillShortcuts() { for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null) continue; if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILL || pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILLGRP) { m_aShortcuts[i] = null; } } } #endregion #region Update Methods /// /// Update item shortcut when item position changed /// /* public void UpdateMovedItemSC(int tidItem, int iSrcIvtr, int iSrcSlot, int iDstIvtr, int iDstSlot) { for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null || pSC.GetType() != CECShortcut.ShortcutType.SCT_ITEM) continue; CECSCItem pItemSC = (CECSCItem)pSC; if (pItemSC.GetInventory() == iSrcIvtr && pItemSC.GetIvtrSlot() == iSrcSlot) { Debug.Assert(pItemSC.GetItemTID() == tidItem); pItemSC.MoveItem(iDstIvtr, iDstSlot); } } }*/ /// /// Update item shortcut when item removed /// /* public void UpdateRemovedItemSC(int tidItem, int iIvtr, int iSlot, int iSameItem) { for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null || pSC.GetType() != CECShortcut.ShortcutType.SCT_ITEM) continue; CECSCItem pItemSC = (CECSCItem)pSC; if (pItemSC.GetInventory() == iIvtr && pItemSC.GetIvtrSlot() == iSlot) { Debug.Assert(pItemSC.GetItemTID() == tidItem); if (pItemSC.GetAutoFindFlag() && iSameItem >= 0) pItemSC.MoveItem(iIvtr, iSameItem); else SetShortcut(i, null); } } }*/ /// /// Update item shortcut when two items exchanged /// /*public void UpdateExchangedItemSC(int tidItem1, int iIvtr1, int iSlot1, int tidItem2, int iIvtr2, int iSlot2) { for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null || pSC.GetType() != CECShortcut.ShortcutType.SCT_ITEM) continue; CECSCItem pItemSC = (CECSCItem)pSC; if (pItemSC.GetInventory() == iIvtr1 && pItemSC.GetIvtrSlot() == iSlot1) { Debug.Assert(pItemSC.GetItemTID() == tidItem1); pItemSC.MoveItem(iIvtr2, iSlot2); } else if (pItemSC.GetInventory() == iIvtr2 && pItemSC.GetIvtrSlot() == iSlot2) { Debug.Assert(pItemSC.GetItemTID() == tidItem2); pItemSC.MoveItem(iIvtr1, iSlot1); } } } /// /// Update pet shortcut when pet freed /// public void UpdateFreedPetSC(int iPetIndex) { for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null || pSC.GetType() != CECShortcut.ShortcutType.SCT_PET) continue; CECSCPet pPetSC = (CECSCPet)pSC; if (pPetSC.GetPetIndex() == iPetIndex) SetShortcut(i, null); } }*/ #endregion #region Skill Management /// /// Replace skill id in skill shortcuts /// public void ReplaceSkillID(int idOld, CECSkill pNewSkill) { for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null || pSC.GetType() != (int)CECShortcut.ShortcutType.SCT_SKILL) continue; // Replace skill CECSCSkill pSkillSC = (CECSCSkill)pSC; CECSkill pSkill = pSkillSC.GetSkill(); if (pSkill.GetSkillID() == idOld) pSkillSC.SetSkill(pNewSkill); } } /// /// Replace skill id in skill shortcuts using skill array /// public void ReplaceSkillID(SkillArrayWrapper skillArray, CECSkill pNewSkill) { for (int i = 0; i < skillArray.Count(); i++) { ReplaceSkillID((int)skillArray[i], pNewSkill); } } /// /// Remove skill shortcut by skill ID /// public bool RemoveSkillShortcut(int idSkill) { bool bRemove = false; for (int i = 0; i < GetShortcutNum(); i++) { CECShortcut pSC = GetShortcut(i); if (pSC == null) continue; if (pSC.GetType() == (int)CECShortcut.ShortcutType.SCT_SKILL) { CECSCSkill pSkillSC = (CECSCSkill)pSC; CECSkill pSkill = pSkillSC.GetSkill(); if (pSkill != null && pSkill.GetSkillID() == idSkill) { SetShortcut(i, null); bRemove = true; continue; } } } return bRemove; } #endregion #region Serialization /// /// Save shortcut configs to specified buffer /// public bool SaveConfigData(out byte[] dataBuffer) { List data = new List(); for (int i = 0; i < m_aShortcuts.Count; i++) { CECShortcut pSC = m_aShortcuts[i]; if (pSC == null) continue; // Record shortcut's position and type data.AddRange(BitConverter.GetBytes(i)); data.AddRange(BitConverter.GetBytes((int)pSC.GetType())); BMLogger.Log($"[MH] Saving shortcut slot: {i} Type: {pSC.GetType()}"); // TODO: implement other shortcut types switch ((CECShortcut.ShortcutType)pSC.GetType()) { case CECShortcut.ShortcutType.SCT_COMMAND: { CECSCCommand cmdSC = (CECSCCommand)pSC; data.AddRange(BitConverter.GetBytes(cmdSC.GetCommandID())); data.AddRange(BitConverter.GetBytes((int)cmdSC.GetParam())); break; } case CECShortcut.ShortcutType.SCT_SKILL: { CECSCSkill skillSC = (CECSCSkill)pSC; data.AddRange(BitConverter.GetBytes(skillSC.GetSkill().GetSkillID())); break; } // case CECShortcut.ShortcutType.SCT_ITEM: // { // CECSCItem itemSC = (CECSCItem)pSC; // data.AddRange(BitConverter.GetBytes(itemSC.GetInventory())); // data.AddRange(BitConverter.GetBytes(itemSC.GetIvtrSlot())); // data.AddRange(BitConverter.GetBytes(itemSC.GetItemTID())); // break; // } case CECShortcut.ShortcutType.SCT_SKILLGRP: { CECSCSkillGrp skillGrpSC = (CECSCSkillGrp)pSC; data.AddRange(BitConverter.GetBytes(skillGrpSC.GetGroupIndex())); break; } // case CECShortcut.ShortcutType.SCT_PET: // { // CECSCPet petSC = (CECSCPet)pSC; // data.AddRange(BitConverter.GetBytes(petSC.GetPetIndex())); // break; // } // // case CECShortcut.ShortcutType.SCT_AUTOFASHION: // { // CECSCAutoFashion fashionSC = (CECSCAutoFashion)pSC; // data.AddRange(BitConverter.GetBytes(fashionSC.GetAutoFashionIndex())); // break; // } case CECShortcut.ShortcutType.SCT_SYSMODULE: { CECSCSysModule sysSC = (CECSCSysModule)pSC; data.AddRange(BitConverter.GetBytes(sysSC.GetSysModID())); break; } default: Debug.LogError($"CECShortcutSet::SaveConfigData - Unknown shortcut type = { pSC.GetType()}"); break; } } // Add the end flag data.AddRange(BitConverter.GetBytes(-1)); dataBuffer = data.ToArray(); return true; } /// /// Load shortcut configs from specified buffer /// public bool LoadConfigData(byte[] pDataBuf, uint dwVer, ref int offset) { if (pDataBuf == null || pDataBuf.Length == 0) { return false; } CECGameRun pGameRun = EC_Game.GetGameRun(); CECHostPlayer pHost = pGameRun.GetHostPlayer(); Debug.Assert(pHost != null); while (offset < pDataBuf.Length) { int iSlot = GPDataTypeHelper.FromBytes(pDataBuf, offset); offset += sizeof(int); if (iSlot < 0) break; // Meet end flag int iSCType = GPDataTypeHelper.FromBytes(pDataBuf, offset); offset += sizeof(int); //BMLogger.Log("[MH] Loading shortcut slot: " + iSlot + " Type: " + iSCType); switch ((CECShortcut.ShortcutType)iSCType) { case CECShortcut.ShortcutType.SCT_COMMAND: { int iCommand = BitConverter.ToInt32(pDataBuf, offset); offset += sizeof(int); int iParam = 0; if (dwVer >= 2) { iParam = BitConverter.ToInt32(pDataBuf, offset); offset += sizeof(int); } // Recreate command shortcut from serialized command id + param. // This is required so "action/command" shortcuts on quickbar persist after relog. var cmd = new CECSCCommand(iCommand); if (dwVer >= 2) cmd.SetParam((uint)iParam); SetShortcut(iSlot, cmd); break; } case CECShortcut.ShortcutType.SCT_SKILL: { int idSkill = BitConverter.ToInt32(pDataBuf, offset); offset += sizeof(int); CECSkill pSkill = pHost.GetPositiveSkillByID(idSkill, true); if (pSkill == null) pSkill = pHost.GetEquipSkillByID(idSkill); CECSkill pSkill2 = null; /* CECHostGoblin pGoblin = (CECHostGoblin)pHost.GetGoblinModel(); if (pGoblin != null) { pSkill2 = pGoblin.GetSkillByID(idSkill); }*/ if (pSkill != null) CreateSkillShortcut(iSlot, pSkill); else if (pSkill2 != null) CreateSkillShortcut(iSlot, pSkill2); 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); 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); break; }*/ 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; } // 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; // } // // 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; // } 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; } /* default: //TODO: uncomment //BMLogger.LogError("CECShortcutSet::LoadConfigData - Unknown shortcut type"); return false;*/ } } return true; } #endregion #region Properties /// /// Get the number of shortcuts in the set /// public int GetShortcutNum() { if(m_aShortcuts == null || m_aShortcuts.Count == 0) { return 0; } return m_aShortcuts.Count; } #endregion } #region Placeholder Classes // These classes are referenced but not defined in the provided files // They should be implemented separately based on EC_Shortcut.h/cpp [Serializable] public class CECShortcut { protected int m_iSCType; public CECShortcut() { m_iSCType = (int)ShortcutType.SCT_UNKNOWN; } public enum ShortcutType { SCT_UNKNOWN = -1, SCT_SKILL = 0, SCT_ITEM, SCT_COMMAND, SCT_SKILLGRP, SCT_PET, SCT_AUTOFASHION, SCT_SYSMODULE, } public virtual int GetType() { return m_iSCType; } public virtual string GetDesc() { return ""; } public virtual CECShortcut Clone() { return new CECShortcut(); } public virtual bool Execute() { return true; } public virtual int GetCoolTime(ref int piMax) { piMax = 0; return 0; } public virtual string GetIconFile() { // Return a default icon file name return "unknown"; } } // Shortcut type public enum ShortcutType { SCT_UNKNOWN = -1, SCT_SKILL = 0, SCT_ITEM, SCT_COMMAND, SCT_SKILLGRP, SCT_PET, SCT_AUTOFASHION, SCT_SYSMODULE, }; public class CECSCCommand : CECShortcut { private int m_iCommand; // Command ID private uint m_dwParam; // Parameter public enum CommandID { CMD_UNKNOWN = -1, CMD_SITDOWN = 0, CMD_WALKRUN, CMD_NORMALATTACK, CMD_FINDTARGET, CMD_ASSISTATTACK, CMD_INVITETOTEAM, CMD_LEAVETEAM, CMD_KICKTEAMMEM, CMD_FINDTEAM, CMD_STARTTRADE, CMD_SELLBOOTH, CMD_BUYBOOTH, CMD_PLAYPOSE, CMD_INVITETOFACTION, CMD_FLY, CMD_PICKUP, CMD_GATHER, CMD_RUSHFLY, CMD_BINDBUDDY, } public CECSCCommand(int iCommand) { m_iSCType = (int)ShortcutType.SCT_COMMAND; m_iCommand = iCommand; m_dwParam = 0; } public override string GetDesc() { CECStringTab pDescTab = EC_Game.GetItemDesc(); string szDesc = (""); switch ((CommandID)m_iCommand) { case CMD_SITDOWN: szDesc = pDescTab.GetWideString((int)CMDDESC_SITDOWN); break; case CMD_WALKRUN: szDesc = pDescTab.GetWideString((int)CMDDESC_WALKRUN); break; case CMD_NORMALATTACK: szDesc = pDescTab.GetWideString((int)CMDDESC_NORMALATTACK); break; case CMD_FINDTARGET: szDesc = pDescTab.GetWideString((int)CMDDESC_FINDTARGET); break; case CMD_ASSISTATTACK: szDesc = pDescTab.GetWideString((int)CMDDESC_ASSISTATTACK); break; case CMD_INVITETOTEAM: szDesc = pDescTab.GetWideString((int)CMDDESC_INVITETOTEAM); break; case CMD_LEAVETEAM: szDesc = pDescTab.GetWideString((int)CMDDESC_LEAVETEAM); break; case CMD_KICKTEAMMEM: szDesc = pDescTab.GetWideString((int)CMDDESC_KICKTEAMMEM); break; case CMD_FINDTEAM: szDesc = pDescTab.GetWideString((int)CMDDESC_FINDTEAM); break; case CMD_STARTTRADE: szDesc = pDescTab.GetWideString((int)CMDDESC_STARTTRADE); break; case CMD_SELLBOOTH: szDesc = pDescTab.GetWideString((int)CMDDESC_SELLBOOTH); break; case CMD_BUYBOOTH: szDesc = pDescTab.GetWideString((int)CMDDESC_BUYBOOTH); break; case CMD_INVITETOFACTION: szDesc = pDescTab.GetWideString((int)CMDDESC_INVITETOFACTION); break; case CMD_FLY: szDesc = pDescTab.GetWideString((int)CMDDESC_FLY); break; case CMD_PICKUP: szDesc = pDescTab.GetWideString((int)CMDDESC_PICKUP); break; case CMD_GATHER: szDesc = pDescTab.GetWideString((int)CMDDESC_GATHER); break; case CMD_RUSHFLY: szDesc = pDescTab.GetWideString((int)CMDDESC_RUSHFLY); break; case CMD_BINDBUDDY: szDesc = pDescTab.GetWideString((int)CMDDESC_BINDBUDDY); break; case CMD_PLAYPOSE: { switch ((RoleExpression)m_dwParam) { case ROLEEXP_WAVE: szDesc = pDescTab.GetWideString((int)FACEDESC_WAVEHAND); break; case ROLEEXP_NOD: szDesc = pDescTab.GetWideString((int)FACEDESC_NOD); break; case ROLEEXP_SHAKEHEAD: szDesc = pDescTab.GetWideString((int)FACEDESC_SHADEHEAD); break; case ROLEEXP_SHRUG: szDesc = pDescTab.GetWideString((int)FACEDESC_SHRUG); break; case ROLEEXP_LAUGH: szDesc = pDescTab.GetWideString((int)FACEDESC_LAUGH); break; case ROLEEXP_ANGRY: szDesc = pDescTab.GetWideString((int)FACEDESC_ANGRY); break; case ROLEEXP_STUN: szDesc = pDescTab.GetWideString((int)FACEDESC_FAINT); break; case ROLEEXP_DEPRESSED: szDesc = pDescTab.GetWideString((int)FACEDESC_SAD); break; case ROLEEXP_KISSHAND: szDesc = pDescTab.GetWideString((int)FACEDESC_KISSHAND); break; case ROLEEXP_SHY: szDesc = pDescTab.GetWideString((int)FACEDESC_SHY); break; case ROLEEXP_SALUTE: szDesc = pDescTab.GetWideString((int)FACEDESC_SALUTE); break; case ROLEEXP_SITDOWN: szDesc = pDescTab.GetWideString((int)FACEDESC_SITDOWN); break; case ROLEEXP_ASSAULT: szDesc = pDescTab.GetWideString((int)FACEDESC_CHARGE); break; case ROLEEXP_THINK: szDesc = pDescTab.GetWideString((int)FACEDESC_THINK); break; case ROLEEXP_DEFIANCE: szDesc = pDescTab.GetWideString((int)FACEDESC_CHALLENGE); break; case ROLEEXP_VICTORY: szDesc = pDescTab.GetWideString((int)FACEDESC_WIN); break; case ROLEEXP_GAPE: szDesc = pDescTab.GetWideString((int)FACEDESC_GAPE); break; case ROLEEXP_KISS: szDesc = pDescTab.GetWideString((int)FACEDESC_KISS); break; case ROLEEXP_FIGHT: szDesc = pDescTab.GetWideString((int)FACEDESC_FIGHT); break; case ROLEEXP_ATTACK1: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK1); break; case ROLEEXP_ATTACK2: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK2); break; case ROLEEXP_ATTACK3: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK3); break; case ROLEEXP_ATTACK4: szDesc = pDescTab.GetWideString((int)FACEDESC_ATTACK4); break; case ROLEEXP_DEFENCE: szDesc = pDescTab.GetWideString((int)FACEDESC_DEFENCE); break; case ROLEEXP_FALL: szDesc = pDescTab.GetWideString((int)FACEDESC_FALL); break; case ROLEEXP_FALLONGROUND: szDesc = pDescTab.GetWideString((int)FACEDESC_FALLONGROUND); break; case ROLEEXP_LOOKAROUND: szDesc = pDescTab.GetWideString((int)FACEDESC_LOOKAROUND); break; case ROLEEXP_DANCE: szDesc = pDescTab.GetWideString((int)FACEDESC_DANCE); break; case ROLEEXP_FASHIONWEAPON: szDesc = pDescTab.GetWideString((int)FACEDESC_FASHIONWEAPON); break; default: break; } break; } default: return (""); } return szDesc; } public CECSCCommand(CECSCCommand src) { // Keep shortcut type when cloning m_iSCType = src.m_iSCType; m_iCommand = src.m_iCommand; m_dwParam = src.m_dwParam; } public override CECShortcut Clone() => new CECSCCommand(this); public int GetCommandID() => m_iCommand; public int GetParam() => (int)m_dwParam; // Set / Get command parameter public void SetParam(uint dwParam) { m_dwParam = dwParam; } // Execute shortcut public override bool Execute() { CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer(); if (pHost == null || !pHost.IsAllResReady()) return false; int iMax = 0; if (GetCoolTime(ref iMax) > 0) { bool bForbidCmd = true; if ((CommandID)m_iCommand == CMD_RUSHFLY && pHost.GetRushFlyFlag()) bForbidCmd = false; if (bForbidCmd) { CECGameRun.Instance?.AddFixedMessage((int)FIXMSG_CMD_INCOOLTIME); return false; } } switch ((CommandID)m_iCommand) { case CMD_SITDOWN: pHost.CmdSitDown(!pHost.IsSitting()); break; case CMD_WALKRUN: pHost.CmdWalkRun(!pHost.GetWalkRunFlag()); break; // case CMD_NORMALATTACK: pHost.CmdNormalAttack(); break; case CMD_FINDTARGET: pHost.CmdFindTarget(); break; case CMD_ASSISTATTACK: pHost.CmdAssistAttack(); break; case CMD_INVITETOTEAM: pHost.CmdInviteToTeam(); break; case CMD_LEAVETEAM: pHost.CmdLeaveTeam(); break; case CMD_KICKTEAMMEM: pHost.CmdKickTeamMember(); break; case CMD_FINDTEAM: pHost.CmdFindTeam(); break; case CMD_STARTTRADE: pHost.CmdStartTrade(); break; case CMD_SELLBOOTH: pHost.CmdSellBooth(); break; case CMD_BUYBOOTH: pHost.CmdBuyBooth(); break; case CMD_PLAYPOSE: pHost.CmdStartPose((int)m_dwParam); break; case CMD_INVITETOFACTION: pHost.CmdInviteToFaction(); break; case CMD_FLY: { // 如果骑乘要飞行,则这些 action switcher,否则 CmdFly // If riding wants to fly, use action switcher; otherwise CmdFly if (pHost.GetActionSwitcher()?.OnRideToFlyAction() != true) { var wm = pHost.GetWorkMan(); if (wm != null) { var mw = wm.GetRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS) as CECHPWorkMove; if (mw != null && mw.GetAutoMove()) wm.FinishRunningWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS); } CECIntelligentRoute.Instance().ResetSearch(); pHost.CmdFly(true); } break; } // case CMD_PICKUP: pHost.CmdPickup(); break; case CMD_GATHER: pHost.CmdGather(); break; case CMD_RUSHFLY: pHost.CmdRushFly(); break; case CMD_BINDBUDDY: pHost.CmdBindBuddy(pHost.GetSelectedTarget()); break; default: return false; } return true; } public override string GetIconFile() { string szIconFile = ""; switch ((CommandID)m_iCommand) { case CommandID.CMD_SITDOWN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_SITDOWN); break; case CommandID.CMD_WALKRUN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_WALKRUN); break; case CommandID.CMD_NORMALATTACK: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_NORMALATTACK); break; case CommandID.CMD_FINDTARGET: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_FINDTARGET); break; case CommandID.CMD_ASSISTATTACK: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_ASSISTATTACK); break; case CommandID.CMD_INVITETOTEAM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_INVITETOTEAM); break; case CommandID.CMD_LEAVETEAM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_LEAVETEAM); break; case CommandID.CMD_KICKTEAMMEM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_KICKTEAMMEM); break; case CommandID.CMD_FINDTEAM: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_FINDTEAM); break; case CommandID.CMD_STARTTRADE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_STARTTRADE); break; case CommandID.CMD_SELLBOOTH: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_SELLBOOTH); break; case CommandID.CMD_BUYBOOTH: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_BUYBOOTH); break; case CommandID.CMD_INVITETOFACTION: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_INVITETOFACTION); break; case CommandID.CMD_FLY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_FLY); break; case CommandID.CMD_PICKUP: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_PICKUP); break; case CommandID.CMD_GATHER: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_GATHER); break; case CommandID.CMD_RUSHFLY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_RUSHFLY); break; case CommandID.CMD_BINDBUDDY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_BINDBUDDY); break; case CommandID.CMD_PLAYPOSE: { switch ((RoleExpression)m_dwParam) { case RoleExpression.ROLEEXP_WAVE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_WAVE); break; case RoleExpression.ROLEEXP_NOD: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_NOD); break; case RoleExpression.ROLEEXP_SHAKEHEAD: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SHAKEHEAD); break; case RoleExpression.ROLEEXP_SHRUG: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SHRUG); break; case RoleExpression.ROLEEXP_LAUGH: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_LAUGH); break; case RoleExpression.ROLEEXP_ANGRY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ANGRY); break; case RoleExpression.ROLEEXP_STUN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_STUN); break; case RoleExpression.ROLEEXP_DEPRESSED: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DEPRESSED); break; case RoleExpression.ROLEEXP_KISSHAND: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_KISSHAND); break; case RoleExpression.ROLEEXP_SHY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SHY); break; case RoleExpression.ROLEEXP_SALUTE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SALUTE); break; case RoleExpression.ROLEEXP_SITDOWN: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_SITDOWN); break; case RoleExpression.ROLEEXP_ASSAULT: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ASSAULT); break; case RoleExpression.ROLEEXP_THINK: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_THINK); break; case RoleExpression.ROLEEXP_DEFIANCE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DEFIANCE); break; case RoleExpression.ROLEEXP_VICTORY: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_VICTORY); break; case RoleExpression.ROLEEXP_GAPE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_GAPE); break; case RoleExpression.ROLEEXP_KISS: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_KISS); break; case RoleExpression.ROLEEXP_FIGHT: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FIGHT); break; case RoleExpression.ROLEEXP_ATTACK1: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK1); break; case RoleExpression.ROLEEXP_ATTACK2: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK2); break; case RoleExpression.ROLEEXP_ATTACK3: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK3); break; case RoleExpression.ROLEEXP_ATTACK4: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_ATTACK4); break; case RoleExpression.ROLEEXP_DEFENCE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DEFENCE); break; case RoleExpression.ROLEEXP_FALL: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FALL); break; case RoleExpression.ROLEEXP_FALLONGROUND: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FALLONGROUND); break; case RoleExpression.ROLEEXP_LOOKAROUND: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_LOOKAROUND); break; case RoleExpression.ROLEEXP_DANCE: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_DANCE); break; case RoleExpression.ROLEEXP_FASHIONWEAPON: szIconFile = res_IconFile((int)IconResourceType.RES_ICON_CMD_EXP_FASHIONWEAPON); break; default: break; } break; } default: return ""; } return szIconFile; } public override int GetCoolTime(ref int piMax) { CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer(); int iTime = 0; piMax = 0; if (pHost == null) return 0; switch ((CommandID)m_iCommand) { case CMD_RUSHFLY: iTime = pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_FLY_RUSH, out piMax); break; case CMD_PLAYPOSE: iTime = pHost.GetCoolTime((int)CoolTimeIndex.GP_CT_EMOTE, out piMax); break; case CMD_BINDBUDDY: { CECCounter cnt = pHost.GetBindCmdCoolCnt(); iTime = (int)(cnt.GetPeriod() - cnt.GetCounter()); piMax = (int)cnt.GetPeriod(); break; } default: piMax = 0; break; } return iTime; } } /* public class CECSCSkill : CECShortcut { private CECSkill m_pSkill; public override ShortcutType GetType() => ShortcutType.SCT_SKILL; public override CECShortcut Clone() => null; public bool Init(CECSkill pSkill) { m_pSkill = pSkill; return true; } public CECSkill GetSkill() => m_pSkill; public void SetSkill(CECSkill pSkill) { m_pSkill = pSkill; } } public class CECSCItem : CECShortcut { private int m_iInventory; private int m_iIvtrSlot; private int m_iItemTID; private bool m_bAutoFind; public override ShortcutType GetType() => ShortcutType.SCT_ITEM; public override CECShortcut Clone() => null; public bool Init(int iIvtr, int iSlot, CECIvtrItem pItem) { m_iInventory = iIvtr; m_iIvtrSlot = iSlot; return true; } public int GetInventory() => m_iInventory; public int GetIvtrSlot() => m_iIvtrSlot; public int GetItemTID() => m_iItemTID; public bool GetAutoFindFlag() => m_bAutoFind; public void MoveItem(int iIvtr, int iSlot) { m_iInventory = iIvtr; m_iIvtrSlot = iSlot; } }*/ /* public class CECSCSkillGrp : CECShortcut { private int m_iGroupIdx; public override ShortcutType GetType() => ShortcutType.SCT_SKILLGRP; public override CECShortcut Clone() => null; public bool Init(int iGroupIdx) { m_iGroupIdx = iGroupIdx; return true; } public int GetGroupIndex() => m_iGroupIdx; } public class CECSCPet : CECShortcut { private int m_iPetIndex; public override ShortcutType GetType() => ShortcutType.SCT_PET; public override CECShortcut Clone() => null; public bool Init(int iPetIndex) { m_iPetIndex = iPetIndex; return true; } public int GetPetIndex() => m_iPetIndex; } public class CECSCAutoFashion : CECShortcut { private int m_iFashionIdx; public override ShortcutType GetType() => ShortcutType.SCT_AUTOFASHION; public override CECShortcut Clone() => null; public bool Init(int iFashionIdx) { m_iFashionIdx = iFashionIdx; return true; } public int GetAutoFashionIndex() => m_iFashionIdx; } public class CECSCSysModule : CECShortcut { private int m_iSysModID; public override ShortcutType GetType() => ShortcutType.SCT_SYSMODULE; public override CECShortcut Clone() => null; public bool Init(int iSys) { m_iSysModID = iSys; return true; } public int GetSysModID() => m_iSysModID; } // Placeholder classes for dependencies public class CECIvtrItem { } public class CECInventory { public CECIvtrItem GetItem(int slot) => null; } public class CECHostGoblin { public CECSkill GetSkillByID(int id) => null; }*/ // class CECSCSysModule : public CECShortcut public class CECSCSysModule : CECShortcut { // public: // Types // enum { FM_NONE = -1, FM_GT, FM_TOUCH, ... FM_NUM, }; public enum SysModuleType { FM_NONE = -1, FM_GT, FM_TOUCH, FM_ROBOT, // 帮派系统 (Faction / Guild system) FM_WIKI, FM_OFFLINESHOP, // 摆摊 (Offline shop / Stall) FM_BORADCAST, // 广播系统 (Broadcast system) FM_MATCH, // 边缘系统 (Match system) FM_ADDEXP, // 帮会系统 (Guild / Add exp system) FM_AUTOHPMP, // 辅助功能,自动加药 (Auxiliary function, auto potion) FM_NUM, } // public: // Attributes // static const int g_SysIndexMap[FM_NUM]; public static readonly int[] g_SysIndexMap = new int[(int)SysModuleType.FM_NUM]; // protected: // Attributes // ACString m_strDesc; protected string m_strDesc; // char m_IconFile[256]; protected string m_IconFile; // int m_iSystem; // system ID protected int m_iSystem; // public: // Constructor and Destructor // CECSCSysModule(); public CECSCSysModule() { m_iSCType = (int)ShortcutType.SCT_SYSMODULE; m_strDesc = string.Empty; m_IconFile = string.Empty; m_iSystem = (int)SysModuleType.FM_NONE; } // CECSCSysModule(const CECSCSysModule& src); public CECSCSysModule(CECSCSysModule src) { m_iSCType = src.m_iSCType; m_strDesc = src.m_strDesc; m_IconFile = src.m_IconFile; m_iSystem = src.m_iSystem; } // virtual ~CECSCSysModule() {} // (no destructor in C#) // bool Init(int iSys); public bool Init(int iSys) { m_iSystem = iSys; // TODO: load m_strDesc and m_IconFile from config/table by iSys if needed return true; } // virtual CECShortcut* Clone(); public override CECShortcut Clone() { return new CECSCSysModule(this); } // virtual bool Execute(); public override bool Execute() { // TODO: open corresponding system UI by m_iSystem (e.g. GT, Touch, Robot, Wiki, OfflineShop, Broadcast, Match, AddExp, AutoHpMp) return true; } // int GetSysModID() const { return m_iSystem; } public int GetSysModID() { return m_iSystem; } // virtual const wchar_t* GetDesc(); public override string GetDesc() { return m_strDesc ?? string.Empty; } public override string GetIconFile() { return string.IsNullOrEmpty(m_IconFile) ? "unknown" : m_IconFile; } } #endregion }