public void TryAttackEnemy() { LivingUnit nearestTarget = getNearestTarget(); // Если видим противника ... if (nearestTarget != null) { double distance = GetDistanceTo(nearestTarget); // ... и он в пределах досягаемости наших заклинаний, ... if (distance <= CastRange) { double angle = GetAngleTo(nearestTarget); // ... то поворачиваемся к цели. _move.Turn = angle; // Если цель перед нами, ... if (Math.Abs(angle) < _game.StaffSector / 2.0D) { // ... то атакуем. _move.Action = ChoseBestAttackMethod();; _move.CastAngle = angle; _move.MinCastDistance = distance - nearestTarget.Radius + _game.MagicMissileRadius; } return; } } }
private void FindBuildingTarget(LivingUnit unit, Building buildingUnit, double attackRange, int maxDamage, List <LivingUnit> p1Units, List <LivingUnit> p2Units) { if ((unit.Faction == Faction.Academy || unit.Faction == Faction.Renegades) && unit.Faction != buildingUnit.Faction && unit.GetDistanceTo(buildingUnit) <= attackRange) { if (unit.Life >= maxDamage) { if (p1Units.Count == 0 || unit.Life < p1Units[0].Life) { p1Units.Clear(); p1Units.Add(unit); } else if (unit.Life == p1Units[0].Life) { p1Units.Add(unit); } } else { if (p2Units.Count == 0 || unit.Life < p2Units[0].Life) { p2Units.Clear(); p2Units.Add(unit); } else if (unit.Life == p2Units[0].Life) { p2Units.Add(unit); } } } }
public LivingUnit getTartgetwithHigestPriority(World world, Wizard self, Game game) { LivingUnit restarget = null; double maxPriority = Double.MinValue; var targets = getTargets(world, self); foreach (var target in targets) { double distance = GetDistance(self.X, self.Y, target.X, target.Y); if (distance < game.WizardCastRange) { double targetpriority = game.WizardCastRange / distance * DistanceK;// + (double)target.MaxLife / (target.Life * target.Life) * HealthK; if (target.Life < CRITICAL_ENEMY_HEALTH_POROG) { targetpriority += FATALITY_PRIORITY_BONUS; if (target is Wizard) { targetpriority *= FATALITY_WIZARD_K; } } if (targetpriority > maxPriority) { restarget = target; maxPriority = targetpriority; } } } return(restarget); }
/// <summary> /// Возвращает ближайшую союзную постройку /// </summary> /// <param name="world">Игровой мир</param> /// <param name="self">Собственный маг</param> /// <returns></returns> private LivingUnit getNearestBuilding(World world, Wizard self) { List <LivingUnit> targetsBuilding = new List <LivingUnit>(); foreach (LivingUnit element in world.Buildings) { targetsBuilding.AddRange(world.Buildings); } LivingUnit nearestBuilding = null; double nearestBuildingDistance = double.MaxValue; foreach (LivingUnit targetBuilding in targetsBuilding) { if (targetBuilding.Faction == Faction.Neutral || targetBuilding.Faction != self.Faction) { continue; } double distance = self.GetDistanceTo(targetBuilding); if (distance < nearestBuildingDistance) { nearestBuilding = targetBuilding; nearestBuildingDistance = distance; } } return(nearestBuilding); }
/** * Находим ближайшую цель для атаки, независимо от её типа и других характеристик. */ private LivingUnit GetNearestTarget() { List <LivingUnit> targets = new List <LivingUnit>(); targets.AddRange(_myWorld.Buildings); targets.AddRange(_myWorld.Wizards); targets.AddRange(_myWorld.Minions); LivingUnit nearestTarget = null; double nearestTargetDistance = Double.MaxValue; foreach (LivingUnit target in targets) { if (target.Faction == Faction.Neutral || target.Faction == _myWizard.Faction) { continue; } double distance = _myWizard.GetDistanceTo(target); if (distance < nearestTargetDistance) { nearestTarget = target; nearestTargetDistance = distance; } } return(nearestTarget); }
/// <summary> /// Выбор тактических приемов /// </summary> /// <param name="world">Игровой мир</param> /// <param name="game">Константы игры</param> /// <param name="self">Собственный маг</param> /// <param name="move">Управление магом</param> /// <returns>Объект-движение</returns> // Добавил move, в который мы будем присваивать дополнительное движение. public Move getTacticMove(World world, Game game, Wizard self, Move move) { if ((IsZalip(world, game, self, move)) || (self.GetDistanceTo(ZalipP.getX(), ZalipP.getY()) < controlZalipDistance)) { move.Speed = game.WizardBackwardSpeed; } LivingUnit target = getTartgetwithHigestPriority(world, self, game); getRocket(world, game, self, target, move); Point2D enemybase = GetEnemyBase(self); if (GetDistance(self.X, self.Y, enemybase.getX(), enemybase.getY()) < obxoddist) { BaseObxod(world, game, self, move, target, 30D); } else { Otstup(world, game, self, move); } if (((double)self.Life / self.MaxLife <= CRITICAL_LIFE_POROG) && (target != null)) { LowHealthCheck(world, game, self, move); //move.Speed = -game.WizardBackwardSpeed; } return(move); //return new Move(); }
public bool IsBurning; // пока только для отображения в визуализаторе protected ACombatUnit(LivingUnit unit) : base(unit) { IsTeammate = unit.Faction == MyStrategy.Self.Faction; Life = unit.Life; MaxLife = unit.MaxLife; var wizard = unit as Wizard; if (wizard != null) { VisionRange = wizard.VisionRange; CastRange = wizard.CastRange; RemainingActionCooldownTicks = wizard.RemainingActionCooldownTicks; } var building = unit as Building; if (building != null) { VisionRange = building.VisionRange; CastRange = building.AttackRange; RemainingActionCooldownTicks = building.RemainingActionCooldownTicks; } var minion = unit as Minion; if (minion != null) { VisionRange = minion.VisionRange; if (minion.Type == MinionType.FetishBlowdart) { CastRange = MyStrategy.Game.FetishBlowdartAttackRange; } RemainingActionCooldownTicks = minion.RemainingActionCooldownTicks; } foreach (var status in unit.Statuses) { switch (status.Type) { case StatusType.Empowered: RemainingEmpowered = Math.Max(RemainingEmpowered, status.RemainingDurationTicks); break; case StatusType.Frozen: RemainingFrozen = Math.Max(RemainingFrozen, status.RemainingDurationTicks); break; case StatusType.Shielded: RemainingShielded = Math.Max(RemainingShielded, status.RemainingDurationTicks); break; case StatusType.Hastened: RemainingHastened = Math.Max(RemainingHastened, status.RemainingDurationTicks); break; case StatusType.Burning: IsBurning = true; break; } } }
void AttackUnit(LivingUnit target) { double angle = self.GetAngleTo(target); move.Turn = angle; move.Action = ActionType.MagicMissile; move.CastAngle = angle; move.MinCastDistance = self.GetDistanceTo(target) - target.Radius + game.MagicMissileRadius; }
public static void AtackTarget(LivingUnit target) { double distance = Tick.Self.GetDistanceTo(target); // ... и он в пределах досягаемости наших заклинаний, ... if (distance <= Tick.Self.CastRange + target.Radius) { double angle = Tick.Self.GetAngleTo(target); // ... то поворачиваемся к цели. Tick.Move.Turn = angle; // Если цель перед нами, ... if (Math.Abs(angle) < Tick.Game.StaffSector / 2.0D) { if (distance - target.Radius <= Tick.Game.StaffRange) { // ... то атакуем с руки. Tick.Move.Action = ActionType.Staff; Tick.Move.CastAngle = angle; Tick.Move.MinCastDistance = distance - target.Radius + Tick.Game.MagicMissileRadius; } else { if (target is Wizard) { var canCastFrostbolt = Tick.Self.Skills.Any(x => x == SkillType.FrostBolt) && Tick.Self.RemainingActionCooldownTicks == 0 && Tick.Self.RemainingCooldownTicksByAction[(int)ActionType.FrostBolt] == 0; var canCastFireball = Tick.Self.Skills.Any(x => x == SkillType.Fireball) && Tick.Self.RemainingActionCooldownTicks == 0 && Tick.Self.RemainingCooldownTicksByAction[(int)ActionType.Fireball] == 0; if (canCastFrostbolt) { Tick.Move.Action = ActionType.FrostBolt; } else if (canCastFireball) { Tick.Move.Action = ActionType.Fireball; } else { Tick.Move.Action = ActionType.MagicMissile; } } else { Tick.Move.Action = ActionType.MagicMissile; } Tick.Move.CastAngle = angle; Tick.Move.MinCastDistance = distance - target.Radius + Tick.Game.MagicMissileRadius; } } } }
/// <summary> /// Определение расстояния до ближайшего врага /// </summary> /// <param name="world">Игровой мир</param> /// <param name="self">Собственный маг</param> /// <returns>Если врагов нет, то возвращает ширину игрового мира</returns> public double getNearestTargetDistance(World world, Wizard self) { LivingUnit target = getNearlestTarget(world, self); double distance = world.Width; if (target != null) { distance = GetDistance(self.X, self.Y, target.X, target.Y); } return(distance); }
public async Task <IActionResult> OnGetAsync(int id) { LivingUnit = await _context.LivingUnits .Include(x => x.Building) .Include(x => x.Persons) .FirstAsync(x => x.LivingUnitId == id); if (LivingUnit == null) { return(new NotFoundResult()); } return(Page()); }
/** * Основной метод стратегии, осуществляющий управление волшебником. * Вызывается каждый тик для каждого волшебника. * * @param self Волшебник, которым данный метод будет осуществлять управление. * @param world Текущее состояние мира. * @param game Различные игровые константы. * @param move Результатом работы метода является изменение полей данного объекта. */ public void Move(Wizard self, World world, Game game, Move move) { InitializeStrategy(self, game); InitializeTick(self, world, game, move); PaintGeneralInfo(self, world, game); p.PaintWayPoints(waypoints.Select(x => new Vector2f((float)x.GetX(), (float)x.GetY())).ToArray()); // Постоянно двигаемся из-стороны в сторону, чтобы по нам было сложнее попасть. // Считаете, что сможете придумать более эффективный алгоритм уклонения? Попробуйте! ;) move.StrafeSpeed = (random.Next(2) == 1) ? game.WizardStrafeSpeed : -game.WizardStrafeSpeed; // Если осталось мало жизненной энергии, отступаем к предыдущей ключевой точке на линии. if (self.Life < self.MaxLife * LOW_HP_FACTOR) { GoTo(GetPreviousWaypoint()); return; } LivingUnit nearestTarget = GetNearestTarget(); // Если видим противника ... if (nearestTarget != null) { double distance = self.GetDistanceTo(nearestTarget); // ... и он в пределах досягаемости наших заклинаний, ... if (distance <= self.CastRange) { double angle = self.GetAngleTo(nearestTarget); // ... то поворачиваемся к цели. move.Turn = angle; // Если цель перед нами, ... if (Math.Abs(angle) < game.StaffSector / 2.0D) { // ... то атакуем. move.Action = ActionType.MagicMissile; move.CastAngle = angle; move.MinCastDistance = (distance - nearestTarget.Radius + game.MagicMissileRadius); } return; } } // Если нет других действий, просто продвигаемся вперёд. GoTo(GetNextWaypoint()); }
public void BaseObxod(World world, Game game, Wizard self, Move move, LivingUnit enemy, double dist) { Point2D enemybase = GetEnemyBase(self); move.Turn = self.GetAngleTo(self.X, self.Y); move.StrafeSpeed = -5.0D; //if(50>GetDistance(self.X,self.Y,400,3600)) //{ // move.Speed = 2.0D; //} //else //{ // move.Speed = -2.0D; //} }
// //******************************************************************************************************************************************************************************************* //Некое разделение областей работы. Ниже будут описаны действия, используемые в тактике. // //Простейший запуск ракеты в заданного противника. Переписан с офсайта. //targetUnit здесь - цель, которую выбрали для атаки. //World, Game добавил на всякий случай. Могут пригодиться. /// <summary> /// Совершает выстрел в заданного протиыника /// </summary> /// <param name="world">Игровой мир</param> /// <param name="game">Константы игры</param> /// <param name="self">Собственный маг</param> /// <param name="targetUnit">Выбранная цель</param> /// <param name="move">Управление магом</param> public void getRocket(World world, Game game, Wizard self, LivingUnit targetUnit, Move move) { if (targetUnit != null) { if (self.GetDistanceTo(targetUnit) <= self.CastRange) { double angle = self.GetAngleTo(targetUnit); move.Turn = angle; move.Speed = 0; if (Math.Abs(angle) <= self.VisionRange) { move.Action = ActionType.MagicMissile; move.CastAngle = angle; move.MinCastDistance = self.GetDistanceTo(targetUnit) + self.Radius - targetUnit.Radius; } } } }
protected virtual void OnTriggerEnter2D(Collider2D collider) // 유닛 충돌함수을 유닛스크립트로 따로 관리 { LivingUnit targetUnit = collider.GetComponent <LivingUnit>(); if (targetUnit == null) { return; } if (targetUnit.colliderForTrigger == null) { if (targetUnit.GetComponent <Collider2D>() == null) { return; } targetUnit.colliderForTrigger = targetUnit.GetComponent <Collider2D>(); } if (targetUnit.colliderForTrigger != collider) { return; } UnitType targetType = targetUnit.type; if (type == UnitType.ALLY_BULLET && targetType == UnitType.ENEMY_LIVING_UNIT) { //아군 총알이 적유닛에 충돌 CollisionProcess(targetUnit); } if (type == UnitType.ENEMY_BULLET && targetType == UnitType.ALLY_LIVING_UNIT) { //적 총알이 아군 유닛에 충돌 CollisionProcess(targetUnit); } if (type == UnitType.ENEMY_LIVING_UNIT && targetType == UnitType.ALLY_LIVING_UNIT) {//적 유닛이 아군 유닛에 충돌 CollisionProcess(targetUnit); } }
public virtual void CollisionProcess(LivingUnit targetUnit) { if (targetUnit is PlayerScript == true) { PlayerScript player = targetUnit as PlayerScript; if (player.IsImmune == true) { return; } else { player.IsImmune = true; } } Shield shield = targetUnit.GetComponent <Shield>(); if (shield != null) { if (shield.ShieldEnable == true) { shield.ShieldEnable = false; if (type == UnitType.ALLY_BULLET || type == UnitType.ENEMY_BULLET) { Destroy(gameObject); } return; } } // target 의 체력 감소 // 충돌시이펙트 추가예정 targetUnit.CurrentHP -= damage; if (type == UnitType.ALLY_BULLET || type == UnitType.ENEMY_BULLET) { Destroy(gameObject); } }
private void OnWorldUpdated(object sender, EventArgs e) { Visualizer.Init(extendedRunnerModel.World.TickIndex); // prepare visual part before drawing foreach (var unit in extendedRunnerModel.CurrentBuildings) { if (unit.Value.IsUnion(extendedRunnerModel.Me)) { Visualizer.AddVisibleArea(unit.Value.X, unit.Value.Y, unit.Value.VisionRange); } } foreach (var unit in extendedRunnerModel.CurrentWizards) { if (targetUnitId == unit.Value.Id) { targetUnit = unit.Value; } if (unit.Value.IsUnion(extendedRunnerModel.Me)) { Visualizer.AddVisibleArea(unit.Value.X, unit.Value.Y, unit.Value.VisionRange); } } foreach (var unit in extendedRunnerModel.CurrentMinions) { if (targetUnitId == unit.Value.Id) { targetUnit = unit.Value; } if (unit.Value.IsUnion(extendedRunnerModel.Me)) { Visualizer.AddVisibleArea(unit.Value.X, unit.Value.Y, unit.Value.VisionRange); } } foreach (var unit in extendedRunnerModel.World.Trees) { Visualizer.AddTree(unit.X, unit.Y, unit.Radius); } }
public void Otstup(World world, Game game, Wizard self, Move move) { LivingUnit vrag = getNearlestTarget(world, self); if (vrag != null) { double d = self.GetDistanceTo(vrag); if (self.GetDistanceTo(vrag) <= MIN_VRAG_DISTANCE) { double angle = self.GetAngleTo(vrag); move.Turn = angle; if (angle == 0) { move.Action = ActionType.Staff; move.CastAngle = 0; //move.Speed = -game.WizardBackwardSpeed; LowHealthCheck(world, game, self, move); } } } }
/// <summary> /// Посик ближайшего врага /// </summary> /// <param name="world">Игровой мир</param> /// <param name="self">Собственный маг</param> /// <returns>Ближайший враг</returns> public LivingUnit getNearlestTarget(World world, Wizard self) { double mindist = double.MaxValue; List <LivingUnit> targets = getTargets(world, self); LivingUnit target = null; foreach (var elem in targets) { double distance = GetDistance(self.X, self.Y, elem.X, elem.Y); if (distance < mindist) { mindist = distance; target = elem; } } //if (targetwizard != null) { return targetwizard; } return(target); }
public LivingUnit getNearlestTarget(List <LivingUnit> targets, Wizard self)//Подразумевается, что в коллекции идут элементы последоваттельно:волшебники, башни, миньоны { double mindist = double.MaxValue; LivingUnit target = null; foreach (var elem in targets) { double distance = GetDistance(self.X, self.Y, elem.X, elem.Y); if (distance < mindist) { mindist = distance; target = elem; } } //if (targetwizard != null) { return targetwizard; } return(target); }
/// <summary> /// Метод возвращает ближайшую вражескую цель для атаки /// </summary> /// <param name="world">Игровой мир</param> /// <param name="self">Собственный маг</param> /// <returns>Живой юнит для атаки</returns> private LivingUnit getNearestTarget(World world, Wizard self) { List <LivingUnit> targets = new List <LivingUnit>(); foreach (LivingUnit element in world.Buildings) { targets.AddRange(world.Buildings); } foreach (LivingUnit element in world.Wizards) { targets.AddRange(world.Wizards); } foreach (LivingUnit element in world.Minions) { targets.AddRange(world.Minions); } LivingUnit nearestTarget = null; double nearestTargetDistance = double.MaxValue; foreach (LivingUnit target in targets) { if (target.Faction == Faction.Neutral || target.Faction == self.Faction) { continue; } double distance = self.GetDistanceTo(target); if (distance < nearestTargetDistance) { nearestTarget = target; nearestTargetDistance = distance; } } return(nearestTarget); }
/// <summary> /// Получить цель для атаки /// </summary> /// <param name="range"></param> /// <returns></returns> private static LivingUnit GetOptimalTargetToAtack(double range) { LivingUnit targetToAtack = null; var nearestEnemyWizards = UnitHelper.GetNearestWizards(range, false, GetObjectRangeMode.CenterToTargetBorder); if (nearestEnemyWizards.Count > 0) { targetToAtack = nearestEnemyWizards.OrderBy(x => x.Life).FirstOrDefault(); } else { var nearestEnemyBuidings = UnitHelper.GetNearestBuidigs(range, false, GetObjectRangeMode.CenterToTargetBorder, canAttack: true); if (nearestEnemyBuidings.Count > 0) { targetToAtack = nearestEnemyBuidings .OrderBy(x => x.Type == BuildingType.FactionBase ? 0 : 1) .ThenBy(x => x.Life) .FirstOrDefault(); } else { var nearestEnemyMinions = UnitHelper.GetNearestMinions(range, false, GetObjectRangeMode.CenterToTargetBorder) .RemoveNonAgressiveNeutrals(); if (nearestEnemyMinions.Count > 0) { targetToAtack = nearestEnemyMinions.OrderBy(x => x.Life).FirstOrDefault(); } } } return(targetToAtack); }
private int lineType = -1; //линия игры нашего мага /*public Strat() * { * * } * public Strat(Wizard self) * { * switch ((int)self.Id)//если наш айди * { * case 1: * case 2: * case 6: * case 7: * lineType = 1; //то линия - топ * break; * case 3: * case 8: * lineType = 2; //то линия - мид * break; * case 4: * case 5: * case 9: * case 10: * lineType = 3; //то линия - боттом * break; * } * }*/ /// <summary> /// Возвращает координаты самой важной зоны /// </summary> /// <param name="world">Игровой мир</param> /// <param name="game">Константы игры</param> /// <param name="self">Собственный маг</param> /// <returns>Точка на двухмерной карте</returns> public Point2D getHotZone(World world, Game game, Wizard self) { Point2D HotZone = new Point2D(); double lowHPFactor = 0.3D; LivingUnit nearestTarget = getNearestTarget(world, self); LivingUnit nearestBuilding = getNearestBuilding(world, self); Point2D myBase = getMyBase(self); Point2D enemyBase = getEnemyBase(self); if (self.Life > self.MaxLife * lowHPFactor) //если у нас достаточно ХП { if (lineType < 0) //если линия еще не выбрана, то выбираем ее по айди { switch ((int)self.Id) //если наш айди { case 1: case 2: case 6: case 7: lineType = 1; //то линия - топ break; case 3: case 8: lineType = 2; //то линия - мид break; case 4: case 5: case 9: case 10: lineType = 3; //то линия - боттом break; } } switch (lineType)//выбираем координаты по нашей линии { case 3: HotZone = new Point2D(3700, 3700); //то боттом break; case -1: case 2: HotZone = new Point2D(2000, 2000); //то мид break; case 1: HotZone = new Point2D(300, 300); //то топ break; } double allyBaseDist = self.GetDistanceTo(myBase.getX(), myBase.getY()); //измеряем расстояние до своей базы double enemyBaseDist = self.GetDistanceTo(enemyBase.getX(), enemyBase.getY()); //измеряем расстояние до базы врага if (enemyBaseDist < allyBaseDist) //если до базы врага ближе { HotZone = enemyBase; //то хотзон - база врага } if (self.X < 500 /*&& self.X > 400*/) //если наш икс в диапазоне { if (self.Y < 500 /*&& self.Y > 400*/) //и игрек тоже { HotZone = enemyBase; //то хотзон - база врага lineType = 1; //и наша линия - топ } } if (/*self.X < 3600.0D &&*/ self.X > 3500.0D) //если наш икс в диапазоне { if (/*self.Y < 3600.0D &&*/ self.Y > 3500.0D) //и игрек тоже { HotZone = enemyBase; //то хотзон - база врага lineType = 3; //и наша линия - боттом } } if (self.X < 2350.0D && self.X > 1650.0D) //если наш икс в диапазоне { if (self.Y < 2350.0D && self.Y > 1650.0D) //и игрек тоже { HotZone = enemyBase; //то хотзон - база врага lineType = 2; //и наша линия - мид } } } else { HotZone = myBase; } return(HotZone); }
public void Start() { if (Visualizer != null) { throw new InvalidOperationException("Visualizer is already initialized."); } Visualizer = new SfmlVisualizer(); Visualizer.SetStaticData(this.extendedRunnerModel.Game.LevelUpXpValues.Sum(), this.extendedRunnerModel.Game.LevelUpXpValues.Length); Visualizer.ToggleAudio += (sender, enableAudio) => { if (enableAudio && BackgroundMusic == null) { BackgroundMusic = Audios.PlayBackgroundMusic(); } else if (!enableAudio && BackgroundMusic != null) { BackgroundMusic.Stop(); BackgroundMusic.Dispose(); BackgroundMusic = null; } }; Visualizer.ToggleTargetObserving += (sender, observe) => { targetUnitId = null; targetUnit = null; }; string debugText = ""; Visualizer.LeftMousePressed += (sender, position) => { debugText = string.Format("{0};{1}", position.X, position.Y); Unit nearestUnit = extendedRunnerModel.AllWizards.Values .Cast <LivingUnit>() .Union(extendedRunnerModel.AllBuildings.Values) .Union(extendedRunnerModel.AllMinions.Values) .Select( x => { var distanceTo = x.GetDistanceTo(position.X, position.Y); return(new { Distance = distanceTo > x.Radius * TargetSelectionRadiusK ? (double?)null : distanceTo, Unit = x }); }) .Where(x => x.Distance.HasValue) .OrderBy(x => x.Distance.Value) .Select(x => x.Unit) .FirstOrDefault(); if (nearestUnit != null) { bool canObserve = false; if (nearestUnit is Building) { if (nearestUnit.Faction == Faction.Academy) { if (((Building)nearestUnit).Type == BuildingType.FactionBase) { Audios.Union_Base_Selected(); } else { Audios.Union_Tower_Selected(); } } else if (nearestUnit.Faction == Faction.Renegades) { if (((Building)nearestUnit).Type == BuildingType.FactionBase) { Audios.Enemy_Base_Selected(); } else { Audios.Enemy_Tower_Selected(); } } } else if (nearestUnit is Wizard) { if (nearestUnit.Faction == Faction.Academy) { Audios.Wizard_Selected_Union(); canObserve = true; } else if (nearestUnit.Faction == Faction.Renegades) { Audios.Wizard_Selected_Enemy(); canObserve = true; } } else if (nearestUnit is Minion) { if (nearestUnit.Faction == Faction.Academy) { Audios.Minion_Selected_Union(((Minion)nearestUnit).Type == MinionType.FetishBlowdart); canObserve = true; } else if (nearestUnit.Faction == Faction.Renegades) { Audios.Minion_Selected_Enemy(((Minion)nearestUnit).Type == MinionType.FetishBlowdart); canObserve = true; } } if (canObserve) { targetUnitId = nearestUnit.Id; targetUnit = null; Visualizer.EnableTargetObservation(); } } }; }