Перейти к содержанию
Форум шарда Middle-Earth
Авторизация  
nepret

Копирования рунбуки и ... не только...

Рекомендуемые сообщения

stealth version 9.6.1  (<- делался на версии)

Копирования рунбуки и ... не только...

Как запустить:  читать тут

Что делает:

  • Летает по рунам из первой рунбуки, маркает на точках прилёта руны, переименовывает их и запихивает во вторую.
  • Если чара убили или упал сервак, после повторного запуска продолжит с руны на которой остановился. (смотрит по числу рун, а не по названию, мешать их не советую)
  • Может летать как по регам так и по скролам, есть в настройках.
  • По завершению, можно отправить домой. с.м. настройки.

Инструкция по применению:

  1. Руны в пак.
  2. Заправить рунбуку скролами и бекпак регами. (для рекола и для Марка)
  3. Подправить настройки под себя.
  4. Запустить скрипт.

"и ... не только... " будет ниже.

 

from datetime import datetime
from py_stealth import *


class Runebook:
    def __init__(self, runebook_id: int):
        self._runebook_id = runebook_id
        self.info_runebook = {}

    def __call__(self, *args, **kwargs):
        pass

    @staticmethod
    def _check_connected() -> bool:
        if Connected():
            return True
        print("Ошибка: нет соединения с сервером.")
        return False

    def _open_backpack(self, pack=None) -> bool:
        if pack is None:
            pack = Backpack()
        if self._check_connected():
            for i in range(5):
                UseObject(pack)
                if LastContainer() == pack:
                    return True
                Wait(1000)
            print("Ошибка: не смог открыть бэкпак.")
        return False

    def _check_runebook(self, runebook_id: int) -> bool:
        if self._open_backpack():
            if GetParent(runebook_id) == Backpack():
                return True
            print(f"Ошибка: рунбука {hex(runebook_id)} не в бэкпаке.")
        return False

    def _open_runebook(self, runebook_id: int) -> bool:
        if self._check_runebook(runebook_id=runebook_id):
            while GetGumpsCount():
                CloseSimpleGump(GetGumpsCount() - 1)
            temp = GetGumpsCount()
            for i in range(10):
                UseObject(runebook_id)
                if temp < GetGumpsCount():
                    return True
                Wait(500)
            print("Ошибка: не смог открыть рунбуку.")
        return False

    def _check_reagents(self, pack=None, gate=False) -> bool:
        '''
        :param pack: если реги в бекпаке, то вызываем пустым, если в мешке, шкатулке, передаём id контейнера
        '''
        if pack is not None:
            self._open_backpack(pack=pack)
        if not gate:
            if any(i < 1 for i in [BPCount(), MRCount(), BMCount()]):
                print(f'Недостаточно реагентов (BP:{BPCount()}, MR:{MRCount()}, BM:{BMCount()})')
                return False
        else:
            if any(i < 1 for i in [BPCount(), MRCount(), SACount()]):
                print(f'Недостаточно реагентов (BP:{BPCount()}, MR:{MRCount()}, SA:{SACount()})')
                return False
        return True

    @staticmethod
    def _check_mana(gate=False) -> bool:
        if not gate:
            if Mana() < 11:
                print(f"Мало маны! <11 ({Mana()}/{MaxMana()})")
                return False
        else:
            if Mana() < 40:
                print(f"Мало маны! <40 ({Mana()}/{MaxMana()})")
                return False
        return True

    def _find_rune(self, rune, runebook_id=None) -> dict | bool:
        '''
        :param runebook_id: если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :param rune: принимает номер руны(НЕ индекс) в рунбуке с 1 по 16
        :return: возвращает словарь с номерами гампов
        {"name": "sortir","set_def": 501, "scroll": 601,"drop": 81,"reagent": 2,"gate": 3}
        '''
        if runebook_id is None:
            runebook_id = self._runebook_id
        if _pull := self.get_info_runebook(runebook_id=runebook_id):
            if isinstance(rune, int):
                if _pull['info']['count_rune'] >= rune - 1:
                    return _pull['gumps'][rune - 1]
            else:
                for i in _pull['gumps']:
                    if i["name"] in rune:
                        return i
        print(f"Ошибка: руна не найдена")
        return False

    def get_info_runebook(self, runebook_id=None) -> dict | bool:
        '''
        :param runebook_id:  если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :return: возвращает словарь с общей информацие о рунбуке и гампами.
        {
            "gumps": [{"name": "sortir","set_def": 501, "scroll": 601,"drop": 81,"reagent": 2,"gate": 3}, [...], ...n],
            "info": {'name': Basyan, 'charge': 2, 'charge_max': 10, 'count_rune': 7}
        }
        '''
        if runebook_id is None:
            runebook_id = self._runebook_id
        if self._open_runebook(runebook_id=runebook_id):
            info_gumps = GetGumpInfo(GetGumpsCount() - 1)
            count_rune = int((info_gumps['GumpButtons'][len(info_gumps['GumpButtons']) - 2]['ReturnValue']) / 2)

            temp_pull_gump = {'gumps': []}
            for n, i, r in zip(range(7, count_rune + 7), range(1, count_rune + 1), range(2, 99, 2)):
                temp_pull_gump['gumps'].append({
                    "name": info_gumps['Text'][n][0],
                    "set_def": 500 + i,
                    "scroll": 600 + i,
                    "drop": 80 + i,
                    "reagent": r,
                    "gate": r + 1
                })

            temp_pull_gump.update({"info": {'name': GetTooltip(runebook_id),
                                            'charge': int(info_gumps['Text'][3][0]),
                                            'charge_max': int(info_gumps['Text'][4][0]),
                                            'count_rune': int(count_rune)}})

            if runebook_id == self._runebook_id:
                self.info_runebook = temp_pull_gump
            return temp_pull_gump
        return False

    def recall(self, rune, pack=None, reagents=False) -> bool:
        '''
        :param pack: если реги в бекпаке, то вызываем пустым, если в мешке, шкатулке, передаём id контейнера
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :param reagents: устой и false рекол по скроллам, если true, рекол по регам
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune):
            if not reagents:
                if self.info_runebook['info']['charge'] <= 0:
                    print(f"АХТУНГ: заправь рунбуку. charge "
                          f"{self.info_runebook['info']['charge']}/{self.info_runebook['info']['charge_max']}")
                    return False
                NumGumpButton(GetGumpsCount() - 1, _rune["scroll"])
                return True
            else:
                if self._check_reagents(pack=pack) and self._check_mana():
                    NumGumpButton(GetGumpsCount() - 1, _rune["reagent"])
                    return True
        return False

    def gate(self, rune, pack=None) -> bool:
        '''
        :param pack: если реги в бекпаке, то вызываем пустым, если в мешке, шкатулке, передаём id контейнера
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune):
            if self._check_reagents(gate=True, pack=pack) and self._check_mana(gate=True):
                NumGumpButton(GetGumpsCount() - 1, _rune["gate"])
                return True
        return False

    def recharge(self, scrolls=None) -> bool:
        '''
        :param scrolls: если пустой, то вызовет таргет речерджа или указать ID стопки с рекалами
        :return: boolean
        '''
        if _rune := self.get_info_runebook():
            if self.info_runebook['info']['charge'] < self.info_runebook['info']['charge_max']:
                if TargetPresent():
                    CancelTarget()
                NumGumpButton(GetGumpsCount() - 1, 800)
                for i in range(5):
                    if TargetPresent():
                        if isinstance(scrolls, int):
                            WaitTargetObject(scrolls)
                        break
                    Wait(500)
            return True
        return False

    def set_def_rune(self, rune) -> bool:
        '''
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune):
            NumGumpButton(GetGumpsCount() - 1, _rune["set_def"])
            return True
        return False

    def drop_rune(self, rune, runebook_id=None) -> int | bool:
        '''
        :param runebook_id: если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune, runebook_id=runebook_id):
            while f := FindTypeEx(0x1F14, 0xFFFF, Backpack(), False):
                Ignore(f)
            NumGumpButton(GetGumpsCount() - 1, _rune["drop"])
            drop_rune = FindTypeEx(0x1F14, 0xFFFF, Backpack(), False)
            IgnoreReset()
            return drop_rune
        return False

    def add_rune(self, rune_id: int, runebook_id=None):
        '''
        :param rune_id: id пустой руны
        :param runebook_id: если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :return:
        '''
        if self.get_info_runebook(runebook_id=runebook_id):
            if TargetPresent():
                CancelTarget()
            NumGumpButton(GetGumpsCount() - 1, 1)
            for i in range(5):
                if TargetPresent():
                    WaitTargetObject(rune_id)
                    break
                Wait(500)
            return True
        return False


