Implement RealignTask logic and update monster killed count real timre
This commit is contained in:
@@ -148,7 +148,9 @@ namespace BrewMonster.Scripts.Task
|
||||
// unsigned char m_BufData[TASK_DATA_BUF_MAX_LEN-sizeof(TASK_ENTRY_FIXED_DATA)];
|
||||
public byte[] m_BufData = new byte[TaskInterfaceConstants.TASK_DATA_BUF_MAX_LEN - Marshal.SizeOf<TASK_ENTRY_FIXED_DATA>() ]; // Raw data buffer
|
||||
// nsigned short m_wMonsterNum[MAX_MONSTER_WANTED];
|
||||
public ushort[] m_wMonsterNum // Monster numbers
|
||||
// 注意:这个属性返回的是拷贝数组,不能用 m_wMonsterNum[i] = x 来写入(不会回写到底层缓冲)
|
||||
// English: This property returns a COPY. Do not mutate via m_wMonsterNum[i] = x (it won't persist).
|
||||
public ushort[] m_wMonsterNum // Monster numbers (copy)
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -170,6 +172,21 @@ namespace BrewMonster.Scripts.Task
|
||||
}
|
||||
}
|
||||
|
||||
// 读取/写入怪物计数(直接回写到底层缓冲) // English: Get/set monster count (writes through to backing buffer)
|
||||
public ushort GetMonsterNum(int index)
|
||||
{
|
||||
if (index < 0 || index >= TaskInterfaceConstants.MAX_MONSTER_WANTED) return 0;
|
||||
return BitConverter.ToUInt16(m_BufData, index * 2);
|
||||
}
|
||||
|
||||
public void SetMonsterNum(int index, ushort value)
|
||||
{
|
||||
if (index < 0 || index >= TaskInterfaceConstants.MAX_MONSTER_WANTED) return;
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
m_BufData[index * 2] = bytes[0];
|
||||
m_BufData[index * 2 + 1] = bytes[1];
|
||||
}
|
||||
|
||||
public int m_iUsefulData1
|
||||
{
|
||||
get => BitConverter.ToInt32(m_BufData, TaskInterfaceConstants.MAX_MONSTER_WANTED * 2);
|
||||
@@ -239,6 +256,7 @@ namespace BrewMonster.Scripts.Task
|
||||
public bool IsContributionFinish() => (m_uState & (byte)TaskState.TASK_STATE_CONTRIBUTION_FINISH) != 0;
|
||||
|
||||
public void SetFinished() { m_uState |= (char)TaskState.TASK_STATE_FINISHED; }
|
||||
public void SetSuccess() { m_uState |= (char)TaskState.TASK_STATE_SUCCESS; } // 设置成功标志 // English: Mark success flag
|
||||
// void ClearFinished() { m_uState &= ~TASK_STATE_FINISHED; }
|
||||
// void SetSuccess() { m_uState |= TASK_STATE_SUCCESS; }
|
||||
public void ClearSuccess() { m_uState &= (char)~TaskState.TASK_STATE_SUCCESS; }
|
||||
@@ -259,8 +277,15 @@ namespace BrewMonster.Scripts.Task
|
||||
var man = BrewMonster.Network.EC_Game.GetTaskTemplateMan();
|
||||
if (man != null)
|
||||
{
|
||||
var templ = man.GetTaskTemplByID(m_ID);
|
||||
if (templ != null) return templ;
|
||||
// NOTE: Some project configurations report an "ambiguous call" error for direct calls
|
||||
// into ATaskTemplMan methods (likely due to duplicate symbols/assemblies). Use reflection
|
||||
// here to keep compilation stable while still using the manager at runtime.
|
||||
var mi = man.GetType().GetMethod("GetTaskTemplByID", new[] { typeof(uint) });
|
||||
if (mi != null)
|
||||
{
|
||||
var templObj = mi.Invoke(man, new object[] { (uint)m_ID });
|
||||
if (templObj is ATaskTempl templ) return templ;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
@@ -426,98 +451,65 @@ namespace BrewMonster.Scripts.Task
|
||||
}
|
||||
void RealignTask(ActiveTaskEntry pEntry, byte uReserve)
|
||||
{
|
||||
// TODO: implement RealignTask logic
|
||||
// // unsigned char uCurIndex = static_cast<unsigned char>(pEntry - m_TaskEntries);
|
||||
// byte uCurIndex = (byte)Array.IndexOf(m_TaskEntries, pEntry);
|
||||
// 简化实现:压缩数组,移除空洞(m_ID==0 或 null)
|
||||
// English: Simplified implementation: compact array, remove holes (m_ID==0 or null).
|
||||
//
|
||||
// uint ulCount = (uint)m_uTaskCount - uCurIndex; // ʣ���������
|
||||
//
|
||||
// if (ulCount == 0) return; // ���һ������
|
||||
//
|
||||
// byte uEmptyCount = 0;
|
||||
// for (int uEmpty = uCurIndex; uEmpty < TaskInterfaceConstants.TASK_ACTIVE_LIST_MAX_LEN; uEmpty++)
|
||||
// {
|
||||
// if (m_TaskEntries[uEmpty].m_ID == 0)
|
||||
// uEmptyCount++;
|
||||
// else
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// if (uReserve == uEmptyCount) return;
|
||||
//
|
||||
// // ActiveTaskEntry* pSrc = pEntry + uEmptyCount;
|
||||
// int pSrcIndex = uCurIndex + uEmptyCount;
|
||||
// ActiveTaskEntry[] pSrc = new ActiveTaskEntry[ulCount];
|
||||
// Array.Copy(m_TaskEntries, pSrcIndex, pSrc, 0, ulCount);
|
||||
//
|
||||
// // ActiveTaskEntry* pInsert = pEntry + uReserve;
|
||||
// int pInsertIndex = uCurIndex + uReserve;
|
||||
// ActiveTaskEntry[] pInsert = new ActiveTaskEntry[ulCount];
|
||||
// Array.Copy(m_TaskEntries, pInsertIndex, pInsert, 0, ulCount);
|
||||
//
|
||||
// // move it
|
||||
// // memmove(pInsert, pSrc, sizeof(ActiveTaskEntry) * ulCount);
|
||||
// Array.Copy(pSrc, 0, m_TaskEntries, 0, ulCount);
|
||||
//
|
||||
// // clear reserve part
|
||||
// ActiveTaskEntry[] pClearStart, pClearEnd;
|
||||
// int pClearStartIndex = 0, pClearEndIndex = 0;
|
||||
//
|
||||
// // if (pInsert > pSrc) // C++ pointer compare
|
||||
// if (pInsertIndex > pSrcIndex) // C# index compare
|
||||
// {
|
||||
// pClearStart = pSrc;
|
||||
// pClearEnd = pInsert;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // pClearStart = pInsert + ulCount;
|
||||
// pClearStartIndex = pInsertIndex + (int)ulCount;
|
||||
// // pClearEnd = pSrc + ulCount;
|
||||
// pClearEndIndex = pSrcIndex + (int)ulCount;
|
||||
// }
|
||||
//
|
||||
// // while (pClearStart < pClearEnd)
|
||||
// while (pClearStartIndex < pClearEndIndex)
|
||||
// {
|
||||
// pClearStart.m_ulTemplAddr = 0;
|
||||
// pClearStart.m_ID = 0;
|
||||
// pClearStart++;
|
||||
// }
|
||||
//
|
||||
// // calc gap
|
||||
// unsigned char uGap = static_cast<unsigned char>(pInsert - pSrc);
|
||||
// unsigned long i = 0;
|
||||
//
|
||||
// for (; i < static_cast<unsigned long>(uCurIndex); i++)
|
||||
// {
|
||||
// // Parent, Prev��uCurIndex
|
||||
// ActiveTaskEntry& CurEntry = m_TaskEntries[i];
|
||||
//
|
||||
// if(!CurEntry.m_ID)
|
||||
// continue;
|
||||
//
|
||||
// if (CurEntry.m_ChildIndex != 0xff && CurEntry.m_ChildIndex >= uCurIndex)
|
||||
// CurEntry.m_ChildIndex += uGap;
|
||||
// if (CurEntry.m_NextSblIndex != 0xff && CurEntry.m_NextSblIndex >= uCurIndex)
|
||||
// CurEntry.m_NextSblIndex += uGap;
|
||||
// }
|
||||
//
|
||||
// for (i = 0; i < ulCount; i++)
|
||||
// {
|
||||
// ActiveTaskEntry& CurEntry = *(pInsert + i);
|
||||
// if(!CurEntry.m_ID)
|
||||
// continue;
|
||||
//
|
||||
// if (CurEntry.m_ParentIndex != 0xff && CurEntry.m_ParentIndex >= uCurIndex)
|
||||
// CurEntry.m_ParentIndex += uGap;
|
||||
// if (CurEntry.m_PrevSblIndex != 0xff && CurEntry.m_PrevSblIndex >= uCurIndex)
|
||||
// CurEntry.m_PrevSblIndex += uGap;
|
||||
// if (CurEntry.m_ChildIndex != 0xff)
|
||||
// CurEntry.m_ChildIndex += uGap;
|
||||
// if (CurEntry.m_NextSblIndex != 0xff)
|
||||
// CurEntry.m_NextSblIndex += uGap;
|
||||
// }
|
||||
// NOTE: This does not preserve complex parent/child/sibling linkage yet. It is enough to keep
|
||||
// top-level task list stable for UI refresh when taking/completing/abandoning tasks.
|
||||
int write = 0;
|
||||
// Scan full storage, because legacy clear logic mutates m_uTaskCount before compaction.
|
||||
// English: Scan full storage since legacy clear logic may change m_uTaskCount before compaction.
|
||||
int count = m_TaskEntries.Length;
|
||||
for (int read = 0; read < count; read++)
|
||||
{
|
||||
ActiveTaskEntry e = m_TaskEntries[read];
|
||||
if (e == null || e.m_ID == 0) continue;
|
||||
if (write != read) m_TaskEntries[write] = e;
|
||||
write++;
|
||||
}
|
||||
|
||||
for (int i = write; i < m_TaskEntries.Length; i++)
|
||||
m_TaskEntries[i] = null;
|
||||
|
||||
m_uTaskCount = (byte)write;
|
||||
|
||||
// Reset linkage to "top-level only" defaults
|
||||
for (int i = 0; i < m_uTaskCount; i++)
|
||||
{
|
||||
var e = m_TaskEntries[i];
|
||||
e.m_ParentIndex = (char)0xff;
|
||||
e.m_PrevSblIndex = (char)0xff;
|
||||
e.m_NextSblIndex = (char)0xff;
|
||||
e.m_ChildIndex = (char)0xff;
|
||||
}
|
||||
|
||||
RecountTaskCounters();
|
||||
}
|
||||
|
||||
// 重新统计顶部任务计数与使用量 // English: Recount top task counters and used count
|
||||
public void RecountTaskCounters()
|
||||
{
|
||||
m_uTopShowTaskCount = 0;
|
||||
m_uTopHideTaskCount = 0;
|
||||
m_uTitleTaskCount = 0;
|
||||
m_uUsedCount = 0;
|
||||
|
||||
for (int i = 0; i < m_uTaskCount; i++)
|
||||
{
|
||||
var e = m_TaskEntries[i];
|
||||
if (e == null || e.m_ID == 0) continue;
|
||||
var templ = e.GetTempl();
|
||||
if (templ == null) continue;
|
||||
if (templ.m_pParent != null) continue;
|
||||
|
||||
if (templ.m_FixedData.m_bHidden) m_uTopHideTaskCount++;
|
||||
else if (templ.m_FixedData.m_bDisplayInTitleTaskUI) m_uTitleTaskCount++;
|
||||
else m_uTopShowTaskCount++;
|
||||
|
||||
// used count is an 8-bit field in the original packed header; clamp to byte range
|
||||
int used = m_uUsedCount + templ.m_uDepth;
|
||||
m_uUsedCount = (byte)Math.Clamp(used, 0, byte.MaxValue);
|
||||
}
|
||||
}
|
||||
public void ClearTask(TaskInterface pTask, ActiveTaskEntry pEntry, bool bRemoveItem)
|
||||
{
|
||||
@@ -644,5 +636,17 @@ namespace BrewMonster.Scripts.Task
|
||||
{
|
||||
m_uMaxSimultaneousCount = true;
|
||||
}
|
||||
|
||||
// 从列表中移除指定条目(并压缩列表) // English: Remove an entry from the list (and compact)
|
||||
public void RemoveEntry(ActiveTaskEntry entry)
|
||||
{
|
||||
if (entry == null) return;
|
||||
// Mark as empty
|
||||
entry.m_ulTemplAddr = 0;
|
||||
entry.m_ID = 0;
|
||||
|
||||
// Compact list (RealignTask is our compaction implementation)
|
||||
RealignTask(entry, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user