Перейти к содержанию
Форум шарда Middle-Earth

Активность

Лента обновляется автоматически     

  1. Ещё раньше
  2. 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
  3. 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 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
  1. Загрузить ещё активность
×
×
  • Создать...