// Move the desired displacement, limited by hitting an
        // obstacle.  Then, if we're not already at the terrain level,
        // "fall" until we are either at the terrain level, or hit an
        // obstacle
        public static Vector3 MoveMobNode(MobNode mobNode, Vector3 requestedDisplacement, Client client)
        {
            //             Logger.Log(0, "MoveMobNode oid {0} requestedDisplacement {1}", mobNode.Oid, requestedDisplacement);
            //             log.DebugFormat("MoveMobNode: mobNode oid {0}, name {1}, followTerrain {2}, position {3}, disp {4}",
            //                             mobNode.Oid, mobNode.Name, mobNode.FollowTerrain, mobNode.Position, requestedDisplacement);
            Vector3 start = mobNode.Position;
            MovingObject mo = mobNode.Collider;
            bool collided = false;
            // Zero the y coordinate of displacement, because it seems
            // that it can be arbitrarily large
            Vector3 desiredDisplacement = requestedDisplacement;
            if (mobNode.FollowTerrain)
                desiredDisplacement.y = 0;
            if (desiredDisplacement.LengthSquared <= float.Epsilon)
                return start;
            if (MO.DoLog)
                MO.Log("MoveMobNode called with mobNode {0} at {1}, disp of {2}",
                       mobNode.Oid, start, requestedDisplacement);
            if (collisionManager == null) {
                log.Info("MoveMobNode: returning because collisionManager isn't initialized");
                return start + desiredDisplacement;
            }
            if (mo == null || mo.parts.Count == 0) {
                if (MO.DoLog)
                    MO.Log("MoveMobNode returning because no collision volume for node");
                return start + requestedDisplacement;
            }
            if (mobNode is Player && NowColliding(mo, "Testing player collision on entry")) {
                if (client.MillisecondsStuckBeforeGotoStuck != 0) {
                    if (!playerStuck) {
                        stuckGotoTime = DateTime.Now.AddMilliseconds(client.MillisecondsStuckBeforeGotoStuck);
                        playerStuck = true;
                    }
                    else if (DateTime.Now >= stuckGotoTime) {
                        // We issue the goto command to move us out of the
                        // collision volume
                        client.Write("Executing /stuck command because player has been in a collision volume for " + client.MillisecondsStuckBeforeGotoStuck + " milliseconds");
                        client.NetworkHelper.SendTargettedCommand(client.Player.Oid, "/stuck");
                        playerStuck = false;
                        return start;
                    }
                }
            }
            else
                playerStuck = false;
            // If we haven't completed setup to this extent, just give up
            CollisionParms parms = new CollisionParms();
            Vector3 pos = FindMobNodeDisplacement(mobNode, parms, desiredDisplacement, out collided);
            //             log.DebugFormat("MoveMobNode: mobNode oid {0}, name {1}, mob node position {2}, displacement {3}",
            //                 mobNode.Oid, mobNode.Name, pos, requestedDisplacement);
            float h = worldManager.GetHeightAt(pos);
            // If we're already below ground level, just set our
            // level to ground level.  This will have to be modified
            // if we deal with caves
            if (pos.y - h < 0) {
            //                 log.DebugFormat("MoveMobNode: mobNode oid {0}, name {1} below terrain level", mobNode.Oid, mobNode.Name);
                mo.AddDisplacement(new Vector3(0f, h - pos.y, 0f));
                pos.y = h;
                if (MO.DoLog && (pos.y - h) < -.001 * Client.OneMeter)
                    MO.Log(string.Format(" MobNode at {0} is below ground height {1}!",
                                         pos, h));
            } // else {
                if (mobNode.FollowTerrain) {
            // 					NowColliding(mo, " Before falling loop");
                    // Fall toward the terrain or an obstacle, whichever comes
                    // first
                    float step = mo.StepSize(new Vector3(0, h, 0));
                    while (true) {
                        if (Math.Abs(pos.y - h) < CollisionAPI.VerticalTerrainThreshold * Client.OneMeter) {
                            mo.AddDisplacement(new Vector3(0f, h - pos.y, 0f));
                            pos.y = h;
                            break;
                        } else {
                            float dy = -Math.Min(pos.y - h, step);
                            Vector3 displacement = new Vector3(0, dy, 0);
                            Vector3 cd = displacement;
                            if (MO.DoLog) {
                                MO.Log(" Testing for collision falling {0}", dy);
                                TraceMOBottom(mo, " Before falling");
                            }
                            if (collisionManager.TestCollision(mo, ref displacement, parms)) {
                                if (MO.DoLog) {
                                    TraceMOBottom(mo, " After TestCollision after falling");
                                    NowColliding(mo, " After TestCollision after falling");
                                    MO.Log(" Collision when object {0} falls from {1} to {2}",
                                           parms.part.handle, pos, pos + cd);
                                    TraceObstacle(parms.obstacle);
                                    MO.Log(" Adding dy {0} - displacement.y {1} to pos {2}",
                                           dy, displacement.y, pos);
                                }
                                pos.y += dy - displacement.y;
                                break;
                            }
                            if (MO.DoLog)
                                MO.Log(" Didn't collide falling; dy {0}, pos {1}",
                                       dy, pos);
                            pos.y += dy;
                        }
                    }
                } else {
                    if (MO.DoLog)
                        MO.Log(" Not falling because mobNode {0} doesn't have FollowTerrain",
                            mobNode.Oid);
                }
            // 			}

            if (MO.DoLog) {
                NowColliding(mo, " Leaving MoveMobNode");
                MO.Log("MoveMobNode returning pos {0}", pos);
                MO.Log("");
            }
            if (collided)
                log.DebugFormat("MoveMobNode collided: mobNode oid {0}, name {1}, orig pos {2}, displacement {3}, new pos {4}",
                    mobNode.Oid, mobNode.Name, start, requestedDisplacement, pos);
            else
                log.DebugFormat("MoveMobNode didn't collide: mobNode oid {0}, name {1}, orig pos {2}, displacement {3}, new pos {4}",
                    mobNode.Oid, mobNode.Name, start, requestedDisplacement, pos);
            return pos;
        }
