Merge branch 'develop' into feature/HP_jump
This commit is contained in:
@@ -5,6 +5,7 @@ using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using PerfectWorld.Scripts;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -132,6 +133,10 @@ namespace BrewMonster
|
||||
float fMaxCut = m_bMoreClose ? -1.0f : 1.0f;
|
||||
|
||||
CECObject pObject = EC_ManMessageMono.Instance.GetObject(m_iObjectId, 0);
|
||||
if (pObject == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float fTouchRadius = 0.0f;
|
||||
if (GPDataTypeHelper.ISPLAYERID(m_iObjectId))
|
||||
@@ -142,7 +147,13 @@ namespace BrewMonster
|
||||
}
|
||||
else
|
||||
{
|
||||
CECPlayer pPlayer = pObject.GetComponent<CECHostPlayer>();
|
||||
// pObject is usually EC_ElsePlayer/CECPlayer, not CECHostPlayer.
|
||||
// Using GetComponent<CECHostPlayer>() returns null and breaks touch checks.
|
||||
CECPlayer pPlayer = pObject as CECPlayer;
|
||||
if (pPlayer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fTouchRadius = pPlayer.GetTouchRadius();
|
||||
}
|
||||
return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut);
|
||||
@@ -150,13 +161,25 @@ namespace BrewMonster
|
||||
else if (GPDataTypeHelper.ISNPCID(m_iObjectId))
|
||||
{
|
||||
CECNPC pNPC = pObject as CECNPC;
|
||||
if (pNPC == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fTouchRadius = pNPC.GetTouchRadius();
|
||||
return m_pHost.CanTouchTarget(vHostPos, vTargetPos, fTouchRadius, iTouchReason, fMaxCut);
|
||||
}
|
||||
else if (GPDataTypeHelper.ISMATTERID(m_iObjectId))
|
||||
{
|
||||
//CECMatter pMatter = (pObject) as CECMatter;
|
||||
//return pMatter.CalcDist(vHostPos, true) < pMatter.GetGatherDist();
|
||||
CECMatter pMatter = (pObject) as CECMatter;
|
||||
if (pMatter == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// For matter, use horizontal distance (ignore Y).
|
||||
// Unity's touch check uses host position + capsule extent, which would otherwise
|
||||
// force the player to get much closer than intended.
|
||||
// C++ behavior expects a stand-off distance (default 3.0).
|
||||
return pMatter.CalcDist(vHostPos, false) < pMatter.GetGatherDist();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -207,7 +230,11 @@ namespace BrewMonster
|
||||
|
||||
public override A3DVECTOR3 GetTargetPos()
|
||||
{
|
||||
return (GetTargetObject() as CECNPC).GetServerPos();
|
||||
// 使用 Unity transform 的实时位置,而不是服务器缓存位置(可能滞后 / 未及时刷新),
|
||||
// 否则追踪目的地/触碰判定会偏离导致永远触不到。
|
||||
// Use live transform position (GetPos) instead of cached server position (GetServerPos),
|
||||
// otherwise tracing destination and touch checks can be wrong and never trigger.
|
||||
return (GetTargetObject() as CECNPC).GetPos();
|
||||
}
|
||||
|
||||
public override bool OnTouched()
|
||||
@@ -231,8 +258,16 @@ namespace BrewMonster
|
||||
}
|
||||
else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK)
|
||||
{
|
||||
if (m_iObjectId == m_pHost.m_idSelTarget &&
|
||||
m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1)
|
||||
// 服务器的选中目标同步可能比追踪触碰晚到,导致这里永远不触发攻击。
|
||||
// 为了保证追踪到目标后能正常攻击,这里在必要时主动选中目标。
|
||||
// Server select-target ack can arrive later than the trace touch moment, which would
|
||||
// make this block forever. Ensure we select the traced target before attacking.
|
||||
if (m_iObjectId != m_pHost.m_idSelTarget)
|
||||
{
|
||||
UnityGameSession.c2s_CmdSelectTarget(m_iObjectId);
|
||||
m_pHost.m_idSelTarget = m_iObjectId;
|
||||
}
|
||||
if (m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1)
|
||||
{
|
||||
byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack);
|
||||
UnityGameSession.c2s_CmdNormalAttack(byPVPMask);
|
||||
@@ -317,7 +352,9 @@ namespace BrewMonster
|
||||
}
|
||||
else
|
||||
{
|
||||
return (pObject as EC_ElsePlayer).GetServerPos();
|
||||
// 同上:用实时位置避免 server pos 滞后导致追踪/触碰失败。
|
||||
// Same rationale: use live position to avoid stale server pos breaking trace/touch.
|
||||
return (pObject as EC_ElsePlayer).GetPos();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,8 +379,14 @@ namespace BrewMonster
|
||||
}
|
||||
if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK)
|
||||
{
|
||||
if (m_iObjectId == m_pHost.m_idSelTarget &&
|
||||
m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1)
|
||||
// 同 NPC:追踪触碰可能早于服务器选中目标同步,需主动选中以避免攻击不触发。
|
||||
// Same as NPC: trace touch can happen before server selection ack; proactively select.
|
||||
if (m_iObjectId != m_pHost.m_idSelTarget)
|
||||
{
|
||||
UnityGameSession.c2s_CmdSelectTarget(m_iObjectId);
|
||||
m_pHost.m_idSelTarget = m_iObjectId;
|
||||
}
|
||||
if (m_pHost.AttackableJudge(m_iObjectId, m_bForceAttack) == 1)
|
||||
{
|
||||
byte byPVPMask = EC_Utility.glb_BuildPVPMask(m_bForceAttack);
|
||||
UnityGameSession.c2s_CmdNormalAttack(byPVPMask);
|
||||
@@ -431,70 +474,78 @@ namespace BrewMonster
|
||||
public override bool OnTouched()
|
||||
{
|
||||
bool bActionDone = false;
|
||||
//if (GPDataTypeHelper.ISMATTERID(m_iObjectId))
|
||||
//{
|
||||
// if (m_pHost.GetProfession() == PROF_GHOST && m_pHost.IsInvisible())
|
||||
// {
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CANNOT_USE_WHEN_INVISIBLE);
|
||||
// return bActionDone;
|
||||
// }
|
||||
// CECMatter* pMatter = (CECMatter*)GetTargetObject();
|
||||
if (GPDataTypeHelper.ISMATTERID(m_iObjectId))
|
||||
{
|
||||
// if (m_pHost.GetProfession() == BrewMonster.RoleTypes.PROF_GHOST && m_pHost.IsInvisible())
|
||||
// {
|
||||
// EC_Game.GetGameRun().AddFixedMessage(FIXMSG_CANNOT_USE_WHEN_INVISIBLE);
|
||||
// return bActionDone;
|
||||
// }
|
||||
CECMatter pMatter = (CECMatter)GetTargetObject();
|
||||
|
||||
// if (m_iReason == CECHPWorkTrace::TRACE_PICKUP)
|
||||
// {
|
||||
// // Check whether we have enougth place to hold this item or money
|
||||
// a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_PICKUP");
|
||||
// if (m_pHost.CanTakeItem(pMatter.GetTemplateID(), 1))
|
||||
// {
|
||||
// // Send pickup asking and wait response command
|
||||
// g_pGame.GetGameSession().c2s_CmdPickup(m_iObjectId, pMatter.GetTemplateID());
|
||||
// bActionDone = true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Print a notify message
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_PACKISFULL);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// { // m_iReason == TRACE_GATHER
|
||||
// int tidMatter = pMatter.GetTemplateID();
|
||||
// a_LogOutput(1, "[NormalATK]- CECTracedMatter- OnTouched- TRACE_GATHER");
|
||||
// // Check mine level requirement
|
||||
// if (m_pHost.GetBasicProps().iLevel < pMatter.GetLevelReq())
|
||||
// {
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_LEVELTOOLOW);
|
||||
// return bActionDone;
|
||||
// }
|
||||
if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_PICKUP)
|
||||
{
|
||||
// Check whether we have enougth place to hold this item or money
|
||||
int tid = pMatter.GetTemplateID();
|
||||
bool isMoney = pMatter.IsMoney() || GPDataTypeHelper.ISMONEYTID(tid);
|
||||
|
||||
// // Check whether we have a mine tool
|
||||
// int iPack, iIndex, idTool;
|
||||
// if (m_pHost.FindMineTool(tidMatter, &iPack, &iIndex, &idTool))
|
||||
// {
|
||||
// DATA_TYPE DataType;
|
||||
// const MINE_ESSENCE* pData = (const MINE_ESSENCE*)g_pGame.GetElementDataMan().get_data_ptr(pMatter.GetTemplateID(), ID_SPACE_ESSENCE, DataType);
|
||||
// if (DataType != DT_MINE_ESSENCE)
|
||||
// {
|
||||
// ASSERT(DataType == DT_MINE_ESSENCE);
|
||||
// return bActionDone;
|
||||
// }
|
||||
// Money pickup should not be blocked by inventory space checks.
|
||||
// Let the server validate (e.g. money cap), and only gate items by bag space.
|
||||
if (isMoney || m_pHost.CanTakeItem(tid, 1))
|
||||
{
|
||||
// Send pickup asking and wait response command
|
||||
UnityGameSession.RequestPickupItem(m_iObjectId, tid);
|
||||
bActionDone = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print a notify message
|
||||
//g_pGame.GetGameRun().AddFixedMessage(FIXMSG_PACKISFULL);
|
||||
Debug.Log("Khong du cho trong de nhat item");
|
||||
}
|
||||
}
|
||||
else if (m_iReason == CECHPWorkTrace.Trace_reason.TRACE_GATHER)
|
||||
{ // m_iReason == TRACE_GATHER
|
||||
int tidMatter = pMatter.GetTemplateID();
|
||||
// Check mine level requirement
|
||||
if (m_pHost.GetBasicProps().iLevel < pMatter.GetLevelReq())
|
||||
{
|
||||
//g_pGame.GetGameRun().AddFixedMessage(FIXMSG_LEVELTOOLOW);
|
||||
Debug.Log("Cap do cua ban khong du de khai thac tai nguyen nay");
|
||||
return bActionDone;
|
||||
}
|
||||
|
||||
// if (m_pHost.GetCoolTime(GP_CT_PLAYER_GATHER))
|
||||
// {
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // Send gather asking and wait response command
|
||||
// g_pGame.GetGameSession().c2s_CmdGatherMaterial(m_iObjectId, iPack, iIndex, idTool, pData.task_in);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEEDTOOL);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
// Check whether we have a mine tool
|
||||
int iPack = 0;
|
||||
int iIndex = 0;
|
||||
int idTool = 0;
|
||||
if (m_pHost.FindMineTool(tidMatter, ref iPack, ref iIndex, ref idTool))
|
||||
{
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
MINE_ESSENCE pData = (MINE_ESSENCE)ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)pMatter.GetTemplateID(), ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
if (DataType != DATA_TYPE.DT_MINE_ESSENCE)
|
||||
{
|
||||
//ASSERT(DataType == DT_MINE_ESSENCE);
|
||||
return bActionDone;
|
||||
}
|
||||
|
||||
// if (m_pHost.GetCoolTime(GP_CT_PLAYER_GATHER))
|
||||
// {
|
||||
// g_pGame.GetGameRun().AddFixedMessage(FIXMSG_CMD_INCOOLTIME);
|
||||
// }
|
||||
else
|
||||
{
|
||||
// Send gather asking and wait response command
|
||||
UnityGameSession.c2s_CmdGatherMaterial(m_iObjectId, iPack, iIndex, idTool, (int)pData.task_in);
|
||||
bActionDone = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//g_pGame.GetGameRun().AddFixedMessage(FIXMSG_NEEDTOOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bActionDone;
|
||||
}
|
||||
|
||||
@@ -531,6 +582,10 @@ namespace BrewMonster
|
||||
public void SetTraceTarget(CECTracedObject pTraceObj, bool bUseAutoPF = false)
|
||||
{
|
||||
ResetUseAutoPF(bUseAutoPF);
|
||||
if (pTraceObj == null)
|
||||
{
|
||||
return; // Invalid trace object / Invalid trace object
|
||||
}
|
||||
if (!pTraceObj.GetTargetObject() || pTraceObj.GetObjectID() == m_pHost.GetCharacterID())
|
||||
{
|
||||
// This is special case
|
||||
@@ -568,10 +623,10 @@ namespace BrewMonster
|
||||
{
|
||||
return new CECTracedNPC(TraceObjectType.TRACE_NPC, iTraceObjId, m_pHost, iReason, bForceAttack);
|
||||
}
|
||||
//else if (GPDataTypeHelper.ISMATTERID(iTraceObjId))
|
||||
//{
|
||||
// return new CECTracedMatter(TraceObjectType.TRACE_MATTER, iTraceObjId, m_pHost, iReason);
|
||||
//}
|
||||
else if (GPDataTypeHelper.ISMATTERID(iTraceObjId))
|
||||
{
|
||||
return new CECTracedMatter(TraceObjectType.TRACE_MATTER, iTraceObjId, m_pHost, iReason);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -596,17 +651,20 @@ namespace BrewMonster
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_bCheckTouch)
|
||||
// 重要:不要用 m_bCheckTouch 在这里抑制 Touch 检测。
|
||||
// 之前的移植里 m_bCheckTouch 会在 GroundMove 后被置为 false,导致下一帧永远不进入 OnTouchTarget。
|
||||
// Important: do not suppress touch checks with m_bCheckTouch here.
|
||||
// In this port, m_bCheckTouch can be forced false after GroundMove, making OnTouchTarget never fire.
|
||||
if (IsGoodTimeToTouch())
|
||||
{
|
||||
if (IsGoodTimeToTouch())
|
||||
// 注意:这里不能加 vExtent.y(胶囊半高),否则会把主角位置抬高导致 3D 距离变大,
|
||||
// 进而 CanTouchTarget 永远不满足(OnTouchTarget 永远不会触发)。
|
||||
// Note: Do NOT add vExtent.y (capsule half-height) here; touch uses 3D distance and this
|
||||
// artificially increases the distance, preventing OnTouchTarget() from ever triggering.
|
||||
if (m_pTraceObject.CanTouchFrom(m_pHost.GetPos()))
|
||||
{
|
||||
//OnTouchTarget();
|
||||
//return true;
|
||||
if (m_pTraceObject.CanTouchFrom(m_pHost.GetPos() + new A3DVECTOR3(0f, m_pHost.m_CDRInfo.vExtent.y, 0f)))
|
||||
{
|
||||
OnTouchTarget();
|
||||
return true;
|
||||
}
|
||||
OnTouchTarget();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
m_bCheckTouch = true;
|
||||
@@ -797,7 +855,7 @@ namespace BrewMonster
|
||||
// Operations
|
||||
|
||||
// On first tick
|
||||
protected virtual void OnFirstTick()
|
||||
protected override void OnFirstTick()
|
||||
{
|
||||
m_pHost.m_iMoveMode = (int)MoveMode.MOVE_MOVE;
|
||||
m_bHaveMoved = false;
|
||||
@@ -851,7 +909,7 @@ namespace BrewMonster
|
||||
else if (!m_pHost.m_GndInfo.bOnGround)
|
||||
iMoveMode = (int)GPMoveMode.GP_MOVE_FALL;
|
||||
|
||||
RaycastHit lastGroundHit;
|
||||
//RaycastHit lastGroundHit;
|
||||
//m_pHost.m_GndInfo.bOnGround = m_pHost.GroundCheck(out lastGroundHit);
|
||||
if (m_pHost.m_GndInfo.bOnGround)
|
||||
{
|
||||
@@ -886,10 +944,9 @@ namespace BrewMonster
|
||||
// CECIntelligentRoute::Instance().OnPlayerPosChange(vCurPos);
|
||||
//}
|
||||
|
||||
if (cdr.vTPNormal.IsZero())
|
||||
{
|
||||
m_bCheckTouch = false;
|
||||
}
|
||||
// 不要在这里关闭 touch 检测:Tick() 的 touch 检测发生在移动之前,
|
||||
// 如果这里把 m_bCheckTouch 置 false,会导致下一帧永远跳过触发逻辑。
|
||||
// Do not disable touch checking here; touch checking happens before movement in Tick().
|
||||
|
||||
//if (!m_vCurDirH.IsZero())
|
||||
//{
|
||||
@@ -972,6 +1029,33 @@ namespace BrewMonster
|
||||
}
|
||||
public A3DVECTOR3 GetCurMovingDest()
|
||||
{
|
||||
// 对于采集/拾取物体:保持一定距离,避免角色模型顶住碰撞体抖动
|
||||
// For gather/pickup matters: keep a stand-off distance to avoid jittering against colliders.
|
||||
if (m_pTraceObject != null && m_pTraceObject.GetTraceType() == TraceObjectType.TRACE_MATTER)
|
||||
{
|
||||
CECMatter matter = m_pTraceObject.GetTargetObject() as CECMatter;
|
||||
if (matter != null)
|
||||
{
|
||||
float keepDist = matter.GetGatherDist();
|
||||
if (keepDist > 0.01f)
|
||||
{
|
||||
A3DVECTOR3 hostPos = m_pHost.GetPos();
|
||||
A3DVECTOR3 targetPos = matter.GetPos();
|
||||
|
||||
A3DVECTOR3 deltaH = targetPos - hostPos;
|
||||
deltaH.y = 0.0f;
|
||||
float distH = deltaH.MagnitudeH();
|
||||
if (distH > keepDist + 0.05f && distH > 1e-4f)
|
||||
{
|
||||
deltaH.Normalize();
|
||||
A3DVECTOR3 dest = targetPos - deltaH * keepDist;
|
||||
// keep Y stable; GroundMove will resolve final Y anyway
|
||||
dest.y = hostPos.y;
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return m_pTraceObject.GetTargetPos();
|
||||
}
|
||||
public void UpdateUseAutoPF()
|
||||
|
||||
@@ -2,6 +2,7 @@ using BrewMonster.Managers;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using PerfectWorld.Scripts;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -25,23 +26,107 @@ namespace BrewMonster
|
||||
|
||||
public void OnMsgLBtnClick()
|
||||
{
|
||||
// 停止自动策略 / Stop auto policy
|
||||
// Note: Auto policy check would go here if implemented
|
||||
|
||||
int idTraceTarget = 0, idSelTarget = 0;
|
||||
bool bForceAttack = false;
|
||||
int iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_NONE;
|
||||
bool bWikiMonster = false;
|
||||
|
||||
ray = mainCam.ScreenPointToRay(Input.mousePosition);
|
||||
Vector3 vStart = mainCam.transform.position;
|
||||
Vector3 vDest = ray.GetPoint(1.0f);
|
||||
Vector3 vDelta = vDest - vStart;
|
||||
|
||||
// Check for NPC with pate text (hover text) first
|
||||
// Note: This would require GetMouseOnPateTextNPC implementation
|
||||
// For now, we'll proceed with raycast
|
||||
|
||||
if (Physics.Raycast(ray, out hit))
|
||||
{
|
||||
if (hit.collider.gameObject.TryGetComponent<CECObject>(out CECObject clickedObject))
|
||||
// Check if hit terrain, building, or forest (no CECObject component)
|
||||
if (!hit.collider.gameObject.TryGetComponent<CECObject>(out CECObject clickedObject))
|
||||
{
|
||||
int idObject = CECObject.GetObjectID(clickedObject);
|
||||
if (idObject != 0)
|
||||
//ENABLE LATER - CURRENT WORKING FINE
|
||||
// Hit terrain / building / forest / Hit terrain
|
||||
// if (m_pWorkMan.IsSitting())
|
||||
// {
|
||||
// UnityGameSession.c2s_CmdStandUp();
|
||||
// return;
|
||||
// }
|
||||
// if (!CanDo(ActionCanDo.CANDO_MOVETO))
|
||||
// return;
|
||||
//
|
||||
// // Calculate move destination / Hit terrain
|
||||
// Vector3 vMoveDest = hit.point;
|
||||
// A3DVECTOR3 a3dMoveDest = EC_Utility.ToA3DVECTOR3(vMoveDest);
|
||||
//
|
||||
// if (Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))
|
||||
// {
|
||||
// // Ctrl pressed - direct goto / Ctrl pressed
|
||||
// // Note: c2s_CmdGoto not implemented, using work system instead
|
||||
// // UnityGameSession.c2s_CmdGoto(a3dMoveDest.x, a3dMoveDest.y, a3dMoveDest.z);
|
||||
// // For now, use work system even with Ctrl
|
||||
// }
|
||||
// // else removed - always use work system
|
||||
// {
|
||||
// CECHPWork pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS);
|
||||
// if (pWork != null)
|
||||
// {
|
||||
// CECHPWorkMove pWorkMove = pWork as CECHPWorkMove;
|
||||
// if (pWorkMove != null)
|
||||
// {
|
||||
// pWorkMove.SetDestination(CECHPWorkMove.DestTypes.DEST_2D, a3dMoveDest);
|
||||
// pWorkMove.SetUseAutoMoveDialog(false);
|
||||
// // Note: PlayMoveTargetGFX would go here if implemented
|
||||
// }
|
||||
// }
|
||||
// else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS))
|
||||
// {
|
||||
// // If destination is too near, ignore it. / If destination is too near, ignore it.
|
||||
// A3DVECTOR3 vDist = a3dMoveDest - GetPos();
|
||||
// float fDistH = (float)Math.Sqrt(vDist.x * vDist.x + vDist.z * vDist.z);
|
||||
// if (fDistH > 0.5f)
|
||||
// {
|
||||
// CECHPWorkMove pWorkMove = (CECHPWorkMove)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS);
|
||||
// pWorkMove.SetDestination(CECHPWorkMove.DestTypes.DEST_2D, a3dMoveDest);
|
||||
// // Note: PlayMoveTargetGFX would go here if implemented
|
||||
// m_pWorkMan.StartWork_p1(pWorkMove);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
// Hit an object / Hit a object
|
||||
int idObject = CECObject.GetObjectID(clickedObject);
|
||||
if (idObject != 0)
|
||||
{
|
||||
// Check if it's a matter object / Check if it's a matter object
|
||||
if (clickedObject.IsMatter())
|
||||
{
|
||||
CECMatter pMatter = clickedObject as CECMatter;
|
||||
if (pMatter != null)
|
||||
{
|
||||
idTraceTarget = pMatter.GetMatterID();
|
||||
// Check if it's a mine (gather) or item (pickup) / Check if it's a mine (gather) or item (pickup)
|
||||
bool bIsMine = pMatter.IsMine();
|
||||
iTraceReason = bIsMine ? CECHPWorkTrace.Trace_reason.TRACE_GATHER : CECHPWorkTrace.Trace_reason.TRACE_PICKUP;
|
||||
}
|
||||
}
|
||||
// Check if it's a dynamic object / Check if it's a dynamic object
|
||||
// else if (clickedObject.gameObject.CompareTag("DynamicObject")) // ECENT_DYN_OBJ
|
||||
// {
|
||||
// return; // Dynamic objects are not clickable
|
||||
// }
|
||||
else
|
||||
{
|
||||
// NPC or Player / NPC or Player
|
||||
CECNPC pNPC = EC_ManMessageMono.Instance.CECNPCMan.GetNPC(idObject);
|
||||
if (pNPC != null)
|
||||
{
|
||||
// Msg.dwParam4 is double click flag / Msg.dwParam4 is double click flag
|
||||
if (!pNPC.IsDead() && m_idSelTarget == idObject)
|
||||
{
|
||||
idTraceTarget = idObject;
|
||||
@@ -53,6 +138,7 @@ namespace BrewMonster
|
||||
|
||||
if (idTraceTarget != 0)
|
||||
{
|
||||
// bForceAttack = glb_GetForceAttackFlag(&Msg.dwParam3);
|
||||
if (AttackableJudge(idObject, bForceAttack) == 1)
|
||||
iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_ATTACK;
|
||||
else if (pNPC.IsServerNPC())
|
||||
@@ -64,12 +150,12 @@ namespace BrewMonster
|
||||
}
|
||||
else
|
||||
{
|
||||
// pCDS.m_RayTraceRt.iEntity == ECENT_PLAYER
|
||||
// pCDS.m_RayTraceRt.iEntity == ECENT_PLAYER / pCDS.m_RayTraceRt.iEntity == ECENT_PLAYER
|
||||
CECPlayer pPlayer = EC_ManMessageMono.Instance.EC_ManPlayer.GetPlayer(idObject);
|
||||
|
||||
// 1. Msg.dwParam4 is double click flag.
|
||||
// 2. Buddy player counld't be traced
|
||||
if (!pPlayer.IsDead() /*&& pPlayer.GetCharacterID() != m_iBuddyId*/ &&
|
||||
// 1. Msg.dwParam4 is double click flag. / 1. Msg.dwParam4 is double click flag.
|
||||
// 2. Buddy player counld't be traced / 2. Buddy player counld't be traced
|
||||
if (pPlayer != null && !pPlayer.IsDead() /*&& pPlayer.GetCharacterID() != m_iBuddyId*/ &&
|
||||
(m_idSelTarget == idObject /*|| (Msg.dwParam4 && m_idUCSelTarget == idObject)*/))
|
||||
{
|
||||
idTraceTarget = idObject;
|
||||
@@ -80,31 +166,73 @@ namespace BrewMonster
|
||||
else if (pPlayer.GetBoothState() != 0)
|
||||
iTraceReason = CECHPWorkTrace.Trace_reason.TRACE_TALK;
|
||||
}
|
||||
else
|
||||
else if (pPlayer != null)
|
||||
{
|
||||
idSelTarget = idObject;
|
||||
}
|
||||
}
|
||||
|
||||
// cancel this action if not selectable
|
||||
// cancel this action if not selectable / cancel this action if not selectable
|
||||
if (!CanSelectTarget(idTraceTarget))
|
||||
{
|
||||
idTraceTarget = 0;
|
||||
//return;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for wiki monster / Check for wiki monster
|
||||
// Note: CDlgAutoHelp::IsAutoHelp() check would go here if implemented
|
||||
// if (CDlgAutoHelp.IsAutoHelp() && pNPC != null && pNPC.IsMonsterNPC())
|
||||
// bWikiMonster = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tell server we select a target
|
||||
if (idSelTarget != 0 && m_idSelTarget != idSelTarget)
|
||||
else
|
||||
{
|
||||
m_idUCSelTarget = idSelTarget;
|
||||
SelectTarget(m_idUCSelTarget);
|
||||
// Nothing is clicked / Nothing is clicked
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CanDo(ActionCanDo.CANDO_MOVETO))
|
||||
return;
|
||||
|
||||
// Move on the clicked direction / Move on the clicked direction
|
||||
Vector3 vMoveDir = vDelta;
|
||||
vMoveDir.y = 0.0f;
|
||||
if (vMoveDir.sqrMagnitude < 0.0001f)
|
||||
return;
|
||||
|
||||
vMoveDir.Normalize();
|
||||
A3DVECTOR3 a3dMoveDir = EC_Utility.ToA3DVECTOR3(vMoveDir);
|
||||
|
||||
CECHPWork pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS);
|
||||
if (pWork != null)
|
||||
{
|
||||
CECHPWorkMove pWorkMove = pWork as CECHPWorkMove;
|
||||
if (pWorkMove != null)
|
||||
{
|
||||
pWorkMove.SetDestination(CECHPWorkMove.DestTypes.DEST_DIR, a3dMoveDir);
|
||||
}
|
||||
}
|
||||
else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS))
|
||||
{
|
||||
CECHPWorkMove pWorkMove = (CECHPWorkMove)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_MOVETOPOS);
|
||||
pWorkMove.SetDestination(CECHPWorkMove.DestTypes.DEST_DIR, a3dMoveDir);
|
||||
m_pWorkMan.StartWork_p1(pWorkMove);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle trace target / Handle trace target
|
||||
if (idTraceTarget != 0)
|
||||
{
|
||||
if (m_pWorkMan.IsSitting())
|
||||
{
|
||||
UnityGameSession.c2s_CmdStandUp();
|
||||
return;
|
||||
}
|
||||
// Trace a object / Trace a object
|
||||
if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_ATTACK)
|
||||
{
|
||||
if (!CanDo(ActionCanDo.CANDO_MELEE))
|
||||
@@ -115,14 +243,15 @@ namespace BrewMonster
|
||||
{
|
||||
if (!CanDo(ActionCanDo.CANDO_MOVETO))
|
||||
return;
|
||||
|
||||
CECHPWork pWork;
|
||||
if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_PICKUP)
|
||||
{
|
||||
//PickupObject(idTraceTarget, false);
|
||||
PickupObject(idTraceTarget, false);
|
||||
}
|
||||
else if (iTraceReason == CECHPWorkTrace.Trace_reason.TRACE_GATHER)
|
||||
{
|
||||
//PickupObject(idTraceTarget, true);
|
||||
PickupObject(idTraceTarget, true);
|
||||
}
|
||||
else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null)
|
||||
{
|
||||
@@ -137,6 +266,13 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tell server we select a target / Tell server we select a target
|
||||
if (idSelTarget != 0 && m_idSelTarget != idSelTarget)
|
||||
{
|
||||
m_idUCSelTarget = idSelTarget;
|
||||
SelectTarget(m_idUCSelTarget);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnMsgHstJump()
|
||||
@@ -226,5 +362,78 @@ namespace BrewMonster
|
||||
//m_GndInfo.bOnGround = GroundCheck(out lastGroundHit);
|
||||
OnMsgHstJump();
|
||||
}
|
||||
|
||||
// Pickup an object / Pickup an object
|
||||
public bool PickupObject(int idTarget, bool bGather)
|
||||
{
|
||||
if (IsDead() || IsSpellingMagic() || idTarget == 0 || !GPDataTypeHelper.ISMATTERID(idTarget))
|
||||
return false;
|
||||
|
||||
// Check matter type / Check matter type
|
||||
CECMatter pMatter = EC_ManMessageMono.Instance.EC_ManMatter.GetMatter(idTarget);
|
||||
if (pMatter == null)
|
||||
{
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||
Debug.LogWarning(
|
||||
$"PickupObject: GetMatter returned null. idTarget={idTarget} (0x{idTarget:X8}) bGather={bGather}");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bGather != pMatter.IsMine())
|
||||
return false;
|
||||
|
||||
if (bGather && !CanGatherMatter(pMatter))
|
||||
return false;
|
||||
|
||||
bool bOK = true;
|
||||
|
||||
// Trace a object / Trace a object
|
||||
CECHPWork pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT);
|
||||
if (pWork != null)
|
||||
{
|
||||
CECHPWorkTrace pWorkTrace = pWork as CECHPWorkTrace;
|
||||
if (pWorkTrace != null)
|
||||
{
|
||||
CECTracedObject traceTarget = pWorkTrace.CreatTraceTarget(idTarget,
|
||||
bGather ? CECHPWorkTrace.Trace_reason.TRACE_GATHER : CECHPWorkTrace.Trace_reason.TRACE_PICKUP,
|
||||
false);
|
||||
if (traceTarget != null)
|
||||
{
|
||||
pWorkTrace.SetTraceTarget(traceTarget);
|
||||
bOK = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT))
|
||||
{
|
||||
CECHPWorkTrace pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT);
|
||||
if (pWorkTrace != null)
|
||||
{
|
||||
CECTracedObject traceTarget = pWorkTrace.CreatTraceTarget(idTarget,
|
||||
bGather ? CECHPWorkTrace.Trace_reason.TRACE_GATHER : CECHPWorkTrace.Trace_reason.TRACE_PICKUP,
|
||||
false);
|
||||
if (traceTarget != null)
|
||||
{
|
||||
pWorkTrace.SetTraceTarget(traceTarget);
|
||||
m_pWorkMan.StartWork_p1(pWorkTrace);
|
||||
bOK = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bOK;
|
||||
}
|
||||
|
||||
// Check whether host can gather specified matter / Check whether host can gather specified matter
|
||||
public bool CanGatherMatter(CECMatter pMatter)
|
||||
{
|
||||
if (pMatter == null || !pMatter.IsMine())
|
||||
return false;
|
||||
|
||||
// TODO: Add level requirement check and other gather validations / TODO: Add level requirement check and other gather validations
|
||||
// For now, return true if it's a mine / For now, return true if it's a mine
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,22 @@ namespace PerfectWorld.Scripts.Managers
|
||||
// Storage for matter data that players can access later
|
||||
private Dictionary<int, info_matter> matterDataStorage = new Dictionary<int, info_matter>();
|
||||
private Dictionary<int, CECMatter> m_MatterTab = new Dictionary<int, CECMatter>();
|
||||
|
||||
/// <summary>
|
||||
/// Unity-only recovery: ensure an existing scene matter is present in the manager table.
|
||||
/// This helps recover after Unity script/domain reload where Dictionaries are not serialized.
|
||||
/// </summary>
|
||||
public void RegisterExistingMatter(CECMatter matter)
|
||||
{
|
||||
if (matter == null)
|
||||
return;
|
||||
|
||||
int mid = matter.GetMatterID();
|
||||
if (mid == 0)
|
||||
return;
|
||||
|
||||
m_MatterTab[mid] = matter;
|
||||
}
|
||||
public bool ProcessMessage(ECMSG Msg)
|
||||
{
|
||||
if (Msg.iSubID == 0)
|
||||
|
||||
@@ -4,6 +4,7 @@ using BrewMonster;
|
||||
using BrewMonster.Managers;
|
||||
using CSNetwork.GPDataType;
|
||||
using CSNetwork.Protocols;
|
||||
using PerfectWorld.Scripts;
|
||||
using UnityEngine;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -229,8 +230,8 @@ public class CECObject : MonoBehaviour
|
||||
return ((CECPlayer)pObject).GetCharacterID();
|
||||
else if (pObject.IsNPC())
|
||||
return ((CECNPC)pObject).GetNPCID();
|
||||
//else if (pObject.IsMatter())
|
||||
// return ((CECMatter*)pObject)->GetMatterID();
|
||||
else if (pObject.IsMatter())
|
||||
return ((CECMatter)pObject).GetMatterID();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ namespace BrewMonster
|
||||
|
||||
{
|
||||
protected int m_iMoneyCnt; // Amount of money the player has
|
||||
protected int m_iMaxMoney;
|
||||
public int GetMoneyAmount() { return m_iMoneyCnt; }
|
||||
|
||||
public int GetMaxMoneyAmount() { return m_iMaxMoney; }
|
||||
public byte GetShapeMask()
|
||||
{
|
||||
// restore the original data from 8~15 bit
|
||||
|
||||
@@ -250,6 +250,10 @@ namespace BrewMonster
|
||||
{
|
||||
return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0;
|
||||
}
|
||||
public bool IsInvisible()
|
||||
{
|
||||
return (m_dwStates & PlayerNPCState.GP_STATE_INVISIBLE) != 0;
|
||||
}
|
||||
|
||||
public bool IsValidAction(int iIndex)
|
||||
{
|
||||
|
||||
@@ -302,6 +302,16 @@ namespace CSNetwork.C2SCommand
|
||||
public byte pvpMask;
|
||||
}
|
||||
|
||||
// Gather material command
|
||||
public struct cmd_gather_material
|
||||
{
|
||||
public int mid; // Matter ID
|
||||
public ushort tool_pack; // Tool package
|
||||
public ushort tool_index; // Tool index
|
||||
public int tool_type; // Tool type ID
|
||||
public int id_task; // Task ID
|
||||
}
|
||||
|
||||
public struct cmd_error_msg
|
||||
{
|
||||
public int iMessage;
|
||||
|
||||
@@ -743,5 +743,18 @@ namespace CSNetwork.C2SCommand
|
||||
// Serialize the command and return the serialized data
|
||||
return SerializeCommand(CommandID.AUTO_TEAM_SET_GOAL, pCmd);
|
||||
}
|
||||
|
||||
public static Octets c2s_CmdGatherMaterial(int idMatter, int iToolPack, int iToolIdx, int idTool, int idTask)
|
||||
{
|
||||
var cmd = new cmd_gather_material
|
||||
{
|
||||
mid = idMatter,
|
||||
tool_pack = (ushort)iToolPack,
|
||||
tool_index = (ushort)iToolIdx,
|
||||
tool_type = idTool,
|
||||
id_task = idTask
|
||||
};
|
||||
return SerializeCommand(CommandID.GATHER_MATERIAL, cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1448,6 +1448,11 @@ namespace CSNetwork.GPDataType
|
||||
return (id & 0x80000000) != 0 && (id & 0x40000000) == 0;
|
||||
}
|
||||
|
||||
public static bool ISMONEYTID(int tid)
|
||||
{
|
||||
return tid == 3044;
|
||||
}
|
||||
|
||||
public static bool ISMATTERID(int id)
|
||||
{
|
||||
return (id & 0xC0000000) == 0xC0000000;
|
||||
|
||||
@@ -276,6 +276,12 @@ namespace CSNetwork
|
||||
gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.CreateGetMallShopping(count, goodsArray);
|
||||
SendProtocol(gamedatasendRequest);
|
||||
}
|
||||
public void c2s_CmdGatherMaterial(int idMatter, int iToolPack, int idToolIndex, int idTool, int idTask)
|
||||
{
|
||||
gamedatasend gamedatasendRequest = new gamedatasend();
|
||||
gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_CmdGatherMaterial(idMatter, iToolPack, idToolIndex, idTool, idTask);
|
||||
SendProtocol(gamedatasendRequest);
|
||||
}
|
||||
|
||||
public void RequestOwnItemInfoAsync(
|
||||
byte byPackage,
|
||||
|
||||
@@ -78,8 +78,10 @@ namespace BrewMonster.Managers
|
||||
(iAliveFlag == 2 && !(pObject as CECPlayer).IsDead()))
|
||||
return null;
|
||||
}
|
||||
//else if (GPDataTypeHelper.ISMATTERID(idObject))
|
||||
// pObject = GetMatterMan()->GetMatter(idObject);
|
||||
else if (GPDataTypeHelper.ISMATTERID((int)idObject))
|
||||
{
|
||||
pObject = EC_ManMatter.GetMatter((int)idObject);
|
||||
}
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
@@ -360,7 +360,10 @@ namespace BrewMonster.Network
|
||||
{
|
||||
Instance._gameSession.c2s_SendCmdAutoTeamSetGoal(type, goal_id, op);//{ ::c2s_SendCmdAutoTeamSetGoal(type, goal_id, op); }
|
||||
}
|
||||
|
||||
public static void c2s_CmdGatherMaterial(int idMatter, int iToolPack, int idToolIndex, int idTool, int idTask)
|
||||
{
|
||||
Instance._gameSession.c2s_CmdGatherMaterial(idMatter, iToolPack, idToolIndex, idTool, idTask);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static void GetRoleBaseInfo(int iNumRole, List<int> aRoleIDs)
|
||||
|
||||
@@ -1,140 +1,286 @@
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using ModelRenderer.Scripts.Common;
|
||||
using PerfectWorld.Scripts.Managers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PerfectWorld.Scripts
|
||||
{
|
||||
public class CECMatter : CECObject
|
||||
{
|
||||
// Matter information got from server
|
||||
public struct INFO
|
||||
{
|
||||
public int mid; // Matter id
|
||||
public int tid; // Template id
|
||||
}
|
||||
|
||||
protected EC_ManMatter m_pMatterMan;
|
||||
protected INFO m_MatterInfo;
|
||||
|
||||
public void SetMatterInfo(INFO matterInfo)
|
||||
{
|
||||
m_MatterInfo = matterInfo;
|
||||
}
|
||||
|
||||
public static async Task<CECMatter> Init(info_matter Info)
|
||||
{
|
||||
INFO matterInfo = new INFO();
|
||||
matterInfo.mid = Info.mid;
|
||||
matterInfo.tid = Info.tid & 0x0000ffff;
|
||||
// get the matter template from elementdataman
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
var matterData = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)matterInfo.tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
if (matterData != null)
|
||||
{
|
||||
var matterType = matterData.GetType();
|
||||
var fileMatterField = matterType.GetField("file_matter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fileMatterField == null)
|
||||
{
|
||||
fileMatterField = matterType.GetField("file_model", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
if (fileMatterField != null)
|
||||
{
|
||||
var fileMatterValue = fileMatterField.GetValue(matterData);
|
||||
string filePath = ByteToStringUtils.ByteArrayToCP936String((byte[])fileMatterValue);
|
||||
|
||||
var matterPrefab = await AddressableManager.Instance.LoadPrefabAsync(AFile.NormalizePath(filePath.ToLower(), true));
|
||||
if (matterPrefab != null)
|
||||
{
|
||||
var matterObject = Instantiate(matterPrefab);
|
||||
matterObject.transform.position = new Vector3(Info.pos.x, Info.pos.y, Info.pos.z);
|
||||
matterObject.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
matterObject.transform.localRotation = Quaternion.identity;
|
||||
matterObject.SetActive(true);
|
||||
|
||||
// Add a collider if it doesn't have one
|
||||
if (matterObject.GetComponent<Collider>() == null)
|
||||
{
|
||||
var collider = matterObject.AddComponent<BoxCollider>();
|
||||
collider.size = matterObject.GetComponentInChildren<Renderer>().bounds.size;
|
||||
}
|
||||
|
||||
// Create text object to display item name above the cube
|
||||
// CreateItemNameText(matterObject, info.tid);
|
||||
|
||||
// Add a script to handle click events
|
||||
// MatterCubeClickHandler clickHandler = matterObject.AddComponent<MatterCubeClickHandler>();
|
||||
// clickHandler.Initialize(Info.mid, this);
|
||||
CECMatter matterScript = matterObject.AddComponent<CECMatter>();
|
||||
matterScript.SetMatterInfo(matterInfo);
|
||||
|
||||
// Store reference to the cube
|
||||
// matterGameObjects[info.mid] = matterObject;
|
||||
|
||||
return matterScript;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Failed to load matter prefab from path: {filePath}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"file_matter field not found on matter data type {matterType.FullName}");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private new void Update()
|
||||
{
|
||||
bool inputPressed = false;
|
||||
Vector2 screenPosition = Vector2.zero;
|
||||
|
||||
// Check for touch input (mobile)
|
||||
if (Input.touchCount > 0)
|
||||
{
|
||||
Touch touch = Input.GetTouch(0);
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
{
|
||||
inputPressed = true;
|
||||
screenPosition = touch.position;
|
||||
}
|
||||
}
|
||||
// Check for mouse input (desktop)
|
||||
else if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
inputPressed = true;
|
||||
screenPosition = Input.mousePosition;
|
||||
}
|
||||
|
||||
if (inputPressed)
|
||||
{
|
||||
Camera mainCamera = Camera.main;
|
||||
if (mainCamera == null)
|
||||
return;
|
||||
|
||||
Ray ray = mainCamera.ScreenPointToRay(screenPosition);
|
||||
|
||||
RaycastHit[] hits = Physics.RaycastAll(ray);
|
||||
|
||||
foreach (RaycastHit hit in hits)
|
||||
{
|
||||
if (hit.collider.gameObject == this.gameObject ||
|
||||
hit.collider.transform.IsChildOf(this.transform))
|
||||
{
|
||||
Debug.Log($"CECMatter::RaycastHit():: mid: {m_MatterInfo.mid}");
|
||||
UnityGameSession.RequestPickupItem(m_MatterInfo.mid, m_MatterInfo.tid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BrewMonster;
|
||||
using BrewMonster.Network;
|
||||
using BrewMonster.Scripts;
|
||||
using CSNetwork.GPDataType;
|
||||
using ModelRenderer.Scripts.Common;
|
||||
using PerfectWorld.Scripts.Managers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace PerfectWorld.Scripts
|
||||
{
|
||||
public class CECMatter : CECObject
|
||||
{
|
||||
// Matter information got from server
|
||||
public struct INFO
|
||||
{
|
||||
public int mid; // Matter id
|
||||
public int tid; // Template id
|
||||
}
|
||||
|
||||
protected EC_ManMatter m_pMatterMan;
|
||||
protected INFO m_MatterInfo;
|
||||
protected int m_iLevelReq;
|
||||
protected float m_fGatherDist;
|
||||
protected uint m_dwMatterType; // Matter type flags / Matter type flags
|
||||
private bool m_registeredToManMatter = false;
|
||||
|
||||
// Matter type constants / Matter type constants
|
||||
public const uint MATTER_UNKNOWN = 0;
|
||||
public const uint MATTER_ITEM = 1;
|
||||
public const uint MATTER_MINE = 2;
|
||||
public const uint MATTER_MONEY = 3;
|
||||
public const uint MATTER_TYPEMASK = 0xff;
|
||||
|
||||
// Constructor / Constructor
|
||||
public CECMatter()
|
||||
{
|
||||
m_iCID = Class_ID.OCID_MATTER;
|
||||
}
|
||||
|
||||
// Awake is called when the component is initialized / Awake is called when the component is initialized
|
||||
private void Awake()
|
||||
{
|
||||
m_iCID = Class_ID.OCID_MATTER; // Ensure CID is set after Unity initialization / Ensure CID is set after Unity initialization
|
||||
TryRegisterToManMatter();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
TryRegisterToManMatter();
|
||||
}
|
||||
|
||||
private void TryRegisterToManMatter()
|
||||
{
|
||||
if (m_registeredToManMatter)
|
||||
return;
|
||||
|
||||
// Only register once we have a valid mid.
|
||||
int mid = GetMatterID();
|
||||
if (mid == 0)
|
||||
return;
|
||||
|
||||
var mono = BrewMonster.Managers.EC_ManMessageMono.Instance;
|
||||
if (mono == null || mono.EC_ManMatter == null)
|
||||
return;
|
||||
|
||||
mono.EC_ManMatter.RegisterExistingMatter(this);
|
||||
m_registeredToManMatter = true;
|
||||
}
|
||||
|
||||
// Override SetUpCECObject to set class ID / Override SetUpCECObject to set class ID
|
||||
public override void SetUpCECObject()
|
||||
{
|
||||
base.SetUpCECObject();
|
||||
m_iCID = Class_ID.OCID_MATTER; // Set after base call to override the reset / Set after base call to override the reset
|
||||
}
|
||||
|
||||
public void SetMatterInfo(INFO matterInfo)
|
||||
{
|
||||
m_MatterInfo = matterInfo;
|
||||
}
|
||||
public int GetTemplateID()
|
||||
{
|
||||
return m_MatterInfo.tid;
|
||||
}
|
||||
|
||||
public int GetLevelReq()
|
||||
{
|
||||
return m_iLevelReq;
|
||||
}
|
||||
|
||||
public float GetGatherDist()
|
||||
{
|
||||
// 采集/拾取距离:某些情况下(例如场景预制体未走 Init 流程)m_fGatherDist 可能为 0。
|
||||
// Gather/pickup distance: in some cases (e.g. scene prefab not created via Init) m_fGatherDist may be 0.
|
||||
// Provide a safe default consistent with native behavior.
|
||||
return m_fGatherDist > 0.01f ? m_fGatherDist : 3.0f;
|
||||
}
|
||||
|
||||
// Is this matter a mine? / Is this matter a mine?
|
||||
public bool IsMine()
|
||||
{
|
||||
return (m_dwMatterType & MATTER_TYPEMASK) == MATTER_MINE;
|
||||
}
|
||||
|
||||
// Is this matter an item? / Is this matter an item?
|
||||
public bool IsItem()
|
||||
{
|
||||
return (m_dwMatterType & MATTER_TYPEMASK) == MATTER_ITEM;
|
||||
}
|
||||
|
||||
// Is this matter money? / Is this matter money?
|
||||
public bool IsMoney()
|
||||
{
|
||||
return (m_dwMatterType & MATTER_TYPEMASK) == MATTER_MONEY;
|
||||
}
|
||||
public static async Task<CECMatter> Init(info_matter Info)
|
||||
{
|
||||
INFO matterInfo = new INFO();
|
||||
matterInfo.mid = Info.mid;
|
||||
matterInfo.tid = Info.tid & 0x0000ffff;
|
||||
// get the matter template from elementdataman
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
var matterData = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)matterInfo.tid, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
|
||||
// Determine matter type based on DataType / Determine matter type based on DataType
|
||||
uint dwMatterType = MATTER_UNKNOWN;
|
||||
if (DataType == DATA_TYPE.DT_MINE_ESSENCE)
|
||||
{
|
||||
dwMatterType = MATTER_MINE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default to ITEM for other essence types / Default to ITEM for other essence types
|
||||
dwMatterType = MATTER_ITEM;
|
||||
}
|
||||
// 钱币掉落 / Money drop
|
||||
// 服务器用特殊 tid 表示金币/银币拾取物;不应占用背包格子。
|
||||
// The server uses a special tid to represent money matters; they should not consume inventory slots.
|
||||
if (GPDataTypeHelper.ISMONEYTID(matterInfo.tid))
|
||||
{
|
||||
dwMatterType = MATTER_MONEY;
|
||||
}
|
||||
|
||||
if (matterData != null)
|
||||
{
|
||||
var matterDataType = matterData.GetType();
|
||||
var fileMatterField = matterDataType.GetField("file_matter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fileMatterField == null)
|
||||
{
|
||||
fileMatterField = matterDataType.GetField("file_model", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
}
|
||||
|
||||
if (fileMatterField != null)
|
||||
{
|
||||
var fileMatterValue = fileMatterField.GetValue(matterData);
|
||||
string filePath = ByteToStringUtils.ByteArrayToCP936String((byte[])fileMatterValue);
|
||||
|
||||
var matterPrefab = await AddressableManager.Instance.LoadPrefabAsync(AFile.NormalizePath(filePath.ToLower(), true));
|
||||
if (matterPrefab != null)
|
||||
{
|
||||
var matterObject = Instantiate(matterPrefab);
|
||||
matterObject.transform.position = new Vector3(Info.pos.x, Info.pos.y, Info.pos.z);
|
||||
matterObject.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
matterObject.transform.localRotation = Quaternion.identity;
|
||||
matterObject.SetActive(true);
|
||||
|
||||
// Add a collider if it doesn't have one
|
||||
if (matterObject.GetComponent<Collider>() == null)
|
||||
{
|
||||
var collider = matterObject.AddComponent<BoxCollider>();
|
||||
collider.size = matterObject.GetComponentInChildren<Renderer>().bounds.size;
|
||||
}
|
||||
|
||||
// Create text object to display item name above the cube
|
||||
// CreateItemNameText(matterObject, info.tid);
|
||||
|
||||
// Add a script to handle click events
|
||||
// MatterCubeClickHandler clickHandler = matterObject.AddComponent<MatterCubeClickHandler>();
|
||||
// clickHandler.Initialize(Info.mid, this);
|
||||
CECMatter matterScript = matterObject.AddComponent<CECMatter>();
|
||||
// Set CID immediately after AddComponent (before SetUpCECObject resets it) / Set CID immediately after AddComponent (before SetUpCECObject resets it)
|
||||
matterScript.m_iCID = Class_ID.OCID_MATTER;
|
||||
matterScript.SetMatterInfo(matterInfo);
|
||||
matterScript.m_dwMatterType = dwMatterType; // Set matter type / Set matter type
|
||||
|
||||
// Set level requirement and gather distance for mines / Set level requirement and gather distance for mines
|
||||
if (dwMatterType == MATTER_MINE && DataType == DATA_TYPE.DT_MINE_ESSENCE)
|
||||
{
|
||||
var levelReqField = matterData.GetType().GetField("level_required", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (levelReqField != null)
|
||||
{
|
||||
matterScript.m_iLevelReq = (int)levelReqField.GetValue(matterData);
|
||||
}
|
||||
var gatherDistField = matterData.GetType().GetField("gather_dist", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (gatherDistField != null)
|
||||
{
|
||||
float gatherDist = (float)gatherDistField.GetValue(matterData);
|
||||
matterScript.m_fGatherDist = gatherDist > 3.0f ? gatherDist - 1.0f : 3.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
matterScript.m_fGatherDist = 3.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// For non-mine items, set a default pickup distance / For non-mine items, set a default pickup distance
|
||||
matterScript.m_fGatherDist = 3.0f; // Default pickup distance / Default pickup distance
|
||||
}
|
||||
|
||||
matterScript.SetUpCECObject(); // This will reset m_iCID, so we set it again after / This will reset m_iCID, so we set it again after
|
||||
// Force set CID again after SetUpCECObject (which resets it to OCID_OBJECT) / Force set CID again after SetUpCECObject (which resets it to OCID_OBJECT)
|
||||
matterScript.m_iCID = Class_ID.OCID_MATTER;
|
||||
|
||||
// Store reference to the cube
|
||||
// matterGameObjects[info.mid] = matterObject;
|
||||
|
||||
return matterScript;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Failed to load matter prefab from path: {filePath}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"file_matter field not found on matter data type {matterDataType.FullName}");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private new void Update()
|
||||
{
|
||||
// Recovery: after Unity domain reload, manager dictionaries reset but scene objects persist.
|
||||
// Keep trying until we successfully register.
|
||||
if (!m_registeredToManMatter)
|
||||
TryRegisterToManMatter();
|
||||
|
||||
// Check for touch input (mobile)
|
||||
if (Input.touchCount > 0)
|
||||
{
|
||||
Touch touch = Input.GetTouch(0);
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
{
|
||||
// Touch handling intentionally disabled for now. / Touch handling intentionally disabled for now.
|
||||
}
|
||||
}
|
||||
// Check for mouse input (desktop)
|
||||
// else if (Input.GetMouseButtonDown(0))
|
||||
// {
|
||||
// inputPressed = true;
|
||||
// screenPosition = Input.mousePosition;
|
||||
// }
|
||||
//
|
||||
// if (inputPressed)
|
||||
// {
|
||||
// Camera mainCamera = Camera.main;
|
||||
// if (mainCamera == null)
|
||||
// return;
|
||||
//
|
||||
// Ray ray = mainCamera.ScreenPointToRay(screenPosition);
|
||||
//
|
||||
// RaycastHit[] hits = Physics.RaycastAll(ray);
|
||||
//
|
||||
// foreach (RaycastHit hit in hits)
|
||||
// {
|
||||
// if (hit.collider.gameObject == this.gameObject ||
|
||||
// hit.collider.transform.IsChildOf(this.transform))
|
||||
// {
|
||||
// Debug.Log($"CECMatter::RaycastHit():: mid: {m_MatterInfo.mid}");
|
||||
// UnityGameSession.RequestPickupItem(m_MatterInfo.mid, m_MatterInfo.tid);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public int GetMatterID()
|
||||
{
|
||||
return m_MatterInfo.mid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5304,5 +5304,67 @@ namespace BrewMonster
|
||||
CANDO_REBUILDPET = 19,
|
||||
CANDO_SWITCH_PARALLEL_WORLD = 20;
|
||||
}
|
||||
public bool CanTakeItem(int idItem, int iAmount)
|
||||
{
|
||||
bool bCanPick = false;
|
||||
|
||||
if (GPDataTypeHelper.ISMONEYTID(idItem))
|
||||
{
|
||||
if (GetMoneyAmount() < GetMaxMoneyAmount())
|
||||
bCanPick = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PackInventory.CanAddItem(idItem, iAmount, false) >= 0)
|
||||
bCanPick = true;
|
||||
}
|
||||
|
||||
return bCanPick;
|
||||
}
|
||||
public bool FindMineTool(int tidMine, ref int piPack, ref int piIndex, ref int pidTool)
|
||||
{
|
||||
if (tidMine == 0)
|
||||
return false;
|
||||
|
||||
DATA_TYPE DataType = DATA_TYPE.DT_INVALID;
|
||||
object pDataPtr = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)tidMine, ID_SPACE.ID_SPACE_ESSENCE, ref DataType);
|
||||
|
||||
if (DataType != DATA_TYPE.DT_MINE_ESSENCE)
|
||||
{
|
||||
//ASSERT(DataType != DATA_TYPE.DT_MINE_ESSENCE);
|
||||
return false;
|
||||
}
|
||||
|
||||
MINE_ESSENCE pData = (MINE_ESSENCE)pDataPtr;
|
||||
int idTool = (int)pData.id_equipment_required;
|
||||
bool bRet = true;
|
||||
|
||||
if (idTool != 0)
|
||||
{
|
||||
int iIndex = PackInventory.FindItem(idTool);
|
||||
if (iIndex >= 0)
|
||||
{
|
||||
piPack = EC_Inventory.Inventory_type.IVTRTYPE_PACK;
|
||||
piIndex = iIndex;
|
||||
pidTool = idTool;
|
||||
}
|
||||
else if ((iIndex = TaskInventory.FindItem(idTool)) >= 0)
|
||||
{
|
||||
piPack = EC_Inventory.Inventory_type.IVTRTYPE_TASKPACK;
|
||||
piIndex = iIndex;
|
||||
pidTool = idTool;
|
||||
}
|
||||
else
|
||||
bRet = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
piPack = 0;
|
||||
piIndex = 0;
|
||||
pidTool = 0;
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user