public static void Game_OnUpdate(EventArgs args) { if (!Game.IsInGame) { return; } if (!Utils.SleepCheck("DDI_GameUpdateSleeper")) { return; } var me = ObjectMgr.LocalHero; if (me == null) { return; } Log.WriteSlowDebug = false; /*if (Utils.SleepCheck("DDI_GameDebugWriterSleeper")) * { * Log.WriteSlowDebug = true; * Log.SlowDebug("======================================="); * Log.SlowDebug("DuelDamageIndicator Debug information"); * }*/ Cache = new List <DrawingData>(); HeroDamageObj myDamageObj = new HeroDamageObj(me, 0.2); var enemies = ObjectMgr.GetEntities <Hero>().Where(x => x.Team != me.Team && x.IsAlive && x.IsVisible && !x.IsIllusion).ToList(); foreach (var enemy in enemies) { HeroDamageObj enemyDamageObj = new HeroDamageObj(enemy, 0.8); int myHitLeft = myDamageObj.CalculateAttackTo(enemyDamageObj); string myHitText = myHitLeft < 0 ? "∞" : "" + myHitLeft; int enemyHitLeft = enemyDamageObj.CalculateAttackTo(myDamageObj); string enemyHitText = enemyHitLeft < 0 ? "∞" : "" + enemyHitLeft; //add to cache Cache.Add(new DrawingData(enemy, myDamageObj.TotalManaCost <= me.Mana, myHitText, enemyDamageObj.TotalManaCost <= enemy.Mana, enemyHitText)); } Utils.Sleep(50, "DDI_GameUpdateSleeper"); /*if (Log.WriteSlowDebug) * { * Log.SlowDebug("END. If you found any miscalculated spell, please post it on the forum topic"); * Log.SlowDebug("======================================="); * Log.WriteSlowDebug = false; * Utils.Sleep(10000, "DDI_GameDebugWriterSleeper"); * }*/ }
public static void Game_OnUpdate(EventArgs args) { if (!Game.IsInGame) return; if (!Utils.SleepCheck("DDI_GameUpdateSleeper")) return; var me = ObjectMgr.LocalHero; if (me == null) return; Log.WriteSlowDebug = false; /*if (Utils.SleepCheck("DDI_GameDebugWriterSleeper")) { Log.WriteSlowDebug = true; Log.SlowDebug("======================================="); Log.SlowDebug("DuelDamageIndicator Debug information"); }*/ Cache = new List<DrawingData>(); HeroDamageObj myDamageObj = new HeroDamageObj(me, 0.2); var enemies = ObjectMgr.GetEntities<Hero>().Where(x => x.Team != me.Team && x.IsAlive && x.IsVisible && !x.IsIllusion).ToList(); foreach (var enemy in enemies) { HeroDamageObj enemyDamageObj = new HeroDamageObj(enemy, 0.8); int myHitLeft = myDamageObj.CalculateAttackTo(enemyDamageObj); string myHitText = myHitLeft < 0 ? "∞" : "" + myHitLeft; int enemyHitLeft = enemyDamageObj.CalculateAttackTo(myDamageObj); string enemyHitText = enemyHitLeft < 0 ? "∞" : "" + enemyHitLeft; //add to cache Cache.Add(new DrawingData(enemy, myDamageObj.TotalManaCost <= me.Mana, myHitText, enemyDamageObj.TotalManaCost <= enemy.Mana, enemyHitText)); } Utils.Sleep(50, "DDI_GameUpdateSleeper"); /*if (Log.WriteSlowDebug) { Log.SlowDebug("END. If you found any miscalculated spell, please post it on the forum topic"); Log.SlowDebug("======================================="); Log.WriteSlowDebug = false; Utils.Sleep(10000, "DDI_GameDebugWriterSleeper"); }*/ }
private int CalculateHit(double rawHealth, double rawDamage, double damageAmplifier, HeroDamageObj enemy) { int result = -1; int compensate = 0; //HasFurySwipesSpell need to be calculated differently: formular = (-attackDamage - sqrt(delta)) / furySwipesDamage, delta = attackDamage^2 + 4 * 0.5 * furySwipesDamage * enemyHealth //known as enemyHealth = 0.5furySwipesDamage * hit^2 + damage * hit if (HasFurySwipesSpell) { double furySwipesStackDamageAfterAmplifier = FurySwipesStackDamage * (1.0 - enemy.HeroObj.DamageResist) * damageAmplifier * FurySwipesMultiplier; rawDamage += enemy.FurySwipesStack * furySwipesStackDamageAfterAmplifier; if (rawDamage < 0) { compensate = (int)Math.Ceiling((-rawDamage) / furySwipesStackDamageAfterAmplifier); rawDamage = 0; } result = Math.Max((int)Math.Ceiling((Math.Sqrt(rawDamage * rawDamage + 2.0 * furySwipesStackDamageAfterAmplifier * rawHealth) - rawDamage) / furySwipesStackDamageAfterAmplifier), 0) + compensate; } else if (rawDamage > 0) { result = Math.Max((int)Math.Ceiling(rawHealth / rawDamage), 0); } return(result); }
public int CalculateAttackTo(HeroDamageObj enemy) { double[] toEnemyTotalDamage = new double[TotalDamageArray.Length]; Array.Copy(TotalDamageArray, toEnemyTotalDamage, TotalDamageArray.Length); //Some spell need to calculate based on enemy hero if (HasQuillSpraySpell) { toEnemyTotalDamage[QuillSprayDamageType] += enemy.QuillSprayStack * QuillSprayStackDamage; } if (HasManaVoid) { toEnemyTotalDamage[ManaVoidDamageType] += (enemy.HeroObj.MaximumMana - enemy.HeroObj.Mana) * ManaVoidMultiplier; } if (HasLvlDeath && ((enemy.HeroObj.Level == 25) || (enemy.HeroObj.Level % LvlDeathBonusHeroMultiple == 0))) { toEnemyTotalDamage[LvlDeathDamageType] += enemy.HeroObj.MaximumHealth * 0.2; } if (HasNecrolyteReapersScythe) { toEnemyTotalDamage[NecrolyteReapersDamageType] += (enemy.HeroObj.MaximumHealth - enemy.HeroObj.Health) * NecrolyteReapersDamageMultipler; } if (HasNyxManaBurn) { toEnemyTotalDamage[NyxManaBurnDamageType] += Math.Max(enemy.HeroObj.TotalIntelligence * NyxManaBurnMultiplier, enemy.HeroObj.Mana); } if (HasLifeBreak) { toEnemyTotalDamage[LifeBreakDamageType] += enemy.HeroObj.Health * LifeBreakMultiplier; } double myTotalDamage = toEnemyTotalDamage[(int)DamageType.Pure] + toEnemyTotalDamage[(int)DamageType.Physical] * (1.0 - enemy.HeroObj.DamageResist) + toEnemyTotalDamage[(int)DamageType.Magical] * (1.0 - enemy.HeroObj.MagicDamageResist); double temporallyDamageAmplifier = 1.0 * OutgoingDamageAmplifier * enemy.IncommingDamageAmplifier; double enemyShieldLeft = 0; if (enemy.HasManaShield) { myTotalDamage = Math.Max(myTotalDamage - enemy.ManaShieldDamageAbsorbed, 0) + Math.Min(myTotalDamage, enemy.ManaShieldDamageAbsorbed) * (1.0 - enemy.ManaShieldReduction / 100); enemyShieldLeft = Math.Max(enemy.ManaShieldDamageAbsorbed - myTotalDamage, 0); } if (enemy.HasBrislebackSpell) { double angle2Hero = HeroObj.FindAngleBetween(enemy.HeroObj.Position) + 180.0; //Face: enemy.HeroObj.FindAngleBetween(HeroObj.Position) double angleBristleFacing = enemy.HeroObj.Angles.Y + 180.0; double angleDifferent = Math.Abs(angle2Hero - angleBristleFacing); if (angleDifferent <= enemy.BristlebackBackAngle) { temporallyDamageAmplifier *= 1 - enemy.BristlebackBackBlock / 100; } else if (angleDifferent < enemy.BristlebackSideAngle) { temporallyDamageAmplifier *= 1 - enemy.BristlebackSideBlock / 100; } } myTotalDamage *= temporallyDamageAmplifier; double myActualAttackDamage = AttackDamage * (1.0 - enemy.HeroObj.DamageResist) * temporallyDamageAmplifier; double enemyHealth = enemy.HeroObj.Health; if (HasSunderSpell) { enemyHealth = Math.Min(enemyHealth, //not exchange Math.Max(((double)HeroObj.Health / HeroObj.MaximumHealth) * enemy.HeroObj.MaximumHealth, SunderMinPercentage * enemy.HeroObj.MaximumHealth)); //if exchange, check between our health and min health } enemyHealth = enemyHealth - myTotalDamage - toEnemyTotalDamage[(int)DamageType.HealthRemoval]; //check any threshold HP removal type if (HasCullingBlade) { if (enemyHealth < CullingBladeThreshold) { enemyHealth = 0; } else { double cullingBladeAmplifier = CullingBladeDamageType == (int)DamageType.Physical ? 1.0 - enemy.HeroObj.DamageResist : CullingBladeDamageType == (int)DamageType.Magical ? 1.0 - enemy.HeroObj.MagicDamageResist : 1.0; enemyHealth = enemyHealth - CullingBladeDamage * cullingBladeAmplifier * temporallyDamageAmplifier; } } if (HasIceBlast && (enemyHealth / enemy.HeroObj.MaximumHealth < IceBlastThreshold)) { enemyHealth = 0; } int shieldHit = 0; int rawHit = CalculateHit(enemyHealth, myActualAttackDamage, temporallyDamageAmplifier, enemy); //if no hit left or unable to hit, return immediately if (rawHit <= 0) { return(rawHit); } //otherwise, compute the shield hit if (enemyShieldLeft > 0) { shieldHit = CalculateHit(enemyShieldLeft, myActualAttackDamage, temporallyDamageAmplifier, enemy); } double shieldCompensationRate = 1.0 / (1 - (ManaShieldReduction / 100)); //compensateRate = 1 / (1 - x); rawHit = (int)Math.Ceiling(Math.Max(rawHit - shieldHit, 0) + Math.Min(rawHit, shieldHit) * shieldCompensationRate); //calculate the real hit. And any hit under shield should be multiplied by compensateRate return(rawHit); }
private int CalculateHit(double rawHealth, double rawDamage, double damageAmplifier, HeroDamageObj enemy) { int result = -1; int compensate = 0; //HasFurySwipesSpell need to be calculated differently: formular = (-attackDamage - sqrt(delta)) / furySwipesDamage, delta = attackDamage^2 + 4 * 0.5 * furySwipesDamage * enemyHealth //known as enemyHealth = 0.5furySwipesDamage * hit^2 + damage * hit if (HasFurySwipesSpell) { double furySwipesStackDamageAfterAmplifier = FurySwipesStackDamage * (1.0 - enemy.HeroObj.DamageResist) * damageAmplifier * FurySwipesMultiplier; rawDamage += enemy.FurySwipesStack * furySwipesStackDamageAfterAmplifier; if (rawDamage < 0) { compensate = (int) Math.Ceiling((-rawDamage) / furySwipesStackDamageAfterAmplifier); rawDamage = 0; } result = Math.Max((int)Math.Ceiling((Math.Sqrt(rawDamage * rawDamage + 2.0 * furySwipesStackDamageAfterAmplifier * rawHealth) - rawDamage) / furySwipesStackDamageAfterAmplifier), 0) + compensate; } else if (rawDamage > 0) { result = Math.Max((int)Math.Ceiling(rawHealth / rawDamage), 0); } return result; }
public int CalculateAttackTo(HeroDamageObj enemy) { double[] toEnemyTotalDamage = new double[TotalDamageArray.Length]; Array.Copy(TotalDamageArray, toEnemyTotalDamage, TotalDamageArray.Length); //Some spell need to calculate based on enemy hero if (HasQuillSpraySpell) { toEnemyTotalDamage[QuillSprayDamageType] += enemy.QuillSprayStack * QuillSprayStackDamage; } if (HasManaVoid) { toEnemyTotalDamage[ManaVoidDamageType] += (enemy.HeroObj.MaximumMana - enemy.HeroObj.Mana) * ManaVoidMultiplier; } if (HasLvlDeath && ((enemy.HeroObj.Level == 25) || (enemy.HeroObj.Level % LvlDeathBonusHeroMultiple == 0))) { toEnemyTotalDamage[LvlDeathDamageType] += enemy.HeroObj.MaximumHealth * 0.2; } if (HasNecrolyteReapersScythe) { toEnemyTotalDamage[NecrolyteReapersDamageType] += (enemy.HeroObj.MaximumHealth - enemy.HeroObj.Health) * NecrolyteReapersDamageMultipler; } if (HasNyxManaBurn) { toEnemyTotalDamage[NyxManaBurnDamageType] += Math.Max(enemy.HeroObj.TotalIntelligence * NyxManaBurnMultiplier, enemy.HeroObj.Mana); } if (HasLifeBreak) { toEnemyTotalDamage[LifeBreakDamageType] += enemy.HeroObj.Health * LifeBreakMultiplier; } double myTotalDamage = toEnemyTotalDamage[(int)DamageType.Pure] + toEnemyTotalDamage[(int)DamageType.Physical] * (1.0 - enemy.HeroObj.DamageResist) + toEnemyTotalDamage[(int)DamageType.Magical] * (1.0 - enemy.HeroObj.MagicDamageResist); double temporallyDamageAmplifier = 1.0 * OutgoingDamageAmplifier * enemy.IncommingDamageAmplifier; double enemyShieldLeft = 0; if (enemy.HasManaShield) { myTotalDamage = Math.Max(myTotalDamage - enemy.ManaShieldDamageAbsorbed, 0) + Math.Min(myTotalDamage, enemy.ManaShieldDamageAbsorbed) * (1.0 - enemy.ManaShieldReduction / 100); enemyShieldLeft = Math.Max(enemy.ManaShieldDamageAbsorbed - myTotalDamage, 0); } if (enemy.HasBrislebackSpell) { double angle2Hero = HeroObj.FindAngleBetween(enemy.HeroObj.Position) + 180.0; //Face: enemy.HeroObj.FindAngleBetween(HeroObj.Position) double angleBristleFacing = enemy.HeroObj.Angles.Y + 180.0; double angleDifferent = Math.Abs(angle2Hero - angleBristleFacing); if (angleDifferent <= enemy.BristlebackBackAngle) { temporallyDamageAmplifier *= 1 - enemy.BristlebackBackBlock / 100; } else if (angleDifferent < enemy.BristlebackSideAngle) { temporallyDamageAmplifier *= 1 - enemy.BristlebackSideBlock / 100; } } myTotalDamage *= temporallyDamageAmplifier; double myActualAttackDamage = AttackDamage * (1.0 - enemy.HeroObj.DamageResist) * temporallyDamageAmplifier; double enemyHealth = enemy.HeroObj.Health; if (HasSunderSpell) { enemyHealth = Math.Min(enemyHealth, //not exchange Math.Max(((double) HeroObj.Health / HeroObj.MaximumHealth) * enemy.HeroObj.MaximumHealth, SunderMinPercentage * enemy.HeroObj.MaximumHealth)); //if exchange, check between our health and min health } enemyHealth = enemyHealth - myTotalDamage - toEnemyTotalDamage[(int) DamageType.HealthRemoval]; //check any threshold HP removal type if (HasCullingBlade) { if (enemyHealth < CullingBladeThreshold) { enemyHealth = 0; } else { double cullingBladeAmplifier = CullingBladeDamageType == (int) DamageType.Physical ? 1.0 - enemy.HeroObj.DamageResist : CullingBladeDamageType == (int) DamageType.Magical ? 1.0 - enemy.HeroObj.MagicDamageResist : 1.0; enemyHealth = enemyHealth - CullingBladeDamage * cullingBladeAmplifier * temporallyDamageAmplifier; } } if (HasIceBlast && (enemyHealth / enemy.HeroObj.MaximumHealth < IceBlastThreshold)) { enemyHealth = 0; } int shieldHit = 0; int rawHit = CalculateHit(enemyHealth, myActualAttackDamage, temporallyDamageAmplifier, enemy); //if no hit left or unable to hit, return immediately if (rawHit <= 0) return rawHit; //otherwise, compute the shield hit if (enemyShieldLeft > 0) { shieldHit = CalculateHit(enemyShieldLeft, myActualAttackDamage, temporallyDamageAmplifier, enemy); } double shieldCompensationRate = 1.0 / (1 - (ManaShieldReduction / 100)); //compensateRate = 1 / (1 - x); rawHit = (int) Math.Ceiling(Math.Max(rawHit - shieldHit, 0) + Math.Min(rawHit, shieldHit) * shieldCompensationRate); //calculate the real hit. And any hit under shield should be multiplied by compensateRate return rawHit; }