Пример #2
0
        // We only call this if both the collisionManager and the collider exist
        private static Vector3 FindMobNodeDisplacement(MobNode mobNode, CollisionParms parms, Vector3 desiredDisplacement, out bool collided)
        {
            Vector3      start        = mobNode.Position;
            Vector3      pos          = start + desiredDisplacement;
            Vector3      displacement = desiredDisplacement;
            MovingObject mo           = mobNode.Collider;
            Vector3      moStart      = mo.parts[0].shape.center;

            if (MO.DoLog)
            {
                MO.Log(" moStart = {0}, start = {1}", moStart, start);
                MO.Log(" pos = {0}, displacement = {1}", pos, displacement);
                TraceMOBottom(mo, " On entry to FindMobNodeDisplacement");
            }
            collided = false;
            if (collisionManager.TestCollision(mo, ref displacement, parms))
            {
                collided = true;
                if (MO.DoLog)
                {
                    MO.Log(" Collision when moving object {0} from {1} to {2}",
                           parms.part.handle, start, pos);
                    NowColliding(mo, " After first TestCollision in FindMobNodeDisplacement");
                    TraceObstacle(parms.obstacle);
                    MO.Log(" Before collision moved {0}", desiredDisplacement - displacement);
                }
                // Decide if the normals are such that we want
                // to slide along the obstacle
                Vector3 remainingDisplacement = displacement;
                Vector3 norm1 = parms.normObstacle.ToNormalized();
                if (DecideToSlide(mo, start + displacement, parms, ref remainingDisplacement))
                {
                    if (MO.DoLog)
                    {
                        MO.Log(" After DecideToSlide, remainingDisplacement {0}", remainingDisplacement);
                    }
                    // We have to test the displacement
                    if (collisionManager.TestCollision(mo, ref remainingDisplacement, parms))
                    {
                        if (MO.DoLog)
                        {
                            NowColliding(mo, " After first try TestCollision");
                            MO.Log(" Slid into obstacle on the first try; remainingDisplacement = {0}",
                                   remainingDisplacement);
                            TraceObstacle(parms.obstacle);
                        }
                        if (remainingDisplacement.LengthSquared > 0)
                        {
                            Vector3 norm2 = parms.normObstacle.ToNormalized();
                            // Find the cross product of the of norm1 and
                            // norm2, and dot with displacement.  If
                            // negative, reverse.
                            Vector3 newDir = norm1.Cross(norm2);
                            float   len    = newDir.Dot(remainingDisplacement);
                            if (len < 0)
                            {
                                newDir = -newDir;
                                len    = -len;
                            }
                            Vector3 slidingDisplacement         = len * newDir;
                            Vector3 originalSlidingDisplacement = slidingDisplacement;
                            if (MO.DoLog)
                            {
                                MO.Log(" norm1 = {0}, norm2 = {1}, len = {2}",
                                       norm1, norm2, len);
                                MO.Log(" Cross product slidingDisplacement is {0}", slidingDisplacement);
                            }
                            if (collisionManager.TestCollision(mo, ref slidingDisplacement, parms))
                            {
                                if (MO.DoLog)
                                {
                                    NowColliding(mo, " After second try TestCollision");
                                    MO.Log(" Slid into obstacle on the second try; slidingDisplacement = {0}",
                                           slidingDisplacement);
                                }
                            }
                            else
                            if (MO.DoLog)
                            {
                                MO.Log(" Didn't slide into obstacle on the second try");
                            }
                            remainingDisplacement -= (originalSlidingDisplacement - slidingDisplacement);
                        }
                    }
                }
                else
                {
                    remainingDisplacement = displacement;
                }
                if (MO.DoLog)
                {
                    MO.Log(" Before checking hop, remainingDisplacement is {0}", remainingDisplacement);
                }
                if (remainingDisplacement.Length > 30f)
                {
                    // Try to hop over the obstacle
                    Vector3 c = remainingDisplacement;
                    mo.AddDisplacement(new Vector3(0f, CollisionAPI.HopOverThreshold * Client.OneMeter, 0f));
                    if (MO.DoLog)
                    {
                        TraceMOBottom(mo, " Before trying to hop");
                        MO.Log(" remainingDisplacement {0}", remainingDisplacement);
                    }
                    if (collisionManager.TestCollision(mo, ref remainingDisplacement, parms))
                    {
                        if (MO.DoLog)
                        {
                            MO.Log(" Even after hopping up {0} meters, can't get over obstacle; disp {1}",
                                   CollisionAPI.HopOverThreshold, remainingDisplacement);
                        }
                        c   = c - remainingDisplacement;
                        c.y = 0;
                        c  += new Vector3(0f, CollisionAPI.HopOverThreshold * Client.OneMeter, 0f);
                        if (MO.DoLog)
                        {
                            MO.Log(" After failed hop, subtracting {0}", c);
                        }
                        mo.AddDisplacement(-c);
                    }
                    else if (MO.DoLog)
                    {
                        MO.Log(" Hopping up {0} meters got us over obstacle; disp {1}",
                               CollisionAPI.HopOverThreshold, remainingDisplacement);
                        TraceMOBottom(mo, " After hopping");
                    }
                    NowColliding(mo, " After hopping");
                }
            }
            Vector3 moPos = mo.parts[0].shape.center;

            pos = start + moPos - moStart;
            if (MO.DoLog)
            {
                MO.Log(" mo location = {0}, moPos - moStart {1}", moPos, moPos - moStart);
                NowColliding(mo, " Leaving FindMobNodeDisplacement");
                MO.Log(" pos = {0}", pos);
            }
            return(pos);
        }
 // We only call this if both the collisionManager and the collider exist
 private static Vector3 FindMobNodeDisplacement(MobNode mobNode, CollisionParms parms, Vector3 desiredDisplacement, out bool collided)
 {
     Vector3 start = mobNode.Position;
     Vector3 pos = start + desiredDisplacement;
     Vector3 displacement = desiredDisplacement;
     MovingObject mo = mobNode.Collider;
     Vector3 moStart = mo.parts[0].shape.center;
     if (MO.DoLog) {
         MO.Log(" moStart = {0}, start = {1}", moStart, start);
         MO.Log(" pos = {0}, displacement = {1}", pos, displacement);
         TraceMOBottom(mo, " On entry to FindMobNodeDisplacement");
     }
     collided = false;
     if (collisionManager.TestCollision(mo, ref displacement, parms)) {
         collided = true;
         if (MO.DoLog) {
             MO.Log(" Collision when moving object {0} from {1} to {2}",
                    parms.part.handle, start, pos);
             NowColliding(mo, " After first TestCollision in FindMobNodeDisplacement");
             TraceObstacle(parms.obstacle);
             MO.Log(" Before collision moved {0}", desiredDisplacement - displacement);
         }
         // Decide if the normals are such that we want
         // to slide along the obstacle
         Vector3 remainingDisplacement = displacement;
         Vector3 norm1 = parms.normObstacle.ToNormalized();
         if (DecideToSlide(mo, start + displacement, parms, ref remainingDisplacement)) {
             if (MO.DoLog)
                 MO.Log(" After DecideToSlide, remainingDisplacement {0}", remainingDisplacement);
             // We have to test the displacement
             if (collisionManager.TestCollision(mo, ref remainingDisplacement, parms)) {
                 if (MO.DoLog) {
                     NowColliding(mo, " After first try TestCollision");
                     MO.Log(" Slid into obstacle on the first try; remainingDisplacement = {0}",
                            remainingDisplacement);
                     TraceObstacle(parms.obstacle);
                 }
                 if (remainingDisplacement.LengthSquared > 0) {
                     Vector3 norm2 = parms.normObstacle.ToNormalized();
                     // Find the cross product of the of norm1 and
                     // norm2, and dot with displacement.  If
                     // negative, reverse.
                     Vector3 newDir = norm1.Cross(norm2);
                     float len = newDir.Dot(remainingDisplacement);
                     if (len < 0) {
                         newDir = - newDir;
                         len = - len;
                     }
                     Vector3 slidingDisplacement = len * newDir;
                     Vector3 originalSlidingDisplacement = slidingDisplacement;
                     if (MO.DoLog) {
                         MO.Log(" norm1 = {0}, norm2 = {1}, len = {2}",
                                norm1, norm2, len);
                         MO.Log(" Cross product slidingDisplacement is {0}", slidingDisplacement);
                     }
                     if (collisionManager.TestCollision(mo, ref slidingDisplacement, parms)) {
                         if (MO.DoLog) {
                             NowColliding(mo, " After second try TestCollision");
                             MO.Log(" Slid into obstacle on the second try; slidingDisplacement = {0}",
                                    slidingDisplacement);
                         }
                     }
                     else
                         if (MO.DoLog)
                             MO.Log(" Didn't slide into obstacle on the second try");
                     remainingDisplacement -= (originalSlidingDisplacement - slidingDisplacement);
                 }
             }
         }
         else
             remainingDisplacement = displacement;
         if (MO.DoLog)
             MO.Log(" Before checking hop, remainingDisplacement is {0}", remainingDisplacement);
         if (remainingDisplacement.Length > 30f) {
             // Try to hop over the obstacle
             Vector3 c = remainingDisplacement;
             mo.AddDisplacement(new Vector3(0f, CollisionAPI.HopOverThreshold * Client.OneMeter, 0f));
             if (MO.DoLog) {
                 TraceMOBottom(mo, " Before trying to hop");
                 MO.Log(" remainingDisplacement {0}", remainingDisplacement);
             }
             if (collisionManager.TestCollision(mo, ref remainingDisplacement, parms)) {
                 if (MO.DoLog) {
                     MO.Log(" Even after hopping up {0} meters, can't get over obstacle; disp {1}",
                            CollisionAPI.HopOverThreshold, remainingDisplacement);
                 }
                 c = c - remainingDisplacement;
          		c.y = 0;
                 c += new Vector3(0f, CollisionAPI.HopOverThreshold * Client.OneMeter, 0f);
                 if (MO.DoLog)
                     MO.Log(" After failed hop, subtracting {0}", c);
                 mo.AddDisplacement(- c);
             }
             else if (MO.DoLog) {
                 MO.Log(" Hopping up {0} meters got us over obstacle; disp {1}",
                        CollisionAPI.HopOverThreshold, remainingDisplacement);
                 TraceMOBottom(mo, " After hopping");
             }
             NowColliding(mo, " After hopping");
         }
     }
     Vector3 moPos = mo.parts[0].shape.center;
     pos = start + moPos - moStart;
     if (MO.DoLog) {
         MO.Log(" mo location = {0}, moPos - moStart {1}", moPos, moPos - moStart);
         NowColliding(mo, " Leaving FindMobNodeDisplacement");
         MO.Log(" pos = {0}", pos);
     }
     return pos;
 }
