public static bool IsPositionTooFarBehind(EncounterPosition position, Unit unit) { var behindVec = AIUtils.VectorFromCenterRotated(unit.AveragePosition, position.X, position.Y, unit.UnitFacing); // This can't be too restrictive or it stops you from sitting at the back of the line when rotating. return(behindVec.Item2 > -Mathf.CeilToInt(unit.Depth / 2) + 5); }
public static bool IsNextRowTooFarAhead(EncounterPosition parentPos, Unit unit) { var directlyInFrontPosition = AIUtils.RotateAndProject(parentPos, 0, -1, unit.UnitFacing); var forwardVec = AIUtils.VectorFromCenterRotated(unit.AveragePosition, directlyInFrontPosition.X, directlyInFrontPosition.Y, unit.UnitFacing); return(forwardVec.Item2 < -Mathf.CeilToInt(unit.Depth / 2) - 1); }
public override bool IsOnFlank(int x, int y, Unit unit, Flank flank) { var northFacing = AIUtils.VectorFromCenterRotated(unit.RallyPoint, x, y, unit.UnitFacing); if (flank == Flank.LEFT) { return(northFacing.Item1 <= -10); } else if (flank == Flank.RIGHT) { return(northFacing.Item1 >= 9); } else { throw new NotImplementedException(); } }
public static List <TriggeredOrder> ExecutePREPARE_SWEEP_NEXT_LANE(EncounterState state, Unit unit) { // Find your current lane Lane closestLane = null; double closestDistance = 9999.0; foreach (var lane in state.DeploymentInfo.Lanes) { var d = lane.LaneCenter.DistanceTo(unit.AveragePosition); if (d < closestDistance) { closestDistance = d; closestLane = lane; } } // Find a target lane int targetLane = -1; for (int i = closestLane.LaneIdx - 1; i >= 0; i--) { GD.Print("PREPPING CHECKING: ", i); var clear = state.DeploymentInfo.Lanes[i].UnitsForFaction(unit.UnitFaction.Opposite()) .Select((unitAtLanePosition) => state.GetUnit(unitAtLanePosition.UnitId).StandingOrder) .All((order) => order == UnitOrder.ROUT); if (!clear) { targetLane = i; break; } } for (int i = closestLane.LaneIdx + 1; i < state.DeploymentInfo.Lanes.Count; i++) { GD.Print("PREPPING CHECKING: ", i); var clear = state.DeploymentInfo.Lanes[i].UnitsForFaction(unit.UnitFaction.Opposite()) .Select((unitAtLanePosition) => state.GetUnit(unitAtLanePosition.UnitId).StandingOrder) .All((order) => order == UnitOrder.ROUT); if (!clear) { targetLane = i; break; } } GD.Print("CHOSEN LANE: ", targetLane); if (targetLane == -1) { return(null); } // Given a target lane, get the closest unit, and advance to its center var closestUnroutedEnemy = state.DeploymentInfo.Lanes[targetLane] .UnitsForFaction(unit.UnitFaction.Opposite()) .Last((u) => state.GetUnit((u.UnitId)).StandingOrder != UnitOrder.ROUT); var enemyUnit = state.GetUnit(closestUnroutedEnemy.UnitId); var enemyPos = enemyUnit.AveragePosition; var vectorToEnemy = AIUtils.VectorFromCenterRotated(unit.AveragePosition, enemyPos.X, enemyPos.Y, unit.UnitFacing); var stepsBehind = vectorToEnemy.Item2; GD.Print("UNIT IS BEHIND THE ENEMY UNIT BY: ", stepsBehind, " unit pos: ", unit.AveragePosition, " enemy pos: ", enemyPos, "facing: ", unit.UnitFacing); // Order unit to march steps + 5 // unit.StandingOrder = UnitOrder.ADVANCE; // Order unit to reform perpendicular to the enemy line // var triggerStepsPlusFive = new OrderTrigger(OrderTriggerType.ACTIVATE_ON_OR_AFTER_TURN, false, activateOnTurn: state.CurrentTurn + stepsBehind + 5); var oldFacing = unit.UnitFacing; var newFacing = vectorToEnemy.Item1 < 0 ? unit.UnitFacing.LeftOf() : unit.UnitFacing.RightOf(); unit.RallyPoint = AIUtils.RotateAndProject(unit.AveragePosition, 0, -1 * stepsBehind - 25, unit.UnitFacing);; unit.UnitFacing = newFacing; unit.StandingOrder = UnitOrder.REFORM; var behindEnemyUnit = AIUtils.RotateAndProject(enemyUnit.AveragePosition, 0, 15, enemyUnit.UnitFacing); // Order unit to advance after wheeling var triggerStepsPlus40 = new OrderTrigger(OrderTriggerType.ACTIVATE_ON_OR_AFTER_TURN, false, activateOnTurn: state.CurrentTurn + Math.Max(0, stepsBehind) + 15); var sweepOrder = new TriggeredOrder(triggerStepsPlus40, new Order(unit.UnitId, OrderType.ROTATE_AND_REFORM_AT, newPosition: behindEnemyUnit, newFacing: oldFacing.Opposite())); // Order unit to finally advance var triggerStepsPlus60 = new OrderTrigger(OrderTriggerType.ACTIVATE_ON_OR_AFTER_TURN, false, activateOnTurn: state.CurrentTurn + Math.Max(0, stepsBehind) + 50); var advance = new TriggeredOrder(triggerStepsPlus60, new Order(unit.UnitId, OrderType.ADVANCE)); return(new List <TriggeredOrder>() { sweepOrder, advance }); }