def meditation():
    if Mana() < 20:
        while Mana() < MaxMana():
            ct = datetime.now()
            if TargetPresent():
                CancelTarget()
            UseSkill('Meditation')
            if WaitJournalLine(ct, "You begin to meditate|"
                                   "Вы уже медитируете|"
                                   "You are already meditating|"
                                   "You must wait to perform another action", 10000):
                while InJournalBetweenTimes("You are unable to concentrate|"
                                            "You stop meditating|"
                                            "I am already performing|", ct, datetime.now()) == -1:
                    Wait(1000)


def cast_mark():
    if Connected() and not Dead():
        if TargetPresent():
            CancelTarget()
        if Mana() >= 20:
            meditation()
        Cast('Mark')
        for i in range(8):
            if TargetPresent():
                return True
            Wait(1000)
    return False


def check_blank_rune(count):
    if Connected() and not Dead():
        FindType(0x1F14, Backpack())
        if FindCount() >= count:
            return True
        print(f"В паке рун меньше чем нужно скопировать. Докинь ещё {count - FindCount()}")
    return False


def main():
    if Connected() and not Dead():
        _runebook = Runebook(runebook_id=ID_RUNEBOOK)

        pull_rune = _runebook.get_info_runebook()
        pull_copy_rune = _runebook.get_info_runebook(ID_CLEAR_RUNEBOOK)

        if check_blank_rune(pull_rune['info']['count_rune'] - pull_copy_rune['info']['count_rune']):
            for i in range(pull_copy_rune['info']['count_rune'], pull_rune['info']['count_rune']):
                if not Connected() or Dead():
                    return
                if not _runebook.recall(rune=i, reagents=REAGENTS):
                    return
                Wait(8000)
                if cast_mark():
                    FindType(0x1F14, Backpack())
                    WaitTargetObject(FindItem())
                    Wait(1000)
                    UseObject(FindItem())
                    UOSay(pull_rune['gumps'][i]['name'])
                    _runebook.add_rune(rune_id=FindItem(), runebook_id=ID_CLEAR_RUNEBOOK)
                else:
                    return
            if RETURN:
                _runebook.recall(rune=RETURN, reagents=REAGENTS)
            print('Скопировано.')