Пример #4
0
        // Move the desired displacement, limited by hitting an
        // obstacle.  Then, if we're not already at the terrain level,
        // "fall" until we are either at the terrain level, or hit an
        // obstacle
        public static Vector3 MoveMobNode(MobNode mobNode, Vector3 requestedDisplacement, Client client)
        {
//             Logger.Log(0, "MoveMobNode oid {0} requestedDisplacement {1}", mobNode.Oid, requestedDisplacement);
//             log.DebugFormat("MoveMobNode: mobNode oid {0}, name {1}, followTerrain {2}, position {3}, disp {4}",
//                             mobNode.Oid, mobNode.Name, mobNode.FollowTerrain, mobNode.Position, requestedDisplacement);
            Vector3      start    = mobNode.Position;
            MovingObject mo       = mobNode.Collider;
            bool         collided = false;
            // Zero the y coordinate of displacement, because it seems
            // that it can be arbitrarily large
            Vector3 desiredDisplacement = requestedDisplacement;

            if (mobNode.FollowTerrain)
            {
                desiredDisplacement.y = 0;
            }
            if (desiredDisplacement.LengthSquared <= float.Epsilon)
            {
                return(start);
            }
            if (MO.DoLog)
            {
                MO.Log("MoveMobNode called with mobNode {0} at {1}, disp of {2}",
                       mobNode.Oid, start, requestedDisplacement);
            }
            if (collisionManager == null)
            {
                log.Info("MoveMobNode: returning because collisionManager isn't initialized");
                return(start + desiredDisplacement);
            }
            if (mo == null || mo.parts.Count == 0)
            {
                if (MO.DoLog)
                {
                    MO.Log("MoveMobNode returning because no collision volume for node");
                }
                return(start + requestedDisplacement);
            }
            if (mobNode is Player && NowColliding(mo, "Testing player collision on entry"))
            {
                if (client.MillisecondsStuckBeforeGotoStuck != 0)
                {
                    if (!playerStuck)
                    {
                        stuckGotoTime = DateTime.Now.AddMilliseconds(client.MillisecondsStuckBeforeGotoStuck);
                        playerStuck   = true;
                    }
                    else if (DateTime.Now >= stuckGotoTime)
                    {
                        // We issue the goto command to move us out of the
                        // collision volume
                        client.Write("Executing /stuck command because player has been in a collision volume for " + client.MillisecondsStuckBeforeGotoStuck + " milliseconds");
                        client.NetworkHelper.SendTargettedCommand(client.Player.Oid, "/stuck");
                        playerStuck = false;
                        return(start);
                    }
                }
            }
            else
            {
                playerStuck = false;
            }
            // If we haven't completed setup to this extent, just give up
            CollisionParms parms = new CollisionParms();
            Vector3        pos   = FindMobNodeDisplacement(mobNode, parms, desiredDisplacement, out collided);
//             log.DebugFormat("MoveMobNode: mobNode oid {0}, name {1}, mob node position {2}, displacement {3}",
//                 mobNode.Oid, mobNode.Name, pos, requestedDisplacement);
            float h = worldManager.GetHeightAt(pos);

            // If we're already below ground level, just set our
            // level to ground level.  This will have to be modified
            // if we deal with caves
            if (pos.y - h < 0)
            {
//                 log.DebugFormat("MoveMobNode: mobNode oid {0}, name {1} below terrain level", mobNode.Oid, mobNode.Name);
                mo.AddDisplacement(new Vector3(0f, h - pos.y, 0f));
                pos.y = h;
                if (MO.DoLog && (pos.y - h) < -.001 * Client.OneMeter)
                {
                    MO.Log(string.Format(" MobNode at {0} is below ground height {1}!",
                                         pos, h));
                }
            } // else {
            if (mobNode.FollowTerrain)
            {
//                  NowColliding(mo, " Before falling loop");
                // Fall toward the terrain or an obstacle, whichever comes
                // first
                float step = mo.StepSize(new Vector3(0, h, 0));
                while (true)
                {
                    if (Math.Abs(pos.y - h) < CollisionAPI.VerticalTerrainThreshold * Client.OneMeter)
                    {
                        mo.AddDisplacement(new Vector3(0f, h - pos.y, 0f));
                        pos.y = h;
                        break;
                    }
                    else
                    {
                        float   dy           = -Math.Min(pos.y - h, step);
                        Vector3 displacement = new Vector3(0, dy, 0);
                        Vector3 cd           = displacement;
                        if (MO.DoLog)
                        {
                            MO.Log(" Testing for collision falling {0}", dy);
                            TraceMOBottom(mo, " Before falling");
                        }
                        if (collisionManager.TestCollision(mo, ref displacement, parms))
                        {
                            if (MO.DoLog)
                            {
                                TraceMOBottom(mo, " After TestCollision after falling");
                                NowColliding(mo, " After TestCollision after falling");
                                MO.Log(" Collision when object {0} falls from {1} to {2}",
                                       parms.part.handle, pos, pos + cd);
                                TraceObstacle(parms.obstacle);
                                MO.Log(" Adding dy {0} - displacement.y {1} to pos {2}",
                                       dy, displacement.y, pos);
                            }
                            pos.y += dy - displacement.y;
                            break;
                        }
                        if (MO.DoLog)
                        {
                            MO.Log(" Didn't collide falling; dy {0}, pos {1}",
                                   dy, pos);
                        }
                        pos.y += dy;
                    }
                }
            }
            else
            {
                if (MO.DoLog)
                {
                    MO.Log(" Not falling because mobNode {0} doesn't have FollowTerrain",
                           mobNode.Oid);
                }
            }
//          }

            if (MO.DoLog)
            {
                NowColliding(mo, " Leaving MoveMobNode");
                MO.Log("MoveMobNode returning pos {0}", pos);
                MO.Log("");
            }
            if (collided)
            {
                log.DebugFormat("MoveMobNode collided: mobNode oid {0}, name {1}, orig pos {2}, displacement {3}, new pos {4}",
                                mobNode.Oid, mobNode.Name, start, requestedDisplacement, pos);
            }
            else
            {
                log.DebugFormat("MoveMobNode didn't collide: mobNode oid {0}, name {1}, orig pos {2}, displacement {3}, new pos {4}",
                                mobNode.Oid, mobNode.Name, start, requestedDisplacement, pos);
            }
            return(pos);
        }