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; } }
private void OnSeekUnable() { //Console.WriteLine("unable to seek"); attackPattern = EnumAttackPattern.BesiegeTarget; pathTraverser.NavigateTo_Async(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, OnSiegeUnable, 3500, 3); }
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); }
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); }