Exemplo n.º 1
0
        /// <summary>
        /// Method that switfly finds the best path from start to end. Doesn't reverse outcome
        /// </summary>
        /// <returns>The end breadcrump where each next is a step back)</returns>
        private static BreadCrumb FindPathReversed(Level world, BotMap level, Point3D start, Point3D end)
        {
            MinHeap <BreadCrumb> openList = new MinHeap <BreadCrumb>(256);

            BreadCrumb[, ,] brWorld = new BreadCrumb[world.Size.x, world.Size.y, world.Size.z];
            BreadCrumb node;
            Point3D    tmp;
            int        cost;
            int        diff;

            BreadCrumb current = new BreadCrumb(start);

            current.cost = 0;

            BreadCrumb finish = new BreadCrumb(end);

            try
            {
                brWorld[current.position.X, current.position.Y, current.position.Z] = current;
            }
            catch { return(current); }
            openList.Add(current);

            while (openList.Count > 0)
            {
                //Find best item and switch it to the 'closedList'
                current = openList.ExtractFirst();
                current.onClosedList = true;

                //Find neighbours
                for (int i = 0; i < surrounding.Length; i++)
                {
                    tmp = current.position + surrounding[i];
                    if ((tmp.X <= -1 || tmp.Y <= -1 || tmp.Z <= -1) || (tmp.X >= level.Size.x || tmp.Y >= level.Size.y || tmp.Z >= level.Size.z))
                    {
                        break;
                    }
                    TriBool block = false;
                    try
                    {
                        block = level.AirMap[tmp.X, tmp.Z, tmp.Y]; //Check if block is air
                    }
                    catch { }
                    if (block != TriBool.Unknown)
                    {
                        //Check if we've already examined a neighbour, if not create a new node for it.
                        if (brWorld[tmp.X, tmp.Y, tmp.Z] == null)
                        {
                            node = new BreadCrumb(tmp);
                            brWorld[tmp.X, tmp.Y, tmp.Z] = node;
                        }
                        else
                        {
                            node = brWorld[tmp.X, tmp.Y, tmp.Z];
                        }

                        //If the node is not on the 'closedList' check it's new score, keep the best
                        if (!node.onClosedList)
                        {
                            diff = 0;
                            if (current.position.X != node.position.X)
                            {
                                diff += 1;
                            }
                            if (current.position.Y != node.position.Y)
                            {
                                diff += 1;
                            }
                            if (current.position.Z != node.position.Z)
                            {
                                diff += 1;
                            }
                            if (block == false) //Solid but breakable, allows bot to go through solid areas
                            {
                                diff += 50;
                            }
                            cost = current.cost + diff + node.position.GetDistanceSquared(end);

                            if (cost < node.cost)
                            {
                                node.cost = cost;
                                node.next = current;
                            }

                            //If the node wasn't on the openList yet, add it
                            if (!node.onOpenList)
                            {
                                //Check to see if we're done
                                if (node.Equals(finish))
                                {
                                    node.next = current;
                                    return(node);
                                }
                                node.onOpenList = true;
                                openList.Add(node);
                            }
                        }
                    }
                }
            }
            return(null); //no path found
        }
