Files
test/Assets/PerfectWorld/Scripts/NPC/CECNPCServer.cs
2026-02-26 14:24:30 +07:00

334 lines
12 KiB
C#

using BrewMonster;
using BrewMonster.Network;
using BrewMonster.Scripts;
using BrewMonster.Scripts.Task;
using CSNetwork.GPDataType;
using Cysharp.Threading.Tasks;
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using static CECNPC;
public class CECNPCServer : CECNPC
{
NPC_ESSENCE? m_pDBEssence;
MONSTER_ESSENCE? m_pMonEssence;
float m_fTaxRate = 0.05f; // Tax rate
private IconTaskType m_TaskIcon = IconTaskType.QI_NONE;
private CECCounter m_TaskCounter = new CECCounter();
private bool _needUpdateTaskIcon = false;
public override void SetUpCECNPC(CECNPCMan pNPCMan)
{
base.SetUpCECNPC(pNPCMan);
m_iCID = (int)Class_ID.OCID_SERVER;
m_pDBEssence = null;
m_TaskCounter.SetPeriod(1000);
}
public override bool Init(int tid, in info_npc info, ReadOnlySpan<byte> packet, int infoOffset)
{
base.Init(tid, info, packet, infoOffset);
//BrewMonster.BMLogger.Log("HoangDev: MonsterInit");
var pDB = ElementDataManProvider.GetElementDataMan();
DATA_TYPE DataType = default;
var data = pDB.get_data_ptr((uint)tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
m_pDBEssence = data != null ? (NPC_ESSENCE?)data : null;
var data1 = pDB.get_data_ptr(m_pDBEssence.Value.id_src_monster, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
if (data1 == null)
{
if ((data1 = (MONSTER_ESSENCE?)pDB.get_data_ptr(4249, ID_SPACE.ID_SPACE_ESSENCE, ref DataType)) == null)
{
BMLogger.LogError("HoangDEv : CECNPCServer::Init, server NPC reference to null monster data");
return false;
}
}
m_pMonEssence = (MONSTER_ESSENCE?)data1;
m_fTouchRad = m_pMonEssence.Value.size;
m_BasicProps.iLevel = m_pMonEssence.Value.level;
QueueLoadNPCModel();
/* float fExt = m_fTouchRad * 1.5f;
m_cdr.vExts.Set(fExt, fExt, fExt);
m_pNPCModelPolicy.SetDefaultPickAABBExt(m_cdr.vExts);*/
// If NPC doesn't have specific name, use the name in database
if ((info.state & (int)PlayerNPCState.GP_STATE_NPC_NAME) == 0)
{
m_strName = Encoding.Unicode.GetString(MemoryMarshal.AsBytes<ushort>(m_pDBEssence.Value.name));
m_npcUI.SetName(m_strName);
}
transform.forward = EC_Utility.ToVector3(EC_Utility.glb_DecompressDirH(info.dir));
transform.position = EC_Utility.ToVector3(info.pos);
StartWork((int)WorkType.WT_NOTHING, (int)WorkID.WORK_STAND);
return true;
}
protected override void Awake()
{
base.Awake();
var destroyToken = this.GetCancellationTokenOnDestroy();
UniTask.RunOnThreadPool(UpdateCurTaskIconProcess, false, cancellationToken: destroyToken).Forget();
}
protected override void Update()
{
base.Update();
if (_needUpdateTaskIcon)
{
UpdateTaskIconUI();
_needUpdateTaskIcon = false;
}
}
private async UniTask UpdateCurTaskIconProcess()
{
while (true)
{
await Task.Delay(1000);
UpdateCurTaskIcon();
}
}
// Get way point ID bound with this NPC
public uint? GetWayPointID()
{
uint? dwID = 0;
if ((m_pDBEssence?.combined_services & 0x08) != 0)
dwID = m_pDBEssence?.id_to_discover;
return dwID;
}
// 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;
}
private void UpdateCurTaskIcon()
{
var pHost = CECGameRun.Instance.GetHostPlayer();
if (pHost == null || pHost.GetTaskInterface() == null)
{
return;
}
if (m_pDBEssence == null)
{
return;
}
var pTaskMan = EC_Game.GetTaskTemplateMan();
var pDataMan = ElementDataManProvider.GetElementDataMan();
var pTask = pHost.GetTaskInterface();
const uint TASK_HAVE_COMPLETE = 0x10000000;
const uint TASK_COMPLETE = 0x01;
const uint TASK_INCOMPLETE = 0x02;
const uint TASK_CANGET = 0x04;
const uint TASK_CANNOTGET = 0x08;
const uint TASK_COMPLETE_TYPE1 = 0x10;
const uint TASK_CANGET_TYPE1 = 0x20;
const uint TASK_COMPLETE_TYPE2 = 0x40;
const uint TASK_CANGET_TYPE2 = 0x80;
const uint TASK_COMPLETE_TYPE3 = 0x100;
const uint TASK_CANGET_TYPE3 = 0x200;
const uint TASK_COMPLETE_TYPE4 = 0x400;
const uint TASK_CANGET_TYPE4 = 0x800;
m_TaskIcon = IconTaskType.QI_NONE;
uint taskFlag = 0;
//BMLogger.Log($"[UpdateCurTaskIcon] NPC {m_NPCInfo.nid}, id_task_in_service={m_pDBEssence.Value.id_task_in_service}, id_task_out_service={m_pDBEssence.Value.id_task_out_service}");
if (m_pDBEssence.Value.id_task_in_service != 0)
{
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var serviceData = pDataMan.get_data_ptr(m_pDBEssence.Value.id_task_in_service, ID_SPACE.ID_SPACE_ESSENCE, ref dt);
if (serviceData != null && dt == DATA_TYPE.DT_NPC_TASK_IN_SERVICE)
{
var inService = (NPC_TASK_IN_SERVICE)serviceData;
for (int i = 0; i < inService.id_tasks.Length; i++)
{
uint idTask = inService.id_tasks[i];
if (idTask <= 0 || !pTask.HasTask(idTask))
continue;
var pTaskTemp = pTaskMan.GetTaskTemplByID(idTask);
if (pTaskTemp == null)
continue;
if (pTask.CanFinishTask(idTask))
{
taskFlag |= TASK_HAVE_COMPLETE;
if (pTaskTemp.IsKeyTask())
{
m_TaskIcon = IconTaskType.QI_IN_K;
_needUpdateTaskIcon = true;
return;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTEvent || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTDaily)
{
taskFlag |= TASK_COMPLETE_TYPE3;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTQiShaList)
{
taskFlag |= TASK_COMPLETE_TYPE2;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFaction || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFunction)
{
taskFlag |= TASK_COMPLETE_TYPE1;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTMajor)
{
taskFlag |= TASK_COMPLETE_TYPE4;
}
else
{
taskFlag |= TASK_COMPLETE;
}
}
else
{
taskFlag |= TASK_INCOMPLETE;
}
}
}
}
if ((taskFlag & TASK_HAVE_COMPLETE) != 0)
{
if ((taskFlag & TASK_COMPLETE_TYPE4) != 0)
m_TaskIcon = IconTaskType.QI_IN_TYPE4;
else if ((taskFlag & TASK_COMPLETE_TYPE3) != 0)
m_TaskIcon = IconTaskType.QI_IN_TYPE3;
else if ((taskFlag & TASK_COMPLETE_TYPE2) != 0)
m_TaskIcon = IconTaskType.QI_IN_TYPE2;
else if ((taskFlag & TASK_COMPLETE) != 0)
m_TaskIcon = IconTaskType.QI_IN;
else if ((taskFlag & TASK_COMPLETE_TYPE1) != 0)
m_TaskIcon = IconTaskType.QI_IN_TYPE1;
_needUpdateTaskIcon = true;
return;
}
if (m_pDBEssence.Value.id_task_out_service != 0)
{
DATA_TYPE dt = DATA_TYPE.DT_INVALID;
var serviceData = pDataMan.get_data_ptr(
m_pDBEssence.Value.id_task_out_service,
ID_SPACE.ID_SPACE_ESSENCE,
ref dt
);
if (serviceData != null && dt == DATA_TYPE.DT_NPC_TASK_OUT_SERVICE)
{
var outService = (NPC_TASK_OUT_SERVICE)serviceData;
if (outService.storage_id != 0 && outService.storage_open_item != 0)
{
var pack = pHost.GetInventory(InventoryConst.IVTRTYPE_PACK);
if (pack != null && pack.GetItemTotalNum((int)outService.storage_open_item) > 0)
{
taskFlag |= TASK_CANGET_TYPE2;
}
}
// Check normal tasks
for (int i = 0; i < outService.id_tasks.Length; i++)
{
uint idTask = outService.id_tasks[i];
if (idTask <= 0)
continue;
if (!pTask.CanShowTask(idTask))
continue;
var pTaskTemp = pTaskMan.GetTaskTemplByID(idTask);
if (pTaskTemp == null)
continue;
if (pTask.CanDeliverTask(idTask) == 0)
{
if (pTaskTemp.IsKeyTask())
{
m_TaskIcon = IconTaskType.QI_OUT_K;
_needUpdateTaskIcon = true;
return;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTEvent || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTDaily)
{
taskFlag |= TASK_CANGET_TYPE3;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTQiShaList)
{
taskFlag |= TASK_CANGET_TYPE2;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFaction || pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTFunction)
{
taskFlag |= TASK_CANGET_TYPE1;
}
else if (pTaskTemp.GetType() == (uint)ENUM_TASK_TYPE.enumTTMajor)
{
taskFlag |= TASK_CANGET_TYPE4;
}
else
{
taskFlag |= TASK_CANGET;
}
}
else
{
taskFlag |= TASK_CANNOTGET;
}
}
}
}
// Set icon by available task priority
if ((taskFlag & TASK_CANGET_TYPE4) != 0)
m_TaskIcon = IconTaskType.QI_OUT_TYPE4;
else if ((taskFlag & TASK_CANGET_TYPE3) != 0)
m_TaskIcon = IconTaskType.QI_OUT_TYPE3;
else if ((taskFlag & TASK_CANGET_TYPE2) != 0)
m_TaskIcon = IconTaskType.QI_OUT_TYPE2;
else if ((taskFlag & TASK_CANGET) != 0)
m_TaskIcon = IconTaskType.QI_OUT;
else if ((taskFlag & TASK_CANGET_TYPE1) != 0)
m_TaskIcon = IconTaskType.QI_OUT_TYPE1;
else if ((taskFlag & TASK_INCOMPLETE) != 0)
m_TaskIcon = IconTaskType.QI_IN_N;
else if ((taskFlag & TASK_CANNOTGET) != 0)
m_TaskIcon = IconTaskType.QI_OUT_N;
//BMLogger.Log($"[UpdateCurTaskIcon] Final icon {m_TaskIcon}, taskFlag={taskFlag}");
_needUpdateTaskIcon = true;
}
private void UpdateTaskIconUI()
{
if(m_npcUI != null)
{
m_npcUI.SetTaskIcon(m_TaskIcon);
}
}
}