Добавлен MpW,
опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Jass
Тип:
Наработка
Версия Warcraft:
1.26
Это карта - система приказов, простая, на ней по всюду разбросаны итемы.
Автоподбор - способность, которая поможет заполнить инвентарь героя до отказа. Кликая по ней, ваш юнит сначала ищет ближайший предмет, и только после этого бежит подбирать. Затем пойдет искать следующий, и так до сих пор, пока не добьет сумку. Есть особые условия для работы этой способности:
- Есть определенный радиус действия, около которого перебирает все предметы. Можете указать это радиус в триггере.
- Если вокруг этого радиуса действия ни одного предмета не обнаруживается, то абилка выключается
- Если инвентарь полон, то юнит завершает подбор, абилка деактивируется
- Если игрок выдернул юнита во время подбора, то абилка здесь тоже становится неактивной.
Автопродажа - способность, которая продает все имеющие итемы в магазин. Тем более этот скилл сам ищет ближайший магазин. Когда носильщик добежит до магазина, то тут же продаст все итемы в одно мгновение. И вам не нужно перетаскивать итемы из каждого слота, за вас сделает сама система. Условие НЕ работы:
- Если инвентарь пуст
- Если игрок выдернул юнита во время продажи, то абилка здесь тоже становится неактивной.
Для работы копируете две категории (папки) с триггерами: "Автоподбор предметов" и "Продажа предмета". При переносе глобальных триггеров с одной карты на другую главную роль играет триггер "in" - специально вывел в GUI.
проверяем приказы при автоподборе.
Тут всего 4-5 проверок:
Тут работаем с кнопкой "Укрыться за щитом" - она не сбивает приказ, юнит не останавливается.
Тут работаем с кнопкой "Укрыться за щитом" - она не сбивает приказ, юнит не останавливается.
- Если нажата кнопка "включить" - включается автопоиск + автоподбор. Сначала проверяется есть ли у героя хотя бы один пустой слот в инвентаре (если нет, то автоподбор вырубается). ЗАМЕТКА: при поиске ближайшего итема мы помечаем итем, чтобы затем снова его не подбирать. Дело в том, что может быть так, что за одним итемом побегут два-три раба. А так, можно сделать, чтобы условно, договорились, кто что будет делать
- Если нажата кнопка "выключить" - автоподбор прерывается
- Если цель - объект, короче получил какой-то другой приказ на цель, но целью не является итем, это должно происходить во время включенного подбора. В итоге автоподбор прерывается.
- получил приказ щелчком правой кнопки мыши отойти в точку. это должно происходить во время включенного автоподбора. Автоподбор прерывается
function T_order_C takes nothing returns boolean
local integer id = GetIssuedOrderId()
local integer x1 = 852055 //приказ defend
local integer x2 = 851971 //приказ smart
local integer x3 = 852056 //приказ undefend
local integer Id = GetHandleId(GetTriggerUnit()) //Id-Handle герой
local boolean b = LoadBoolean(udg_Hash, Id, 0) //включен ли автоподбор
local integer Ev = GetHandleId(GetTriggerEventId()) //Id-Handle события (38 - без цели, 39 - точка, 40 - цель)
local boolean b1 = (id == x1 and Ev == 38) //включить автоподбор
local boolean b2 = (id != x2 and GetOrderTargetItem() == null and Ev == 40 and b) //получил какой-то другой приказ по цели, но целью не является итем, это должно происходить во время включеннного подбора
local boolean b3 = (id == x2 and Ev == 39 and b) //получил приказ щелчком правой кнопки мыши отойти в точку. это должно происходить во время включенного автоподбора
local boolean b4 = (id == x3 and Ev == 38) //выключить автоподбор
local boolean b5 = ( (id != x1 or id !=x2 or id != x3) and (Ev == 38 or Ev == 39) and b) //если ни один из проверок выше не работает
//local boolean b6 = ( (not b1) and b2 and b3 and b4 and b5) and (Ev > 37 and Ev < 41) //старая версия b5
return (b1) or (b2) or (b3) or (b4) or (b5) //or (b6)//происходит проверка
endfunction
function Trig_XX2 takes nothing returns nothing
local real x1 = GetUnitX(udg_unit) //координаты юнита
local real y1 = GetUnitY(udg_unit)
local real x2 = GetItemX(GetEnumItem()) //координаты выбранного итема, каждый раз итем сменяется на другой, короче цикл здесь
local real y2 = GetItemY(GetEnumItem())
local real dx = x2 - x1 //разность между координатами направление вектора короче
local real dy = y2 - y1
// ищем самый ближайщий предмет
// проверяем расстояние (дистанцию) между точками - юнитом и предметом
set udg_dist1 = SquareRoot(dx * dx + dy * dy) //подсчитывает расстояние, допустим dx * dx или dy * dy - возводим в степень, SquareRoot - функция корня
if udg_dist1 < udg_DD then //сравнивают, если расстояние между итемом и юнитов меньше, чем должно то подходит
if ( udg_dist1 < udg_dist2 ) then //сравнивают, если расстояние между итемом и юнитов меньше, чем должно то подходит
set udg_dist2 = udg_dist1
set udg_item[0] = GetEnumItem()
endif
set udg_h = udg_h + 1
endif
set udg_MAXX = udg_MAXX + 1
endfunction
function FG takes nothing returns boolean
local integer i = GetPlayerId(GetOwningPlayer(udg_unit)) //номер игрока
local integer id = GetHandleId(GetFilterItem()) //Id-Handle итема
local boolean b = LoadBoolean(udg_Hash, id, i) //подзагружает проверку, короче метку (помечен ли юнит, если в хэше ничего не сохранено. то выдаст false)
return IsItemVisible(GetFilterItem()) and (not b) //выбирает итемы если видимы и не помечены
endfunction
function NHR takes nothing returns nothing
local timer t = GetExpiredTimer() //запущенный таймер
local integer id = GetHandleId(t) //Id-Handle таймера
local unit u = LoadUnitHandle(udg_Hash, id, 0) //подзагружаем нашего героя
call PauseTimer(t) //паузим таймер
call DestroyTimer(t) //уничтожаем
call FlushChildHashtable( udg_Hash, id ) //очищаем хэш-таблицу от хэндла таймера
call BJDebugMsgXX( "|cFFff1e00На карте нет итемов, поэтому будет отдан приказ < выключить автоподбор >|r", u )
call DisableTrigger(GetTriggeringTrigger()) //выключаем триггер перед применением приказов. Выключаем специально, чтобы не было зацикливания и вылета
call IssueImmediateOrderById( u, 852056 ) //приказ использовать undefend
call EnableTrigger(GetTriggeringTrigger()) //включать триггер
set t = null
set u = null
endfunction
function TH takes unit u, real mind1, real maxd2 returns nothing
local integer id = GetHandleId(u) //Id-Handle юнита
local timer t = LoadTimerHandle(udg_Hash, id, 1) //подзагружаем таймер
local integer Id = GetHandleId(t) //Id-Handle таймера
local integer ID //Id-Handle итема
local boolexpr f //это фильтр, в него заносится функция которая отсеивает не нужное
local integer n //номер игрока
//засовываем в глобалки, чтобы в отдельной функции перебрать все итемы
set udg_unit = u //юнит
set udg_h = 0 //счетчик на кол-во предметов в радиусе maxd2, обнуляем счетчик на ноль
set udg_MAXX = 0 //счетчик на кол-во предметов по всей карте, обнуляем счетчик на ноль
set udg_dist1 = mind1 //изначальная дистанция (эта дистанция ничего не значит. так как все равно будет перезаписана)
set udg_dist2 = maxd2 //макс. дистанция, это важный пункт, показывает с какой радиус действия подбора итемов
set udg_DD = maxd2 //в эту переменную записывают реальное число, короче макс. дистанцию
// выбираем все предметы которые есть на карте, короче идет перебор между предметами
set f = Condition(function FG) //фильтр помогает отсеивать не нужные данные, например в EnumItemsInRect подберет те итемы, которые указаны в function FG, то есть итемы, которые видны (есть итемы, которые исчезают вроде рун), но вообще-то условие фильтра потом может увеличится со временем
call EnumItemsInRect( bj_mapInitialPlayableArea, f, function Trig_XX2 ) //перебирает все итемы на карте
call BJDebugMsgXX( "|cFFD852FFкол-во предметов по всей карте:|r " + I2S(udg_MAXX), u )
if udg_h > 0 then //если на карте кол-во итемов больше
call BJDebugMsgXX( "|cFFFFB0C2кол-во предметов в радиусе " + R2S(maxd2) + ":|r " + I2S(udg_h), u )
call BJDebugMsgXX( "|cFF00C850найден самый ближайщий итем|r " + "|cFFFFDC00" + GetItemName(udg_item[0])+ " |r", u )
set ID = GetHandleId(udg_item[0]) //Id-Handle итема
set n = GetPlayerId(GetOwningPlayer(u))
call SaveBoolean( udg_Hash, ID, n, true ) //запоминаем то, что этот предмет решился взять юнит
call SaveUnitHandle( udg_Hash, ID, n+100, u ) //запоминаем, что юнит данного игрока подбирает итем
call SaveBoolean( udg_Hash, id, 49, true ) //сохраняем проверку, что этот юнит пошел подбирать итем
call SaveItemHandle(udg_Hash, id, 50, udg_item[0] ) //сохраняем итем
call GroupAddUnit( udg_Group, u)
call IssueTargetOrderById( u, 851971, udg_item[0] ) //приказ подобрать итем
elseif udg_h == 0 then
call BJDebugMsgXX( "|cFFff1e00на карте отсутствуют итемы|r - |cFFD852FFкол-во итемов: " + I2S(udg_h) + " |r", u )
call SaveBoolean( udg_Hash, id, 0, false ) //пересохраняем то, что автоподбор выключен
call GroupRemoveUnit( udg_Group, u ) //удаляем юнита из группы !!!это действие бесполезно и нигде не используется, можно удалить!!!
call TimerStart(t, 0.00, false, function NHR) //используется вместо вэйта
endif
call DestroyBoolExpr(f) //не обязательно удалять, знаю привычка
set f = null
set t = null
endfunction
function GHJK takes nothing returns nothing
local timer t = GetExpiredTimer() //запущенный таймер
local integer id = GetHandleId(t) //Id-Handle таймера
local unit u = LoadUnitHandle(udg_Hash, id, 0) //подзагружаем нашего героя
local real dx = LoadReal(udg_Hash, id, 1) //подзагружаем прошедшие координаты
local real dy = LoadReal(udg_Hash, id, 2)
local integer tu = GetHandleId(u) //Id-Handle героя
local integer i = 0 //для цикла - помогает перебирать слоты
local integer count = 0 //для цикла - помогает подсчитать кол-во итемов
local boolean b = LoadBoolean(udg_Hash, tu, 0) //проверяет включена ли у него способность
local integer ID = GetUnitCurrentOrder(u) //текущий приказ, имеет числовое значение
local boolean b1 = (dx == GetUnitX(u) and dy == GetUnitY(u)) //сверяет прошедшедшее положение с текущим (есть ли смещения). GetUnitX/GetUnitY - определяют текущее положение, dy/dy - прошедшее
local boolean b2 = LoadBoolean(udg_Hash, tu, 49) //метка о том, что юнит подбирает итем
if (b) then //включен ли автоподбор
if ((b1) and ID == 0) or (not b2) then //если стоит на одном месте, и не выполняет никаких приказов или этот юнит не подбирает предмет
//то проверяем сколько свободных слотов имеет
loop
exitwhen i > 5
if ( UnitItemInSlot(u, i) == null ) then // если пустая ячейка то прибавляем к переменной единицу
set count = ( count + 1 )
endif
set i = i + 1
endloop
call BJDebugMsgXX( "|cFF00b25cЮнит стоит на одном месте, и ничего не делает|r " + "|cFFA000FFсвободных слотов: " + I2S(count) + " |r", u )
// потом проверяем если свободных слотов count больше 0, и автоподбор включен (b), значит ищем итемы
if count > 0 and b then
call BJDebugMsgXX( "|cFFFF00FFИдем искать итем (запускаем автопоиск итемов)|r", u )
call TH(u, 0, 1000000.) //запускаем функцию автопоиска предметов (здесь можно указать минимальный и максимальный радиус поиска предметов. максимальный стоит на 1000000. - почти на всю карту, нужно поубавить радиус)
// потом проверяем если свободных слотов нет (count=0), но автоподбор включен (b), значит выключаем автоподбор, удаляем таймер и чистим все
elseif (count == 0)and(b) then
call PauseTimer(t) //паузим таймер
call DestroyTimer(t) //удаляем таймер
call FlushChildHashtable( udg_Hash, id ) //чистим хэш-таблицу по ид-таймера
call SaveBoolean( udg_Hash, tu, 0, false ) //пересохраняем то, что автоподбор выключен
set ID = GetHandleId(LoadItemHandle(udg_Hash, tu, 50)) //Id-Handle итема
call SaveBoolean(udg_Hash, ID, GetPlayerId(GetOwningPlayer(u)), false) //убираем метку
call SaveItemHandle(udg_Hash, tu, 50, null ) //обнуляем из хэша итем
//внизу ссылочные данные (один ссылается на юнита. другой на итем), нужны чтобы удалить метки или ссылать на других
call SaveUnitHandle( udg_Hash, ID, GetPlayerId(GetOwningPlayer(u))+100, null ) //обнуляем юнита данного игрока, что решился ранее подобрать итем
call SaveBoolean( udg_Hash, tu, 49, false ) //стираем проверку (метка), что этот юнит когда-то хотел подобрать итем
//не знаю нужно ли выключать/включать триггер здесь
call DisableTrigger(GetTriggeringTrigger())//выключаем триггер перед применением приказов. Выключаем специально, чтобы не было зацикливания и вылета
call IssueImmediateOrderById( u, 852056 ) //приказ использовать undefend
call EnableTrigger(GetTriggeringTrigger()) //включаем обратно
call BJDebugMsgXX( "|cFFFF9E00Cлоты заняты, поэтому отключаем абилку (отдаем приказ < выключить автоподбор > ) и удаляем таймер|r", u )
endif
elseif (not b1) then //эта проверка говорит, что координаты смещены, то есть юнит двигается или делает какие-нибудь дела
call SaveReal(udg_Hash, id, 1, GetUnitX(u)) //пересохраняем
call SaveReal(udg_Hash, id, 2, GetUnitY(u))
endif
elseif (not b) then //если выключен автоподбор, то таймер нужно удалить
//бывают случаи, когда отключаешь автоподбор, а юнит дальше бежит подбирать итем, то тут здесь, в этом блоке if надо дать приказ "стоп"
call PauseTimer(t) //паузим таймер
call DestroyTimer(t) //уничтожаем таймер
call FlushChildHashtable( udg_Hash, id ) //очищаем хэш-таблицу от хэндла таймера (это важно, здесь мы очишаем от хэндла таймера который не нужен)
call SaveBoolean( udg_Hash, tu, 0, false ) //сохраняем то, что автоподбор выключен
call BJDebugMsgXX( "|cFFFF9E00Если автоподбор отключен, то удаляем таймер|r", u )
endif
set t = null
set u = null
endfunction
function T_order_A takes nothing returns nothing
local integer OId = GetIssuedOrderId() //текущий Id-приказ юнита
local unit U = GetOrderedUnit() //юнит, получивший этот приказ
local integer id = GetHandleId(U) //Id-Handle юнита (короче номер объекта. у каждого он свой)
local integer i = 0 //для цикла - помогает перебирать слоты
local integer count = 0 //для цикла - помогает подсчитать кол-во итемов
local integer ID //Id-Handle итема
local integer x1 = 852055 //приказ defend
local integer x2 = 851971 //приказ smart
local integer x3 = 852056 //приказ undefend
local boolean b = LoadBoolean(udg_Hash, id, 0) //проверяет включен ли у юнита автоподбор (если там ничего не сохранено, то вернет false)
local integer Ev = GetHandleId(GetTriggerEventId()) //Id-Handle события (38 - без цели, 39 - точка, 40 - цель)
local boolean b1 = (OId == x1 and Ev == 38) //включить автоподбор
local boolean b2 = (OId != x2 and GetOrderTargetItem() == null and Ev == 40 and b) //получил какой-то другой приказ по цели, но целью не является итем, это должно происходить во время включеннного подбора
local boolean b3 = (OId == x2 and Ev == 39 and b) //получил приказ щелчком правой кнопки мыши отойти в точку. это должно происходить во время включенного автоподбора
local boolean b4 = (OId == x3 and Ev == 38) //выключить автоподбор
local boolean b5 = ( (OId != x1 or OId !=x2 or OId != x3) and (Ev == 38 or Ev == 39) and b) //если ни один из приказов не работает
//local boolean b6 = ( (not b1) and b2 and b3 and b4) and (Ev > 37 and Ev < 41) //старая версия b5
local item ITM
local timer t = null //таймер
local integer it //Id-Handle таймера
local integer n //номер игрока
//автоподбор включен, 852055 - приказ укрыться щитом (defend)
if ( b1 ) then
call BJDebugMsgXX( "|cFF00b25cавтоподбор включен|r", U )
//циклом проверяем слоты
loop
exitwhen i > 5
// если пустая ячейка то прибавляем к переменной count единицу
if ( UnitItemInSlot(U, i) == null ) then
set count = ( count + 1 )
endif
set i = i + 1
endloop
call BJDebugMsgXX( "|cFFdbf900кол-во свободных слотов:|r " + I2S(count), U )
// потом проверяем если свободных слотов count больше 0, и значит делаем действия
if ( count > 0 ) then
call BJDebugMsgXX( "|cFFA0C2DFКол-во свободных слотов больше нуля, значит есть места, запускаем автопоиск (Идем искать итем) и таймер по отслеживанию состояния героя (делает ли герой что-нибудь)|r", U )
set t = LoadTimerHandle(udg_Hash, id, 1) //подзагружаем таймер (если ранее таймер не был создан, то вернет null)
if t == null then //если переменная пустая, значит таймер не запущен у раба, следовательно, запускаем новый
//здесь создается таймер, который ежесекундно проверяет раба, стоит ли он или что-то делает
set t = CreateTimer()
set it = GetHandleId(t) //Id-Handle таймера
call SaveUnitHandle(udg_Hash, it, 0, U) //сохраняем героя
call SaveReal(udg_Hash, it, 1, GetUnitX(U)) //сохраняем текущие координаты
call SaveReal(udg_Hash, it, 2, GetUnitY(U))
call SaveTimerHandle(udg_Hash, id, 1, t) //сохраняем таймер
call TimerStart(t, 0.03, true, function GHJK) //запускаем таймер
call BJDebugMsgXX( "|cFFA0C200У этого юнита нет таймера, поэтому создаем и запускаем новый таймер|r", U )
endif
call SaveBoolean( udg_Hash, id, 0, true ) //сохраняем то, что автоподбор включен (это важная фишка для работы системы, проверяет включен ли автоподбор у героя)
call TH(U, 0, 1000000.) //запускаем функцию автопоиска предметов (здесь можно указать минимальный и максимальный радиус поиска предметов. максимальный стоит на 1000000. - почти на всю карту, нужно поубавить радиус)
elseif count == 0 then //если нет свободных слотов (count = 0), то отключаем автоподбор
call SaveBoolean( udg_Hash, id, 0, false ) //пересохраняем то, что автоподбор выключен
set ITM = LoadItemHandle(udg_Hash, id, 50) //загружаем итем в локалку (если в хэше ничего не сохранено, то вернет null)
set ID = GetHandleId(ITM) //Id-Handle итема
set n = GetPlayerId(GetOwningPlayer(U)) //номер игрока
call SaveBoolean(udg_Hash, ID, n, false) //убираем метку
call SaveItemHandle(udg_Hash, id, 50, null ) //обнуляем из хэша итем
//внизу ссылочные данные (один ссылается на юнита. другой на итем), нужны чтобы удалить метки или ссылать на других
call SaveUnitHandle( udg_Hash, ID, n+100, null ) //обнуляем юнита данного игрока, что решился ранее подобрать итем
call SaveBoolean( udg_Hash, id, 49, false ) //стираем проверку (метка), что этот юнит когда-то хотел подобрать итем
//call GroupRemoveUnit( udg_Group, U ) //удаляем юнита из группы !!!это действие бесполезно и нигде не используется!!!
//call FlushChildHashtable( udg_Hash, id ) //это стирает все данные по хэндлу !!!будьте осторожны, из-за этого у меня в другой системе не работало, лучше отказаться от нее!!!
call TriggerSleepAction(0.) //вэйт, его нужно !!! попробовать убрать !!!!
call DisableTrigger(GetTriggeringTrigger()) //выключаем триггер перед применением приказов. Выключаем специально, чтобы не было зацикливания и вылета
call IssueImmediateOrderById( U, 852056 ) //использовать приказ undefend
call EnableTrigger(GetTriggeringTrigger()) //включаем обратно триггер
call BJDebugMsgXX( "|cFFff1e00кол-во свободных слотов равно ноль (мест нет, куда положить итемы), автоподбор выключен|r", U )
endif
//здесь может быть ситуация, когда может дан другой приказ, отличающий от автоподбора и приказа подобрать итем (щелчком правой кнопки мыши по итему - smart)
//иначе если переменная "Итем-цель приказа" пуста и приказ не равен 851971 (smart), короче отсеиваем отданный приказ взять итем
//или если приказ щелчком мыши кликнули по земле, то нужно это тоже предусмотреть, щелчок правой кнопки мыши (smart = 851971) мы можем отвести юнита от итема, короче автоподбор должен выключится
//или если какой-нибудь другой приказ отдан будет
//три условия выше срабатывают, при условии, что автоподбор (b) включен
elseif (b2 or b3 or b4 or b5) then //851971 - приказ smart
call SaveBoolean( udg_Hash, id, 0, false ) //пересохраняем то, что автоподбор выключен
set ITM = LoadItemHandle(udg_Hash, id, 50 ) //подзагрузим итем в глобалку, глобалка нужна в качестве ссылки. Мы короче ссылаемся на udg_item[44] в нижних функциях
set ID = GetHandleId(ITM) //Id-Handle итема
//Внизу будет сохранение метки, короче мы помечаем, что этот предмет подобран игроком.
//У каждого игрока одна метка, то есть у этого игрока только один его юнит может взять, а остальные не могут
//посоперничать игроки могут конечно за итем, но вряд ли до такого абсурда дойдет
set n = GetPlayerId(GetOwningPlayer(U))
call SaveBoolean( udg_Hash, ID, n, false ) // (МЕТКА) пересохраняем то, что этот предмет больше никто не берет из юнитов игрока
call SaveItemHandle(udg_Hash, id, 50, null ) //обнуляем из хэша итем
//внизу ссылочные данные (один ссылается на юнита. другой на итем), нужны чтобы удалить метки или ссылать на других
call SaveUnitHandle( udg_Hash, ID, n+100, null ) //обнуляем юнита данного игрока, что решился ранее подобрать итем
call SaveBoolean( udg_Hash, id, 49, false ) //стираем проверку (метка), что этот юнит когда-то хотел подобрать итем
//очистка
//call GroupRemoveUnit( udg_Group, U ) //удаляем юнита из группы !!!эта группа вообще не нужна, не нашел в ней нужды и нигде не используется, можно удалить!!!
//call FlushChildHashtable( udg_Hash, id ) //это стирает все данные по хэндлу !!!будьте осторожны, из-за этого у меня в другой системе не работало, лучше отказаться от нее!!!
if b2 then
call BJDebugMsgXX( "|cFFff1e00Автоподбор выключен, удаляем метку с итема |r" + "Причина: был отдан другой приказ. В качестве цели является цель, либо целью не является итем (а мб юнит, декорация и др.), либо отдан другой приказ (атаковать итем). Все это произошло во время автоподбора. Id приказ: " + I2S(OId) + ". Название приказа: " + OrderId2StringBJ(OId) + ". Номер событий: " + I2S(Ev),U)
elseif b3 then
call BJDebugMsgXX( "|cFFff1e00Автоподбор выключен, удаляем метку с итема |r" + "Причина: был отдан другой приказ. В качестве цели является точка, был отдан приказ щелчком по правой кнопки мыши в точку, короче был отдан приказ отойти во время автоподбора" , U )
elseif b4 then
call BJDebugMsgXX( "|cFFff1e00Автоподбор выключен, удаляем метку с итема |r" + "Причина: Была нажата кнопка выключить автоподбор", U )
elseif b5 then
call BJDebugMsgXX( "|cFFff1e00Автоподбор выключен, удаляем метку с итема |r" + "Причина: был отдан неизвестный другой приказ во время автоподбора. Id приказ: " + I2S(OId) + ". Название приказа: " + OrderId2StringBJ(OId) + ". Номер событий: " + I2S(Ev),U)
endif
if ( OId != 852056 ) then //проверяем, что данный приказ не равно undefend
call DisableTrigger(GetTriggeringTrigger()) //выключаем триггер, чтобы не было зацикливания при отдаче приказа
call IssueImmediateOrderById( U, 852056 ) //приказ использовать щит, короче undefend
call EnableTrigger(GetTriggeringTrigger()) //включаем обратно
elseif ( OId == 852056 ) then
call DisableTrigger(GetTriggeringTrigger()) //выключаем триггер перед применением приказов. Выключаем специально, чтобы не было зацикливания и вылета
call IssueImmediateOrderById( U, 851972 ) //приказ стоп
call IssueImmediateOrderById( U, 852056 ) //приказ использовать щит, короче undefend
call EnableTrigger(GetTriggeringTrigger()) //включаем обратно триггер
endif
endif
set t = null
set U = null
set ITM = null
endfunction
//===========================================================================
function InitTrig_order_pick_of_item takes nothing returns nothing
set gg_trg_order_pick_of_item = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_order_pick_of_item, EVENT_PLAYER_UNIT_ISSUED_ORDER )
call TriggerRegisterAnyUnitEventBJ( gg_trg_order_pick_of_item, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterAnyUnitEventBJ( gg_trg_order_pick_of_item, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
call TriggerAddCondition( gg_trg_order_pick_of_item, Condition( function T_order_C ) )
call TriggerAddAction( gg_trg_order_pick_of_item, function T_order_A )
endfunction
при получении итема, ставим метку на итем
function Trig_item_Conditions takes nothing returns boolean
local integer ID = GetHandleId( GetManipulatedItem()) ////Id хэндл итема
local boolean b = LoadBoolean(udg_Hash, ID, GetPlayerId(GetTriggerPlayer())) //проверяем метку
return( b ) //если помечен, то ...
endfunction
function Trig_item_Actions takes nothing returns nothing
local integer id1 = GetHandleId(GetManipulatedItem()) //Id хэндл итема
local unit u = GetTriggerUnit() //юнит который продал итем
local integer n = GetPlayerId(GetTriggerPlayer()) //номер игрока
local unit U
local integer i = 0 //для цикла
local integer y = 0 //для подсчета юнитов
loop
exitwhen i>11
set U = LoadUnitHandle( udg_Hash, id1, i+100) //подзагружаем юнита из хэша (если в хэше ничего не сохранено, то вернет null, короче пусто будет)
if U != u and U != null then //юнит не равен герою. который подобрал, и не равен пустоте
call SaveBoolean(udg_Hash, GetHandleId(U), 49, false) //тут пересохраняем
set y = y + 1
endif
set i = i + 1
endloop
call FlushChildHashtable( udg_Hash, id1 )
call BJDebugMsgXX( "подобран итем " + GetItemName(GetManipulatedItem()), u )
call BJDebugMsgXX( "кол-во юнитов, которые не смогли подобрать " + I2S(y), u )
set u = null
set U = null
endfunction
//===========================================================================
function InitTrig_unit_pickup_item takes nothing returns nothing
set gg_trg_unit_pickup_item = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_unit_pickup_item, EVENT_PLAYER_UNIT_PICKUP_ITEM )
call TriggerAddCondition( gg_trg_unit_pickup_item, Condition( function Trig_item_Conditions ) )
call TriggerAddAction( gg_trg_unit_pickup_item, function Trig_item_Actions )
endfunction
проверяем приказы при автопродаже
Здесь используется другая способность - магическая защита. Преимущество - не сбивает приказ, не останавливается, недостаток - не дает натравить вражеские заклинания. Замените тогда, на магический щит.
- Если мы включаем кнопку, первое, что на нужно сделать это проверить наличие хотя бы одного итема. Затем ищем магазин, и помечаем в хэше, что этот раб идет продавать. Здесь метка отличается от метки итема при автоподборе. Дело в том, что юнит сначала дропает итем в магазин, а потом продает (закладывает).
- Если кнопка отключена, автопродажа отключена.
- Если отдан другой какой-нибудь приказ, то автопродажа отменяется.
function T_ss_C takes nothing returns boolean
local integer id = GetIssuedOrderId() //Id отданный приказ
local integer Id = GetHandleId(GetTriggerUnit()) //Id-Handle героя
local integer x1 = 852478 //приказ magicdefense
local integer x2 = 852479 //приказ magicundefense
local integer x3 = 852001 //приказ dropitem
local integer Ev = GetHandleId(GetTriggerEventId()) //Id-Handle события (38 - без цели, 39 - точка, 40 - цель)
local boolean b = LoadBoolean(udg_Hash, Id, 67) //загружаем метку (не бежит ли в данный момент герой продавать итемы)
local boolean b1 = (id == x1 and Ev == 38) //автопродажа включена
local boolean b2 = (id == x2 and Ev == 38) //автопродажа выключена
local boolean b3 = (id != x1 and id != x2 and id != x3 and (Ev > 38 and Ev < 41) and b) //отдан какой-нибудь другой приказ
return (b1 or b2 or b3)
endfunction
function Tfilter takes nothing returns boolean
return (GetUnitAbilityLevel(GetFilterUnit(), 'Apit') > 0) //те кто имеет скил лавка продать итем, без этого скила никто не сможет продать предметы
endfunction
function TXS takes nothing returns nothing
local real x1 = GetUnitX(udg_unit) //юнит
local real y1 = GetUnitY(udg_unit)
local real x2 = GetUnitX(GetEnumUnit()) //выбранный магазин
local real y2 = GetUnitY(GetEnumUnit())
local real dx = x2 - x1 //направление вектора
local real dy = y2 - y1
//вычисляем расстояние между героем и выбранным магазином
set udg_dist1 = SquareRoot(dx * dx + dy * dy) //SquareRoot - корень, dx * dx - возводим в степень 2
if ( udg_dist1 < udg_dist2 ) then //если расстояние между героем и данным магазином меньше текущего, то ...
set udg_dist2 = udg_dist1 //перезапоминаем текущее расстояние (если в будущем попадется меньше, то перезапишется снова)
set udg_U[55] = GetEnumUnit() //запоминаем магазин
endif
set udg_h = udg_h + 1
endfunction
function TTT takes player p, unit u5 returns unit
local boolexpr b
call GroupClear(udg_ggg) //очищаем группу от юнитов
set udg_Player = p //эта переменная игрок бесполезна. но может пригодится в качестве ссылки, будем ссылаться на игрока, нужна для переноса в функцию фильтр (проверять враг или союзник и так далее). Вместо этого можно использовать классификацию нейтральный например
set b = Condition(function Tfilter)
call GroupEnumUnitsOfPlayer(udg_ggg, p, b)
call DestroyBoolExpr(b) //не обязательно удалять, знаю привычка
call BJDebugMsgXX( "|cFFFFBF00Начинаем поиск магазина|r", u5)
//засовываем в переменные
set udg_unit = u5
set udg_dist1 = 0.00
set udg_dist2 = 1000000000.00
set udg_h = 0 //счетчик на кол-во магазинов, обнуляем на ноль
call ForGroup(udg_ggg, function TXS)
call BJDebugMsgXX( "|cFFFF00FFкол-во магазинов на карте " + I2S(udg_h) + " |r", u5 )
return udg_U[55]
endfunction
function T_ss_A takes nothing returns nothing
local unit u1 = GetTriggerUnit() //герой
local unit u2 //предпологаемый магазин, в данный момент переменная пуста
local integer id = GetHandleId(u1) //Id-Handle героя
local integer i = 0 //для цикла, нужно при пробеге по слотам
local integer c = 0 // для подсчета кол-ва итемов в инвентаре героя
local boolean b = false //это нужно, чтобы выбрать первый итем
local integer n //номер первого слота
local integer ID = GetIssuedOrderId() //Id отданный приказ
local integer x1 = 852478 //приказ magicdefense
local integer x2 = 852479 //приказ magicundefense
local integer x3 = 852001 //приказ dropitem
local integer Ev = GetHandleId(GetTriggerEventId()) //Id-Handle события (38 - без цели, 39 - точка, 40 - цель)
local boolean b0 = LoadBoolean(udg_Hash, id, 67) //загружаем метку (не бежит ли в данный момент герой продавать итемы)
local boolean b1 = (ID == x1 and Ev == 38) //автопродажа включена
local boolean b2 = (ID == x2 and Ev == 38) //автопродажа выключена
local boolean b3 = (ID != x1 and ID != x2 and ID != x3 and (Ev > 38 and Ev < 41) and b0) //отдан какой-нибудь другой приказ
if b1 then
call BJDebugMsgXX( "|cFF00C850автопродажа включена|r", u1 )
//пробегаем циклом по слотам героя
loop
exitwhen i > 5 //условия выхода из цикла (от 0 до 5, нумерация другая не от 1-6, а от 0-5)
if ( UnitItemInSlot(u1, i) != null ) then //проверяет не пустой ли слот
set c = ( c + 1 ) //если не пустой складываем
if b == false then //если нам попался первый слот
set n = i //запоминаем номер первого слота
set b = true //запоминаем. что первый слот мы получили
endif
endif
set i = i + 1
endloop
call BJDebugMsgXX( "|cFF4FC6D1Проверка: в начале в инвентаре героя предметов всего |r"+ I2S(c), u1 )
if c > 0 then
call BJDebugMsgXX( "|cFF4FDF00Номер слота первого выбранного итема: " + I2S(n+1) + " |r", u1 )
call BJDebugMsgXX( "|cFF00FFFFслоты еще не пустые, поэтому сохраняем юнита и ...|r" , u1 )
call BJDebugMsgXX( "|cFFFFB0C2Ищем ближайший магазин|r", u1)
set u2 = TTT(GetTriggerPlayer(), u1) //ищем магазин
call BJDebugMsgXX( "|cFFFFBF00Найден ближайший магазин, имя ему " + GetUnitName(u2) + " |r", u1)
call SaveUnitHandle(udg_Hash,id, 4, u2) //магазин
call UnitDropItemTarget( u1, UnitItemInSlot(u1, n), u2 ) //Приказываем дропнуть/продать/заложить в лавку
call SaveBoolean(udg_Hash, id, 67, true) //сохраняем то, что юнит получил приказ продать итем, пока он бежит к магазину, он имеет эту метку. Как только получит другую метку, то произойдет отмена автопродажи
elseif c == 0 then
call BJDebugMsgXX( "|cFFff1e00Автопродажа отключена, потому что у героя нет больше итемов.|r Проверка использована после включения кнопки < включить автопродажу >. Будет отдан приказ использовать кнопку < выключить автопродажу >. ", u1 )
call SaveUnitHandle(udg_Hash, id, 4, null) //обнуляем данные
call SaveBoolean(udg_Hash, id, 67, false) //обнуляем данные
call DisableTrigger(GetTriggeringTrigger()) //выключаем триггер перед применением приказов. Выключаем специально, чтобы не было зацикливания и вылета
call IssueImmediateOrderById( u1, 851972 ) //приказ стоп
call TriggerSleepAction(0.) //очень важная пауза, помогает сменить иконку выключенную кнопки на включенную
call IssueImmediateOrderById( u1, 852479 ) //приказ magicundefense
call EnableTrigger(GetTriggeringTrigger())
endif
elseif (b2 or b3) then
call SaveUnitHandle(udg_Hash, id, 66, null) //обнуляем данные
call SaveBoolean(udg_Hash, id, 67, false) //обнуляем данные
call DisableTrigger(GetTriggeringTrigger()) //выключаем триггер перед применением приказов. Выключаем специально, чтобы не было зацикливания и вылета
call IssueImmediateOrderById( u1, 851972 ) //приказ стоп
call IssueImmediateOrderById( u1, 852479 ) //приказ magicundefense
call EnableTrigger(GetTriggeringTrigger()) //включаем триггер
if b2 then
call BJDebugMsgXX( "|cFFff1e00Автопродажа отключена.|r " + "Причина: была нажата кнопка < выключить автопродажа >", u1 )
elseif b3 then
call BJDebugMsgXX( "|cFFff1e00Автопродажа отключена.|r " + "Причина: был отдан другой приказ во время автопродажи. Id приказ: " + I2S(ID) + ". Название приказа: " + OrderId2StringBJ(ID) + ". Номер событий: " + I2S(Ev), u1 )
endif
endif
set u1 = null
set u2 = null
endfunction
//===========================================================================
function InitTrig_order_drop_of_item takes nothing returns nothing
set gg_trg_order_drop_of_item = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_order_drop_of_item, EVENT_PLAYER_UNIT_ISSUED_ORDER )
call TriggerRegisterAnyUnitEventBJ( gg_trg_order_drop_of_item, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterAnyUnitEventBJ( gg_trg_order_drop_of_item, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
call TriggerAddCondition( gg_trg_order_drop_of_item, Condition( function T_ss_C ) )
call TriggerAddAction( gg_trg_order_drop_of_item, function T_ss_A )
endfunction
при дропе итема снимаем метку (короче хэш чистим и все)
function T_sell_item_C takes nothing returns boolean
local integer id = GetHandleId(GetTriggerUnit())
local boolean b = LoadBoolean(udg_Hash, id, 67)
return(b)
endfunction
function T_sell_item_A takes nothing returns nothing
local unit u1 = GetTriggerUnit() //продавец (герой)
local integer id = GetHandleId(u1) //Id-Handle героя
local unit u2 = LoadUnitHandle(udg_Hash, id, 4) //покупатель (магазин)
local integer i = 0
local integer c = 0
local boolean b = false
local integer n
local item it1
call BJDebugMsgXX( "|cFF00C850Проданный итем|cFFFFBB00 " + GetItemName(GetSoldItem()) + " |r", u1 )
call TriggerSleepAction(0.) //ЭТОТ ВЭЙТ ОЧЕНЬ ВАЖНАЯ ШТУКА делает задержку, очень необходима, так как триггер срабатывает и показывает, что итем уже продан. но самом деле данный предмет еще не продан
//проверяем инвентарь героя, пробегаемся по слотам (от 1 до 6)
loop
exitwhen i > 5
if ( UnitItemInSlot(u1, i) != null ) then //если слот не пустой...
set c = ( c + 1 ) //то прибавляем кол-во итемов
if b == false then //если это в первый раз
set n = i //запоминаем номер слота
set it1 = UnitItemInSlot(u1, i) //запоминаем первый итем
set b = true //запоминаем уже, что это не первый раз
endif
endif
set i = i + 1
endloop
call BJDebugMsgXX( "|cFF2B81FFкол-во ПРЕДМЕТОВ в инвентаре героя:|r " + I2S(c), u1 )
if c > 0 then
call SaveUnitHandle(udg_Hash, id, 4, u2)
call SaveBoolean(udg_Hash, id, 67, true)
call BJDebugMsgXX( "|cFF00FFFFВыставляем на продажу|r", u1 )
call BJDebugMsgXX( "|cFF4FDF00Номер слота следующего выбранного итема: " + I2S(n+1) + " |r", u1 )
call BJDebugMsgXX( "|cFFA0FF00Имя героя|cFFFFA900 - " + GetUnitName(u1)+"/|cFFA000FFИмя лавки|cFFFFA900 - " + GetUnitName(u2)+ "/|cFFA0FC61Название выбранной на продажу вещи|cFFFFA900 - " +GetItemName(it1) + " |r", u1)
call UnitDropItemTarget( u1, it1, u2 )
elseif c == 0 then
call BJDebugMsgXX( "|cFFff1e00Автопродажа отключена, потому что у героя нет больше итемов.|r Проверка использована при продаже. Будет отдан приказ использовать кнопку < выключить автопродажу >.", u1 )
call SaveUnitHandle(udg_Hash, id, 4, null) //обнуляем данные
call SaveBoolean(udg_Hash, id, 67, false) //обнуляем данные
//пока вылетов не было я не стал выключать / включать триггер
call IssueImmediateOrderById( u1, 852479 ) //приказ magicundefense
endif
set u1 = null
set u2 = null
set it1 = null
endfunction
//===========================================================================
function InitTrig_unit_pawn_item takes nothing returns nothing
set gg_trg_unit_pawn_item = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_unit_pawn_item, EVENT_PLAYER_UNIT_PAWN_ITEM )
call TriggerAddCondition( gg_trg_unit_pawn_item, Condition( function T_sell_item_C ) )
call TriggerAddAction( gg_trg_unit_pawn_item, function T_sell_item_A )
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован MpW