fix: update logic swim.

This commit is contained in:
Tungdv
2025-12-31 15:09:10 +07:00
parent 8da1b60188
commit 8508ad873f
3 changed files with 245 additions and 52 deletions
@@ -175,8 +175,8 @@ namespace BrewMonster.Scripts
{
if (m_pHost.m_iMoveEnv == CECPlayer.Move_environment.MOVEENV_GROUND)
Tick_Walk(fDeltaTime);
/* else // AIR or WATER
Tick_FlySwim(fDeltaTime);*/
else // AIR or WATER
Tick_FlySwim(fDeltaTime);
}
if (m_iPoseAction == (int)PLAYER_ACTION_TYPE.ACT_STAND)
@@ -236,25 +236,37 @@ namespace BrewMonster.Scripts
}
// Tick routine of flying or swimming
/* bool Tick_FlySwim(float fDeltaTime)
{
m_bMoving = false;
bool Tick_FlySwim(float fDeltaTime)
{
m_bMoving = false;
if (m_pHost.m_iMoveEnv == CECPlayer.Move_environment.MOVEENV_WATER && !m_bWaterStop)
{
// Handle floating at water surface after falling into water
A3DVECTOR3 vCurPos = m_pHost.GetPos();
// ON_AIR_CDR_INFO not available in current C# port; approximate using CDR_INFO where applicable
float fSpeed = m_pHost.GetSwimSpeedSev();
if (m_pHost.m_iMoveEnv == CECPlayer.Move_environment.MOVEENV_WATER && !m_bWaterStop)
{
// Handle floating at water surface after falling into water
A3DVECTOR3 vCurPos = m_pHost.GetPos();
ON_AIR_CDR_INFO cdr = m_pHost.m_AirCDRInfo;
float fSpeed = m_pHost.GetSwimSpeedSev();
// As we don't have water height/extent readily available on host in this port,
// retain structure and leave movement here minimal.
// If water height APIs are added, restore the original logic.
// m_bMoving = true; // enable when full water logic is available
}
if (m_pHost.m_GndInfo.fWaterHei - vCurPos.y < cdr.vExtent.y + m_pHost.m_MoveConst.fWaterSurf)
{
m_bMoving = true;
return true;
}*/
vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(-GPDataTypeHelper.g_vAxisY, fSpeed, fDeltaTime, false, false);
m_pHost.SetPos(EC_Utility.ToVector3(vCurPos));
if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3 ||
m_pHost.m_GndInfo.fWaterHei - vCurPos.y >= cdr.vExtent.y + m_pHost.m_MoveConst.fWaterSurf)
{
m_bWaterStop = true;
m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed, (int)GPMoveMode.GP_MOVE_WATER | (int)GPMoveMode.GP_MOVE_RUN);
}
else
m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, GPDataTypeHelper.g_vOrigin, -GPDataTypeHelper.g_vAxisY * fSpeed, (int)GPMoveMode.GP_MOVE_WATER | (int)GPMoveMode.GP_MOVE_RUN);
}
}
return true;
}
// Get stop sliding flag
public bool GetStopSlideFlag()
+214 -33
View File
@@ -18,6 +18,8 @@ namespace BrewMonster
public static LayerMask WaterMask { get; set; } = 1 << 8;
public static RaycastHit[] hits = new RaycastHit[5];
public static RaycastHit[] fHitsTerrain = new RaycastHit[5];
public static RaycastHit[] fHitsWater = new RaycastHit[5];
const float LOCAL_EPSILON = 1e-5f;
const float FLY_MAX_HEIGHT = 800.0f; // ·ÉÐеÄ×î´ó¸ß¶È£¡
@@ -113,62 +115,99 @@ namespace BrewMonster
Vector3 vExt = EC_Utility.ToVector3(pEnvTrc.vExt);
Vector3 vDelta = EC_Utility.ToVector3(pEnvTrc.vDelta);
Vector3 vTerStart = EC_Utility.ToVector3(pEnvTrc.vTerStart);
Vector3 vWatStart = EC_Utility.ToVector3(pEnvTrc.vWatStart);
Vector3 dir = Vector3.zero;
int countHits = 0;
if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_BRUSH) == CDR_EVN.CDR_BRUSH)
{
dir = vStart + vDelta;
if (Physics.BoxCast(vStart, vExt, dir, out RaycastHit hit, Quaternion.identity, vDelta.magnitude, 1 << 7))
dir = vDelta;
countHits = Physics.BoxCastNonAlloc(vStart, vExt, dir.normalized, hits, Quaternion.identity, vDelta.magnitude, 1 << 7);
if (countHits > 0 && Vector3.Distance(hits[0].point, vStart) > 0.0009f)
{
pEnvTrc.fFraction = (hit.distance - vExt.x) / vDelta.magnitude;
pEnvTrc.vHitNormal = EC_Utility.ToA3DVECTOR3(hit.normal);
pEnvTrc.fFraction = (hits[0].distance - vExt.x) / vDelta.magnitude;
pEnvTrc.vHitNormal = EC_Utility.ToA3DVECTOR3(hits[0].normal);
pEnvTrc.dwClsFlag = CDR_EVN.CDR_BRUSH;
}
else
{
pEnvTrc.fFraction = 1f;
}
}
if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_TERRAIN) == CDR_EVN.CDR_TERRAIN)
{
float fFractionTerrain = 0f;
dir = vDelta;
if (Physics.Raycast(vTerStart, dir.normalized, out RaycastHit hit, vDelta.magnitude, 1 << 6))
float fFractionTerrain = 100f;
dir = vTerStart + vDelta;
countHits = 0;
countHits = Physics.RaycastNonAlloc(vTerStart, dir.normalized, fHitsTerrain, vDelta.magnitude, 1 << 6);
if (countHits > 0 && Vector3.Distance(fHitsTerrain[0].point, vTerStart) > 0.0009f)
{
fFractionTerrain = (hit.distance) / vDelta.magnitude;
pEnvTrc.vHitNormal = EC_Utility.ToA3DVECTOR3(hit.normal);
fFractionTerrain = (hits[0].distance) / vDelta.magnitude;
pEnvTrc.vHitNormal = EC_Utility.ToA3DVECTOR3(hits[0].normal);
pEnvTrc.dwClsFlag = CDR_EVN.CDR_TERRAIN;
}
else
{
fFractionTerrain = 1f;
}
if (fFractionTerrain < pEnvTrc.fFraction)
{
hits = fHitsTerrain;
pEnvTrc.fFraction = fFractionTerrain;
}
}
if ((pEnvTrc.dwCheckFlag & CDR_EVN.CDR_WATER) == CDR_EVN.CDR_WATER)
{
float fFraction = 0f;
A3DVECTOR3 vWatNormal = new A3DVECTOR3();
float fFraction = 100f;
Vector3 vWatNormal = Vector3.zero;
bool bStart = false;
//@todo : TBD: use center or foot? By Kuiwu[10/10/2005]
//if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart)
// && fFraction < pEnvTrc.fFraction)
//{
// pEnvTrc.fFraction = fFraction;
// pEnvTrc.vHitNormal = vWatNormal;
// pEnvTrc.bStartSolid = bStart;
// pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER;
// //# ifdef CDR_DEBUG
// // A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction);
// // sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z);
// // OUTPUT_DEBUG_INFO(msg);
// //#endif
if (pEnvTrc.bWaterSolid && (vDelta.y > LOCAL_EPSILON))
{
fFraction = 0;
}
else if (!pEnvTrc.bWaterSolid && (vDelta.y < -LOCAL_EPSILON))
{
fFraction = 0;
}
else if (vDelta.y < LOCAL_EPSILON && vDelta.y > -LOCAL_EPSILON)
{ //parallel the water plane
fFraction = 0;
}
else
{
float h0 = 0f;
int countHits0 = Physics.RaycastNonAlloc(vWatStart, Vector3.down, fHitsWater, 1000f, 1 << 8);
if (countHits0 > 0)
{
h0 = fHitsWater[0].point.y;
}
float h1 = 0f;
countHits0 = Physics.RaycastNonAlloc((vWatStart + vDelta), Vector3.down, fHitsWater, 1000f, 1 << 8);
if(countHits0 > 0)
{
h1 = fHitsWater[0].point.y;
}
float hWater = Mathf.Max(h0, h1);
vWatNormal = Vector3.up;
float t = (hWater - vWatStart.y) / pEnvTrc.vDelta.y;
if (t >= 0.0f && t <= 1.0f)
{
fFraction = Mathf.Max(0.0f, t - 1E-2f);
if (pEnvTrc.bWaterSolid && h0 > vStart.y)
{
fFraction = 0.0f;
bStart = true;
}
//}
if (!pEnvTrc.bWaterSolid && h0 < vStart.y)
{
fFraction = 0.0f;
bStart = true;
}
if(fFraction < pEnvTrc.fFraction)
{
pEnvTrc.fFraction = fFraction;
pEnvTrc.vHitNormal = EC_Utility.ToA3DVECTOR3(vWatNormal);
pEnvTrc.bStartSolid = bStart;
pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER;
}
}
}
}
return (pEnvTrc.fFraction < 1.0f + 1E-4f);
@@ -751,7 +790,149 @@ namespace BrewMonster
static void WaterMove(ref ON_AIR_CDR_INFO awmInfo)
{
float fTime = awmInfo.t;
//@todo : is it necessary to clamp the speed? By Kuiwu[20/9/2005]
float fSpeed = awmInfo.fSpeed;
if (fSpeed * fTime < DIST_EPSILON)
{
//@todo : set the output param. By Kuiwu[20/9/2005]
return;
}
A3DVECTOR3 vStart = awmInfo.vCenter;
A3DVECTOR3 vExt = awmInfo.vExtent;
A3DVECTOR3 vVelDir = awmInfo.vVelDir;
float dtp = 0f;
A3DVECTOR3 vVelocity = vVelDir* fSpeed;
if ((dtp = DotProduct(vVelDir, awmInfo.vTPNormal)) < 0.0f)
{
vVelocity = (vVelDir - awmInfo.vTPNormal * dtp - awmInfo.vTPNormal * dtp * 0.01f) * fSpeed;
}
A3DVECTOR3 vDelta = (vVelocity* fTime), vNormal, vFinalPos = vStart;
int nTry = 0;
bool bClear = true;
env_trace_t trcInfo = new env_trace_t();
trcInfo.bWaterSolid = false;
trcInfo.dwCheckFlag = CDR_EVN.CDR_TERRAIN | CDR_EVN.CDR_BRUSH | CDR_EVN.CDR_WATER;
trcInfo.vExt = vExt;
while (nTry < 1)
{
if (vDelta.SquaredMagnitude() < DIST_EPSILON)
{
break;
}
trcInfo.vStart = vStart;
trcInfo.vDelta = vDelta;
trcInfo.vTerStart = vStart;
trcInfo.vTerStart.y -= vExt.y;
trcInfo.vWatStart = vStart;
trcInfo.vWatStart.y += awmInfo.fUnderWaterDistThresh; //shoulder
bClear = !CollideWithEnv(ref trcInfo);
++nTry;
if (bClear || (trcInfo.bStartSolid && ((trcInfo.dwClsFlag & CDR_EVN.CDR_WATER) != CDR_EVN.CDR_WATER)))
{
vFinalPos = vStart + vDelta;
break;
}
vStart += vDelta * trcInfo.fFraction;
fTime -= fTime * trcInfo.fFraction;
fSpeed = Normalize(vVelocity,ref vVelDir);
fSpeed *= (1 - nTry * 0.1f);
if ((trcInfo.dwClsFlag & CDR_EVN.CDR_WATER) == CDR_EVN.CDR_WATER)
{
if (trcInfo.bStartSolid)
{//rescue from solid
//@note : it may cause some problems. By Kuiwu[11/10/2005]
float fHWater = 0f;
int countHits0 = Physics.RaycastNonAlloc(EC_Utility.ToVector3(vStart), Vector3.down, fHitsWater, 1000f, 1 << 8);
if(countHits0 > 0)
{
fHWater = fHitsWater[0].point.y;
}
vStart.y = fHWater;
}
vVelDir.y = 0.0f;
vVelocity = vVelDir * fSpeed;
}
else
{
vNormal = trcInfo.vHitNormal;
dtp = DotProduct(vNormal, vVelDir);
vVelocity = (vVelDir - vNormal * dtp - vNormal * dtp * VEL_REFLECT) * fSpeed;
}
vDelta = vVelocity * fTime;
vFinalPos = vStart;
}
//@note : prevent moving to the invalid area. By Kuiwu[20/9/2005]
if (!IsPosInAvailableMap(vFinalPos))
{
//@todo : set some flag to notify the caller? By Kuiwu[20/9/2005]
return;
}
//see if meet height thresh
Vector3 v3Start = EC_Utility.ToVector3(vFinalPos);
Vector3 v3Ext = EC_Utility.ToVector3(vExt);
float fDeltaY = awmInfo.fHeightThresh + 0.1f;
if (!DoGroundProbe(v3Start, v3Ext, fDeltaY, UsedMask_Ground(), out Vector3 vEnd, out Vector3 groundNormal, out bool bSupport))
{
return;
}
A3DVECTOR3 vTpNormal = new A3DVECTOR3(0.0f);
A3DVECTOR3 vOverTp = vFinalPos;
bool bAdjust = false;
awmInfo.bMeetHeightThresh = true;
if (bSupport)
{
bAdjust = true;
vOverTp = EC_Utility.ToA3DVECTOR3(vEnd);
vTpNormal = EC_Utility.ToA3DVECTOR3(groundNormal);
}
if (bAdjust && (vOverTp.y + awmInfo.fHeightThresh > vFinalPos.y))
{
float fHWater = 0f;
int countHits = Physics.RaycastNonAlloc(EC_Utility.ToVector3(vFinalPos), Vector3.down, fHitsWater, 1000f, 1 << 8);
if (countHits > 0)
{
fHWater = fHitsWater[0].point.y;
}
float fAllow = fHWater - awmInfo.fUnderWaterDistThresh - vFinalPos.y;
if (fAllow > 1E-4f)
{
vDelta.Clear();
vDelta.y = vOverTp.y + awmInfo.fHeightThresh - vFinalPos.y;
fAllow = EC_Utility.a_Min(fAllow, 0.15f);
AAssist.a_ClampRoof(ref vDelta.y, fAllow);
Vector3 dir = EC_Utility.ToVector3(vDelta);
countHits = Physics.BoxCastNonAlloc(v3Start, v3Ext, dir.normalized, hits, Quaternion.identity, dir.magnitude, 1 << 7);
if (countHits > 0)
{
vFinalPos += EC_Utility.ToA3DVECTOR3(hits[0].point);
}
else
{
vFinalPos += vDelta;
}
awmInfo.bMeetHeightThresh = (vFinalPos.y - vOverTp.y > awmInfo.fHeightThresh);
}
}
awmInfo.vCenter = vFinalPos;
awmInfo.vTPNormal = vTpNormal;
}
//////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -13,7 +13,7 @@ TagManager:
- UI
- Terrain
- Brush
-
- Water
-
-
-