bool CheckIntersectionsAndTress(AWizard self, IEnumerable <ACircularUnit> units) { if (self.GetFirstIntersection(units) != null) { return(true); } var nearestTree = TreesObserver.GetNearestTree(self); return(nearestTree != null && self.IntersectsWith(nearestTree)); }
public static double GetSegmentWeight(Point a, Point b, bool checkStart) { var dir = b - a; var res = dir.Length; ATree prev = null; for (var i = (checkStart ? 0 : 1); i <= SegmentDivideParts; i++) { var p = dir * (1.0 * i / SegmentDivideParts) + a; var tree = TreesObserver.GetNearestTree(p); if (tree != null && tree != prev && Geom.SegmentCircleIntersects(a, b, tree, tree.Radius + Const.WizardRadius + MagicConst.RadiusAdditionalEpsilon)) { res += Math.Ceiling(tree.Life / 12) * MagicConst.TreeObstacleWeight; prev = tree; } } return(res); }
public bool Move(Func <AProjectile, bool> check = null) { var prev = new Point(this); var nearestTree = TreesObserver.GetNearestTree(this); for (var i = 0; i < MicroTicks; i++) { if (!Exists) { return(false); } MicroMove(); if (nearestTree != null && GetDistanceTo2(nearestTree) <= Math.Sqrt(Radius + nearestTree.Radius)) { // снаряд ударился об дерево RemainingDistance = 0; return(false); } if (!Exists) { return(false); } if (check != null && !check(this)) { return(false); } } if (nearestTree != null && Geom.SegmentCircleIntersects(prev, this, nearestTree, nearestTree.Radius + Radius)) { // снаряд ударился об дерево (это более точная проверка) RemainingDistance = 0; return(false); } return(true); }
private List <ProjectilePathSegment> _emulate(ACombatUnit[] nearestUnits, double wizardsChangeAngle, TargetsSelector minionsTargetsSelector) { if (Type != ProjectileType.MagicMissile && Type != ProjectileType.FrostBolt && Type != ProjectileType.Fireball) { throw new Exception("Unsupported projectile type " + Type); } // NOTE: nearestUnits уже склонированы // NOTE: nearestUnits и они же в minionsTargetsSelector - одни и те же instance var list = new List <ProjectilePathSegment>(); var projectile = new AProjectile(this); var owner = nearestUnits.FirstOrDefault(x => x.Id == OwnerUnitId); var nearestCandidates = nearestUnits.Where(x => x.Id != OwnerUnitId).ToArray(); while (projectile.Exists) { projectile.Move(proj => { if (Type == ProjectileType.Fireball) { double selfDamage = 0; double oppDamage = 0; var selfBurned = 0; var oppBurned = 0; var selfDeads = 0; var oppDeads = 0; ACombatUnit importantTarget = null; foreach (var unit in nearestCandidates) { var damage = GetFireballDamage(proj, unit); if (damage > 0) { var deads = 0; if (damage >= unit.Life - Const.Eps) { // killed deads++; damage = unit.Life; } if (unit.Faction == proj.Faction) { if (unit is AWizard) { selfDamage += damage; selfBurned++; selfDeads += deads; } } else if (Utility.HasConflicts(proj, unit)) { oppDamage += damage; oppBurned++; oppDeads += deads; if (importantTarget == null || _targetImportance(unit) > _targetImportance(importantTarget)) { importantTarget = unit; } } } } if (owner != null) { var damage = GetFireballDamage(proj, owner); if (damage > 0) { selfBurned++; if (damage >= owner.Life - Const.Eps) { // killed selfDamage += owner.Life; selfDeads++; } else { selfDamage += damage; } } } list.Add(new ProjectilePathSegment { StartDistance = list.Count == 0 ? 0 : list.Last().EndDistance, EndDistance = list.Count == 0 ? 0 : list.Last().EndDistance, OpponentDamage = oppDamage, SelfDamage = selfDamage, OpponentDeadsCount = oppDeads, SelfDeadsCount = selfDeads, State = (selfDamage + oppDamage < Const.Eps) ? ProjectilePathState.Free : ProjectilePathState.Fireball, OpponentBurned = oppBurned, SelfBurned = selfBurned, Target = importantTarget, }); } else { var inter = proj.GetFirstIntersection(nearestCandidates); if (inter != null) { if (list.Count == 0 || list.Last().State != ProjectilePathState.Shot) { var opp = inter as ACombatUnit; list.Add(new ProjectilePathSegment { StartDistance = list.Count == 0 ? 0 : list.Last().EndDistance, EndDistance = list.Count == 0 ? 0 : list.Last().EndDistance, State = ProjectilePathState.Shot, Target = Utility.CloneCombat(opp), SelfDamage = proj.Faction == inter.Faction ? Math.Min(opp.Life, Damage) : 0, OpponentDamage = Utility.HasConflicts(proj, opp) ? Math.Min(opp.Life, Damage) : 0, }); } } else { if (list.Count == 0 || list.Last().State != ProjectilePathState.Free) { list.Add(new ProjectilePathSegment { StartDistance = list.Count == 0 ? 0 : list.Last().EndDistance, EndDistance = list.Count == 0 ? 0 : list.Last().EndDistance, State = ProjectilePathState.Free, }); } } } list.Last().EndDistance += proj.Speed / proj.MicroTicks; return(true); }); foreach (var unit in nearestCandidates) { if (unit is AWizard) { var wizard = unit as AWizard; var dir = (wizard - this).RotateClockwise(wizardsChangeAngle) + wizard; // вдоль снаряда wizard.MoveTo(dir, null, w => { var tree = TreesObserver.GetNearestTree(w); return((tree == null || !w.IntersectsWith(tree)) && wizard.GetFirstIntersection(nearestCandidates) == null); }); } else if (unit is AMinion) { var target = minionsTargetsSelector.Select(unit); unit.EthalonMove(target); } } } return(list); }