Добавлен , опубликован

Осваиваем jass (0-1)

Содержание:

17. Приложение 2: JESP стандарт

Зарубежные картостроители (буржуи) разработали специальный стандарт написания триггерных заклинаний, который упрощает работу с ними. Упрощает, впрочем, не автору, а тем, кто захочет данное заклинание импортировать или поменять его параметры. Не думаю, что стандарт стоит применять в чистом виде. Но некоторые принципы JESP можно позаимствовать, т.к. с точки зрения программиста они разумны.
Разберем пример.
//===========================================================================
//            Ion cannon
//            удар по местности с массивными повреждениями
//===========================================================================

//SpellData==================================================================
function Ion_cannon_ability takes nothing returns integer
    return 'A04Y'//способность ионной пушки
endfunction
function Ion_cannon_seunit takes nothing returns integer
    return 'h01B'//юнит-спецэффект
endfunction

//SpellValues================================================================
function Ion_cannon_range takes nothing returns real
    return 200.0//радиус действия
endfunction
function Ion_cannon_damage takes nothing returns real
    return 100.0//урон за цикл 
endfunction
function Ion_cannon_cilnum takes nothing returns integer
    return 5//количество циклов
endfunction

//Cond/Filter funcs==========================================================
function Trig_GEN_Ion_cannon_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == Ion_cannon_ability() )
endfunction

//actions==================================================================//уничтожение деревьев
function Trig_GEN_Ion_cannon_ddestr takes nothing returns nothing
    call KillDestructable( GetEnumDestructable() )
endfunction

//пушка
function Trig_GEN_Ion_cannon_Actions takes nothing returns nothing
    local unit u = GetSpellAbilityUnit()
    local unit u2
    local integer i
    local location p = GetSpellTargetLoc()

    call PolledWait(1)

    call CreateNUnitsAtLoc( 1, Ion_cannon_seunit(), GetOwningPlayer(u), p, bj_UNIT_FACING )
    set u2 = GetLastCreatedUnit()

//половинные повреждения
call UnitDamagePointLoc( u2, 0, Ion_cannon_range()/2, p, Ion_cannon_damage()/2, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE )


//полные повреждения
    set i = 1
    loop
        exitwhen i > Ion_cannon_cilnum()
        call PolledWait(0.1)
        call UnitDamagePointLoc( u2, 0, Ion_cannon_range(), p, Ion_cannon_damage(), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE )
        set i = i + 1
    endloop

    call PolledWait(0.5)
    call EnumDestructablesInCircleBJ( Ion_cannon_range(), p, function Trig_GEN_Ion_cannon_ddestr )
    call RemoveUnit(u2)
    call RemoveLocation(p)
set p = null
set u = null
set u2 = null
set i = 0
endfunction

//===========================================================================
function InitTrig_GNR_Ion_cannon takes nothing returns nothing
    set gg_trg_GNR_Ion_cannon = CreateTrigger(  )
    call DisableTrigger( gg_trg_GNR_Ion_cannon )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_GNR_Ion_cannon, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_GNR_Ion_cannon, Condition( function Trig_GEN_Ion_cannon_Conditions ) )
    call TriggerAddAction( gg_trg_GNR_Ion_cannon, function Trig_GEN_Ion_cannon_Actions )
endfunction
Это триггерное заклинание «Ионная пушка». В выбранной точке создается невыделяемый юнит- спецэффект в виде светового луча. Юниты в области луча получают повреждения (100 повреждений каждые 0.1 секунды – не более 5 раз). Луч также уничтожает деревья в области попадания.
Теперь обратите внимание на то, как это заклинание оформлено.
  1. В верхней части имеется шапка с комментариями: название заклинание, его действие и пр.
  1. Ниже шапки располагается раздел «SpellData», в котором есть список всех используемых в заклинании объектов:
function Ion_cannon_ability takes nothing returns integer
    return 'A04Y'//способность ионной пушки
endfunction
function Ion_cannon_seunit takes nothing returns integer
    return 'h01B'//юнит-спецэффект
