using System; using System.Linq; using System.Threading; using robotManager.Helpful; using robotManager.Products; using wManager.Wow; using wManager.Wow.Class; using wManager.Wow.Helpers; using wManager.Wow.ObjectManager; public class Main : ICustomClass { private bool _isLaunched; // ==================== НАСТРОЙКИ СПЕЛЛОВ ==================== // true = спелл используется, false = отключён // Бафы private const bool USE_ARCANE_INTELLECT = true; private const bool USE_ICE_ARMOR = true; private const bool USE_DAMPEN_MAGIC = true; // Защитные private const bool USE_ICE_BARRIER = true; private const bool USE_ICE_BLOCK = true; // Кулдауны private const bool USE_WATER_ELEMENTAL = true; private const bool USE_ICY_VEINS = true; private const bool USE_COLD_SNAP = true; private const bool USE_EVOCATION = true; // Боевые private const bool USE_FROSTBOLT = true; private const bool USE_ICE_LANCE = true; private const bool USE_FROST_NOVA = true; private const bool USE_CONE_OF_COLD = true; private const bool USE_FIRE_BLAST = true; private const bool USE_COUNTERSPELL = true; // Еда/вода private const bool USE_CONJURE_FOOD = true; private const bool USE_CONJURE_WATER = true; // ============================================================ // Settings / Configuration private readonly string[] _foodNames = new string[] { "Conjured Muffin", "Conjured Bread", "Conjured Rye", "Conjured Pumpernickel", "Conjured Sourdough", "Conjured Sweet Roll", "Conjured Cinnamon Roll" }; private readonly string[] _waterNames = new string[] { "Conjured Water", "Conjured Fresh Water", "Conjured Purified Water", "Conjured Spring Water", "Conjured Mineral Water", "Conjured Sparkling Water", "Conjured Crystal Water", "Conjured Mountain Spring Water", "Conjured Glacier Water" }; // Constants private const int FOOD_CHECK_INTERVAL_SECONDS = 300; // 5 минут private const int FOOD_LOW_THRESHOLD = 5; // Порог "мало еды" private const int WATER_LOW_THRESHOLD = 5; // Порог "мало воды" private const int BUFF_REBUFF_TIME_MS = 600000; // 10 минут // Food management tracking private DateTime _lastFoodCheck = DateTime.MinValue; private int _currentFoodCount = 0; private int _currentWaterCount = 0; // Buffs / Utility private Spell ArcaneIntellect = new Spell("Arcane Intellect"); private Spell IceArmor = new Spell("Ice Armor"); private Spell IceBarrier = new Spell("Ice Barrier"); private Spell IceBlock = new Spell("Ice Block"); private Spell WaterElemental = new Spell("Summon Water Elemental"); private Spell Evocation = new Spell("Evocation"); private Spell IcyVeins = new Spell("Icy Veins"); private Spell ColdSnap = new Spell("Cold Snap"); private Spell ConjureFood = new Spell("Conjure Food"); private Spell ConjureWater = new Spell("Conjure Water"); // Combat private Spell Frostbolt = new Spell("Frostbolt"); private Spell IceLance = new Spell("Ice Lance"); private Spell FrostNova = new Spell("Frost Nova"); private Spell ConeOfCold = new Spell("Cone of Cold"); private Spell FireBlast = new Spell("Fire Blast"); private Spell Counterspell = new Spell("Counterspell"); private Spell DampenMagic = new Spell("Dampen Magic"); public float Range { get { return 30f; } } public void Initialize() { _isLaunched = true; // КРИТИЧЕСКИ ВАЖНО: создать еду/воду ДО запуска ротации PerformInitialFoodCheck(); Logging.Write("Frost Mage Grind FC initialized."); Rotation(); } public void Dispose() { _isLaunched = false; Logging.Write("Frost Mage Grind FC stopped."); } public void ShowConfiguration() { } private int CountItems(string[] itemNames) { int count = 0; foreach (string itemName in itemNames) { count = count + ItemsManager.GetItemCountByNameLUA(itemName); } return count; } private bool ConjureItem(Spell spell, string itemType) { if (!spell.KnownSpell || !spell.IsSpellUsable) return false; Logging.Write(string.Format("[FoodCheck] Creating {0}...", itemType)); spell.Launch(); // Ждём окончания каста while (ObjectManager.Me.IsCast || ObjectManager.Me.CastingSpellId != 0) { Thread.Sleep(100); } Thread.Sleep(500); Logging.Write(string.Format("[FoodCheck] {0} created!", itemType)); return true; } private void CheckFoodWaterLevels() { _currentFoodCount = CountItems(_foodNames); _currentWaterCount = CountItems(_waterNames); _lastFoodCheck = DateTime.Now; Logging.Write(string.Format("[FoodCheck] Current: Food={0}, Water={1}", _currentFoodCount, _currentWaterCount)); if (_currentFoodCount == 0) Logging.Write("[FoodCheck] CRITICAL: No food!"); else if (_currentFoodCount < FOOD_LOW_THRESHOLD) Logging.Write(string.Format("[FoodCheck] LOW: Food={0}, will create when convenient", _currentFoodCount)); if (_currentWaterCount == 0) Logging.Write("[FoodCheck] CRITICAL: No water!"); else if (_currentWaterCount < WATER_LOW_THRESHOLD) Logging.Write(string.Format("[FoodCheck] LOW: Water={0}, will create when convenient", _currentWaterCount)); } private void PerformInitialFoodCheck() { try { Logging.Write("[FoodCheck] Performing initial food/water check..."); CheckFoodWaterLevels(); FoodManagement(); Logging.Write("[FoodCheck] Initial check complete!"); } catch (Exception ex) { Logging.WriteError("[FoodCheck] Error: " + ex.Message); } } private void Rotation() { Logging.Write("Frost Mage Grind running."); while (_isLaunched) { try { if (!Products.InPause && !ObjectManager.Me.IsDeadMe) { BuffRotation(); FoodManagement(); if (Fight.InFight && ObjectManager.Target.IsValid && ObjectManager.Target.IsAttackable) { CombatRotation(); } } } catch (Exception ex) { Logging.WriteError("ERROR: " + ex); } Thread.Sleep(50); } } private void BuffRotation() { if (Fight.InFight || ObjectManager.Me.InCombat) return; // === ARCANE INTELLECT === if (USE_ARCANE_INTELLECT) { int arcaneIntellectTimeLeft = ObjectManager.Me.BuffTimeLeft("Arcane Intellect"); if (ArcaneIntellect.KnownSpell && ArcaneIntellect.IsSpellUsable && arcaneIntellectTimeLeft <= 0 && !ObjectManager.Me.IsCast) { ArcaneIntellect.Launch(); Thread.Sleep(Usefuls.Latency + 100); return; } if (ArcaneIntellect.KnownSpell && ArcaneIntellect.IsSpellUsable && arcaneIntellectTimeLeft > 0 && arcaneIntellectTimeLeft < BUFF_REBUFF_TIME_MS && !ObjectManager.Me.IsMounted && !ObjectManager.Me.IsCast) { ArcaneIntellect.Launch(); Thread.Sleep(Usefuls.Latency + 100); return; } } // === ICE ARMOR === if (USE_ICE_ARMOR) { int iceArmorTimeLeft = ObjectManager.Me.BuffTimeLeft("Ice Armor"); if (IceArmor.KnownSpell && IceArmor.IsSpellUsable && iceArmorTimeLeft <= 0 && !ObjectManager.Me.IsCast) { IceArmor.Launch(); Thread.Sleep(Usefuls.Latency + 100); return; } if (IceArmor.KnownSpell && IceArmor.IsSpellUsable && iceArmorTimeLeft > 0 && iceArmorTimeLeft < BUFF_REBUFF_TIME_MS && !ObjectManager.Me.IsMounted && !ObjectManager.Me.IsCast) { IceArmor.Launch(); Thread.Sleep(Usefuls.Latency + 100); } } // === DAMPEN MAGIC === if (USE_DAMPEN_MAGIC) { int dampenTimeLeft = ObjectManager.Me.BuffTimeLeft("Dampen Magic"); if (DampenMagic.KnownSpell && DampenMagic.IsSpellUsable && dampenTimeLeft <= 0 && !ObjectManager.Me.IsCast) { DampenMagic.Launch(); Thread.Sleep(Usefuls.Latency + 100); return; } if (DampenMagic.KnownSpell && DampenMagic.IsSpellUsable && dampenTimeLeft > 0 && dampenTimeLeft < BUFF_REBUFF_TIME_MS && !ObjectManager.Me.IsMounted && !ObjectManager.Me.IsCast) { DampenMagic.Launch(); Thread.Sleep(Usefuls.Latency + 100); } } } private void FoodManagement() { if (!USE_CONJURE_FOOD && !USE_CONJURE_WATER) return; if (_lastFoodCheck == DateTime.MinValue || (DateTime.Now - _lastFoodCheck).TotalSeconds >= FOOD_CHECK_INTERVAL_SECONDS) { CheckFoodWaterLevels(); } if (ObjectManager.Me.IsDeadMe) return; bool foodCritical = USE_CONJURE_FOOD && (_currentFoodCount == 0); bool waterCritical = USE_CONJURE_WATER && (_currentWaterCount == 0); bool foodLow = USE_CONJURE_FOOD && (_currentFoodCount > 0 && _currentFoodCount < FOOD_LOW_THRESHOLD); bool waterLow = USE_CONJURE_WATER && (_currentWaterCount > 0 && _currentWaterCount < WATER_LOW_THRESHOLD); if (!foodCritical && !waterCritical && !foodLow && !waterLow) return; // КРИТИЧЕСКАЯ СИТУАЦИЯ if (foodCritical || waterCritical) { if (!ObjectManager.Me.IsCast && !Fight.InFight && !ObjectManager.Me.InCombat) { int stopTime = (foodCritical && waterCritical) ? 10000 : 5000; MovementManager.StopMoveTo(false, stopTime); if (foodCritical && !ObjectManager.Me.IsCast) { if (ConjureItem(ConjureFood, "food (CRITICAL)")) { _currentFoodCount = 20; } } if (waterCritical && !ObjectManager.Me.IsCast) { if (ConjureItem(ConjureWater, "water (CRITICAL)")) { _currentWaterCount = 20; } } } return; } // НИЗКИЙ УРОВЕНЬ if ((foodLow || waterLow) && !ObjectManager.Me.IsMounted && !ObjectManager.Me.IsCast && !Fight.InFight && !ObjectManager.Me.InCombat) { int stopTime = (foodLow && waterLow) ? 10000 : 5000; MovementManager.StopMoveTo(false, stopTime); if (foodLow && !ObjectManager.Me.IsCast) { if (ConjureItem(ConjureFood, "food (low level)")) { _currentFoodCount = 20; } } if (waterLow && !ObjectManager.Me.IsCast) { if (ConjureItem(ConjureWater, "water (low level)")) { _currentWaterCount = 20; } } } } private void CombatRotation() { WoWUnit target = ObjectManager.Target; if (target == null || !target.IsAlive) return; WoWLocalPlayer me = ObjectManager.Me; WoWUnit pet = ObjectManager.Pet; bool isCasting = me.IsCast; bool petValid = pet.IsValid; float distance = target.GetDistance; bool targetFrozen = target.HaveBuff("Frost Nova") || target.HaveBuff("Freeze") || target.HaveBuff("Frostbite"); var enemiesAttackingMe = ObjectManager.GetObjectWoWUnit() .Where(u => u.IsAlive && u.IsAttackable && u.IsTargetingMe && u.GetDistance <= 30f) .ToList() .Count; // Ice Barrier - всегда поддерживаем if (USE_ICE_BARRIER && IceBarrier.KnownSpell && IceBarrier.IsSpellUsable && !me.HaveBuff("Ice Barrier") && !isCasting) { IceBarrier.Launch(); Thread.Sleep(Usefuls.Latency + 100); } // Counterspell - прерывание вражеского каста (высокий приоритет) if (USE_COUNTERSPELL && Counterspell.KnownSpell && Counterspell.IsSpellUsable && target.IsCast && target.CanInterruptCasting && distance <= 30f) { Counterspell.Launch(); Thread.Sleep(Usefuls.Latency + 100); } // Ice Block - экстренная защита при низком HP if (USE_ICE_BLOCK && IceBlock.KnownSpell && IceBlock.IsSpellUsable && me.HealthPercent < 20 && !isCasting) { Logging.Write("Ice Block - HP below 20%"); IceBlock.Launch(); Thread.Sleep(Usefuls.Latency + 100); while (me.HaveBuff("Ice Block")) { Thread.Sleep(500); } return; } // Evocation - критически низкая мана if (USE_EVOCATION && me.ManaPercentage < 5 && Evocation.KnownSpell && Evocation.IsSpellUsable && !isCasting) { Logging.Write("Critical mana, using Evocation"); Evocation.Launch(); while (me.IsCast || me.CastingSpellId != 0) { Thread.Sleep(100); } } // Water Elemental - на каждом мобе if (USE_WATER_ELEMENTAL && WaterElemental.KnownSpell && WaterElemental.IsSpellUsable && (!petValid || pet.IsDead) && !isCasting) { WaterElemental.Launch(); Thread.Sleep(Usefuls.Latency + 250); Lua.LuaDoString("PetAttack();"); } // Icy Veins - 2+ мобов if (USE_ICY_VEINS && IcyVeins.KnownSpell && IcyVeins.IsSpellUsable && enemiesAttackingMe >= 2 && !me.HaveBuff("Icy Veins") && !isCasting) { IcyVeins.Launch(); Thread.Sleep(Usefuls.Latency + 100); } // Cold Snap - сброс КД элементаля при 2+ мобах if (USE_COLD_SNAP && ColdSnap.KnownSpell && ColdSnap.IsSpellUsable && enemiesAttackingMe >= 2 && WaterElemental.KnownSpell && !petValid && !WaterElemental.IsSpellUsable && !isCasting) { ColdSnap.Launch(); Thread.Sleep(Usefuls.Latency + 100); } // Cone of Cold - 2+ мобов, ближний бой if (USE_CONE_OF_COLD && ConeOfCold.KnownSpell && ConeOfCold.IsSpellUsable && enemiesAttackingMe >= 2 && distance <= 10f && !isCasting) { ConeOfCold.Launch(); } // Frost Nova - дебаф на крит (только если цель ещё живучая) if (USE_FROST_NOVA && FrostNova.KnownSpell && FrostNova.IsSpellUsable && distance <= 10f && target.HealthPercent >= 50 && !targetFrozen && !isCasting) { FrostNova.Launch(); } // Ice Lance - по фрозену if (USE_ICE_LANCE && IceLance.KnownSpell && IceLance.IsSpellUsable && distance <= 30f && targetFrozen && !isCasting) { IceLance.Launch(); } // Fire Blast - добивание при низком HP цели if (USE_FIRE_BLAST && FireBlast.KnownSpell && FireBlast.IsSpellUsable && distance <= 20f && target.HealthPercent < 10 && !isCasting) { FireBlast.Launch(); } // Frostbolt - спам if (USE_FROSTBOLT && Frostbolt.KnownSpell && Frostbolt.IsSpellUsable && distance <= 30f && !isCasting) { Frostbolt.Launch(); } } }