if __name__ == '__main__':
    # settings
    ID_RUNEBOOK = 0x13D07FEC            # id рунбуки которую хотим скопировать
    ID_CLEAR_RUNEBOOK = 0x13D07FDD      # id пустой рунбуки
    REAGENTS = False                    # если телепорт по скроллам в рунбуке, то оставляйте False, если телепорт по регам, то True
    RETURN = "place1"                   # если надо вернуться домой, то укажите имя руны, или её номер (без ковычек) в рунбуке. Если нет, то False (RETURN = False)

    main()

 

CopyRuneBook.py

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

stealth version 9.6.1  (<- делался на версии)

Блок (класс) для работы с рунбукой

Как запустить:  читать тут

Что делает:

  • Все действия что можно сделать с рунбукой (телепорт по регам\скролам, открытия портов и т.д.)

Инструкция по применению:

  • дока в теле скрипта, в низу все доступные методы.
from datetime import datetime
from py_stealth import *


class Runebook:
    def __init__(self, runebook_id: int):
        self._runebook_id = runebook_id  # ID рунбуки
        self.info_runebook = {}

    def __call__(self, *args, **kwargs):
        pass

    @staticmethod
    def _check_connected() -> bool:
        if Connected():
            return True
        print("Ошибка: нет соединения с сервером.")
        return False

    def _open_backpack(self, pack=None) -> bool:
        if pack is None:
            pack = Backpack()
        if self._check_connected():
            for i in range(5):
                UseObject(pack)
                if LastContainer() == pack:
                    return True
                Wait(1000)
            print("Ошибка: не смог открыть бэкпак.")
        return False

    def _check_runebook(self, runebook_id: int) -> bool:
        if self._open_backpack():
            if GetParent(runebook_id) == Backpack():
                return True
            print(f"Ошибка: рунбука {hex(runebook_id)} не в бэкпаке.")
        return False

    def _open_runebook(self, runebook_id: int) -> bool:
        if self._check_runebook(runebook_id=runebook_id):
            while GetGumpsCount():
                CloseSimpleGump(GetGumpsCount() - 1)
            temp = GetGumpsCount()
            for i in range(10):
                UseObject(runebook_id)
                if temp < GetGumpsCount():
                    return True
                Wait(500)
            print("Ошибка: не смог открыть рунбуку.")
        return False

    def _check_reagents(self, pack=None, gate=False) -> bool:
        '''
        :param pack: если реги в бекпаке, то вызываем пустым, если в мешке, шкатулке, передаём id контейнера
        '''
        if pack is not None:
            self._open_backpack(pack=pack)
        if not gate:
            if any(i < 1 for i in [BPCount(), MRCount(), BMCount()]):
                print(f'Недостаточно реагентов (BP:{BPCount()}, MR:{MRCount()}, BM:{BMCount()})')
                return False
        else:
            if any(i < 1 for i in [BPCount(), MRCount(), SACount()]):
                print(f'Недостаточно реагентов (BP:{BPCount()}, MR:{MRCount()}, SA:{SACount()})')
                return False
        return True

    @staticmethod
    def _check_mana(gate=False) -> bool:
        if not gate:
            if Mana() < 11:
                print(f"Мало маны! <11 ({Mana()}/{MaxMana()})")
                return False
        else:
            if Mana() < 40:
                print(f"Мало маны! <40 ({Mana()}/{MaxMana()})")
                return False
        return True

    def _find_rune(self, rune, runebook_id=None) -> dict | bool:
        '''
        :param runebook_id: если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :param rune: принимает номер руны(НЕ индекс) в рунбуке с 1 по 16
        :return: возвращает словарь с номерами гампов
        {"name": "sortir","set_def": 501, "scroll": 601,"drop": 81,"reagent": 2,"gate": 3}
        '''
        if runebook_id is None:
            runebook_id = self._runebook_id
        if _pull := self.get_info_runebook(runebook_id=runebook_id):
            if isinstance(rune, int):
                if _pull['info']['count_rune'] >= rune - 1:
                    return _pull['gumps'][rune - 1]
            else:
                for i in _pull['gumps']:
                    if i["name"] in rune:
                        return i
        print(f"Ошибка: руна не найдена")
        return False

    def get_info_runebook(self, runebook_id=None) -> dict | bool:
        '''
        :param runebook_id:  если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :return: возвращает словарь с общей информацие о рунбуке и гампами.
        {
            "gumps": [{"name": "sortir","set_def": 501, "scroll": 601,"drop": 81,"reagent": 2,"gate": 3}, [...], ...n],
            "info": {'name': Basyan, 'charge': 2, 'charge_max': 10, 'count_rune': 7}
        }
        '''
        if runebook_id is None:
            runebook_id = self._runebook_id
        if self._open_runebook(runebook_id=runebook_id):
            info_gumps = GetGumpInfo(GetGumpsCount() - 1)
            count_rune = int((info_gumps['GumpButtons'][len(info_gumps['GumpButtons']) - 2]['ReturnValue']) / 2)

            temp_pull_gump = {'gumps': []}
            for n, i, r in zip(range(7, count_rune + 7), range(1, count_rune + 1), range(2, 99, 2)):
                temp_pull_gump['gumps'].append({
                    "name": info_gumps['Text'][n][0],
                    "set_def": 500 + i,
                    "scroll": 600 + i,
                    "drop": 80 + i,
                    "reagent": r,
                    "gate": r + 1
                })

            temp_pull_gump.update({"info": {'name': GetTooltip(runebook_id),
                                            'charge': int(info_gumps['Text'][3][0]),
                                            'charge_max': int(info_gumps['Text'][4][0]),
                                            'count_rune': int(count_rune)}})

            if runebook_id == self._runebook_id:
                self.info_runebook = temp_pull_gump
            return temp_pull_gump
        return False

    def recall(self, rune, pack=None, reagents=False) -> bool:
        '''
        :param pack: если реги в бекпаке, то вызываем пустым, если в мешке, шкатулке, передаём id контейнера
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :param reagents: устой и false рекол по скроллам, если true, рекол по регам
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune):
            if not reagents:
                if self.info_runebook['info']['charge'] <= 0:
                    print(f"АХТУНГ: заправь рунбуку. charge "
                          f"{self.info_runebook['info']['charge']}/{self.info_runebook['info']['charge_max']}")
                    return False
                NumGumpButton(GetGumpsCount() - 1, _rune["scroll"])
                return True
            else:
                if self._check_reagents(pack=pack) and self._check_mana():
                    NumGumpButton(GetGumpsCount() - 1, _rune["reagent"])
                    return True
        return False

    def gate(self, rune, pack=None) -> bool:
        '''
        :param pack: если реги в бекпаке, то вызываем пустым, если в мешке, шкатулке, передаём id контейнера
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune):
            if self._check_reagents(gate=True, pack=pack) and self._check_mana(gate=True):
                NumGumpButton(GetGumpsCount() - 1, _rune["gate"])
                return True
        return False

    def recharge(self, scrolls=None) -> bool:
        '''
        :param scrolls: если пустой, то вызовет таргет речерджа или указать ID стопки с рекалами
        :return: boolean
        '''
        if _rune := self.get_info_runebook():
            if self.info_runebook['info']['charge'] < self.info_runebook['info']['charge_max']:
                if TargetPresent():
                    CancelTarget()
                NumGumpButton(GetGumpsCount() - 1, 800)
                for i in range(5):
                    if TargetPresent():
                        if isinstance(scrolls, int):
                            WaitTargetObject(scrolls)
                        break
                    Wait(500)
            return True
        return False

    def set_def_rune(self, rune) -> bool:
        '''
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune):
            NumGumpButton(GetGumpsCount() - 1, _rune["set_def"])
            return True
        return False

    def drop_rune(self, rune, runebook_id=None) -> int | bool:
        '''
        :param runebook_id: если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :param rune: номер руны в рунбуке (с 1 до 16), 0 - последняя руна или имя руны "sortir" (чувствителен к регистру)
        :return: boolean
        '''
        if _rune := self._find_rune(rune=rune, runebook_id=runebook_id):
            while f := FindTypeEx(0x1F14, 0xFFFF, Backpack(), False):
                Ignore(f)
            NumGumpButton(GetGumpsCount() - 1, _rune["drop"])
            drop_rune = FindTypeEx(0x1F14, 0xFFFF, Backpack(), False)
            IgnoreReset()
            return drop_rune
        return False

    def add_rune(self, rune_id: int, runebook_id=None):
        '''
        :param rune_id: id пустой руны
        :param runebook_id: если вызывается пустым, присваивается id рунбуки из конструктора, или указать id
        интересующей рунбуки.
        :return:
        '''
        if self.get_info_runebook(runebook_id=runebook_id):
            if TargetPresent():
                CancelTarget()
            NumGumpButton(GetGumpsCount() - 1, 1)
            for i in range(5):
                if TargetPresent():
                    WaitTargetObject(rune_id)
                    break
                Wait(500)
            return True
        return False


if __name__ == '__main__':
    _runebook = Runebook()

    _runebook.recall()
    _runebook.gate()
    _runebook.recharge()
    _runebook.drop_rune()
    _runebook.add_rune()
    _runebook.get_info_runebook()
    _runebook.info_runebook

 

 

runebook.py

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Авторизация  

×
×
  • Создать...