Exemplo n.º 1
0
        Pair <CPos, SubCell>?PopPath(Actor self)
        {
            if (path.Count == 0)
            {
                return(null);
            }

            var nextCell = path[path.Count - 1];

            // Something else might have moved us, so the path is no longer valid.
            if (!Util.AreAdjacentCells(mobile.ToCell, nextCell))
            {
                path = EvalPath(BlockedByActor.Immovable);
                return(null);
            }

            var containsTemporaryBlocker = WorldUtils.ContainsTemporaryBlocker(self.World, nextCell, self);

            // Next cell in the move is blocked by another actor
            if (containsTemporaryBlocker || !mobile.CanEnterCell(nextCell, ignoreActor))
            {
                // Are we close enough?
                var cellRange = nearEnough.Length / 1024;
                if (!containsTemporaryBlocker && (mobile.ToCell - destination.Value).LengthSquared <= cellRange * cellRange && mobile.CanStayInCell(mobile.ToCell))
                {
                    // Apply some simple checks to avoid giving up in cases where we can be confident that
                    // nudging/waiting/repathing should produce better results.

                    // Avoid fighting over the destination cell
                    if (path.Count < 2)
                    {
                        path.Clear();
                        return(null);
                    }

                    // We can reasonably assume that the blocker is friendly and has a similar locomotor type.
                    // If there is a free cell next to the blocker that is a similar or closer distance to the
                    // destination then we can probably nudge or path around it.
                    var blockerDistSq = (nextCell - destination.Value).LengthSquared;
                    var nudgeOrRepath = CVec.Directions
                                        .Select(d => nextCell + d)
                                        .Any(c => c != self.Location && (c - destination.Value).LengthSquared <= blockerDistSq && mobile.CanEnterCell(c, ignoreActor));

                    if (!nudgeOrRepath)
                    {
                        path.Clear();
                        return(null);
                    }
                }

                // There is no point in waiting for the other actor to move if it is incapable of moving.
                if (!mobile.CanEnterCell(nextCell, ignoreActor, BlockedByActor.Immovable))
                {
                    path = EvalPath(BlockedByActor.Immovable);
                    return(null);
                }

                // See if they will move
                self.NotifyBlocker(nextCell);

                // Wait a bit to see if they leave
                if (!hasWaited)
                {
                    waitTicksRemaining = mobile.Info.LocomotorInfo.WaitAverage;
                    hasWaited          = true;
                    return(null);
                }

                if (--waitTicksRemaining >= 0)
                {
                    return(null);
                }

                hasWaited = false;

                // If the blocking actors are already leaving, wait a little longer instead of repathing
                if (CellIsEvacuating(self, nextCell))
                {
                    return(null);
                }

                // Calculate a new path
                mobile.RemoveInfluence();
                var newPath = EvalPath(BlockedByActor.All);
                mobile.AddInfluence();

                if (newPath.Count != 0)
                {
                    path = newPath;
                    var newCell = path[path.Count - 1];
                    path.RemoveAt(path.Count - 1);

                    return(Pair.New(newCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor)));
                }
                else if (mobile.IsBlocking)
                {
                    // If there is no way around the blocker and blocker will not move and we are blocking others, back up to let others pass.
                    var newCell = mobile.GetAdjacentCell(nextCell);
                    if (newCell != null)
                    {
                        if ((nextCell - newCell).Value.LengthSquared > 2)
                        {
                            path.Add(mobile.ToCell);
                        }

                        return(Pair.New(newCell.Value, mobile.GetAvailableSubCell(newCell.Value, mobile.FromSubCell, ignoreActor)));
                    }
                }

                return(null);
            }

            hasWaited = false;
            path.RemoveAt(path.Count - 1);

            return(Pair.New(nextCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor)));
        }
