public bool CancelChanneling(TargetManager targetManager) { if (!this.Ability.IsChanneling || !this.Ability.BaseAbility.IsChanneling) { return(false); } var target = targetManager.Target; if (target.IsStunned || target.IsRooted) { return(false); } var travelDistance = this.Owner.Distance(this.castPosition) / this.Ability.Speed; var predictedPolygon = new Polygon.Circle(this.castPosition, this.Ability.Radius - 200); var currentPolygon = new Polygon.Circle(this.castPosition, this.Ability.Radius - (travelDistance * target.Speed) - 175); var input = this.Ability.GetPredictionInput(target); input.Delay = (0.75f - this.Ability.BaseAbility.ChannelTime) + travelDistance; var output = this.Ability.GetPredictionOutput(input); if ((!predictedPolygon.IsInside(output.TargetPosition) && !currentPolygon.IsInside(target.Position) && target.GetAngle(this.castPosition) > 1.5f) || this.primalSpring.GetCurrentDamage(target) > target.Health) { return(this.Owner.BaseUnit.Stop()); } return(false); }
// Token: 0x06000503 RID: 1283 RVA: 0x0001A11C File Offset: 0x0001831C public bool CancelChanneling(TargetManager targetManager) { if (!base.Ability.IsChanneling || !base.Ability.BaseAbility.IsChanneling) { return(false); } Unit9 target = targetManager.Target; if (target.IsStunned || target.IsRooted) { return(false); } float num = base.Owner.Distance(this.castPosition) / base.Ability.Speed; Polygon polygon = new Polygon.Circle(this.castPosition, base.Ability.Radius, 20); Polygon.Circle circle = new Polygon.Circle(this.castPosition, base.Ability.Radius - num * target.Speed - 75f, 20); PredictionInput9 predictionInput = base.Ability.GetPredictionInput(target, null); predictionInput.Delay = this.primalSpring.ChannelTime - base.Ability.BaseAbility.ChannelTime + num; PredictionOutput9 predictionOutput = base.Ability.GetPredictionOutput(predictionInput); return(((!polygon.IsInside(predictionOutput.TargetPosition) && !circle.IsInside(target.Position) && target.GetAngle(this.castPosition, false) > 1.5f) || (float)this.primalSpring.GetCurrentDamage(target) > target.Health) && base.Owner.BaseUnit.Stop()); }
private void OnUpdate() { try { if (this.Sleeper.IsSleeping) { return; } var target = this.TargetManager.TargetLocked ? this.TargetManager.Target : this.killSteal.Target; if (target?.IsValid != true || !target.IsVisible) { return; } foreach (var abilityTiming in this.abilityTimings.ToList()) { var ability = abilityTiming.Key; if (!ability.IsValid || !ability.BaseAbility.IsInAbilityPhase) { continue; } var owner = ability.Owner; var phaseEnd = abilityTiming.Value; var input = ability.GetPredictionInput(target); input.Delay = Math.Max(phaseEnd - GameManager.RawGameTime, 0) + ability.ActivationDelay; var output = ability.GetPredictionOutput(input); if (!(ability is IHasRadius)) { continue; } if (!this.abilityPositions.TryGetValue(ability.Handle, out var castPosition)) { continue; } Polygon polygon = null; switch (ability) { case AreaOfEffectAbility aoe: { polygon = new Polygon.Circle(castPosition, aoe.Radius + 50); break; } case CircleAbility circle: { polygon = new Polygon.Circle(castPosition, circle.Radius + 50); break; } case ConeAbility cone: { polygon = new Polygon.Trapezoid( owner.Position.Extend2D(castPosition, -cone.Radius / 2), owner.Position.Extend2D(castPosition, cone.Range), cone.Radius + 50, cone.EndRadius + 100); break; } case LineAbility line: { polygon = new Polygon.Rectangle( owner.Position, owner.Position.Extend2D(castPosition, line.Range), line.Radius + 50); break; } } if (polygon == null) { continue; } if (!target.IsAlive || output.HitChance == HitChance.Impossible || !polygon.IsInside(output.TargetPosition)) { this.Sleeper.Sleep(0.15f); this.abilityTimings.Remove(ability); this.abilityPositions.Remove(ability.Handle); this.OrbwalkSleeper.Reset(ability.Owner.Handle); this.AbilitySleeper.Reset(ability.Handle); // this.TargetSleeper.Reset(target.Handle); this.killSteal.KillStealSleeper.Reset(); target.RefreshUnitState(); ability.Owner.BaseUnit.Stop(); var unit = this.BaseHero.UnitManager.AllControllableUnits.FirstOrDefault(x => x.Handle == ability.Owner.Handle); unit?.ComboSleeper.Reset(); } } } catch (Exception e) { Logger.Error(e); } }
private async Task OnHealingWardControl(CancellationToken token) { if (this.healingWardUnit == null) { return; } var team = this.healingWardUnit.Team; var healingRadius = this.HealingWard.Radius; while ((this.healingWardUnit != null) && this.healingWardUnit.IsValid && this.healingWardUnit.IsAlive) { if (Game.IsPaused) { await Task.Delay(125, token); continue; } var enemyHeroes = EntityManager <Hero> .Entities.Where(x => x.IsAlive && x.IsVisible && (x.Team != team) && (x.Distance2D(this.healingWardUnit) < 1000)).ToList(); var alliedHeroes = EntityManager <Hero> .Entities.Where(x => x.IsAlive && x.IsVisible && (x.Team == team) && (x.HealthPercent() <= 0.9f) && (x.Distance2D(this.healingWardUnit) < 800)) .OrderBy(x => x.HealthPercent()) .ToList(); if (!alliedHeroes.Any()) { if (!this.Owner.IsAlive) { // nobody is there to heal ... *feelsbadman* await Task.Delay(125, token); continue; } alliedHeroes.Add(this.Owner); } // get areas to avoid with the healing ward var avoidCircles = new List <Polygon.Circle>(enemyHeroes.Count); foreach (var enemyHero in enemyHeroes) { var dangerRange = enemyHero.AttackRange(this.healingWardUnit); dangerRange = enemyHero.IsMelee ? dangerRange * 2f : dangerRange * 1.2f; var circle = new Polygon.Circle(enemyHero.Position, dangerRange); // Log.Debug($"Adding avoid circle {circle.Center} ({circle.Radius})"); avoidCircles.Add(circle); } // find allies which need healing and are not close to enemies var healCircles = new List <Polygon.Circle>(alliedHeroes.Count); foreach (var alliedHero in alliedHeroes) { var circle = new Polygon.Circle(alliedHero.Position, healingRadius); if (avoidCircles.Exists(x => x.Center.Distance(circle.Center) <= Math.Abs(x.Radius - circle.Radius))) { // Log.Debug($"Skipping heal circle {circle.Center} ({circle.Radius})"); continue; } // Log.Debug($"Adding heal circle {circle.Center} ({circle.Radius})"); healCircles.Add(circle); } var hasMoved = false; if (healCircles.Any()) { while (healCircles.Count > 1) { var mecResult = MEC.GetMec(healCircles.Select((target) => target.Center).ToList()); if ((mecResult.Radius != 0f) && (mecResult.Radius < healingRadius)) { var movePos = new Vector3( healCircles.Count <= 2 ? (healCircles[0].Center + healCircles[1].Center) / 2 : mecResult.Center, this.healingWardUnit.Position.Z); if (avoidCircles.TrueForAll(x => !x.IsInside(movePos))) { this.healingWardUnit.Move(movePos); hasMoved = true; break; } } Log.Debug($"removing target since radius {mecResult.Radius} or movePos to dangerous"); var itemToRemove = healCircles.Where(x => x.Center != this.Owner.Position.ToVector2()) .MaxOrDefault((target) => healCircles[0].Center.DistanceSquared(target.Center)); healCircles.Remove(itemToRemove); } } // no safe area available... so just move to the target who needs it most and hope for the best if (!healCircles.Any() || !hasMoved) { var isOwnerLow = this.Owner.HealthPercent() <= 0.5f; var heroPos = isOwnerLow ? this.Owner.Position : alliedHeroes.First().Position; if (!avoidCircles.Any()) { this.healingWardUnit.Move(heroPos); Log.Debug($"No heal + avoid circles, moving to first allied"); } else { var z = this.healingWardUnit.Position.Z; var clusterPos = Vector3.Zero; foreach (var avoidCircle in avoidCircles) { clusterPos += avoidCircle.Center.ToVector3(z); } clusterPos /= avoidCircles.Count; var movePos = (clusterPos - heroPos).Normalized(); movePos = heroPos + (movePos * healingRadius * -1f); this.healingWardUnit.Move(movePos); Log.Debug($"No heal, moving to first allied and away from enemies"); } } await Task.Delay(125, token); } this.healingWardUnit = null; }
// Token: 0x060009F9 RID: 2553 RVA: 0x0002B730 File Offset: 0x00029930 private void OnUpdate() { try { if (!this.Sleeper.IsSleeping) { Unit9 unit = base.TargetManager.TargetLocked ? base.TargetManager.Target : this.killSteal.Target; if (unit != null && unit.IsValid && unit.IsVisible) { foreach (KeyValuePair <ActiveAbility, float> keyValuePair in this.abilityTimings.ToList <KeyValuePair <ActiveAbility, float> >()) { ActiveAbility ability = keyValuePair.Key; if (ability.IsValid && ability.BaseAbility.IsInAbilityPhase) { Unit9 owner = ability.Owner; float value = keyValuePair.Value; PredictionInput9 predictionInput = ability.GetPredictionInput(unit, null); predictionInput.Delay = Math.Max(value - Game.RawGameTime, 0f) + ability.ActivationDelay; PredictionOutput9 predictionOutput = ability.GetPredictionOutput(predictionInput); Vector3 vector; if (ability is IHasRadius && this.abilityPositions.TryGetValue(ability.Handle, out vector)) { Polygon polygon = null; ActiveAbility ability2 = ability; if (ability2 != null) { AreaOfEffectAbility areaOfEffectAbility; if ((areaOfEffectAbility = (ability2 as AreaOfEffectAbility)) == null) { CircleAbility circleAbility; if ((circleAbility = (ability2 as CircleAbility)) == null) { ConeAbility coneAbility; if ((coneAbility = (ability2 as ConeAbility)) == null) { LineAbility lineAbility; if ((lineAbility = (ability2 as LineAbility)) != null) { LineAbility lineAbility2 = lineAbility; polygon = new Polygon.Rectangle(owner.Position, Vector3Extensions.Extend2D(owner.Position, vector, lineAbility2.Range), lineAbility2.Radius + 50f); } } else { ConeAbility coneAbility2 = coneAbility; polygon = new Polygon.Trapezoid(Vector3Extensions.Extend2D(owner.Position, vector, -coneAbility2.Radius / 2f), Vector3Extensions.Extend2D(owner.Position, vector, coneAbility2.Range), coneAbility2.Radius + 50f, coneAbility2.EndRadius + 100f); } } else { CircleAbility circleAbility2 = circleAbility; polygon = new Polygon.Circle(vector, circleAbility2.Radius + 50f, 20); } } else { AreaOfEffectAbility areaOfEffectAbility2 = areaOfEffectAbility; polygon = new Polygon.Circle(vector, areaOfEffectAbility2.Radius + 50f, 20); } } if (polygon != null && (!unit.IsAlive || predictionOutput.HitChance == null || !polygon.IsInside(predictionOutput.TargetPosition))) { this.Sleeper.Sleep(0.15f); this.abilityTimings.Remove(ability); this.abilityPositions.Remove(ability.Handle); this.OrbwalkSleeper.Reset(ability.Owner.Handle); this.AbilitySleeper.Reset(ability.Handle); this.killSteal.KillStealSleeper.Reset(); unit.RefreshUnitState(); ability.Owner.BaseUnit.Stop(); ControllableUnit controllableUnit = base.BaseHero.UnitManager.AllControllableUnits.FirstOrDefault((ControllableUnit x) => x.Handle == ability.Owner.Handle); if (controllableUnit != null) { controllableUnit.ComboSleeper.Reset(); } } } } } } } } catch (Exception ex) { Logger.Error(ex, null); } }
private async void Player_OnExecuteOrder(Player sender, ExecuteOrderEventArgs args) { try { if (!(args.Entities.First() is Unit caster)) { return; } ActiveAbility ability; switch (args.OrderId) { case OrderId.Ability: case OrderId.AbilityLocation: case OrderId.AbilityTarget: try { ability = (ActiveAbility)this.context.AbilityFactory.GetAbility(args.Ability); } catch (AbilityNotImplementedException e) { // Log.Error(e); return; } break; default: return; } int delay; Vector3 center; switch (args.OrderId) { case OrderId.Ability: { if (!this.config.NoTargetSpells.PictureStates.TryGetValue(ability.Ability.TextureName, out var state) || !state) { return; } delay = ability.GetCastDelay(); center = caster.Position; break; } case OrderId.AbilityLocation: { if (!this.config.AreaSpells.PictureStates.TryGetValue(ability.Ability.TextureName, out var state) || !state) { return; } delay = ability.GetCastDelay(args.TargetPosition); center = args.TargetPosition; break; } case OrderId.AbilityTarget: { if (!this.config.TargetSpells.PictureStates.TryGetValue(ability.Ability.TextureName, out var state) || !state) { return; } if (args.Target is Unit target) { Unit betterTarget = null; // check for real target if we targeted an illusion if (target is Hero heroTarget && target.IsIllusion) { var replicateFrom = heroTarget.ReplicateFrom; if (replicateFrom.IsValid && replicateFrom.IsAlive && replicateFrom.IsVisible && !replicateFrom.IsLinkensProtected() && !replicateFrom.IsReflectingAbilities() && replicateFrom.IsEnemy(caster) && ability.CanHit(replicateFrom)) { betterTarget = replicateFrom; } } // check for the closest hero target if used on a creep var targetBlocking = target.IsLinkensProtected() || target.IsReflectingAbilities(); if (betterTarget == null && (target.IsNeutral || target is Creep || targetBlocking)) { betterTarget = EntityManager <Hero> .Entities.Where( x => x.IsAlive && x.IsVisible && !x.IsIllusion && !x.IsLinkensProtected() && !x.IsReflectingAbilities() && x.IsEnemy(caster) && ability.CanHit(x)) .OrderBy(x => x.Distance2D(target)) .FirstOrDefault(); } if (betterTarget != null) { args.Process = false; if (this.config.FindRealTarget) { ability.UseAbility(betterTarget); } } else if (targetBlocking) { args.Process = false; } } return; } default: return; } if (delay > 0) { await Task.Delay((int)(delay - Game.Ping)); } var radius = 0f; if (ability is IAreaOfEffectAbility aoeAbility) { radius = aoeAbility.Radius; } else if (ability is CircleAbility circleAbility) { radius = circleAbility.Radius; } if (radius > 0) { var circle = new Polygon.Circle(center, radius); if (!EntityManager <Hero> .Entities.Any(x => x.IsAlive && x.IsVisible && x.IsEnemy(this.context.Owner) && circle.IsInside(x.Position))) { caster.Stop(); } } } catch (Exception e) { Log.Error(e); } }
private async Task HealingWardController(CancellationToken token) { if (UnitExtensions.HasAghanimsScepter(this.Owner)) { this.SwiftSlash = this.Owner.Spellbook.Spells.FirstOrDefault <Ability>(x => x.Name == "juggernaut_swift_slash"); } if (this.healingWardUnit == null) { return; } var team = this.healingWardUnit.Team; var healingRadius = this.HealingWardAbility.Radius; while ((this.healingWardUnit != null) && this.healingWardUnit.IsValid && this.healingWardUnit.IsAlive) { if (Game.IsPaused) { await Task.Delay(125, token); continue; } var enemyHeroes = EntityManager <Hero> .Entities.Where( x => x.IsAlive && x.IsVisible && (x.Team != team) && (x.Distance2D(this.healingWardUnit) < 1000)) .ToList(); var alliedHeroes = EntityManager <Hero> .Entities.Where( x => x.IsAlive && x.IsVisible && (x.Team == team) && (x.HealthPercent() <= 0.9f) && (x.Distance2D(this.healingWardUnit) < 800)) .OrderBy(x => x.HealthPercent()) .ToList(); if (!alliedHeroes.Any()) { if (!this.Owner.IsAlive) { await Task.Delay(125, token); continue; } alliedHeroes.Add(this.Owner); } var avoidCircles = new List <Polygon.Circle>(enemyHeroes.Count); foreach (var enemyHero in enemyHeroes) { var dangerRange = enemyHero.AttackRange(this.healingWardUnit); dangerRange = enemyHero.IsMelee ? dangerRange * 2f : dangerRange * 1.2f; var circle = new Polygon.Circle(enemyHero.Position, dangerRange); avoidCircles.Add(circle); } var healCircles = new List <Polygon.Circle>(alliedHeroes.Count); foreach (var alliedHero in alliedHeroes) { var circle = new Polygon.Circle(alliedHero.Position, healingRadius); if (avoidCircles.Exists(x => x.Center.Distance(circle.Center) <= Math.Abs(x.Radius - circle.Radius))) { continue; } healCircles.Add(circle); } var hasMoved = false; if (healCircles.Any()) { while (healCircles.Count > 1) { var mecResult = MEC.GetMec(healCircles.Select((target) => target.Center).ToList()); if ((mecResult.Radius != 0f) && (mecResult.Radius < healingRadius)) { var movePos = new Vector3( healCircles.Count <= 2 ? (healCircles[0].Center + healCircles[1].Center) / 2 : mecResult.Center, this.healingWardUnit.Position.Z); if (avoidCircles.TrueForAll(x => !x.IsInside(movePos))) { this.healingWardUnit.Move(movePos); hasMoved = true; break; } } var itemToRemove = healCircles.Where(x => x.Center != this.Owner.Position.ToVector2()) .MaxOrDefault((target) => healCircles[0].Center.DistanceSquared(target.Center)); healCircles.Remove(itemToRemove); } } if (!healCircles.Any() || !hasMoved) { var isOwnerLow = this.Owner.HealthPercent() <= 0.5f; var heroPos = isOwnerLow ? this.Owner.Position : alliedHeroes.First().Position; if (!avoidCircles.Any()) { this.healingWardUnit.Move(heroPos); } else { var z = this.healingWardUnit.Position.Z; var clusterPos = Vector3.Zero; foreach (var avoidCircle in avoidCircles) { clusterPos += avoidCircle.Center.ToVector3(z); } clusterPos /= avoidCircles.Count; var movePos = (clusterPos - heroPos).Normalized(); movePos = heroPos + (movePos * healingRadius * -1f); this.healingWardUnit.Move(movePos); } } await Task.Delay(125, token); } this.healingWardUnit = null; }