Ejemplo n.º 1
0
        public TransitionState ValidateWalkable(Sphere checkPos, Plane contactPlane, bool isWater, float waterDepth, Transition transition, uint landCellID)
        {
            var path      = transition.SpherePath;
            var collision = transition.CollisionInfo;

            if (State.HasFlag(ObjectInfoState.IsViewer))
            {
                var dist = Vector3.Dot(checkPos.Center, contactPlane.Normal) - checkPos.Radius;
                if (dist > -PhysicsGlobals.EPSILON && path.BeginPos != null && (path.BeginPos.ObjCellID & 0xFFFF) >= 0x100)
                {
                    return(TransitionState.OK);
                }

                var offset = checkPos.Center - path.GlobalCurrCenter[0].Center;
                var angle  = dist / Vector3.Dot(offset, contactPlane.Normal);
                if ((angle <= 0.0f || angle > 1.0f) && path.BeginPos != null && (path.BeginPos.ObjCellID & 0xFFFF) >= 0x100)
                {
                    return(TransitionState.OK);
                }

                path.AddOffsetToCheckPos(offset * -angle);
                collision.SetCollisionNormal(contactPlane.Normal);
                collision.CollidedWithEnvironment = true;
                return(TransitionState.Adjusted);
            }
            else
            {
                var dist = Vector3.Dot(checkPos.Center - new Vector3(0, 0, checkPos.Radius), contactPlane.Normal) + waterDepth;
                if (dist >= -PhysicsGlobals.EPSILON)
                {
                    if (dist > PhysicsGlobals.EPSILON)
                    {
                        return(TransitionState.OK);
                    }

                    if (path.StepDown || !State.HasFlag(ObjectInfoState.OnWalkable) || Object.is_valid_walkable(contactPlane.Normal))
                    {
                        collision.SetContactPlane(contactPlane, isWater);
                        collision.ContactPlaneCellID = landCellID;
                    }
                    if (!State.HasFlag(ObjectInfoState.Contact) && !path.StepDown)
                    {
                        collision.SetCollisionNormal(contactPlane.Normal);
                        collision.CollidedWithEnvironment = true;
                    }
                    return(TransitionState.OK);
                }
                else
                {
                    if (path.CheckWalkable)
                    {
                        return(TransitionState.Collided);
                    }
                    var zDist = dist / contactPlane.Normal.Z;

                    if (path.StepDown || !State.HasFlag(ObjectInfoState.OnWalkable) || Object.is_valid_walkable(contactPlane.Normal))
                    {
                        collision.SetContactPlane(contactPlane, isWater);
                        collision.ContactPlaneCellID = landCellID;
                        if (path.StepDown)
                        {
                            var interp = (1.0f - -1.0f / (path.StepDownAmt * path.WalkInterp) * zDist) * path.WalkInterp;
                            if (interp >= path.WalkInterp || interp < -0.1f)
                            {
                                return(TransitionState.Collided);
                            }

                            path.WalkInterp = interp;
                        }

                        var offset = new Vector3(0, 0, -zDist);
                        path.AddOffsetToCheckPos(offset);
                    }

                    if (!State.HasFlag(ObjectInfoState.Contact) && !path.StepDown)
                    {
                        collision.SetCollisionNormal(contactPlane.Normal);
                        collision.CollidedWithEnvironment = true;
                    }
                    return(TransitionState.Adjusted);
                }
            }
        }