public override AIAction GFixedUpdate(UnitCommander unitCmd, Vector2 goalPos) { //Init Vector2 moveVec = Vector2.zero; Vector2 pos = unitCmd.transform.position; unitCmd.GetComponent<Rigidbody2D>().gravityScale = 1; state = AIState.MOVING; //Check for enemies float directionX = unitCmd.turnedRight ? 1f : -1f; Vector2 inFrontUpperLeft = new Vector2(pos.x + directionX * 0.5f, pos.y + 0.5f); Vector2 inFrontLowerRight = new Vector2(pos.x + directionX * 0.9f, pos.y - 0.5f); Collider2D[] inFrontColliders = Physics2D.OverlapAreaAll(inFrontUpperLeft, inFrontLowerRight); foreach (Collider2D coll in inFrontColliders) { if (coll.tag.Equals("Monster")){ state = AIState.ATTACKING; } } switch (state) { case AIState.MOVING: moveVec = Movement(unitCmd, goalPos); break; case AIState.ATTACKING: moveVec = AttackMove(unitCmd, inFrontColliders); break; default: break; } Debug.DrawLine(inFrontUpperLeft, inFrontLowerRight, Color.green); return new AIAction(moveVec, state == AIState.ATTACKING); }
/// <summary> /// Move as close as possible to closest enemy /// </summary> /// <returns>The move.</returns> /// <param name="unitCmd">Unit cmd.</param> /// <param name="goalPos">Goal position.</param> protected Vector2 AttackMove(UnitCommander unitCmd, Collider2D[] inFrontColliders) { Vector2 moveVec = Vector2.zero; Vector2 pos = unitCmd.transform.position; //Get closest enemy float closestDist = float.MaxValue; Transform closestMonster = null; foreach (Collider2D coll in inFrontColliders) { if (coll.tag.Equals("Monster")){ float dist = Vector2.Distance(unitCmd.transform.position, coll.transform.position); if (dist < closestDist){ closestDist = dist; closestMonster = coll.transform; } } } //Turn towards closest enemy if (closestMonster.position.x > pos.x) unitCmd.turnedRight = true; else unitCmd.turnedRight = false; //Move towards enemy float distToEnemy = 0.75f; //TODO float goalPosX = closestMonster.position.x + (unitCmd.turnedRight ? -1 : 1) * distToEnemy; moveVec.x = Mathf.MoveTowards(pos.x, goalPosX, 0.1f) - pos.x; // Debug.Log("pos: " + pos + ", closestMonster.position: " + closestMonster.position + ", closestDist: " + closestDist + " , moveVec: "+ moveVec); //keep distance to fellow heroes // Vector2 upperLeft = new Vector2(pos.x - 0.1f, pos.y + 0.5f); // Vector2 lowerRight = new Vector2(pos.x + 0.1f, pos.y - 0.5f); // Collider2D[] colliders = Physics2D.OverlapAreaAll(upperLeft, lowerRight); // // float totXForce = 0; // foreach (Collider2D coll in colliders) { // // if (coll.tag.Equals("Hero")) // { // float xDiff = coll.transform.position.x - pos.x; // float xForce = xDiff == 0 ? 0 : 0.1f/xDiff; // totXForce -= xForce; // } // } // //Apply hero-distancer force // if (totXForce > 0.1) totXForce = 0.1f; // if (totXForce < -0.1) totXForce = -0.1f; // if ((moveVec.x > 0 && totXForce < 0) || (moveVec.x < 0 && totXForce > 0)) moveVec.x += totXForce; return moveVec; }
void Start() { //create UnitCommander unitCommander = (UnitCommander)Instantiate(Resources.Load(("Prefabs/UnitCommander"), typeof(UnitCommander))); unitCommander.transform.position = transform.parent.position; unitCommander.transform.parent = transform.parent; unitCommander.SetClan(clan); //create BuildingCommander buildingCommander = (BuildingCommander)Instantiate(Resources.Load(("Prefabs/BuildingCommander"), typeof(BuildingCommander))); buildingCommander.transform.position = transform.parent.position; buildingCommander.transform.parent = transform.parent; buildingCommander.SetClan(clan); }
bool SupportArmy(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, int frame, out List <SC2APIProtocol.Action> action) { action = null; 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 cloak field var armyUnits = ActiveUnitData.Commanders.Where(u => u.Value.UnitCalculation.UnitClassifications.Contains(UnitClassification.ArmyUnit)).Select(s => s.Value); var unitToSupport = GetSupportTarget(commander, armyUnits, target, defensivePoint); if (unitToSupport == null) { return(false); } var moveTo = GetSupportSpot(commander, unitToSupport, target, defensivePoint); action = commander.Order(frame, Abilities.MOVE, moveTo); return(true); }
public void UpdateHealthBar(UnitCommander unitCmd) { int instId = unitCmd.GetInstanceID(); Transform healthBarT = null; if (!healthBarDict.ContainsKey(instId)){ healthBarT = Instantiate(healthBarPrefab); healthBarT.SetParent(canvas); healthBarDict.Add(instId, healthBarT); }else{ healthBarT = healthBarDict[instId]; } Vector2 aboveHeadPosition = Camera.main.WorldToScreenPoint(unitCmd.transform.position); aboveHeadPosition.y += 25; healthBarT.position = aboveHeadPosition; float health = unitCmd.health / (float) unitCmd.maxHealth; healthBarT.GetComponent<HealthBar>().UpdateBar(health, HealthToColor(health)); }
Point2D GetTimeWarpLocation(UnitCommander commander) { var enemiesInRange = commander.UnitCalculation.NearbyEnemies.Where(e => !e.Attributes.Contains(SC2APIProtocol.Attribute.Structure) && Vector2.DistanceSquared(e.Position, commander.UnitCalculation.Position) < TimeWarpRange * TimeWarpRange); var damageCounts = new Dictionary <Point, float>(); foreach (var enemyAttack in commander.UnitCalculation.NearbyEnemies) { float damageReduction = 0; foreach (var hitEnemy in enemiesInRange) { if (!hitEnemy.Attributes.Contains(SC2APIProtocol.Attribute.Structure) && Vector2.DistanceSquared(hitEnemy.Position, enemyAttack.Position) <= (hitEnemy.Unit.Radius + TImeWarpRadius) * (hitEnemy.Unit.Radius + TImeWarpRadius)) { damageReduction += hitEnemy.Dps; } } damageCounts[enemyAttack.Unit.Pos] = damageReduction; } return(GetBestTimeWarpLocation(damageCounts.OrderByDescending(x => x.Value))); }
public List <SC2APIProtocol.Action> HarassWorkers(UnitCommander commander, Point2D target, Point2D defensivePoint, int frame) { List <SC2APIProtocol.Action> action = null; var bestTarget = GetBestHarassTarget(commander, target); if (PreOffenseOrder(commander, target, defensivePoint, null, bestTarget, frame, out action)) { return(action); } if (WeaponReady(commander) && commander.UnitCalculation.EnemiesInRange.Count() > 0) { if (AttackBestTarget(commander, target, defensivePoint, null, bestTarget, frame, out action)) { return(action); } } return(NavigateToPoint(commander, target, defensivePoint, null, frame)); }
protected override bool OffensiveAbility(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (PulsarBeam(commander, frame, bestTarget, out action)) { return(true); } if (Revelation(commander, frame, out action)) { return(true); } if (StasisWard(commander, frame, bestTarget, out action)) { return(true); } return(false); }
protected override bool PreOffenseOrder(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (commander.UnitCalculation.Unit.Shield == commander.UnitCalculation.Unit.ShieldMax) { var cloakedPosition = CloakedInvader(commander); if (cloakedPosition != null) { action = commander.Order(frame, Abilities.MOVE, cloakedPosition); return(true); } } if (SupportArmy(commander, target, defensivePoint, groupCenter, frame, out action)) { return(true); } return(false); }
public List <SC2APIProtocol.Action> NavigateToPoint(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, int frame) { List <SC2APIProtocol.Action> action = null; if (PreOffenseOrder(commander, target, defensivePoint, null, null, frame, out action)) { return(action); } if (MapDataService.InEnemyDetection(commander.UnitCalculation.Unit.Pos)) { if (commander.UnitCalculation.NearbyEnemies.Count(e => e.DamageAir) > 0) { if (commander.RetreatPathFrame + 20 < frame) { commander.RetreatPath = SharkyPathFinder.GetSafeAirPath(target.X, target.Y, commander.UnitCalculation.Unit.Pos.X, commander.UnitCalculation.Unit.Pos.Y, frame); commander.RetreatPathFrame = frame; } if (FollowPath(commander, frame, out action)) { return(action); } } if (AvoidTargettedDamage(commander, target, defensivePoint, frame, out action)) { return(action); } if (AvoidDamage(commander, target, defensivePoint, frame, out action)) { return(action); } } NavigateToTarget(commander, target, groupCenter, null, Formation.Normal, frame, out action); return(action); }
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); }
protected override bool PreOffenseOrder(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; var cloakedPosition = CloakedInvader(commander); if (cloakedPosition != null && commander.UnitCalculation.Unit.Energy >= 25) { action = commander.Order(frame, Abilities.EFFECT_ORACLEREVELATION, cloakedPosition); return(true); } var order = commander.UnitCalculation.Unit.Orders.FirstOrDefault(o => o.AbilityId == (uint)Abilities.EFFECT_ORACLEREVELATION && o.TargetWorldSpacePos != null); if (order != null && commander.UnitCalculation.Unit.Shield == commander.UnitCalculation.Unit.ShieldMax && commander.UnitCalculation.Unit.Orders.Any(o => o.AbilityId == (uint)Abilities.EFFECT_ORACLEREVELATION)) { if (commander.UnitCalculation.Unit.Shield > commander.UnitCalculation.Unit.ShieldMax / 2.0) { return(true); } if (Revelation(commander, frame, out action)) { return(true); } } if (AvoidTargettedDamage(commander, target, defensivePoint, frame, out action)) { return(true); } if (AvoidDamage(commander, target, defensivePoint, frame, out action)) { return(true); } return(false); }
bool PulsarBeam(UnitCommander commander, int frame, UnitCalculation bestTarget, out List <SC2APIProtocol.Action> action) { action = null; if (DeactivatePulsarBeam(commander, frame, bestTarget, out action)) { return(true); } if (commander.UnitCalculation.Unit.BuffIds.Contains((uint)Buffs.ORACLEWEAPON) || commander.UnitCalculation.Unit.Energy < 50 || bestTarget == null) { return(false); } if (commander.UnitCalculation.EnemiesInRange.Any(e => e.Unit.Tag == bestTarget.Unit.Tag)) { action = commander.Order(frame, Abilities.BEHAVIOR_PULSARBEAMON); return(true); } return(false); }
protected override UnitCalculation GetBestDpsReduction(UnitCommander commander, Weapon weapon, IEnumerable <UnitCalculation> primaryTargets, IEnumerable <UnitCalculation> secondaryTargets) { float splashRadius = 1f; var dpsReductions = new Dictionary <ulong, float>(); foreach (var enemyAttack in primaryTargets) { float dpsReduction = 0; foreach (var splashedEnemy in secondaryTargets) { if (Vector2.DistanceSquared(splashedEnemy.Position, enemyAttack.Position) < (splashedEnemy.Unit.Radius + splashRadius) * (splashedEnemy.Unit.Radius + splashRadius)) { dpsReduction += splashedEnemy.Dps / TimeToKill(weapon, splashedEnemy.Unit, SharkyUnitData.UnitData[(UnitTypes)splashedEnemy.Unit.UnitType]); } } dpsReductions[enemyAttack.Unit.Tag] = dpsReduction; } var best = dpsReductions.OrderByDescending(x => x.Value).FirstOrDefault().Key; return(primaryTargets.FirstOrDefault(t => t.Unit.Tag == best)); }
protected override bool AttackBestTargetInRange(UnitCommander commander, Point2D target, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (bestTarget != null) { if (commander.UnitCalculation.EnemiesInRange.Any(e => e.Unit.Tag == bestTarget.Unit.Tag) && bestTarget.Unit.DisplayType == DisplayType.Visible) { action = commander.Order(frame, Abilities.ATTACK, null, bestTarget.Unit.Tag); return(true); } var blinkReady = SharkyUnitData.ResearchedUpgrades.Contains((uint)Upgrades.BLINKTECH) && commander.AbilityOffCooldown(Abilities.EFFECT_BLINK_STALKER, frame, SharkyOptions.FramesPerSecond, SharkyUnitData); if (blinkReady) { action = commander.Order(frame, Abilities.EFFECT_BLINK_STALKER, new Point2D { X = bestTarget.Unit.Pos.X, Y = bestTarget.Unit.Pos.Y }); return(true); } } return(false); }
protected override UnitCalculation GetBestDpsReduction(UnitCommander commander, Weapon weapon, IEnumerable <UnitCalculation> primaryTargets, IEnumerable <UnitCalculation> secondaryTargets) { float splashRadius = 0.3f; var dpsReductions = new Dictionary <ulong, float>(); foreach (var enemyAttack in primaryTargets) { float dpsReduction = 0; var attackLine = GetAttackLine(commander.UnitCalculation.Unit.Pos, enemyAttack.Unit.Pos); foreach (var splashedEnemy in secondaryTargets) { if (CollisionCalculator.Collides(splashedEnemy.Position, splashedEnemy.Unit.Radius + splashRadius, attackLine.Start, attackLine.End)) { dpsReduction += splashedEnemy.Dps / TimeToKill(weapon, splashedEnemy.Unit, SharkyUnitData.UnitData[(UnitTypes)splashedEnemy.Unit.UnitType]); } } dpsReductions[enemyAttack.Unit.Tag] = dpsReduction; } var best = dpsReductions.OrderByDescending(x => x.Value).FirstOrDefault().Key; return(primaryTargets.FirstOrDefault(t => t.Unit.Tag == best)); }
protected override bool OffensiveAbility(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (bestTarget != null && SharkyUnitData.ResearchedUpgrades.Contains((uint)Upgrades.DARKTEMPLARBLINKUPGRADE) && commander.AbilityOffCooldown(Abilities.EFFECT_SHADOWSTRIDE, frame, SharkyOptions.FramesPerSecond, SharkyUnitData)) { var distanceSqaured = Vector2.DistanceSquared(commander.UnitCalculation.Position, bestTarget.Position); if (distanceSqaured <= ShadowStrikeRange * ShadowStrikeRange && distanceSqaured > 9) { var x = bestTarget.Unit.Radius * Math.Cos(bestTarget.Unit.Facing); var y = bestTarget.Unit.Radius * Math.Sin(bestTarget.Unit.Facing); var blinkPoint = new Point2D { X = bestTarget.Unit.Pos.X + (float)x, Y = bestTarget.Unit.Pos.Y - (float)y }; action = commander.Order(frame, Abilities.EFFECT_SHADOWSTRIDE, blinkPoint); return(true); } } return(false); }
protected override bool OffensiveAbility(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (commander.UnitCalculation.Unit.Energy < 50) { return(false); } if (commander.UnitCalculation.NearbyEnemies.Any(e => e.Unit.BuffIds.Contains((uint)Buffs.GRAVITONBEAM))) // only have one unit lifted at a time { return(false); } var bestGravitonTarget = GetBestGravitonBeamTarget(commander, target); if (bestGravitonTarget != null) { action = commander.Order(frame, Abilities.EFFECT_GRAVITONBEAM, null, bestGravitonTarget.Unit.Tag); return(true); } return(false); }
bool TimeWarp(UnitCommander commander, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (commander.UnitCalculation.Unit.Orders.Any(o => o.AbilityId == (uint)Abilities.EFFECT_TIMEWARP)) { return(true); } if (commander.UnitCalculation.Unit.Energy < 100 || !commander.AbilityOffCooldown(Abilities.EFFECT_TIMEWARP, frame, SharkyOptions.FramesPerSecond, SharkyUnitData)) { return(false); } var point = GetTimeWarpLocation(commander); if (point == null) { return(false); } action = commander.Order(frame, Abilities.EFFECT_TIMEWARP, point); return(true); }
Point2D CloakedInvader(UnitCommander commander) { var pos = commander.UnitCalculation.Position; var hiddenUnits = ActiveUnitData.EnemyUnits.Where(e => e.Value.Unit.DisplayType == DisplayType.Hidden).OrderBy(e => Vector2.DistanceSquared(pos, e.Value.Position)); if (hiddenUnits.Count() > 0) { return(new Point2D { X = hiddenUnits.FirstOrDefault().Value.Unit.Pos.X, Y = hiddenUnits.FirstOrDefault().Value.Unit.Pos.Y }); } var unit = ActiveUnitData.SelfUnits.Values.Where(a => a.Unit.UnitType == (uint)UnitTypes.PROTOSS_NEXUS).SelectMany(a => a.NearbyEnemies).Where(e => SharkyUnitData.CloakableAttackers.Contains((UnitTypes)e.Unit.UnitType) && !e.Unit.BuffIds.Contains((uint)Buffs.ORACLEREVELATION)).OrderBy(e => Vector2.DistanceSquared(pos, e.Position)).FirstOrDefault(); if (unit != null) { return(new Point2D { X = unit.Unit.Pos.X, Y = unit.Unit.Pos.Y }); } return(null); }
bool DetermineMiningAction(UnitCommander commander, int frame, out List <SC2APIProtocol.Action> action) { action = new List <SC2APIProtocol.Action>(); if (commander.UnitCalculation.NearbyEnemies.Count > 0) { return(false); } var nexuses = BaseData.SelfBases.Where(u => u.ResourceCenter.BuildProgress == 1 && u.MineralMiningInfo.Count() > 0).OrderBy(u => u.MineralMiningInfo.Sum(m => m.Workers.Count) / u.MineralMiningInfo.Count()).ThenBy(u => Vector2.DistanceSquared(commander.UnitCalculation.Position, new Vector2(u.Location.X, u.Location.Y))); //foreach (var nexusBase in BaseData.Bases) //{ // DrawSphere(SC2Util.Point(nexusBase.MineralLinePos.X, nexusBase.MineralLinePos.Y, 11)); //} if (commander.UnitCalculation.Unit.Passengers.Count > 0) { //action = commander.Order(frame, Abilities.UNLOADALLAT_WARPPRISM, null, commander.UnitCalculation.Unit.Tag); foreach (var passenger in commander.UnitCalculation.Unit.Passengers) { var passengerAction = commander.UnloadSpecificUnit(frame, Abilities.UNLOADUNIT_WARPPRISM, passenger.Tag); if (passengerAction != null) { action.AddRange(passengerAction); } } return(true); } if (StopWarping(commander, frame, out action)) { return(true); } var otherWarpPrisms = ActiveUnitData.SelfUnits.Where(u => u.Value.Unit.Tag != commander.UnitCalculation.Unit.Tag && (u.Value.Unit.UnitType == (uint)UnitTypes.PROTOSS_WARPPRISM || u.Value.Unit.UnitType == (uint)UnitTypes.PROTOSS_WARPPRISMPHASING)); foreach (var nexus in nexuses) { if (!otherWarpPrisms.Any(o => Vector2.DistanceSquared(o.Value.Position, new Vector2(nexus.Location.X, nexus.Location.Y)) < 25)) { var miningLocation = GetMiningSpot(nexus); if (miningLocation != null) { //DrawSphere(SC2Util.Point(miningLocation.X, miningLocation.Y, 11)); if (Vector2.DistanceSquared(commander.UnitCalculation.Position, new Vector2(miningLocation.X, miningLocation.Y)) < .5) { var probe = commander.UnitCalculation.NearbyAllies.Where(a => a.Unit.BuffIds.Any(b => SharkyUnitData.CarryingMineralBuffs.Contains((Buffs)b)) && InRange(a.Position, commander.UnitCalculation.Position, PickupRange) && !InRange(a.Position, new Vector2(nexus.Location.X, nexus.Location.Y), nexus.ResourceCenter.Radius + 1)).OrderByDescending(u => Vector2.DistanceSquared(new Vector2(nexus.Location.X, nexus.Location.Y), u.Position)).FirstOrDefault(); if (probe != null) { action = commander.Order(frame, Abilities.LOAD, null, probe.Unit.Tag); return(true); } else { action = commander.Order(frame, Abilities.UNLOADALLAT_WARPPRISM, miningLocation); return(true); } } action = commander.Order(frame, Abilities.MOVE, miningLocation); return(true); } } } return(false); }
protected Vector2 Movement(UnitCommander unitCmd, Vector2 goalPos) { Vector2 moveVec = Vector2.zero; Vector2 pos = unitCmd.transform.position; bool isOnStairs = false; Vector2 upperLeft = new Vector2(pos.x - 0.1f, pos.y + 0.5f); Vector2 lowerRight = new Vector2(pos.x + 0.1f, pos.y - 0.5f); Collider2D[] colliders = Physics2D.OverlapAreaAll(upperLeft, lowerRight); float totXForce = 0; foreach (Collider2D coll in colliders) { //Is on stairs? if (coll.tag.Equals("Stairs")) { isOnStairs = true; unitCmd.GetComponent<Rigidbody2D>().gravityScale = 0; unitCmd.GetComponent<Rigidbody2D>().velocity = Vector2.zero; break; }//Move away from other heroes // else if (coll.tag.Equals("Hero")) // { // float xDiff = coll.transform.position.x - pos.x; // float xForce = xDiff == 0 ? 0 : 0.1f/xDiff; // totXForce -= xForce; // } } //Move in x or y direction / Can move in y direction? if (isOnStairs && CanContinueOnStairs(pos, goalPos)){ // && transform.position.y - 0.5f < goalPos.y || transform.position.y - 0.6f > goalPos.y){ moveVec.y = Mathf.MoveTowards(pos.y, goalPos.y, 0.1f) - pos.y; }else{ moveVec.x = Mathf.MoveTowards(pos.x, goalPos.x, 0.1f) - pos.x; } //Apply hero-distancer force // if (totXForce > 0.1) totXForce = 0.1f; // if (totXForce < -0.1) totXForce = -0.1f; // if ((moveVec.x > 0 && totXForce < 0) || (moveVec.x < 0 && totXForce > 0)) moveVec.x += totXForce; return moveVec; }
public virtual AIAction GFixedUpdate(UnitCommander unitCmd, Vector2 goalPos) { return new AIAction(Vector2.zero, false); }
bool StasisWard(UnitCommander commander, int frame, UnitCalculation bestTarget, out List <SC2APIProtocol.Action> action) { action = null; return(false); // TODO: stasis ward, put stasis wards on the tops of ramps }
public void Init(Vector2 velVec, Sprite sprite, UnitCommander unitCmd) { GetComponent<SpriteRenderer>().sprite = sprite; GetComponent<Rigidbody2D>().velocity = velVec; ownerUnitCmd = unitCmd; }
protected override bool GetHighGroundVision(UnitCommander commander, Point2D target, Point2D defensivePoint, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; return(false); }
protected override UnitCalculation GetBestTarget(UnitCommander commander, Point2D target, int frame) { var existingAttackOrder = commander.UnitCalculation.Unit.Orders.Where(o => o.AbilityId == (uint)Abilities.ATTACK || o.AbilityId == (uint)Abilities.ATTACK_ATTACK).FirstOrDefault(); var range = commander.UnitCalculation.Range; var attacks = new List <UnitCalculation>(commander.UnitCalculation.EnemiesInRange.Where(u => u.Unit.DisplayType == DisplayType.Visible)); // units that are in range right now UnitCalculation bestAttack = null; if (attacks.Count > 0) { var oneShotKills = attacks.Where(a => a.Unit.Health + a.Unit.Shield < GetDamage(commander.UnitCalculation.Weapons, a.Unit, a.UnitTypeData) && !a.Unit.BuffIds.Contains((uint)Buffs.IMMORTALOVERLOAD)); if (oneShotKills.Count() > 0) { if (existingAttackOrder != null) { var existing = oneShotKills.FirstOrDefault(o => o.Unit.Tag == existingAttackOrder.TargetUnitTag); if (existing != null) { return(existing); // just keep attacking the same unit } } var oneShotKill = GetBestTargetFromList(commander, oneShotKills, existingAttackOrder); if (oneShotKill != null) { return(oneShotKill); } else { commander.BestTarget = oneShotKills.OrderBy(o => o.Dps).FirstOrDefault(); return(commander.BestTarget); } } bestAttack = GetBestTargetFromList(commander, attacks, existingAttackOrder); if (bestAttack != null && (bestAttack.UnitClassifications.Contains(UnitClassification.ArmyUnit) || bestAttack.UnitClassifications.Contains(UnitClassification.DefensiveStructure) || (bestAttack.UnitClassifications.Contains(UnitClassification.Worker) && bestAttack.EnemiesInRange.Any(e => e.Unit.Tag == commander.UnitCalculation.Unit.Tag)))) { commander.BestTarget = bestAttack; return(bestAttack); } } attacks = new List <UnitCalculation>(); // nearby units not in range right now foreach (var enemyAttack in commander.UnitCalculation.NearbyEnemies) { if (enemyAttack.Unit.DisplayType == DisplayType.Visible && DamageService.CanDamage(commander.UnitCalculation, enemyAttack) && !InRange(enemyAttack.Position, commander.UnitCalculation.Position, range + enemyAttack.Unit.Radius + commander.UnitCalculation.Unit.Radius)) { attacks.Add(enemyAttack); } } var safeAttacks = attacks.Where(a => a.Damage < commander.UnitCalculation.Unit.Health); if (safeAttacks.Count() > 0) { var bestOutOfRangeAttack = GetBestTargetFromList(commander, safeAttacks, existingAttackOrder); if (bestOutOfRangeAttack != null && (bestOutOfRangeAttack.UnitClassifications.Contains(UnitClassification.ArmyUnit) || bestOutOfRangeAttack.UnitClassifications.Contains(UnitClassification.DefensiveStructure))) { commander.BestTarget = bestOutOfRangeAttack; return(bestOutOfRangeAttack); } if (bestAttack == null) { bestAttack = bestOutOfRangeAttack; } } if (commander.UnitCalculation.Unit.Health < 6) { return(null); } if (attacks.Count > 0) { var bestOutOfRangeAttack = GetBestTargetFromList(commander, attacks, existingAttackOrder); if (bestOutOfRangeAttack != null && (bestOutOfRangeAttack.UnitClassifications.Contains(UnitClassification.ArmyUnit) || bestOutOfRangeAttack.UnitClassifications.Contains(UnitClassification.DefensiveStructure))) { commander.BestTarget = bestOutOfRangeAttack; return(bestOutOfRangeAttack); } if (bestAttack == null) { bestAttack = bestOutOfRangeAttack; } } if (!MapDataService.SelfVisible(target)) // if enemy main is unexplored, march to enemy main { var fakeMainBase = new Unit(commander.UnitCalculation.Unit); fakeMainBase.Pos = new Point { X = target.X, Y = target.Y, Z = 1 }; fakeMainBase.Alliance = Alliance.Enemy; return(new UnitCalculation(fakeMainBase, 0, SharkyUnitData, SharkyOptions, UnitDataService, frame)); } var unitsNearEnemyMain = ActiveUnitData.EnemyUnits.Values.Where(e => e.Unit.UnitType != (uint)UnitTypes.ZERG_LARVA && InRange(new Vector2(target.X, target.Y), e.Position, 20)); if (unitsNearEnemyMain.Count() > 0 && InRange(new Vector2(target.X, target.Y), commander.UnitCalculation.Position, 100)) { attacks = new List <UnitCalculation>(); // enemies in the main enemy base foreach (var enemyAttack in unitsNearEnemyMain) { if (enemyAttack.Unit.DisplayType == DisplayType.Visible && DamageService.CanDamage(commander.UnitCalculation, enemyAttack)) { attacks.Add(enemyAttack); } } if (attacks.Count > 0) { var bestMainAttack = GetBestTargetFromList(commander, attacks, existingAttackOrder); if (bestMainAttack != null && (bestMainAttack.UnitClassifications.Contains(UnitClassification.ArmyUnit) || bestMainAttack.UnitClassifications.Contains(UnitClassification.DefensiveStructure))) { commander.BestTarget = bestMainAttack; return(bestMainAttack); } if (bestAttack == null) { bestAttack = bestMainAttack; } } } commander.BestTarget = bestAttack; return(bestAttack); }
protected override bool WeaponReady(UnitCommander commander) { return(commander.UnitCalculation.Unit.BuffIds.Contains((uint)Buffs.ORACLEWEAPON)); }
// TODO: regular range is 8, but leash range is 14 protected override bool WeaponReady(UnitCommander commander) { return(commander.UnitCalculation.Unit.WeaponCooldown == 0 || commander.UnitCalculation.Unit.Orders.Any(o => o.AbilityId == (uint)Abilities.ATTACK || o.AbilityId == (uint)Abilities.ATTACK_ATTACK)); }
public override IEnumerable <Action> OnFrame(ResponseObservation observation) { //var total = new Stopwatch(); //total.Start(); //var stopwatch = new Stopwatch(); //stopwatch.Start(); var frame = (int)observation.Observation.GameLoop; if (observation.Observation.RawData.Event != null && observation.Observation.RawData.Event.DeadUnits != null) { ActiveUnitData.DeadUnits = observation.Observation.RawData.Event.DeadUnits.ToList(); } else { ActiveUnitData.DeadUnits = new List <ulong>(); } foreach (var unit in ActiveUnitData.SelfUnits.Where(u => u.Value.Unit.UnitType == (uint)UnitTypes.PROTOSS_DISRUPTORPHASED)) // remove things like purification novas that don't have dead unit events { if (!observation.Observation.RawData.Units.Any(u => u.Tag == unit.Key)) { ActiveUnitData.DeadUnits.Add(unit.Key); } } foreach (var tag in ActiveUnitData.DeadUnits) { if (ActiveUnitData.EnemyUnits.TryRemove(tag, out UnitCalculation removedEnemy)) { ActiveUnitData.EnemyDeaths++; } else if (ActiveUnitData.SelfUnits.TryRemove(tag, out UnitCalculation removedAlly)) { ActiveUnitData.SelfDeaths++; } else if (ActiveUnitData.NeutralUnits.TryRemove(tag, out UnitCalculation removedNeutral)) { ActiveUnitData.NeutralDeaths++; } ActiveUnitData.Commanders.TryRemove(tag, out UnitCommander removedCommander); } foreach (var unit in ActiveUnitData.EnemyUnits.Where(u => UndeadTypes.Contains((UnitTypes)u.Value.Unit.UnitType))) { ActiveUnitData.EnemyUnits.TryRemove(unit.Key, out UnitCalculation removed); } foreach (var unit in ActiveUnitData.SelfUnits.Where(u => UndeadTypes.Contains((UnitTypes)u.Value.Unit.UnitType))) { ActiveUnitData.SelfUnits.TryRemove(unit.Key, out UnitCalculation removed); } foreach (var unit in ActiveUnitData.Commanders.Where(u => UndeadTypes.Contains((UnitTypes)u.Value.UnitCalculation.Unit.UnitType))) { ActiveUnitData.Commanders.TryRemove(unit.Key, out UnitCommander removed); } foreach (var unit in ActiveUnitData.EnemyUnits.Where(u => u.Value.UnitTypeData.Attributes.Contains(SC2APIProtocol.Attribute.Structure))) // structures get replaced by snapshots if we can't see them, so just remove them and let them get readded { ActiveUnitData.EnemyUnits.TryRemove(unit.Key, out UnitCalculation removed); } //Debug.WriteLine($"removal {stopwatch.ElapsedMilliseconds}"); //stopwatch.Restart(); var repairers = observation.Observation.RawData.Units.Where(u => u.UnitType == (uint)UnitTypes.TERRAN_SCV || u.UnitType == (uint)UnitTypes.TERRAN_MULE); //Parallel.ForEach(observation.Observation.RawData.Units, (unit) => //{ // if (unit.Alliance == Alliance.Enemy) // { // var repairingUnitCount = repairers.Where(u => u.Alliance == Alliance.Enemy && Vector2.DistanceSquared(new Vector2(u.Pos.X, u.Pos.Y), new Vector2(unit.Pos.X, unit.Pos.Y)) < (1.0 + u.Radius + unit.Radius) * (0.1 + u.Radius + unit.Radius)).Count(); // var attack = new UnitCalculation(unit, repairingUnitCount, SharkyUnitData, SharkyOptions, UnitDataService, frame); // if (ActiveUnitData.EnemyUnits.TryGetValue(unit.Tag, out UnitCalculation existing)) // { // attack.SetPreviousUnit(existing, existing.FrameLastSeen); // } // ActiveUnitData.EnemyUnits[unit.Tag] = attack; // } // else if (unit.Alliance == Alliance.Self) // { // var attack = new UnitCalculation(unit, 0, SharkyUnitData, SharkyOptions, UnitDataService, frame); // if (ActiveUnitData.SelfUnits.TryGetValue(unit.Tag, out UnitCalculation existing)) // { // attack.SetPreviousUnit(existing, existing.FrameLastSeen); // } // ActiveUnitData.SelfUnits[unit.Tag] = attack; // } // else if (unit.Alliance == Alliance.Neutral) // { // var attack = new UnitCalculation(unit, 0, SharkyUnitData, SharkyOptions, UnitDataService, frame); // if (ActiveUnitData.NeutralUnits.TryGetValue(unit.Tag, out UnitCalculation existing)) // { // attack.SetPreviousUnit(existing, existing.FrameLastSeen); // } // ActiveUnitData.NeutralUnits[unit.Tag] = attack; // } //}); foreach (var unit in observation.Observation.RawData.Units) { if (unit.Alliance == Alliance.Enemy) { var repairingUnitCount = repairers.Where(u => u.Alliance == Alliance.Enemy && Vector2.DistanceSquared(new Vector2(u.Pos.X, u.Pos.Y), new Vector2(unit.Pos.X, unit.Pos.Y)) < (1.0 + u.Radius + unit.Radius) * (0.1 + u.Radius + unit.Radius)).Count(); var attack = new UnitCalculation(unit, repairingUnitCount, SharkyUnitData, SharkyOptions, UnitDataService, frame); if (ActiveUnitData.EnemyUnits.TryGetValue(unit.Tag, out UnitCalculation existing)) { attack.SetPreviousUnit(existing, existing.FrameLastSeen); } ActiveUnitData.EnemyUnits[unit.Tag] = attack; } else if (unit.Alliance == Alliance.Self) { var attack = new UnitCalculation(unit, 0, SharkyUnitData, SharkyOptions, UnitDataService, frame); if (ActiveUnitData.SelfUnits.TryGetValue(unit.Tag, out UnitCalculation existing)) { attack.SetPreviousUnit(existing, existing.FrameLastSeen); } ActiveUnitData.SelfUnits[unit.Tag] = attack; } else if (unit.Alliance == Alliance.Neutral) { var attack = new UnitCalculation(unit, 0, SharkyUnitData, SharkyOptions, UnitDataService, frame); if (ActiveUnitData.NeutralUnits.TryGetValue(unit.Tag, out UnitCalculation existing)) { attack.SetPreviousUnit(existing, existing.FrameLastSeen); } ActiveUnitData.NeutralUnits[unit.Tag] = attack; } } //Debug.WriteLine($"parallel {stopwatch.ElapsedMilliseconds}"); //stopwatch.Restart(); foreach (var enemy in ActiveUnitData.EnemyUnits.Select(e => e.Value).ToList()) // if we can see this area of the map and the unit isn't there anymore remove it (we just remove it because visible units will get re-added below) { if (enemy.FrameLastSeen != frame && MapDataService.SelfVisible(enemy.Unit.Pos)) { ActiveUnitData.EnemyUnits.TryRemove(enemy.Unit.Tag, out UnitCalculation removed); } } //Debug.WriteLine($"remove vision {stopwatch.ElapsedMilliseconds}"); //stopwatch.Restart(); foreach (var allyAttack in ActiveUnitData.SelfUnits) { foreach (var enemyAttack in ActiveUnitData.EnemyUnits) { if (DamageService.CanDamage(allyAttack.Value, enemyAttack.Value) && Vector2.DistanceSquared(allyAttack.Value.Position, enemyAttack.Value.Position) <= (allyAttack.Value.Range + allyAttack.Value.Unit.Radius + enemyAttack.Value.Unit.Radius) * (allyAttack.Value.Range + allyAttack.Value.Unit.Radius + enemyAttack.Value.Unit.Radius)) { allyAttack.Value.EnemiesInRange.Add(enemyAttack.Value); enemyAttack.Value.EnemiesInRangeOf.Add(allyAttack.Value); } if (DamageService.CanDamage(enemyAttack.Value, allyAttack.Value) && Vector2.DistanceSquared(allyAttack.Value.Position, enemyAttack.Value.Position) <= (enemyAttack.Value.Range + allyAttack.Value.Unit.Radius + enemyAttack.Value.Unit.Radius) * (enemyAttack.Value.Range + allyAttack.Value.Unit.Radius + enemyAttack.Value.Unit.Radius)) { enemyAttack.Value.EnemiesInRange.Add(allyAttack.Value); allyAttack.Value.EnemiesInRangeOf.Add(enemyAttack.Value); } if (Vector2.DistanceSquared(allyAttack.Value.Position, enemyAttack.Value.Position) <= NearbyDistance * NearbyDistance) { enemyAttack.Value.NearbyEnemies.Add(allyAttack.Value); allyAttack.Value.NearbyEnemies.Add(enemyAttack.Value); } } allyAttack.Value.NearbyAllies = ActiveUnitData.SelfUnits.Where(a => a.Key != allyAttack.Key && Vector2.DistanceSquared(allyAttack.Value.Position, a.Value.Position) <= NearbyDistance * NearbyDistance).Select(a => a.Value).ToList(); var commander = new UnitCommander(allyAttack.Value); ActiveUnitData.Commanders.AddOrUpdate(allyAttack.Value.Unit.Tag, commander, (tag, existingCommander) => { commander = existingCommander; commander.UnitCalculation = allyAttack.Value; return(commander); }); } //Debug.WriteLine($"allyattack {stopwatch.ElapsedMilliseconds}"); //stopwatch.Restart(); foreach (var enemyAttack in ActiveUnitData.EnemyUnits) { enemyAttack.Value.NearbyAllies = ActiveUnitData.EnemyUnits.Where(a => a.Key != enemyAttack.Key && Vector2.DistanceSquared(enemyAttack.Value.Position, a.Value.Position) <= NearbyDistance * NearbyDistance).Select(a => a.Value).ToList(); } //Debug.WriteLine($"enemyunits {stopwatch.ElapsedMilliseconds}"); //stopwatch.Restart(); if (TargetPriorityCalculationFrame + 10 < frame) { foreach (var selfUnit in ActiveUnitData.SelfUnits) { if (selfUnit.Value.TargetPriorityCalculation == null || selfUnit.Value.TargetPriorityCalculation.FrameCalculated + 10 < frame) { var priorityCalculation = TargetPriorityService.CalculateTargetPriority(selfUnit.Value, frame); selfUnit.Value.TargetPriorityCalculation = priorityCalculation; foreach (var nearbyUnit in selfUnit.Value.NearbyAllies.Where(a => a.NearbyEnemies.Count() == selfUnit.Value.NearbyAllies.Count())) { nearbyUnit.TargetPriorityCalculation = priorityCalculation; } } selfUnit.Value.Attackers = GetTargettedAttacks(selfUnit.Value).ToList(); } TargetPriorityCalculationFrame = frame; } //foreach (var selfUnit in ActiveUnitData.SelfUnits) //{ // if (selfUnit.Value.TargetPriorityCalculation == null || selfUnit.Value.TargetPriorityCalculation.FrameCalculated + 10 < frame) // { // var priorityCalculation = TargetPriorityService.CalculateTargetPriority(selfUnit.Value, frame); // selfUnit.Value.TargetPriorityCalculation = priorityCalculation; // foreach (var nearbyUnit in selfUnit.Value.NearbyAllies) // { // nearbyUnit.TargetPriorityCalculation = priorityCalculation; // } // } // selfUnit.Value.Attackers = GetTargettedAttacks(selfUnit.Value).ToList(); //} //Debug.WriteLine($"selfunits {stopwatch.ElapsedMilliseconds}"); //stopwatch.Restart(); if (SharkyOptions.Debug) { foreach (var selfUnit in ActiveUnitData.SelfUnits) { DebugService.DrawLine(selfUnit.Value.Unit.Pos, new Point { X = selfUnit.Value.End.X, Y = selfUnit.Value.End.Y, Z = selfUnit.Value.Unit.Pos.Z + 1f }, new SC2APIProtocol.Color { R = 0, B = 0, G = 255 }); } foreach (var enemyUnit in ActiveUnitData.EnemyUnits) { DebugService.DrawLine(enemyUnit.Value.Unit.Pos, new Point { X = enemyUnit.Value.End.X, Y = enemyUnit.Value.End.Y, Z = enemyUnit.Value.Unit.Pos.Z + 1f }, new SC2APIProtocol.Color { R = 255, B = 0, G = 0 }); } } //stopwatch.Stop(); //Debug.WriteLine($"debug {stopwatch.ElapsedMilliseconds}"); //total.Stop(); //Debug.WriteLine($"total {total.ElapsedMilliseconds}"); //if (total.ElapsedMilliseconds > 15) //{ // var uhoh = true; //} //Debug.WriteLine($""); return(null); }
protected override bool OffensiveAbility(UnitCommander commander, Point2D target, Point2D defensivePoint, Point2D groupCenter, UnitCalculation bestTarget, int frame, out List <SC2APIProtocol.Action> action) { action = null; if (!commander.AbilityOffCooldown(Abilities.EFFECT_PURIFICATIONNOVA, frame, SharkyOptions.FramesPerSecond, SharkyUnitData)) { return(false); } if (commander.UnitCalculation.NearbyAllies.Any(a => a.Unit.UnitType == (uint)UnitTypes.PROTOSS_DISRUPTORPHASED && Vector2.DistanceSquared(a.Position, commander.UnitCalculation.Position) < PurificationNovaRange * PurificationNovaRange)) { return(false); } if (lastPurificationFrame >= frame - 5) { return(false); } var attacks = new List <UnitCalculation>(); var center = commander.UnitCalculation.Position; foreach (var enemyAttack in commander.UnitCalculation.NearbyEnemies) { if (!enemyAttack.Unit.IsFlying && InRange(enemyAttack.Position, commander.UnitCalculation.Position, PurificationNovaRange + enemyAttack.Unit.Radius + commander.UnitCalculation.Unit.Radius)) // TODO: do actual pathing to see if the shot can make it there, if a wall is in the way it can't { attacks.Add(enemyAttack); } } if (attacks.Count > 0) { var oneShotKills = attacks.OrderBy(a => GetPurificationNovaDamage(a.Unit, SharkyUnitData.UnitData[(UnitTypes)a.Unit.UnitType])).ThenByDescending(u => u.Dps); if (oneShotKills.Count() > 0) { var bestAttack = GetBestAttack(commander.UnitCalculation, oneShotKills, attacks); if (commander.UnitCalculation.TargetPriorityCalculation.TargetPriority == TargetPriority.WinAir) { var airAttackers = oneShotKills.Where(u => u.DamageAir); if (airAttackers.Count() > 0) { var air = GetBestAttack(commander.UnitCalculation, airAttackers, attacks); if (air != null) { bestAttack = air; } } } else if (commander.UnitCalculation.TargetPriorityCalculation.TargetPriority == TargetPriority.WinGround) { var groundAttackers = oneShotKills.Where(u => u.DamageGround); if (groundAttackers.Count() > 0) { var ground = GetBestAttack(commander.UnitCalculation, groundAttackers, attacks); if (ground != null) { bestAttack = ground; } } } else { if (oneShotKills.Count() > 0) { var any = GetBestAttack(commander.UnitCalculation, oneShotKills, attacks); if (any != null) { bestAttack = any; } } } if (bestAttack != null) { action = commander.Order(frame, Abilities.EFFECT_PURIFICATIONNOVA, bestAttack); lastPurificationFrame = frame; 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); } }
UnitCalculation GetBestHarassTarget(UnitCommander commander, Point2D target) { var existingAttackOrder = commander.UnitCalculation.Unit.Orders.Where(o => o.AbilityId == (uint)Abilities.ATTACK || o.AbilityId == (uint)Abilities.ATTACK_ATTACK).FirstOrDefault(); var range = commander.UnitCalculation.Range; var attacks = new List <UnitCalculation>(commander.UnitCalculation.EnemiesInRange.Where(u => u.Unit.DisplayType != DisplayType.Hidden && u.UnitClassifications.Contains(UnitClassification.Worker))); // units that are in range right now UnitCalculation bestAttack = null; if (attacks.Count > 0) { var oneShotKills = attacks.Where(a => a.Unit.Health + a.Unit.Shield < GetDamage(commander.UnitCalculation.Weapon, a.Unit, a.UnitTypeData)); if (oneShotKills.Count() > 0) { if (existingAttackOrder != null) { var existing = oneShotKills.FirstOrDefault(o => o.Unit.Tag == existingAttackOrder.TargetUnitTag); if (existing != null) { return(existing); // just keep attacking the same unit } } var oneShotKill = GetBestTargetFromList(commander, oneShotKills, existingAttackOrder); if (oneShotKill != null) { return(oneShotKill); } else { commander.BestTarget = oneShotKills.OrderBy(o => o.Dps).FirstOrDefault(); return(commander.BestTarget); } } bestAttack = GetBestTargetFromList(commander, attacks, existingAttackOrder); if (bestAttack != null && bestAttack.UnitClassifications.Contains(UnitClassification.Worker) && bestAttack.EnemiesInRange.Any(e => e.Unit.Tag == commander.UnitCalculation.Unit.Tag)) { commander.BestTarget = bestAttack; return(bestAttack); } } attacks = new List <UnitCalculation>(); // nearby units not in range right now foreach (var enemyAttack in commander.UnitCalculation.NearbyEnemies) { if (enemyAttack.Unit.DisplayType != DisplayType.Hidden && enemyAttack.UnitClassifications.Contains(UnitClassification.Worker) && !InRange(enemyAttack.Unit.Pos, commander.UnitCalculation.Unit.Pos, range + enemyAttack.Unit.Radius + commander.UnitCalculation.Unit.Radius)) { attacks.Add(enemyAttack); } } if (attacks.Count > 0) { var bestOutOfRangeAttack = GetBestTargetFromList(commander, attacks, existingAttackOrder); if (bestOutOfRangeAttack != null && (bestOutOfRangeAttack.UnitClassifications.Contains(UnitClassification.ArmyUnit) || bestOutOfRangeAttack.UnitClassifications.Contains(UnitClassification.DefensiveStructure))) { commander.BestTarget = bestOutOfRangeAttack; return(bestOutOfRangeAttack); } if (bestAttack == null) { bestAttack = bestOutOfRangeAttack; } } commander.BestTarget = bestAttack; return(bestAttack); }
// TODO: when retreating cancel prismatic alignment protected override bool WeaponReady(UnitCommander commander) { return(true); }
public override List <SC2APIProtocol.Action> Retreat(UnitCommander commander, Point2D defensivePoint, Point2D groupCenter, int frame) { return(Attack(commander, defensivePoint, defensivePoint, groupCenter, frame)); }
protected override bool WeaponReady(UnitCommander commander) { return(commander.UnitCalculation.Unit.WeaponCooldown < 5 || commander.UnitCalculation.Unit.WeaponCooldown > 15); // a zealot has 2 attacks, so we do this because after one attack the cooldown starts over instead of both }
public LevelManagement(ICommanderFactory factory) { _enemyUnits = factory.CreateEnemyCommander(); _playerUnits = factory.CreatePlayerCommander(); }