Merge remote-tracking branch 'origin/develop' into feature/movement

# Conflicts:
#	Assets/PerfectWorld/Scripts/Common/CECObject.cs
#	Assets/PerfectWorld/Scripts/NPC/CECNPC.cs
#	Assets/Scripts/Move/CECHostMove.cs
This commit is contained in:
VDH
2025-10-09 11:31:55 +07:00
46 changed files with 4505 additions and 232 deletions
+463 -45
View File
@@ -1,16 +1,17 @@
using BrewMonster.Network;
using BrewMonster;
using BrewMonster.Network;
using CSNetwork;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
using PerfectWorld.Scripts.Managers;
using PerfectWorld.Scripts.Player;
using PerfectWorld.Scripts.Task;
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
@@ -30,7 +31,18 @@ public class CECHostPlayer : EC_Player
PlayerStateMachine _playerStateMachine;
PlayerMoveState _moveState;
PlayerIdleState _idleState;
CECHostMove m_MoveCtrl;
public CECHostMove m_MoveCtrl;
CECHPWorkMan m_pWorkMan; // Host work manager
uint m_dwLIES; // Logic-influence extend states
FACTION_FORTRESS_ENTER m_fortressEnter; // ½øÈë»ùµØÐÅÏ¢
PVPINFO m_pvp; // pvp information
bool m_bInSanctuary = false; // true, player is in sanctuary
int m_idFaction = 0; // ID of player's faction
public bool m_bPrepareFight = false; // true, prepare to fight
int m_iJumpCount = 0;
bool m_bJumpInWater = false;
public A3DVECTOR3 m_vVelocity; // Velocity
float playerSpeed = 5.0f;
float jumpHeight = 1.5f;
@@ -40,6 +52,9 @@ public class CECHostPlayer : EC_Player
bool isGrounded = false;
bool isRun = false;
Vector3 m_vLastSevPos;
public CDR_INFO m_CDRInfo;
public GNDINFO m_GndInfo;
public float m_fVertSpeed = 0f;
// ====== Ground cast config ======
[Header("Ground Cast")]
@@ -214,7 +229,7 @@ public class CECHostPlayer : EC_Player
case int value when value == EC_MsgDef.MSG_HST_TASKDATA:
{
OnMsgHstTaskData(Msg);
Debug.Log("[Dat]- OnMsgHstTaskData");
Debug.LogError("[Dat]- OnMsgHstTaskData");
break;
}
case int value when value == EC_MsgDef.MSG_HST_ITEMOPERATION:
@@ -331,34 +346,34 @@ public class CECHostPlayer : EC_Player
break;
}
case CommandID.EQUIP_ITEM:
{
{
byte index_inv = data[0];
byte index_equip = data[1];
// Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT
var invItem = EC_Inventory.GetItem(EC_Inventory.PACK_INVENTORY, index_inv, true);
var equipItem = EC_Inventory.GetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, true);
if (invItem != null)
{
invItem.Package = EC_Inventory.PACK_EQUIPMENT;
invItem.Slot = index_equip;
EC_Inventory.SetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, invItem);
}
if (equipItem != null)
{
equipItem.Package = EC_Inventory.PACK_INVENTORY;
equipItem.Slot = index_inv;
EC_Inventory.SetItem(EC_Inventory.PACK_INVENTORY, index_inv, equipItem);
}
// Update client-side data: move item between PACK_INVENTORY and PACK_EQUIPMENT
var invItem = EC_Inventory.GetItem(EC_Inventory.PACK_INVENTORY, index_inv, true);
var equipItem = EC_Inventory.GetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, true);
if (invItem != null)
{
invItem.Package = EC_Inventory.PACK_EQUIPMENT;
invItem.Slot = index_equip;
EC_Inventory.SetItem(EC_Inventory.PACK_EQUIPMENT, index_equip, invItem);
}
if (equipItem != null)
{
equipItem.Package = EC_Inventory.PACK_INVENTORY;
equipItem.Slot = index_inv;
EC_Inventory.SetItem(EC_Inventory.PACK_INVENTORY, index_inv, equipItem);
}
// Trigger UI refresh if an EC_InventoryUI is present in scene
var ui = GameObject.FindObjectOfType<EC_InventoryUI>();
if (ui != null)
{
ui.RefreshAll();
}
// Trigger UI refresh if an EC_InventoryUI is present in scene
var ui = GameObject.FindObjectOfType<EC_InventoryUI>();
if (ui != null)
{
ui.RefreshAll();
}
break;
}
break;
}
}
}
public void OnMsgHstOwnItemInfo(ECMSG Msg)
@@ -428,7 +443,7 @@ public class CECHostPlayer : EC_Player
}
private void SetPos(Vector3 pos)
public void SetPos(Vector3 pos)
{
transform.position = pos;
}
@@ -461,6 +476,13 @@ public class CECHostPlayer : EC_Player
{
visual.InitHostPlayerEventDoneHandler();
}
// Create work manager
m_pWorkMan = new CECHPWorkMan(this);
if (m_pWorkMan == null)
{
return;
}
}
private void JoystickStartDrag(JoystickPressEvent joystickPressEvent)
@@ -497,7 +519,7 @@ public class CECHostPlayer : EC_Player
//cmd_task_data* pCmd = (cmd_task_data*)Msg.dwParam1;
//ASSERT(pCmd);
//int iActiveListSize = (int)pCmd->active_list_size;
//int iActiveListSize = (int)pCmd.active_list_size;
//BYTE* pData = (BYTE*)pCmd + sizeof(size_t);
//void* pActiveListbuf = pData;
//pData += iActiveListSize;
@@ -523,30 +545,30 @@ public class CECHostPlayer : EC_Player
//pData += iStorageTasksListSize;
//A3DRELEASE(m_pTaskInterface);
return;
var m_pTaskInterface = new CECTaskInterface(this);
if (!m_pTaskInterface.Init(null, 0, null, 0,
null, 0, null, 0, null, 0))
{
//a_LogOutput(1, "CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface");
return;
}
//todo
//var m_pTaskInterface = new CECTaskInterface(this);
m_pTaskInterface.CheckPQEnterWorldInit();
//if (!m_pTaskInterface.Init(null, 0, null, 0,
// null, 0, null, 0, null, 0))
//{
// //a_LogOutput(1, "CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface");
// return;
//}
//m_pTaskInterface.CheckPQEnterWorldInit();
//// check if player has equipped goblin
//if (m_pEquipPack->GetItem(EQUIPIVTR_GOBLIN) != NULL)
//if (m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN) != NULL)
//{
// CECIvtrGoblin* pIvtrGoblin = (CECIvtrGoblin*)m_pEquipPack->GetItem(EQUIPIVTR_GOBLIN);
// CECIvtrGoblin* pIvtrGoblin = (CECIvtrGoblin*)m_pEquipPack.GetItem(EQUIPIVTR_GOBLIN);
// m_pGoblin = new CECHostGoblin();
// m_pGoblin->Init(pIvtrGoblin->GetTemplateID(), pIvtrGoblin, this);
// m_pGoblin.Init(pIvtrGoblin.GetTemplateID(), pIvtrGoblin, this);
//}
//// Note: this command now is also used as the end flag of responding
//// for GET_ALL_DATA request
//g_pGame->GetGameSession()->LoadConfigData();
//g_pGame.GetGameSession().LoadConfigData();
//// ¸ù¾Ý×°±¸°ü¹ü¸üÐÂ×°±¸¼¼Äܵ½¼¼ÄÜÁбí
//if (UpdateEquipSkills())
@@ -557,12 +579,357 @@ public class CECHostPlayer : EC_Player
//cmd_task_var_data* pCmd = (cmd_task_var_data*)Msg.dwParam1;
//ASSERT(pCmd);
//if (m_pTaskInterface)
// OnServerNotify(m_pTaskInterface, pCmd->data, pCmd->size);
// OnServerNotify(m_pTaskInterface, pCmd.data, pCmd.size);
//else
// ASSERT(m_pTaskInterface);
}
}
#endregion
private bool NormalAttackObject(int idTarget, bool bForceAttack, bool bMoreClose = false)
{
if (idTarget == 0 || idTarget == m_PlayerInfo.cid)
{
// We should have check target isn't dead
return false;
}
//if (!EC_Game.GetGameRun().GetWorld().GetObject(idTarget, 1))
// return false;
bool bStartNewWork = false;
bool bUseAutoPF = false;
//CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper();
//if (CECAutoPolicy::GetInstance().IsAutoPolicyEnabled() && pWrapper.GetAttackError() >= 2)
bUseAutoPF = true;
CECHPWorkTrace pWorkTrace = null;
CECHPWork pWork = null;
if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT)) != null)
{
pWorkTrace = pWork as CECHPWorkTrace;
}
else if ((pWork = m_pWorkMan.GetWork(CECHPWork.Host_work_ID.WORK_HACKOBJECT)) != null)
{
if ((pWork as CECHPWorkMelee).GetTarget() == idTarget)
return false; // Host is attacking the target
pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT);
bStartNewWork = true;
}
else if (m_pWorkMan.CanStartWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT))
{
pWorkTrace = (CECHPWorkTrace)m_pWorkMan.CreateWork(CECHPWork.Host_work_ID.WORK_TRACEOBJECT);
bStartNewWork = true;
}
if (pWorkTrace != null)
{
pWorkTrace.SetTraceTarget(pWorkTrace.CreatTraceTarget(idTarget, CECHPWorkTrace.Trace_reason.TRACE_ATTACK, bForceAttack), bUseAutoPF);
pWorkTrace.SetMoveCloseFlag(bMoreClose);
if (bStartNewWork)
m_pWorkMan.StartWork_p1(pWorkTrace);
return true;
}
return false;
}
public int AttackableJudge(int idTarget, bool bForceAttack)
{
if (CannotAttack())
return 0;
//if (CDlgAutoHelp::IsAutoHelp())
// return 0;
if (idTarget == 0 || idTarget == m_PlayerInfo.cid)
return -1;
CECObject pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1);
if (!pObject)
return -1;
// If target is pet, it's attacked possibility depends on it's monster
if (GPDataTypeHelper.ISNPCID(idTarget))
{
CECNPC pNPC = (CECNPC)pObject;
int idMaster = pNPC.GetMasterID();
if (idMaster != 0)
{
// master¿ÉÄÜÊÇhostplayer
if (idMaster == m_PlayerInfo.cid)
return 0;
//// Follow pet cannot be attacked
//if (pNPC.IsPetNPC() && ((CECPet)pNPC).IsFollowPet())
// return 0;
idTarget = idMaster;
pObject = EC_ManMessageMono.Instance.GetObject(idTarget, 1);
if (!pObject)
return -1;
}
}
int iRet = 0;
if (GPDataTypeHelper.ISNPCID(idTarget))
{
CECNPC pNPC = (CECNPC)pObject;
// If this npc is host's pet, cannot be attacked
//if (pNPC.GetMasterID() == m_PlayerInfo.cid)
// return 0;
// If it's a pet and can not be attacked, pet can be attacked only if it's a fighting pet
//if (pNPC.IsPetNPC() && !((CECPet)pNPC).CanBeAttacked())
// return 0;
if (IsInBattle()) // Host is in battle
{
if (InSameBattleCamp(pNPC))
iRet = 0;
else
{
if (pNPC.IsMonsterNPC())
iRet = 1;
else if (pNPC.IsServerNPC() && (IsInFortress() || pNPC.GetRoleInBattle() == 8)) // ¶Ô·þÎñÐÍNPCµÄ¹¥»÷£¬°ïÅÉ»ùµØ»ò³Çսʱ¿ÉÓÃ
iRet = 1;
else
iRet = 0;
}
}
else if (pNPC.IsServerNPC())
{
// In sanctuary we cannot attack NPCs
if (!IsPVPOpen() || m_bInSanctuary || !bForceAttack)
iRet = 0;
else
iRet = 1;
}
else // Is monster
{
iRet = 1;
}
if (iRet == 1 && pNPC.GetOwnerFaction() > 0)
{
// Õë¶Ô°ïÅÉ PVP Õ½ÕùÖнûÖ¹²¿·Ö¹¥»÷
if (GetFactionID() == pNPC.GetOwnerFaction() || // ²»¹¥»÷ͬ°ï¹Ö
pNPC.IsFactionPVPMineCar() && !CanAttackFactionPVPMineCar() || // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï¿ó³µÇé¿ö
pNPC.IsFactionPVPMineBase() && !CanAttackFactionPVPMineBase())
{ // ÎÞ·¨ÔÙ¹¥»÷Ëû°ï´æ¿óµãÇé¿ö
iRet = 0;
}
}
}
// TO DO: fix later
//else if (GPDataTypeHelper.ISPLAYERID(idTarget))
//{
// // Check duel at first
// if (m_pvp.iDuelState == Duel_state.DUEL_ST_INDUEL && m_pvp.idDuelOpp == idTarget)
// return 1;
// else if (m_pvp.iDuelState == Duel_state.DUEL_ST_STOPPING && m_pvp.idDuelOpp == idTarget)
// return 0;
// // In sanctuary we cannot attack other players
// if (m_bInSanctuary)
// return 0;
// //ASSERT(pObject.GetClassID() == CECObject::OCID_ELSEPLAYER);
// EC_ElsePlayer pPlayer = (EC_ElsePlayer)pObject;
// ROLEBASICPROP bp = pPlayer.GetBasicProps();
// EC_GAME_SETTING gs = g_pGame.GetConfigs().GetGameSettings();
// if (m_pvp.bFreePVP)
// {
// if (IsTeamMember(idTarget))
// return 0;
// // In free pvp mode, for example, host is in arena.
// if (bForceAttack)
// iRet = 1;
// else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID()))
// iRet = 0;
// else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah())
// iRet = 0;
// else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID()))
// iRet = 0;
// else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce())
// iRet = 0;
// else
// iRet = 1;
// }
// else if (m_iBattleCamp != GP_BATTLE_CAMP_NONE)
// {
// // Host is in battle
// int iCamp = pPlayer.GetBattleCamp();
// if (iCamp != GP_BATTLE_CAMP_NONE && iCamp != m_iBattleCamp)
// iRet = 1;
// else
// iRet = 0;
// }
// else // Normal mode
// {
// if (IsTeamMember(idTarget))
// return 0;
// if (!IsPVPOpen() || !pPlayer.IsPVPOpen() || m_BasicProps.iLevel < EC_MAXNOPKLEVEL || bp.iLevel < EC_MAXNOPKLEVEL)
// iRet = 0;
// else if (bForceAttack)
// iRet = 1;
// else if (!gs.bAtk_Player)
// iRet = 0;
// else if (gs.bAtk_NoMafia && IsFactionMember(pPlayer.GetFactionID()))
// iRet = 0;
// else if (gs.bAtk_NoWhite && !pPlayer.IsInvader() && !pPlayer.IsPariah())
// iRet = 0;
// else if (gs.bAtk_NoAlliance && g_pGame.GetFactionMan().IsFactionAlliance(pPlayer.GetFactionID()))
// iRet = 0;
// else if (gs.bAtk_NoForce && GetForce() > 0 && GetForce() == pPlayer.GetForce())
// iRet = 0;
// else
// iRet = 1;
// }
//}
else
{
return -1;
}
return iRet;
}
private float A3d_Magnitude(A3DVECTOR3 v)
{
return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
public int GetCharacterID(){ return m_PlayerInfo.cid; }
public bool CannotAttack() { return (m_dwLIES & (uint)Logic_Influence_Extned_states.LIES_DISABLEFIGHT) != 0; }
public bool CanTouchTarget(A3DVECTOR3 vHostPos, A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f)
{
float fDist = A3d_Magnitude(vTargetPos - vHostPos);
switch (iReason)
{
case 1: // melee
{
float fRange;
if (fMaxCut >= 0.0f)
{
float fCutDist = m_ExtProps.ak.AttackRange * 0.3f;
if (fCutDist > fMaxCut)
fCutDist = fMaxCut;
fRange = m_ExtProps.ak.AttackRange - fCutDist;
}
else
fRange = m_ExtProps.ak.AttackRange * 0.7f;
if (fDist - fTargetRad <= fRange)
return true;
break;
}
//case 2: // cast magic
//{
// if (m_pPrepSkill)
// {
// float fRange = m_pPrepSkill->GetCastRange(m_ExtProps.ak.AttackRange, GetPrayDistancePlus());
// if (fRange > 0.0f)
// {
// if (fDist - fTargetRad <= fRange)
// return true;
// }
// else
// return true;
// }
// break;
//}
case 3: // talk
{
if (fDist - fTargetRad <= 5.0f)
return true;
break;
}
default: // no special reason
{
if (fDist < (fTargetRad + m_fTouchRad) * 3.0f)
return true;
break;
}
}
return false;
}
public bool CanTouchTarget(A3DVECTOR3 vTargetPos, float fTargetRad, int iReason, float fMaxCut = 1.0f)
{
A3DVECTOR3 vector = new A3DVECTOR3(gameObject.transform.position.x, gameObject.transform.position.y, gameObject.transform.position.z);
return CanTouchTarget(vector, vTargetPos, fTargetRad, iReason, fMaxCut);
}
public bool IsRooting() {
var mask = (uint)(Logic_Influence_Extned_states.LIES_ROOT
| Logic_Influence_Extned_states.LIES_SLEEP
| Logic_Influence_Extned_states.LIES_STUN);
return (m_dwLIES & mask) != 0; }
bool IsInFortress() { return m_fortressEnter.role_in_war != 0; }
bool IsPVPOpen() { return m_pvp.bEnable; }
// Get faction ID
int GetFactionID(){ return m_idFaction; }
public bool IsJumping() { return m_iJumpCount > 0; }
public bool IsPlayingAction(int iAction)
{
if (iAction == (int)PLAYER_ACTION_TYPE.ACT_WALK && _playerStateMachine.State is PlayerMoveState)
{
return true;
}
if (iAction == (int)PLAYER_ACTION_TYPE.ACT_STAND && _playerStateMachine.State is PlayerIdleState)
{
return true;
}
return false;
}
public void ResetJump() { m_iJumpCount = 0; m_bJumpInWater = false; }
// Get move speed
public float GetFlySpeed() { return m_ExtProps.mv.flight_speed; }
public float GetSwimSpeed() { return m_ExtProps.mv.swim_speed; }
//public float GetSwimSpeedSev()
//{
// float fSpeedSev = GetSwimSpeed();
// while (true)
// {
// if (!IsUnderWater()) break;
// //CECWorld* pWorld = g_pGame->GetGameRun()->GetWorld();
// //if (!pWorld) break;
// const A3DVECTOR3 vPos = GetPos();
// float fTerrainHeight = pWorld->GetTerrainHeight(vPos);
// float fWaterHeight = pWorld->GetWaterHeight(vPos);
// if (fWaterHeight <= fTerrainHeight) break;
// float fBorderLine = fWaterHeight - 2.0f;
// if (vPos.y <= fBorderLine) break;
// // ·þÎñÆ÷¶Ë½«Ë®ÃæÒÔÏÂ2Ã×ÒÔÉÏ´¦ÀíΪ run_speed£¨ÓÐÎÊÌ⣩
// // µ«Î´Ê¹ÓüÓËÙ¼¼ÄÜʱ swim_speed СÓÚ run_speed£¬
// // ¿ÉÒÔÔÚË®ÃæÒÔÏÂ2Ã×ÒÔÉÏ»ñÈ¡³¬¹ý swim_speed µÄËÙ¶È£¬Òò´Ë£¬´Ë´¦È¡Á½Õß½ÏСֵΪºÏÀí×ö·¨
// fSpeedSev = min(m_ExtProps.mv.run_speed, fSpeedSev);
// break;
// }
// return fSpeedSev;
//}
}
public enum StateAnim
@@ -572,3 +939,54 @@ public enum StateAnim
Run = 3,
Jump = 4
}
// Mask of some special extend states which will influence host game logic.
// Logic Influence Extned states
[Flags]
public enum Logic_Influence_Extned_states
{
LIES_SLEEP = 0x0001,
LIES_STUN = 0x0002,
LIES_ROOT = 0x0004,
LIES_NOFGIHT = 0x0008,
LIES_DISABLEFIGHT = 0x000B,
}
// ½øÈë»ùµØÐÅÏ¢
public struct FACTION_FORTRESS_ENTER
{
public int faction_id;
public int role_in_war; // 0 : ÖÐÁ¢»ò²»ÔÚ»ùµØ 1:¹¥·½ 2: ÊØ·½
public int end_time;
public FACTION_FORTRESS_ENTER(int faction_id, int role_in_war, int end_time)
{
this.faction_id = faction_id;
this.role_in_war = role_in_war;
this.end_time = end_time;
}
}
// PVP infomation
public struct PVPINFO
{
public bool bEnable; // PVP switch
public uint dwCoolTime;
public uint dwMaxCoolTime;
public bool bFreePVP; // Free PVP flag, ignore bEnable flag
public bool bInPVPCombat; // true, in PVP combat
public int iDuelState; // Duel state
public int idDuelOpp; // Duel opponent
public int iDuelTimeCnt; // Duel time counter
public int iDuelRlt; // Duel result. 0, no defined; 1-win; 2-lose; 3-draw
};
// Current ground information
public struct GNDINFO
{
public float fGndHei; // Ground height
public float fWaterHei; // Water height
public A3DVECTOR3 vGndNormal; // Terrain normal
public bool bOnGround; // On ground flag
};
+41
View File
@@ -86,4 +86,45 @@ public static class EC_Utility
return $"{prefix}_{suffix}";
}
// Build pvp mask
public static byte glb_BuildPVPMask(bool bForceAttack)
{
byte byMask = 0;
if (bForceAttack)
byMask |= (byte)PVP_mask.GP_PVPMASK_FORCE;
//else
//{
// CECConfigs* pConfigs = g_pGame->GetConfigs();
// if (pConfigs->GetGameSettings().bAtk_Player)
// {
// byMask |= GP_PVPMASK_FORCE;
// if (pConfigs->GetGameSettings().bAtk_NoMafia)
// byMask |= GP_PVPMASK_NOMAFIA;
// if (pConfigs->GetGameSettings().bAtk_NoWhite)
// byMask |= GP_PVPMASK_NOWHITE;
// if (pConfigs->GetGameSettings().bAtk_NoAlliance)
// byMask |= GP_PVPMASK_NOALLIANCE;
// if (pConfigs->GetGameSettings().bAtk_NoForce)
// byMask |= GP_PVPMASK_NOFORCE;
// }
//}
return byMask;
}
public static T a_ClampFloor<T>(T x, T min) where T : IComparable<T>
{
return (x.CompareTo(min) < 0) ? min : x;
}
public static T a_Min<T>(T x, T y) where T : IComparable<T>
{
return (y.CompareTo(x) < 0) ? y : x;
}
}
+162 -17
View File
@@ -1,9 +1,12 @@
using BrewMonster.Network;
using CSNetwork;
using CSNetwork.C2SCommand;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using System;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
using System.Security.Cryptography;
using System.Text;
using UnityEngine;
using CSNetwork.Protocols;
@@ -24,7 +27,12 @@ public class CECHostMove
ulong m_dwLastTime;
Vector3 m_vLastPos;
float m_fAverSpeedH;
int m_iBlockedCnt; // Move blocked counter
bool m_bSlideLock; // Locked when slide
float m_fBlockTime; // Block time counter
float m_fBlockMove; // Block move counter
A3DVECTOR3 m_vBlockMove;
bool m_bLocalMove; // true, Moving info isn't sent to server
public CECHostMove(CECHostPlayer pHost)
{
@@ -42,8 +50,8 @@ public class CECHostMove
{
var m = m_DelayedStop;
// a_GetTime() -> Environment.TickCount (ms)
ulong dwCurrent = (ulong)Mathf.RoundToInt( Time.time * 1000);
// a_GetTime() . Environment.TickCount (ms)
ulong dwCurrent = (ulong)Mathf.RoundToInt(Time.time * 1000);
// iTime: thời gian tích lũy (ms) + delta từ timestamp đến hiện tại
int iTime = (int)((m.fTime * 1000f)
@@ -57,9 +65,9 @@ public class CECHostMove
// make a potential check with tuojigua
iMoveMode |= (int)GPMoveMode.GP_MOVE_DEAD;
UnityGameSession.Instance.c2s_SendCmdStopMove(
m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime
);
UnityGameSession.Instance.c2s_SendCmdStopMove(
m.vPos, fSpeed, iMoveMode, m.byDir, m_wMoveStamp++, iTime
);
// Record this position
m_vLastSevPos = m.vPos;
@@ -73,6 +81,33 @@ public class CECHostMove
m_vLastPos = m_pHost.transform.position;
m_dwLastTime = dwDeltaTime;
}
public void SendStopMoveCmd()
{
int iMoveMode = (int)GPMoveMode.GP_MOVE_RUN;
float fSpeed = 0f;
switch (m_pHost.GetMoveEnv())
{
case EC_Player.Move_environment.MOVEENV_AIR:
iMoveMode |= (int)GPMoveMode.GP_MOVE_AIR;
fSpeed = m_pHost.GetFlySpeed();
break;
//case EC_Player.Move_environment.MOVEENV_WATER:
// iMoveMode |= (int)GPMoveMode.GP_MOVE_WATER;
// fSpeed = m_pHost.GetSwimSpeedSev();
// break;
default:
fSpeed = m_pHost.GetGroundSpeed();
break;
}
SendStopMoveCmd(EC_Utility.ToVector3(m_pHost.GetPos()), fSpeed, iMoveMode);
}
public void SendStopMoveCmd(in Vector3 vPos, float fSpeed, int iMoveMode)
{
Debug.LogWarning("HoangDev : SendStopMoveCmd");
@@ -87,7 +122,7 @@ public class CECHostMove
UnityGameSession.Instance.c2s_SendCmdStopMove(vPos, fSpeed, iMoveMode, byDir, m_wMoveStamp++, iTime);
m_vLastSevPos = vPos;
m_vLastSevPos = vPos;
Reset();
}
else
@@ -115,14 +150,31 @@ public class CECHostMove
float fSpeed = vMoveDir.magnitude;
SendMoveCmd(vCurPos, fSpeed, iMoveMode, bForceSend);
}
public void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest, A3DVECTOR3 vVel, int iMoveMode, bool bForceSend = false)
{
A3DVECTOR3 vMoveDir = vVel;
float fSpeed = vMoveDir.Normalize();
SendMoveCmd(vCurPos, iDestType, vDest, vMoveDir, fSpeed, iMoveMode, bForceSend);
}
void SendMoveCmd(A3DVECTOR3 vCurPos, int iDestType, A3DVECTOR3 vDest,
A3DVECTOR3 vMoveDir, float fSpeed, int iMoveMode, bool bForceSend)
{
Vector3 pos = new Vector3(vCurPos.x, vCurPos.y, vCurPos.z);
SendMoveCmd(pos, fSpeed, iMoveMode, bForceSend);
}
void SendMoveCmd(in Vector3 vCurPos,
float fSpeed, int iMoveMode, bool bForceSend)
float fSpeed, int iMoveMode, bool bForceSend)
{
if (m_bStop)
{
// m_CmdTimeCnt.Reset();
cmdmovedelayCounter = (ulong)( m_fMoveTime * 1000);
cmdmovedelayCounter = (ulong)(m_fMoveTime * 1000);
m_bStop = false;
}
if (!bForceSend && cmdmovedelayCounter < 500)
@@ -151,7 +203,7 @@ public class CECHostMove
m_vLastSevPos = vCurPos;
}
float l_CalcAverageSpeed(in Vector3 p1, in Vector3 p2, float fTime, float fDefSpeed)
{
if (Mathf.Approximately(fTime, 0f))
@@ -183,14 +235,107 @@ public class CECHostMove
struct STOPMOVE
{
public bool bValid; // Valid flag
public Vector3 vPos;
public float fSpeed;
public int iMoveMode;
public byte byDir;
public ulong dwTimeStamp;
public float fTime;
public bool bValid; // Valid flag
public Vector3 vPos;
public float fSpeed;
public int iMoveMode;
public byte byDir;
public ulong dwTimeStamp;
public float fTime;
};
// Check whether host meet a slope
// vMoveDirH: normalized horizontal moving direction
// fMaxSpeed (out): maximum vertical speed
public bool MeetSlope(A3DVECTOR3 vMoveDirH, float fMaxSpeedV)
{
A3DVECTOR3 vTangent = m_pHost.m_GndInfo.vGndNormal;
float d = vTangent.MagnitudeH();
float tan = d / (float)Math.Abs(vTangent.y);
float max = m_pHost.GetGroundSpeed() * tan * 0.96f;
// Prevent max is too small, tan60 = 1.732
EC_Utility.a_ClampFloor(max, m_pHost.GetGroundSpeed() * 1.732f);
fMaxSpeedV = EC_Utility.a_Min(max, 19.5f);
// fMaxSpeedV = 100.0f;
vTangent.y = 0.0f;
vTangent.Normalize();
if (A3DVECTOR3.DotProduct(vMoveDirH, vTangent) <= -0.85f)
return true;
return false;
}
public A3DVECTOR3 GroundMove(A3DVECTOR3 vDirH, float fSpeedH, float fTime, float fSpeedV = 0f, float fGravity = 9.8f)
{
A3DVECTOR3 vRealDirH = vDirH;
if (Math.Abs(vRealDirH.y) > 0.0001)
{
vRealDirH.y = 0.0f;
vRealDirH.Normalize();
}
// OnGroundMove only accept positive speed value
if (fSpeedH < 0.0f)
{
vRealDirH = -vDirH;
fSpeedH = -fSpeedH;
}
//int idInst = g_pGame.GetGameRun().GetWorld().GetInstanceID();
//CECInstance pInstance = g_pGame.GetGameRun().GetInstance(idInst);
//if (pInstance.GetLimitJump())
fGravity *= 4.0f;
CDR_INFO cdr = m_pHost.m_CDRInfo;
var pos = m_pHost.m_aabbServer.Center;
cdr.vCenter = new Vector3(pos.x, pos.y, pos.z);
cdr.vXOZVelDir = new Vector3(vRealDirH.x, vRealDirH.y, vRealDirH.z);
cdr.fSpeed = fSpeedH;
cdr.t = fTime;
cdr.fGravityAccel = fGravity;
cdr.fYVel += fSpeedV;
EC_CDR.OnGroundMove(ref cdr);
//if (g_pGame.GetGameRun().GetWorld().GetAssureMove())
// g_pGame.GetGameRun().GetWorld().GetAssureMove().AssureMove(m_pHost.m_aabbServer.Center, cdr.vCenter);
if (cdr.vTPNormal != Vector3.zero)
m_pHost.SetGroundNormal(new A3DVECTOR3(cdr.vTPNormal.x, cdr.vTPNormal.y, cdr.vTPNormal.z));
else
m_pHost.SetGroundNormal(GPDataTypeHelper.g_vAxisY);
A3DVECTOR3 vNewPos = new A3DVECTOR3(cdr.vCenter.x, cdr.vCenter.y, cdr.vCenter.z) - GPDataTypeHelper.g_vAxisY * m_pHost.m_aabbServer.Extents.y;
m_iBlockedCnt = 0;
m_fBlockMove += (vNewPos - m_pHost.GetPos()).Magnitude();
m_vBlockMove += vNewPos - m_pHost.GetPos();
if ((m_fBlockTime += fTime) >= 1.0f)
{
if (m_fBlockMove < GPDataTypeHelper.MIN_MOVELEN_ON_GROUND || m_vBlockMove.Magnitude() < GPDataTypeHelper.MIN_MOVELEN_FOR_DETECT_VIBRATION)
{
m_iBlockedCnt = 5;
}
m_fBlockTime = 0.0f;
m_fBlockMove = 0.0f;
m_vBlockMove.Clear();
}
m_fMoveTime += fTime;
return vNewPos;
}
public int MoveBlocked() { return m_iBlockedCnt; }
public void SetSlideLock(bool bLock) { m_bSlideLock = bLock; }
// Is stoping ?
public bool IsStop() { return m_bStop; }
}
public struct CDR_INFO
{
+134 -5
View File
@@ -1,18 +1,30 @@
using BrewMonster;
using CSNetwork.GPDataType;
using ModelRenderer.Scripts.GameData;
using PerfectWorld.Scripts.Player;
using System;
using System.Collections.Generic;
using UnityEngine;
public abstract class EC_Player : MonoBehaviour
public abstract class EC_Player : CECObject
{
private static PLAYER_ACTION[] _default_actions;
private static PLAYER_ACTION[] _turning_actions;
PLAYER_ACTION[] m_PlayerActions;
[SerializeField] protected INFO m_PlayerInfo;
[SerializeField] internal INFO m_PlayerInfo;
protected GameObject m_pPlayerModel;
protected float rotationSpeed = 5;
internal int m_iMoveMode; // Player's move mode
internal int m_idSelTarget; // Ñ¡ÖÐÄ¿±êµÄID
uint m_dwStates; // Player's basic states
protected ROLEEXTPROP m_ExtProps; // Extend properties
protected float m_fTouchRad = 0.3f; // Touch radius
protected int m_iBattleCamp = Player_camp_in_battle.GP_BATTLE_CAMP_NONE; // Battle this player belongs to
byte m_factionPVPMask; // pvp mask
protected ROLEBASICPROP m_BasicProps;
public int m_iMoveEnv = Move_environment.MOVEENV_GROUND; // Move environment
public bool m_bWalkRun;
public A3DAABB m_aabbServer; // Óë·þÎñÆ÷±£³ÖÒ»ÖµÄaabb£¬ ²»ÊÜËõ·ÅÓ°Ïì
protected void Awake()
{
m_PlayerActions = _default_actions;
@@ -30,7 +42,10 @@ public abstract class EC_Player : MonoBehaviour
{
BuildActionList();
}
public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; }
public bool IsDead(){ return (m_dwStates & PlayerNPCState.GP_STATE_CORPSE) != 0; }
public bool IsValidAction(int iIndex) { return (iIndex >= 0 && iIndex < (int)PLAYER_ACTION_TYPE.ACT_MAX) ? true : false; }
private static void BuildActionList()
{
if (_default_actions == null)
@@ -270,6 +285,102 @@ public abstract class EC_Player : MonoBehaviour
ACT_CASTSKILL // Chỉ là placeholder cho skill actions
}
public float GetTouchRadius(){ return m_fTouchRad; }
// Is player in battle
public bool IsInBattle() { return m_iBattleCamp != Player_camp_in_battle.GP_BATTLE_CAMP_NONE; }
// Check whether specified npc in a same battle camp
public bool InSameBattleCamp(CECNPC pNPC)
{
if (!pNPC || m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_NONE ||
(m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_INVADER && !pNPC.IsInBattleInvaderCamp()) ||
(m_iBattleCamp == Player_camp_in_battle.GP_BATTLE_CAMP_DEFENDER && !pNPC.IsInBattleDefenderCamp()))
return false;
return true;
}
public bool IsInFactionPVP() => (m_factionPVPMask & 0x01) != 0;
public bool CanAttackFactionPVPMineCar() => (m_factionPVPMask & 0x02) != 0;
public bool CanAttackFactionPVPMineBase() => (m_factionPVPMask & 0x04) != 0;
// Get basic properties
public ROLEBASICPROP GetBasicProps() { return m_BasicProps; }
public int GetMoveStandAction(bool bMove, bool bFight = false)
{
int iMoveEnv = m_iMoveEnv;
//if (m_AttachMode != enumAttachNone)
//{
// bFight = false;
// if (m_bHangerOn)
// iMoveEnv = MOVEENV_GROUND;
//}
int iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND;
if (bMove)
{
// Play appropriate actions
if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND)
{
if (m_bWalkRun)
iAction = (int)PLAYER_ACTION_TYPE.ACT_RUN;
else
iAction = (int)PLAYER_ACTION_TYPE.ACT_WALK;
}
//else if (iMoveEnv == MOVEENV_AIR)
//{
// //if (/*UsingWing()*/ m_wingType == WINGTYPE_WING)
// // iAction = ACT_FLY;
// //else
// // iAction = ACT_FLY_SWORD;
//}
//else if (iMoveEnv == MOVEENV_WATER)
//{
// //if (CanCombineWithMoveForSkill())
// //{
// // iAction = ACT_SWIM_FOR_MOVESKILL;
// //}
// //else
// //{
// // iAction = ACT_SWIM;
// //}
//}
}
else
{
// Play appropriate actions
if (iMoveEnv == (int)MoveEnvironment.MOVEENV_GROUND)
{
if (bFight)
iAction = (int)PLAYER_ACTION_TYPE.ACT_FIGHTSTAND;
else
iAction = (int)PLAYER_ACTION_TYPE.ACT_STAND;
}
//else if (iMoveEnv == MOVEENV_AIR)
//{
// if (/*UsingWing()*/ m_wingType == WINGTYPE_WING)
// iAction = ACT_HANGINAIR;
// else
// iAction = ACT_HANGINAIR_SWORD;
//}
//else if (iMoveEnv == MOVEENV_WATER)
// iAction = ACT_HANGINWATER;
}
return iAction;
}
public float GetGroundSpeed()
{
// return m_bWalkRun ? g_pGame->GetConfigs()->GetHostRunSpeed() : m_ExtProps.mv.walk_speed;
return m_bWalkRun ? m_ExtProps.mv.run_speed : m_ExtProps.mv.walk_speed;
}
// Get move environment
public int GetMoveEnv(){ return m_iMoveEnv; }
// Get character ID
public int GetCharacterID(){ return m_PlayerInfo.cid; }
}
public struct PlayActionEvent
{
@@ -291,4 +402,22 @@ public struct INFO
this.crc_c = crc_c;
this.crc_e = crc_;
}
};
}
public static class Duel_state // Duel state
{
public const int DUEL_ST_NONE = 0,
DUEL_ST_PREPARE = 1,
DUEL_ST_INDUEL = 2,
DUEL_ST_STOPPING = 3;
}
//// Move mode
//public static class Move_Mode
//{
// public const int MOVE_STAND = 0,
// MOVE_MOVE = 1, // Normal move, walk, run, swim or fly
// MOVE_JUMP = 2,
// MOVE_FREEFALL = 3,
// MOVE_SLIDE = 4;
//}
+2
View File
@@ -5,6 +5,8 @@ public class PlayerStateMachine
PlayerState _state;
CECHostPlayer _characterCtrl;
public PlayerState State { get => _state; }
public void InitState(PlayerState state)
{
if (_state != null)