skill pos processing

This commit is contained in:
VDH
2025-12-05 21:07:25 +07:00
parent 2d3f98bb2c
commit 80c40705d2
28 changed files with 1289 additions and 380 deletions
@@ -0,0 +1,123 @@
using CSNetwork.GPDataType;
namespace BrewMonster
{
public class A3DAABB
{
public A3DVECTOR3 Center;
public A3DVECTOR3 Extents;
public A3DVECTOR3 Mins;
public A3DVECTOR3 Maxs;
public A3DAABB() { }
public A3DAABB(A3DAABB aabb)
{
Center = aabb.Center;
Extents = aabb.Extents;
Mins = aabb.Mins;
Maxs = aabb.Maxs;
}
public A3DAABB(A3DVECTOR3 mins, A3DVECTOR3 maxs)
{
Mins = mins;
Maxs = maxs;
Center = (mins + maxs) * 0.5f;
Extents = maxs - Center;
}
// Reset AABB về trạng thái rỗng
public void Clear()
{
Mins = new A3DVECTOR3(999999f, 999999f, 999999f);
Maxs = new A3DVECTOR3(-999999f, -999999f, -999999f);
Center = new A3DVECTOR3(0f, 0f, 0f);
Extents = new A3DVECTOR3(0f, 0f, 0f);
}
// Thêm 1 điểm vào AABB
public void AddVertex(A3DVECTOR3 v)
{
if (v.x < Mins.x) Mins.x = v.x;
if (v.y < Mins.y) Mins.y = v.y;
if (v.z < Mins.z) Mins.z = v.z;
if (v.x > Maxs.x) Maxs.x = v.x;
if (v.y > Maxs.y) Maxs.y = v.y;
if (v.z > Maxs.z) Maxs.z = v.z;
CompleteCenterExts();
}
// Hợp nhất 2 AABB
public void Merge(A3DAABB subAABB)
{
if (subAABB.Mins.x < Mins.x) Mins.x = subAABB.Mins.x;
if (subAABB.Mins.y < Mins.y) Mins.y = subAABB.Mins.y;
if (subAABB.Mins.z < Mins.z) Mins.z = subAABB.Mins.z;
if (subAABB.Maxs.x > Maxs.x) Maxs.x = subAABB.Maxs.x;
if (subAABB.Maxs.y > Maxs.y) Maxs.y = subAABB.Maxs.y;
if (subAABB.Maxs.z > Maxs.z) Maxs.z = subAABB.Maxs.z;
CompleteCenterExts();
}
// Cập nhật Mins, Maxs từ Center + Extents
public void CompleteMinsMaxs()
{
Mins = Center - Extents;
Maxs = Center + Extents;
}
// Cập nhật Center + Extents từ Mins, Maxs
public void CompleteCenterExts()
{
Center = (Mins + Maxs) * 0.5f;
Extents = Maxs - Center;
}
// Kiểm tra điểm có nằm trong AABB không
public bool IsPointIn(A3DVECTOR3 v)
{
return !(v.x > Maxs.x || v.x < Mins.x ||
v.y > Maxs.y || v.y < Mins.y ||
v.z > Maxs.z || v.z < Mins.z);
}
// Kiểm tra 1 AABB khác có nằm trong AABB này không
public bool IsAABBIn(A3DAABB aabb)
{
return (aabb.Mins.x >= Mins.x && aabb.Maxs.x <= Maxs.x &&
aabb.Mins.y >= Mins.y && aabb.Maxs.y <= Maxs.y &&
aabb.Mins.z >= Mins.z && aabb.Maxs.z <= Maxs.z);
}
// Xây AABB từ một tập vertices
public void Build(A3DVECTOR3[] vertices)
{
Clear();
foreach (var v in vertices)
AddVertex(v);
}
// Lấy các vertices (8 điểm) của AABB
public A3DVECTOR3[] GetVertices()
{
A3DVECTOR3[] verts = new A3DVECTOR3[8];
verts[0] = new A3DVECTOR3(Mins.x, Mins.y, Mins.z);
verts[1] = new A3DVECTOR3(Maxs.x, Mins.y, Mins.z);
verts[2] = new A3DVECTOR3(Maxs.x, Maxs.y, Mins.z);
verts[3] = new A3DVECTOR3(Mins.x, Maxs.y, Mins.z);
verts[4] = new A3DVECTOR3(Mins.x, Mins.y, Maxs.z);
verts[5] = new A3DVECTOR3(Maxs.x, Mins.y, Maxs.z);
verts[6] = new A3DVECTOR3(Maxs.x, Maxs.y, Maxs.z);
verts[7] = new A3DVECTOR3(Mins.x, Maxs.y, Maxs.z);
return verts;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7a6824a3d5ac15a4e8deab66a3ceaae2
@@ -761,7 +761,10 @@ namespace BrewMonster
public CECConfigs()
{
m_fCurPVRadius = m_fSevActiveRad;
m_gs = default;
DefaultUserSettings(ref m_ss, ref m_vs, ref m_gs, ref m_bs, ref m_cas);
m_gs.bAtk_NoWhite = true;
m_gs.bAtk_NoForce = true;
}
public bool Init(string szCfgFile, string szClientIDFile, string szSSFile)
@@ -103,6 +103,7 @@ namespace BrewMonster.Network
if (m_pTaskMan == null) m_pTaskMan = new ATaskTemplMan();
m_pTaskMan.Init(m_pElementDataMan);
m_pConfigs = new CECConfigs(); /*ElementClient.g_GameCfgs*/;
if (!m_pTaskMan.InitStorageTask())
{
BMLogger.LogError("[Dat]- CECGame::Init, Storage task Init Failed!");
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BrewMonster
{
public static class ElementClient
{
public static CECConfigs g_GameCfgs;
public static bool _InitGameApp()
{
g_GameCfgs = new CECConfigs();
if (!g_GameCfgs.Init("Configs\\element_client.cfg", "client_id.cfg", "userdata\\SystemSettings.ini"))
{
BMLogger.LogError("_InitGameApp(), Failed to load configs file");
return false;
}
return true;
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5b3f9ba4c8ff457408f56fef6c34c7bd
@@ -120,3 +120,4 @@ namespace BrewMonster.Managers
+1 -1
View File
@@ -26,7 +26,7 @@ namespace BrewMonster
static LayerMask UsedMask_Ground() => BrushMask | TerrainMask;
public static bool CollideWithEnv(env_trace_t pEnvTrc)
public static bool CollideWithEnv(ref env_trace_t pEnvTrc)
{
pEnvTrc.fFraction = 100.0f;
pEnvTrc.bStartSolid = false;
+363 -3
View File
@@ -1,11 +1,370 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using BrewMonster.Scripts;
using CSNetwork.GPDataType;
using UnityEngine;
using CombinedActMap = System.Collections.Generic.Dictionary<string, object>;
using CoGfxMap = System.Collections.Generic.Dictionary<string, object>;
using ConvexHullDataArray = System.Collections.Generic.List<object>;
using ECModelHookMap = System.Collections.Generic.Dictionary<string, object>;
using BrewMonster;
public enum ECMScript
{
enumECMScriptStartAction = 0,
enumECMScriptEndActioin,
enumECMScriptInit,
enumECMScriptRelease,
enumECMScriptModelLoaded,
enumECMScriptChangeEquip,
enumECMScriptChangeEquipTableInit,
enumECMScriptPhysBreak,
enumECMScriptCount
}
public enum ECMScriptVar
{
enumECMVarModel = 0,
enumECMVarActName,
enumECMVarActChannel,
enumECMVarEquipId,
enumECMVarEquipFlag,
enumECMVarFashionMode,
enumECMVarPathId,
enumECMVarId,
enumECMVarEquipIndex,
enumECMVarBreakOffsetX,
enumECMVarBreakOffsetY,
enumECMVarBreakOffsetZ,
enumECMVarCasterId,
enumECMVarCastTargetId,
enumECMVarSelf,
enumECMVarCount
}
public static class CECModelConstants
{
public const int ECM_SCRIPT_MAX_VAR_COUNT = 8;
public const int OUTER_DATA_COUNT = 8;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ECM_SCRIPT_VAR
{
[MarshalAs(UnmanagedType.I4)]
public int var_count;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = CECModelConstants.ECM_SCRIPT_MAX_VAR_COUNT)]
public int[] var_index;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BoneScale
{
public int m_nIndex;
public int m_nType;
public A3DVECTOR3 m_vScale;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BoneScaleEx
{
public int m_nIndex;
public float m_fLenFactor;
public float m_fThickFactor;
public float m_fWholeFactor;
}
public class ActChannelInfo
{
public List<string> bone_names = new List<string>();
public List<int> joint_indices = new List<int>();
public ActChannelInfo Clone()
{
return new ActChannelInfo
{
bone_names = new List<string>(bone_names),
joint_indices = new List<int>(joint_indices)
};
}
}
public enum A3DBLEND
{
A3DBLEND_SRCALPHA,
A3DBLEND_INVSRCALPHA
}
public struct A3DSHADER
{
public A3DBLEND SrcBlend;
public A3DBLEND DestBlend;
}
public class CECModelStaticData
{
private string m_strFilePath = string.Empty;
private string m_strSkinModelPath = string.Empty;
private bool m_bAutoUpdate = true;
private bool m_bActMapped;
private readonly CombinedActMap m_ActionMap = new CombinedActMap();
private uint m_dwVersion;
private string m_strHook = string.Empty;
private string m_strCCName = string.Empty;
private readonly List<BoneScale> m_BoneScales = new List<BoneScale>();
private readonly List<BoneScaleEx> m_BoneScaleExArr = new List<BoneScaleEx>();
private string m_strScaleBaseBone = string.Empty;
private uint m_OrgColor = 0xFFFFFFFF;
private uint m_EmissiveColor = 0;
private float m_fDefPlaySpeed = 1.0f;
private A3DSHADER m_BlendMode = new A3DSHADER
{
SrcBlend = A3DBLEND.A3DBLEND_SRCALPHA,
DestBlend = A3DBLEND.A3DBLEND_INVSRCALPHA
};
private readonly float[] m_OuterData = new float[CECModelConstants.OUTER_DATA_COUNT];
private bool m_bCanCastShadow = true;
private bool m_bRenderSkinModel = true;
private bool m_bRenderEdge = true;
private readonly CoGfxMap m_CoGfxMap = new CoGfxMap();
private readonly ConvexHullDataArray m_ConvexHullDataArr = new ConvexHullDataArray();
private readonly A3DAABB m_CHAABB = new A3DAABB();
private readonly Dictionary<int, ActChannelInfo> m_ChannelInfoDict = new Dictionary<int, ActChannelInfo>();
private readonly Dictionary<int, uint> m_EventMasks = new Dictionary<int, uint>();
private readonly string[] m_Scripts = new string[(int)ECMScript.enumECMScriptCount];
private readonly bool[] m_ScriptEnable = new bool[(int)ECMScript.enumECMScriptCount];
private readonly CLuaMemTbl m_ScriptMemTbl = new CLuaMemTbl();
private bool m_bInitGlobalScript;
private string m_strGlobalScriptName = string.Empty;
public class ChildInfo
{
public string m_strName = string.Empty;
public string m_strPath = string.Empty;
public string m_strHHName = string.Empty;
public string m_strCCName = string.Empty;
}
private readonly List<ChildInfo> m_ChildInfoArray = new List<ChildInfo>();
private readonly List<string> m_AdditionalSkinLst = new List<string>();
private string m_strPhysFileName = string.Empty;
private object m_pPhysSyncData;
private readonly ECModelHookMap m_ECModelHookMap = new ECModelHookMap();
private string m_strPixelShader = string.Empty;
private string m_strShaderTex = string.Empty;
private readonly List<object> m_vecPSConsts = new List<object>();
public CECModelStaticData()
{
ResetOuterData();
m_CHAABB.Clear();
}
public bool LoadData(string szModelFile, bool bLoadAdditionalSkin)
{
throw new NotImplementedException("CECModelStaticData.LoadData requires the legacy AFile system to be ported.");
}
public bool Save(string szFile, CECModel pModel)
{
throw new NotImplementedException("CECModelStaticData.Save requires the legacy serialization pipeline to be ported.");
}
public bool SaveBoneScaleInfo(string szFile)
{
throw new NotImplementedException("CECModelStaticData.SaveBoneScaleInfo is not yet implemented.");
}
public void Release()
{
m_BoneScales.Clear();
m_BoneScaleExArr.Clear();
m_CoGfxMap.Clear();
m_ActionMap.Clear();
m_AdditionalSkinLst.Clear();
m_ChildInfoArray.Clear();
m_ConvexHullDataArr.Clear();
m_ChannelInfoDict.Clear();
m_EventMasks.Clear();
Array.Clear(m_Scripts, 0, m_Scripts.Length);
Array.Clear(m_ScriptEnable, 0, m_ScriptEnable.Length);
m_ECModelHookMap.Clear();
m_vecPSConsts.Clear();
m_bInitGlobalScript = false;
m_strGlobalScriptName = string.Empty;
m_pPhysSyncData = null;
m_CHAABB.Clear();
ResetOuterData();
}
public ConvexHullDataArray GetConvexHullData() => m_ConvexHullDataArr;
public bool HasCHAABB() => m_ConvexHullDataArr.Count != 0;
public A3DAABB GetCHAABB() => m_CHAABB;
public bool UpdateScript(int index, string strScript, bool bCompileOnly)
{
if (index < 0 || index >= (int)ECMScript.enumECMScriptCount)
return false;
if (!bCompileOnly)
m_Scripts[index] = strScript ?? string.Empty;
m_ScriptEnable[index] = !string.IsNullOrEmpty(m_Scripts[index]);
return m_ScriptEnable[index];
}
public CoGfxMap GetCoGfxMap() => m_CoGfxMap;
public CombinedActMap GetCombinedActMap() => m_ActionMap;
public string GetPhysFileName() => m_strPhysFileName;
public void SetPhysFileName(string szFile) => m_strPhysFileName = szFile ?? string.Empty;
public object GetPhysSyncData() => m_pPhysSyncData;
public void SetPhysSyncData(object p) => m_pPhysSyncData = p;
public uint GetVersion() => m_dwVersion;
public string GetPixelShaderPath() => m_strPixelShader;
public void SetPixelShaderPath(string szPath) => m_strPixelShader = szPath ?? string.Empty;
public string GetShaderTexture() => m_strShaderTex;
public void SetShaderTexture(string szPath) => m_strShaderTex = szPath ?? string.Empty;
public IList<object> GetPSConstVec() => m_vecPSConsts;
public void SetActionEventMask(int nChannel, uint dwMask) => m_EventMasks[nChannel] = dwMask;
public uint GetActionEventMask(int nChannel)
{
return m_EventMasks.TryGetValue(nChannel, out uint mask) ? mask : uint.MaxValue;
}
public IReadOnlyDictionary<int, uint> GetActionEventMaskSnapshot() => m_EventMasks;
public void OnScriptEndAction(CECModel pModel, int nChannel, string szActName)
{
if (!IsScriptEnabled(ECMScript.enumECMScriptEndActioin))
return;
Debug.LogWarning($"CECModelStaticData.OnScriptEndAction invoked for {szActName}, scripting runtime not yet ported.");
}
public void Reset()
{
m_OrgColor = 0xFFFFFFFF;
m_EmissiveColor = 0;
m_fDefPlaySpeed = 1.0f;
m_BlendMode = new A3DSHADER
{
SrcBlend = A3DBLEND.A3DBLEND_SRCALPHA,
DestBlend = A3DBLEND.A3DBLEND_INVSRCALPHA
};
ResetOuterData();
m_BoneScales.Clear();
m_BoneScaleExArr.Clear();
m_strScaleBaseBone = string.Empty;
m_ChannelInfoDict.Clear();
m_strPhysFileName = string.Empty;
}
public void AddScriptMethod(int index, string szScript)
{
if (index < 0 || index >= (int)ECMScript.enumECMScriptCount)
return;
m_ScriptEnable[index] = !string.IsNullOrEmpty(szScript);
}
public void OnScriptPlayAction(CECModel pModel, int nChannel, string szActName)
{
if (!IsScriptEnabled(ECMScript.enumECMScriptStartAction))
return;
Debug.LogWarning($"CECModelStaticData.OnScriptPlayAction triggered for {szActName}, scripting runtime not available.");
}
public void OnScriptChangeEquip(CECModel pModel, int nEquipId, int nEquipFlag, bool bFashionMode, int nPathId, int nEquipIndex)
{
if (!IsScriptEnabled(ECMScript.enumECMScriptChangeEquip))
return;
Debug.LogWarning("CECModelStaticData.OnScriptChangeEquip called, scripting runtime not available.");
}
public void OnScriptPhysBreak(CECModel pModel, float fBreakOffsetX, float fBreakOffsetY, float fBreakOffsetZ)
{
if (!IsScriptEnabled(ECMScript.enumECMScriptPhysBreak))
return;
Debug.LogWarning("CECModelStaticData.OnScriptPhysBreak called, scripting runtime not available.");
}
public void InitGlobalScript()
{
if (m_bInitGlobalScript)
return;
if (!IsScriptEnabled(ECMScript.enumECMScriptInit))
return;
m_bInitGlobalScript = true;
m_strGlobalScriptName = $"GlobalScriptFunc_{DateTime.UtcNow.Ticks}";
}
public bool LoadAdditionalSkin(object pFile, uint dwVersion, bool bLoadAdditionalSkin)
{
Debug.LogWarning("CECModelStaticData.LoadAdditionalSkin stub invoked.");
return true;
}
public IList<string> GetAdditionalSkinList() => m_AdditionalSkinLst;
public IList<ChildInfo> GetChildInfoArray() => m_ChildInfoArray;
public float[] GetOuterData() => m_OuterData;
public bool CanCastShadow => m_bCanCastShadow;
public bool CanRenderSkinModel => m_bRenderSkinModel;
public bool CanRenderEdge => m_bRenderEdge;
private bool IsScriptEnabled(ECMScript scriptId)
{
int idx = (int)scriptId;
if (idx < 0 || idx >= m_ScriptEnable.Length)
return false;
return m_ScriptEnable[idx];
}
private void ResetOuterData()
{
for (int i = 0; i < m_OuterData.Length; i++)
m_OuterData[i] = 1.0f;
}
}
public class CLuaMemTbl
{
public void Init(string tableName) { }
public bool AddMethod(string name, IList<string> args, string script) => false;
public void RemoveMethod(string name) { }
public void Release() { }
}
public class CECModel
{
private const uint COMACT_FLAG_MODE_NONE = 0;
//protected CECModelStaticData m_pMapModel;
protected CECModelStaticData m_pMapModel;
public void ClearComActFlag(bool bSignalCurrent) { ClearComActFlag(0, bSignalCurrent); }
public void ClearComActFlag(int nChannel, bool bSignalCurrent)
{
@@ -42,14 +401,15 @@ public class CECModel
AnimationName = animationName;
}
}
public bool HasCHAABB() { return m_pMapModel.HasCHAABB(); }
public void PlayGfx(string szPath, string szHook, float fScale, bool bFadeOut, A3DVECTOR3 vOffset, float fPitch, float fYaw, float fRot, bool bUseECMHook, uint dwFadeOutTime)
{
if (!bFadeOut)
dwFadeOutTime = 0;
string strKey = szPath;
strKey += szHook;
// PGFX_INFO pInfo;
//
+9 -4
View File
@@ -609,7 +609,7 @@ public class CECNPC : CECObject
Vector3 dir = m_vMoveDir.normalized;
Vector3 moveDelta = dir * m_fMoveSpeed * deltaTime;
if(_characterController == null)
if (_characterController == null)
{
BMLogger.LogError(" CECNPC.MovingTo _characterController == null " + gameObject.name);
}
@@ -662,7 +662,7 @@ public class CECNPC : CECObject
// No delay die, enter disappear process immediately
if (!bDelay)
Disappear();
StartWork((int)WorkType.WT_NORMAL, (int)WorkID.WORK_DEAD, m_dwStates);
@@ -807,8 +807,9 @@ public class CECNPC : CECObject
return;
}
var model = await NPCBuilder.Instance.GetModelByPath(AFile.NormalizePath(szModelFile.ToLower(), true));
if (model == null) {
if (model == null)
{
model = GameObject.CreatePrimitive(PrimitiveType.Capsule);
BMLogger.LogWarning($" CECNPC.QueueLoadNPCModel model == null szModelFile= {szModelFile} ");
}
@@ -979,6 +980,10 @@ public class CECNPC : CECObject
}
}
}
public bool GetCHAABB(ref A3DAABB aabb)
{
return m_pNPCModelPolicy.GetCHAABB(ref aabb);
}
void SetPos(Vector3 pos)
{
transform.position = pos;
@@ -7,6 +7,10 @@ public class CECNPCModelDefaultPolicy
{
CECModel m_pNPCModel;
CECNPC m_pNPC;
int m_nBrushes;
A3DAABB m_CHAABB; // AABB Updated with m_ppBrushes
// number of brush object used in collision
public CECNPCModelDefaultPolicy(CECNPC pNPC)
{
m_pNPCModel = new CECModel();
@@ -51,6 +55,27 @@ public class CECNPCModelDefaultPolicy
}
return true;
}
public override bool GetCHAABB(ref A3DAABB aabb)
{
bool bRet = (false);
if (HasCHAABB())
{
aabb = m_CHAABB;
// m_CHAABB ¸ù¾Ý͹°üÉϵĶ¥µãλÖÃÀ´¼ÆËã°üΧºÐ£¬¸ü׼ȷ²¢Óë͹°ü¼ì²â±£³ÖÒ»ÖÂ
// ²»ÄÜʹÓà GetPos() À´µ÷Õû m_CHAABB ºó×÷Ϊ¼ÆËã½á¹û·µ»Ø
//aabb.Center = GetPos() + A3DVECTOR3(0.0f, m_CHAABB.Extents.y, 0.0f);
//aabb.CompleteMinsMaxs();
bRet = true;
}
return bRet;
}
bool HasCHAABB()
{
return m_pNPCModel != null
&& m_pNPCModel.HasCHAABB()
&& m_nBrushes > 0;
}
public override bool PlayModelAction(int iAction, bool bRestart, CECAttackEvent cECAttackEvent)
{
/* if (m_pNPCModel == null)
@@ -72,7 +97,7 @@ public class CECNPCModelDefaultPolicy
else if (iAction == (int)NPCActionIndex.ACT_ATTACK1 || iAction == (int)NPCActionIndex.ACT_ATTACK2)
{
//bool bHideFX = !CECOptimize::Instance().GetGFX().CanShowAttack(m_pNPC->GetNPCID(), m_pNPC->GetClassID());
result = _npcVisual.TryPlayAction(GetActionName(iAction, true), cECAttackEvent,true);
result = _npcVisual.TryPlayAction(GetActionName(iAction, true), cECAttackEvent, true);
if (result)
{
string szAct = GetActionName(iAction, false);
@@ -13,5 +13,7 @@ namespace BrewMonster
public abstract bool HasAction(int iAction);
public abstract void ClearComActFlag(bool bSignalCurrent);
public abstract bool PlayAttackAction(int nAttackSpeed, CECAttackEvent attackevent);
public abstract bool GetCHAABB(ref A3DAABB ab);
}
}
@@ -713,7 +713,21 @@ namespace CSNetwork
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_ENCHANTRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
else if (ISNPCID(pCmd3.caster))
EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_ENCHANTRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader);
break;
case CommandID.SKILL_PERFORM:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.SET_COOLDOWN:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SETCOOLTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader);
break;
case CommandID.COMBO_SKILL_PREPARE:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COMBO_SKILL_PREPARE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize);
break;
case CommandID.PLAYER_EXT_PROP_BASE:
case CommandID.PLAYER_EXT_PROP_MOVE:
case CommandID.PLAYER_EXT_PROP_ATK:
case CommandID.PLAYER_EXT_PROP_DEF:
EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREXTPROP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader);
break;
}
}
@@ -652,122 +652,5 @@ namespace BrewMonster
APPEAR_RUNINTOVIEW, // Player run into view
APPEAR_GHOST, // Player is in ghost state, in player list but not active
};
public class A3DAABB
{
public A3DVECTOR3 Center;
public A3DVECTOR3 Extents;
public A3DVECTOR3 Mins;
public A3DVECTOR3 Maxs;
public A3DAABB() { }
public A3DAABB(A3DAABB aabb)
{
Center = aabb.Center;
Extents = aabb.Extents;
Mins = aabb.Mins;
Maxs = aabb.Maxs;
}
public A3DAABB(A3DVECTOR3 mins, A3DVECTOR3 maxs)
{
Mins = mins;
Maxs = maxs;
Center = (mins + maxs) * 0.5f;
Extents = maxs - Center;
}
// Reset AABB về trạng thái rỗng
public void Clear()
{
Mins = new A3DVECTOR3(999999f, 999999f, 999999f);
Maxs = new A3DVECTOR3(-999999f, -999999f, -999999f);
Center = new A3DVECTOR3(0f, 0f, 0f);
Extents = new A3DVECTOR3(0f, 0f, 0f);
}
// Thêm 1 điểm vào AABB
public void AddVertex(A3DVECTOR3 v)
{
if (v.x < Mins.x) Mins.x = v.x;
if (v.y < Mins.y) Mins.y = v.y;
if (v.z < Mins.z) Mins.z = v.z;
if (v.x > Maxs.x) Maxs.x = v.x;
if (v.y > Maxs.y) Maxs.y = v.y;
if (v.z > Maxs.z) Maxs.z = v.z;
CompleteCenterExts();
}
// Hợp nhất 2 AABB
public void Merge(A3DAABB subAABB)
{
if (subAABB.Mins.x < Mins.x) Mins.x = subAABB.Mins.x;
if (subAABB.Mins.y < Mins.y) Mins.y = subAABB.Mins.y;
if (subAABB.Mins.z < Mins.z) Mins.z = subAABB.Mins.z;
if (subAABB.Maxs.x > Maxs.x) Maxs.x = subAABB.Maxs.x;
if (subAABB.Maxs.y > Maxs.y) Maxs.y = subAABB.Maxs.y;
if (subAABB.Maxs.z > Maxs.z) Maxs.z = subAABB.Maxs.z;
CompleteCenterExts();
}
// Cập nhật Mins, Maxs từ Center + Extents
public void CompleteMinsMaxs()
{
Mins = Center - Extents;
Maxs = Center + Extents;
}
// Cập nhật Center + Extents từ Mins, Maxs
public void CompleteCenterExts()
{
Center = (Mins + Maxs) * 0.5f;
Extents = Maxs - Center;
}
// Kiểm tra điểm có nằm trong AABB không
public bool IsPointIn(A3DVECTOR3 v)
{
return !(v.x > Maxs.x || v.x < Mins.x ||
v.y > Maxs.y || v.y < Mins.y ||
v.z > Maxs.z || v.z < Mins.z);
}
// Kiểm tra 1 AABB khác có nằm trong AABB này không
public bool IsAABBIn(A3DAABB aabb)
{
return (aabb.Mins.x >= Mins.x && aabb.Maxs.x <= Maxs.x &&
aabb.Mins.y >= Mins.y && aabb.Maxs.y <= Maxs.y &&
aabb.Mins.z >= Mins.z && aabb.Maxs.z <= Maxs.z);
}
// Xây AABB từ một tập vertices
public void Build(A3DVECTOR3[] vertices)
{
Clear();
foreach (var v in vertices)
AddVertex(v);
}
// Lấy các vertices (8 điểm) của AABB
public A3DVECTOR3[] GetVertices()
{
A3DVECTOR3[] verts = new A3DVECTOR3[8];
verts[0] = new A3DVECTOR3(Mins.x, Mins.y, Mins.z);
verts[1] = new A3DVECTOR3(Maxs.x, Mins.y, Mins.z);
verts[2] = new A3DVECTOR3(Maxs.x, Maxs.y, Mins.z);
verts[3] = new A3DVECTOR3(Mins.x, Maxs.y, Mins.z);
verts[4] = new A3DVECTOR3(Mins.x, Mins.y, Maxs.z);
verts[5] = new A3DVECTOR3(Maxs.x, Mins.y, Maxs.z);
verts[6] = new A3DVECTOR3(Maxs.x, Maxs.y, Maxs.z);
verts[7] = new A3DVECTOR3(Mins.x, Maxs.y, Maxs.z);
return verts;
}
}
}
@@ -18,7 +18,7 @@ namespace BrewMonster
public static Skill56Stub __stub_Skill56Stub = new Skill56Stub();
public static Skill57Stub __stub_Skill57Stub = new Skill57Stub();
public static Skill58Stub __stub_Skill58Stub = new Skill58Stub();
//public static Skill59Stub __stub_Skill59Stub = new Skill59Stub();
public static Skill59Stub __stub_Skill59Stub = new Skill59Stub();
//public static Skill60Stub __stub_Skill60Stub = new Skill60Stub();
//public static Skill61Stub __stub_Skill61Stub = new Skill61Stub();
//public static Skill62Stub __stub_Skill62Stub = new Skill62Stub();
@@ -30,6 +30,7 @@ namespace BrewMonster.Scripts.Skills
{
id = i;
stub = s;
player = new PlayerWrapper();
}
public static Skill Create(uint id, int n)
{
@@ -61,6 +62,8 @@ namespace BrewMonster.Scripts.Skills
{
return stub.is_senior != 0 ? stub.pre_skills : new Dictionary<uint, int>();
}
public override int GetRangeType() { return stub.GetRange().type; }
public override int GetTargetType()
{
if (stub.restrict_corpse == 1)
@@ -227,3 +227,4 @@ namespace BrewMonster
@@ -227,3 +227,4 @@ namespace BrewMonster
@@ -324,3 +324,4 @@ namespace BrewMonster
@@ -318,3 +318,4 @@ namespace BrewMonster
@@ -329,3 +329,4 @@ namespace BrewMonster
@@ -322,3 +322,4 @@ namespace BrewMonster
@@ -0,0 +1,316 @@
#define SKILL_CLIENT
using BrewMonster.Scripts.Skills;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using static BrewMonster.PET_EVOLVE_CONFIG;
namespace BrewMonster
{
#if SKILL_SERVER
public class Skill59 : Skill
{
public const int SKILL_ID = 59;
public Skill59() : base(SKILL_ID)
{
}
}
#endif
public class Skill59Stub : SkillStub
{
private static readonly int[] RequiredLevelArray = { 29, 34, 39, 44, 49, 54, 59, 64, 69, 74 };
private static readonly int[] RequiredSpArray = { 3540, 5190, 7380, 10260, 14100, 19200, 26100, 35400, 48000, 71700 };
private static readonly int[] RequiredMoneyArray = { 1090, 1540, 1990, 2480, 2980, 3480, 3980, 12980, 51980, 151980 };
#if SKILL_SERVER
public class State1 : SkillStub.State
{
public int GetTime(Skill skill)
{
return 0;
}
public bool Quit(Skill skill)
{
return false;
}
public bool Loop(Skill skill)
{
return false;
}
public bool Bypass(Skill skill)
{
return false;
}
public void Calculate(Skill skill)
{
skill.GetPlayer().SetPray(1);
}
public bool Interrupt(Skill skill)
{
return false;
}
public bool Cancel(Skill skill)
{
return true;
}
public bool Skip(Skill skill)
{
return false;
}
}
#endif
#if SKILL_SERVER
public class State2 : SkillStub.State
{
public int GetTime(Skill skill)
{
return 1000;
}
public bool Quit(Skill skill)
{
return false;
}
public bool Loop(Skill skill)
{
return false;
}
public bool Bypass(Skill skill)
{
return false;
}
public void Calculate(Skill skill)
{
skill.GetPlayer().SetPerform(1);
}
public bool Interrupt(Skill skill)
{
return false;
}
public bool Cancel(Skill skill)
{
return false;
}
public bool Skip(Skill skill)
{
return false;
}
}
#endif
#if SKILL_SERVER
public class State3 : SkillStub.State
{
public int GetTime(Skill skill)
{
return 0;
}
public bool Quit(Skill skill)
{
return false;
}
public bool Loop(Skill skill)
{
return false;
}
public bool Bypass(Skill skill)
{
return false;
}
public void Calculate(Skill skill)
{
}
public bool Interrupt(Skill skill)
{
return false;
}
public bool Cancel(Skill skill)
{
return false;
}
public bool Skip(Skill skill)
{
return false;
}
}
#endif
public Skill59Stub() : base(59)
{
cls = 0;
name = "虎跃";
nativename = "虎跃";
icon = "虎跃.dds";
max_level = 10;
type = 8;
apcost = 10;
arrowcost = 0;
apgain = 0;
attr = 1;
rank = 3;
eventflag = 0;
posdouble = 0;
clslimit = 0;
time_type = 0;
showorder = 1129;
allow_land = true;
allow_air = true;
allow_water = true;
allow_ride = false;
auto_attack = false;
long_range = 0;
restrict_corpse = 0;
allow_forms = 1;
effect = "虎跃.sgc";
range = new Range();
range.type = 5;
doenchant = 1;
dobless = 0;
commoncooldown = 0;
commoncooldowntime = 0;
pre_skills = new Dictionary<uint, int>();
pre_skills.Add(0, 1);
restrict_weapons.Add(0);
restrict_weapons.Add(1);
restrict_weapons.Add(182);
restrict_weapons.Add(5);
restrict_weapons.Add(292);
restrict_weapons.Add(9);
#if SKILL_SERVER
statestub.Add(new State1());
statestub.Add(new State2());
statestub.Add(new State3());
#endif
}
~Skill59Stub()
{
}
public float GetMpcost(Skill skill)
{
return 0f;
}
public int GetExecutetime(Skill skill)
{
return 1000;
}
public int GetCoolingtime(Skill skill)
{
return 16000 - 1000 * skill.GetLevel();
}
public int GetRequiredLevel(Skill skill)
{
return RequiredLevelArray[skill.GetLevel() - 1];
}
public int GetRequiredSp(Skill skill)
{
return RequiredSpArray[skill.GetLevel() - 1];
}
public int GetRequiredMoney(Skill skill)
{
return RequiredMoneyArray[skill.GetLevel() - 1];
}
public float GetRadius(Skill skill)
{
return 0f;
}
public float GetAttackdistance(Skill skill)
{
return 0f;
}
public float GetAngle(Skill skill)
{
return (float)(1 - 0.0111111 * 0);
}
public float GetPraydistance(Skill skill)
{
return (float)(10 + 0.6 * skill.GetLevel());
}
#if SKILL_CLIENT
public int GetIntroduction(Skill skill, StringBuilder buffer, int length, string format)
{
string result = string.Format(format,
skill.GetLevel(),
16 - skill.GetLevel(),
10 + 0.6 * skill.GetLevel());
if (result.Length < length)
{
buffer.Append(result);
return result.Length;
}
return 0;
}
#endif
#if SKILL_SERVER
public int GetEnmity(Skill skill)
{
return 0;
}
public bool StateAttack(Skill skill)
{
skill.GetVictim().SetProbability(1.0f * 100);
skill.GetVictim().SetTime(2100);
skill.GetVictim().SetRatio(0.65f);
skill.GetVictim().SetIncdebuffdodge(1);
return true;
}
public bool TakeEffect(Skill skill)
{
return true;
}
public float GetEffectdistance(Skill skill)
{
return 25f;
}
public int GetAttackspeed(Skill skill)
{
return 0;
}
public float GetHitrate(Skill skill)
{
return 1f;
}
#endif
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4ed6ddc876b1d6d4d91c7bbf94bc0c8f
@@ -232,3 +232,4 @@ namespace BrewMonster
@@ -35,6 +35,13 @@ namespace BrewMonster.Scripts.World
return pTerrain.GetPosHeight(vPos, ref pvNormal);
}
public float GetWaterHeight(A3DVECTOR3 vPos)
{
// TODO: Hook into the actual water system once it is available.
A3DVECTOR3 dummy = default;
return GetTerrainHeight(vPos, ref dummy);
}
public CECObject GetObject(int idObject, int iAliveFlag)
{
CECObject pObject = null;
+370 -56
View File
@@ -1214,7 +1214,7 @@ namespace BrewMonster
trcInfo.vExt = vExt;
trcInfo.vStart = vTargetPos + EC_Utility.ToA3DVECTOR3(g_vAxisY) * vExt.y;
trcInfo.vDelta = new A3DVECTOR3(0);
if (EC_CDR.CollideWithEnv(trcInfo))
if (EC_CDR.CollideWithEnv(ref trcInfo))
break;
bAvailable = true;
@@ -1223,6 +1223,319 @@ namespace BrewMonster
return bAvailable;
}
private float CalcAABBOnCollidePos(A3DAABB aabbTarget)
{
// ¸ù¾Ý HostPlayer Óëij¶ÔÏó£¨ÈçNPC£© AABB£¬¼ÆËã AABB ³åÍ»ÁÙ½ç״̬ÏÂÁ½Õß¾àÀë (Compute the separation distance between host/player AABBs when they nearly collide)
// ·µ»ØÖµÓ¦Êʵ±Ôö¼ÓÒ»¸öÔöÁ¿£¬¼´Àë³åͻλÖÃÉÔԶЩ (Return value should keep a slightly safer distance)
float fAABBCollideDist = 0.0f;
A3DAABB aabbHost = m_aabb;
A3DVECTOR3 vHostHeight = new A3DVECTOR3(0.0f, aabbHost.Extents.y, 0.0f);
A3DVECTOR3 vHostRoot = aabbHost.Center - vHostHeight;
A3DVECTOR3 vTargetHeight = new A3DVECTOR3(0.0f, aabbTarget.Extents.y, 0.0f);
A3DVECTOR3 vTargetRoot = aabbTarget.Center - vTargetHeight;
A3DVECTOR3 vRootDir = vTargetRoot - vHostRoot;
float fRootDist = vRootDir.Normalize();
float fMinDist = Mathf.Min(Mathf.Min(aabbHost.Extents.x, aabbHost.Extents.y), aabbHost.Extents.z);
fMinDist = Mathf.Max(fMinDist, 0.01f);
if (fRootDist >= fMinDist)
{
A3DVECTOR3 vCenterDelta0 = aabbHost.Center - aabbTarget.Center;
A3DVECTOR3 vTargetExt = aabbTarget.Extents;
A3DVECTOR3 vHostExt = aabbHost.Extents;
A3DVECTOR3 vSumExt = vTargetExt + vHostExt;
A3DVECTOR3 t = new A3DVECTOR3(0.0f);
const float fZero = 0.001f;
if (Mathf.Abs(vRootDir.x) >= fZero)
{
float t1 = (vSumExt.x - vCenterDelta0.x) / vRootDir.x;
float t2 = (vSumExt.x + vCenterDelta0.x) / -vRootDir.x;
if (t1 >= fZero && t1 < fRootDist) t.x = t1;
if (t2 >= fZero && t2 < fRootDist && t2 > t.x) t.x = t2;
}
if (Mathf.Abs(vRootDir.y) >= fZero)
{
float t1 = (vSumExt.y - vCenterDelta0.y) / vRootDir.y;
float t2 = (vSumExt.y + vCenterDelta0.y) / -vRootDir.y;
if (t1 >= fZero && t1 < fRootDist) t.y = t1;
if (t2 >= fZero && t2 < fRootDist && t2 > t.y) t.y = t2;
}
if (Mathf.Abs(vRootDir.z) >= fZero)
{
float t1 = (vSumExt.z - vCenterDelta0.z) / vRootDir.z;
float t2 = (vSumExt.z + vCenterDelta0.z) / -vRootDir.z;
if (t1 >= fZero && t1 < fRootDist) t.z = t1;
if (t2 >= fZero && t2 < fRootDist && t2 > t.z) t.z = t2;
}
float fHostMove = 0.0f;
if (t.x > 0.0f) fHostMove = t.x;
if (t.y > 0.0f && t.y > fHostMove) fHostMove = t.y;
if (t.z > 0.0f && t.z > fHostMove) fHostMove = t.z;
if (fHostMove > 0.0f)
{
fAABBCollideDist = fRootDist - fHostMove;
}
}
return fAABBCollideDist;
}
private bool CalcCollideFreePos(A3DAABB aabbTarget, out A3DVECTOR3 vPos)
{
// ¸ù¾Ýµ±Ç° HostPlayer λÖÃÓë¸ø¶¨Ä¿±êµÄÅöײ°üΧºÐ aabbTarget£¬¼ÆËãÄ¿±ê¸½½ü(ÓëµØÐκÍ͹°ü)ÎÞ³åÍ»µÄλÖà (Find a terrain/brush free position near the target AABB)
// vPos ´æ·ÅÎÞ³åÍ»µÄλÖ㬿ÉÓÃÓÚ SetPos (vPos stores the safe position for SetPos)
bool bFound = false;
vPos = default;
A3DAABB aabbHost = m_aabb;
A3DVECTOR3 vHostHeight = new A3DVECTOR3(0.0f, aabbHost.Extents.y, 0.0f);
A3DVECTOR3 vHostRoot = aabbHost.Center - vHostHeight;
A3DVECTOR3 vTargetHeight = new A3DVECTOR3(0.0f, aabbTarget.Extents.y, 0.0f);
A3DVECTOR3 vTargetRoot = aabbTarget.Center - vTargetHeight;
A3DVECTOR3 vRootDir = vTargetRoot - vHostRoot;
float fRootDist = vRootDir.Normalize();
float fAABBCollideDist = CalcAABBOnCollidePos(aabbTarget);
if (fAABBCollideDist > 0.0f)
{
float[] fDeltaTests = { 0.001f, 0.1f };
foreach (float fDelta in fDeltaTests)
{
// ¿¼Âǵ½µØÐÎÆð·üµÈÒòËØ£¬Óëʵ¼Ê³åͻλÖÃÀ­¿ªÒ»¶¨¾àÀë²¢Öð¸ö²âÊÔ£¬ÒÔÔö´ó³É¹¦·µ»Ø¼¸ÂÊ (Offset slightly to improve success probability)
if (fRootDist > fAABBCollideDist + fDelta)
{
float fTestMoveDist = fRootDist - (fAABBCollideDist + fDelta);
A3DVECTOR3 vTestPos = vHostRoot + vRootDir * fTestMoveDist;
// ¸ù¾ÝµØÐκÍ͹°ü½øÐÐÐÞÕý¡¢²¢²âÊÔ¿ÉÓÃÐÔ (Adjust with terrain/brush constraints and verify)
vTestPos.y = ClampAboveGround(vTestPos);
if (IsPosCollideFree(vTestPos))
{
// ºÍ͹°üÎÞÅöײ£¬Ö±½Ó¿ÉÓà (No brush collision, use directly)
bFound = true;
vPos = vTestPos;
}
else
{
// ºÍ͹°üÓÐÅöײ£¬³¢ÊÔÔÚÊúÖ±·½ÏòÉϲéÕÒ (If still colliding, search vertically)
if (CalcVerticalCollideFreePos(vTestPos, out A3DVECTOR3 vTestPos2))
{
bFound = true;
vPos = vTestPos2;
}
}
if (bFound)
{
break;
}
}
}
}
return bFound;
}
private bool CalcBrushOnCollidePos(A3DVECTOR3 vTestPos, A3DVECTOR3 vDelta, A3DVECTOR3 vExtents, out A3DVECTOR3 vPos, out bool bNoCollide)
{
// ·µ»Ø true£ºvPos ΪÎÞÅöײλÖã»Èô bNoCollide Ϊ true£¬Ôò vPos Ϊ vTestPos£»·ñÔòΪ¼ÆËã³öµÄλÖà (Return true with vPos pointing at a usable location; if bNoCollide==true the input position was already free)
// ·µ»Ø false£ºÒâζ×Å bStartSolid = true (Return false implies we started within solid geometry)
bool bFound = false;
A3DVECTOR3 vCenterHeight = new A3DVECTOR3(0.0f, vExtents.y, 0.0f);
env_trace_t trcInfo = new env_trace_t
{
dwCheckFlag = EC_CDR.CDR_EVN.CDR_BRUSH,
vExt = vExtents,
vStart = vTestPos + vCenterHeight,
vDelta = vDelta,
vTerStart = vTestPos + vCenterHeight,
vWatStart = vTestPos + vCenterHeight,
bWaterSolid = false
};
if (EC_CDR.CollideWithEnv(ref trcInfo))
{
bNoCollide = false;
if (!trcInfo.bStartSolid)
{
vPos = trcInfo.vStart + trcInfo.fFraction * trcInfo.vDelta - vCenterHeight;
bFound = true;
}
else
{
vPos = default;
}
}
else
{
vPos = vTestPos;
bNoCollide = true;
bFound = true;
}
if (!bFound)
{
vPos = default;
bNoCollide = false;
}
return bFound;
}
private bool CalcVerticalCollideFreePos(A3DVECTOR3 vRefPos, out A3DVECTOR3 vPos)
{
// ¼ÆËã vRefPos ¸½½üÊúÖ±·½ÏòÉÏÓë͹°ü¼°µØÐÎÎÞ³åÍ»µÄλÖà (Search along the vertical direction around vRefPos for a collision-free spot)
// vRefPos Ϊ HostPlayer foot λÖà (vRefPos corresponds to the host's foot)
bool bFound = false;
vPos = default;
CECWorld world = CECWorld.Instance;
if (world == null)
{
return false;
}
while (true)
{
A3DAABB hostAabb = m_aabb;
A3DVECTOR3 vHostExts = hostAabb.Extents;
// ¹¹½¨ËõС°æ HostPlayer £¬ÏòÏÂѰÕÒ¿ÉÓÃλÖà (Use a shrinked collider to probe downward)
A3DVECTOR3 vShrinkExts = new A3DVECTOR3(vHostExts.x, vHostExts.y * 0.5f, vHostExts.z);
A3DVECTOR3 vShrinkPos = vRefPos + new A3DVECTOR3(0.0f, vHostExts.y * 0.5f, 0.0f);
A3DVECTOR3 vStartPos = vShrinkPos;
A3DVECTOR3 vVerticalDelta = new A3DVECTOR3(0.0f, -1.0f, 0.0f);
A3DVECTOR3 dummyNormal = default;
float terrainHeight = world.GetTerrainHeight(vStartPos, ref dummyNormal);
if (vStartPos.y < terrainHeight + 0.01f)
{
// ²âÊÔλÖÃÐè´¦ÓÚµØÐÎÒÔÉÏ (Candidate must be above the terrain)
break;
}
if (!CalcBrushOnCollidePos(vStartPos, vVerticalDelta, vShrinkExts, out A3DVECTOR3 vCandidate, out bool bNoCollide))
{
// vStartPos ´¦ÓÚ͹°üÀï (Start position lies inside a brush)
break;
}
if (bNoCollide)
{
// ´Ó vStartPos µ½ vRefPos ¶¼ÎÞÅöײ£¬¿ÉÄÜÊÇ (No collision between vStartPos and vRefPos; possible cases)
// ÇéÐÎ1£ºvRefPos ´¦Í·¶¥ÓÐ͹°üµ¼ÖÂÅöײ£¨´Ó¶øµ÷Óô˺¯ÊýÐÞÕý£© (Case1: upper brush causes the issue)
// ÇéÐÎ2£º»òÕß vRefPos ±¾Éí¼´ÎÞÅöײ£¬Îóµ÷Óô˺¯Êý×öÖØ¸´¼ÆËã (Case2: vRefPos was already free)
// ÇéÐÎ3£º»òÆäËüδ¿¼ÂÇÇé¿ö (Case3: other edge cases)
// ³¢ÊԴӵײ¿Ïò vRefPos ʹÓÃԭʼ´óС HostPlayer ²éÕÒÎÞÅöײλÖã¬ÒÔ´¦ÀíÉÏÊöÇéÐÎ1 (Try again with the original extents to address case1)
vStartPos += vVerticalDelta;
vVerticalDelta = vRefPos - vStartPos;
if (!CalcBrushOnCollidePos(vStartPos, vVerticalDelta, vHostExts, out vCandidate, out bNoCollide))
{
break;
}
if (bNoCollide)
{
vCandidate = vRefPos;
}
// else vCandidate ÊÇËõС°æ HostPlayer ÎÞÅöײµÄλÖã¬Ò²ÊÇʵ¼Ê´óС HostPlayer ÐÞÕý vRefPos µÄλÖà (Otherwise the computed candidate already fixes the offset)
}
vCandidate.y = ClampAboveGround(vCandidate);
if (!IsPosCollideFree(vCandidate))
{
// λÖóåÍ» (Still interpenetrating)
break;
}
vPos = vCandidate;
bFound = true;
break;
}
return bFound;
}
private float ClampAboveGround(A3DVECTOR3 vPos)
{
// ½« vPos ÏÞÖÆµ½µØÃæÒÔÉÏ (Clamp vPos above the ground)
// ·ÉÐÐ״̬»òË®µ×ʱ£¬ÏÞÖÆÈËÎïÔÚË®ÃæÒÔÉÏ£¬ÀëË®Ãæ/µØÃæÒ»¶¨¾àÀ룻Èôµ÷Õûºó vPos ÊúÖ±ÍùÏÂÓÐ͹°ü£¬Ôò»¹»áÏÞÖÆµ½Àë͹°üÒ»¶¨¾àÀë (When flying/underwater we also keep distance from surfaces and nearby brushes)
// ×¢Ò⣺vPos ±»µ÷Õûºó£¬ÓпÉÄÜ´¦ÓÚ͹°üÖУ»Ðè¼ì²é·µ»Ø¸ß¶Èµ÷ÕûÖµ£¬ÒÔ±ÜÃâµ÷Õû¹ý´ó (Beware of large adjustments placing us back into brushes)
A3DVECTOR3 vTemp = new A3DVECTOR3(vPos);
CECWorld world = CECWorld.Instance;
if (world == null)
{
return vTemp.y;
}
while (true)
{
A3DVECTOR3 dummyNormal = default;
float fTerrainHeight = world.GetTerrainHeight(vTemp, ref dummyNormal);
vTemp.y = EC_Utility.a_ClampFloor(vTemp.y, fTerrainHeight);
A3DAABB hostAabb = m_aabb;
A3DVECTOR3 vExts = hostAabb.Extents;
if (IsFlying())
{
float fAbove = m_MoveConst.fMinAirHei;
// Ïȱ£Ö¤ÀëµØÃæ/Ë®ÃæÒ»¶¨¸ß¶È (Keep some height over terrain/water)
float fWaterHeight = world.GetWaterHeight(vTemp);
float fSurface = Mathf.Max(fTerrainHeight, fWaterHeight);
vTemp.y = EC_Utility.a_ClampFloor(vTemp.y, fSurface + fAbove);
// ÔÙ³¢ÊÔÀë͹°üÒ»¶¨¸ß¶È (Then test against brushes)
if (!CalcBrushOnCollidePos(vTemp, GPDataTypeHelper.g_vAxisY * (fSurface - vTemp.y), vExts, out A3DVECTOR3 vHitPos, out bool bNoCollide) || bNoCollide)
{
break;
}
// ÉèÖÃÀë͹°üÒ»¶¨¸ß¶È (Clamp to stay above brushes)
vTemp.y = EC_Utility.a_ClampFloor(vTemp.y, vHitPos.y + fAbove);
break;
}
float fWaterHeightLow = world.GetWaterHeight(vTemp);
if (fWaterHeightLow > fTerrainHeight && vTemp.y + vExts.y < fWaterHeightLow - m_MoveConst.fWaterSurf)
{
// Ë®µ× (Underwater)
float fAbove = m_MoveConst.fMinWaterHei;
// Ïȱ£Ö¤ÀëË®µ×Ò»¶¨¾àÀë (Keep distance from the riverbed)
vTemp.y = EC_Utility.a_ClampFloor(vTemp.y, fTerrainHeight + fAbove);
// ÔÙ³¢ÊÔÀë͹°üÒ»¶¨¸ß¶È (Then ensure clearance from brushes)
if (!CalcBrushOnCollidePos(vTemp, GPDataTypeHelper.g_vAxisY * (fTerrainHeight - vTemp.y), vExts, out A3DVECTOR3 vHitPos, out bool bNoCollide) || bNoCollide)
{
break;
}
// ÉèÖÃÀë͹°üÒ»¶¨¸ß¶È (Clamp relative to brush hit position)
vTemp.y = EC_Utility.a_ClampFloor(vTemp.y, vHitPos.y + fAbove);
break;
}
// µØÃæÉÏ£¬ÎÞÐèÔÙ´¦Àí (Already safe on ground)
break;
}
return vTemp.y;
}
public void OnMsgHstPickupItem(in ECMSG Msg)
{
var data = Msg.dwParam1 as byte[];
@@ -2886,7 +3199,7 @@ namespace BrewMonster
// 刺客如影随行类技能 (Assassin shadow-following skills)
bool bSuccess = false;
do
while (true)
{
// Break if no target or self-target
if (idTarget == 0 || idTarget == GetCharacterID())
@@ -2946,62 +3259,63 @@ namespace BrewMonster
A3DVECTOR3 vMovePos = vHostPos + vMoveDir * (fDist - fNearDist);
// TODO: Implement ClampAboveGround
// float fClampedHeight = ClampAboveGround(vMovePos);
// if (Mathf.Abs(fClampedHeight - vMovePos.y) >= 5.0f)
// {
// Debug.Log("Would stuck or so");
// break;
// }
// vMovePos.y = fClampedHeight;
float fClampedHeight = ClampAboveGround(vMovePos);
if (Mathf.Abs(fClampedHeight - vMovePos.y) >= 5.0f)
{
Debug.Log("Would stuck or so");
break;
}
vMovePos.y = fClampedHeight;
bool bPosVerified = false;
// 目标为带凸包的 NPC 时,单独处理 (Special handling for NPCs with collision)
if (GPDataTypeHelper.ISNPCID(idTarget))
{
// TODO: Implement CalcCollideFreePos for NPC AABB
// CECNPC pNPC = pObject as CECNPC;
// A3DAABB aabbNPC;
// if (pNPC.GetCHAABB(out aabbNPC))
// {
// A3DVECTOR3 vTestPos;
// if (CalcCollideFreePos(aabbNPC, out vTestPos))
// {
// vMovePos = vTestPos;
// bPosVerified = true;
// }
// else
// {
// Debug.Log("Would stuck or so");
// break;
// }
// }
CECNPC pNPC = pObject as CECNPC;
A3DAABB aabbNPC = new A3DAABB();
if (pNPC.GetCHAABB(ref aabbNPC))
{
A3DVECTOR3 vTestPos;
if (CalcCollideFreePos(aabbNPC, out vTestPos))
{
vMovePos = vTestPos;
bPosVerified = true;
}
else
{
Debug.Log("Would stuck or so");
break;
}
}
}
// TODO: Implement collision checking
// if (!bPosVerified && !IsPosCollideFree(vMovePos))
// {
// A3DVECTOR3 vTestPos2;
// if (!CalcVerticalCollideFreePos(vMovePos, out vTestPos2))
// {
// Debug.Log("Would stuck or so");
// break;
// }
// vMovePos = vTestPos2;
// bPosVerified = true;
// }
if (!bPosVerified && !IsPosCollideFree(vMovePos))
{
A3DVECTOR3 vTestPos2;
if (!CalcVerticalCollideFreePos(vMovePos, out vTestPos2))
{
Debug.Log("Would stuck or so");
break;
}
vMovePos = vTestPos2;
bPosVerified = true;
}
// TODO: Implement IsTooNear check for final position
// if (IsTooNear(vMovePos))
// {
// Debug.Log("Target is too near");
// break;
// }
//TODO: Implement IsTooNear check for final position
float reffake = 0;
if (IsTooNear(vMovePos, ref reffake))
{
Debug.Log("Target is too near");
break;
}
// 发送协议 (Send protocol)
UnityGameSession.c2s_CmdCastPosSkill(m_pPrepSkill.GetSkillID(), EC_Utility.ToVector3(vMovePos), byPVPMask, 1, idTarget);
bSuccess = true;
} while (false);
}
m_pPrepSkill = null;
return bSuccess;
@@ -3091,24 +3405,24 @@ namespace BrewMonster
byMask |= (byte)PVPMask.GP_PVPMASK_FORCE;
else
{
/* CECConfigs pConfigs = EC_Game.GetConfigs();
CECConfigs pConfigs = EC_Game.GetConfigs();
if (pConfigs.GetGameSettings().bAtk_Player)
{
byMask |= GP_PVPMASK_FORCE;
if (pConfigs.GetGameSettings().bAtk_Player)
{
byMask |= (byte)PVPMask.GP_PVPMASK_FORCE;
if (pConfigs.GetGameSettings().bAtk_NoMafia)
byMask |= GP_PVPMASK_NOMAFIA;
if (pConfigs.GetGameSettings().bAtk_NoMafia)
byMask |= (byte)PVPMask.GP_PVPMASK_NOMAFIA;
if (pConfigs.GetGameSettings().bAtk_NoWhite)
byMask |= GP_PVPMASK_NOWHITE;
if (pConfigs.GetGameSettings().bAtk_NoWhite)
byMask |= (byte)PVPMask.GP_PVPMASK_NOWHITE;
if (pConfigs.GetGameSettings().bAtk_NoAlliance)
byMask |= GP_PVPMASK_NOALLIANCE;
if (pConfigs.GetGameSettings().bAtk_NoAlliance)
byMask |= (byte)PVPMask.GP_PVPMASK_NOALLIANCE;
if (pConfigs.GetGameSettings().bAtk_NoForce)
byMask |= GP_PVPMASK_NOFORCE;
}*/
if (pConfigs.GetGameSettings().bAtk_NoForce)
byMask |= (byte)PVPMask.GP_PVPMASK_NOFORCE;
}
}
return byMask;
File diff suppressed because one or more lines are too long