bool UnloadUnits(UnitCommander commander, Point2D defensivePoint, int frame, out List <SC2APIProtocol.Action> action) { action = null; // TODO: if already unloading all return false and it will unload as it moves? if (commander.UnitCalculation.Unit.Orders.Any(o => o.AbilityId == (uint)Abilities.UNLOADALLAT_WARPPRISM || o.AbilityId == (uint)Abilities.UNLOADUNIT_WARPPRISM)) { // if a unit has been in there for more than a second, warp prism must be on unloadable ground, move to a new area then try again if (commander.LoadTimes.Any(l => l.Value > 100)) { action = commander.Order(frame, Abilities.MOVE, defensivePoint); } return(true); } if (!MapDataService.PathWalkable(commander.UnitCalculation.Unit.Pos)) { return(false); } foreach (var passenger in commander.UnitCalculation.Unit.Passengers) { if (!commander.LoadTimes.ContainsKey(passenger.Tag)) { commander.LoadTimes[passenger.Tag] = frame; } // use LoadTimes to calculate weapon cooldown if (commander.UnitCalculation.Unit.Shield + commander.UnitCalculation.Unit.Health < 50 || passenger.Shield > 25) // unload any units that regained shields, or if warp prism dying { action = commander.UnloadSpecificUnit(frame, Abilities.UNLOADUNIT_WARPPRISM, passenger.Tag); return(true); } else { if (!ActiveUnitData.SelfUnits.ContainsKey(passenger.Tag)) { action = commander.Order(frame, Abilities.UNLOADALLAT_WARPPRISM, null, commander.UnitCalculation.Unit.Tag); return(true); } else { var weapon = ActiveUnitData.SelfUnits[passenger.Tag].Weapon; if (weapon == null || (frame - commander.LoadTimes[passenger.Tag]) / SharkyOptions.FramesPerSecond > weapon.Speed) // unload any units ready to fire { action = commander.UnloadSpecificUnit(frame, Abilities.UNLOADUNIT_WARPPRISM, passenger.Tag); return(true); } } } } return(false); }
public Point2D GetCliffProxyLocation() { var numberOfCloseLocations = NumberOfCloseBaseLocations(); var closeAirLocations = BaseData.EnemyBaseLocations.Take(5).OrderBy(b => Vector2.DistanceSquared(new Vector2(TargetingData.EnemyMainBasePoint.X, TargetingData.EnemyMainBasePoint.Y), new Vector2(b.Location.X, b.Location.Y))).Take(numberOfCloseLocations); var baseLocation = closeAirLocations.OrderBy(b => PathFinder.GetGroundPath(TargetingData.EnemyMainBasePoint.X, TargetingData.EnemyMainBasePoint.Y, b.Location.X, b.Location.Y, 0).Count()).Last().Location; var angle = Math.Atan2(TargetingData.EnemyMainBasePoint.Y - baseLocation.Y, baseLocation.X - TargetingData.EnemyMainBasePoint.X); var x = 0 * Math.Cos(angle); var y = 0 * Math.Sin(angle); var location = new Point2D { X = baseLocation.X + (float)x, Y = baseLocation.Y - (float)y }; if (MapDataService.PathWalkable(location)) { return(location); } return(baseLocation); }
bool NavigateToSupportUnit(UnitCommander commander, Point2D target, int frame, out List <SC2APIProtocol.Action> action) { if (MapDataService.PathWalkable(commander.UnitCalculation.Unit.Pos)) // if it is in unplaceable terrain, can't unload { if (commander.UnitCalculation.Unit.Shield + commander.UnitCalculation.Unit.Health < 50 || commander.UnitCalculation.EnemiesInRangeOf.Count > 0) // if warp prism dying or enemies nearby unload { action = commander.Order(frame, Abilities.UNLOADALLAT_WARPPRISM, null, commander.UnitCalculation.Unit.Tag); return(true); } foreach (var passenger in commander.UnitCalculation.Unit.Passengers) { var passengerUnit = ActiveUnitData.Commanders[passenger.Tag].UnitCalculation.Unit; var unit = ActiveUnitData.Commanders[passenger.Tag].UnitCalculation; foreach (var enemyAttack in commander.UnitCalculation.NearbyEnemies) { if (DamageService.CanDamage(unit, enemyAttack) && InRange(commander.UnitCalculation.Position, enemyAttack.Position, unit.Range + passengerUnit.Radius + enemyAttack.Unit.Radius) && MapDataService.MapHeight(commander.UnitCalculation.Unit.Pos) == MapDataService.MapHeight(enemyAttack.Unit.Pos)) { if (!enemyAttack.UnitClassifications.Contains(UnitClassification.ArmyUnit) && !InRange(commander.UnitCalculation.Position, enemyAttack.Position, 2 + passengerUnit.Radius + enemyAttack.Unit.Radius)) { continue; } // if an enemy is in range drop the unit //action = commander.Order(frame, Abilities.UNLOADALLAT_WARPPRISM, null, commander.UnitCalculation.Unit.Tag); // TODO: dropping a specific unit not working, can only drop all, change it if they ever fix the api action = commander.UnloadSpecificUnit(frame, Abilities.UNLOADUNIT_WARPPRISM, passenger.Tag); return(true); } } } if (InRange(new Vector2(target.X, target.Y), commander.UnitCalculation.Position, 3)) // if made it to the target just drop { action = commander.Order(frame, Abilities.UNLOADALLAT_WARPPRISM, null, commander.UnitCalculation.Unit.Tag); return(true); } } if (commander.UnitCalculation.Unit.CargoSpaceMax > commander.UnitCalculation.Unit.CargoSpaceTaken && commander.UnitCalculation.Unit.Shield + commander.UnitCalculation.Unit.Health > 50) // find more units to load { var friendly = commander.UnitCalculation.NearbyAllies.Where(u => !u.Unit.IsFlying && u.Unit.BuildProgress == 1 && u.UnitClassifications.Contains(UnitClassification.ArmyUnit) && !commander.UnitCalculation.Unit.Passengers.Any(p => p.Tag == u.Unit.Tag) && commander.UnitCalculation.Unit.CargoSpaceMax - commander.UnitCalculation.Unit.CargoSpaceTaken >= UnitDataService.CargoSize((UnitTypes)u.Unit.UnitType) && u.EnemiesInRange.Count == 0 && u.EnemiesInRangeOf.Count == 0).OrderBy(u => Vector2.DistanceSquared(commander.UnitCalculation.Position, u.Position)).FirstOrDefault(); if (friendly != null) { action = commander.Order(frame, Abilities.LOAD, null, friendly.Unit.Tag); return(true); } } action = commander.Order(frame, Abilities.MOVE, target); return(true); }
bool StartWarping(UnitCommander commander, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (!MapDataService.PathWalkable(commander.UnitCalculation.Unit.Pos)) { return(false); } if (ActiveUnitData.Commanders.Values.Where(v => v.UnitCalculation.Unit.UnitType == (uint)UnitTypes.PROTOSS_WARPGATE && !v.UnitCalculation.Unit.IsActive && v.WarpInAlmostOffCooldown(frame, SharkyOptions.FramesPerSecond, SharkyUnitData)).Count() == 0) { return(false); } if (commander.UnitCalculation.Unit.Shield > 25 && !commander.UnitCalculation.NearbyAllies.Any(v => (v.Unit.UnitType == (uint)UnitTypes.PROTOSS_PYLON || v.Unit.UnitType == (uint)UnitTypes.PROTOSS_WARPPRISMPHASING) && DistanceSquared(commander.UnitCalculation, v) < 400)) // not near any pylons or other warping prisms { if (commander.UnitCalculation.Unit.UnitType == (uint)UnitTypes.PROTOSS_WARPPRISM) { action = commander.Order(frame, Abilities.MORPH_WARPPRISMPHASINGMODE, allowSpam: true); return(true); } } return(false); }
public bool SupportArmy(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, int frame, out List <SC2APIProtocol.Action> action, IEnumerable <UnitCalculation> supportableUnits = null) { action = null; UpdateLoadTimes(commander); if (commander.UnitCalculation.Unit.Shield < commander.UnitCalculation.Unit.ShieldMax / 2) { if (AvoidTargettedDamage(commander, target, defensivePoint, frame, out action)) { return(true); } if (AvoidDamage(commander, target, defensivePoint, frame, out action)) { return(true); } if (commander.UnitCalculation.Unit.Shield < 1) { if (Retreat(commander, target, defensivePoint, frame, out action)) { return(true); } } } // follow behind at the range of pickup var unitToSupport = GetSupportTarget(commander, target, defensivePoint, supportableUnits); if (unitToSupport == null) { return(false); } if (!commander.UnitCalculation.NearbyAllies.Any(a => a.Unit.Tag == unitToSupport.Unit.Tag)) { if (Vector2.DistanceSquared(commander.UnitCalculation.Position, new Vector2(target.X, target.Y)) > Vector2.DistanceSquared(unitToSupport.Position, new Vector2(target.X, target.Y))) { if (NavigateToSupportUnit(commander, target, frame, out action)) { return(true); } } } if (UnloadUnits(commander, defensivePoint, frame, out action)) { return(true); } var moveTo = GetPickupSpot(new Point2D { X = unitToSupport.Unit.Pos.X, Y = unitToSupport.Unit.Pos.Y }, defensivePoint); if (commander.UnitCalculation.Unit.Orders.Any(o => o.AbilityId == (uint)Abilities.UNLOADALLAT_WARPPRISM || o.AbilityId == (uint)Abilities.UNLOADUNIT_WARPPRISM) || !MapDataService.PathWalkable(moveTo)) // TODO: does this groundpathable thing work right? { moveTo = new Point2D { X = unitToSupport.Unit.Pos.X, Y = unitToSupport.Unit.Pos.Y }; } if (InRange(new Vector2(moveTo.X, moveTo.Y), commander.UnitCalculation.Position, 2) && InRange(unitToSupport.Position, commander.UnitCalculation.Position, PickupRange)) { //look at all units within pickup range, ordered by proximity to their closeest enemy // get average hp + shields of back // if unit is in front half weapon is off cooldown and (has below that hp + shields or could die in one hit) pick it up var friendliesInRange = commander.UnitCalculation.NearbyAllies.Where(u => !commander.UnitCalculation.Unit.Passengers.Any(p => p.Tag == u.Unit.Tag) && InRange(u.Position, commander.UnitCalculation.Position, PickupRange)).OrderBy(u => ClosestEnemyDistance(u)); var frontHalf = friendliesInRange.Take(friendliesInRange.Count() / 2); var backHalf = friendliesInRange.Skip(friendliesInRange.Count() / 2); var backAverageHealth = backHalf.Sum(u => u.Unit.Health + u.Unit.Shield) / backHalf.Count(); foreach (var friendly in frontHalf) { if (commander.UnitCalculation.Unit.CargoSpaceMax - commander.UnitCalculation.Unit.CargoSpaceTaken >= UnitDataService.CargoSize((UnitTypes)friendly.Unit.UnitType)) { if (ShouldLoadUnit(friendly, backAverageHealth, frame)) { action = commander.Order(frame, Abilities.LOAD, null, friendly.Unit.Tag); return(true); } } } if (friendliesInRange.Count() < 4) { foreach (var friendly in friendliesInRange) { if (commander.UnitCalculation.Unit.CargoSpaceMax - commander.UnitCalculation.Unit.CargoSpaceTaken >= UnitDataService.CargoSize((UnitTypes)friendly.Unit.UnitType)) { if (ShouldLoadUnit(friendly, friendly.Unit.Health + (friendly.Unit.ShieldMax / 2), frame)) { if (friendly.Unit.WeaponCooldown > 0 && friendly.Unit.Shield < friendly.Unit.ShieldMax / 2) { action = commander.Order(frame, Abilities.LOAD, null, friendly.Unit.Tag); return(true); } } } } } foreach (var friendly in friendliesInRange.Where(f => f.EnemiesInRangeOf.Count() > 0 && f.Range > 2).OrderBy(f => f.Unit.Shield).ThenBy(f => f.Unit.Health)) { if (commander.UnitCalculation.Unit.CargoSpaceMax - commander.UnitCalculation.Unit.CargoSpaceTaken >= UnitDataService.CargoSize((UnitTypes)friendly.Unit.UnitType)) { if (friendly.Unit.WeaponCooldown > 0) { action = commander.Order(frame, Abilities.LOAD, null, friendly.Unit.Tag); return(true); } } } StartWarping(commander, frame, out action); return(true); } else { // move to pickup the friendly closest to the enemy if (StopWarping(commander, frame, out action)) { return(true); } action = commander.Order(frame, Abilities.MOVE, moveTo); return(true); } }