diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkFall.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkFall.cs index 89db36ccf7..0af9cbc10d 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkFall.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HPWorkFall.cs @@ -17,6 +17,9 @@ namespace BrewMonster.Scripts protected bool m_fForceDown; Vector3 g_vOrigin = Vector3.zero; + + const float EC_NACCE_WATER = -5.0f; + public static class FlyFallStage { public const int enumStageNone = 0, @@ -130,13 +133,13 @@ namespace BrewMonster.Scripts else FreeFall_Air(fDeltaTime); } - //else // m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER - //{ - // if (m_iFallType == Fall_type.TYPE_FLYFALL) - // Fall_Water(fDeltaTime); - // else - // FreeFall_Water(fDeltaTime); - //} + else // m_pHost.m_iMoveEnv == CECPlayer::MOVEENV_WATER + { + if (m_iFallType == Fall_type.TYPE_FLYFALL) + Fall_Water(fDeltaTime); + else + FreeFall_Water(fDeltaTime); + } } return true; @@ -303,6 +306,11 @@ namespace BrewMonster.Scripts return true; } + private float A3d_Magnitude(A3DVECTOR3 v) + { + return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); + } + // Finish public void Finish() { @@ -313,5 +321,177 @@ namespace BrewMonster.Scripts //if (m_iFallType == Fall_type.TYPE_FLYFALL) // m_pHost.ShowWing(false); } + + // Free fall in water + bool Fall_Water(float fDeltaTime) + { + A3DVECTOR3 vCurPos = m_pHost.GetPos(); + A3DVECTOR3 vCurVel = m_pHost.m_vVelocity; + float fGndHei = m_pHost.m_GndInfo.fGndHei; + + if (!m_bEnterWater) + { + m_bEnterWater = true; + vCurVel = m_pHost.m_CDRInfo.vAbsVelocity; + float fWaterHei = m_pHost.m_GndInfo.fWaterHei; + if (fWaterHei - fGndHei > 1.5f) + m_nCurStage = FlyFallStage.enumStageDeepWater; + else + m_nCurStage = FlyFallStage.enumStageShallowWater; + } + + float fSpeed1 = vCurVel.Normalize(); + float na = -fSpeed1 * 0.7f + EC_NACCE_WATER * 4.0f; + float fSpeed2 = fSpeed1 + na * fDeltaTime; + if (fSpeed2 * fSpeed1 < 0.0f) + fSpeed2 = 0.0f; + + if (m_fForceDown) + { + // Note: When speed=0 we should check whether a special case: EstimateMoveEnv find + // we are in water but we stop at a underwater position which is very close + // to water surface. + // if (vCurPos.y < m_pHost.m_GndInfo.fWaterHei && + // m_pHost.m_GndInfo.fWaterHei - m_pHost.m_GndInfo.fGndHei > m_pHost.m_MoveConst.fShoreDepth && + if (m_pHost.CheckWaterMoveEnv(vCurPos, m_pHost.m_GndInfo.fWaterHei, m_pHost.m_GndInfo.fGndHei) && + m_pHost.m_GndInfo.fWaterHei - vCurPos.y < m_pHost.m_MoveConst.fShoreDepth) + { + vCurPos = m_pHost.m_MoveCtrl.GroundMove(m_vDirH, m_fSpeedH, fDeltaTime, -5.0f); + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3) + { + // Fall on ground + Finish(); + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.m_vVelocity.Magnitude(), (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + m_pHost.m_vVelocity.Clear(); + } + + return true; + } + } + + if (Math.Abs(fSpeed2 - 0f) > float.Epsilon) + { + A3DVECTOR3 vOldPos = vCurPos; + vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(vCurVel, fSpeed2, fDeltaTime, false, false); + vCurVel *= fSpeed2; + + if (m_nCurStage == FlyFallStage.enumStageShallowWater) + { + if (vCurPos.y - fGndHei < 1.0f) + { + //if (m_pHost.UsingWing()) + if (m_pHost.GetWingType() == enumWingType.WINGTYPE_WING) + m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_LANDON, false); + else + m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_LANDON_SWORD, false); + + m_nCurStage = FlyFallStage.enumStageLandOn; + } + } + else if (m_nCurStage == FlyFallStage.enumStageDeepWater) + { + if (vCurVel.y > -9.0f) + m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_HANGINWATER, false); + } + + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3 || + vCurPos.y - m_pHost.m_MoveConst.fMinWaterHei <= fGndHei) + { + // Fall on ground + Finish(); + + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.m_vVelocity.Magnitude(), (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + m_pHost.m_vVelocity.Clear(); + } + else + { + m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, EC_Utility.ToA3DVECTOR3(g_vOrigin), vCurVel, (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + m_pHost.m_vVelocity = vCurVel; + } + + // If moving too small + if (A3d_Magnitude(vCurPos - vOldPos) < 0.001f) + m_fForceDown = true; + } + else + { + Finish(); + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed1, (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + m_pHost.m_vVelocity.Clear(); + } + + return true; + } + + // Free fall in water + bool FreeFall_Water(float fDeltaTime) + { + A3DVECTOR3 vCurPos = m_pHost.GetPos(); + A3DVECTOR3 vCurVel = m_pHost.m_vVelocity; + float fGndHei = m_pHost.m_GndInfo.fGndHei; + + if (!m_bEnterWater) + { + m_bEnterWater = true; + vCurVel = m_pHost.m_CDRInfo.vAbsVelocity; + float fWaterHei = m_pHost.m_GndInfo.fWaterHei; + if (fWaterHei - fGndHei > 1.5f) + m_nCurStage = FlyFallStage.enumStageDeepWater; + else + m_nCurStage = FlyFallStage.enumStageShallowWater; + } + + float fSpeed1 = vCurVel.Normalize(); + float na = EC_NACCE_WATER * 4.0f; + float fSpeed2 = fSpeed1 + na * fDeltaTime; + if (fSpeed2 * fSpeed1 < 0.0f) + fSpeed2 = 0.0f; + + if (Math.Abs(fSpeed2 - 0f) > float.Epsilon) + { + vCurPos = m_pHost.m_MoveCtrl.AirWaterMove(vCurVel, fSpeed2, fDeltaTime, false, false); + vCurVel *= fSpeed2; + + if (m_pHost.m_MoveCtrl.MoveBlocked() >= 3 || + vCurPos.y - m_pHost.m_MoveConst.fMinWaterHei <= fGndHei) + { + // Fall on ground + Finish(); + + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), m_pHost.m_vVelocity.Magnitude(), (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + m_pHost.m_vVelocity.Clear(); + } + else + { + m_pHost.m_MoveCtrl.SendMoveCmd(vCurPos, 2, EC_Utility.ToA3DVECTOR3(g_vOrigin), vCurVel, (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + m_pHost.m_vVelocity = vCurVel; + + if (m_nCurStage == FlyFallStage.enumStageDeepWater) + m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_HANGINWATER, false); + else + m_pHost.PlayAction((int)PLAYER_ACTION_TYPE.ACT_JUMP_LOOP, false); + } + } + else + { + Finish(); + m_pHost.m_MoveCtrl.SendStopMoveCmd(EC_Utility.ToVector3(vCurPos), fSpeed1, (int)GPMoveMode.GP_MOVE_WATER | m_iFallMode); + + m_pHost.SetPos(EC_Utility.ToVector3(vCurPos)); + m_pHost.m_vVelocity.Clear(); + } + + return true; + } } } diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_HostInputFilter.cs b/Assets/PerfectWorld/Scripts/Managers/EC_HostInputFilter.cs index bf231e0f26..aa4fb76edf 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_HostInputFilter.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_HostInputFilter.cs @@ -115,7 +115,6 @@ namespace BrewMonster // Check for NPC with pate text (hover text) first // Note: This would require GetMouseOnPateTextNPC implementation // For now, we'll proceed with raycast - if (Physics.RaycastNonAlloc(ray, hits) > 0) { // Check if hit terrain, building, or forest (no CECObject component) diff --git a/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs b/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs index cc420dddd4..e4785b8fa3 100644 --- a/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs +++ b/Assets/PerfectWorld/Scripts/Move/EC_CDR.cs @@ -176,7 +176,7 @@ namespace BrewMonster h0 = fHitsWater[0].point.y; } float h1 = 0f; - countHits0 = Physics.RaycastNonAlloc((vWatStart + vDelta), Vector3.down, fHitsWater, 1000f, 1 << 8); + countHits0 = Physics.RaycastNonAlloc((vWatStart + vDelta) + Vector3.up * 500f, Vector3.down, fHitsWater, 1000f, 1 << 8); if(countHits0 > 0) { h1 = fHitsWater[0].point.y; @@ -184,9 +184,11 @@ namespace BrewMonster float hWater = Mathf.Max(h0, h1); vWatNormal = Vector3.up; float t = (hWater - vWatStart.y) / pEnvTrc.vDelta.y; + Debug.LogError("t = " + t); if (t >= 0.0f && t <= 1.0f) { fFraction = Mathf.Max(0.0f, t - 1E-2f); + Debug.LogError("fFraction = " + fFraction); if (pEnvTrc.bWaterSolid && h0 > vStart.y) { fFraction = 0.0f; @@ -818,7 +820,7 @@ namespace BrewMonster trcInfo.dwCheckFlag = CDR_EVN.CDR_TERRAIN | CDR_EVN.CDR_BRUSH | CDR_EVN.CDR_WATER; trcInfo.vExt = vExt; - while (nTry < 1) + while (nTry < 4) { if (vDelta.SquaredMagnitude() < DIST_EPSILON) { @@ -838,8 +840,11 @@ namespace BrewMonster if (bClear || (trcInfo.bStartSolid && ((trcInfo.dwClsFlag & CDR_EVN.CDR_WATER) != CDR_EVN.CDR_WATER))) { vFinalPos = vStart + vDelta; + Debug.DrawLine(EC_Utility.ToVector3(vStart), EC_Utility.ToVector3(vFinalPos), Color.red, 1f); + Debug.LogError("vFinalPos = " + vFinalPos + " vStart = " + vStart); break; } + Debug.LogError("vStart = " + vStart + " vStart1 = " + (vStart + vDelta * trcInfo.fFraction)); vStart += vDelta * trcInfo.fFraction; fTime -= fTime * trcInfo.fFraction; fSpeed = Normalize(vVelocity,ref vVelDir); @@ -850,7 +855,7 @@ namespace BrewMonster {//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.up * 900f, Vector3.down, fHitsWater, 1000f, 1 << 8); + int countHits0 = Physics.RaycastNonAlloc(EC_Utility.ToVector3(vStart) + Vector3.up * 500f, Vector3.down, fHitsWater, 1000f, 1 << 8); if(countHits0 > 0) { fHWater = fHitsWater[0].point.y; diff --git a/Assets/Scenes/a61.unity b/Assets/Scenes/a61.unity index 3a900e96c5..3985f6a8dd 100644 --- a/Assets/Scenes/a61.unity +++ b/Assets/Scenes/a61.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dfacfe7598c13b74bf00df392384c4c626d00ac99325d3db2353f0e31cc8a414 -size 200761977 +oid sha256:358c0733c65ab471cec0047f7881ab2349868ef5267c77e2848329015674f176 +size 200775096 diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index 373a2d4878..e0709bc046 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -2433,13 +2433,13 @@ namespace BrewMonster }*/ m_dwMoveRelDir = 0; if (!CanDo(ActionCanDo.CANDO_MOVETO)) return; - if(joystick.Vertical > 0) + if (joystick.Vertical > 0) { - if(joystick.Horizontal > 0) + if (joystick.Horizontal > 0) { m_dwMoveRelDir |= (uint)(MOVE_DIR.MD_FORWARD | MOVE_DIR.MD_RIGHT); } - else if(joystick.Horizontal < 0) + else if (joystick.Horizontal < 0) { m_dwMoveRelDir |= (uint)(MOVE_DIR.MD_FORWARD | MOVE_DIR.MD_LEFT); } @@ -4394,10 +4394,16 @@ namespace BrewMonster } else if (m_iMoveEnv == Move_environment.MOVEENV_WATER) { - vPushDir.x = joystick.Horizontal; - vPushDir.y = (transform.position - mainCam.transform.position).normalized.y; - vPushDir.z = joystick.Vertical; - vPushDir.Normalize(); + float angle = Vector2.Angle(new Vector2(joystick.Horizontal, joystick.Vertical), Vector2.up); + angle *= joystick.Horizontal < 0 ? 1 : -1; + Vector2 v2Cam = new Vector2(mainCam.transform.forward.x, mainCam.transform.forward.z); + v2Cam = Quaternion.Euler(0, 0, angle) * v2Cam; + v2Cam.Normalize(); + vPushDir.x = v2Cam.x; + vPushDir.y = ((transform.position + Vector3.up * m_CDRInfo.vExtent.y) - mainCam.transform.position).normalized.y; + vPushDir.z = v2Cam.y; + //Debug.LogError("vPushDir = " + vPushDir); + Debug.DrawRay((transform.position + Vector3.up * m_CDRInfo.vExtent.y), vPushDir.normalized, Color.green, 10f); } else { @@ -5243,7 +5249,7 @@ namespace BrewMonster // Is gathering resources public bool IsGathering() { - if(m_pWorkMan == null) return false; + if (m_pWorkMan == null) return false; CECHPWork pWork = m_pWorkMan.GetRunningWork(Host_work_ID.WORK_PICKUP); if (pWork != null) return ((EC_HPWorkPick)pWork).IsGather(); @@ -5281,7 +5287,7 @@ namespace BrewMonster VertRayTrace(EC_Utility.ToVector3(vTestPos), ref vGndPos, ref m_GndInfo.vGndNormal, 1000f); m_GndInfo.fGndHei = vGndPos.y; - if(Physics.RaycastNonAlloc(EC_Utility.ToVector3(vTestPos), Vector3.down, hits, 1000f, 1<<8) > 0) + if (Physics.RaycastNonAlloc(EC_Utility.ToVector3(vTestPos) + Vector3.up * 500f, Vector3.down, hits, 1000f, 1 << 8) > 0) { m_GndInfo.fWaterHei = hits[0].point.y; } @@ -5383,13 +5389,13 @@ namespace BrewMonster LayerMask layerMaskTerrain = 1 << 6; LayerMask layerMaskBush = 1 << 7; - if (Physics.RaycastNonAlloc(vPos, (vPos + Vector3.down), hits, layerMaskTerrain) > 0) + if (Physics.RaycastNonAlloc(vPos, (Vector3.down), hits, layerMaskTerrain) > 0) { vTerrainPos = hits[0].point; vTerrainNormal = hits[0].normal; } - if (Physics.RaycastNonAlloc(vPos, (vPos + Vector3.down), hits, DeltaY, layerMaskTerrain) > 0) + if (Physics.RaycastNonAlloc(vPos, (Vector3.down), hits, DeltaY, layerMaskBush) > 0) { if (vBuildingPos.y > vTerrainPos.y) { @@ -5417,19 +5423,85 @@ namespace BrewMonster vHitPos.y -= DeltaY; LayerMask layerMask = 1 << 6 | 1 << 7; - if (Physics.BoxCastNonAlloc(vCenter, vExt, (vCenter + Vector3.down).normalized, - hits, transform.rotation, DeltaY, layerMask) == 0) + hits = new RaycastHit[5]; + int count = Physics.BoxCastNonAlloc(vCenter, vExt, (Vector3.down).normalized, + hits, transform.rotation, DeltaY, layerMask); + if (count == 0) { vHitPos = vCenter; vHitNormal = EC_Utility.ToA3DVECTOR3(Vector3.up); } else - { - vHitPos = hits[0].point; - vHitNormal = EC_Utility.ToA3DVECTOR3(hits[0].normal); + { + if (Math.Abs(hits[0].distance - 0f) <= float.Epsilon) + { + count = Physics.BoxCastNonAlloc(vCenter, new Vector3(vExt.x, 0.05f, vExt.z), (Vector3.down).normalized, + hits, transform.rotation, DeltaY, layerMask); + if(count == 0) + { + vHitPos = vCenter; + vHitNormal = EC_Utility.ToA3DVECTOR3(Vector3.up); + } + else + { + vHitPos = hits[0].point; + vHitPos.y += vExt.y; + vHitNormal = EC_Utility.ToA3DVECTOR3(hits[0].normal); + } + } } } + void DebugBoxCast(Vector3 center, Vector3 halfExtents, Vector3 direction, + Quaternion orientation, float distance, Color color) + { + Vector3 end = center + direction.normalized * distance; + + // Vẽ box ở vị trí bắt đầu + DebugDrawBox(center, halfExtents, orientation, color); + + // Vẽ box ở vị trí kết thúc + DebugDrawBox(end, halfExtents, orientation, color); + + // Vẽ đường nối giữa 2 box + Debug.DrawLine(center, end, color); + } + + // Vẽ 1 box từ center + halfExtents + rotation + void DebugDrawBox(Vector3 center, Vector3 halfExtents, Quaternion orientation, Color color) + { + var matrix = Matrix4x4.TRS(center, orientation, Vector3.one); + Vector3[] points = { + matrix.MultiplyPoint3x4(new Vector3(-halfExtents.x, -halfExtents.y, -halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3( halfExtents.x, -halfExtents.y, -halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3( halfExtents.x, -halfExtents.y, halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3(-halfExtents.x, -halfExtents.y, halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3(-halfExtents.x, halfExtents.y, -halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3( halfExtents.x, halfExtents.y, -halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3( halfExtents.x, halfExtents.y, halfExtents.z)), + matrix.MultiplyPoint3x4(new Vector3(-halfExtents.x, halfExtents.y, halfExtents.z)) + }; + + // đáy + Debug.DrawLine(points[0], points[1], color); + Debug.DrawLine(points[1], points[2], color); + Debug.DrawLine(points[2], points[3], color); + Debug.DrawLine(points[3], points[0], color); + + // đỉnh + Debug.DrawLine(points[4], points[5], color); + Debug.DrawLine(points[5], points[6], color); + Debug.DrawLine(points[6], points[7], color); + Debug.DrawLine(points[7], points[4], color); + + // cạnh + Debug.DrawLine(points[0], points[4], color); + Debug.DrawLine(points[1], points[5], color); + Debug.DrawLine(points[2], points[6], color); + Debug.DrawLine(points[3], points[7], color); + } + + void OnMsgHstExtProp(ECMSG Msg) { cmd_own_ext_prop pCmd = GPDataTypeHelper.FromBytes((byte[])Msg.dwParam1);