Добавлен , опубликован
Раздел:
Триггеры и объекты
Думаю, многие хотели бы использовать нестандартные триггеры на всех картах, однако это считалось невозможным. На самом деле, это решили еще в годы мода Nirvana, но никто не обратил внимание, по крайней мере, я не находил информации. Меня много раз просили написать статью, но мне было лень, но, как видите, руки всё же дошли до дела.
Первое, что нам нужно, это создать триггер либо в GUI, либо в Jass. Для примера я написал триггер по перехвату контроля над юнитом. Если ваш триггер изначально написан на Jass, можно пропустить следующий шаг.

Далее наш триггер нужно перевести в Jass, для этого нажмем на пункт "Правка" и в всплывшем меню выберем "Конвертировать в текст".

Отлично, теперь мы обладаем кучей кода, который нам нужно будет пристроить к WC3, для этого открываем War3Patch.mpq и достаем из него Blizzard.j (Scripts/Blizzard.j). Там мы ищем функцию InitBlizzard, как показано на скриншоте.
Внимание, у WC3 - TFT и ROC разные Blizzard.j, будьте внимательны!
Мой код
function Trig_Take_Control_Func001A takes nothing returns nothing
    call SetUnitOwner( GetEnumUnit(), GetTriggerPlayer(), true )
endfunction

function Trig_Take_Control_Actions takes nothing returns nothing
    call ForGroupBJ( GetUnitsSelectedAll(GetTriggerPlayer()), function Trig_Take_Control_Func001A )
endfunction

//===========================================================================
function InitTrig_Take_Control takes nothing returns nothing
    set gg_trg_Take_Control = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(0), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(1), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(2), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(3), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(4), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(5), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(6), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(7), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(8), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(9), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(10), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(11), "-takecontrol", true )
    call TriggerAddAction( gg_trg_Take_Control, function Trig_Take_Control_Actions )
endfunction

Чтобы всё работало, код, к которому будут обращаться, должен располагаться выше вызова. Прошу заметить, что я также немного изменил его, а именно заменил оператор set на local trigger, показав, что эта переменная типа триггер и является локальной. Также, для простоты чтения, я дописал комментарии и вынес все функции вызова в отдельную функцию InitCustomTrigs. Не знаю почему, но когда я указывал название InitCustomTriggers, то возникала ошибка. Как я это определил, узнаем чуть ниже.
Мой код
//===========================================================================
// Command: -takecontrol

function Trig_Take_Control_Func001A takes nothing returns nothing
    call SetUnitOwner( GetEnumUnit(), GetTriggerPlayer(), true )
endfunction

function Trig_Take_Control_Actions takes nothing returns nothing
    call ForGroupBJ( GetUnitsSelectedAll(GetTriggerPlayer()), function Trig_Take_Control_Func001A )
endfunction

//===========================================================================
function InitTrig_Take_Control takes nothing returns nothing
    local trigger gg_trg_Take_Control = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(0), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(1), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(2), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(3), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(4), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(5), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(6), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(7), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(8), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(9), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(10), "-takecontrol", true )
    call TriggerRegisterPlayerChatEvent( gg_trg_Take_Control, Player(11), "-takecontrol", true )
    call TriggerAddAction( gg_trg_Take_Control, function Trig_Take_Control_Actions )
endfunction

//===========================================================================
// Custom triggers initializing

function InitCustomTrigs takes nothing returns nothing
	call InitTrig_Take_Control()
endfunction

//===========================================================================
function InitBlizzard takes nothing returns nothing
    // Set up the Neutral Victim player slot, to torture the abandoned units
    // of defeated players.  Since some triggers expect this player slot to
    // exist, this is performed for all maps.
    call ConfigureNeutralVictim()

    call InitBlizzardGlobals()
    call InitQueuedTriggers()
    call InitRescuableBehaviorBJ()
    call InitDNCSounds()
    call InitMapRects()
    call InitSummonableCaps()
    call InitNeutralBuildings()
    call DetectGameStarted()
	call InitCustomTrigs()
	
endfunction

Так, теперь нам пора опробовать наше творение, для этого каким-либо способом подгружаем получившийся Blizzard.j к WC3. Я это буду делать через mix. Также создаем папку Scripts и кидаем файл туда.

Для проверки кода на валидность, заходим в сражение, и если меню настройки лобби у вас не пропало, то всё работает. Так себе метод, но главное, что работает.

И так, вот и пришло время проверки, я всегда хотел поиграть за Тралла в кампании орды от WC3 - TFT, ну и вот, что получилось)
На всякий случай прикреплю mix к статье.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
1
9
4 года назад
1
Красавчик! Определенно плюс! Странно что такие полезности не замечают сразу!
1
37
4 года назад
Отредактирован ScorpioT1000
1
Лол)) это было известно чуть ли не с рождения xgm
3
32
4 года назад
3
Эта игра слишком древняя, новое поколение повторно делает открытия, и не вижу в этом ничего плохого
0
19
4 года назад
0
ScorpioT1000, возможно, однако в свое время искал статьи, но так и не нашел\ Был где-то 2015

Ах да, касательно отправленной ссылки, там речь-то о common.j идет, где прописаны константы и нативки, а не про встраивание триггеров :DDD
0
27
4 года назад
0
единственное что нужно дополнить, в мультиплеере это вызывает мгновенный десинк.
0
19
4 года назад
0
DioD, ну почему, если это будет встроено в карту, или mix будет у всех клиентов + сервера, то всё будет работать.
0
10
4 года назад
0
Ev3nt:
DioD, ну почему, если это будет встроено в карту, или mix будет у всех клиентов + сервера, то всё будет работать.
Камера для игрока у которого микс тоже дессинхрон будет?
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.