Merge pull request 'Update logic interact dlgnpc.' (#64) from feature/hp_interact_npc into develop

Reviewed-on: https://git.brew.monster/Unity/perfect-world-unity/pulls/64
This commit is contained in:
tungdv
2025-11-21 04:46:20 +00:00
20 changed files with 1967 additions and 828 deletions
@@ -15,6 +15,24 @@ namespace BrewMonster.Scripts.Managers
// Item array: index is slot, null means empty.
private EC_IvtrItem[] m_aItems = Array.Empty<EC_IvtrItem>();
public static class Inventory_type
{
public const int IVTRTYPE_PACK = 0, // Normal pack
IVTRTYPE_EQUIPPACK = 1, // Equipment
IVTRTYPE_TASKPACK = 2, // Task pack
IVTRTYPE_TRASHBOX = 3, // Trash box
IVTRTYPE_TRASHBOX2 = 4, // Trash box - material box
IVTRTYPE_TRASHBOX3 = 5, // Trash box - fashion box
IVTRTYPE_ACCOUNT_BOX = 6, // User account box
IVTRTYPE_GENERALCARD_BOX = 7; // 卡牌包裹
};
// 注意 IVTRTYPE_CLIENT_GENERALCARD_PACK 枚举值不能喝上面的 Inventory type 值重复!!
public static class IVTRTYPE_PACK_CLIENT_GENERALCAR
{
public const int IVTRTYPE_CLIENT_GENERALCARD_PACK = 1024; // 客户端本地包裹, 由于卡牌图鉴要求对已获得卡牌通过聊天发送。为了统一处理聊天窗口的物品,添加本地包裹。
};
public EC_Inventory()
{
}
@@ -10,6 +10,7 @@ public class CECNPCServer : CECNPC
{
NPC_ESSENCE? m_pDBEssence;
MONSTER_ESSENCE? m_pMonEssence;
float m_fTaxRate = 0.05f; // Tax rate
public override void SetUpCECNPC(CECNPCMan pNPCMan)
{
base.SetUpCECNPC(pNPCMan);
@@ -71,4 +72,13 @@ public class CECNPCServer : CECNPC
// Get essence data in database
public NPC_ESSENCE? GetDBEssence() { return m_pDBEssence; }
// Get tax rate
public float GetTaxRate() { return m_fTaxRate; }
// Get item price scale factor
public float GetPriceScale()
{
return 1.0f + m_pDBEssence.Value.tax_rate;
}
}
@@ -1359,6 +1359,29 @@ namespace CSNetwork.S2CCommand
{
public int id;
};
public struct cmd_sevnpc_serve
{
public int service_type;
public uint len;
};
public struct accept_task_CONTENT
{
public int idTask;
public int idStorage;
public int idRefreshItem;
};
public struct SevReturnTaskCONTENT
{
public int idTask;
public int iChoice;
}
public struct SevTaskMatterCONTENT
{
public int idTask;
}
}
// Player and NPC state
@@ -516,22 +516,22 @@ namespace CSNetwork.C2SCommand
return SerializeCommand(CommandID.NORMAL_ATTACK, cmd);
}
public static Octets CreateCmdNPCSevAcceptTask(int idTask,int idStorage,int idRefreshItem)
public static Octets CreateCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem)
{
cmd_sevnpc_serve cmd = new cmd_sevnpc_serve()
{
service_type = 1,
len = Marshal.SizeOf<accept_task_CONTENT>()
service_type = NPC_service_type.GP_NPCSEV_TASK_ACCEPT,
len = (uint)Marshal.SizeOf<accept_task_CONTENT>()
};
accept_task_CONTENT acceptTaskContent = new accept_task_CONTENT()
accept_task_CONTENT content = new accept_task_CONTENT()
{
idTask = idTask,
idStorage = idStorage,
idRefreshItem = idRefreshItem
};
var octets = SerializeCommand(CommandID.SEVNPC_SERVE, command: cmd, command2: acceptTaskContent);
var octets = SerializeCommand(CommandID.SEVNPC_SERVE, command: cmd, command2: content);
return octets;
}
@@ -545,10 +545,39 @@ namespace CSNetwork.C2SCommand
var cmd = new cmd_sevnpc_serve
{
service_type = serviceType,
len = (int)len
len = len
};
return SerializeCommand(CommandID.SEVNPC_SERVE, cmd);
}
public static Octets CreateNPCSevReturnTaskCmd(int idTask, int iChoice)
{
var cmd = new cmd_sevnpc_serve
{
service_type = NPC_service_type.GP_NPCSEV_TASK_RETURN,
len = (uint)Marshal.SizeOf<SevReturnTaskCONTENT>()
};
SevReturnTaskCONTENT content = new SevReturnTaskCONTENT()
{
idTask = idTask,
iChoice = iChoice,
};
return SerializeCommand(CommandID.SEVNPC_SERVE, cmd, content);
}
public static Octets CreateNPCSevTaskMatterCmd(int idTask)
{
var cmd = new cmd_sevnpc_serve
{
service_type = NPC_service_type.GP_NPCSEV_TASK_MATTER,
len = (uint)Marshal.SizeOf<SevTaskMatterCONTENT>()
};
SevTaskMatterCONTENT content = new SevTaskMatterCONTENT()
{
idTask = idTask
};
return SerializeCommand(CommandID.SEVNPC_SERVE, cmd, content);
}
public static Octets CreateTaskNotifyCmd()
{
@@ -1611,19 +1611,6 @@ namespace CSNetwork.GPDataType
public int time;
public int timebias;
public int lua_version;
};
public struct cmd_sevnpc_serve
{
public int service_type;
public int len;
};
public struct accept_task_CONTENT
{
public int idTask;
public int idStorage;
public int idRefreshItem;
};
};
}
@@ -6,6 +6,7 @@ using CSNetwork.C2SCommand;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
using CSNetwork.S2CCommand;
using System;
using System;
using System.Collections.Generic;
@@ -1125,6 +1126,32 @@ namespace CSNetwork
// }
}
public void c2s_SendCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem)
{
gamedatasend gamedatasend = new gamedatasend();
gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask(
idTask,
idStorage,
idRefreshItem);
SendProtocol(gamedatasend);
}
public void c2s_SendCmdNPCSevReturnTask(int idTask, int iChoice)
{
gamedatasend gamedatasend = new gamedatasend();
gamedatasend.Data = C2SCommandFactory.CreateNPCSevReturnTaskCmd(
idTask,
iChoice);
SendProtocol(gamedatasend);
}
public void c2s_SendCmdNPCSevTaskMatter(int idTask)
{
gamedatasend gamedatasend = new gamedatasend();
gamedatasend.Data = C2SCommandFactory.CreateNPCSevTaskMatterCmd(idTask);
SendProtocol(gamedatasend);
}
public void GetRoleCustomizeData(int iNumRole, List<int> aRoleIDs)
{
if (iNumRole <= 0 || aRoleIDs == null || aRoleIDs.Count == 0) return;
@@ -274,10 +274,25 @@ namespace BrewMonster.Network
{
Instance._gameSession.c2s_CmdSendEnterPKPrecinctint();
}
public static void c2s_CmdNPCSevHeal()
{
}
public static void c2s_CmdNPCSevAcceptTask(int idTask,int idStorage,int idRefreshItem)
{
Instance._gameSession.c2s_CmdNPCSevAcceptTask(idTask, idStorage, idRefreshItem);
}
public static void c2s_CmdNPCSevReturnTask(int idTask, int iChoice)
{
Instance._gameSession.c2s_SendCmdNPCSevReturnTask(idTask, iChoice);
}
public static void c2s_CmdNPCSevTaskMatter(int idTask)
{
Instance._gameSession.c2s_SendCmdNPCSevTaskMatter(idTask);
}
#region Task
public static void c2s_CmdGetAllData(bool byPack, bool byEquip, bool byTask)
{
@@ -335,7 +335,7 @@ namespace BrewMonster.Scripts.Task
private Dictionary<int, bool> m_TasksToConfirm = new Dictionary<int, bool>();
private readonly System.Collections.Generic.Dictionary<uint, bool> m_emotionTask = new System.Collections.Generic.Dictionary<uint, bool>();
private bool m_bForceNavigateFinish;
private int m_tmFinishDlgShown;
public CECTaskInterface()
{
@@ -445,7 +445,7 @@ namespace BrewMonster.Scripts.Task
public bool IsDeliverLegal()
{
// return !m_pHost->IsTrading() && m_pHost->GetBoothState() == 0 && !m_pHost->IsDead();
// return !m_pHost.IsTrading() && m_pHost.GetBoothState() == 0 && !m_pHost.IsDead();
return true;
// TODO: implement
return m_pHost.IsTrading() && m_pHost.GetBoothState() == 0 && !m_pHost.IsDead();
@@ -462,8 +462,8 @@ namespace BrewMonster.Scripts.Task
public int GetTaskItemCount(uint ulTaskItem)
{
// CECInventory* pPack = m_pHost->GetTaskPack();
// return pPack ? pPack->GetItemTotalNum((int)ulTaskItem) : 0;
// CECInventory* pPack = m_pHost.GetTaskPack();
// return pPack ? pPack.GetItemTotalNum((int)ulTaskItem) : 0;
var inv = m_pHost?.GetInventory(InventoryConst.IVTRTYPE_TASKPACK);
return inv != null ? inv.GetItemTotalNum((int)ulTaskItem) : 0;
@@ -964,7 +964,7 @@ namespace BrewMonster.Scripts.Task
if (!IsDeliverLegal()) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_INDETERMINATE;
// return pTempl->CheckPrerequisite(this, static_cast<ActiveTaskList*>(GetActiveTaskList()), GetCurTime(), true, true, false);
// return pTempl.CheckPrerequisite(this, static_cast<ActiveTaskList*>(GetActiveTaskList()), GetCurTime(), true, true, false);
return pTempl.CheckPrerequisite(this, GetActiveTaskList(), GetCurTime(), true, true, false);
// if (!pTempl.CheckReachLevel(this)) return (uint)TaskInterfaceConstants.TASK_PREREQU_FAIL_BELOW_LEVEL;
@@ -1186,7 +1186,7 @@ namespace BrewMonster.Scripts.Task
return;
}
private uint GetCurTime()
public uint GetCurTime()
{
// use this to avoid task hack by changing the system time
return (uint)EC_Game.GetServerAbsTime();
@@ -1202,6 +1202,93 @@ namespace BrewMonster.Scripts.Task
string strName = m_pHost.GetName(); // assumes string; use ToString() if needed
return ret.Replace(SYMBOL_HOSTNAME, $"&{strName}&");
}
public bool GetAwardCandidates(uint ulTaskId, ref AWARD_DATA pAward)
{
ActiveTaskList pLst = GetActiveTaskList() as ActiveTaskList;
ActiveTaskEntry pEntry = pLst.GetEntry(ulTaskId);
if (pEntry == null || pEntry.m_ulTemplAddr == 0) return false;
uint ulCurTime = GetCurTime();
pEntry.GetTempl().CalcAwardData(
this,
ref pAward,
pEntry,
pEntry.m_ulTaskTime,
ulCurTime);
return true;
}
public uint GetTaskFinishedTime(uint value) { return 0; }
bool IsCaptain()
{
// TO DO: fix later
//CECTeam pTeam = m_pHost.GetTeam();
//if (!pTeam)
// return false;
//return pTeam.GetLeaderID() == m_pHost.GetCharacterID();
return true;
}
public bool CanFinishTask(uint ulTaskId)
{
ActiveTaskEntry pEntry = (GetActiveTaskList() as ActiveTaskList).GetEntry(ulTaskId);
if (pEntry == null)
return false;
ATaskTempl pTempl = pEntry.GetTempl();
if (pTempl == null)
return false;
if (pTempl.m_FixedData.m_bMarriage && !IsCaptain())
return false;
return pTempl.CanFinishTask(this, pEntry, GetCurTime());
}
public bool CanShowTask(uint ulTaskId)
{
ATaskTempl pTempl = GetTaskTemplMan().GetTopTaskByID(ulTaskId);
return pTempl != null && pTempl.CanShowTask(this);
}
public void SetFinishDlgShowTime(int t) { m_tmFinishDlgShown = t; }
public void OnUIDialogEnd(uint ulTask)
{
SetFinishDlgShowTime(0);
ActiveTaskList pLst = GetActiveTaskList() as ActiveTaskList;
ActiveTaskEntry pEntry = pLst.GetEntry(ulTask);
if (pEntry == null || pEntry.m_ulTemplAddr == 0) return;
//ATaskTempl pTempl = (pEntry.m_ulTemplAddr) as ATaskTempl;
ATaskTempl pTempl = GetTaskTemplMan().GetTaskTemplByID(pEntry.m_ulTemplAddr);
switch (pTempl.m_FixedData.m_enumMethod)
{
case (uint)TaskCompletionMethod.enumTMReachSite:
pTempl.IncValidCount();
_notify_svr(this, 3, (ushort)ulTask); //TASK_CLT_NOTIFY_REACH_SITE = 3
break;
}
}
public void GiveUpTask(uint ulTaskId)
{
ActiveTaskEntry pEntry = (GetActiveTaskList() as ActiveTaskList).GetEntry(ulTaskId);
if (pEntry == null || pEntry.GetTempl() == null) return;
_notify_svr(this, 2, (ushort)(pEntry.GetTempl().GetTopTask().GetID())); //TASK_CLT_NOTIFY_CHECK_GIVEUP = 2
}
void _notify_svr(TaskInterface pTask, byte uReason, ushort uTaskID)
{
}
public bool IsTaskReadyToConfirm(int iTaskID)
{
@@ -82,6 +82,8 @@ namespace BrewMonster.Scripts.Task
bool IsKing();
bool IsInTeam();
uint GetAccountTotalCash();
uint GetCurTime();
void SetFinishDlgShowTime(int t);
void NotifyServer(ref task_notify_base pBuf, uint sz);
bool CheckVersion();
StorageTaskList GetStorageTaskList();
+68 -60
View File
@@ -143,43 +143,43 @@ namespace PerfectWorld.Scripts.Task
}
return null;
}
// const ATaskTempl* GetCap() const { return reinterpret_cast<const ATaskTempl*>(m_ulCapTemplAddr); }
// const ATaskTempl* GetCapOrSelf() const
// {
// if (m_ulCapTemplAddr) return GetCap();
// else return GetTempl();
// }
// bool HasParent() const { return m_ParentIndex != 0xff; }
// bool HasChildren() const { return m_ChildIndex != 0xff; }
// bool IsValid(unsigned char uIndex, unsigned char uMaxCount) const
// {
// if (m_ParentIndex != 0xff)
// {
// if (m_ParentIndex >= uIndex || m_ParentIndex >= uMaxCount)
// return false;
// }
//
// if (m_PrevSblIndex != 0xff)
// {
// if (m_PrevSblIndex >= uIndex || m_PrevSblIndex >= uMaxCount)
// return false;
// }
//
// if (m_NextSblIndex != 0xff)
// {
// if (m_NextSblIndex <= uIndex || m_NextSblIndex >= uMaxCount)
// return false;
// }
//
// if (m_ChildIndex != 0xff)
// {
// if (m_ChildIndex <= uIndex || m_ChildIndex >= uMaxCount)
// return false;
// }
//
// return true;
// }
};
// const ATaskTempl* GetCap() const { return reinterpret_cast<const ATaskTempl*>(m_ulCapTemplAddr); }
// const ATaskTempl* GetCapOrSelf() const
// {
// if (m_ulCapTemplAddr) return GetCap();
// else return GetTempl();
// }
// bool HasParent() const { return m_ParentIndex != 0xff; }
// bool HasChildren() const { return m_ChildIndex != 0xff; }
// bool IsValid(unsigned char uIndex, unsigned char uMaxCount) const
// {
// if (m_ParentIndex != 0xff)
// {
// if (m_ParentIndex >= uIndex || m_ParentIndex >= uMaxCount)
// return false;
// }
//
// if (m_PrevSblIndex != 0xff)
// {
// if (m_PrevSblIndex >= uIndex || m_PrevSblIndex >= uMaxCount)
// return false;
// }
//
// if (m_NextSblIndex != 0xff)
// {
// if (m_NextSblIndex <= uIndex || m_NextSblIndex >= uMaxCount)
// return false;
// }
//
// if (m_ChildIndex != 0xff)
// {
// if (m_ChildIndex <= uIndex || m_ChildIndex >= uMaxCount)
// return false;
// }
//
// return true;
// }
};
public class ActiveTaskList
{
@@ -421,27 +421,35 @@ namespace PerfectWorld.Scripts.Task
}
}
}
// void ClearChildrenOf(TaskInterface* pTask, ActiveTaskEntry* pParent, bool bRemoveItem = true);
// ActiveTaskEntry* GetEntry(unsigned long ulId)
// {
// for (unsigned char i = 0; i < m_uTaskCount; i++)
// if (m_TaskEntries[i].m_ID == ulId)
// return &m_TaskEntries[i];
//
// return NULL;
// }
// void RemoveAll()
// {
// unsigned short ver = m_Version;
// memset(this, 0, sizeof(*this));
// m_Version = ver;
// }
// bool IsValid() const { return m_uTaskCount <= TASK_ACTIVE_LIST_MAX_LEN; }
// bool IsTimeMarkUpdate() const { return (m_uListState & TLIST_STATE_UPDATE_TIME_MARK) != 0; }
// void SetTimeMarkUpdate() { m_uListState |= TLIST_STATE_UPDATE_TIME_MARK; }
// void ClearTimeMarkUpdate() { m_uListState &= ~TLIST_STATE_UPDATE_TIME_MARK; }
// int GetMaxSimultaneousCount() {return m_uMaxSimultaneousCount ? TASK_MAX_SIMULTANEOUS_COUT : TASK_DEFAULT_MAX_SIMULTANEOUS_COUT;}
// void ExpandMaxSimultaneousCount() {m_uMaxSimultaneousCount = 1;}
};
public ActiveTaskEntry GetEntry(uint ulId)
{
for (int i = 0; i < m_uTaskCount; i++)
if (m_TaskEntries[i].m_ID == ulId)
return m_TaskEntries[i];
return null;
}
// void ClearChildrenOf(TaskInterface* pTask, ActiveTaskEntry* pParent, bool bRemoveItem = true);
// ActiveTaskEntry* GetEntry(unsigned long ulId)
// {
// for (unsigned char i = 0; i < m_uTaskCount; i++)
// if (m_TaskEntries[i].m_ID == ulId)
// return &m_TaskEntries[i];
//
// return NULL;
// }
// void RemoveAll()
// {
// unsigned short ver = m_Version;
// memset(this, 0, sizeof(*this));
// m_Version = ver;
// }
// bool IsValid() const { return m_uTaskCount <= TASK_ACTIVE_LIST_MAX_LEN; }
// bool IsTimeMarkUpdate() const { return (m_uListState & TLIST_STATE_UPDATE_TIME_MARK) != 0; }
// void SetTimeMarkUpdate() { m_uListState |= TLIST_STATE_UPDATE_TIME_MARK; }
// void ClearTimeMarkUpdate() { m_uListState &= ~TLIST_STATE_UPDATE_TIME_MARK; }
// int GetMaxSimultaneousCount() {return m_uMaxSimultaneousCount ? TASK_MAX_SIMULTANEOUS_COUT : TASK_DEFAULT_MAX_SIMULTANEOUS_COUT;}
// void ExpandMaxSimultaneousCount() {m_uMaxSimultaneousCount = 1;}
};
}
@@ -606,13 +606,13 @@ namespace BrewMonster.Scripts.Task
// const wchar_t* GetDescription() const { assert(m_pwstrDescript); return (wchar_t*)m_pwstrDescript; }
// const wchar_t* GetOkText() const { assert(m_pwstrOkText); return (wchar_t*)m_pwstrOkText; }
// const wchar_t* GetNoText() const { assert(m_pwstrNoText); return (wchar_t*)m_pwstrNoText; }
// const wchar_t* GetTribute() const { assert(m_pwstrTribute); return (wchar_t*)m_pwstrTribute; }
public ushort[] GetTribute() { return m_pwstrTribute; }
//
// const talk_proc* GetDeliverTaskTalk() const { return &m_DelvTaskTalk; }
// const talk_proc* GetUnqualifiedTalk() const { return &m_UnqualifiedTalk; }
// const talk_proc* GetDeliverItemTalk() const { return &m_DelvItemTalk; }
// const talk_proc* GetUnfinishedTalk() const { return &m_ExeTalk; }
// const talk_proc* GetAwardTalk() const { return &m_AwardTalk; }
public talk_proc GetDeliverTaskTalk() { return m_DelvTaskTalk; }
public talk_proc GetUnqualifiedTalk() { return m_UnqualifiedTalk; }
public talk_proc GetDeliverItemTalk() { return m_DelvItemTalk; }
public talk_proc GetUnfinishedTalk() { return m_ExeTalk; }
public talk_proc GetAwardTalk() { return m_AwardTalk; }
//
public uint GetDeliverNPC() { return m_FixedData.m_ulDelvNPC; }
public uint GetAwardNPC() { return m_FixedData.m_ulAwardNPC; }
+150 -16
View File
@@ -408,7 +408,7 @@ namespace BrewMonster.Scripts.Task
public struct ITEM_WANTED
{
public uint m_ulItemTemplId;
// when check bool -> m_bCommonItem > 0 == true
// when check bool . m_bCommonItem > 0 == true
[MarshalAs(UnmanagedType.U1)]
public bool m_bCommonItem;
public uint m_ulItemNum;
@@ -1395,6 +1395,22 @@ namespace BrewMonster.Scripts.Task
public byte m_uValidCount;
private uint m_ulMask; // 任务掩码 // Task mask
/* ÈÎÎñ½áÊøºóµÄ½±Àø */
uint m_ulAwardType_S;
uint m_ulAwardType_F;
// ʱ¼äÏÞÖÆ
uint m_ulTimeLimit;
/* ÆÕͨºÍ°´Ã¿¸ö·½Ê½ */
AWARD_DATA m_Award_S = new AWARD_DATA(); /* ³É¹¦ */
AWARD_DATA m_Award_F = new AWARD_DATA(); /* ʧ°Ü */
/* ʱ¼ä±ÈÀý·½Ê½ */
AWARD_RATIO_SCALE m_AwByRatio_S;
AWARD_RATIO_SCALE m_AwByRatio_F;
/* °´»ñµÃÎï±ÈÀý·½Ê½ */
AWARD_ITEMS_SCALE m_AwByItems_S;
AWARD_ITEMS_SCALE m_AwByItems_F;
public bool LoadFromBinFile(FileStream fp)
{
LoadBinary(fp);
@@ -1416,7 +1432,7 @@ namespace BrewMonster.Scripts.Task
if (pTask == null || pEntry == null) break;
if (!pTask.IsDeliverLegal()) break;
// 已完成直接返回 // Already finished -> true
// 已完成直接返回 // Already finished . true
if (pEntry.IsFinished())
{
ret = true;
@@ -1665,7 +1681,7 @@ namespace BrewMonster.Scripts.Task
// ATaskTempl* pSub = new ATaskTempl;
// g_ulNewCount++;
// AddSubTaskTempl(pSub);
// pSub->LoadBinary(fp);
// pSub.LoadBinary(fp);
// }
// 上述C++逻辑的C#实现 // C# implementation of the above C++ logic
if (m_nSubCount > 0)
@@ -2320,7 +2336,7 @@ namespace BrewMonster.Scripts.Task
fixedData.m_ulMutexTasks = AAssit.ReadArrayFromBinary<uint>(fp, TaskTemplConstants.MAX_MUTEX_TASK_COUNT, ref readBytes);
logContent += $"m_ulMutexTasks[0..{TaskTemplConstants.MAX_MUTEX_TASK_COUNT - 1}] loaded\n\n";
// Living skills levels (C++ long -> 4 bytes). Read as int and widen to long
// Living skills levels (C++ long . 4 bytes). Read as int and widen to long
var skillLevelsInt = AAssit.ReadArrayFromBinary<int>(fp, TaskTemplConstants.MAX_LIVING_SKILLS, ref readBytes);
fixedData.m_lSkillLev = Array.ConvertAll(skillLevelsInt, v => (long)v);
logContent += $"m_lSkillLev[0..{TaskTemplConstants.MAX_LIVING_SKILLS - 1}] loaded\n\n";
@@ -3283,12 +3299,12 @@ namespace BrewMonster.Scripts.Task
ad.m_ulCandItems = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulCandItems: {ad.m_ulCandItems} \n";
fp.Seek(4, SeekOrigin.Current); // C++: AWARD_ITEMS_CAND* m_CandItems; skip pointer address
logContent += $"skip 4 bytes -> AWARD_ITEMS_CAND* m_CandItems \n";
logContent += $"skip 4 bytes . AWARD_ITEMS_CAND* m_CandItems \n";
ad.m_ulSummonedMonsters = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulSummonedMonsters: {ad.m_ulSummonedMonsters} \n";
fp.Seek(4, SeekOrigin.Current); // C++: AWARD_MONSTERS_SUMMONED* m_SummonedMonsters; skip pointer address
logContent += $"skip 4 bytes -> AWARD_MONSTERS_SUMMONED* m_SummonedMonsters \n";
logContent += $"skip 4 bytes . AWARD_MONSTERS_SUMMONED* m_SummonedMonsters \n";
ad.m_bAwardDeath = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
logContent += $"m_bAwardDeath: {ad.m_bAwardDeath} \n";
@@ -3327,7 +3343,7 @@ namespace BrewMonster.Scripts.Task
ad.m_ulPQRankingAwardCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulPQRankingAwardCnt: {ad.m_ulPQRankingAwardCnt} \n";
fp.Seek(4, SeekOrigin.Current); // C++: AWARD_PQ_RANKING* m_PQRankingAward; skip pointer address
logContent += $"skip 4 bytes -> AWARD_PQ_RANKING* m_PQRankingAward \n";
logContent += $"skip 4 bytes . AWARD_PQ_RANKING* m_PQRankingAward \n";
// Change global key/value arrays (pointers to basic types)
ad.m_ulChangeKeyCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
@@ -3335,7 +3351,7 @@ namespace BrewMonster.Scripts.Task
fp.Seek(4, SeekOrigin.Current); // C++: long* m_plChangeKey; skip sizeof(long)
fp.Seek(4, SeekOrigin.Current); // C++: long* m_plChangeKeyValue; skip sizeof(long)
fp.Seek(4, SeekOrigin.Current); // C++: bool* m_pbChangeType; skip sizeof(bool)
logContent += $"skip 4 pointers -> m_plChangeKey(4) \n m_plChangeKeyValue(4) \n m_pbChangeType(4) \n";
logContent += $"skip 4 pointers . m_plChangeKey(4) \n m_plChangeKeyValue(4) \n m_pbChangeType(4) \n";
// Modify historical progress
ad.m_ulHistoryChangeCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
@@ -3344,7 +3360,7 @@ namespace BrewMonster.Scripts.Task
fp.Seek(4, SeekOrigin.Current); // C++: long* m_plHistoryChangeKey
fp.Seek(4, SeekOrigin.Current); // C++: long* m_plHistoryChangeKeyValue
fp.Seek(4, SeekOrigin.Current); // C++: bool* m_pbHistoryChangeType
logContent += $"skip pointers -> m_plHistoryChangeKey(4) \n m_plHistoryChangeKeyValue(4) \n m_pbHistoryChangeType(4) \n";
logContent += $"skip pointers . m_plHistoryChangeKey(4) \n m_plHistoryChangeKeyValue(4) \n m_pbHistoryChangeType(4) \n";
// Multiplier
ad.m_bMulti = AAssit.ReadFromBinaryOf<byte>(fp, ref readBytes) > 0;
@@ -3358,21 +3374,21 @@ namespace BrewMonster.Scripts.Task
ad.m_ulDisplayKeyCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulDisplayKeyCnt: {ad.m_ulDisplayKeyCnt} \n";
fp.Seek(4, SeekOrigin.Current); // C++: long* m_plDisplayKey
logContent += $"skip 4 bytes -> long* m_plDisplayKey \n";
logContent += $"skip 4 bytes . long* m_plDisplayKey \n";
// Display global variable expressions
ad.m_ulExpCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulExpCnt: {ad.m_ulExpCnt} \n";
fp.Seek(4, SeekOrigin.Current); // C++: char (*m_pszExp)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN]
fp.Seek(4, SeekOrigin.Current); // C++: TASK_EXPRESSION (*m_pExpArr)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN]
logContent += $"skip 4 bytes -> m_pszExp(row ptr) \n";
logContent += $"skip 4 bytes -> m_pExpArr(row ptr) \n";
logContent += $"skip 4 bytes . m_pszExp(row ptr) \n";
logContent += $"skip 4 bytes . m_pExpArr(row ptr) \n";
// Display global variable expression prompt strings
ad.m_ulTaskCharCnt = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulTaskCharCnt: {ad.m_ulTaskCharCnt} \n";
fp.Seek(4, SeekOrigin.Current); // C++: task_char (*m_pTaskChar)[TASK_AWARD_MAX_DISPLAY_CHAR_LEN]
logContent += $"skip 4 bytes -> task_char (*m_pTaskChar)[LEN] \n";
logContent += $"skip 4 bytes . task_char (*m_pTaskChar)[LEN] \n";
// Force-related
ad.m_iForceContribution = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
@@ -3389,7 +3405,7 @@ namespace BrewMonster.Scripts.Task
ad.m_ulTitleNum = AAssit.ReadFromBinaryOf<uint>(fp, ref readBytes);
logContent += $"m_ulTitleNum: {ad.m_ulTitleNum} \n";
fp.Seek(4, SeekOrigin.Current); // C++: TITLE_AWARD* m_pTitleAward
logContent += $"skip 4 bytes -> TITLE_AWARD* m_pTitleAward \n";
logContent += $"skip 4 bytes . TITLE_AWARD* m_pTitleAward \n";
ad.m_iLeaderShip = AAssit.ReadFromBinaryOf<int>(fp, ref readBytes);
logContent += $"m_iLeaderShip: {ad.m_iLeaderShip} \n";
@@ -3416,7 +3432,7 @@ namespace BrewMonster.Scripts.Task
if (ad.m_ulSummonedMonsters > 0)
{
//C++: ad.m_SummonedMonsters->m_ulMonsterNum = ad.m_ulSummonedMonsters;
//C++: ad.m_SummonedMonsters.m_ulMonsterNum = ad.m_ulSummonedMonsters;
ad.m_SummonedMonsters.m_ulMonsterNum = ad.m_ulSummonedMonsters;
LoadAwardMonstersBin(fp, ref ad.m_SummonedMonsters, ulVersion, ref readBytes);
}
@@ -3425,7 +3441,7 @@ namespace BrewMonster.Scripts.Task
if (ad.m_ulPQRankingAwardCnt > 0)
{
// C++: ad.m_PQRankingAward->m_ulRankingAwardNum = ad.m_ulPQRankingAwardCnt;
// C++: ad.m_PQRankingAward.m_ulRankingAwardNum = ad.m_ulPQRankingAwardCnt;
ad.m_PQRankingAward.m_ulRankingAwardNum = ad.m_ulPQRankingAwardCnt;
LoadAwardPQRankingBin(fp, ref ad.m_PQRankingAward, ulVersion, ref readBytes);
}
@@ -4210,5 +4226,123 @@ namespace BrewMonster.Scripts.Task
unchecked { m_uDepth += uDepthLocal; }
}
public void CalcAwardData(
TaskInterface pTask,
ref AWARD_DATA pAward,
ActiveTaskEntry pEntry,
uint ulTaskTime,
uint ulCurTime)
{
var ulType = (pEntry.IsSuccess() ? m_ulAwardType_S : m_ulAwardType_F);
switch (ulType)
{
case (uint)TaskAwardType.enumTATNormal:
case (uint)TaskAwardType.enumTATEach:
pAward = (pEntry.IsSuccess() ? m_Award_S : m_Award_F);
break;
case (uint)TaskAwardType.enumTATRatio:
CalcAwardDataByRatio(ref pAward, pEntry, ulTaskTime, ulCurTime);
break;
case (uint)TaskAwardType.enumTATItemCount:
CalcAwardDataByItems(pTask, ref pAward, pEntry);
break;
default:
break;
}
}
public void CalcAwardDataByRatio(
ref AWARD_DATA pAward,
ActiveTaskEntry pEntry,
uint ulTaskTime,
uint ulCurTime)
{
if (m_ulTimeLimit == 0) return;
AWARD_RATIO_SCALE p = (pEntry.IsSuccess() ? m_AwByRatio_S : m_AwByRatio_F);
float ratio = (float)(ulCurTime - ulTaskTime) / m_ulTimeLimit;
uint i;
for (i = 0; i<p.m_ulScales; i++)
{
if (ratio <= p.m_Ratios[i])
{
pAward = p.m_Awards[i];
return;
}
}
}
public void CalcAwardDataByItems(
TaskInterface pTask,
ref AWARD_DATA pAward,
ActiveTaskEntry pEntry)
{
AWARD_ITEMS_SCALE p = (pEntry.IsSuccess() ? m_AwByItems_S : m_AwByItems_F);
uint ulCount = (uint)pTask.GetTaskItemCount(p.m_ulItemId), i;
for (i = 0; i < p.m_ulScales; i++)
{
if (ulCount >= p.m_Counts[i])
{
pAward = p.m_Awards[i];
return;
}
}
}
public bool CanShowTask(TaskInterface pTask)
{
uint ulCurTime = pTask.GetCurTime();
if (m_pParent != null
|| (pTask.GetActiveTaskList() as ActiveTaskList).GetEntry(GetID()) != null
|| CheckTimetable(ulCurTime) > 0
|| CheckDeliverTime(pTask, ulCurTime) > 0
|| CheckFnshLst(pTask, ulCurTime) > 0
|| CheckMutexTask(pTask, ulCurTime) > 0
|| CheckLivingSkill(pTask) > 0
|| CheckSpecialAward(pTask) > 0
|| CheckGlobalKeyValue(pTask, false) > 0)
return false;
uint ulRet;
if (m_FixedData.m_bShowByDeposit && CheckDeposit(pTask) > 0) return false;
if (m_FixedData.m_bShowByGender && CheckGender(pTask) > 0) return false;
if (m_FixedData.m_bShowByItems && CheckItems(pTask) > 0) return false;
ulRet = CheckLevel(pTask);
if (ulRet == TaskInterfaceConstants.TASK_PREREQU_FAIL_ABOVE_LEVEL || (m_FixedData.m_bShowByLev && ulRet > 0)) return false;
if (m_FixedData.m_bShowByTransformed && CheckTransform(pTask) > 0) return false;
if (m_FixedData.m_bShowByForce && CheckForce(pTask) > 0) return false;
if (m_FixedData.m_bShowByForceActivityLevel && CheckForceActivityLevel(pTask) > 0) return false;
if (m_FixedData.m_bShowByForceExp && CheckExp(pTask) > 0) return false;
if (m_FixedData.m_bShowByForceSP && CheckSP(pTask) > 0) return false;
if (m_FixedData.m_bShowByForceContribution && CheckForceContribution(pTask) > 0) return false;
if (m_FixedData.m_bShowByForceReputation && CheckForceReputation(pTask) > 0) return false;
if (m_FixedData.m_bShowByNeedRecordTasksNum && CheckRecordTasksNum(pTask) > 0) return false;
if (m_FixedData.m_bShowByFactionContrib && CheckFactionContrib(pTask) > 0) return false;
if (m_FixedData.m_bShowByOccup && CheckOccupation(pTask) > 0) return false;
if (m_FixedData.m_bShowByPreTask && CheckPreTask(pTask) > 0) return false;
if (m_FixedData.m_bShowByRepu && CheckRepu(pTask) > 0) return false;
if (m_FixedData.m_bShowByTeam && CheckTeamTask(pTask) > 0) return false;
if (m_FixedData.m_bShowByFaction && CheckFaction(pTask) > 0) return false;
if (m_FixedData.m_bShowByPeriod && CheckPeriod(pTask) > 0) return false;
if (m_FixedData.m_bShowByCharTime && CheckCharTime(pTask) > 0) return false;
if (m_FixedData.m_bShowByRMB && CheckAccountRMB(pTask) > 0) return false;
if (m_FixedData.m_bShowByWeddingOwner && CheckWeddingOwner(pTask) > 0) return false;
if (m_FixedData.m_bShowByKing && CheckKing(pTask) > 0) return false;
if (m_FixedData.m_bShowByNotInTeam && CheckNotInTeam(pTask) > 0) return false;
if (m_FixedData.m_bShowByReincarnation && CheckReincarnation(pTask) > 0) return false;
if (m_FixedData.m_bShowByRealmLevel && (CheckRealmLevel(pTask) > 0 || CheckRealmExpFull(pTask) > 0)) return false;
if (m_FixedData.m_bShowByGeneralCard && CheckCardCollection(pTask) > 0) return false;
if (m_FixedData.m_bShowByGeneralCardRank && CheckCardRankCount(pTask) > 0) return false;
if (m_FixedData.m_bShowByHistoryStage && CheckHistoryStage(pTask) > 0) return false;
return true;
}
public uint GetType() { return m_FixedData.m_ulType; }
}
}
@@ -12,6 +12,7 @@ namespace BrewMonster.UI
protected Canvas m_canvas;
protected Dictionary<int, string> m_StringTable = new Dictionary<int, string>();
protected Dictionary<int, string> m_auiDialog_stringTable = new Dictionary<int, string>();
protected Dictionary<string, AUIDialog> m_DlgName = new Dictionary<string, AUIDialog>();
public string GetStringFromTable(int idString)
{
@@ -254,5 +255,14 @@ namespace BrewMonster.UI
}
return true;
}
public AUIDialog GetDialog(string pszName)
{
if(m_DlgName.TryGetValue(pszName, out AUIDialog dlg))
{
return dlg;
}
return null;
}
}
}
@@ -70,7 +70,6 @@ namespace BrewMonster.UI
return str;
}
public AUIManager GetAUIManager()
{
return m_pAUIManager;
@@ -80,5 +79,25 @@ namespace BrewMonster.UI
{
m_pAUIManager = pAUIManager;
}
public virtual void OnEnable()
{
}
public virtual void OnDisable()
{
}
public virtual void Awake()
{
}
public virtual void Start()
{
}
}
}
@@ -15,6 +15,7 @@ namespace BrewMonster.UI
List<ItemUIListBox> m_Item = new List<ItemUIListBox>();
int m_nCurSel = 0;
Action<int> m_OnClickBtn = null;
const uint AUILISTBOX_ERROR = 0xFFFFFFFF; // same as -1 for uint
public void ResetContent()
@@ -28,6 +29,11 @@ namespace BrewMonster.UI
content.sizeDelta = Vector2.zero;
}
public void SetActionOnClickBtnItem(Action<int> onClick)
{
m_OnClickBtn = onClick;
}
public void AddString(string pszString)
{
ItemUIListBox item = Instantiate(prefabItemUIListBox, content);
@@ -47,6 +53,8 @@ namespace BrewMonster.UI
return -1;
m_Item[nIndex].strDataName[nSubIndex] = strName;
m_Item[nIndex].dwData[nSubIndex] = dwItemData;
m_Item[nIndex].SetActOnClickBtn(m_OnClickBtn, nIndex);
return nIndex;
}
@@ -59,9 +67,37 @@ namespace BrewMonster.UI
m_Item[nIndex].strDataPtrName[nSubIndex] = strName;
m_Item[nIndex].pvData[nSubIndex] = pData;
m_Item[nIndex].SetActOnClickBtn(m_OnClickBtn, nIndex);
return nIndex;
}
public int SetItemData64(int nIndex, ulong pData, int nSubIndex = 0, string strName = "")
{
if (nIndex < 0 || nIndex >= (m_Item.Count))
return -1;
if (nSubIndex < 0 || nSubIndex >= 20) // #define AUILISTBOX_DATA_NUM AUILISTBOX_MAX_COLUMN 20
return -1;
m_Item[nIndex].strData64Name[nSubIndex] = strName;
m_Item[nIndex].uiData64[nSubIndex] = pData;
m_Item[nIndex].SetActOnClickBtn(m_OnClickBtn, nIndex);
return nIndex;
}
public ulong GetItemData64(int nIndex, int nSubIndex, string strName)
{
if (nIndex < 0 || nIndex >= (m_Item.Count))
return AUILISTBOX_ERROR;
if (nSubIndex < 0 || nSubIndex >= 20) // AUILISTBOX_DATA_NUM 20
return AUILISTBOX_ERROR;
//if (0 != m_Item[nIndex].uiData64[nSubIndex] && strName != m_Item[nIndex].strData64Name[nSubIndex])
// AUI_ReportError(__LINE__, 1, "AUIListBox::GetItemData64(), data name not match");
return m_Item[nIndex].uiData64[nSubIndex];
}
public int GetCount()
{
return m_Item.Count;
@@ -111,5 +147,20 @@ namespace BrewMonster.UI
else
return m_Item[nIndex].strText;
}
//public int SetItemTextColor(int nIndex, A3DCOLOR color, int nItem)
//{
// if (nIndex < 0 || nIndex >= int(m_Item.size()))
// return AUILISTBOX_ERROR;
// UpdateRenderTarget();
// if (nItem >= 0)
// m_Item[nIndex].color[nItem] = color;
// else
// for (int i = 0; i < max(1, m_nNumColumns); i++)
// m_Item[nIndex].color[i] = color;
// return nIndex;
//}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,7 @@
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace BrewMonster
{
@@ -9,15 +11,33 @@ namespace BrewMonster
public string[] strDataName = new string[20];
public string[] strDataPtrName = new string[20];
public string[] strData64Name = new string[20];
public ulong[] uiData64 = new ulong[20];
public uint[] dwData = new uint[20];
public object[] pvData = new object[20];
public int indexItem;
public string strText;
Button btnItem = null;
public void OnEnable()
{
if(btnItem == null)
{
btnItem = GetComponent<Button>();
}
}
public void SetText(string txt)
{
strText = txt;
txtItem.text = txt;
}
public void SetActOnClickBtn(Action<int> onClick, int index)
{
btnItem.onClick.RemoveAllListeners();
indexItem = index;
btnItem.onClick.AddListener(()=> { onClick?.Invoke(indexItem); });
}
}
}
@@ -14,6 +14,7 @@ namespace BrewMonster.UI
{
DlgNPC m_pDlgNPC;
public NPC_ESSENCE? m_pCurNPCEssence;
public int m_idCurFinishTask = -1;
public static bool TALKPROC_IS_TERMINAL(uint id)
{
+26
View File
@@ -418,7 +418,31 @@ MonoBehaviour:
-
-
-
strData64Name:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
uiData64: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
dwData: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
indexItem: 0
strText:
--- !u!1 &936487781243711958
GameObject:
m_ObjectHideFlags: 0
@@ -1371,6 +1395,8 @@ MonoBehaviour:
m_pTxt_npc: {fileID: 6706225607899780532}
m_pTxt_Content: {fileID: 8493998618141770687}
m_pLst_Main: {fileID: 4816029163115819860}
m_btnBack: {fileID: 6071484966713915762}
m_btnClose: {fileID: 1639099275032120166}
--- !u!1 &8376521380240807646
GameObject:
m_ObjectHideFlags: 0
+219 -91
View File
@@ -46,7 +46,7 @@ public partial class CECHostPlayer : CECPlayer
private int m_iJumpCount = 0;
private bool m_bJumpInWater = false;
public A3DVECTOR3 m_vVelocity; // Velocity
bool m_bChangingFace; // true, host is changing face
private int m_iRoleCreateTime;
private int m_iRoleLastLoginTime; // Role last login time
@@ -106,14 +106,14 @@ public partial class CECHostPlayer : CECPlayer
private BaseVfxObject m_pSelectedGFX;
private BaseVfxObject m_pHoverGFX;
// Cursor estimation optimization
private Vector2 m_lastMousePosition;
private float m_cursorUpdateTimer;
private const float CURSOR_UPDATE_INTERVAL = 0.05f; // 20 times per second instead of 60+
private UnityEngine.InputSystem.Mouse m_cachedMouse;
private UnityEngine.InputSystem.Keyboard m_cachedKeyboard;
public bool IsChangingFace() { return m_bChangingFace; }
// ===== Inventory packs (instance-based) =====
@@ -219,7 +219,7 @@ public partial class CECHostPlayer : CECPlayer
_playerStateMachine.InitState(_idleState);
// btnJump.onClick.AddListener(HandleJump);
// Cache input devices for better performance
m_cachedMouse = UnityEngine.InputSystem.Mouse.current;
m_cachedKeyboard = UnityEngine.InputSystem.Keyboard.current;
@@ -234,7 +234,7 @@ public partial class CECHostPlayer : CECPlayer
ApplySkillShortcut(1);
}
#endif
//Debug.Log($"(ulong)Time.deltaTime * 1000 {(ulong)(Time.deltaTime * 1000)}");
m_MoveCtrl.Tick((ulong)(Time.deltaTime * 1000));
// Nếu có thay đổi runtime, có thể lấy lại mỗi vài giây/Start nếu bạn thích:
@@ -354,10 +354,10 @@ public partial class CECHostPlayer : CECPlayer
}
}
m_pWorkMan?.Tick(Time.deltaTime);
// Update cursor based on what's under mouse
EstimateCursor();
// Update GFXs
UpdateGFXs(Time.deltaTime);
}
@@ -1182,23 +1182,23 @@ public partial class CECHostPlayer : CECPlayer
SetPos(new Vector3(pCmd.vPos.x, pCmd.vPos.y, pCmd.vPos.z));
}
private void OnMsgHstStartAttack(in ECMSG msg)
{
cmd_host_start_attack pCmd = GPDataTypeHelper.FromBytes<cmd_host_start_attack>((byte[])msg.dwParam1);
// ASSERT(pCmd);
// test code...
// g_pGame->GetRTDebug()->OutputNotifyMessage(RTDCOL_WARNING, _AL("start attack !"));
// g_pGame->GetRTDebug()->OutputNotifyMessage(RTDCOL_WARNING, _AL("start attack !"));
// Check whether target is the one that we have selected
if (m_idSelTarget != pCmd.idTarget)
{
BMLogger.Log("Target has changed !");
}
// If target turn to be un-attackable, cancel action
if (AttackableJudge(pCmd.idTarget, true)<=0)
if (AttackableJudge(pCmd.idTarget, true) <= 0)
{
UnityGameSession.c2s_CmdCancelAction();
BMLogger.Log("Cannel attacking !");
@@ -1221,54 +1221,54 @@ public partial class CECHostPlayer : CECPlayer
m_bMelee = true;
// AP_ActionEvent(AP_EVENT_STARTMELEE);
}
private void OnMsgHstStopAttack(in ECMSG Msg)
{
m_bMelee = false;
// if there is an attack event currently, we should let it fire now.
ClearComActFlagAllRankNodes(true);
cmd_host_stop_attack pCmd = GPDataTypeHelper.FromBytes<cmd_host_stop_attack>((byte[])Msg.dwParam1);
m_bMelee = false;
// if there is an attack event currently, we should let it fire now.
ClearComActFlagAllRankNodes(true);
/* If attack stopped for target is leave too far, trace it and continue
attacking. Stop reason defined as below:
cmd_host_stop_attack pCmd = GPDataTypeHelper.FromBytes<cmd_host_stop_attack>((byte[])Msg.dwParam1);
0x00: attack is canceled or host want to do some other things.
0x01: unable to attack anymore (no ammo, weapon is broken etc.)
0x02: invalid target (target missed or died)
0x04: target is out of range
*/
if ((pCmd.iReason & 0x04) !=0)
{
if (!m_pWorkMan.IsMovingToPosition() &&
!m_pWorkMan.IsTracing())
{
if (CmdNormalAttack(false, false, 0, -1)) //m_pComboSkill != NULL
{
// AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE, 1);
}
else
{
m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT);
// AP_ActionEvent(AP_EVENT_STOPMELEE);
}
}
else
{
// AP_ActionEvent(AP_EVENT_STOPMELEE);
}
}
else
{
m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT);
// AP_ActionEvent(AP_EVENT_STOPMELEE);
}
/* If attack stopped for target is leave too far, trace it and continue
attacking. Stop reason defined as below:
// #ifdef _SHOW_AUTOPOLICY_DEBUG
// a_LogOutput(1, "Stop Attack, Reason = %d", pCmd->iReason);
// #endif
0x00: attack is canceled or host want to do some other things.
0x01: unable to attack anymore (no ammo, weapon is broken etc.)
0x02: invalid target (target missed or died)
0x04: target is out of range
*/
if ((pCmd.iReason & 0x04) != 0)
{
if (!m_pWorkMan.IsMovingToPosition() &&
!m_pWorkMan.IsTracing())
{
if (CmdNormalAttack(false, false, 0, -1)) //m_pComboSkill != NULL
{
// AP_ActionEvent(AP_EVENT_MELEEOUTOFRANGE, 1);
}
else
{
m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT);
// AP_ActionEvent(AP_EVENT_STOPMELEE);
}
}
else
{
// AP_ActionEvent(AP_EVENT_STOPMELEE);
}
}
else
{
m_pWorkMan.FinishRunningWork(Host_work_ID.WORK_HACKOBJECT);
// AP_ActionEvent(AP_EVENT_STOPMELEE);
}
// #ifdef _SHOW_AUTOPOLICY_DEBUG
// a_LogOutput(1, "Stop Attack, Reason = %d", pCmd->iReason);
// #endif
}
private void OnMsgHstChangeFace(in ECMSG Msg)
{
var param2 = Convert.ToInt32(Msg.dwParam2);
@@ -1304,7 +1304,7 @@ public partial class CECHostPlayer : CECPlayer
// CECIvtrItem* pItem = m_pPack->GetItem(pCmd->ivtr_idx);
// if (pItem)
// pItem->Freeze(false);
StopChangeFace();
// pClipboard->EraseData(CECClipboard::DATA_CUSTOMDATA);
//
@@ -1427,7 +1427,7 @@ public partial class CECHostPlayer : CECPlayer
{
return;
}
LoadGfx();
}
@@ -1436,10 +1436,10 @@ public partial class CECHostPlayer : CECPlayer
// Load GFX
var gfxCaster = EC_Game.GetGFXCaster();
// m_pMoveTargetGFX = g_pGame->GetGFXCaster()->LoadGFXEx(res_GFXFile(RES_GFX_MOVETARGET));
m_pSelectedGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_CURSORHOVER));//RES_GFX_SELECTED
m_pHoverGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_CURSORHOVER));
m_pSelectedGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_CURSORHOVER));//RES_GFX_SELECTED
m_pHoverGFX = await gfxCaster.LoadGFXEx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_CURSORHOVER));
// m_pFloatDust = g_pGame->GetGFXCaster()->LoadGFXEx(res_GFXFile(RES_GFX_FLOATING_DUST));
if (true /*CECUIConfig::Instance().GetGameUI().bEnableActionSwitch*/)
{
m_pActionSwitcher = new CECActionSwitcher(this);
@@ -2700,7 +2700,7 @@ public partial class CECHostPlayer : CECPlayer
public FACTION_FORTRESS_CONFIG GetFactionFortressConfig()
{
elementdataman pDataMan = EC_Game.GetElementDataMan();
elementdataman pDataMan = ElementDataManProvider.GetElementDataMan();
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var ob = pDataMan.get_data_ptr(854, ID_SPACE.ID_SPACE_CONFIG, ref dt);
FACTION_FORTRESS_CONFIG pConfig = new FACTION_FORTRESS_CONFIG();
@@ -2744,11 +2744,11 @@ public partial class CECHostPlayer : CECPlayer
m_bIsInKingService = false;
//m_pOffShopCtrl.SetNPCSevFlag(COfflineShopCtrl::NPCSEV_NULL);
}
void UpdateGFXs(float dwDeltaTime)
void UpdateGFXs(float dwDeltaTime)
{
// if (m_pLevelUpGFX)
// m_pLevelUpGFX->SetParentTM(GetAbsoluteTM());
// if (m_pLevelUpGFX)
// m_pLevelUpGFX->SetParentTM(GetAbsoluteTM());
if (m_pHoverGFX)// && m_idCurHover != m_idSelTarget)
{
@@ -2811,7 +2811,7 @@ public partial class CECHostPlayer : CECPlayer
// }
// UpdateMonsterSpiritGfx(dwDeltaTime);
}
// Level up
public void LevelUp()
{
@@ -2823,10 +2823,10 @@ public partial class CECHostPlayer : CECPlayer
// // Get all extend properties
// pSession->c2s_CmdGetExtProps();
// if (m_pLevelUpGFX)
// m_pLevelUpGFX->Start(true);
PlayGfx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_LEVELUP), null, 1f,1);//PLAYERMODEL_TYPEALL
// if (m_pLevelUpGFX)
// m_pLevelUpGFX->Start(true);
PlayGfx(EC_Resource.res_GFXFile((int)GfxResourceType.RES_GFX_LEVELUP), null, 1f, 1);//PLAYERMODEL_TYPEALL
// // Popup notify bubble text
// BubbleText(BUBBLE_LEVELUP, 0);
//
@@ -2859,7 +2859,7 @@ public partial class CECHostPlayer : CECPlayer
// ((CDlgOnlineAward*)pGameUI->GetDialog("Win_AddExp2"))->RestartWhenLevelup();
// }
}
// Estimate mouse cursor
private void EstimateCursor()
{
@@ -2867,50 +2867,50 @@ public partial class CECHostPlayer : CECPlayer
if (m_cursorUpdateTimer < CURSOR_UPDATE_INTERVAL)
return;
m_cursorUpdateTimer = 0f;
// Early exit checks
if (IsChangingFace() || mainCam == null || m_cachedMouse == null)
{
m_idCurHover = 0;
return;
}
// Get mouse position using cached device
Vector2 mousePosition = m_cachedMouse.position.ReadValue();
// Early exit if mouse hasn't moved significantly (2 pixel threshold)
if (Vector2.Distance(mousePosition, m_lastMousePosition) < 2f)
return;
m_lastMousePosition = mousePosition;
m_idCurHover = 0;
CursorType cursorType = CursorType.RES_CUR_NORMAL;
// Check modifier keys using cached keyboard
bool isShiftPressed = m_cachedKeyboard != null &&
bool isShiftPressed = m_cachedKeyboard != null &&
(m_cachedKeyboard.leftShiftKey.isPressed || m_cachedKeyboard.rightShiftKey.isPressed);
Ray ray = mainCam.ScreenPointToRay(mousePosition);
RaycastHit hit;
// You can add a layer mask here to only raycast against specific layers
// LayerMask interactableMask = LayerMask.GetMask("NPC", "Player", "Item");
// if (Physics.Raycast(ray, out hit, 100f, interactableMask))
if (Physics.Raycast(ray, out hit, 1000f)) // Reduced from 1000f to 100f for better performance
{
// Try to get CECObject component (cached lookup)
CECObject hitObject = hit.collider.GetComponent<CECObject>();
if (hitObject != null)
{
int idHitObject = CECObject.GetObjectID(hitObject);
if (idHitObject != 0)
{
bool bForceAttack = isShiftPressed;
// Check object type and set appropriate cursor
if (GPDataTypeHelper.ISNPCID(idHitObject))
{
@@ -2919,7 +2919,7 @@ public partial class CECHostPlayer : CECPlayer
if (pNPC != null && !pNPC.IsDead())
{
m_idCurHover = idHitObject;
if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1)
{
cursorType = CursorType.RES_CUR_ATTACK;
@@ -2940,7 +2940,7 @@ public partial class CECHostPlayer : CECPlayer
if (pPlayer != null)
{
m_idCurHover = idHitObject;
if (m_idSelTarget == idHitObject && AttackableJudge(idHitObject, bForceAttack) == 1)
{
cursorType = CursorType.RES_CUR_ATTACK;
@@ -2967,11 +2967,11 @@ public partial class CECHostPlayer : CECPlayer
}
}
}
// Apply cursor change
EC_Game.ChangeCursor((int)cursorType);
}
// Start normal attacking to selected target
private bool CmdNormalAttack(bool bMoreClose/* false */, bool bCombo/* false */,
int idTarget/* 0 */, int iForceAtk/* -1 */)
@@ -2992,9 +2992,9 @@ public partial class CECHostPlayer : CECPlayer
// return false;
// if (!bCombo)
// ClearComboSkill();
// ClearComboSkill();
if (idTarget<=0)
if (idTarget <= 0)
idTarget = m_idSelTarget;
bool bForceAttack;
@@ -3008,14 +3008,142 @@ public partial class CECHostPlayer : CECPlayer
return NormalAttackObject(idTarget, bForceAttack, bMoreClose);
}
public void StartChangeFace(){
public void StartChangeFace()
{
m_bChangingFace = true;
}
public void StopChangeFace(){
public void StopChangeFace()
{
m_bChangingFace = false;
}
public void PrepareNPCService(int idSev)
{
if (!GPDataTypeHelper.ISNPCID(m_idSevNPC))
{
return;
}
DATA_TYPE DataType = new DATA_TYPE();
object pBuf = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)idSev, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
switch (DataType)
{
case DATA_TYPE.DT_NPC_TALK_SERVICE:
break;
case DATA_TYPE.DT_NPC_SELL_SERVICE:
case DATA_TYPE.DT_NPC_BUY_SERVICE:
{
//// Get NPC's tex rate
//float fScale = 1.0f;
//CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(m_idSevNPC);
//if (pNPC && pNPC.IsServerNPC())
//{
// CECNPCServer pServer = (CECNPCServer)pNPC;
// fScale = (1.0f + pServer.GetTaxRate()) * pServer.GetPriceScale();
//}
//// Fill NPC package
//NPC_SELL_SERVICE pData = (NPC_SELL_SERVICE)pBuf;
//int[] id_goods = new int[InventoryConst.IVTRSIZE_NPCPACK];
//for (int j = 0; j < InventoryConst.NUM_NPCIVTR; j++)
//{
// for (int i = 0; i < InventoryConst.IVTRSIZE_NPCPACK; ++i)
// id_goods[i] = (int)pData.pages[j].goods[i].id;
// FillNPCPack(j, pData.pages[j].page_title, id_goods, fScale, false);
//}
//// Clear packs
//m_pBuyPack.RemoveAllItems();
//m_pSellPack.RemoveAllItems();
break;
}
case DATA_TYPE.DT_NPC_SKILL_SERVICE:
case DATA_TYPE.DT_NPC_PETLEARNSKILL_SERVICE:
{
//CECNPC pNPC = EC_ManMessageMono.Instance._CECNPCMan.GetNPC(m_idSevNPC);
//if (!pNPC || !pNPC.IsServerNPC())
//{
// return;
//}
//if (DataType == DATA_TYPE.DT_NPC_SKILL_SERVICE)
// ((CECNPCServer)pNPC).BuildSkillList(idSev);
//else
// ((CECNPCServer)pNPC).BuildPetSkillList();
break;
}
case DATA_TYPE.DT_NPC_REPAIR_SERVICE:
case DATA_TYPE.DT_NPC_INSTALL_SERVICE:
case DATA_TYPE.DT_NPC_UNINSTALL_SERVICE:
case DATA_TYPE.DT_NPC_TASK_IN_SERVICE:
case DATA_TYPE.DT_NPC_TASK_OUT_SERVICE:
case DATA_TYPE.DT_NPC_TASK_MATTER_SERVICE:
case DATA_TYPE.DT_NPC_HEAL_SERVICE:
case DATA_TYPE.DT_NPC_TRANSMIT_SERVICE:
case DATA_TYPE.DT_NPC_TRANSPORT_SERVICE:
case DATA_TYPE.DT_NPC_PROXY_SERVICE:
case DATA_TYPE.DT_NPC_STORAGE_SERVICE:
case DATA_TYPE.DT_NPC_DECOMPOSE_SERVICE:
case DATA_TYPE.DT_NPC_PETNAME_SERVICE:
case DATA_TYPE.DT_NPC_PETFORGETSKILL_SERVICE:
break;
case DATA_TYPE.DT_NPC_MAKE_SERVICE:
{
//// Fill NPC package
//NPC_MAKE_SERVICE pData = (NPC_MAKE_SERVICE)pBuf;
//for (int j = 0; j < NUM_NPCIVTR; j++)
// FillNPCPack(j, pData.pages[j].page_title, pData.pages[j].id_goods, 1.0f, true);
//// Clear deal pack
//m_pDealPack.RemoveAllItems();
break;
}
case DATA_TYPE.DT_NPC_RANDPROP_SERVICE:
{
//NPC_RANDPROP_SERVICE* pData = (NPC_RANDPROP_SERVICE*)pBuf;
//elementdataman* pDataMan = g_pGame.GetElementDataMan();
//// Fill equip data into NPC pack
//ASSERT(sizeof(pData.pages) / sizeof(pData.pages[0]) == NUM_NPCIVTR );
//for (int j = 0; j < NUM_NPCIVTR; j++)
//{
// unsigned int id_recipe = pData.pages[j].id_recipe;
// DATA_TYPE dt = DT_INVALID;
// RANDPROP_ESSENCE* pRecipe = (RANDPROP_ESSENCE*)pDataMan.get_data_ptr(id_recipe, ID_SPACE_RECIPE, dt);
// if (pRecipe && dt == DT_RANDPROP_ESSENCE)
// {
// FillNPCPack(j, pData.pages[j].page_title, (int*)pRecipe.equip_id, 1.0f, false);
// }
// else
// {
// // skip the invalid recipe id
// GetNPCSevPack(j).RemoveAllItems();
// GetNPCSevPack(j).SetName(_AL(""));
// }
//}
//// Clear deal pack
//m_pDealPack.RemoveAllItems();
break;
}
}
}
public EC_Inventory GetPack() { return m_packInventory; }
}
public enum StateAnim