endfunction
Т.е. для работы заклинания требуется 2 объекта:
а) юнит-спецэффект
б) способность-пустышка
Во всей остальной части триггера больше нету ссылок на константы 'A04Y' или 'h01B'. Вместо них применяются функции Ion_cannon_ability() или Ion_cannon_seunit(). Например, строку
    call CreateNUnitsAtLoc( 1, **'h01B'**, GetOwningPlayer(u), p, bj_UNIT_FACING ) 
мы заменяем на код:
    call CreateNUnitsAtLoc( 1, **Ion_cannon_seunit()**, GetOwningPlayer(u), p, bj_UNIT_FACING ) 
Этот прием поможет заметно ускорить импорт карты. Ведь при импорте вы уже будете знать все необходимые объекты. При импорте объектов сменятся идентификаторы. Но вместо того, чтобы выискивать их по всему триггеру, достаточно будет поменять их в одном месте в верхней части триггера.
  1. Еще ниже располагается блок «SpellValues». Здесь находится список констант, имеющих значение для настройки и изменения базовых параметров заклинания. Например, для заклинания ионной пушки я счел нужным вынести в константы:
  • радиус действия заклинания
  • количество повреждений, наносимых заклинанием за 1 цикл
  • количество циклов
Все эти параметры использованы внутри заклинания. Вместо того, чтобы писать:
        call UnitDamagePointLoc( u2, 0, **200.0**, p, **100.0**, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE ) 
мы пишем:
        call UnitDamagePointLoc( u2, 0, **Ion_cannon_range()**, p, **Ion_cannon_damage()**, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_FIRE ) 
Благодаря этому, любой человек сможет быстро поменять параметры заклинания.
Примечание: заклинание «Ионная пушка» – одноуровневое. Для многоуровневых заклинаний, можно усложнить функции. К примеру:
function Ion_cannon_damage takes integer level returns real
    return 50.0 +50*I2R(level)//урон за цикл 
endfunction
Т.е. в функцию мы будем передавать уровень заклинания. И от уровня будут зависеть повреждения за цикл:
1 ур – 50
2 ур – 100
3ур - 150 и т.д.
  1. Следующий блок называется «Cond/Filter funcs»
Сюда мы помещаем все функции-фильтры, в которых происходит проверка каких-то условий. В нашем случае имеется единственная подобная функция, в которой проверяется, какая абила была применена.
  1. Следующий блок называется «Actions»
Сюда мы помещаем все функции-действия. В нашем случае, имеется функция с основными действиями и еще одна функция с действием убить дерево.
  1. В самом низу находится функция инициализации триггера.
Замечание 1: обращаю внимание, что все функции, используемые в триггере начинаются с названия «Ion_cannon». Это имеет смысл. В игре может быть всего один триггер с именем «Ion_cannon». Поэтому делая такую приставку в начале каждой триггерной функции, мы можем гарантировать, что подобное название не будет повторено в других триггерах.
Замечание 2: в стандарте JESP бывает еще один блок «CacheValues» (сразу после шапки) где указывается названия Кеш-переменных, использованных в триггере (SCV или ее аналоги).
Вот такая структура триггера. Достаточно удобная – рекомендую пользоваться.
Итак, для того, чтобы оптимизировать готовое заклинание, нужно сделать следующее:
  1. Создать базовые блоки
    • шапка
  • «CacheValues»
  • «SpellData»
  • «SpellValues»
  • «Cond/Filter funcs»
  • «Actions»
  1. Заполнить шапку.
  2. Выделить все использованные объекты. Создать для них функции-константы. Заменить ссылки на эти объекты, ссылками на функции-константы.
  3. Выделить ключевые параметры заклинания, которые имеет смысл менять балансерам. Создать для этих параметров функции-константы. Заменить параметры на функции-константы.
  4. Разнести игровые функции по разделам.
Эта схема позволит упростить импорт и изучение заклинания. В том числе и вам самим, т.к. через некоторое время сам забываешь, как работало твое заклинание.

1
1
12 лет назад
1
UnitDamagePointLoc заменить на UnitDamagePoint()
CreateNUnitsAtLoc заменить на CreateUnit()
call PolledWait(0.1) о боже, вы забыли о таймерах и хэше?
1
2
11 лет назад
1
В Rise of Chivilizations тоже есть эта пушка и там я смотрел карта не защищена , там легкий триггер , тоже юнит пустышка и тоже урон и тоже деревья разрушаютьса.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.