diff --git a/BuffUtil.cs b/BuffUtil.cs index 6a967d1..882bee8 100644 --- a/BuffUtil.cs +++ b/BuffUtil.cs @@ -2,12 +2,13 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Numerics; using WindowsInput; using WindowsInput.Native; using ExileCore; using ExileCore.PoEMemory.Components; using ExileCore.PoEMemory.MemoryObjects; -using SharpDX; +using ExileCore.Shared.Enums; namespace BuffUtil { @@ -25,11 +26,16 @@ public class BuffUtil : BaseSettingsPlugin private DateTime? lastPhaseRunCast; private DateTime? lastWitheringStepCast; private DateTime? lastSteelSkinCast; + private DateTime? lastArcaneCloakCast; private DateTime? lastImmortalCallCast; private DateTime? lastMoltenShellCast; + private DateTime? lastWarcryCast; + private DateTime? lastBerserkCast; private float HPPercent; private float MPPercent; private int? nearbyMonsterCount; + private int? rageBuffCount; + private bool? uniqueBossNearby; private bool showErrors = true; private Stopwatch movementStopwatch { get; set; } = new Stopwatch(); @@ -70,10 +76,13 @@ private void OnExecute() HandleScourgeArrow(); HandleBloodRage(); HandleSteelSkin(); + HandleArcaneCloak(); HandleImmortalCall(); HandleMoltenShell(); HandlePhaseRun(); HandleWitheringStep(); + HandleWarcry(); + HandleBerserk(); } catch (Exception ex) { @@ -95,7 +104,7 @@ private void HandleBladeFlurry() if (stacksBuff == null) return; - var charges = stacksBuff.Charges; + var charges = stacksBuff.BuffCharges; if (charges < Settings.BladeFlurryMinCharges.Value) return; @@ -107,7 +116,7 @@ private void HandleBladeFlurry() } if (Settings.Debug) - LogMessage($"Releasing Blade Flurry at {charges} charges.", 1); + LogMessage($"Releasing Blade Flurry at {charges} charges."); if (Settings.BladeFlurryUseLeftClick) { @@ -138,7 +147,7 @@ private void HandleScourgeArrow() if (stacksBuff == null) return; - var charges = stacksBuff.Charges; + var charges = stacksBuff.BuffCharges; if (charges < Settings.ScourgeArrowMinCharges.Value) return; @@ -150,7 +159,7 @@ private void HandleScourgeArrow() } if (Settings.Debug) - LogMessage($"Releasing Scourge Arrow at {charges} charges.", 1); + LogMessage($"Releasing Scourge Arrow at {charges} charges."); if (Settings.ScourgeArrowUseLeftClick) { @@ -188,12 +197,11 @@ private void HandleBloodRage() if (!hasBuff.HasValue || hasBuff.Value) return; - var skill = GetUsableSkill(C.BloodRage.Name, C.BloodRage.InternalName, - Settings.BloodRageConnectedSkill.Value); + var skill = GetUsableSkill(C.BloodRage.Name, C.BloodRage.InternalName); if (skill == null) { if (Settings.Debug) - LogMessage("Can not cast Blood Rage - not found in usable skills.", 1); + LogMessage("Can not cast Blood Rage - not found in usable skills."); return; } @@ -201,9 +209,9 @@ private void HandleBloodRage() return; if (Settings.Debug) - LogMessage("Casting Blood Rage", 1); - inputSimulator.Keyboard.KeyPress((VirtualKeyCode) Settings.BloodRageKey.Value); - lastBloodRageCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble(0, 0.2)); + LogMessage("Casting Blood Rage"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.BloodRageKey.Value); + lastBloodRageCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); } catch (Exception ex) { @@ -230,12 +238,12 @@ private void HandleSteelSkin() if (!hasBuff.HasValue || hasBuff.Value) return; - var skill = GetUsableSkill(C.SteelSkin.Name, C.SteelSkin.InternalName, - Settings.SteelSkinConnectedSkill.Value); + var skill = GetUsableSkill(C.SteelSkin.Name, C.SteelSkin.InternalName + ); if (skill == null) { if (Settings.Debug) - LogMessage("Can not cast Steel Skin - not found in usable skills.", 1); + LogMessage("Can not cast Steel Skin - not found in usable skills."); return; } @@ -243,9 +251,9 @@ private void HandleSteelSkin() return; if (Settings.Debug) - LogMessage("Casting Steel Skin", 1); - inputSimulator.Keyboard.KeyPress((VirtualKeyCode) Settings.SteelSkinKey.Value); - lastSteelSkinCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble(0, 0.2)); + LogMessage("Casting Steel Skin"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.SteelSkinKey.Value); + lastSteelSkinCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); } catch (Exception ex) { @@ -254,6 +262,48 @@ private void HandleSteelSkin() } } + private void HandleArcaneCloak() + { + try + { + if (!Settings.ArcaneCloak) + return; + + if (lastArcaneCloakCast.HasValue && currentTime - lastArcaneCloakCast.Value < + C.ArcaneCloak.TimeBetweenCasts) + return; + + if (HPPercent > Settings.ArcaneCloakMaxHP.Value) + return; + + var hasBuff = HasBuff(C.ArcaneCloak.BuffName); + if (!hasBuff.HasValue || hasBuff.Value) + return; + + var skill = GetUsableSkill(C.ArcaneCloak.Name, C.ArcaneCloak.InternalName + ); + if (skill == null) + { + if (Settings.Debug) + LogMessage("Can not cast Arcane Cloak - not found in usable skills."); + return; + } + + if (!NearbyMonsterCheck()) + return; + + if (Settings.Debug) + LogMessage("Casting Arcane Cloak"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.ArcaneCloakKey.Value); + lastArcaneCloakCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); + } + catch (Exception ex) + { + if (showErrors) + LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandleArcaneCloak)}: {ex.StackTrace}", 3f); + } + } + private void HandleImmortalCall() { try @@ -272,12 +322,11 @@ private void HandleImmortalCall() if (!hasBuff.HasValue || hasBuff.Value) return; - var skill = GetUsableSkill(C.ImmortalCall.Name, C.ImmortalCall.InternalName, - Settings.ImmortalCallConnectedSkill.Value); + var skill = GetUsableSkill(C.ImmortalCall.Name, C.ImmortalCall.InternalName); if (skill == null) { if (Settings.Debug) - LogMessage("Can not cast Immortal Call - not found in usable skills.", 1); + LogMessage("Can not cast Immortal Call - not found in usable skills."); return; } @@ -285,9 +334,9 @@ private void HandleImmortalCall() return; if (Settings.Debug) - LogMessage("Casting Immortal Call", 1); - inputSimulator.Keyboard.KeyPress((VirtualKeyCode) Settings.ImmortalCallKey.Value); - lastImmortalCallCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble(0, 0.2)); + LogMessage("Casting Immortal Call"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.ImmortalCallKey.Value); + lastImmortalCallCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); } catch (Exception ex) { @@ -314,12 +363,11 @@ private void HandleMoltenShell() if (!hasBuff.HasValue || hasBuff.Value) return; - var skill = GetUsableSkill(C.MoltenShell.Name, C.MoltenShell.InternalName, - Settings.MoltenShellConnectedSkill.Value); + var skill = GetUsableSkill(C.MoltenShell.Name, C.MoltenShell.InternalName); if (skill == null) { if (Settings.Debug) - LogMessage("Can not cast Molten Shell - not found in usable skills.", 1); + LogMessage("Can not cast Molten Shell - not found in usable skills."); return; } @@ -327,9 +375,9 @@ private void HandleMoltenShell() return; if (Settings.Debug) - LogMessage("Casting Molten Shell", 1); - inputSimulator.Keyboard.KeyPress((VirtualKeyCode) Settings.MoltenShellKey.Value); - lastMoltenShellCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble(0, 0.2)); + LogMessage("Casting Molten Shell"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.MoltenShellKey.Value); + lastMoltenShellCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); } catch (Exception ex) { @@ -363,16 +411,15 @@ private void HandlePhaseRun() if (requiredBVStacks > 0) { var bvBuff = GetBuff(C.BladeVortex.BuffName); - if (bvBuff == null || bvBuff.Charges < requiredBVStacks) + if (bvBuff == null || bvBuff.BuffCharges < requiredBVStacks) return; } - var skill = GetUsableSkill(C.PhaseRun.Name, C.PhaseRun.InternalName, - Settings.PhaseRunConnectedSkill.Value); + var skill = GetUsableSkill(C.PhaseRun.Name, C.PhaseRun.InternalName); if (skill == null) { if (Settings.Debug) - LogMessage("Can not cast Phase Run - not found in usable skills.", 1); + LogMessage("Can not cast Phase Run - not found in usable skills."); return; } @@ -380,14 +427,14 @@ private void HandlePhaseRun() return; if (Settings.Debug) - LogMessage("Casting Phase Run", 1); - inputSimulator.Keyboard.KeyPress((VirtualKeyCode) Settings.PhaseRunKey.Value); - lastPhaseRunCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble(0, 0.2)); + LogMessage("Casting Phase Run"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.PhaseRunKey.Value); + lastPhaseRunCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); } catch (Exception ex) { if (showErrors) - LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandleSteelSkin)}: {ex.StackTrace}", 3f); + LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandlePhaseRun)}: {ex.StackTrace}", 3f); } } @@ -412,12 +459,11 @@ private void HandleWitheringStep() if (!hasBuff.HasValue || hasBuff.Value) return; - var skill = GetUsableSkill(C.WitheringStep.Name, C.WitheringStep.InternalName, - Settings.WitheringStepConnectedSkill.Value); + var skill = GetUsableSkill(C.WitheringStep.Name, C.WitheringStep.InternalName); if (skill == null) { if (Settings.Debug) - LogMessage("Can not cast Withering Step - not found in usable skills.", 1); + LogMessage("Can not cast Withering Step - not found in usable skills."); return; } @@ -425,17 +471,104 @@ private void HandleWitheringStep() return; if (Settings.Debug) - LogMessage("Casting Withering Step", 1); - inputSimulator.Keyboard.KeyPress((VirtualKeyCode) Settings.WitheringStepKey.Value); - lastWitheringStepCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble(0, 0.2)); + LogMessage("Casting Withering Step"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.WitheringStepKey.Value); + lastWitheringStepCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.2); } catch (Exception ex) { if (showErrors) - LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandleSteelSkin)}: {ex.StackTrace}", 3f); + LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandleWitheringStep)}: {ex.StackTrace}", 3f); + } + } + + private void HandleWarcry() + { + try + { + if (!Settings.Warcry) + return; + + if (lastWarcryCast.HasValue && currentTime - lastWarcryCast.Value < + TimeSpan.FromMilliseconds(500)) + return; + + var minRage = Settings.WarCryMinRage.Value; + var maxRage = Settings.WarCryMaxRage.Value; + var rage = GetRageBuffCharges(); + if (rage < minRage || rage > maxRage) + return; + + var useAlways = Settings.WarcryUseAlways.Value; + var requiredEnemies = Settings.WarcryNearbyEnemiesCount; + var useOnBosses = Settings.WarcryUseOnUniqueBoss.Value; + if (!(useAlways || requiredEnemies > 0 && requiredEnemies <= GetNearbyMonsterCount() || + useOnBosses && IsUniqueBossInRange())) + return; + + var skill = GetWarcryActorSkill(); + if (skill == null || !skill.CanBeUsed) + { + if (Settings.Debug) + LogMessage("Can not cast Warcry skill - not found in usable skills."); + return; + } + + if (Settings.Debug) + LogMessage("Casting Warcry"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.WarcryKey.Value); + lastWarcryCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.1); + } + catch (Exception ex) + { + if (showErrors) + LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandleWarcry)}: {ex.StackTrace}", 3f); + } + } + + private void HandleBerserk() + { + try + { + if (!Settings.Berserk) + return; + + if (lastBerserkCast.HasValue && currentTime - lastBerserkCast.Value < + TimeSpan.FromMilliseconds(500)) + return; + + var minRage = Settings.BerserkMinRage.Value; + var rage = GetRageBuffCharges(); + if (rage < minRage) + return; + + var requiredEnemies = Settings.BerserkNearbyEnemiesCount.Value; + var useOnBosses = Settings.BerserkUseOnUniqueBoss.Value; + if (!(requiredEnemies > 0 && requiredEnemies <= GetNearbyMonsterCount() || + useOnBosses && IsUniqueBossInRange())) + return; + + var skill = GetUsableSkill(C.Berserk.Name, C.Berserk.InternalName); + if (skill == null || !skill.CanBeUsed) + { + if (Settings.Debug) + LogMessage("Can not cast Berserk skill - not found in usable skills."); + return; + } + + if (Settings.Debug) + LogMessage("Casting Berserk"); + inputSimulator.Keyboard.KeyPress((VirtualKeyCode)Settings.BerserkKey.Value); + lastBerserkCast = currentTime + TimeSpan.FromSeconds(rand.NextDouble() * 0.1); + } + catch (Exception ex) + { + if (showErrors) + LogError($"Exception in {nameof(BuffUtil)}.{nameof(HandleWarcry)}: {ex.StackTrace}", 3f); } } + private bool OnPreExecute() { try @@ -473,9 +606,9 @@ private bool OnPreExecute() HPPercent = 100f * playerLife.HPPercentage; MPPercent = 100f * playerLife.MPPercentage; - + var playerActor = player.GetComponent(); - if (player != null && player.Address != 0 && playerActor.isMoving) + if (player.Address != 0 && playerActor.isMoving) { if (!movementStopwatch.IsRunning) movementStopwatch.Start(); @@ -484,7 +617,7 @@ private bool OnPreExecute() { movementStopwatch.Reset(); } - + return true; } @@ -504,6 +637,8 @@ private void OnPostExecute() skills = null; currentTime = null; nearbyMonsterCount = null; + rageBuffCount = null; + uniqueBossNearby = null; } catch (Exception ex) { @@ -517,7 +652,7 @@ private void OnPostExecute() if (buffs == null) { if (showErrors) - LogError("Requested buff check, but buff list is empty.", 1); + LogError("Requested buff check, but buff list is empty."); return null; } @@ -529,35 +664,57 @@ private Buff GetBuff(string buffName) if (buffs == null) { if (showErrors) - LogError("Requested buff retrieval, but buff list is empty.", 1); + LogError("Requested buff retrieval, but buff list is empty."); return null; } return buffs.FirstOrDefault(b => string.Compare(b.Name, buffName, StringComparison.OrdinalIgnoreCase) == 0); } - private ActorSkill GetUsableSkill(string skillName, string skillInternalName, int skillSlotIndex) + private ActorSkill GetUsableSkill(string skillName, string skillInternalName) + { + if (skills == null) + { + if (showErrors) + LogError("Requested usable skill, but skill list is empty."); + return null; + } + + return skills.FirstOrDefault(s => + (string.Compare(s.Name, skillName, StringComparison.OrdinalIgnoreCase) == 0 || + string.Compare(s.InternalName, skillInternalName, StringComparison.OrdinalIgnoreCase) == 0)); + } + + private ActorSkill GetUsableSkill(IEnumerable skillNames) { if (skills == null) { if (showErrors) - LogError("Requested usable skill, but skill list is empty.", 1); + LogError("Requested usable skill, but skill list is empty."); return null; } return skills.FirstOrDefault(s => - (s.Name == skillName || s.InternalName == skillInternalName)); + (skillNames.Any(sn => + string.Compare(s.Name, sn, StringComparison.OrdinalIgnoreCase) == 0))); } private bool NearbyMonsterCheck() { if (!Settings.RequireMinMonsterCount.Value) return true; + var result = GetNearbyMonsterCount() >= Settings.NearbyMonsterCount; + if (Settings.Debug.Value && !result) + LogMessage("NearbyMonstersCheck failed."); + return result; + } + private int GetNearbyMonsterCount() + { if (nearbyMonsterCount.HasValue) - return nearbyMonsterCount.Value >= Settings.NearbyMonsterCount; + return nearbyMonsterCount.Value; - var playerPosition = GameController.Game.IngameState.Data.LocalPlayer.GetComponent().Pos; + var playerPosition = GameController.Game.IngameState.Data.LocalPlayer.GetComponent().PosNum; List localLoadedMonsters; lock (loadedMonstersLock) @@ -573,10 +730,38 @@ private bool NearbyMonsterCheck() monsterCount++; nearbyMonsterCount = monsterCount; - var result = nearbyMonsterCount.Value >= Settings.NearbyMonsterCount; - if (Settings.Debug.Value && !result) - LogMessage("NearbyMonstersCheck failed.", 1); - return result; + return monsterCount; + } + + private bool IsUniqueBossInRange() + { + if (uniqueBossNearby.HasValue) + return uniqueBossNearby.Value; + + var playerPosition = GameController.Game.IngameState.Data.LocalPlayer.GetComponent().PosNum; + + List localLoadedMonsters; + lock (loadedMonstersLock) + { + localLoadedMonsters = new List(loadedMonsters); + } + + var maxDistance = 750; + var maxDistanceSquared = maxDistance * maxDistance; + foreach (var monster in localLoadedMonsters) + if (monster.Rarity == MonsterRarity.Unique && + IsValidNearbyMonster(monster, playerPosition, maxDistanceSquared)) + { + var life = monster.GetComponent(); + if (life.CurHP < life.MaxHP || life.CurES < life.MaxES) + { + uniqueBossNearby = true; + return true; + } + } + + uniqueBossNearby = false; + return false; } private bool IsValidNearbyMonster(Entity monster, Vector3 playerPosition, int maxDistanceSquared) @@ -587,7 +772,7 @@ private bool IsValidNearbyMonster(Entity monster, Vector3 playerPosition, int ma !monster.IsValid) return false; - var monsterPosition = monster.Pos; + var monsterPosition = monster.PosNum; var xDiff = playerPosition.X - monsterPosition.X; var yDiff = playerPosition.Y - monsterPosition.Y; @@ -605,6 +790,33 @@ private bool IsValidNearbyMonster(Entity monster, Vector3 playerPosition, int ma private bool IsMonster(Entity entity) => entity != null && entity.HasComponent(); + private int GetRageBuffCharges() + { + if (rageBuffCount.HasValue) + return rageBuffCount.Value; + if (buffs == null || buffs.Count == 0) + { + rageBuffCount = 0; + return rageBuffCount.Value; + } + + var rageBuff = GetBuff(C.Rage.BuffName); + rageBuffCount = rageBuff?.BuffCharges ?? 0; + return rageBuffCount.Value; + } + + + private ActorSkill GetWarcryActorSkill() + { + string[] warcryNames = + { + C.WarcryAncestralCry.Name, C.WarcryBattlemagesCry.Name, C.WarcryEnduringCry.Name, + C.WarcryInfernalCry.Name, C.WarcryIntimidatingCry.Name, C.WarcryRallyingCry.Name + }; + + return GetUsableSkill(warcryNames); + } + public override void EntityAdded(Entity entity) { if (!IsMonster(entity)) diff --git a/BuffUtil.csproj b/BuffUtil.csproj index fc27a1e..78cf6d0 100644 --- a/BuffUtil.csproj +++ b/BuffUtil.csproj @@ -18,6 +18,6 @@ - + \ No newline at end of file diff --git a/BuffUtilSettings.cs b/BuffUtilSettings.cs index 27bff98..4464392 100644 --- a/BuffUtilSettings.cs +++ b/BuffUtilSettings.cs @@ -12,38 +12,50 @@ public BuffUtilSettings() Enable = new ToggleNode(false); BloodRage = new ToggleNode(false); BloodRageKey = new HotkeyNode(Keys.E); - BloodRageConnectedSkill = new RangeNode(1, 1, 13); BloodRageMaxHP = new RangeNode(100, 0, 100); BloodRageMaxMP = new RangeNode(100, 0, 100); + ArcaneCloak = new ToggleNode(false); + ArcaneCloakKey = new HotkeyNode(Keys.R); + ArcaneCloakMaxHP = new RangeNode(90, 0, 100); + SteelSkin = new ToggleNode(false); SteelSkinKey = new HotkeyNode(Keys.W); - SteelSkinConnectedSkill = new RangeNode(1, 1, 13); SteelSkinMaxHP = new RangeNode(90, 0, 100); ImmortalCall = new ToggleNode(false); ImmortalCallKey = new HotkeyNode(Keys.T); - ImmortalCallConnectedSkill = new RangeNode(1, 1, 13); ImmortalCallMaxHP = new RangeNode(50, 0, 100); MoltenShell = new ToggleNode(false); MoltenShellKey = new HotkeyNode(Keys.Q); - MoltenShellConnectedSkill = new RangeNode(1, 1, 13); MoltenShellMaxHP = new RangeNode(50, 0, 100); PhaseRun = new ToggleNode(false); PhaseRunKey = new HotkeyNode(Keys.R); - PhaseRunConnectedSkill = new RangeNode(1, 1, 13); PhaseRunMaxHP = new RangeNode(90, 0, 100); PhaseRunMinMoveTime = new RangeNode(0, 0, 5000); PhaseRunMinBVStacks = new RangeNode(0, 0, 10); WitheringStep = new ToggleNode(false); WitheringStepKey = new HotkeyNode(Keys.R); - WitheringStepConnectedSkill = new RangeNode(1, 1, 13); WitheringStepMaxHP = new RangeNode(90, 0, 100); WitheringStepMinMoveTime = new RangeNode(0, 0, 5000); + Berserk = new ToggleNode(false); + BerserkKey = new HotkeyNode(Keys.R); + BerserkMinRage = new RangeNode(5, 5, 50); + BerserkNearbyEnemiesCount = new RangeNode(1, 0, 50); + BerserkUseOnUniqueBoss = new ToggleNode(true); + + Warcry = new ToggleNode(false); + WarcryKey = new HotkeyNode(Keys.R); + WarCryMinRage = new RangeNode(0, 0, 50); + WarCryMaxRage = new RangeNode(24, 0, 100); + WarcryNearbyEnemiesCount = new RangeNode(1, 0, 50); + WarcryUseOnUniqueBoss = new ToggleNode(true); + WarcryUseAlways = new ToggleNode(false); + BladeFlurry = new ToggleNode(false); BladeFlurryMinCharges = new RangeNode(6, 1, 6); BladeFlurryUseLeftClick = new ToggleNode(false); @@ -71,14 +83,10 @@ public BuffUtilSettings() [Menu("Blood Rage Key", "Which key to press to activate Blood Rage?", 11, 1)] public HotkeyNode BloodRageKey { get; set; } - - [Menu("Connected Skill", "Set the skill slot (1 = top left, 8 = bottom right)", 12, 1)] - public RangeNode BloodRageConnectedSkill { get; set; } - - [Menu("Max HP", "HP percent above which skill is not cast", 13, 1)] + [Menu("Max HP", "HP percent above which skill is not cast", 12, 1)] public RangeNode BloodRageMaxHP { get; set; } - [Menu("Max Mana", "Mana percent above which skill is not cast", 14, 1)] + [Menu("Max Mana", "Mana percent above which skill is not cast", 13, 1)] public RangeNode BloodRageMaxMP { get; set; } #endregion @@ -89,10 +97,7 @@ public BuffUtilSettings() [Menu("Steel Skin Key", 21, 2)] public HotkeyNode SteelSkinKey { get; set; } - [Menu("Connected Skill", "Set the skill slot (1 = top left, 8 = bottom right)", 22, 2)] - public RangeNode SteelSkinConnectedSkill { get; set; } - - [Menu("Max HP", "HP percent above which skill is not cast", 23, 2)] + [Menu("Max HP", "HP percent above which skill is not cast", 22, 2)] public RangeNode SteelSkinMaxHP { get; set; } #endregion @@ -103,10 +108,7 @@ public BuffUtilSettings() [Menu("Immortal Call Key", 31, 3)] public HotkeyNode ImmortalCallKey { get; set; } - [Menu("Connected Skill", "Set the skill slot (1 = top left, 8 = bottom right)", 32, 3)] - public RangeNode ImmortalCallConnectedSkill { get; set; } - - [Menu("Max HP", "HP percent above which skill is not cast", 33, 3)] + [Menu("Max HP", "HP percent above which skill is not cast", 32, 3)] public RangeNode ImmortalCallMaxHP { get; set; } #endregion @@ -117,10 +119,8 @@ public BuffUtilSettings() [Menu("Molten Shell Key", 41, 4)] public HotkeyNode MoltenShellKey { get; set; } - [Menu("Connected Skill", "Set the skill slot (1 = top left, 8 = bottom right)", 42, 4)] - public RangeNode MoltenShellConnectedSkill { get; set; } - [Menu("Max HP", "HP percent above which skill is not cast", 43, 4)] + [Menu("Max HP", "HP percent above which skill is not cast", 42, 4)] public RangeNode MoltenShellMaxHP { get; set; } #endregion @@ -131,16 +131,14 @@ public BuffUtilSettings() [Menu("Phase Run Key", 51, 5)] public HotkeyNode PhaseRunKey { get; set; } - [Menu("Connected Skill", "Set the skill slot (1 = top left, 8 = bottom right)", 52, 5)] - public RangeNode PhaseRunConnectedSkill { get; set; } - [Menu("Max HP", "HP percent above which skill is not cast", 53, 5)] + [Menu("Max HP", "HP percent above which skill is not cast", 52, 5)] public RangeNode PhaseRunMaxHP { get; set; } - - [Menu("Move time", "Time in ms spent moving after which skill can be cast", 54, 5)] + + [Menu("Move time", "Time in ms spent moving after which skill can be cast", 53, 5)] public RangeNode PhaseRunMinMoveTime { get; set; } - - [Menu("BV Stacks", "Blade Vortex stacks required to cast Phase Run", 55, 5)] + + [Menu("BV Stacks", "Blade Vortex stacks required to cast Phase Run", 54, 5)] public RangeNode PhaseRunMinBVStacks { get; set; } #endregion @@ -151,66 +149,118 @@ public BuffUtilSettings() [Menu("Withering Step Key", 61, 6)] public HotkeyNode WitheringStepKey { get; set; } - [Menu("Connected Skill", "Set the skill slot (1 = top left, 8 = bottom right)", 62, 6)] - public RangeNode WitheringStepConnectedSkill { get; set; } - - [Menu("Max HP", "HP percent above which skill is not cast", 63, 6)] + [Menu("Max HP", "HP percent above which skill is not cast", 62, 6)] public RangeNode WitheringStepMaxHP { get; set; } - - [Menu("Move time", "Time in ms spent moving after which skill can be cast", 64, 6)] + + [Menu("Move time", "Time in ms spent moving after which skill can be cast", 63, 6)] public RangeNode WitheringStepMinMoveTime { get; set; } #endregion + #region Berserk + + [Menu("Berserk", 7)] public ToggleNode Berserk { get; set; } + + [Menu("Berserk Key", 71, 7)] public HotkeyNode BerserkKey { get; set; } + + [Menu("Min Rage", "Minimum amount of Rage charges to use", 72, 7)] + public RangeNode BerserkMinRage { get; set; } + + [Menu("Nearby monsters", "Nearby enemy monsters count to use", 73, 7)] + public RangeNode BerserkNearbyEnemiesCount { get; set; } + + [Menu("Unique bosses", "Use Berserk on Unique Bosses", 74, 7)] + public ToggleNode BerserkUseOnUniqueBoss { get; set; } + + #endregion + + #region Arcane Cloak + + [Menu("Arcane Cloak", 8)] public ToggleNode ArcaneCloak { get; set; } + + [Menu("Arcane Cloak Key", 81, 8)] public HotkeyNode ArcaneCloakKey { get; set; } + + [Menu("Max HP", "HP percent above which skill is not cast", 82, 8)] + public RangeNode ArcaneCloakMaxHP { get; set; } + + #endregion + + #region Warcry + + [Menu("Warcry", 9)] public ToggleNode Warcry { get; set; } + + [Menu("Warcry Key", 91, 9)] public HotkeyNode WarcryKey { get; set; } + + + [Menu("MinRage", "Use if at least X amount of Rage charges", 92, 9)] + public RangeNode WarCryMinRage { get; set; } + + [Menu("Max Rage", "Use if at most X amount of Rage charges", 93, 9)] + public RangeNode WarCryMaxRage { get; set; } + + [Menu("Nearby monsters", "Nearby enemy monsters count to use", 94, 9)] + public RangeNode WarcryNearbyEnemiesCount { get; set; } + + [Menu("Unique bosses", "Use Berserk on Unique Bosses", 95, 9)] + public ToggleNode WarcryUseOnUniqueBoss { get; set; } + + [Menu("Use always when ready", "Use always when ready (and matches Rage conditions)", 96, 9)] + public ToggleNode WarcryUseAlways { get; set; } + + #endregion + #region Blade Flurry - [Menu("Blade Flurry", "Use mouse click to release Blade Flurry charges", 7)] public ToggleNode BladeFlurry { get; set; } + [Menu("Blade Flurry", "Use mouse click to release Blade Flurry charges", 10)] + public ToggleNode BladeFlurry { get; set; } - [Menu("Min charges", "Minimal amount of BF charges to release", 71, 7)] + [Menu("Min charges", "Minimal amount of BF charges to release", 101, 10)] public RangeNode BladeFlurryMinCharges { get; set; } - [Menu("Use left click", "Use left click instead of right click to release charges", 72, 7)] + [Menu("Use left click", "Use left click instead of right click to release charges", 102, 10)] public ToggleNode BladeFlurryUseLeftClick { get; set; } - - [Menu("Wait for Infused Channeling buff", "Wait for Infused Channeling buff before release", 73, 7)] + + [Menu("Wait for Infused Channeling buff", "Wait for Infused Channeling buff before release", 103, 10)] public ToggleNode BladeFlurryWaitForInfused { get; set; } #endregion #region Scourge Arrow - [Menu("Scourge Arrow", "Use mouse click to release Scourge Arrow charges", 8)] public ToggleNode ScourgeArrow { get; set; } + [Menu("Scourge Arrow", "Use mouse click to release Scourge Arrow charges", 11)] + public ToggleNode ScourgeArrow { get; set; } - [Menu("Min charges", "Minimal amount of BF charges to release", 81, 8)] + [Menu("Min charges", "Minimal amount of BF charges to release", 111, 11)] public RangeNode ScourgeArrowMinCharges { get; set; } - [Menu("Use left click", "Use left click instead of right click to release charges", 82, 8)] + [Menu("Use left click", "Use left click instead of right click to release charges", 112, 11)] public ToggleNode ScourgeArrowUseLeftClick { get; set; } - - [Menu("Wait for Infused Channeling buff", "Wait for Infused Channeling buff before release", 83, 8)] + + [Menu("Wait for Infused Channeling buff", "Wait for Infused Channeling buff before release", 113, 11)] public ToggleNode ScourgeArrowWaitForInfused { get; set; } + #endregion #region Misc - [Menu("Misc", 10)] public EmptyNode MiscSettings { get; set; } + [Menu("Misc", 13)] public EmptyNode MiscSettings { get; set; } - [Menu("Nearby monsters", "Require a minimum count of nearby monsters to cast buffs?", 101, 10)] + [Menu("Nearby monsters", "Require a minimum count of nearby monsters to cast buffs?", 131, 13)] public ToggleNode RequireMinMonsterCount { get; set; } - [Menu("Range", "Minimum count of nearby monsters to cast", 102, 10)] + [Menu("Range", "Minimum count of nearby monsters to cast", 132, 13)] public RangeNode NearbyMonsterCount { get; set; } - [Menu("Range", "Max distance of monsters to player to count as nearby", 103, 10)] + [Menu("Range", "Max distance of monsters to player to count as nearby", 133, 13)] public RangeNode NearbyMonsterMaxDistance { get; set; } - [Menu("Disable in hideout", "Disable the plugin in hideout?", 104, 10)] + [Menu("Disable in hideout", "Disable the plugin in hideout?", 134, 13)] public ToggleNode DisableInHideout { get; set; } - - [Menu("Debug", "Print debug messages?", 105, 10)] + + [Menu("Debug", "Print debug messages?", 135, 13)] public ToggleNode Debug { get; set; } - - [Menu("Silence errors", "Hide error messages?", 106, 10)] + + [Menu("Silence errors", "Hide error messages?", 136, 13)] public ToggleNode SilenceErrors { get; set; } #endregion diff --git a/C.cs b/C.cs index eabf65e..300609c 100644 --- a/C.cs +++ b/C.cs @@ -12,6 +12,14 @@ public static class SteelSkin public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(1); } + public static class ArcaneCloak + { + public const string BuffName = "arcane_cloak"; + public const string Name = "ArcaneCloak"; + public const string InternalName = "arcane_cloak"; + public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(1); + } + public static class ImmortalCall { public const string BuffName = "mortal_call"; @@ -53,6 +61,60 @@ public static class BloodRage public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(1); } + public static class WarcryBattlemagesCry + { + public const string BuffName = "divine_cry"; + public const string Name = "BattlemagesCry"; + public const string InternalName = "battlemages_cry"; + public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(8); + } + + public static class WarcryEnduringCry + { + public const string BuffName = "enduring_cry_endurance_charge_benefits"; + public const string Name = "EnduringCry"; + public const string InternalName = "enduring_cry"; + public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(8); + } + + public static class WarcryIntimidatingCry + { + public const string BuffName = "intimidating_cry"; + public const string Name = "IntimidatingCry"; + public const string InternalName = "intimidating_cry"; + public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(8); + } + + public static class WarcryAncestralCry + { + public const string BuffName = "ancestral_cry"; + public const string Name = "AncestralCry"; + public const string InternalName = "ancestral_cry"; + public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(8); + } + + public static class WarcryInfernalCry + { + public const string BuffName = ""; + public const string Name = "AbyssalCry"; + public const string InternalName = "infernal_cry"; + public static readonly TimeSpan TimeBetweenCasts = TimeSpan.FromSeconds(8); + } + + public static class WarcryRallyingCry + { + public const string BuffName = ""; + public const string Name = "RallyingCry"; + public const string InternalName = "rallying_cry"; + } + + public static class Berserk + { + public const string BuffName = "berserk"; + public const string Name = "Berserk"; + public const string InternalName = "berserk"; + } + public static class BladeFlurry { public const string BuffName = "charged_attack"; @@ -77,5 +139,10 @@ public static class BladeVortex { public const string BuffName = "blade_vortex_counter"; } + + public static class Rage + { + public const string BuffName = "rage"; + } } } \ No newline at end of file