Создание несложного бота для WoW, программирование маршрутов
Я отлично понимаю, что использование ботов запрещено лицензионным соглашением Blizzard. Это может привести к перманентному бану аккаунта. Я бы расстроился, узнав, что кто-то, воспользовавшись материалами данного поста, стал наживаться, ухудшая экономику игры и вызывая неодобрение других игроков. И да, я понимаю, то, что делаю я, нечестно.
Цель поста — рассказать о моем опыте и описать сложности, с которыми я столкнулся, узнать у вас, что можно было сделать лучше.
Предыстория
Коллекционирование
Люди, далекие от индустрии игр, могут без ущерба пропустить этот раздел. В игре WoW есть такой аспект — коллекционирование. Как и в нумизматике/филателии, чем больше у вас, например, верховых животных, тем вам приятнее. Точно так же важен процесс получения.
Какие-то драконы требуют для получения выполнения десятка задач («ачивок»), какие-то — войти в лучшие 2% игроков в мире по навыку управления персонажем (сражения на арене), что-то можно просто купить за игровую валюту, что-то — за реальные деньги в магазине. Подробности можно почитать в другом источнике, речь не об этом.
Как создать чат-бот для телеграм
Так вот, некоторые из коллекционируемых предметов падают в подземелье с шансом около 0,5%. Если шанс выпадения дается игроку лишь раз в день (иногда в неделю), вам потребуется время, соизмеримое с годом, для забегов. И все ради того мгновения получения заветного выстраданного предмета. Чем больше вы потратили времени и сил на «фарм» предмета, тем приятнее вам его в итоге получить. По моему опыту радость очень мимолетна.
Зависимость шанса выпадения от количества попыток
Небольшое отступление. Какова вероятность того, что за шесть бросков игральной кости выпадет «6»? Очевидно, что . То есть, наше событие является противоположным событием к невыпадению «6» за все шесть попыток.
Используя второй замечательный предел, нетрудно показать, что .
А вероятность получения коня с шансом «дропа» в 1% за 100 попыток примерно равна 63%.
Некоторые игроки, сделав триста попыток считают, что вот-вот повезет — ведь вероятность облома за такое большое число попыток мала. Их ждет разочарование, ведь за следующие 100 им повезет снова лишь на 63%. А старые труды не дают ничего.
Задача
Есть подземелье. Нужно пробежать по нему с виражами, выполнить пару несложных задач по пути. Убить финального босса и поднять добычу. Чтобы не бежать к выходу пешком, телепортироваться в ближайшую деревню и долететь ко входу. Повторить 5 раз.
Карта подземелья и маршрут:
Задача максимум. Запустил и ушел на пол часа. Процесс полностью автоматический.
Задача минимум. Запустить и сидеть рядом, читать или играть на гитаре, поглядывая на монитор. При необходимости изредка помогать персонажу выбраться из непредвиденной ситуации.
Мои трэш кампании в озвучке голосами Warcraft 3 от бота Silero!
Важно иметь возможность при желании описать маршрут другого подземелья, не залезая в код.
Подход
Движение и позиционирование
- Вам требуется воспроизвести первоначальное положение персонажа и направление его взгляда. Если вы перед автоматическим забегом повернетесь слегка в другую сторону, вы побежите кривовато и рано или поздно упретесь в стенку
- Если вы записали точные координаты и угол, то поставить персонажа туда же вам также не удастся. Реагирует на кнопки он как бульдозер и поворачивается так же. А даже ошибка в 1 градус через 100 метров выльется в метра (ширина дверного проема)
- Время нажатия и отпускания кнопок тоже далеко от идеала. Это похоже на передвижение по квартире с закрытыми глазами. Вроде бы шесть шагов вперед и строго направо, но на деле вместо туалета мы оказываемся в ванной. Попробуйте также открыть дверь с закрытыми глазами, не щупая ручку
move 40.644 20.417 1.537 move 40.526 20.411 1.537 move 40.246 20.408 1.592 move 39.974 20.414 1.592 move 39.691 20.411 1.537 move 39.417 20.388 1.510
Это отрывок из списка команд робота по перемещению. Указаны координаты x, y и угол поворота в пространстве в радианах.
Клавиши и команды
По пути надо нажимать кнопки и кликать мышкой, открывать двери, где-то нужно ждать. Не хотелось бы выписывать это все вручную. Да и искать среди команд с координатами (в примере выше), куда же что вписать, не очень приятно. Поэтому единовременные нажатия на кнопки и клики мы будем писать параллельно с записью координат.
pitch -0.89 mouse right 942 498 pause 10000 move 39.417 20.388 1.510 key ` pause 1000 key move 39.142 20.364 1.510 key key 3 key 3 mouse right 963 622 move 38.864 20.340 1.510 move 38.653 20.321 1.510
Отдельно упомяну про «pitch» (наклон). Если персонаж смотрит в горизонт, он равен нулю. Если под ноги, наклон отрицателен. А в небо — положителен. Измеряется в радианах.
Его пришлось добавить, как только персонажу захотелось летать.
Модули
- Мы напишем addon для интерфейса WoW, который будет определять позицию персонажа, азимут, наклон. Правилами игры аддоны ничуть не запрещены, указанная информация доступна через игровое API внутри аддона. Он будет рисовать это все на экране. Сам аддон пишется на языке Lua, потому что так решили разработчики игры.
- В аддоне можно определять кое-что, можно рисовать, но вот заставить персонажа двигаться нельзя. Еще в аддоне нельзя писать в файл, спрашивать у игры, где стены, где враги, да и много чего еще нельзя. Поэтому нам нужно написать внешнее управляющее приложение. Я не стал оригинальничать и использовал AutoIt. Это действительно быстро и удобно, хоть и немного дико для меня, привыкшего программировать на строго типизированных языках.
- Приложение должно уметь записывать мои действия. Назовем этот функционал Recorder
- Приложение должно уметь воспроизводить запись. Назовем Player
- Записанные действия и координаты мы будем хранить в текстовом файле построчно. Их можно и нужно редактировать вручную. Добавлять костыли, удалять мусор. Скажу сразу, это самое сложное.
Addon для WoW на Lua
Аддон для WoW это скрипт на языке Lua. Язык полноценный, гибкий, эффективный. Делать с системой ничего нельзя. Делать с игрой можно все, но только в рамках того API, которое предоставляет вам игра. Так как Blizzard не хочет, а точнее, запрещает игрокам и предпринимателям писать ботов, то и API кроме упомянутых выше координат почти ничего полезного и не предоставляет.
Разумеется, полезного для наших нужд. Неплохой гайд по написанию аддонов сразу с описанием Lua можно найти здесь. Ну а я опишу свой вариант.
Манифест и GUI
Подробности и источник. В папке World of WarcraftInterfaceAddOns создаете папку HelloWorld. В нее кладете HelloWorld.toc с содержимым
## Interface: 50001 ## Title: Hello, World! ## Notes: My first AddOn HelloWorld.lua
Если бы я хотел понарисовать формочек и кнопочек (а для этого обычно и нужны аддоны), последней строчкой я бы вписал еще HelloWorld.xml с описанием этих кнопочек. В дизайне и написании такого GUI-аддона хорошо помогает AddOn Studio. Мощный инструмент на базе MS Visual Studio.
Но так как я минималист, рисовать мы в этот раз не будем. Кроме того, это даст мне возможность показать, что создавать формы можно динамически из самого скрипта без использования дизайнера. Рассмотрим же HelloWorld.lua. Редактировал я его в Notepad++. Чтобы игра подключила изменения в HelloWorld.toc, надо перезапустить ее целиком.
А вот изменения в HelloWorld.lua можно подхватить, написав в консоли команду /reload. Поэтому процесс программирования и отладки не такой болезненный.
Слеш-команды
Кстати, об отладке. Советую сразу добавить обработчик слеш-команд:
SLASH_HELLO_WORLD1 = ‘/helloworld’; function SlashCmdList.HELLO_WORLD(msg, editbox) local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); print(format(«HelloWorld %.2f %.2f %.2f %.2f», x*100, y*100, facing, pitch)); end
Для этого определим переменную вида SLASH_ИМЯn. Где ИМЯ уникально для всех аддонов, а n либо пусто, либо порядковое число с 1. И добавим функцию с именем ИМЯ в некий объект.
Может показаться странным для программиста на C++, что мы эту функцию-обработчик нигде явно не регистрируем. Да и со строковой переменной связываем чисто по имени переменной. Но вот такая она, мощь и магия Lua.
Теперь команда в WoW-консоли /helloworld выполнит требуемые вам действия: позволит вывести отладочную информацию, а для простейших аддонов, собственно, произведет все то, ради чего вы их писали.
Ну и тут же я показал WoW API, которое достает требуемую информацию.
Обработчик событий
Система работы с GUI в аддоне похожа на работу Windows со своими сообщениями и их обработкой.
local EventFrame = CreateFrame(«Frame») function EventFrame:OnEvent(event, . ) print(«HelloWorld:», event) self[event](self, . ) end EventFrame:SetScript(«OnEvent», EventFrame.OnEvent) EventFrame:RegisterEvent(«PLAYER_LOGIN») function EventFrame:PLAYER_LOGIN() — Инициализация тут end function EventFrame:OnUpdate() — Полезные действия тут end EventFrame:SetScript(«OnUpdate», EventFrame.OnUpdate)
Мы создаем фрейм типа «Frame» и подключаемся на действия «OnEvent» и «OnUpdate» командами
EventFrame:SetScript(«OnEvent», EventFrame.OnEvent) EventFrame:SetScript(«OnUpdate», EventFrame.OnUpdate)
Обработчик OnUpdate будет вызываться после каждого кадра — то, что нам нужно для обновления координат. А OnEvent будет вызываться при других желаемых событиях. Из него будем дергать соответствующие функции:
self[event](self, . )
Что еще удобнее в Lua, это то, что вот такой конструкцией можно вызвать уникальные обработчики вида
function EventFrame:PLAYER_LOGIN()
Здесь PLAYER_LOGIN — это событие, которое рассылается во все фреймы при входе в мир и перезапуске пользовательского интерфейса. Другие события: PLAYER_LEAVE_COMBAT, QUEST_FINISHED, PLAYER_EQUIPMENT_CHANGED, PLAYER_DEAD, — и еще очень много. С полным списком можно ознакомиться тут. Зарегистрируем то событие, которое мы хотим обрабатывать, командой
EventFrame:RegisterEvent(«PLAYER_LOGIN»)
Передача информации
Так как в аддоне нельзя ничего делать с системой, информацию из WoW другой части бота мы будем передавать при помощи изменения цвета пикселей. Как это делал rednaxi в своем посте. Но только мы будем передавать цветом не один бит информации, а будем сериализовать данные и передавать их больше.
Рисование
Так как для рисования тоже нужны фреймы, создадим их
local HelloWorld1 = CreateFrame(«Frame», nil, UIParent) local HelloWorld2 = CreateFrame(«Frame», nil, UIParent) function EventFrame:PLAYER_LOGIN() HelloWorld1:SetFrameStrata(«BACKGROUND») HelloWorld1:SetWidth(10) HelloWorld1:SetHeight(10) HelloWorld1.texture = HelloWorld1:CreateTexture(nil,»BACKGROUND») HelloWorld1.texture:SetAllPoints(HelloWorld1) HelloWorld1:SetPoint(«TOPLEFT»,0,0) HelloWorld1:Show() HelloWorld2:SetFrameStrata(«BACKGROUND») HelloWorld2:SetWidth(10) HelloWorld2:SetHeight(10) HelloWorld2.texture = HelloWorld2:CreateTexture(nil,»BACKGROUND») HelloWorld2.texture:SetAllPoints(HelloWorld2) HelloWorld2:SetPoint(«TOPLEFT»,10,0) HelloWorld2:Show() end
Думаю, тут все понятно и без комментариев. Подробности по каждому методу ищите сами.
Сериализация
У нас есть две координаты и два угла. Все — числа с плавающей запятой. Компоненты цветов пикселей в аддоне тоже числа с плавающей запятой, но от 0.0 до 1.0. Кроме того, известно, что сохранится компонента цвета в одном байте. Поначалу я каждую координату сохранял в одну компоненту цвета. В итоге точность позиционирования в локации составляла 1/255 от размера карты.
Получалось как в GPS: вроде координаты есть, но вести машину на автомате (управление компьютером без человека) по дороге по навигатору не выйдет. Так что пришлось давать два байта. Как повыгоднее сохранить одно дробное число в два байта? Я сделал так
local x1, x2 = math.modf(x*255)
Функция modf возвращает целую и дробную часть числа через запятую. Здесь используется параллельное присваивание — еще одна полезная фишечка Lua.
При таком подходе я использую полную мощность каждого из двух байтов, в которые сохраняется координата. Ну а азимут и наклон не так требовательны к точности, лишь бы укладывались в отрезок 0.0-1.0. Получается вот так:
local math = getfenv(0).math function EventFrame:OnUpdate() local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); local x1, x2 = math.modf(x*255) local y1, y2 = math.modf(y*255) HelloWorld1.texture:SetTexture(x1/255, x2, facing/7) HelloWorld2.texture:SetTexture(y1/255, y2, pitch/4+0.5) end
Теперь при перемещении по миру в левом верхнем углу два квадратика 10 на 10 будут хаотично менять свой цвет.
Полный текст HelloWorld.lua
local math = getfenv(0).math SLASH_HELLO_WORLD1 = ‘/helloworld’; local EventFrame = CreateFrame(«Frame») local HelloWorld1 = CreateFrame(«Frame», nil, UIParent) local HelloWorld2 = CreateFrame(«Frame», nil, UIParent) function EventFrame:OnEvent(event, . ) print(«HelloWorld:», event) self[event](self, . ) end EventFrame:SetScript(«OnEvent», EventFrame.OnEvent) EventFrame:RegisterEvent(«PLAYER_LOGIN») function EventFrame:PLAYER_LOGIN() HelloWorld1:SetFrameStrata(«BACKGROUND») HelloWorld1:SetWidth(10) HelloWorld1:SetHeight(10) HelloWorld1.texture = HelloWorld1:CreateTexture(nil,»BACKGROUND») HelloWorld1.texture:SetAllPoints(HelloWorld1) HelloWorld1:SetPoint(«TOPLEFT»,0,0) HelloWorld1:Show() HelloWorld2:SetFrameStrata(«BACKGROUND») HelloWorld2:SetWidth(10) HelloWorld2:SetHeight(10) HelloWorld2.texture = HelloWorld2:CreateTexture(nil,»BACKGROUND») HelloWorld2.texture:SetAllPoints(HelloWorld2) HelloWorld2:SetPoint(«TOPLEFT»,10,0) HelloWorld2:Show() end function EventFrame:OnUpdate() local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); local x1, x2 = math.modf(x*255) local y1, y2 = math.modf(y*255) HelloWorld1.texture:SetTexture(x1/255, x2, facing/7) HelloWorld2.texture:SetTexture(y1/255, y2, pitch/4+0.5) end EventFrame:SetScript(«OnUpdate», EventFrame.OnUpdate) function SlashCmdList.HELLO_WORLD(msg, editbox) local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); print(format(«HelloWorld %.2f %.2f %.2f %.2f», x*100, y*100, facing, pitch)); end
Заключение первой части
- Мы посчитали вероятность получения предмета за большое число попыток
- Обозначили задачу, выработали подход к решению, разбили на модули
- Мы рассмотрели код простейшего аддона для WoW на языке Lua
- научились передавать координаты при помощи цвета
- научились рисовать, обрабатывать события
- научились обрабатывать слеш-команды
Теперь вы готовы к написанию своего аддона.
- написании Recorder’а клавиш и координат на языке AutoIt
- написании Player’a инструкций для бота
- математике 2D, как ориентироваться в декартовой системе координат без теоремы косинусов
- управлении роботом при недостаточном количестве датчиков
- мерах противодействия ботам
Источник: habr.com
Как создать свой бот в warcraft
. Какой-то нехороший человек сматерился на канале клана! Его забанили, он вышел. Создал другой аккаунт и вновь зашел материться, пришлось заново забанить :duel: .
. на наш клан постоянно заходят по 10 человек с иконками пеонов :alc: .
. на нашем канале постоянно матерятся.
. у нас здесь «скучно». :end:
. друга нет в баттл нете, и у него нет ICQ,как бы передать ему сообщение, придется ждать.
От всех этих и не только этих проблем нас может избавить грамотно настроенный бот. Он может не только кикать/банить кого нужно, но и давать некоторое удовольствие пользователям. К примеру можно, чтобы бот писал интересные цитаты, заранее написанные в файле, делал викторины, смеялся вместе со всеми, приветствовал всех, если на канале много людей итд.
Вообще взялся за эту «полезную» тему по двум причинам:
1)У нас в клане есть один не хороший человек,незнающий команды бота,который банит всех направо-налево.
2)Вообщем-то статьи такой еще небыло, да и пригодиться может немоло кому.
Здесь я хочу рассказать о StealthBot’е версии 2.6.3 и о его возможностях.
Но сразу скажу-я сам не все знаю про этого бота и расскажу вам все, что знаю и помню на этот момент.
Первый вопрос-ответ: Где скачать? -Скачать бота собственно можно на сайте http://www.stealthbot.net/forum/getsb.php.
Второй вопрос-ответ: -Можно ли и мне и боту сидеть на одном кее? –Нельзя.
Далее идем по настройкам бота: Лезем в Settings>Bot settings(Ctrl+P).
Знающие английский без труда смогут настроить бота нажатием кнопки Step-by-step configuration, которая находится снизу этого меню. Остальным посвящается:
Идем по порядку. Первая группа идет Connection Settings, в ней
Configuration.
Здесь нам нужно указать главные настройки подключения:
Username-пишем имя уже существующего аккаунта Баттл.нета.
Password-пишем пароль от аккаунта Баттл.нета.
CDKey-пишем CD-key от игры(за сохранность сд-кея не переживайте, эта программа его никуда и никому не отсылает).*
Expansion CDKey-Необязательное поле, если вы используете только оригинальную игру, а не дополнение. Но если вы используете дополнение(Brood War, Lord of Destruction,The Frozen Throne), то вам придется написать здесь дополнительный кей. Для варкрафта необязательно использовать The Frozen Throne.*
Home Channel-домашний канал бота. При успешном соединении с баттл.нетом, а также при включении одной функции(см. далее) бот зайдет сюда.
Server-указываем нужный нам сервер(europe.battle.net asia.battle.net uswest.battle.net useast.battle.net). При необходимости пишем свой.
*примечание: если вы играете на пиратских серверах, можно написать любой 26-ти значный набор букв.
Тут разобрались, едем дальше, то есть ниже:
Advanced
Здесь указываем дополнительные опции подключения бота. Если вы собираетесь играть на официальных серверах, то на данный момент написания этой стати у варкрафта версия 1.20с, и бот на данное время «устарел», и метод соединения с баттл.нетом изменился. Поэтому в пункте Connection method указываем ADVANCED – Local hashing. После этого идем в директорию бота и создаём папку WAR3 . В неё кидаем следующие файлы: Game.dll; Storm.dll; War3.exe. Желательно, эти файлы должны быть нетронутые.
После этих настроек можно нажимать кнопку connect.*
*Если у вас после данных настроек все еще не получается соединиться с сервером, зайдите в файл config,ini, который находится в папке бота. Сразу после [Main] жмите ENTER и пишите:
WAR3VerByte=14
W3XPVerByte=14
На очереди General Settings:
Show join/leave notifications-показывать, или не показывать в окне бота входящих-уходящих пользователей.
Use chat filtering- собственно функция ничего особого не делает-понижает использование памяти.
Show splash screen on startup- показывать, или нет симпатичный рисунок StealthBot’а при запуске программы.
Flash window on events- засвечивать, или нет окно бота при событиях(см. далее).
Disable name autocomplection- насколько я помню, эта функция отключает запись имени пользователя-отправителя письма(.mail ; !inbox).
Use UTF-8 encoding/decoding when processing and sending messages-позволяет боту расшифровывать «русские буквы».
Do not minimize to the System Tray- когда выключена, бот будет сворачиваться в System Tray-панель возле часов, при нажатии на «минус».
Timestamp Settings-стиль показа времени и даты сообщения.
Disable channel list name coloring- подсвечивает разными цветами активность пользователей, находящихся на канале.
Channel text logging- 1)Бот ведет запись всех событий и разговоров и сохраняет при завершении из программы. 2)Бот ведет запись всех событий и разговоров и удаляет при завершении программы. 3)Бот вообще не ведет ни каких записей.
Maximum logfile size [0] –максимальный размер записей оставленных ботом в мегобайтах. У меня максимальный имеющийся размер файла составляет 294кб, когда бот просидел в онлайне с 23х до 22х.
На очереди Fonts and Colors, но на нем останавливаться, как мне кажется смысла не имеет. В нем можно указать косметические настройки бота такие как смена Шрифта и размера Шрифта, цвета сообщений.
Moderation Settings-это опции для оператора канала.
Enable Phrasebanning-бот банит всех тех, кого нет в safelist’е и находится в phrase-листе.
Enable IPBanning-банит пользователей по их IP-адресу, так что если кто-то был забанен ботом и зашел под любым другим ником снова, бот его забанит снова.
Enable ClientBans-включает включенные опции, которые находятся дальше.
Enable Quiet-Time-включает очень веселый режим- банит всех, кто нарушит тишину и кого нет в safelist’е.
Enable Kick-On-Yell-Банит тех, кто ОРЁТ- написал больше пяти БОЛЬШИХ букв.
Enable PlugBans- здесь я, к сожалению, не знаю. (Ban users, with a UDP plug)
Enable Channel Protection-защита канала, банит всех, кого нет в safelist’е.
Ниже можно ввести сообщение, которое будет выводиться при любом бане.
Ban idle users-банит тех, кто молчит более Х секунд. Их можно указать ниже.
Kick instead of ban-вместо предыдущего БАНа, бот только кикает.
Ban Warcraft III Peons-банит игроков с иконкой раба.
Clientbans: должна быть включена опция Enable ClientBans. Ниже просто выбираете нужные игры.
Тут-же LevelBans
Diablo II | Warcraft III
Банит всех, кто ниже такого-то уровня. Поставьте 0, чтобы отключить эту функцию.
Levelban message –сообщение, которое будет выводиться, при недостаточном уровне, например «У вас низкий уровень.»
СКРИНШОТ№4
Greet Message Settings.
Здесь нам можно делать приветствующее сообщение. Для этого включаем опцию Greet users who join the channel. Дальше появляется опция Whisper the greet message-отправлять как личное сообщение, чтобы его увидел только тот, кто зашел.
Так же-ниже доступны некоторые простые функции, которые можно писать в приветствующем сообщении.
%c-канал; %0-ник пользователя; %1-ник бота; %p-пинг пользователя; %v-версия бота; %a-количество access’а пользователя; %f-метка access’а пользователя; %t-время(чч:мм); %d-дата(дд.мм.гггг).
Например:
«Hi, %0. You are wellcome to %c. My name is %1. You have %a and %f flags. Your ping at login is %pms at %t %d. ».
То есть если игрок ABC с access 10 и flags VOJD зайдет на канал LUCKERS, то бот GDA скажет:
«Hi, ABC. You are welcome to LUCKERS. My name is GDA. You have 10 and VOJD flags.Your ping at login is 32ms at 00:01 01.01.2001»
Idle message settings
Здесь можно написать то, что будет говорить бот каждые Х секунд, которые можно указать в пункте Delay between messages (minutes). Собственно здесь все точно так-же как и в прошлом меню, только выбор команд немного «урезан»:
%c-канал, на котором находится бот; %me-ник бота; %v-версия бота; %botup-время коннекта бота; %cpuup-продолжительность работы компьютера. %mp3-то, что играет у вас в Winamp’е; %quote-случайная цитата. Их можно написать в quotes list. %rnd-случайный пользователь на канале.
Без скриншота.
Miscellaneous general settings
В этом меню полно «ненужных» для варкрафта опций.(На мой взгляд-это меню предназначалось лично для удобств создателя).
Use ProfileApm-каждые 30секунд выводится сообщение- что играет в винампе.
Whisper command responses-включает опцию Forward whispers-пересылка сообщений пользователю, которая идет дальше.
Check user’s mail –проверяет, есть ли почта у пользователя, который заходит на канал.
Ignore Tic-Tac-Toe games-игнорировать Tic-Tac-Toe мини-игры(в варкрафте не встречается).
Disable the User Monitor-не знаю, что за функция, по умолчанию стоит галочка.
Do not use 0x65 internal friend’s list-отключить использование альтернативного friend-листа.
Enable URL detection-включает «нахождение» URL-адресов. То есть на них можно «нажимать» прямо в окне разговора.
Show offline friends-показывать друзей, которые находятся в оффлайне(так до конца и не понял, что именно она делает, наверное не для варкрафта).
Allow MP3 commands-разрешить использование mp3-команд. Лучше убрать эту функцию.
Connect on startup-первая полезная опция-соединяться с баттл.нетом при старте программы.
Minimize on startup-вторая полезная опция-сворачиваться в System Tray при запуске программы.
Forward whispers-если включена опция «Whisper command responses», то сообщения будут передаваться пользователю, которого вы укажете ниже.
Join backup channel when kicked-третья полезная опция- когда бота кто-то за что-то пнул или послал в баню, бот шел бы на канал, который указан ниже.
С настройками бота мы закончили и казалось все знаем. Теперь, скажу я вам, нам предстоит узнать стандартные команды бота и как их разграничить.
У бота есть сотня(примерно, не считал) встроенных команд, таких как .pingme и другие. По умолчанию на всех них стоит определенная цифра, называемая access,что означает доступ. У команды pingme стоит доступ 40, это значит, что ей могут пользоваться только те, у кого access больше или равно 40. Но если вам хочется, чтобы к этой функции имел доступ не только тот, у кого 40access’а, но и любой другой, мы заходим в файл access.ini,который лежит в папке с ботом, или же пройти далее Settings>Edit Fles>Access/Flags.
Ищем «Numeric]» и после этого на новой строке пишем нужную нам команду, например «pingme=» и далее пишет то число access’а, которое нам необходимо, например 0. соединяемся и просим первого встречного написать .pingme. Воаля! Бот пишет ему пинг!
Список всех базовых команд можно найти в справке, или в файле readme.chm.
Теперь займемся небольшим программированием бота. Сделаем например, чтобы тот, кто писал .whoami выводилось сообщение: «You, юзер , Just a little noob of BNet.». Для этого лезем в Custom Command Editor, который находится в субменю Bot. Жмем кнопку ADD. У нас появилась новая команда-new,её переименовываем в whoami(без точки).
А справа нам требуется ввести действия, хотя действиями это назвать трудно, это скорее то, что ответить.
Здесь у нас есть только парочка переменных- %0-это будет ник юзера, который сказал .whoami, и остальные %1, %2, %3,… %N-все эти переменные-это слова, разделенные пробелами. То есть если пользователь сказал .whoami azbuka chto takoe?, то переменные %1,%2,%3-будет azbuka;chto;takoe? соответственно.
Вернемся там, где остановились- на том, что ответить пользователю. Пишем только «You, %0 , Just a little noob of BNet.» и все. Теперь просим кого-нибудь написать .whoami и готовьте воду, чтобы избавиться от икоты, вызванной смехом от увиденного!
Вот мы и изучили основные возможности бота, и познакомились с его базовыми возможностями, хотя поверьте-возможности у него практически неограниченны! В ближайшее время выйдет вторая статья, ради которой я-таки и начал писать эту статью-скриптинг бота. Будем программировать бота с использованием стандартных Майкрософтовских элементарных VBscrit’ов(Visual Basic Scripts), на которых, собственно и построен сам бот.
Источник:
Небольшое отступление. Какова вероятность того, что за шесть бросков игральной кости выпадет «6»? Очевидно, что . То есть, наше событие является противоположным событием к невыпадению «6» за все шесть попыток. А вероятность получения коня с шансом «дропа» в 1% за 100 попыток примерно равна 63%. Некоторые игроки, сделав триста попыток считают, что вот-вот повезет — ведь вероятность облома за такое большое число попыток мала. Их ждет разочарование, ведь за следующие 100 им повезет снова лишь на 63%. А старые труды не дают ничего. Есть подземелье. Нужно пробежать по нему с виражами, выполнить пару несложных задач по пути. Убить финального босса и поднять добычу. Чтобы не бежать к выходу пешком, телепортироваться в ближайшую деревню и долететь ко входу. Повторить 5 раз. Карта подземелья и маршрут: Задача максимум. Запустил и ушел на пол часа. Процесс полностью автоматический. Задача минимум. Запустить и сидеть рядом, читать или играть на гитаре, поглядывая на монитор. При необходимости изредка помогать персонажу выбраться из непредвиденной ситуации. Важно иметь возможность при желании описать маршрут другого подземелья, не залезая в код. Просто записать нажатие и отпускание клавиш, позицию и щелчки мыши не получится. Точнее записать-то получится, только при проигрывании будет происходить совсем не то, что вы ожидали, по следующим причинам: Вот по этим причинам нам необходимо позиционироваться в мире при помощи координат. При этом сверять позицию и вносить коррективы необходимо регулярно, каждые 100 миллисекунд. move 40.644 20.417 1.537 move 40.526 20.411 1.537 move 40.246 20.408 1.592 move 39.974 20.414 1.592 move 39.691 20.411 1.537 move 39.417 20.388 1.510 Это отрывок из списка команд робота по перемещению. Указаны координаты x, y и угол поворота в пространстве в радианах. По пути надо нажимать кнопки и кликать мышкой, открывать двери, где-то нужно ждать. Не хотелось бы выписывать это все вручную. Да и искать среди команд с координатами (в примере выше), куда же что вписать, не очень приятно. Поэтому единовременные нажатия на кнопки и клики мы будем писать параллельно с записью координат. pitch -0.89 mouse right 942 498 pause 10000 move 39.417 20.388 1.510 key ` pause 1000 key move 39.142 20.364 1.510 key key 3 key 3 mouse right 963 622 move 38.864 20.340 1.510 move 38.653 20.321 1.510 Отдельно упомяну про «pitch» (наклон). Если персонаж смотрит в горизонт, он равен нулю. Если под ноги, наклон отрицателен. А в небо — положителен. Измеряется в радианах. Его пришлось добавить, как только персонажу захотелось летать. Таким образом, у нас вырисовываются части программно-аппаратного комплекса бота: Аддон для WoW это скрипт на языке Lua. Язык полноценный, гибкий, эффективный. Делать с системой ничего нельзя. Делать с игрой можно все, но только в рамках того API, которое предоставляет вам игра. Так как Blizzard не хочет, а точнее, запрещает игрокам и предпринимателям писать ботов, то и API кроме упомянутых выше координат почти ничего полезного и не предоставляет. Разумеется, полезного для наших нужд. Неплохой гайд по написанию аддонов сразу с описанием Lua можно найти здесь. Ну а я опишу свой вариант. Подробности и источник. В папке World of WarcraftInterfaceAddOns создаете папку HelloWorld. В нее кладете HelloWorld.toc с содержимым ## Interface: 50001 ## Title: Hello, World! ## Notes: My first AddOn HelloWorld.lua Если бы я хотел понарисовать формочек и кнопочек (а для этого обычно и нужны аддоны), последней строчкой я бы вписал еще HelloWorld.xml с описанием этих кнопочек. В дизайне и написании такого GUI-аддона хорошо помогает AddOn Studio. Мощный инструмент на базе MS Visual Studio. Но так как я минималист, рисовать мы в этот раз не будем. Кроме того, это даст мне возможность показать, что создавать формы можно динамически из самого скрипта без использования дизайнера. Рассмотрим же HelloWorld.lua. Редактировал я его в Notepad++. Чтобы игра подключила изменения в HelloWorld.toc, надо перезапустить ее целиком. А вот изменения в HelloWorld.lua можно подхватить, написав в консоли команду /reload. Поэтому процесс программирования и отладки не такой болезненный. Кстати, об отладке. Советую сразу добавить обработчик слеш-команд: SLASH_HELLO_WORLD1 = ‘/helloworld’; function SlashCmdList.HELLO_WORLD(msg, editbox) local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); print(format(«HelloWorld %.2f %.2f %.2f %.2f», x*100, y*100, facing, pitch)); end Для этого определим переменную вида SLASH_ИМЯn. Где ИМЯ уникально для всех аддонов, а n либо пусто, либо порядковое число с 1. И добавим функцию с именем ИМЯ в некий объект. Может показаться странным для программиста на C++, что мы эту функцию-обработчик нигде явно не регистрируем. Да и со строковой переменной связываем чисто по имени переменной. Но вот такая она, мощь и магия Lua. Теперь команда в WoW-консоли /helloworld выполнит требуемые вам действия: позволит вывести отладочную информацию, а для простейших аддонов, собственно, произведет все то, ради чего вы их писали. Ну и тут же я показал WoW API, которое достает требуемую информацию. Система работы с GUI в аддоне похожа на работу Windows со своими сообщениями и их обработкой. local EventFrame = CreateFrame(«Frame») function EventFrame:OnEvent(event, . ) print(«HelloWorld:», event) self[event](self, . ) end EventFrame:SetScript(«OnEvent», EventFrame.OnEvent) EventFrame:RegisterEvent(«PLAYER_LOGIN») function EventFrame:PLAYER_LOGIN() — Инициализация тут end function EventFrame:OnUpdate() — Полезные действия тут end EventFrame:SetScript(«OnUpdate», EventFrame.OnUpdate) Мы создаем фрейм типа «Frame» и подключаемся на действия «OnEvent» и «OnUpdate» командами EventFrame:SetScript(«OnEvent», EventFrame.OnEvent) EventFrame:SetScript(«OnUpdate», EventFrame.OnUpdate) Обработчик OnUpdate будет вызываться после каждого кадра — то, что нам нужно для обновления координат. А OnEvent будет вызываться при других желаемых событиях. Из него будем дергать соответствующие функции: self[event](self, . ) Что еще удобнее в Lua, это то, что вот такой конструкцией можно вызвать уникальные обработчики вида function EventFrame:PLAYER_LOGIN() Здесь PLAYER_LOGIN — это событие, которое рассылается во все фреймы при входе в мир и перезапуске пользовательского интерфейса. Другие события: PLAYER_LEAVE_COMBAT, QUEST_FINISHED, PLAYER_EQUIPMENT_CHANGED, PLAYER_DEAD, — и еще очень много. С полным списком можно ознакомиться тут. Зарегистрируем то событие, которое мы хотим обрабатывать, командой EventFrame:RegisterEvent(«PLAYER_LOGIN») Так как в аддоне нельзя ничего делать с системой, информацию из WoW другой части бота мы будем передавать при помощи изменения цвета пикселей. Как это делал rednaxi в своем посте. Но только мы будем передавать цветом не один бит информации, а будем сериализовать данные и передавать их больше. Так как для рисования тоже нужны фреймы, создадим их local HelloWorld1 = CreateFrame(«Frame», nil, UIParent) local HelloWorld2 = CreateFrame(«Frame», nil, UIParent) function EventFrame:PLAYER_LOGIN() HelloWorld1:SetFrameStrata(«BACKGROUND») HelloWorld1:SetWidth(10) HelloWorld1:SetHeight(10) HelloWorld1.texture = HelloWorld1:CreateTexture(nil,»BACKGROUND») HelloWorld1.texture:SetAllPoints(HelloWorld1) HelloWorld1:SetPoint(«TOPLEFT»,0,0) HelloWorld1:Show() HelloWorld2:SetFrameStrata(«BACKGROUND») HelloWorld2:SetWidth(10) HelloWorld2:SetHeight(10) HelloWorld2.texture = HelloWorld2:CreateTexture(nil,»BACKGROUND») HelloWorld2.texture:SetAllPoints(HelloWorld2) HelloWorld2:SetPoint(«TOPLEFT»,10,0) HelloWorld2:Show() end Думаю, тут все понятно и без комментариев. Подробности по каждому методу ищите сами. У нас есть две координаты и два угла. Все — числа с плавающей запятой. Компоненты цветов пикселей в аддоне тоже числа с плавающей запятой, но от 0.0 до 1.0. Кроме того, известно, что сохранится компонента цвета в одном байте. Поначалу я каждую координату сохранял в одну компоненту цвета. В итоге точность позиционирования в локации составляла 1/255 от размера карты. Получалось как в GPS: вроде координаты есть, но вести машину на автомате (управление компьютером без человека) по дороге по навигатору не выйдет. Так что пришлось давать два байта. Как повыгоднее сохранить одно дробное число в два байта? Я сделал так local x1, x2 = math.modf(x*255) Функция modf возвращает целую и дробную часть числа через запятую. Здесь используется параллельное присваивание — еще одна полезная фишечка Lua. При таком подходе я использую полную мощность каждого из двух байтов, в которые сохраняется координата. Ну а азимут и наклон не так требовательны к точности, лишь бы укладывались в отрезок 0.0-1.0. Получается вот так: local math = getfenv(0).math function EventFrame:OnUpdate() local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); local x1, x2 = math.modf(x*255) local y1, y2 = math.modf(y*255) HelloWorld1.texture:SetTexture(x1/255, x2, facing/7) HelloWorld2.texture:SetTexture(y1/255, y2, pitch/4+0.5) end Теперь при перемещении по миру в левом верхнем углу два квадратика 10 на 10 будут хаотично менять свой цвет.
Полный текст HelloWorld.lua
local math = getfenv(0).math SLASH_HELLO_WORLD1 = ‘/helloworld’; local EventFrame = CreateFrame(«Frame») local HelloWorld1 = CreateFrame(«Frame», nil, UIParent) local HelloWorld2 = CreateFrame(«Frame», nil, UIParent) function EventFrame:OnEvent(event, . ) print(«HelloWorld:», event) self[event](self, . ) end EventFrame:SetScript(«OnEvent», EventFrame.OnEvent) EventFrame:RegisterEvent(«PLAYER_LOGIN») function EventFrame:PLAYER_LOGIN() HelloWorld1:SetFrameStrata(«BACKGROUND») HelloWorld1:SetWidth(10) HelloWorld1:SetHeight(10) HelloWorld1.texture = HelloWorld1:CreateTexture(nil,»BACKGROUND») HelloWorld1.texture:SetAllPoints(HelloWorld1) HelloWorld1:SetPoint(«TOPLEFT»,0,0) HelloWorld1:Show() HelloWorld2:SetFrameStrata(«BACKGROUND») HelloWorld2:SetWidth(10) HelloWorld2:SetHeight(10) HelloWorld2.texture = HelloWorld2:CreateTexture(nil,»BACKGROUND») HelloWorld2.texture:SetAllPoints(HelloWorld2) HelloWorld2:SetPoint(«TOPLEFT»,10,0) HelloWorld2:Show() end function EventFrame:OnUpdate() local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); local x1, x2 = math.modf(x*255) local y1, y2 = math.modf(y*255) HelloWorld1.texture:SetTexture(x1/255, x2, facing/7) HelloWorld2.texture:SetTexture(y1/255, y2, pitch/4+0.5) end EventFrame:SetScript(«OnUpdate», EventFrame.OnUpdate) function SlashCmdList.HELLO_WORLD(msg, editbox) local facing = GetPlayerFacing(); local pitch = GetUnitPitch(«player»); local x, y = GetPlayerMapPosition(«player»); print(format(«HelloWorld %.2f %.2f %.2f %.2f», x*100, y*100, facing, pitch)); end Повторим, о чем шла речь А если вы разрабатываете нечто и хотите дать возможность себе или пользователям принимать участие, гибко подстраивать ПО под себя с использованием вашего API (например, писать искусственный интеллект противников, дать возможность брокерам размещать позиции, основываясь на котировках, дать возможность администраторам выполнять свои действия по результатам инвентаризации систем пользователей и т.п.), то знайте, Lua очень гибок и очень легко встраивается. Обдумайте такую возможность. Ну, а в следующей части мы поговорим о Источник: www.pvsm.ruЗависимость шанса выпадения от количества попыток
Используя второй замечательный предел, нетрудно показать, что .Задача
Подход
Движение и позиционирование
Клавиши и команды
Модули
Addon для WoW на Lua
Манифест и GUI
Слеш-команды
Обработчик событий
Передача информации
Рисование
Сериализация
Заключение первой части