Реклама: Новые сервера Lineage 2

Ходьба крипов как в Dota Allstars

4 августа 2009
Доброго времени суток дорогие посетители.

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

1. Когда крип доходит до последней точки, он (если еще остался живым) возвращается на то место, где появился.
2. Здания - они атакуют находящегося в зоне действия крипа при этом когда у крипа оказывается уровень жизни на 50%, он убегает.
3. Крипы на пролом проходят мимо оборонительных сооружений, при этом получают урон и получается проблема № 2. Конечно когда они будут возвращатся, тогда их окончательно убьёт оборонительное сооружение.

Давайте разберёмся от чего получаются подобные проблемы.

Наверное все замечали, что если ударить любого крипа (нейтрала, врага) и отбежать, то он будет бежать за вами, но не долго. После он развернётся и пойдёт на исходную позицию. Это так сказать "фишка" близзардов, так сказать что бы крипы не скитались по миру, а были на своём посту, но если мы делаем карту типа Доты, Коридоров то, нам просто необходимо отключить данную способность. За эту способность отвечает одна интересная функция Guard Position, далее рассмотрим ее более подробно.

Для понимания данной функции мы направим крипа в точку обозначая ее Locations записывая в колонку Custom value ID направления к которому должен идти наш крип. Теперь рассмотрим это в действии, так описываем событие Trigger:

call TriggerRegisterPlayerUnitEvent(t,Player(13),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)
call TriggerRegisterPlayerUnitEvent(t,Player(14),EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,null)

Условие, здесь опишем что нам нужно от события, а нам нужно передвижение к определенному ID Locations:

return GetIssuedOrderId()==OrderId("move")

Описываем действие (перемещения крипа) события:

function IssOrder takes nothing returns nothing
local unit u = GetTriggerUnit()
call SetUnitPosition(u,GetUnitX(u),GetUnitY(u))
call DisableTrigger(GetTriggeringTrigger())
call IssuePointOrderByIdLoc(u,OrderId("attack"),udg_Locations[GetUnitUserData(u)])
call EnableTrigger(GetTriggeringTrigger())
endfunction

Обратите внимание на скрипт:

call SetUnitPosition(u,GetUnitX(u),GetUnitY(u))

Что же делает этот участок скрипта, спросите вы, а делает он очень не хитрое, но очень нужное действие. Он сбивает точку появления крипа и заменяет ее на ту где он в данный момент. Тоесть он будет следовать совей цели не смотря ни на что. Вот и всё, убили одновременно два зайца, так как проблемы под № 1 и 2 мы только что решили.

Хочу ещё обратить ваше внимание на не менее интересный кусок скрипта:

call IssuePointOrderByIdLoc(u,OrderId("attack"),udg_Locations[GetUnitUserData(u)])

Как видим из написаного, наш крип перемещается с точки "рождения" которая постоянно меняется на ту где он находится по пути атакуя все вражиские цели, за это отвечает функция attack.

У нас осталась проблема под № 3, давайте решим и её.

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

Для этого напишем событие, в котором будем перебирать юнитов и сооружения. Первым делом создаём Trigger и добавим ему следующее событие:

set t = CreateTrigger()
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(13),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
if GetUnitAcquireRange(u)!=0 and IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call TriggerRegisterUnitInRange(t,u,600,null)
endif
endloop
call DestroyGroup(g)
set g = CreateGroup()
call GroupEnumUnitsOfPlayer(g,Player(14),null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
if GetUnitAcquireRange(u)!=0 and IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call TriggerRegisterUnitInRange(t,u,600,null)
endif
endloop
call DestroyGroup(g)

Здесь мы указали что крип проходя свой путь (Locations) не только вражеских юнитов, но и сооружения, как это сделано в "Dota Allstars".
Добавим условие нашему Triggers, описанное в решении проблемы № 1 и 2:

call TriggerAddCondition(t,Condition(function IsMobCondition))
call TriggerAddAction(t,function IssOrder)

А наша функция условия, будет таковой:

function IsMobCondition takes nothing returns boolean
return (GetOwningPlayer(GetTriggerUnit())==Player(13)) or (GetOwningPlayer(GetTriggerUnit())==Player(14))
endfunction

Вот и всё, удачного маппинга и до новых встречь!

Автор статьи : PROGRAMMATOR
При копировании статьи ссылка на http://zone-game.info/guard_position.html - обязательна!