Exemplo n.º 2
0
        Pair <CPos, SubCell>?PopPath(Actor self)
        {
            if (path.Count == 0)
            {
                return(null);
            }

            var nextCell = path[path.Count - 1];

            var containsTemporaryBlocker = WorldUtils.ContainsTemporaryBlocker(self.World, nextCell, self);

            //Next cell in the move is blocked by another actor.
            if (containsTemporaryBlocker || !mobile.CanEnterCell(nextCell, ignoreActor, true))
            {
                //Are we close enough?
                var cellRange = nearEnough.Length / 1024;
                if (!containsTemporaryBlocker && (mobile.ToCell - destination.Value).LengthSquard <= cellRange * cellRange)
                {
                    path.Clear();
                    return(null);
                }

                //See if they will move
                if (!hasNotifiedBlocker)
                {
                    self.NotifyBlocker(nextCell);
                    hasNotifiedBlocker = true;
                }

                //Wait a bit to see if they leave
                if (!hasWaited)
                {
                    waitTicksRemaining = mobile.Info.WaitAverage + self.World.SharedRandom.Next(-mobile.Info.WaitSpread, mobile.Info.WaitSpread);
                    hasWaited          = true;
                }

                if (--waitTicksRemaining >= 0)
                {
                    return(null);
                }


                if (mobile.TicksBeforePathing > 0)
                {
                    mobile.TicksBeforePathing--;
                    return(null);
                }

                //Calculate a new path
                mobile.RemoveInfluence();
                var newPath = EvalPath();
                mobile.AddInfluence();

                if (newPath.Count != 0)
                {
                    path = newPath;
                }

                return(null);
            }

            hasNotifiedBlocker = false;
            hasWaited          = false;
            path.RemoveAt(path.Count - 1);

            var subCell = mobile.GetAvailableSubCell(nextCell, SubCell.Any, ignoreActor);

            return(Pair.New(nextCell, subCell));
        }
Exemplo n.º 3
0
        Pair <CPos, SubCell>?PopPath(Actor self)
        {
            if (path.Count == 0)
            {
                return(null);
            }

            var nextCell = path[path.Count - 1];

            // Something else might have moved us, so the path is no longer valid.
            if (!Util.AreAdjacentCells(mobile.ToCell, nextCell))
            {
                path = EvalPath(BlockedByActor.Immovable);
                return(null);
            }

            var containsTemporaryBlocker = WorldUtils.ContainsTemporaryBlocker(self.World, nextCell, self);

            // Next cell in the move is blocked by another actor
            if (containsTemporaryBlocker || !mobile.CanEnterCell(nextCell, ignoreActor))
            {
                // Are we close enough?
                var cellRange = nearEnough.Length / 1024;
                if (!containsTemporaryBlocker && (mobile.ToCell - destination.Value).LengthSquared <= cellRange * cellRange)
                {
                    path.Clear();
                    return(null);
                }

                // There is no point in waiting for the other actor to move if it is incapable of moving.
                if (!mobile.CanEnterCell(nextCell, ignoreActor, BlockedByActor.Immovable))
                {
                    path = EvalPath(BlockedByActor.Immovable);
                    return(null);
                }

                // See if they will move
                self.NotifyBlocker(nextCell);

                // Wait a bit to see if they leave
                if (!hasWaited)
                {
                    waitTicksRemaining = mobile.Info.LocomotorInfo.WaitAverage;
                    hasWaited          = true;
                    return(null);
                }

                if (--waitTicksRemaining >= 0)
                {
                    return(null);
                }

                hasWaited = false;

                // If the blocking actors are already leaving, wait a little longer instead of repathing
                if (CellIsEvacuating(self, nextCell))
                {
                    return(null);
                }

                // Calculate a new path
                mobile.RemoveInfluence();
                var newPath = EvalPath(BlockedByActor.All);
                mobile.AddInfluence();

                if (newPath.Count != 0)
                {
                    path = newPath;
                    var newCell = path[path.Count - 1];
                    path.RemoveAt(path.Count - 1);

                    return(Pair.New(newCell, mobile.GetAvailableSubCell(nextCell, SubCell.Any, ignoreActor)));
                }
                else if (mobile.IsBlocking)
                {
                    // If there is no way around the blocker and blocker will not move and we are blocking others, back up to let others pass.
                    var newCell = mobile.GetAdjacentCell(nextCell);
                    if (newCell != null)
                    {
                        if ((nextCell - newCell).Value.LengthSquared > 2)
                        {
                            path.Add(mobile.ToCell);
                        }

                        return(Pair.New(newCell.Value, mobile.GetAvailableSubCell(newCell.Value, SubCell.Any, ignoreActor)));
                    }
                }

                return(null);
            }

            hasWaited = false;
            path.RemoveAt(path.Count - 1);

            return(Pair.New(nextCell, mobile.GetAvailableSubCell(nextCell, SubCell.Any, ignoreActor)));
        }