예제 #1
0
        private void tryTacticalRetreat()
        {
            if (RemainInOffensiveMode)
            {
                return;
            }

            //Console.WriteLine("doTacticalRetreatIfHurt");

            // Found no circling path, let's run away then
            if (RecentlyHurt || RemainInTacticalRetreat)
            {
                // Console.WriteLine("tactical retreat!");

                updateTargetPosFleeMode(targetPos);
                float size = targetEntity.SelectionBox.XSize;
                pathTraverser.WalkTowards(targetPos, moveSpeed, size + 0.2f, OnGoalReached, OnStuck);
                if (attackPattern != EnumAttackPattern.TacticalRetreat)
                {
                    tacticalRetreatBeginTotalMs = entity.World.ElapsedMilliseconds;
                }

                attackPattern    = EnumAttackPattern.TacticalRetreat;
                attackedByEntity = null;
            }
        }
예제 #2
0
        private void OnSeekUnable()
        {
            //Console.WriteLine("unable to seek");

            attackPattern = EnumAttackPattern.BesiegeTarget;
            pathTraverser.NavigateTo_Async(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, OnSiegeUnable, 3500, 3);
        }
예제 #3
0
        public override void StartExecute()
        {
            stopNow           = false;
            active            = true;
            currentFollowTime = 0;

            if (RemainInTacticalRetreat)
            {
                tryTacticalRetreat();
                return;
            }

            attackPattern = EnumAttackPattern.DirectAttack;

            // 1 in 20 times we do an expensive search
            int searchDepth = 3500;

            if (world.Rand.NextDouble() < 0.05)
            {
                searchDepth = 10000;
            }

            pathTraverser.NavigateTo_Async(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, OnSeekUnable, searchDepth, 1);
        }
예제 #4
0
        private bool TryCircleTarget()
        {
            // Console.WriteLine("try circle target");

            bool giveUpWhenNoPath = targetPos.SquareDistanceTo(entity.Pos) < 12 * 12;
            int  searchDepth      = 3500;

            attackPattern  = EnumAttackPattern.CircleTarget;
            lastPathfindOk = false;

            // If we cannot find a path to the target, let's circle it!
            float angle = (float)Math.Atan2(entity.ServerPos.X - targetPos.X, entity.ServerPos.Z - targetPos.Z);

            for (int i = 0; i < 3; i++)
            {
                // We need to avoid crossing the path of the target, so we do only small angle variation between us and the target
                double randAngle = angle + 0.5 + world.Rand.NextDouble() / 2;

                double distance = 4 + world.Rand.NextDouble() * 6;

                double dx = GameMath.Sin(randAngle) * distance;
                double dz = GameMath.Cos(randAngle) * distance;
                targetPos.Add(dx, 0, dz);

                int      tries = 0;
                bool     ok    = false;
                BlockPos tmp   = new BlockPos((int)targetPos.X, (int)targetPos.Y, (int)targetPos.Z);

                int dy = 0;
                while (tries < 5)
                {
                    // Down ok?
                    if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y - dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.SelectionBox, new Vec3d(tmp.X + 0.5, tmp.Y - dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y -= dy;
                        targetPos.Y++;
                        break;
                    }

                    // Up ok?
                    if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y + dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.SelectionBox, new Vec3d(tmp.X + 0.5, tmp.Y + dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y += dy;
                        targetPos.Y++;
                        break;
                    }

                    tries++;
                    dy++;
                }

                if (ok)
                {
                    pathTraverser.NavigateTo_Async(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, OnCircleTargetUnable, searchDepth, 1);
                    return(true);
                }
            }

            return(false);
        }