Нашёл вот такой скриптец. Копает, но что-то не то с паузой между копанием. То ждет что-то, то слишком быстро повторяет действие и по этому выходит "You stop mining".
Может кто-то, кто понимает глянет... Есть ли смысл мучать этот скрипт, либо искать другое что-то.
Заранее спасибо.
P.S. - Ультиму открыл сегодня за много лет, а Orion увидел вообще в первый раз.
/////////////////////////////////////////////////////////////////////////////////////////// //////////////////// -Mining for UORPG server (17.05.2017) by Hotride- //////////////////// ///////////////////////////// -Minimal OA version 2.0.7.0- //////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// -Настройка скрипта- /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// // // Перед запуском требуется: // 1) Настроить WayPoints - массив координат, на которых будут обкапываться тайлы вокруг // персонажа. Желательно записывать их так, что бы персонаж раскапывал как можно больше // тайлов пещеры, и не тратил много времени при перемещениями между точками. // 2) Подготовка ресурсов. // При разгрузке в банк (UnloadToBank): указать ResultContainer как серийник банка // (_info на любую вещь в банке, C=0x... будет серийник банка), закинуть туда реги на // реколл, инструменты, указать OreBag в нем (или, может быть равен ResultContainer). // При разгрузке в контейнер у дома: указать его как ResultContainer, закинуть туда реги // на реколл, инструменты, указать OreBag в нем (или, может быть равен ResultContainer). // 3) Задать Tool (если нужно копать конкретным инструментом), указать ToolType для // добора инструментов из ResultContainer, указать количество инструментов для добора // ToolsCount. // 4) Указать серийники рун или рунбук с дефолтными рунами (в дом RuneHomeSerial и в пещеру // RuneCaveSerial), указать минимальное количество регов ReagentsCount, после которого // добирать их из ResultContainer. // 5) Настроить использование хайда UseHiding. // 6) Настроить расстояние для обкопки DigDistanceX и DigDistanceY. // 7) Если нужно игнорировать некоторые руды при копки (не продолжать копать, если такая руда // попалась) то указать названия руды в IgnoreOreNames, либо оставить это поле пустым. // 8) Если нужно сбрасывать какую-то руду после обкопки (или перед улетом домой) то // указать цвета руды в DropOreColors, либо оставить это поле пустым. // 9) Настроить лимит веса MaxWeight. // // Принцп работы скрипта: // Запускаем непосредственно в пещере. // Скрипт подходит к первой точке, обкапывает все тайлы вокруг на указанном расстоянии и // переходит на следующую точку, повторяет до бесконечности (либо пока не убьют). // При достижении лимита веса сбрасывает указанную руду на пол (под ноги), если перевес // остался - летит на разгрузку и добор расходников. // После этого - летит обратно в пещеру и идет на ту же точку, с которой улетел, // продолжает обкопку. // /////////////////////////////////////////////////////////////////////////////////////////// //Чем будем копать (серийник объекта), если пустая строка - ищет ToolType var Tool = 'pickaxe'; //Тип кирки/лопаты, чем копать, можно указать несколько типов var ToolType = '0x0E85|0x0E86'; //Количество инструментов для добора var ToolsCount = 0; //Контейнер с мешком для руды (или просто для руды, если не нужно скидывать ее в мешок) var ResultContainer = '0x409A986F'; //Контейнер, куда складывать руду (может быть равен ResultContainer, если для руды нет отдельного мешка в нем) var OreBag = '0x409A986F'; //Разгрузка происходит в банк, true - да, false - разгружается в контейнер у дома (или где-то еще) var UnloadToBank = false; //Максимальный вес, при котором выкидывать лишнее из пака (если есть что-то лишнее), если вес не изменился - лететь домой разгружаться var MaxWeight = Player.MaxWeight() - 10; //Серийник руны в дом var RuneHomeSerial = '0x4056158C'; //Серийник руны в перещу var RuneCaveSerial = '0x4058675E'; //Текст физла заклинания var FizzlesText = 'The spell fizzles'; //Сколько брать регов на реколл? var ReagentsCount = 20; //Текст удачной копки var PutText = 'You put'; //Текст не удачной копки или режима вармода (если такое сообщение есть на сервере) var FailText = 'You loosen some|thoughts of battle'; //Текст ошибки мининга (слишком далеко, не могу достать, сдох или что-то еще) var StopText = 'There is nothing here to mine|Try mining|away|no line of|reach that|You cannot mine so|Where do you want|слишком далеко'; //Какую руду прекращать копать, если попалась var IgnoreOreNames = ''; //Какую руду (цвета руды) сбрасывать на землю, когда обрыли все тайлы вокруг себя var DropOreColors = ''; //Прятаться во время обкопки тайлов (true - прятаться, false - нет) var UseHiding = false; //Текст хайдинга var HidingText = 'seem to hide|have hidden'; //Расстояние, на котором копать по X var DigDistanceX = 2; //Расстояние, на котором копать по Y var DigDistanceY = 2; //Список точек, на которых обкапывать тайлы вокруг себя var WayPoints = [ [2439, 94], [2432, 91], [2428, 87], [2422, 90], [2426, 95], [2427, 101], [2427, 106], [2423, 109], ]; /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////// -Глобальные переменные. Не изменять- ////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// //Склейка текстов, что представлены выше. var SearchText = PutText + '|' + FailText + '|' + StopText; //Указатель на текущую точку var CurrentWayPoint = 0; var CurrentMinDropX = 0; var CurrentMaxDropX = 0; var CurrentDropX = 0; var CurrentMinDropY = 0; var CurrentMaxDropY = 0; var CurrentDropY = 0; /////////////////////////////////////////////////////////////////////////////////////////// //Основная фукнция function Mining() { //Роем бесконечно while (true) { //Проходимся по списку точек for (CurrentWayPoint = 0; CurrentWayPoint < WayPoints.length; CurrentWayPoint++) { var point = WayPoints[CurrentWayPoint]; //Пытаемся прийти на точку if (WalkToPoint(point[0], point[1])) { //Пытаемся обкопать все вокруг себя if (!MiningHere(point[0], point[1])) { //Завершаем скрипт, если что-то пошло не так (только для теста, в дальнейшем заменить на какое-то действие) return; } } } //Обеспечение задержек в вечных циклах Orion.Wait(100); } } /////////////////////////////////////////////////////////////////////////////////////////// //Функция обкопки тайлов вокруг персонажа function MiningHere(x, y) { //Сбрасываем вармод, если это необходимо if (Player.WarMode()) { Orion.WarMode(false); Orion.Wait(100); } //Проход по квадрату for (var x = -DigDistanceX; x <= DigDistanceX; x++) { for (var y = -DigDistanceY; y <= DigDistanceY; y++) { //Роем, если вернулось false - максимальный вес достигнут if (!Dig(x, y)) { Orion.Print(0x0022, 'Достигнут максимальный вес!'); return false; } Orion.Wait(100); } } DropExtraOres(); return true; } /////////////////////////////////////////////////////////////////////////////////////////// //Функция получения серийника инструмента function GetTool() { var obj = Orion.FindObject(Tool); if (obj == null) { var list = Orion.FindType(ToolType, -1, self); if (list.length) return list[0]; else { list = Orion.FindType(ToolType); if (list.length) return list[0]; } return ''; } return obj.Serial(); } /////////////////////////////////////////////////////////////////////////////////////////// //Функция выкапывания тайла function Dig(x, y) { //Пока живы - роем while (!Player.Dead()) { //Прячемся if (UseHiding && !Player.Hidden()) { Orion.UseSkill('Hiding'); Orion.WaitJournal(HidingText, Orion.Now(), Orion.Now() + 7000, 'sys|my'); } Orion.UseObject(toolSerial); //Проверяем возможность наведения автотаргета на тайл if (!Orion.ValidateTargetTileRelative('cave', x, y)) break; var toolSerial = GetTool(); if (toolSerial == '') { Orion.Print('0x0021', 'Tool is not found!!!'); Orion.Wait(1000); return false; } //Используем кирку и тыкаем со смещением относительно персонажа на тайл Orion.WaitTargetTileRelative('cave', x, y, 0); Orion.UseObject(toolSerial); var msg = Orion.WaitJournal(SearchText, Orion.Now(), Orion.Now() + 15000, 'sys|my'); Orion.Wait(5000); //Если сдохли - выходим из цикла if (Player.Dead()) return false; //Если максимальный вес достигнут - пытаемся сбросить лишнюю руду на пол if (Player.Weight() >= MaxWeight) { DropExtraOres(); //Если это не помогло (запас веса 50) - летим разгружаться if (Player.Weight() >= MaxWeight - 10) RecallUnload(); } if (msg != null) { var text = msg.Text(); //Если что-то упало в пак if (Orion.Contains(text, PutText)) { //Если это нечто - игнорируемая руда - выходим из цикла if (Orion.Contains(text, IgnoreOreNames)) break; } else if (Orion.Contains(text, FailText)) //Дернем вармод при физле/сообщении о том, что мы в вармоде Orion.WarMode(false); else if (Orion.Contains(text, StopText)) //Если нельзя достать до тайла или тут больше нет руды - выходим break; } Orion.Wait(100); } return true; } /////////////////////////////////////////////////////////////////////////////////////////// //Функция сброса предмета на землю, с проверкой на персонажа (под персонажей нельзя сбрасывать) function DropGround(serial) { var obj = Orion.FindObject(serial); if (obj == null) return false; var oldContainer = obj.Container(); //Проходимся по координатам for (var x = CurrentDropX; x <= CurrentMaxDropX; x++) { for (var y = CurrentDropY; y <= CurrentMaxDropY; y++) { for (var i = 0; i < 3; i++) { Orion.Drop(serial, 0, x, y, Player.Z()); Orion.Wait('moveitemdelay'); if (oldContainer != obj.Container()) return true; } } CurrentDropY = CurrentMinDropY; } CurrentDropX = CurrentMinDropX; return false; } /////////////////////////////////////////////////////////////////////////////////////////// //Функция сброса лишней руды function DropExtraOres() { //Если не указаны цвета руды - выходим if (DropOreColors == '') return; //Максимальная дистанция дропа var maxDropDistance = 1; //Минимальные и максимальные координаты для дропа CurrentMinDropX = Player.X() - maxDropDistance; CurrentMaxDropX = Player.X() + maxDropDistance; CurrentMinDropY = Player.Y() - maxDropDistance; CurrentMaxDropY = Player.Y() + maxDropDistance; CurrentDropX = CurrentMinDropX; CurrentDropY = CurrentMinDropY; //Крутим цикл, пока не сбросим всю руду while (true) { //Поиск всех типов руды всех указанных цветов var list = Orion.FindType('0x19B7|0x19BA|0x19B8|0x19B9', DropOreColors); //Ничего не нашлось - выходим if (!list.length) break; //Сбрасываем под ноги все что нашлось for (var i = 0; i < list.length; i++) { if (!DropGround(list[i])) return; Orion.Wait(100); } Orion.Wait(100); } } /////////////////////////////////////////////////////////////////////////////////////////// //Функция разгрузки function UnloadOres() { if (UnloadToBank) Orion.Say('bank'); else Orion.UseObject(ResultContainer); Orion.Wait(500); if (ResultContainer != OreBag) { Orion.UseObject(OreBag); Orion.Wait(500); } //Крутим цикл, пока не сбросим всю руду while (true) { //Поиск всех типов руды всех указанных цветов var list = Orion.FindType('0x19B7|0x19BA|0x19B8|0x19B9'); //Ничего не нашлось - выходим if (!list.length) break; //Сбрасываем под ноги все что нашлось for (var i = 0; i < list.length; i++) { Orion.MoveItem(list[i], 0, OreBag); Orion.Wait('moveitemdelay'); } Orion.Wait(100); } } /////////////////////////////////////////////////////////////////////////////////////////// //Функция добора расходников function ReloadConsumables() { var types = ['bp', 'bm', 'mr']; for (var i = 0; i < types.length; i++) { var count = Orion.Count(types[i]); if (count < ReagentsCount) { var list = Orion.FindType(types[i], '-1', ResultContainer); if (!list.length) { Orion.Print('0x0021', 'Reagent is not found ' + types[i]); continue; } Orion.MoveItem(list[0], ReagentsCount / 2); Orion.Wait('moveitemdelay'); } //Дополнительное время ожидания Orion.Wait('moveitemdelay'); } var list = Orion.FindType(ToolType); if (list.length < ToolsCount) { var count = ToolsCount - list.length; var list = Orion.FindType(types[i], '-1', ResultContainer); if (!list.length) Orion.Print('0x0021', 'Tool is not found ' + types[i]); else { if (list.length < count) count = list.length; for (var i = 0; i < count; i++) { Orion.MoveItem(list[i]); Orion.Wait('moveitemdelay'); } //Дополнительное время ожидания Orion.Wait('moveitemdelay'); } } } /////////////////////////////////////////////////////////////////////////////////////////// function Recall() { Orion.WalkTo( 2441, 94, 30, 0); Orion.WalkTo( 2451,91, 30, 0); } function Recall2() { Orion.WalkTo( 2451, 91, 30, 0); Orion.WalkTo( 2441, 94, 30, 0); } /////////////////////////////////////////////////////////////////////////////////////////// //Фукнция разгрузки function RecallUnload() { //xodilka домой Recall(); Orion.Wait(1000); //Разгрузка UnloadOres(); Orion.Wait(1000); //Добор расходников ReloadConsumables(); Orion.Wait(1000); //xodilka обратно в перещу Recall2() //Проходимся по списку точек, возвращаемся на место, где стояли for (var i = 0; i < CurrentWayPoint; i++) { var point = WayPoints[i]; //Пытаемся прийти на точку WalkToPoint(point[0], point[1]); } } /////////////////////////////////////////////////////////////////////////////////////////// //Функция ходилки, можно добавить сюда что-то еще function WalkToPoint(x, y) { return Orion.WalkTo(x, y, 0, 0); } ///////////////////////////////////////////////////////////////////////////////////////////