DONE: save skill combo

This commit is contained in:
MinhHai
2026-03-12 13:50:41 +07:00
parent e81797def4
commit f8a8d3d9d4
18 changed files with 540 additions and 1607 deletions
@@ -200,7 +200,7 @@ GameObject:
- component: {fileID: 121983901978661093}
- component: {fileID: 1531713798130676148}
m_Layer: 0
m_Name: MiniMap
m_Name: DlgMap
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -238,6 +238,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: dbb3be46f1d07224f90ade7b25776f34, type: 3}
m_Name:
m_EditorClassIdentifier:
skillNameText: {fileID: 0}
imageProgress: {fileID: 0}
_debugHostPlayerPos: {x: 0, y: 209.1, z: 0}
_hostPlayerIcon: {fileID: 7794785241219751657}
nRow: 3
@@ -509,8 +511,8 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 26.4528, y: -24.152}
m_SizeDelta: {x: -65.7241, y: 37.6547}
m_AnchoredPosition: {x: 6.132599, y: -15.7265}
m_SizeDelta: {x: -25.0837, y: 20.8038}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &499780769183870607
CanvasRenderer:
File diff suppressed because it is too large Load Diff
@@ -57,3 +57,5 @@ MonoBehaviour:
prefab: {fileID: 1590197940424963217, guid: 0c248d0510a114829b58d62d2ecc3b5e, type: 3}
- id: Win_TeamMain
prefab: {fileID: 9152579472324007262, guid: 2060bbc2e61f6db4590ab041243b6294, type: 3}
- id: Win_Map
prefab: {fileID: 4582549600041979364, guid: fd12cafdb76332a488e2a1f3782fe40f, type: 3}
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d381b291f0b51a7d9440c9129ad3176acc9c4e8a8ade93205cd8c87875c5b5db
size 309973
oid sha256:c53fc434d47c67f0b4ba55d6e6fc4443a6d39082d96d4e87eda59e4e57a784cb
size 313030
@@ -15,6 +15,7 @@ using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using CSNetwork.GPDataType;
using UnityEngine;
namespace BrewMonster
@@ -286,9 +287,82 @@ namespace BrewMonster
if (dwVer >= 31)
bCloseMeridiansHint = reader.ReadBoolean();
}
/// <summary>
/// Write video settings to binary stream (same format as Read for save/load consistency).
/// 写入视频设置到二进制流(与 Read 格式一致,保证存档/读档一致)。
/// </summary>
public void Write(BinaryWriter writer, uint dwVer)
{
if (dwVer < 15) return;
writer.Write(bPlayerHP);
writer.Write(bPlayerMP);
writer.Write(bPlayerEXP);
writer.Write(bPlayerHeadText);
writer.Write(bPlayerName);
writer.Write(bPlayerFaction);
writer.Write(bPlayerTitle);
writer.Write(bPlayerShop);
writer.Write(bPlayerSelfName);
writer.Write(bPlayerTalk);
writer.Write(bPlayerBubble);
writer.Write(bMonsterName);
writer.Write(bNPCName);
writer.Write(bGoodsName);
writer.Write(bModelLimit);
writer.Write(nDistance);
writer.Write(bMapMonster);
writer.Write(bMapNPC);
writer.Write(bMapPlayer);
writer.Write(nEffect);
writer.Write(bShowCustomize);
for (int i = 0; i < EC_ConfigConstants.EC_COMBOSKILL_NUM; i++)
{
writer.Write(comboSkill[i].nIcon);
for (int j = 0; j < EC_ConfigConstants.EC_COMBOSKILL_LEN; j++)
writer.Write(comboSkill[i].idSkill[j]);
}
if (dwVer >= 21)
writer.Write(bPlayerForce);
if (dwVer >= 22)
{
writer.Write(bMailToFriendsRemind);
writer.Write(iMailToFriendsCheckTime);
}
if (dwVer >= 24)
writer.Write(cTabSelType);
if (dwVer >= 28)
{
writer.Write(bActivityRemind);
writer.Write(ibActivityReminderCheckTime);
}
if (dwVer >= 31)
writer.Write(bCloseMeridiansHint);
}
/// <summary>
/// Returns the number of bytes that Write(writer, dwVer) writes. 返回 Write 写入的字节数。
/// </summary>
public static int GetSerializedSize(uint dwVer)
{
if (dwVer < 15) return 0;
int n = 17 + 2 + 1 + (EC_ConfigConstants.EC_COMBOSKILL_NUM * (1 + EC_ConfigConstants.EC_COMBOSKILL_LEN * 2));
if (dwVer >= 21) n += 1;
if (dwVer >= 22) n += 1 + 4;
if (dwVer >= 24) n += 2; // char = 2 bytes in BinaryWriter
if (dwVer >= 28) n += 1 + 4;
if (dwVer >= 31) n += 1;
return n;
}
}
// Game Settings Structure
// CharSet.Ansi required so szAutoReply matches C++ ACHAR[65] (1 byte/char); default is Unicode (2 bytes/char).
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
@@ -1146,32 +1220,7 @@ namespace BrewMonster
return true;
}
public bool SaveUserConfigData(byte[] pDataBuf, out int piSize)
{
piSize = 0;
int iTotalSize = 0;
iTotalSize += sizeof(uint); // Version
iTotalSize += Marshal.SizeOf(typeof(EC_VIDEO_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_GAME_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_BLACKLIST_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_COMPUTER_AIDED_SETTING));
if (pDataBuf != null && pDataBuf.Length >= iTotalSize)
{
using (MemoryStream ms = new MemoryStream(pDataBuf))
using (BinaryWriter writer = new BinaryWriter(ms))
{
writer.Write((uint)EC_ConfigConstants.EC_CONFIG_VERSION);
// Note: Would need proper serialization for structs
// This is a simplified version
}
}
piSize = iTotalSize;
return true;
}
/// <summary>
/// Write user config data into buffer at given offset. 在指定偏移处写入用户配置数据。
@@ -1180,9 +1229,11 @@ namespace BrewMonster
{
if (startIndex < 0) { piSize = 0; return false; }
piSize = 0;
uint dwVer = (uint)EC_ConfigConstants.EC_CONFIG_VERSION;
int iVideoSize = EC_VIDEO_SETTING.GetSerializedSize(dwVer);
int iTotalSize = 0;
iTotalSize += sizeof(uint);
iTotalSize += Marshal.SizeOf(typeof(EC_VIDEO_SETTING));
iTotalSize += iVideoSize;
iTotalSize += Marshal.SizeOf(typeof(EC_GAME_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_BLACKLIST_SETTING));
iTotalSize += Marshal.SizeOf(typeof(EC_COMPUTER_AIDED_SETTING));
@@ -1192,7 +1243,11 @@ namespace BrewMonster
using (MemoryStream ms = new MemoryStream(pDataBuf, startIndex, pDataBuf.Length - startIndex))
using (BinaryWriter writer = new BinaryWriter(ms))
{
writer.Write((uint)EC_ConfigConstants.EC_CONFIG_VERSION);
writer.Write((uint)dwVer);
m_vs.Write(writer, dwVer);
writer.Write(GPDataTypeHelper.ToBytes(m_gs));
writer.Write(GPDataTypeHelper.ToBytes(m_bs));
writer.Write(GPDataTypeHelper.ToBytes(m_cas));
}
}
piSize = iTotalSize;
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
using BrewMonster.UI;
using EditorAttributes;
// using NaughtyAttributes;
using UnityEngine;
@@ -14,6 +15,14 @@ namespace BrewMonster
{
}
[ContextMenu(" Size of USER_LAYOUT")]
public void SizeOfUserLayer()
{
var sizeClass = Marshal.SizeOf(typeof(USER_LAYOUT));
var sizeFlat = Marshal.SizeOf<USER_LAYOUT_Flat>();
BMLogger.Log($" USER_LAYOUT (class): {sizeClass} bytes, USER_LAYOUT_Flat (struct): {sizeFlat} bytes, expected: {EC_GameUIMan_Constants.USER_LAYOUT_SIZE}");
}
[ContextMenu("Test")]
public void Test()
@@ -531,7 +531,7 @@ namespace CSNetwork
private void OnProtocolReceived(Protocol protocol)
{
_logger.Log(LogType.Debug, $"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})");
//BMLogger.Log($"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})");
BMLogger.Log($"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})");
if (protocol is null)
return;
@@ -1236,6 +1236,10 @@ namespace BrewMonster.Scripts.Task
return 0u;
}
public int GetTaskId(int ulIndex)
{
return (int)GetTaskId((uint)ulIndex);
}
public uint CanDeliverTask(uint ulTaskId)
{
ATaskTempl pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId);
@@ -1987,6 +1991,21 @@ namespace BrewMonster.Scripts.Task
// }
#endregion
public bool CheckParent(uint ulParent, uint ulChild)
{
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID(ulChild);
bool ret = false;
if (pTempl != null)
{
ATaskTempl pParent = pTempl;
while (pParent.m_pParent != null)
pParent = pParent.m_pParent;
ret = ulParent == pParent.m_ID;
}
return ret;
}
}
@@ -172,5 +172,7 @@ namespace BrewMonster.Scripts.Task
byte[] GetFinishedCntList();
uint GetObtainedGeneralCardCount();
uint GetObtainedGeneralCardCountByRank(int rank);
bool CheckParent(uint ulParent, uint ulChild);
}
}
+69 -2
View File
@@ -1218,7 +1218,55 @@ namespace BrewMonster.Scripts.Task.UI
// bool IsTreasureMapTask(int idTask);
//
// bool TraceTask(int idTask);
// void SyncTrace(void* pData, bool fromServer);
public void SyncTrace(object pData, bool fromServer)
{
USER_LAYOUT pul = (USER_LAYOUT)pData;
if(fromServer)
{
m_vecTasksUnFinish.Clear();
m_vecTasksCanFinish.Clear();
uint dwTraceMask = pul.dwTraceMask;
CECTaskInterface pTask = GetHostPlayer().GetTaskInterface();
for(int i = 0; i < (int)pTask.GetTaskCount(); i++ )
{
if( (dwTraceMask & (1 << i)) != 0 )
{
TraceTask(pTask.GetTaskId((uint)i));
}
}
// store m_bShowTrace flag instead of bTraceAll flag
m_bShowTrace = pul.bTraceAll;
}
else
{
pul.bTraceAll = m_bShowTrace;
uint dwTraceMask = 0;
int i = 0;
for(i=0;i<m_vecTasksCanFinish.Count;i++)
{
int index = GetTaskIndex(m_vecTasksCanFinish[i]);
if (index >= 0)
{
dwTraceMask |= (uint)(1 << index);
}
}
for(i=0;i<m_vecTasksUnFinish.Count;i++)
{
int index = GetTaskIndex(m_vecTasksUnFinish[i]);
if (index >= 0)
{
dwTraceMask |= (uint)(1 << index);
}
}
pul.dwTraceMask = dwTraceMask;
}
}
// bool IsShowTrace(){return m_bShowTrace;}
//
// typedef CECGame::ObjectCoords ObjectCoords;
@@ -1457,7 +1505,26 @@ namespace BrewMonster.Scripts.Task.UI
}
// void SetTaskText(PAUIOBJECT pObj, ACString* pStr);
// int GetTaskIndex(int idTask);
int GetTaskIndex(int idTask)
{
// find the task index in task list
if(idTask <= 0)
{
return -1;
}
CECTaskInterface pTask = GetHostPlayer().GetTaskInterface();
for(int i = 0; i < (int)pTask.GetTaskCount(); i++ )
{
int curTask = pTask.GetTaskId(i);
if(idTask == curTask || pTask.CheckParent((uint)curTask, (uint)idTask))
return i;
}
return -1;
}
//
// bool IsQuest()const;
// bool IsShowHaveQuest()const;
@@ -16,7 +16,7 @@ namespace BrewMonster
public void OnSkillDragDrop()
{
var iSlot = 1;
var nCombo = 2;
var nCombo = 1;
CECShortcutSet pSCS = CECUIManager.Instance.GetInGameUIMan().GetSCSByDlg(1);
if (pSCS.GetShortcut(iSlot - 1) == null || !EC_Game.GetConfigs().GetGameSettings().bLockQuickBar)
pSCS.CreateSkillGroupShortcut(iSlot - 1, nCombo - 1);
@@ -20,14 +20,20 @@ namespace BrewMonster
//[SerializeField] List<Image> m_aSkillImage = new List<Image>();
//[SerializeField] List<Button> m_aSkillButton = new List<Button>();
[SerializeField] List<AUIImagePicture> AUIImagePictureList = new List<AUIImagePicture>();
int m_nCurPanel1 = 1;
int m_nCurPanel2 = 1;
public int m_nCurPanel1 = 1;
public int m_nCurPanel2 = 1;
/// <summary>
/// Apply for a license remove later
/// </summary>
/// <returns></returns>
// public int m_nCurPanel1 = 1;
// public int m_nCurPanel2 = 1;
public bool m_bShowAll1 = false;
public bool m_bShowAll2 = false;
public int m_nDisplayPanels1 = 0;
public int m_nDisplayPanels2 = 0;
public bool UpdateShortcuts()
@@ -1,3 +1,4 @@
using System;
using System.Runtime.InteropServices;
using CSNetwork.GPDataType;
@@ -18,6 +19,12 @@ namespace BrewMonster.UI
public const int CECGAMEUIMAN_MAX_CHATS = 10;
public const int CECGAMEUIMAN_MAX_QSHOPITEMS = 8;
public const int CECGAMEUIMAN_MAX_FASHIONSHOPITEMS = 6;
/// <summary>
/// C++ sizeof(USER_LAYOUT) with default packing (MSVC pack 8).
/// 与 C++ sizeof(USER_LAYOUT) 一致(MSVC 默认 pack 8)。
/// </summary>
public const int USER_LAYOUT_SIZE = 344;
}
// SAVE_MARK: saved mark (NPC, position, name)
@@ -31,6 +38,48 @@ namespace BrewMonster.UI
public ushort[] szName; // ACHAR in C++ (wchar_t) → ushort[]
}
// USER_LAYOUT_Flat: flat struct for binary serialization (total size 344 to match C++ sizeof).
// 扁平结构体,用于二进制序列化(总大小 344,与 C++ sizeof 一致)。
// Field order matches C++ EC_GameUIMan.h. Pack=1 + explicit padding for exact 344-byte output.
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_Flat
{
public sbyte nVersion;
public sbyte nMapMode;
[MarshalAs(UnmanagedType.U1)] public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] bChecked1;
[MarshalAs(UnmanagedType.U1)] public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] bChecked2;
[MarshalAs(UnmanagedType.U1)] public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
[MarshalAs(UnmanagedType.U1)] public bool bOnlineNotify;
[MarshalAs(UnmanagedType.U1)] public bool bAutoReply;
[MarshalAs(UnmanagedType.U1)] public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
[MarshalAs(UnmanagedType.U1)] public bool bTraceAll;
[MarshalAs(UnmanagedType.U1)] public bool bQuickbarShowAll1;
[MarshalAs(UnmanagedType.U1)] public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1, nQuickbarCurPanel2, nQuickbarDisplayPanels1, nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask;
public byte ucCurSystemModuleSC;
[MarshalAs(UnmanagedType.U1)] public bool bSystemModuleQuickBarMini;
[MarshalAs(UnmanagedType.U1)] public bool bMenuMode;
[MarshalAs(UnmanagedType.U1)] public bool bShowCompareDesc;
[MarshalAs(UnmanagedType.U1)] public bool bShowLowHP;
[MarshalAs(UnmanagedType.U1)] public bool bShowTargetOfTarget;
// Padding to reach C++ sizeof(USER_LAYOUT)=344 (C# Pack=1 yields 313, +31 padding)
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 31)]
public byte[] _padding;
}
// TASK_HINT: task hint data
// 任务提示数据
// TODO: ACString strHint is not inline in C++ (pointer); when reading from C++ binary skip ptr after dwTime and fill strHint separately.
@@ -43,24 +92,30 @@ namespace BrewMonster.UI
// USER_LAYOUT_6: user layout version 6
// 用户布局版本 6
// Base for layout versions: common fields (v6 and v7 differ only by bChecked1 size).
// 布局版本基类:公共字段(v6 与 v7 仅 bChecked1 长度不同)
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_6
public class USER_LAYOUT_Base
{
public sbyte nVersion; // __int8 → sbyte
public sbyte nMapMode;
[MarshalAs(UnmanagedType.U1)]
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked1;
[MarshalAs(UnmanagedType.U1)]
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public byte[] bChecked2;
[MarshalAs(UnmanagedType.U1)]
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
[MarshalAs(UnmanagedType.U1)]
public bool bOnlineNotify;
[MarshalAs(UnmanagedType.U1)]
public bool bAutoReply;
[MarshalAs(UnmanagedType.U1)]
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
@@ -68,61 +123,32 @@ namespace BrewMonster.UI
public uint[] clrGroup; // A3DCOLOR (DWORD) → uint
}
// USER_LAYOUT_7: user layout version 7 (bChecked1[5])
// 用户布局版本 7
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_7
public class USER_LAYOUT_6 : USER_LAYOUT_Base
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public byte[] bChecked1;
}
// USER_LAYOUT_8: extends USER_LAYOUT_7 (no struct inheritance in C#; flattened)
// USER_LAYOUT_7: user layout version 7 (bChecked1[5]); base for v8current
// 用户布局版本 7bChecked1[5]);v8 至当前版本的基类
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class USER_LAYOUT_7 : USER_LAYOUT_Base
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public byte[] bChecked1;
}
// USER_LAYOUT_8: extends USER_LAYOUT_7
// 用户布局版本 8
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_8
public class USER_LAYOUT_8 : USER_LAYOUT_7
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
// _USER_LAYOUT_8 additional fields
[MarshalAs(UnmanagedType.U1)]
public bool bTraceAll;
[MarshalAs(UnmanagedType.U1)]
public bool bQuickbarShowAll1;
[MarshalAs(UnmanagedType.U1)]
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
@@ -133,275 +159,130 @@ namespace BrewMonster.UI
// USER_LAYOUT_9: extends USER_LAYOUT_8
// 用户布局版本 9
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_9
public class USER_LAYOUT_9 : USER_LAYOUT_8
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID; // _USER_LAYOUT_9(): init to 1 per element in C++; caller must init in C#
public short[] a_MarkMapID; // init to 1 per element in C++; caller must init in C#
}
// USER_LAYOUT_10: extends USER_LAYOUT_9
// 用户布局版本 10
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_10
public class USER_LAYOUT_10 : USER_LAYOUT_9
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask; // DWORD → uint; _USER_LAYOUT_10(): init 0
public uint dwTraceMask; // DWORD → uint; init 0
}
// USER_LAYOUT_11: extends USER_LAYOUT_10
// 用户布局版本 11
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_11
public class USER_LAYOUT_11 : USER_LAYOUT_10
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask;
public byte ucCurSystemModuleSC; // unsigned char → byte; _USER_LAYOUT_11(): init 0
public byte ucCurSystemModuleSC; // unsigned char → byte; init 0
}
// USER_LAYOUT_12: extends USER_LAYOUT_11
// 用户布局版本 12
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_12
public class USER_LAYOUT_12 : USER_LAYOUT_11
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask;
public byte ucCurSystemModuleSC;
public bool bSystemModuleQuickBarMini; // _USER_LAYOUT_12(): init false
[MarshalAs(UnmanagedType.U1)]
public bool bSystemModuleQuickBarMini; // init false
}
// USER_LAYOUT_13: extends USER_LAYOUT_12
// 用户布局版本 13
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_13
public class USER_LAYOUT_13 : USER_LAYOUT_12
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask;
public byte ucCurSystemModuleSC;
public bool bSystemModuleQuickBarMini;
public bool bMenuMode; // _USER_LAYOUT_13(): init false
[MarshalAs(UnmanagedType.U1)]
public bool bMenuMode; // init false
}
// USER_LAYOUT_14: extends USER_LAYOUT_13
// 用户布局版本 14
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT_14
public class USER_LAYOUT_14 : USER_LAYOUT_13
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask;
public byte ucCurSystemModuleSC;
public bool bSystemModuleQuickBarMini;
public bool bMenuMode;
public bool bShowCompareDesc; // _USER_LAYOUT_14(): init true
[MarshalAs(UnmanagedType.U1)]
public bool bShowCompareDesc; // init true
[MarshalAs(UnmanagedType.U1)]
public bool bShowLowHP; // init true
}
// USER_LAYOUT: current user layout (extends USER_LAYOUT_14)
// 当前用户布局
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USER_LAYOUT
public class USER_LAYOUT : USER_LAYOUT_14
{
public sbyte nVersion;
public sbyte nMapMode;
public bool bQuickbar1Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
public bool[] bChecked1;
public bool bQuickbar2Mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public bool[] bChecked2;
public bool bQuickbarPetMode;
public int nChatWinSize;
public int nCurChatColor;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public SAVE_MARK[] a_Mark;
public bool bOnlineNotify;
public bool bAutoReply;
public bool bSaveHistory;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public int[] idGroup;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS)]
public uint[] clrGroup;
public bool bTraceAll;
public bool bQuickbarShowAll1;
public bool bQuickbarShowAll2;
public int nQuickbarCurPanel1;
public int nQuickbarCurPanel2;
public int nQuickbarDisplayPanels1;
public int nQuickbarDisplayPanels2;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS)]
public short[] a_MarkMapID;
public uint dwTraceMask;
public byte ucCurSystemModuleSC;
public bool bSystemModuleQuickBarMini;
public bool bMenuMode;
public bool bShowCompareDesc;
public bool bShowLowHP;
public bool bShowTargetOfTarget; // _USER_LAYOUT(): init true
[MarshalAs(UnmanagedType.U1)]
public bool bShowTargetOfTarget; // init true
/// <summary>
/// Serializes this USER_LAYOUT to a byte array (344 bytes to match C++ sizeof(USER_LAYOUT)).
/// 序列化为字节数组(344 字节,与 C++ sizeof(USER_LAYOUT) 一致)。
/// </summary>
public byte[] ToBytes()
{
USER_LAYOUT_Flat flat = ToFlat();
byte[] bytes = new byte[EC_GameUIMan_Constants.USER_LAYOUT_SIZE];
IntPtr ptr = Marshal.AllocHGlobal(EC_GameUIMan_Constants.USER_LAYOUT_SIZE);
try
{
Marshal.StructureToPtr(flat, ptr, false);
Marshal.Copy(ptr, bytes, 0, EC_GameUIMan_Constants.USER_LAYOUT_SIZE);
return bytes;
}
finally
{
Marshal.FreeHGlobal(ptr);
}
}
/// <summary>Converts this USER_LAYOUT to USER_LAYOUT_Flat for binary serialization.</summary>
public USER_LAYOUT_Flat ToFlat()
{
var flat = new USER_LAYOUT_Flat
{
nVersion = nVersion,
nMapMode = nMapMode,
bQuickbar1Mode = bQuickbar1Mode,
bChecked1 = bChecked1 ?? new byte[5],
bQuickbar2Mode = bQuickbar2Mode,
bChecked2 = bChecked2 ?? new byte[3],
bQuickbarPetMode = bQuickbarPetMode,
nChatWinSize = nChatWinSize,
nCurChatColor = nCurChatColor,
a_Mark = a_Mark ?? new SAVE_MARK[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS],
bOnlineNotify = bOnlineNotify,
bAutoReply = bAutoReply,
bSaveHistory = bSaveHistory,
idGroup = idGroup ?? new int[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS],
clrGroup = clrGroup ?? new uint[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS],
bTraceAll = bTraceAll,
bQuickbarShowAll1 = bQuickbarShowAll1,
bQuickbarShowAll2 = bQuickbarShowAll2,
nQuickbarCurPanel1 = nQuickbarCurPanel1,
nQuickbarCurPanel2 = nQuickbarCurPanel2,
nQuickbarDisplayPanels1 = nQuickbarDisplayPanels1,
nQuickbarDisplayPanels2 = nQuickbarDisplayPanels2,
a_MarkMapID = a_MarkMapID ?? new short[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS],
dwTraceMask = dwTraceMask,
ucCurSystemModuleSC = ucCurSystemModuleSC,
bSystemModuleQuickBarMini = bSystemModuleQuickBarMini,
bMenuMode = bMenuMode,
bShowCompareDesc = bShowCompareDesc,
bShowLowHP = bShowLowHP,
bShowTargetOfTarget = bShowTargetOfTarget,
_padding = new byte[31]
};
// Ensure a_Mark elements have szName initialized
for (int i = 0; i < flat.a_Mark.Length; i++)
{
if (flat.a_Mark[i].szName == null)
flat.a_Mark[i].szName = new ushort[EC_GameUIMan_Constants.CECGAMEUIMAN_MARK_NAME_LEN + 1];
}
return flat;
}
}
}
@@ -1,3 +1,4 @@
using System;
using BrewMonster.Assets.PerfectWorld.Scripts.UI.GamePlay;
using BrewMonster.Managers;
using BrewMonster.Scripts.Task;
@@ -6,6 +7,9 @@ using BrewMonster.Scripts.UI;
using System.Collections.Generic;
using System.Linq;
using BrewMonster.Network;
using BrewMonster.Scripts;
using CSNetwork.GPDataType;
using PerfectWorld.UI.MiniMap;
using UnityEngine;
namespace BrewMonster.UI
@@ -24,6 +28,22 @@ namespace BrewMonster.UI
private const string SKILL_ICONLIST_NAME = "iconlist_skill_multisprite";
private const string ACTION_ICONLIST_NAME = "ActionIcon/iconlist_action_multisprite";
public CDlgMiniMap m_pDlgMiniMap;
// Layout/settings flags for GetUserLayout (saved to server)
// 布局/设置标志,用于 GetUserLayout(保存到服务器)
private bool m_bAutoReply;
private bool m_bOnlineNotify;
private bool m_bSaveHistory;
private bool m_bShowItemDescCompare = true;
private bool m_bShowLowHP = true;
private bool m_bShowTargetOfTarget = true;
// TODO: System module quick bar dialog GetMiniMode() not yet wired in C#
private AUIDialog m_pDlgSysModuleQuickBar;
// TODO: System bar dialog IsShow() for bMenuMode
private AUIDialog m_pDlgSystemb;
public static bool TALKPROC_IS_TERMINAL(uint id)
{
return ((id & 0x80000000u) != 0) && ((id & 0x40000000u) != 0);
@@ -172,167 +192,142 @@ namespace BrewMonster.UI
}
/// <summary>
/// Get user layout data for saving to server. Stub: returns size 0 (UI layout save not implemented).
/// 获取用户布局数据用于保存到服务器。桩:返回长度 0(UI 布局保存未实现)
/// Get user layout data for saving to server. Fills USER_LAYOUT and optionally writes to pData.
/// 获取用户布局数据用于保存到服务器。填充 USER_LAYOUT,并可选写入 pData
/// </summary>
/// TODO: NOW, IT ONLY RETURN THE FIXED SIZE OF STRUCTURE. NEED TO IMPLEMENT THE REAL DATA SAVE/LOAD.
public void GetUserLayout(byte[] pData, ref uint dwUISize)
public void GetUserLayout(byte[] pData, int startIndex, ref uint dwUISize)
{
if( pData != null )
{
int i;
USER_LAYOUT ul;
char szName[40];
PAUICHECKBOX pCheck;
CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer();
// memset(&ul, 0, sizeof(USER_LAYOUT));
ul.nVersion = LAYOUTDATA_VERSION;
ul.nMapMode = m_pDlgMiniMap->GetMode();
// TODO: ul.bQuickbarPetMode = GetDialog("Win_QuickbarPetV")->IsShow();
ul.bQuickbarPetMode = false;
string dlgName;
dlgName.Format("Win_Quickbar%dHa", SIZE_HOSTSCSET1);
ul.bQuickbar1Mode = GetDialog(dlgName)->IsShow();
for( i = 0; i < NUM_HOSTSCSETS1; i++ )
{
sprintf(szName, "Win_Quickbar%dHb_%d", SIZE_HOSTSCSET1, i+1);
pCheck = (PAUICHECKBOX)GetDialog(szName)->GetDlgItem("Chk_Normal");
ul.bChecked1[i] = pCheck->IsChecked();
}
dlgName.Format("Win_Quickbar%dHa", SIZE_HOSTSCSET2);
ul.bQuickbar2Mode = GetDialog(dlgName)->IsShow();
for( i = 0; i < NUM_HOSTSCSETS2; i++ )
{
sprintf(szName, "Win_Quickbar%dHb_%d", SIZE_HOSTSCSET2, i+1);
pCheck = (PAUICHECKBOX)GetDialog(szName)->GetDlgItem("Chk_Normal");
ul.bChecked2[i] = pCheck->IsChecked();
}
m_pDlgTask->SyncTrace(&ul, false);
ul.bQuickbarShowAll1 = CDlgQuickBar::m_bShowAll1;
ul.bQuickbarShowAll2 = CDlgQuickBar::m_bShowAll2;
ul.nQuickbarCurPanel1 = CDlgQuickBar::m_nCurPanel1;
ul.nQuickbarCurPanel2 = CDlgQuickBar::m_nCurPanel2;
ul.nQuickbarDisplayPanels1 = CDlgQuickBar::m_nDisplayPanels1;
ul.nQuickbarDisplayPanels2 = CDlgQuickBar::m_nDisplayPanels2;
ul.nChatWinSize = m_pDlgChat->GetChatWinSize();
ul.nCurChatColor = m_pDlgChat->GetChatColor();
for( i = 0; i < (int)m_pDlgMiniMap->GetMarks().size(); i++ )
{
ul.a_Mark[i].nNPC = m_pDlgMiniMap->GetMarks()[i].nNPC;
ul.a_Mark[i].vecPos = m_pDlgMiniMap->GetMarks()[i].vecPos;
ul.a_MarkMapID[i] = (short)m_pDlgMiniMap->GetMarks()[i].mapID;
a_strncpy(ul.a_Mark[i].szName, m_pDlgMiniMap->GetMarks()[i].strName, CECGAMEUIMAN_MARK_NAME_LEN);
}
CECFriendMan::GROUP *pGroup;
CECFriendMan *pMan = g_pGame->GetGameRun()->GetHostPlayer()->GetFriendMan();
if (pMan)
{
int j(0);
for( i = 0; i < pMan->GetGroupNum() && j < CECGAMEUIMAN_MAX_GROUPS; i++ )
{
pGroup = pMan->GetGroupByIndex(i);
if (pGroup->iGroup)
{
ul.idGroup[j] = pGroup->iGroup;
ul.clrGroup[j] = pGroup->color;
++ j;
}
}
}
ul.bAutoReply = m_bAutoReply;
ul.bOnlineNotify = m_bOnlineNotify;
ul.bSaveHistory = m_bSaveHistory;
ul.ucCurSystemModuleSC = pHost->GetCurSysModShortcutSetIndex(); // ǰʹõϵͳģ
ul.bSystemModuleQuickBarMini = m_pDlgSysModuleQuickBar->GetMiniMode();
ul.bMenuMode = m_pDlgSystemb->IsShow();
ul.bShowCompareDesc = m_bShowItemDescCompare;
ul.bShowLowHP = m_bShowLowHP;
ul.bShowTargetOfTarget = m_bShowTargetOfTarget;
memcpy(pvData, &ul, sizeof(USER_LAYOUT));
POINT ptPos;
float fx, fy;
AIniFile theIni;
char szIniFile[MAX_PATH], szKey[40];
A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam();
for( i = 0; i < (int)m_aDialog.size() - 1; i++ )
{
ptPos = m_aDialog[i]->GetPos();
fx = ptPos.x * 100.0f / p->Width;
fy = ptPos.y * 100.0f / p->Height;
//Խ԰UIλò
/*
if( dynamic_cast<CDlgHomeBase*>( m_aDialog[i]) != NULL)
{
continue;
}
*/
sprintf(szKey, "%s_x", m_aDialog[i]->GetName());
theIni.WriteFloatValue("Windows", szKey, fx);
sprintf(szKey, "%s_y", m_aDialog[i]->GetName());
theIni.WriteFloatValue("Windows", szKey, fy);
}
// ͬ "Win_ELFZoom""Win_ELF" λ
//
PAUIDIALOG pDlg(NULL);
if (GetDialog("Win_ELF")->IsShow())
{
pDlg = GetDialog("Win_ELFZoom");
ptPos = GetDialog("Win_ELF")->GetPos();
}
else if (GetDialog("Win_ELFZoom")->IsShow())
{
pDlg = GetDialog("Win_ELF");
ptPos = GetDialog("Win_ELFZoom")->GetPos();
}
if (pDlg)
{
fx = ptPos.x * 100.0f / p->Width;
fy = ptPos.y * 100.0f / p->Height;
sprintf(szKey, "%s_x", pDlg->GetName());
theIni.WriteFloatValue("Windows", szKey, fx);
sprintf(szKey, "%s_y", pDlg->GetName());
theIni.WriteFloatValue("Windows", szKey, fy);
}
sprintf(szIniFile, "%s\\Userdata\\Layout", af_GetBaseDir());
CreateDirectoryA(szIniFile, NULL);
sprintf(szIniFile, "%s\\UserData\\Layout\\%d.ini",
af_GetBaseDir(), pHost->GetCharacterID());
theIni.Save(szIniFile);
theIni.Close();
}
else
{
// TODO: NEW STRUCT USER_LAYOUT
// dwSize = sizeof(USER_LAYOUT);
dwUISize = 344;
}
CECHostPlayer pHost = EC_Game.GetGameRun()?.GetHostPlayer();
if (pHost == null)
{
dwUISize = 0;
return;
}
// Build and fill USER_LAYOUT (ul)
USER_LAYOUT ul = new USER_LAYOUT();
// Initialize array fields (C# class does not auto-init these)
ul.bChecked1 = new byte[HostCfgConstants.NUM_HOSTSCSETS1];
ul.bChecked2 = new byte[HostCfgConstants.NUM_HOSTSCSETS2];
ul.a_Mark = new SAVE_MARK[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS];
ul.idGroup = new int[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS];
ul.clrGroup = new uint[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_GROUPS];
ul.a_MarkMapID = new short[EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS];
for (int k = 0; k < ul.a_Mark.Length; k++)
{
ul.a_Mark[k].szName = new ushort[EC_GameUIMan_Constants.CECGAMEUIMAN_MARK_NAME_LEN + 1];
ul.a_MarkMapID[k] = 1; // C++ inits to 1 per element
}
ul.nVersion = (sbyte)LAYOUTDATA_VERSION;
ul.nMapMode = (sbyte)(m_pDlgMiniMap != null ? m_pDlgMiniMap.GetMode() : 0);
// TODO: Win_QuickbarPetV dialog bQuickbarPetMode not wired in C# yet
// TODO: 快捷栏宠物模式对话框尚未在 C# 中接入
ul.bQuickbarPetMode = false;
// TODO : check later bQuickbar1Mode and bChecked1 from Win_Quickbar*Ha_* dialogs
// string dlgName = $"Win_Quickbar{HostCfgConstants.SIZE_HOSTSCSET1}Ha";
// AUIDialog dlgQuickbar1Ha = GetDialog(dlgName);
// ul.bQuickbar1Mode = dlgQuickbar1Ha != null && dlgQuickbar1Ha.IsShow();
ul.bQuickbar1Mode = false;
for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS1; i++)
{
// TODO: check later Chk_Normal checkbox per quickbar panel
// TODO: 后续核对 每个快捷栏面板的 Chk_Normal 勾选状态
ul.bChecked1[i] = 0;
}
// TODO: check later bQuickbar2Mode and bChecked2 from Win_Quickbar*Hb_* dialogs
ul.bQuickbar2Mode = false;
for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++)
ul.bChecked2[i] = 0;
if (m_pDlgTask != null)
m_pDlgTask.SyncTrace(ul, false);
CDlgQuickBar dlgQuickBar = CECUIManager.Instance?.GetCDlgQuickBar();
if (dlgQuickBar != null)
{
ul.bQuickbarShowAll1 = dlgQuickBar.m_bShowAll1;
ul.bQuickbarShowAll2 = dlgQuickBar.m_bShowAll2;
ul.nQuickbarCurPanel1 = dlgQuickBar.m_nCurPanel1;
ul.nQuickbarCurPanel2 = dlgQuickBar.m_nCurPanel2;
ul.nQuickbarDisplayPanels1 = dlgQuickBar.m_nDisplayPanels1;
ul.nQuickbarDisplayPanels2 = dlgQuickBar.m_nDisplayPanels2;
}
// TODO: chat window size/color m_pDlgChat not wired in C#
ul.nChatWinSize = 1;
ul.nCurChatColor = 1;
// MiniMap marks
if (m_pDlgMiniMap != null)
{
var marks = m_pDlgMiniMap.GetMarks();
int markCount = Mathf.Min(marks.Count, EC_GameUIMan_Constants.CECGAMEUIMAN_MAX_MARKS);
for (int i = 0; i < markCount; i++)
{
var m = marks[i];
ul.a_Mark[i].nNPC = m.nNPC;
ul.a_Mark[i].vecPos = m.vecPos;
ul.a_MarkMapID[i] = (short)m.mapID;
CopyStringToUshortArray(ul.a_Mark[i].szName, m.strName ?? "", EC_GameUIMan_Constants.CECGAMEUIMAN_MARK_NAME_LEN);
}
}
// TODO: friend group layout CECFriendMan / GetFriendMan() not available in C# yet
// TODO: 好友分组布局 C# 中尚未提供 CECFriendMan / GetFriendMan()
// Placeholder: idGroup / clrGroup remain zeroed (already initialized)
ul.bAutoReply = m_bAutoReply;
ul.bOnlineNotify = m_bOnlineNotify;
ul.bSaveHistory = m_bSaveHistory;
// TODO: current system module shortcut set index GetCurSysModShortcutSetIndex() not in C# host
// TODO: 当前使用的系统模块快捷栏索引 – C# 宿主中暂无 GetCurSysModShortcutSetIndex()
ul.ucCurSystemModuleSC = 0;
// TODO: m_pDlgSysModuleQuickBar GetMiniMode() not wired
ul.bSystemModuleQuickBarMini = m_pDlgSysModuleQuickBar != null && GetDlgSysModuleQuickBarMiniMode();
// TODO: m_pDlgSystemb system bar show state
ul.bMenuMode = m_pDlgSystemb != null && m_pDlgSystemb.IsShow();
ul.bShowCompareDesc = m_bShowItemDescCompare;
ul.bShowLowHP = m_bShowLowHP;
ul.bShowTargetOfTarget = m_bShowTargetOfTarget;
dwUISize = EC_GameUIMan_Constants.USER_LAYOUT_SIZE; // Match C++ sizeof(USER_LAYOUT)=344
if (pData != null)
{
// Serialize USER_LAYOUT to binary (344 bytes) and copy into pData (match C++ memcpy)
byte[] layoutBytes = ul.ToBytes();
Array.Copy(layoutBytes, 0, pData, startIndex, (int)dwUISize);
}
}
/// <summary>Copy string into fixed ushort[] (for SAVE_MARK.szName).</summary>
private static void CopyStringToUshortArray(ushort[] dest, string str, int maxLen)
{
if (dest == null || dest.Length < maxLen + 1) return;
int len = System.Math.Min(str?.Length ?? 0, maxLen);
for (int i = 0; i < len; i++)
dest[i] = (ushort)str[i];
for (int i = len; i < dest.Length; i++)
dest[i] = 0;
}
/// <summary>TODO: Wire to system module quick bar mini mode when dialog is available.</summary>
private bool GetDlgSysModuleQuickBarMiniMode()
{
return false;
}
public override void Init()
@@ -341,6 +336,8 @@ namespace BrewMonster.UI
m_IconMap = new Dictionary<byte, (string, Sprite[])>();
m_pDlgTask = GetDialog(CECUIHelper.DlgTaskName).GetComponent<DlgTask>();
m_pDlgTask.Show(false);
m_pDlgMiniMap = GetDialog("Win_Map").GetComponent<CDlgMiniMap>();
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_SKILL] = (SKILL_ICONLIST_NAME, Resources.LoadAll<Sprite>(SKILL_ICONLIST_NAME));
m_IconMap[(byte)EC_GAMEUI_ICONS.ICONS_ACTION] = (ACTION_ICONLIST_NAME, Resources.LoadAll<Sprite>(ACTION_ICONLIST_NAME));
@@ -46,6 +46,8 @@ namespace BrewMonster
}
}
}
// TODO: this is hard-code to test, need to implement the real logic to get the combo skill info from the UI
public void OnCommandConfirm()
{
EC_VIDEO_SETTING setting = EC_Game.GetConfigs().GetVideoSettings();
@@ -63,7 +65,7 @@ namespace BrewMonster
//int iType = pImage->GetData();
if (true/*iType == 0 && pSkill != null*/)
{
setting.comboSkill[GetData() - 1].idSkill[j] = (short)(i +1) /*pSkill.GetSkillID()*/;
setting.comboSkill[0].idSkill[j] = (short)(EC_Game.GetGameRun().GetHostPlayer().GetPositiveSkillByIndex(i).GetSkillID()) /*pSkill.GetSkillID()*/;
j++;
}
else
+14 -12
View File
@@ -9,6 +9,19 @@ using BrewMonster.Scripts;
namespace BrewMonster
{
// C++: Host config constants (version, shortcut set counts/sizes)
public static class HostCfgConstants
{
public const int HOSTCFG_VERSION = 11;
public const int NUM_HOSTSCSETS1 = 5; // expanded from 3 to 5 (2009.05.27)
public const int NUM_HOSTSCSETS2 = 3;
public const int SIZE_HOSTSCSET1 = 9; // expanded from 6 to 9 (2009.05.27)
public const int SIZE_HOSTSCSET2 = 8;
public const int NUM_SYSMODSETS = 4; // System module shortcut sets count
public const int SIZE_SYSMODSCSET = 4; // System module shortcut set size (first 4 slots)
public const int SIZE_FASHIONSCSET = 240;
}
public partial class CECHostPlayer
{
// Shortcut sets (converted from C++: m_aSCSets1[NUM_HOSTSCSETS1], m_aSCSets2[NUM_HOSTSCSETS2], m_aSCSetSysMod[NUM_SYSMODSETS])
@@ -27,18 +40,7 @@ namespace BrewMonster
BOOTH_AUTO_YINPIAO m_AutoYinpiao;
// C++: Host config constants (version, shortcut set counts/sizes)
private static class HostCfgConstants
{
public const int HOSTCFG_VERSION = 11;
public const int NUM_HOSTSCSETS1 = 5; // expanded from 3 to 5 (2009.05.27)
public const int NUM_HOSTSCSETS2 = 3;
public const int SIZE_HOSTSCSET1 = 9; // expanded from 6 to 9 (2009.05.27)
public const int SIZE_HOSTSCSET2 = 8;
public const int NUM_SYSMODSETS = 4; // System module shortcut sets count
public const int SIZE_SYSMODSCSET = 4; // System module shortcut set size (first 4 slots)
public const int SIZE_FASHIONSCSET = 240;
}
// Load configs data (shortcut, etc.) from specified buffer
// Converted from: bool CECHostPlayer::LoadConfigData(const void* pDataBuf)
+3 -3
View File
@@ -902,14 +902,14 @@ public partial class CECGameRun : ITickable
// iTotalSize += (int)dwUISize;
// iTotalSize += sizeof (int);
uint dwUISize = 0;
pGameUI.GetUserLayout(null, ref dwUISize); // TODO: Check if this is needed here
pGameUI.GetUserLayout(null,0, ref dwUISize); // TODO: Check if this is needed here
iTotalSize += sizeof(int) + (int)dwUISize;
// int iSettingSize = 0;
// g_pGame->GetConfigs()->SaveUserConfigData(NULL, &iSettingSize);
// iTotalSize += iSettingSize;
int iSettingSize = 0;
EC_Game.GetConfigs().SaveUserConfigData(null, out iSettingSize);
EC_Game.GetConfigs().SaveUserConfigData(null, 0, out iSettingSize);
// iTotalSize += sizeof(int) + iSettingSize;
iTotalSize += iSettingSize;
@@ -941,7 +941,7 @@ public partial class CECGameRun : ITickable
// pData += dwUISize;
Buffer.BlockCopy(BitConverter.GetBytes((int)dwUISize), 0, pDataBuf, offset, sizeof(int));
offset += sizeof(int);
pGameUI.GetUserLayout(pDataBuf, ref dwUISize); // TODO: Check if this is needed here
pGameUI.GetUserLayout(pDataBuf, offset, ref dwUISize); // TODO: Check if this is needed here
offset += (int)dwUISize;
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after UI layout, dwUISize={dwUISize})");