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

Как сказали выше "Запускаешь таймер и на его хэндл сохраняешь юнита." Внутри таймера собственно урон и наносишь
А чтобы горение обновлялось, сохраняешь сам таймер на хендл горящего юнита и при попадании скилла удаляешь таймер (старый) и запускаешь новый, тем самым огонь обновится
`
ОЖИДАНИЕ РЕКЛАМЫ...
31
Запускаешь таймер и на его хэндл сохраняешь юнита.
8
Как сказали выше "Запускаешь таймер и на его хэндл сохраняешь юнита." Внутри таймера собственно урон и наносишь
А чтобы горение обновлялось, сохраняешь сам таймер на хендл горящего юнита и при попадании скилла удаляешь таймер (старый) и запускаешь новый, тем самым огонь обновится
Принятый ответ
8
Я не знаю как условить, что урон был нанесен именно заклинанием. У меня получилось поджигать юнита при любом нанесении урона. В событие добавил только паладина, чтобы работало на всех нужно сделать отдельный триггер "юнит вошел в область (вся карта) -> добавить событие триггеру (gg_trg_DetectFireDamage). В триггере сообщения для дебага есть, можешь удалить. Если есть вопросы, помощь в освоении жасса - контакты в профиле, пиши.
Вот код, карту также прикрепил ниже
function Trig_DetectFireDamage_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetEventDamageSource()) == 'Hblm' //наш огненный... как там его... А, точно - еврей
endfunction

function TimerFire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(udg_HASH, GetHandleId(t),StringHash("fireUnit"))
    local unit u2 = LoadUnitHandle(udg_HASH, GetHandleId(t),StringHash("fireSource"))
    local trigger trig = LoadTriggerHandle(udg_HASH, GetHandleId(t),StringHash("fireTrigger"))
    local integer count = LoadInteger(udg_HASH, GetHandleId(t),StringHash("fireСount"))
    local real damage = LoadReal(udg_HASH, GetHandleId(t),StringHash("fireDamage"))
    
    call DisplayTextToForce( GetPlayersAll(), "count" + I2S(count) )
    
    call DisableTrigger( gg_trg_DetectFireDamage ) //выключаем триггер, чтоб опять не сработал и горение не зациклилось
    //наносим урон. использую БЖ функцию, т.к. в нативке много непонятных страшных аргументов я не буду лезть в это дерьмо
    call UnitDamageTargetBJ( u2, u, damage, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_FIRE )
    call EnableTrigger( gg_trg_DetectFireDamage ) //вкл триггер
    
    //какой нибудь эффект бахнуть к юниту
    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl",u, "head" ))
    
    call SaveInteger(udg_HASH, GetHandleId(t),StringHash("fireСount"),count-1) //уменьшаем количество срабатываний
    if count <= 1 then
        call DisplayTextToForce( GetPlayersAll(), "destroy" )
        call FlushChildHashtable(udg_HASH, GetHandleId(t))//очищаем хеш
        call PauseTimer(t)
        call DestroyTimer(t) //удаляем наш таймер, мол все, гореть больше не будет
    endif
    set t = null
    set trig = null
    set u = null
    set u2 = null
endfunction

function Trig_DetectFireDamage_Actions takes nothing returns nothing
    local timer t = LoadTimerHandle(udg_HASH, GetHandleId(GetTriggerUnit()),StringHash("fireTimer")) //загружаем таймер который будет переодически бить поджегом
    call DisplayTextToForce( GetPlayersAll(), "1" )
    
    if t == null then //если такого таймера нет, то создадим его
        set t = CreateTimer()
        call SaveTimerHandle(udg_HASH, GetHandleId(GetTriggerUnit()),StringHash("fireTimer"),t)
    endif
    
    call SaveReal(udg_HASH, GetHandleId(t),StringHash("fireDamage"),20) //урон
    call SaveInteger(udg_HASH, GetHandleId(t),StringHash("fireСount"),3) //количество срабатываний
    call SaveUnitHandle(udg_HASH, GetHandleId(t),StringHash("fireUnit"),GetTriggerUnit()) //юнит которому наносим урон
    call SaveUnitHandle(udg_HASH, GetHandleId(t),StringHash("fireSource"),GetEventDamageSource()) //юнит от которого наносим урон
    call SaveTriggerHandle(udg_HASH, GetHandleId(t),StringHash("fireTrigger"),GetTriggeringTrigger())
    
    call TimerStart(t,1, true,function TimerFire) //переодический таймер в котором мы будем наносить урон
    
    set t = null
endfunction

//===========================================================================
function InitTrig_DetectFireDamage takes nothing returns nothing
    set gg_trg_DetectFireDamage = CreateTrigger(  )
    call TriggerRegisterUnitEvent( gg_trg_DetectFireDamage, gg_unit_Hpal_0001, EVENT_UNIT_DAMAGED )
    call TriggerAddCondition( gg_trg_DetectFireDamage, Condition( function Trig_DetectFireDamage_Conditions ) )
    call TriggerAddAction( gg_trg_DetectFireDamage, function Trig_DetectFireDamage_Actions )
endfunction
Загруженные файлы
Ответы (37)
8
IzobretatelBoom, я на своей карте через дамми-кастера проверяю, нанесён урон магией или нет, если урон от дамми-кастера, значит магией, если нет, значит тычка от юнита
Второй способ это через UjAPI, там вроде есть способы отловить то что нужно
P.S. Мега-хорош, лайк
31
Если есть вопросы, помощь в освоении жасса - контакты в профиле, пиши.
А ты всем помогаешь жасс освоить? А то у меня не выходит...
8
nazarpunk, я надеюсь что среди 100500 даунов я найду человека. Да и всмысле у тебя не выходит? Ты мне с этим очень помог, спасибо)
31
Да и всмысле у тебя не выходит?
Ну вот не выходит. Вот например банальнейшая задача - сделать систему аур дешевле чем O(n*n). Который год бьюсь, а ни одной реализации не увидел.
20
nazarpunk, TriggerRegisterUnitInRange + перебор группы и сравниваем расстояние. O(n^2) там как вообще получается?
Могу преподавать тебе жасс, 100 юсд за час
31
KaneThaumaturge, у тебя в кучке стоит 10 юнитов с аурами. Сколько раз ты пикнешь каждого юнита?
8
nazarpunk, Опиши задачу пожалуйста поподробней, ни разу не слышал о ней, что нужно сделать, чтобы например при 20 юнитах с аурами и например ещё 30 без ауры, стоящими рядом/или не совсем рядом (рандомно), каждый юнит просчитывался только 1 раз? А не каждый раз от каждой ауры, я правильно понял?
8
nazarpunk, Я вот щас подумал, вот стоит у меня 1000 юнитов с аурами в кучке, сначало, просчитается 999+1 юнит, а потом ещё 999*(999+1), то есть всего 1.000.000, а что если некому будет просчитываться
Можно создать 1000 точек (по точке под каждым юнитом), потом 1 раз взять группу GroupEnumUnitsInRange, в ней окажутся все эти 1000 юнитов, сохранить их и удалить, и тогда все остальные GroupEnumUnitsInRange вокруг оставшихся точек, не просчитают ни одного юнита, а потом всех этих сохранённых юнитов вернуть со всеми их приказами и прочей фигнёй
P.S. Я незнаю насколько сильно будет нагружать удаление и создание юнитов, вообще главная задача сделать так чтобы GroupEnumUnitsInRange не проверял юнита, а для этого нужно чтобы либо 1. Юнит перестал быть юнитом 2. Юнита не было
Ну вот короче мой вариант, скорее всего фегня, есть идея с созданием тектуры карты, но я не знаю как в варкрафте делать текстуры на ходу
31
А не каждый раз от каждой ауры, я правильно понял?
Правильно.
20
nazarpunk, пикать юнитов не буду, но перебирать буду. Переберу каждого юнита 10 раз. А это O(10n) а значит O(n). Да, нет?
20
nazarpunk, Ну это лучше и производительнее, чем перебирать всех юнитов на карте в большинстве случаев.
31
А это O(10n) а значит O(n). Да, нет?
const + n -> n ибо const по сути ничего не делает с n.
const * n, log n, n! и прочее говорит что нужно что-то делать с n и посему до n не сокращается.
20
nazarpunk, Понял, принял. Ну сложность квадратичная да, ты прав. Ну в целом можно перебирать общую группу под аурами и все. Тогда все ок будет. Мб руки дойдут и перепишу свою систему.
8
nazarpunk, а если аура будет не круглой, а приблизительно круглой это пойдёт? или нужен прям идеальный круг
31
Tredor46, через индексацию по квадратам какраз делают приближение к кругу.
8
nazarpunk, я имел ввиду не совсем приближенную, вот такую вот как на картинке
Её и какие-нибудь пересекающиеся/не пересекающиеся с ней ауры можно было бы разбить на неналегающие друг на друга регионы и потом каждого юнита с каждого региона пикнуть (получится 2 раза для владельцев аур и 1 раз для тех кто просто под аурой)
Но тут другая проблема правда возникает, как раз все эти регионы, я понятия не имею насколько максимально их можно оптимизировать и выгодно ли их делать вообще, это просто идея, пока что
Однако когда я доберусь до аур у себя в карте, я сделаю что-нибудь подобное и протесчу, может чо и выйдет годное
Загруженные файлы
31
я имел ввиду не совсем приближенную, вот такую вот как на картинке
Ну так ты и приблизил окружность квадратами. Ну и да, ты переизобрёл индексацию по квадратам. Идея такова, что в чётный тик таймера ты перебираешь всех чуваков с аурами и пишешь их в ячейку с квадратом. В нечётный перебираешь всех юнитов, читаешь данные с квадрата и делаешь всякое. Правда выгода от такого метода начнётся на реально большом количестве аур.
8
nazarpunk, Да я уже велосипеды знаю, уже делал, вот оцени ещё идею, я вот утром думал юнита удалять и создавать, а щас чёт подумал, а что если их всех просто тепнуть, ну типо, создать точки на их местах, 100 юнитов = 100 точек, собственно после каждой проверки вокруг точки тепать (проверенных) их нафиг в жопу мира, а потом назад, я сейчас проверял, тепал иллидана 50 раз в секунду, он как бегал, атаковал, юзал скиллы (протестил 1 скилл ток), у него ничего не прерывалось, мож и не прервётся ничё
Это тоже если набросок вот щас за 15 минут, поэтому он ну такое себе, вообще я думаю что если у меня ничё с аурами не получится, если даже у тебя не получается, у меня они просто будут в очередь становиться и будут срабатывать не одновременно, чтоб не лагало (ну а чо делать, хоть какая-то оптимизация)
SaveReal(FastHash, 0, 0, GetUnitX(gg_unit_OH07_0022))
SaveReal(FastHash, 0, 1, GetUnitY(gg_unit_OH07_0022))
SetUnitX(gg_unit_OH07_0022, 1000)
SetUnitY(gg_unit_OH07_0022, 1000)
SetUnitX(gg_unit_OH07_0022, LoadReal(FastHash, 0, 0))
SetUnitY(gg_unit_OH07_0022, LoadReal(FastHash, 0, 1))
8
nazarpunk, фиг знает короче, у меня даже сосание не прерывается, авось между этими телепортациями и можно проверки делать, надо будет мне потом получше всё проверить
Загруженные файлы
31
Tredor46, поставь в кучку 10 кастеров ауры и посчитай, сколько раз будет перебран каждый юнит. Можно конечно упростить задачу с индексированием. Сделать квадратную, ориентированную по осям ауру. И индексировать отдельно X и Y. Ну а в конечном переборе просто сверить квадрат расстояния чтоб округлить ауру.
8
nazarpunk, Имеет 10 кастеров ауры (в кучке)
  1. сначала переберутся 10 кастеров, под ними создадутся точки
  2. собственно кастеров, как обладателей ауры можно сразу отправить на край света
  3. останутся точки, вокруг них и будут все эти GroupEnumUnitsInRange() делаться
  4. у точек никого не осталось, сработают 10 GroupEnumUnitsInRange() и не найдут юнитов вокруг себя (они же на краю света)
  5. на всех тех кто на краю света собственно вешается то что должно вешаться там
  6. их тепает назад (в тот же момент когда они и отправились на край света)
  7. ответ 10
Возможно, я где-то ошибся, но пока что я не понял где
Загруженные файлы
31
Tredor46, кастеры не только обладают аурами, но и как-бы получают эффект от аур.
8
nazarpunk, ну так они же его и получат
  1. на всех тех кто на краю света собственно вешается то что должно вешаться там (эффект ауры вешается)
31
Tredor46, ты начал перебирать кастеров. Выбрал первого. Как ты узнаешь кому вешать эффект его ауры?
8
nazarpunk,
  1. собственно кастеров, как обладателей ауры можно сразу отправить на край света
  2. останутся точки, вокруг них и будут все эти GroupEnumUnitsInRange() делаться
3.Х. внезапный поворот, оказалось, что рядом с этими 10 кастерами ещё 20 микрочеликов
  • 3.1. вокруг первой точки (которая осталась на месте первого кастера), оказалось 18/20 из них, они так же идут на край света
  • 3.2. вокруг второй точки (которая осталась на месте второго кастера), оказались оставшиеся 2, они так же идут на край света
  • 3.3. вокруг 3-10 точек ни осталось никого, поэтому GroupEnumUnitsInRange() не пропикает там никого
Ну короче, как только юнита пикают в первый раз, его отправляют на край света (чтоб не пикался больше), вешают бафф и больше не пикают, пока все точки не переберут, а потом назад возвращают
31
Tredor46, вот ты пикнул второго Кастера. Первый на краю света. Откуда ты знаешь что ему нужно раздать ауру от второго?
31
Tredor46, ну и учти. Даже на краю света игра под капотом будет перебирать юнита.
8
nazarpunk, если у всех 10 юнитов разные ауры, то вот тут уже мои полномочия всё, я разные ауры планирую обрабатывать в разные промежутки времени, потому что пока что в моём предствлении даже если там всё чики-пуки оптимизированно будет, но всё это будет обрабатываться в 1 момент, всё равно лаганёт
8
nazarpunk, Как она его будет там перебирать, если он не в ренже то? Только если что-то в этот момент там случиться, но случиться там ничего не может (не потому что он далеко, а потому что времени не хватит чему-либо случиться, кроме того что написано)
31
Tredor46, под капотом игра проходит по всем юнитам и сравнивает условия чтоб добавить в группу.
8
nazarpunk, то есть пользоваться GroupEnumUnitsInRange() вообще нельзя?
20
Tredor46, Если ты имеешь ввиду, что ты хочешь избежать перебора юнитов и делать все на событиях входа/выхода из региона, то там свои подводные камни есть. Например аура, которая снижает защиту не должна действовать на юнитов которые стали имунным к магии. В таком случае тебе нужно делать свое событие на становление имунным и детектить такие случаи. В общем, работы больше, а выхлоп сомнительный как по мне.
20
Tredor46, А если в твоем случае все равно пик юнитов идет, то я вообще не понял смысла с квадратами
31
а выхлоп сомнительный как по мне
Выхлоп появляется в случае прям большого количества аур. В дефолтных мили и O(n^n) прокатит в виду собственно малого значения n.
20
nazarpunk, Ну я бы переписал свои ауры именно так и взаимодействовал через ивенты, но Старк не любит микросервисы, он любит монолит
31
но Старк не любит микросервисы
Ну и кто ему лекарь?
Этот комментарий удален
Чтобы оставить комментарий, пожалуйста, войдите на сайт.