раньше делал массив функций через массив триггеров с экзекутом
Это автоматически делает function interface в vJass.
Boolexp тоже неплохой вариант. Они могут даже ничего не возвращать (по идее, должны возвращать boolean, но можно возвращать что угодно, всё равно все типы в Jass занимают 4 байта и возвращают то, что записано напротив return. nothing возвращает 0).
force BForce = CreateForce()
Можно использовать bj переменную, ты же всё равно ничего не добавляешь в клан.
А простая проверка на имеющийся бафф требовала нахождения таймера который уже мог быть запущен, то бишь нужно было хранить его хендл, а там еще всякие коллизии начинали возникать.
У меня это проверяется просто, я сохраняю к хеш-таблицу созданный бафф (объект структуры, он же integer) под handleid юнита и id баффа (у каждого баффа есть свой id). Когда я запускаю бафф, достаю из хеша это значение, если оно 0 (то есть бафф ещё не был создан), создаю бафф и сохраняю его в хеш.
Вот пара примеров из моей старой версии карты, где вообще нет никакой системы, но используется тот же подход по запрету нового наложения баффа. Тут все таймеры создаются заранее и не удаляются по истечению баффа. А ещё тут пробелы не расставлены.
раскрыть
Непериодический бафф.
function FrostArmorEnd takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer tH=GetHandleId(t)
local unit m=LoadUnitHandle(Hash,tH,0)
local integer mH=GetHandleId(m)
local effect e=LoadEffectHandle(Hash,tH,1)
call RemoveSavedBoolean(Hash,mH,'A01F')
call RemoveSavedHandle(Hash,tH,1)
call DestroyEffect(e)
set t=null
set m=null
set e=null
endfunction
function FrostArmor takes nothing returns nothing
local unit m=GetSpellTargetUnit()
local integer mH=GetHandleId(m)
local timer t=LoadTimerHandle(Hash,mH,'A01F')
local integer tH=GetHandleId(t)
local effect e
if not HaveSavedHandle(Hash,tH,1)then
call SaveBoolean(Hash,mH,'A01F',true)
set e=AddSpecialEffectTarget("Abilities\\Spells\\Undead\\FrostArmor\\FrostArmorTarget.mdx",m,"chest")
call SaveEffectHandle(Hash,tH,1,e)
set e=null
endif
call TimerStart(t,2,false,function FrostArmorEnd)
set m=null
set t=null
endfunction
function Trig_FrostArmor_Conditions takes nothing returns boolean
return GetSpellAbilityId()=='A01F'
endfunction
function InitTrig_FrostArmor takes nothing returns nothing
set gg_trg_FrostArmor=CreateTrigger()
call TriggerRegisterPlayerUnitEvent(gg_trg_FrostArmor,Player(11),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
call TriggerAddCondition(gg_trg_FrostArmor,function Trig_FrostArmor_Conditions)
call TriggerAddAction(gg_trg_FrostArmor,function FrostArmor)
endfunction
Периодический бафф.
function RejuvenationEnd takes nothing returns nothing
local timer t=GetExpiredTimer()
local integer tH=GetHandleId(t)
local unit m=LoadUnitHandle(Hash,tH,0)
local integer mH=GetHandleId(m)
local effect e=LoadEffectHandle(Hash,tH,1)
local integer times=LoadInteger(Hash,mH,'A030')
call AddHPPerc(m,25)
call SaveInteger(Hash,mH,'A030',times+1)
if(times==2)then
call RemoveSavedInteger(Hash,mH,'A030')
call RemoveSavedHandle(Hash,tH,1)
call DestroyEffect(e)
call PauseTimer(t)
endif
set t=null
set m=null
set e=null
endfunction
function Rejuvenation takes nothing returns nothing
local unit m=GetSpellTargetUnit()
local integer mH=GetHandleId(m)
local integer times=LoadInteger(Hash,mH,'A030')
local timer t=LoadTimerHandle(Hash,mH,'A030')
local integer tH=GetHandleId(t)
local effect e
if(times==0)then
set e=AddSpecialEffectTarget("Abilities\\Spells\\NightElf\\Rejuvenation\\RejuvenationTarget.mdx",m,"chest")
call SaveEffectHandle(Hash,tH,1,e)
set e=null
call TimerStart(t,1,true,function RejuvenationEnd)
endif
call AddHPPerc(m,20)
call SaveInteger(Hash,mH,'A030',1)
set m=null
set t=null
endfunction
function Trig_Rejuvenation_Conditions takes nothing returns boolean
return GetSpellAbilityId()=='A030'
endfunction
function InitTrig_Rejuvenation takes nothing returns nothing
set gg_trg_Rejuvenation=CreateTrigger()
call TriggerRegisterPlayerUnitEvent(gg_trg_Rejuvenation,Player(11),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
call TriggerAddCondition(gg_trg_Rejuvenation,function Trig_Rejuvenation_Conditions)
call TriggerAddAction(gg_trg_Rejuvenation,function Rejuvenation)
endfunction
Не проще было бы задавать бафф просто длительностью и интервалом между периодическим эффектом? В 6 секунд длительностью и 1.5 секундным интервалом срабатывает 4 раза. Вроде на порядок проще получается.
Я задаю длительностью, максимальным количеством тиков и начальным количеством тиков. Период вычисляется делением длительности на начальное количество тиков. Такие параметры необходимы для того, что система позволяла создавать баффы, которые изначально имеют 1 тик, но при повторном наложении могут увеличивать кол-во тиков вплоть до указанного максимума.
Что же касается вопроса простоты и удобства - дело личное. Мне было удобнее сделать так.
Я не показал БД, где прописываются свойства баффов, потому что не посчитал это нужным. Вопрос ведь про готовые системы баффов. Я ответил, что наличие такой системы зависит от требований к ней. Также я хотел привести рабочий пример псевдомассива code, о чём также спрашивалось.
Зависит от того, что тебе нужно от этой системы.
В карте, что я сейчас делаю, отличная система кастомных баффов (баффы WarCraft 3 я не использую вообще). Её я собираюсь выложить и рассказать, когда создам проект на XGM.
Система долго эволюционировала, потому человеку, который её никогда не видел, возможно будет сложно её понять.
Вкратце.
Есть структура MinionBuff, в ней есть следующие функции.
раскрыть
stub method tickAction takes nothing returns boolean
return true
endmethod
static method tickEnd takes nothing returns nothing
local thistype this = GetCustomTimer()
set currticks = currticks - 1
if tickAction() then
call destroy()
endif
endmethod
method extendTicks takes integer addticks returns nothing
set currticks = currticks + addticks
if currticks > buffdata.maxticks then
set currticks = buffdata.maxticks
endif
endmethod
method startWithPeriod takes real period returns nothing
set currticks = buffdata.startticks
call UnitAddAbility(target.minion, buffdata.effectid)
call TimerStart(t, period, buffdata.periodic, function thistype.tickEnd)
call DebugMsgIf(isStopped(), "MinionBuff " + I2S(this) + " is started.")
set isRunning = true
endmethod
method start takes nothing returns nothing
call startWithPeriod(buffdata.period)
endmethod
method startPeriodic takes integer addticks returns nothing
if isRunning then
call extendTicks(addticks)
else
call start()
endif
endmethod
endstruct
Объект этой структуры не создаётся, создаются объекты конкретных баффов (которые тоже структуры). Есть два типа баффов - периодический (максимальное количество тиков больше 1) и непериодический. Я знаю, какой бафф периодический, а какой нет, потому периодические баффы стартуются функцией startPeriodic, а непериодические - start. Их таймер запускается в функцию tickEnd, где вызывается tickAction. Если у баффа эта функция перезаписана, то выполнится его версия функции. Если нет, то вернётся правда, и бафф будет удалён.
Примеры баффов.
Да нормально, вместо катапульты можно сделать даммик, который сам не атакует, а в момент смерти перемещается в позицию героя и делает 1 атаку. А можно создавать даммик с второй способностью мины в момент смерти и сразу же его убивать.
Вот условие на проверку баффа. Но тут может быть проблема, если у тебя есть станящие способности, которые используют не этот бафф.
Но мой способ, предложенный выше, также должен работать, причём независимо от того, какой станящий бафф наложен.
Flush чистит все ячейки с указанным parent ключом. RemoveSaved чистит только 1 ячейку, так как указываются child и parent ключи.
Пример использования Flush: (handleid юнита) используется как parent ключ для сохранения таймеров, статов и прочего. Когда юнит удаляется, нужно и хеш почистить. Чтобы не запускать для каждого child ключа RemoveSaved, выполняется Flush, куда передаётся только parent ключ - (handleid юнита).
Пример использования RemoveSaved: структура использует таймер. Как только структура создаётся, в хеш сохраняется структура с parent ключом X и child ключом (handleid таймера). Когда структура удаляется, удаляется и таймер, а перед этим чистится ячейка с parent ключом X и child ключом (handleid таймера) с помощью RemoveSaved. Flush тут не подойдёт, потому что очистить нужно всего 1 ячейки и parent ключ общий для каждого объекта структуры.
посмотрел сделал 2 книги заклинаний в одной,так способности в эту одну некоторые и переместились,а вторая полностью переключает и работает,а первая не реагирует на нажимания!
Я же сказал, что нужно сменить ID приказа у одной книги. Читайте, что пишут. PT153:
Ред. PT153
» WarCraft 3 / Триггерный бафф
Boolexp тоже неплохой вариант. Они могут даже ничего не возвращать (по идее, должны возвращать boolean, но можно возвращать что угодно, всё равно все типы в Jass занимают 4 байта и возвращают то, что записано напротив return. nothing возвращает 0). Можно использовать bj переменную, ты же всё равно ничего не добавляешь в клан.
» WarCraft 3 / Скрыть способность?
» WarCraft 3 / Скрыть способность?
Ред. PT153
» WarCraft 3 / Триггерный бафф
А ещё тут пробелы не расставлены.
» WarCraft 3 / Некрополь слишком близок к шахте
Я думаю, что если добавить в некрополь сдачу золота, то и его нельзя будет строить.
» WarCraft 3 / Перевод карты без предоставления исходников
Ред. PT153
» WarCraft 3 / Триггерный бафф
Что же касается вопроса простоты и удобства - дело личное. Мне было удобнее сделать так.
Я не показал БД, где прописываются свойства баффов, потому что не посчитал это нужным. Вопрос ведь про готовые системы баффов. Я ответил, что наличие такой системы зависит от требований к ней. Также я хотел привести рабочий пример псевдомассива code, о чём также спрашивалось.
» WarCraft 3 / Триггерный бафф
В карте, что я сейчас делаю, отличная система кастомных баффов (баффы WarCraft 3 я не использую вообще). Её я собираюсь выложить и рассказать, когда создам проект на XGM.
Система долго эволюционировала, потому человеку, который её никогда не видел, возможно будет сложно её понять.
Есть структура MinionBuff, в ней есть следующие функции.
Примеры баффов.
» WarCraft 3 / Прерывание триггерной способности оглушением.
» WarCraft 3 / Урон в области героя
Ред. PT153
» WarCraft 3 / Прерывание триггерной способности оглушением.
Но мой способ, предложенный выше, также должен работать, причём независимо от того, какой станящий бафф наложен.
» WarCraft 3 / Как сделать способность, которая работает, когда героя атакуют?
Ред. PT153
» WarCraft 3 / Прерывание триггерной способности оглушением.
» WarCraft 3 / что из этого вызывает десинк?
» WarCraft 3 / Помощь в избавлении от BJ
» WarCraft 3 / Хеш-таблица или куча массивных переменных
Пример использования RemoveSaved: структура использует таймер. Как только структура создаётся, в хеш сохраняется структура с parent ключом X и child ключом (handleid таймера). Когда структура удаляется, удаляется и таймер, а перед этим чистится ячейка с parent ключом X и child ключом (handleid таймера) с помощью RemoveSaved. Flush тут не подойдёт, потому что очистить нужно всего 1 ячейки и parent ключ общий для каждого объекта структуры.
» WarCraft 3 / Более трёх героев
С каких пор понимать английский является способом получения удовольствия посредством унижения или мучения? xD
Ред. PT153
» WarCraft 3 / Книга заклинаний (X2)
Absolute:
» WarCraft 3 / Книга заклинаний (X2)
Вот карта, где всё отлично работает.
» WarCraft 3 / Книга заклинаний (X2)
Ред. PT153
» WarCraft 3 / Музыка и пауза
» WarCraft 3 / Книга заклинаний (X2)
PT153:
» WarCraft 3 / Музыка и пауза
» WarCraft 3 / Книга заклинаний (X2)
» WarCraft 3 / Хеш-таблица или куча массивных переменных
Используй то, что тебе удобнее, я вот структуры использую.