using System; using System.ComponentModel; using System.Linq; using System.Threading; using robotManager.Events; using robotManager.FiniteStateMachine; using robotManager.Helpful; using wManager.Plugin; using wManager.Wow.Bot.Tasks; using wManager.Wow.Helpers; using wManager.Wow.ObjectManager; public class Main : IPlugin { public void Initialize() { Logging.Write("[AmmoManager] Plugin started"); AmmoStateAdder.Start(); } public void Dispose() { AmmoStateAdder.Stop(); Logging.Write("[AmmoManager] Plugin stopped"); } public void Settings() { } } public class AmmoStateAdder { // ============================================================ // НАСТРОЙКИ ПАТРОНОВ // ============================================================ private const string AMMO_NAME = "Wicked Arrow"; private const int AMMO_TARGET_COUNT = 2800; private const int AMMO_THRESHOLD = 2000; private const int AMMO_CRITICAL = 200; // ============================================================ // ВЕНДОРЫ - Раскомментируй нужного для текущего спота // ============================================================ // ============================================================ // GOSSIP OPTION // -1 = не использовать (обычные вендоры) // 1, 2, 3... = номер опции в меню (если у вендора есть диалог) // ============================================================ // Theramore // private const int VENDOR_ENTRY = 4892; // private static readonly Vector3 VENDOR_POSITION = new Vector3(-3779.607f, -4542.269f, 11.40062f); // private const int GOSSIP_OPTION = -1; // Hellfire Peninsula - Honor Hold private const int VENDOR_ENTRY = 16826; private static readonly Vector3 VENDOR_POSITION = new Vector3(-708.8713f, 2739.131f, 94.7337f); private const int GOSSIP_OPTION = 2; public static bool ShouldBuyAmmo = false; private static AmmoBuying _ammoBuyingState = null; private static bool _isStarted = false; private static bool _stateAdded = false; private static Thread _checkThread = null; public static void Start() { if (_isStarted) return; _isStarted = true; FiniteStateMachineEvents.OnAfterRunState += OnAfterRunState; _checkThread = new Thread(AmmoCheckLoop); _checkThread.IsBackground = true; _checkThread.Start(); Logging.Write("[AmmoManager] StateAdder started"); } public static void Stop() { _isStarted = false; ShouldBuyAmmo = false; _stateAdded = false; _checkThread = null; FiniteStateMachineEvents.OnAfterRunState -= OnAfterRunState; Logging.Write("[AmmoManager] StateAdder stopped"); } private static void AmmoCheckLoop() { while (_isStarted && robotManager.Products.Products.IsStarted) { try { if (wManager.Wow.Helpers.Conditions.InGameAndConnectedAndProductStartedNotInPause) { int ammoCount = ItemsManager.GetItemCountByNameLUA(AMMO_NAME); if (ammoCount < AMMO_CRITICAL && !wManager.Wow.Bot.States.ToTown.ForceToTown && !ShouldBuyAmmo) { Logging.Write("[AmmoManager] Ammo critical (" + ammoCount.ToString() + " < " + AMMO_CRITICAL.ToString() + "), forcing ToTown"); ShouldBuyAmmo = true; wManager.Wow.Bot.States.ToTown.ForceToTown = true; } } } catch (Exception e) { Logging.WriteError("[AmmoManager] AmmoCheckLoop error: " + e.ToString()); } Thread.Sleep(60000); } } private static void OnAfterRunState(Engine engine, State state) { try { if (engine == null || state == null) return; if (state.DisplayName == "To Town") { if (!_stateAdded) { _ammoBuyingState = new AmmoBuying(); AddStateAfter(engine, _ammoBuyingState, "To Town"); _stateAdded = true; } int ammoCount = ItemsManager.GetItemCountByNameLUA(AMMO_NAME); if (ammoCount < AMMO_THRESHOLD) { Logging.Write("[AmmoManager] Ammo low (" + ammoCount.ToString() + "/" + AMMO_THRESHOLD.ToString() + "), setting buy flag"); ShouldBuyAmmo = true; } else { Logging.Write("[AmmoManager] Ammo OK (" + ammoCount.ToString() + "/" + AMMO_THRESHOLD.ToString() + ")"); } } } catch (Exception e) { Logging.WriteError("[AmmoManager] OnAfterRunState error: " + e.ToString()); } } public static void AddStateAfter(Engine engine, State state, string afterStateName) { if (engine == null || state == null) { Logging.WriteError("[AmmoManager] AddStateAfter: engine or state is null"); return; } // Проверка на дублирование if (engine.States.Exists(s => s.DisplayName == state.DisplayName)) { Logging.Write("[AmmoManager] State '" + state.DisplayName + "' already exists, skipping"); return; } try { State stateToPlaceAfter = engine.States.Find(s => s.DisplayName == afterStateName); if (stateToPlaceAfter == null) { Logging.WriteError("[AmmoManager] Couldn't find state '" + afterStateName + "'"); return; } int priorityToSet = stateToPlaceAfter.Priority + 1; // Сдвигаем все State с Priority > найденного на +1 foreach (State s in engine.States) { if (s.Priority > stateToPlaceAfter.Priority) s.Priority++; } state.Priority = priorityToSet; engine.AddState(state); engine.States.Sort(); Logging.Write("[AmmoManager] State '" + state.DisplayName + "' added after '" + afterStateName + "' with priority " + priorityToSet.ToString()); } catch (Exception ex) { Logging.WriteError("[AmmoManager] AddStateAfter error: " + ex.ToString()); } } public static void BuyAmmo() { try { int currentAmmo = ItemsManager.GetItemCountByNameLUA(AMMO_NAME); int needed = AMMO_TARGET_COUNT - currentAmmo; if (needed <= 0) { Logging.Write("[AmmoManager] Ammo already at target (" + currentAmmo.ToString() + "), skipping"); return; } int stacksToBuy = needed / 200; Logging.Write("[AmmoManager] Starting ammo purchase. Current: " + currentAmmo.ToString() + ", buying " + stacksToBuy.ToString() + " stacks"); GoToTask.ToPositionAndIntecractWithNpc( VENDOR_POSITION, VENDOR_ENTRY, GOSSIP_OPTION, false, null, false ); Thread.Sleep(2000 + Usefuls.Latency); for (int i = 0; i < stacksToBuy; i++) { Vendor.BuyItem(AMMO_NAME, 200); Thread.Sleep(Usefuls.Latency + 200); } Thread.Sleep(500 + Usefuls.Latency); Logging.Write("[AmmoManager] Purchase complete! Bought " + (stacksToBuy * 200).ToString() + " arrows"); } catch (Exception e) { Logging.WriteError("[AmmoManager] BuyAmmo error: " + e.ToString()); } } } public class AmmoBuying : State { public override string DisplayName { get { return "Ammo Buying"; } } public override int Priority { get; set; } public override bool NeedToRun { get { return AmmoStateAdder.ShouldBuyAmmo; } } public override void Run() { try { AmmoStateAdder.BuyAmmo(); } finally { AmmoStateAdder.ShouldBuyAmmo = false; } } }