Exemplo n.º 2
0
        /// <summary>
        /// Handles bot AI
        /// </summary>
        public static void HandleBots()
        {
            foreach (Bot Bot in Server.Bots.ToArray())
            {
                Random Random = new Random();
                if (Bot.Movement)
                {
                    Vector3S TemporaryLocation = new Vector3S(Bot.Player.Pos.x, Bot.Player.Pos.z, Bot.Player.Pos.y);
                    string   PlayerName        = "";
                    if (Bot.FollowPlayers)
                    {
                        #region Find Closest Player
                        bool     HitAPlayer      = false;
                        Vector3S ClosestLocation = Bot.Player.Level.Size * 32;
                        foreach (Player p in Server.Players)
                        {
                            if (p.Level == Bot.Player.Level)
                            {
                                TargetPlayerArgs eargs  = new TargetPlayerArgs(p);
                                bool             cancel = OnBotTargetPlayer.Call(Bot, eargs).Canceled;
                                if (!cancel)
                                {
                                    if (Bot.BlackListPlayers.ContainsKey(p.Username))
                                    {
                                        if (Math.Abs(Bot.BlackListPlayers[p.Username] - Bot.shouldCheckAgainLoopInt) > 100)
                                        {
                                            Bot.BlackListPlayers.Remove(p.Username);
                                        }
                                    }
                                    if (p.Pos - Bot.Player.Pos < ClosestLocation - Bot.Player.Pos && !Bot.BlackListPlayers.ContainsKey(p.Username))
                                    {
                                        HitAPlayer      = true;
                                        ClosestLocation = new Vector3S(p.Pos);
                                        PlayerName      = p.Username;
                                        if (Math.Abs((ClosestLocation.x / 32) - (Bot.LastPos.x / 32)) >= 12 || Math.Abs((ClosestLocation.z / 32) - (Bot.LastPos.z / 32)) >= 12)
                                        {
                                            Bot.shouldCheckAgainLoopInt = 1000;
                                        }
                                    }
                                }
                            }
                        }
                        #endregion
                        if (HitAPlayer)
                        {
                            Vector3S TempLocation = new Vector3S(Bot.Player.Pos);
                            TemporaryLocation = new Vector3S(Bot.Player.Pos);

                            Vector3S Pathfound = new Vector3S(Bot.Player.Pos);

                            #region AStar

                            if (Bot.shouldCheckAgain || Bot.Waypoint == null)
                            {
                                Bot.Waypoint = Pathfind(Bot, ClosestLocation);
                                Bot.LastPos  = ClosestLocation;
                            }
                            try
                            {
                                Pathfound.x = (short)(Bot.Waypoint.position.X * 32);
                                Pathfound.z = (short)(Bot.Waypoint.position.Z * 32);
                                Pathfound.y = (short)(Bot.Waypoint.position.Y * 32);
                            }
                            catch
                            {
                                Bot.shouldCheckAgainLoopInt = 1000;
                                try
                                {
                                    Bot.BlackListPlayers.Add(PlayerName, Bot.shouldCheckAgainLoopInt);
                                }
                                catch { }
                                break;
                            }

                            if (Bot.intLoop >= 2) //Slows down the bots so they arent insta-propogate, it slows them a bit too much though, need to fix
                            {                     //Also makes them a bit less accurate than instant, but much more accurate than Vector2D.Move()
                                Bot.intLoop  = 0;
                                Bot.Waypoint = Bot.Waypoint.next;
                            }
                            else
                            {
                                Bot.intLoop += 1;
                            }

                            TemporaryLocation.x += (short)((Pathfound.x - TemporaryLocation.x) / 2);
                            TemporaryLocation.z += (short)((Pathfound.z - TemporaryLocation.z) / 2);
                            //TemporaryLocation.y += (short)((Pathfound.y - TemporaryLocation.y) / 2);
                            #endregion

                            Block Block1          = Bot.Player.Level.GetBlock(TemporaryLocation / 32);
                            Block Block2          = Bot.Player.Level.GetBlock((TemporaryLocation.x / 32), (TemporaryLocation.z / 32), (TemporaryLocation.y / 32) - 1);
                            Block BlockUnderneath = Bot.Player.Level.GetBlock((TemporaryLocation.x / 32), (TemporaryLocation.z / 32), (TemporaryLocation.y / 32) - 2);
                            Block BlockAbove      = Bot.Player.Level.GetBlock((TemporaryLocation.x / 32), (TemporaryLocation.z / 32), (TemporaryLocation.y / 32) + 1);

                            Vector3S delta = new Vector3S((short)Math.Abs(ClosestLocation.x - TemporaryLocation.x),
                                                          (short)Math.Abs(ClosestLocation.z - TemporaryLocation.z),
                                                          (short)Math.Abs(ClosestLocation.y - TemporaryLocation.y));

                            if (Block.CanWalkThrough(BlockUnderneath) && Block.CanWalkThrough(Block2) &&
                                !Block.CanEscalate(Block1) && !Block.CanEscalate(Block2))
                            {
                                TemporaryLocation.y -= 21;
                            }

                            if (Block.CanWalkThrough(Block1) && !Block.CanWalkThrough(Block2) && !Block.CanWalkThrough(BlockUnderneath))
                            {
                                TemporaryLocation.y += 21;
                            }
                            else if (Block.CanEscalate(Block1) && Block.CanEscalate(Block2) && Pathfound.y > TemporaryLocation.y)
                            {
                                TemporaryLocation.y += 21;
                            }
                            else if (Block.CanWalkThrough(BlockAbove) && !Block.CanWalkThrough(BlockUnderneath) && Pathfound.y > TemporaryLocation.y && !Block.IsOPBlock(BlockUnderneath))
                            {
                                TemporaryLocation.y += 21;
                                Bot.Player.Level.BlockChange((ushort)(TemporaryLocation.x / 32), (ushort)(TemporaryLocation.z / 32), (ushort)((TemporaryLocation.y / 32) - 2), 1);
                            }
                            else if (!Block.CanWalkThrough(BlockAbove) && !Block.CanWalkThrough(BlockUnderneath) && !Block.IsOPBlock(BlockAbove))
                            {
                                Bot.Player.Level.BlockChange((ushort)(TemporaryLocation.x / 32), (ushort)(TemporaryLocation.z / 32), (ushort)((TemporaryLocation.y / 32) + 1), 0);
                            }

                            if (Block.CanWalkThrough(BlockUnderneath) && !Block.CanWalkThrough(Bot.Player.Level.GetBlock((Bot.Player.oldPos.x / 32), (Bot.Player.oldPos.z / 32), (Bot.Player.oldPos.y / 32) - 2)) &&
                                !Block.IsOPBlock(BlockUnderneath) && Pathfound.y > TemporaryLocation.y)
                            {
                                Bot.Player.Level.BlockChange((ushort)(TemporaryLocation.x / 32), (ushort)(TemporaryLocation.z / 32), (ushort)((TemporaryLocation.y / 32) - 2), 1);
                            }

                            if ((!Block.IsOPBlock(Block1) && !Block.IsOPBlock(Block2)) && (!Block.CanWalkThrough(Block1) && !Block.CanWalkThrough(Block2)) &&
                                (Block1 != Block.BlockList.UNKNOWN && Block2 != Block.BlockList.UNKNOWN))
                            {
                                Bot.Player.Level.BlockChange(TemporaryLocation / 32, 0);
                                Bot.Player.Level.BlockChange((ushort)(TemporaryLocation.x / 32), (ushort)(TemporaryLocation.z / 32), (ushort)((TemporaryLocation.y / 32) - 1), 0);
                            }

                            if (!Block.CanWalkThrough(BlockUnderneath) && (Pathfound.y / 32) < (TemporaryLocation.y / 32) && !Block.IsOPBlock(BlockUnderneath))
                            {
                                Bot.Player.Level.BlockChange((ushort)(TemporaryLocation.x / 32), (ushort)(TemporaryLocation.z / 32), (ushort)((TemporaryLocation.y / 32) - 2), 0);
                            }

                            MoveEventArgs eargs  = new MoveEventArgs(TemporaryLocation, Bot.Player.Pos);
                            bool          cancel = OnBotMove.Call(Bot, eargs).Canceled;
                            if (cancel)
                            {
                                TemporaryLocation = TempLocation;
                            }
                        }
                    }

                    Bot.Player.Pos = TemporaryLocation;
                    Bot.Player.UpdatePosition(true); //Pls leave this true, bots dont appear properly otherwise
                }
            }
        }