Тема: JQuery на примере начала диалога в Некровиле
В общем меня спрашивают, как нажать на объекты в подземелье...вспоминать каждый раз долго, решил что-то вроде гайда написать.
С недавнего времени команда разработчиков в БК добавили возможность использования фрэймворка JQuery.
Для меня это большой плюс, т.к. громоздкие циклы с for теперь можно заменить на всего 1 строку кода.
Естественно мы раньше и сами могли прицепить его для собственного удобства, но это легко было бы проверить со стороны сервера и, соответственно, привлечь внимание к персонажу.
Что использую при тестах:
- IE 11. Его консоль и проводник DOM просто шикарны.
- (Please log in or register to see this URL)
- описание (Please log in or register to see this URL)
Постановка задачи:
1) Если находимся на клетке со сторожем - найти сторожа и нажать на него.
2) Если висит меню с выбором действий со сторожем - нажать Поговорить.
3) Сам разговор
4) Если уже поговорили - идти дальше.
Решение пункта 1
При помощи "Проводник DOM" легко найти, что код Сторжа выглядит таким образом:
<map name="ObjectsMap" id="ObjectsMap"><area title="Сторож могил" href="javascript:void(0)" coords="132,41,219,202"></map>
Это тэг 'area' в главном фрэйме, в title которого содержится слово сторож.
Используя синтаксис jquery поиск этого тэга можно записать таким образом:
$('area[title*="Сторож"]',get_mainframe().document)
Первый параметр - это селектор (Что искать), второй параметр - это контекст(Где начинать поиск).
Если вы выполнте данный код в консоли, то увидите, что будет возвращен объект, содержащий массив найденных реультатов, к которым можно обращаться по индексу ([0],[1]...[index]) и свойство length, указывающее на количество найденных объектов.
Результирующий код для пункта 1:
var storozh = $('area',get_mainframe().document).filter('[title*="Сторож"]');
if(storozh.length > 0) { storozh[0].click(); }
Примечание: Если на клетке было бы два сторожа, можно было бы кликнуть по второму storozh[1].click();
Решение пункта 2
До момента нажатия на сторожа, меню с "Поговорить" не существует в DOM и к нему нельзя обратиться.
После нажатия данное меню выглядит следующим образом:
<div id="pmenu" style="left: 195px; top: 141px; height: auto; overflow: visible; display: block; visibility: visible; -ms-overflow-y: visible;">
<a onclick="return p_action('dialog=gy_gravedigger_default&use','1.4.10.71-77')" href="#">Поговорить</a><br>
<input name="close" style="width: 16px; height: 16px; vertical-align: middle;" onclick="closemenu(); return false;" type="submit" value="X"></div>
Меню - тэг div с id pmenu.
Код нахождения:
$('#pmenu',get_mainframe().document)
Но само меню нам не важно - нам важна ссылка на Поговорить, внутри данного меню.
Код нахождения ссылки "Поговорить":
$('#pmenu',get_mainframe().document).find('a:contains("Поговорить")')
Объединяем решение двух пунктов:
var talk_link = $('#pmenu',get_mainframe().document).find('a:contains("Поговорить")');
if(talk_link.lenght > 0)
{ talk_link[0].click();}
else
{
var storozh = $('area',get_mainframe().document).filter('[title*="Сторож"]');
if(storozh.length > 0) { storozh[0].click(); }
}
Решение пункта 3:
Это решается плагинами. На форуме где-то были, но искать сейчас некогда
Решение пункта 4:
А вот здесь уже то, что нельзя протестировать в IE, т.к. используются методы самого бота.
Псевдокод:
if(Поговорили?){ Поговорили=false; Walk("rr"); }else{ Поговорить и присвоить значение переменной Поговорили=true;}
Для реализации буду использовать методы external.InitVal(key,val), external.SetVal(key,val), external.GetVal(key).
При помощи данных методов доступ к переменной можно выполнить и из плагинов, и из маршрутов.
Существовать переменная будет до полного перезапуска бота.
Готовый(почти) код:
external.InitVal("storozh_talked",false);
if(external.GetVal("storozh_talked") == true)
{
external.SetVal("storozh_talked",false); Walk("rr");
}
else
{
Поговорить;
external.SetVal("storozh_talked",true);
}
Остаётся объединить решения для 1, 2 и 4-го пункта:
external.InitVal("storozh_talked",false);
if(external.GetVal("storozh_talked") == true)
{
external.SetVal("storozh_talked",false);
Walk("rr");
}
else
{
var talk_link = $('#pmenu',get_mainframe().document).find('a:contains("Поговорить")');
if(talk_link.lenght > 0)
{
external.SetVal("storozh_talked",true);
talk_link[0].click();
}
else
{
var storozh = $('area',get_mainframe().document).filter('[title*="Сторож"]');
if(storozh.length > 0) { storozh[0].click(); }
}
}
Хочу обратить внимание, что строки external.SetVal("storozh_talked",true) и external.SetVal("storozh_talked",false) здесь не обязательны, т.к. вы можете задать эти значения внутри плагина для диалога.
Собственно запись кода в одну строку, чтобы использовать в маршруте:
external.InitVal("storozh_talked",false); if(external.GetVal("storozh_talked") == true) { external.SetVal("storozh_talked",false); Walk("rr"); } else { var talk_link = $('#pmenu',get_mainframe().document).find('a:contains("Поговорить")'); if(talk_link.lenght > 0) { external.SetVal("storozh_talked",true); talk_link[0].click(); } else { var storozh = $('area',get_mainframe().document).filter('[title*="Сторож"]'); if(storozh.length > 0) { storozh[0].click(); } } }