Всем доброго времени суток! Не нашел подобного вопроса, поэтому спрошу, не могу понять концепцию работы со способностями с ядом. Я задумал заклинание, при использовании которого герой поджигает свой меч и наносит огненный урон врагам. При этом враги должны гореть в течение некоторого времени после атаки героя. Я пробовал яд дриады и яд от предмета Клинок убийцы, переделанные под горение. Когда герой кастует способность-пустышку, даю ему способность на основе яда, но при атаке на цель не вешается яд. Если дать герою предмет с ядом, то все будет работать, если просто дать саму способность - нет. Подскажите пожалуйста, в чем дело?

Принятый ответ

ладно, ты наверное не разобрался либо занят, в общем я решил сделать пример
вот основной код
globals
    constant hashtable H = InitHashtable( )
    constant group TempGroup = CreateGroup( )
endglobals

function addEff takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local unit u  = LoadUnitHandle( H, GetHandleId( t ), 0 )
    local EffectS A = LoadInteger( H, GetHandleId( u ), EffectStructKey )
    
    set A.eff  = AddSpecialEffectTarget( "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", u, "weapon" )
    set A.eff2 = AddSpecialEffectTarget( "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl", u, "weapon" )
    
    call FlushChildHashtable( H, GetHandleId( t ) )
    call DestroyTimer( t )
    
    set t = null
    set u = null
endfunction

function poisonDamage takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local integer i = GetHandleId( t )
    local unit attacker = LoadUnitHandle( H, i, 0 )
    local unit damaged  = LoadUnitHandle( H, i, 1 )
    local real r = LoadReal( H, i, 3 ) - 1.00
    
    call UnitDamageTarget( attacker, damaged, 20.00, false, false, null, null, null )
    
    if r <= 0.00 or not UnitAlive( damaged ) then
        call RemoveSavedHandle( H, GetHandleId( attacker ), GetHandleId( damaged ) )
        call DestroyEffect( LoadEffectHandle( H, i, 2 ) )
        call DestroyTimer( t )
        call FlushChildHashtable( H, i )
    else
        call SaveReal( H, i, 3, r )
    endif
    
    set t = null
    set attacker = null
    set damaged  = null
endfunction

function FlamingAttacks_Actions takes nothing returns nothing
    local unit attacker = GetEventDamageSource( )
    local unit damaged  = GetTriggerUnit( )
    local real damage   = GetEventDamage( )
    local unit u
    local timer t
    local EffectS A
    
    if GetUnitAbilityLevel( damaged, 'Bssd' ) > 0 then
        call UnitRemoveAbility( damaged, 'Bssd' )
        
        // потужні удари
        if GetUnitAbilityLevel( attacker, 'A002' ) > 0 then
            call GroupEnumUnitsInRange( TempGroup, GetUnitX( damaged ), GetUnitY( damaged ), 300.00, null )
            
            loop
                set u = FirstOfGroup( TempGroup )
                exitwhen u == null
                call GroupRemoveUnit( TempGroup, u )
                
                if IsUnitEnemy( u, GetOwningPlayer( attacker ) ) and UnitAlive( u ) then
                    call UnitDamageTarget( attacker, u, damage, false, false, null, null, null )
                endif
            endloop
            
            set t = CreateTimer( )
            
            set A = LoadInteger( H, GetHandleId( attacker ), EffectStructKey )
    
            call DestroyEffect( A.eff )
            call DestroyEffect( A.eff2 )
            call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", GetUnitX( damaged ), GetUnitY( damaged ) ) )
            call SaveUnitHandle( H, GetHandleId( t ), 0, attacker )
            call TimerStart( t, 1.00, false, function addEff )
            
            set t = null
        elseif GetUnitAbilityLevel( attacker, 'A003' ) > 0 then
            // вогняна атака
            call GroupEnumUnitsInRange( TempGroup, GetUnitX( damaged ), GetUnitY( damaged ), 150.00, null )
            
            loop
                set u = FirstOfGroup( TempGroup )
                exitwhen u == null
                call GroupRemoveUnit( TempGroup, u )
                
                if u != damaged and IsUnitEnemy( u, GetOwningPlayer( attacker ) ) and UnitAlive( u ) then
                    call UnitDamageTarget( attacker, u, damage / 2.00, false, false, null, null, null )
                endif
            endloop
            
            set t = LoadTimerHandle( H, GetHandleId( attacker ), GetHandleId( damaged ) )
            
            if t == null then
                set t = CreateTimer( )
                
                call SaveTimerHandle( H, GetHandleId( attacker ), GetHandleId( damaged ), t )
                
                call SaveUnitHandle( H, GetHandleId( t ), 0, attacker )
                call SaveUnitHandle( H, GetHandleId( t ), 1, damaged )
                call SaveEffectHandle( H, GetHandleId( t ), 2, AddSpecialEffectTarget( "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl", damaged, "origin" ) )
                
                call TimerStart( t, 1.00, true, function poisonDamage )
            endif
            
            call SaveReal( H, GetHandleId( t ), 3, 5.00 )
            call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl", damaged, "chest" ) )
            call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl", damaged, "chest" ) )
            
            set t = null
        endif
    endif
    
    set damaged  = null
    set attacker = null
endfunction

//===========================================================================
//function InitTrig_FlamingAttacks takes nothing returns nothing
    //set gg_trg_FlamingAttacks = CreateTrigger(  )
//endfunction
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
2 года назад
0
Похожие вопросы:

ответ
Если по игроку то массив переменных по игроку, если прям каждого конкретного героя каждого игрока - то через custom value или прочий регистратор юнитов.
Чета типа так, для ознакомления с CV
ответ
Параметры стака ядов с одним и тем же баффом, это нужно чтобы складывались замедлени и\или урон от разных юнитов, или бафф тупо обновлялся.
С одним из параметров яды с разными баффами скатаются независимо, каждый вешает свой бафф. (годная основа для замедляющих способностей)
А игра вылетает из за зацикливания, темболее бафф при удалении и появлении наносит 0.00 ед урона, это так для справки.
ответ
Гуванч, ну как бы написано одно, а по факту другое
ответ
Никакие, делать лишь кастом.

2
27
2 года назад
2
бред если честно, отобрази проблему на отдельной карте, максимум ты настройки кривые выставил либо юзаешь яд с каким-то орбом или что-то в этом духе
0
15
2 года назад
0
rsfghd, вот. Там несколько сложнее, чем описано, но не думаю, что это влияет. Способность яда я специально откатил до дефолтных значений, полагая, что испортил все переделыванием под горение, но нет. Оно не работало изначально.
Загруженные файлы
2
27
2 года назад
2
Meddin, всё у тебя работает, как я и сказал, орб не даёт наложить эффект яда, просто сделай либо триггерный яд, либо триггерный орб, второе предпочтительнее ибо с помощью яда можно отлавливать урон с руки
0
15
2 года назад
0
rsfghd, имеешь в виду как то отлавливать юнита, которого бьет герой и на него триггерно вешать яд по таймеру? Попробую поразбираться, как можно определить юнита, по которому наносит удары герой...
2
27
2 года назад
2
Meddin, регистрируешь событие получения урона на каждого юнита:
смотришь есть ли у атакованного дебафф яда, если есть - снимаешь его и делаешь триггерные операции (доп. урон, свой собственный яд и так далее, всё что связанно в автоатакой)
саму абилку яда выдать всем юнитам, чья атака должна отлавливаться
2
27
2 года назад
2
Meddin, если не сделаешь, то позже скину пример триггерного яда
2
15
2 года назад
2
rsfghd, благодарю, завтра вечером посижу поразбираюсь, возможно даже пригодится для моей задумки, за реализацию которой я пока боюсь браться, сделать виды стихийных атак и соответственно дамажить кого надо, потому как я переделал способность благословение элуны и у меня маги могут атаковать юнитов с иммунитетом к магии, но при этом наносят 0 урона(всегда бесило, что в варкрафте они просто запретили атаковать и все, в реальной жизни же никто не мешает нам в танк с пистолета стрелять или швыряться горохом в стену, даже не смотря на то, что смысла в этом 0).
2
27
2 года назад
2
Meddin, кстати, ты наверное не интересовался моими ресурсами, но я уже делал огненное оружие с поджиганием в спеллпаке привратника ада
2
27
2 года назад
2
ладно, ты наверное не разобрался либо занят, в общем я решил сделать пример
вот основной код
globals
    constant hashtable H = InitHashtable( )
    constant group TempGroup = CreateGroup( )
endglobals

function addEff takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local unit u  = LoadUnitHandle( H, GetHandleId( t ), 0 )
    local EffectS A = LoadInteger( H, GetHandleId( u ), EffectStructKey )
    
    set A.eff  = AddSpecialEffectTarget( "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", u, "weapon" )
    set A.eff2 = AddSpecialEffectTarget( "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl", u, "weapon" )
    
    call FlushChildHashtable( H, GetHandleId( t ) )
    call DestroyTimer( t )
    
    set t = null
    set u = null
endfunction

function poisonDamage takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local integer i = GetHandleId( t )
    local unit attacker = LoadUnitHandle( H, i, 0 )
    local unit damaged  = LoadUnitHandle( H, i, 1 )
    local real r = LoadReal( H, i, 3 ) - 1.00
    
    call UnitDamageTarget( attacker, damaged, 20.00, false, false, null, null, null )
    
    if r <= 0.00 or not UnitAlive( damaged ) then
        call RemoveSavedHandle( H, GetHandleId( attacker ), GetHandleId( damaged ) )
        call DestroyEffect( LoadEffectHandle( H, i, 2 ) )
        call DestroyTimer( t )
        call FlushChildHashtable( H, i )
    else
        call SaveReal( H, i, 3, r )
    endif
    
    set t = null
    set attacker = null
    set damaged  = null
endfunction

function FlamingAttacks_Actions takes nothing returns nothing
    local unit attacker = GetEventDamageSource( )
    local unit damaged  = GetTriggerUnit( )
    local real damage   = GetEventDamage( )
    local unit u
    local timer t
    local EffectS A
    
    if GetUnitAbilityLevel( damaged, 'Bssd' ) > 0 then
        call UnitRemoveAbility( damaged, 'Bssd' )
        
        // потужні удари
        if GetUnitAbilityLevel( attacker, 'A002' ) > 0 then
            call GroupEnumUnitsInRange( TempGroup, GetUnitX( damaged ), GetUnitY( damaged ), 300.00, null )
            
            loop
                set u = FirstOfGroup( TempGroup )
                exitwhen u == null
                call GroupRemoveUnit( TempGroup, u )
                
                if IsUnitEnemy( u, GetOwningPlayer( attacker ) ) and UnitAlive( u ) then
                    call UnitDamageTarget( attacker, u, damage, false, false, null, null, null )
                endif
            endloop
            
            set t = CreateTimer( )
            
            set A = LoadInteger( H, GetHandleId( attacker ), EffectStructKey )
    
            call DestroyEffect( A.eff )
            call DestroyEffect( A.eff2 )
            call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", GetUnitX( damaged ), GetUnitY( damaged ) ) )
            call SaveUnitHandle( H, GetHandleId( t ), 0, attacker )
            call TimerStart( t, 1.00, false, function addEff )
            
            set t = null
        elseif GetUnitAbilityLevel( attacker, 'A003' ) > 0 then
            // вогняна атака
            call GroupEnumUnitsInRange( TempGroup, GetUnitX( damaged ), GetUnitY( damaged ), 150.00, null )
            
            loop
                set u = FirstOfGroup( TempGroup )
                exitwhen u == null
                call GroupRemoveUnit( TempGroup, u )
                
                if u != damaged and IsUnitEnemy( u, GetOwningPlayer( attacker ) ) and UnitAlive( u ) then
                    call UnitDamageTarget( attacker, u, damage / 2.00, false, false, null, null, null )
                endif
            endloop
            
            set t = LoadTimerHandle( H, GetHandleId( attacker ), GetHandleId( damaged ) )
            
            if t == null then
                set t = CreateTimer( )
                
                call SaveTimerHandle( H, GetHandleId( attacker ), GetHandleId( damaged ), t )
                
                call SaveUnitHandle( H, GetHandleId( t ), 0, attacker )
                call SaveUnitHandle( H, GetHandleId( t ), 1, damaged )
                call SaveEffectHandle( H, GetHandleId( t ), 2, AddSpecialEffectTarget( "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl", damaged, "origin" ) )
                
                call TimerStart( t, 1.00, true, function poisonDamage )
            endif
            
            call SaveReal( H, GetHandleId( t ), 3, 5.00 )
            call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Spells\\Items\\AIfb\\AIfbSpecialArt.mdl", damaged, "chest" ) )
            call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl", damaged, "chest" ) )
            
            set t = null
        endif
    endif
    
    set damaged  = null
    set attacker = null
endfunction

//===========================================================================
//function InitTrig_FlamingAttacks takes nothing returns nothing
    //set gg_trg_FlamingAttacks = CreateTrigger(  )
//endfunction
Загруженные файлы
Принятый ответ
2
27
2 года назад
2

яд можно разделить на несколько категорий
вариковский - проверяющий наличие дебаффа на юните, не стакающийся яд который сбивается тем, кто атакует, обновляется при атаке
нубский - тупо таймер каждый раз периодический вешать, стакающийся яд
нормальный - сохраняется таймер в атакующего по ключу жертвы, таким образом яд от разных юнитов будет стакаться, но от одного и того же нет, только обновляться, то есть яды не перебивают друг друга и при этом работают как вариковские
я сделал на примере последнего
Загруженные файлы
2
15
2 года назад
2
rsfghd, сейчас только добрался снова до кода карты с твоими спеллами для демона. Я начал переписывать твой код на чистый jass, потому как пишу на нем, без всяких дополнительных наворотов. Сложновато конечно, особенно фокусы с получением хэндлов юнитов и сохранение их в хэш-таблицу, до этого во всех примерах я видел только работу с хэндлами таймеров и по ним и велось сохранение и это было просто и понятно. Сейчас гляну твой код, что ты скинул, огромное тебе спасибо, не факт конечно, что за этот час до сна, что решил сесть пораскуривать, разберусь, но если что, еще завтра попробую добить.

Кстати удары громовые, что ты сделал, выглядят впечатляюще. Тоже пригодятся. Благодарю.
2
27
2 года назад
Отредактирован rsfghd
2
Meddin, я думал над тем чтобы сразу писать на чистом джассе, зная тебя, но стало лень когда библиотеку на блок урона закинул (она кстати не пригодилась), если нужна будет помощь с переписыванием, то напишешь, потому что там 2 хэштаблицы понадобятся если сохранять именно такой тип ядов, потому что возможна перезапись значений
0
15
2 года назад
0
У меня есть несколько вопросов по твоему коду:
  1. Что за способность 'Bssd', на которую ты проверяешь вначале?
  2. Я не вижу, чтобы где то инициализировалось значение EffectStructKey. Чем я могу это заменить?
  3. Не понимаю назначения начинки триггера NegateDamage.
  4. Переменная r в poisonDamage - это, так сказать, период действия яда, верно? Типо урон от яда может быть нанес 5 раз после удара. Получается, в течении 5-ти секунд еще дамажит.
Пока пора укладываться спать, я более-менее осознал остальной код, пока не заглядывал в 2 нижних триггера, ну так, мельком только, там я так понял красота просто с анимациями и эффектами. Завтра буду пытаться адаптировать под себя и думать, как скрестить со своей способностью.

rsfghd, ну вот, а я думал у тебя объявлена хэш-таблица в глобалках в константах, это как на обычном джассе просто в глобалках создать хэш-таблицу и усе. Понял, значит все сложнее... Попытаюсь понять тогда где какая используется, если не дойду сам, спрошу.
2
27
2 года назад
Отредактирован rsfghd
2
Meddin,
  1. абилка яда, т.е. заклинание (дебафф)
  2. это целочисленная, ключ вджасса позволяет генерировать уникальное константное число, это по сути улучшенная версия StringHash
  3. библиотека позволяет блокировать урон, по сути как доспехи элуны против магии или как там правильно, только намного более гибкое ибо ты сам решаешь сколько блочить на каждый случай, мне не понадобилось, я по привычке закинул
  4. да, это время
да, в остальных триггерах я просто налепил всяких эффектов, они не важны
2
15
2 года назад
2
Есть у меня предположение, что триггер NegateDamage, отменяет урон с руки, для того, чтобы потом триггерно продамажить от удара... Это безумие какое то =D

rsfghd, благодарю за пояснения. Так, завтра продолжу, доброй тебе ночи, дружище!
0
15
2 года назад
Отредактирован Meddin
0
rsfghd, пока что переписываю без некоторых эффектов для простоты и без мощных ударов. Яд не добавяю в способности в РО, а триггерно добавляю своей той функцией, что скидывал в карте. В общем оно заработало даже, но работает определенно криво, хотя бы потому что, я вывожу при ударах цель и игра выводит не того юнита, которого бьет в данный момент герой, а соседнего. Карту приложил, увидишь. Завтра попробую разобраться, в чем я накосячил и добавить мощные удары. Но все равно, даже так, я уже в восторге от того, что задумка притворяется в жизнь и очень тебе благодарен!
Загруженные файлы
2
27
2 года назад
2
Meddin, так ты сам в условиях поставил чтобы не учитывался юнит, которого бьёт герой
			loop
                set nextUnit = FirstOfGroup(udg_TempGroup)
				
                exitwhen nextUnit == null
                call GroupRemoveUnit(udg_TempGroup, nextUnit)
                
                if (nextUnit != target and IsUnitEnemy(nextUnit, GetOwningPlayer(caster)) and (GetUnitState(nextUnit, UNIT_STATE_LIFE) > 0.405)) then
                    call DisplayTextToForce(GetPlayersAll(), "Target = " + GetUnitName(nextUnit))
                    call UnitDamageTarget(caster, nextUnit, damage + abilityLevel * 10, false, false, null, null, null)
                endif
            endloop
Загруженные файлы
0
15
2 года назад
Отредактирован Meddin
0
rsfghd, ну условие взял же у тебя в коде из твоей карты примера. Гляди:

Если инвертировать условие, то цель та, но тогда рядом стоящие юниты не получают урон. А у тебя на карте не могу проверить, потому что если что-то поменять и пытаться стартануть карту, то редактор сразу выбрасывать кучи ошибок, а жаль, хотелось бы проверить. Ну сейчас отрою xgm'cкий редактор, попробую им.

Блин, слушай, и верно, у тебя тоже тогда рядом стоящие не дамажатся, как от сферы огня, а было бы круто, ну это ничего, достаточно добавить будет после этой строки
if (abilityLevel > 0) then
    // Горение
    call GroupEnumUnitsInRange(udg_TempGroup, GetUnitX(target), GetUnitY(target), 150.00, null)
строчку:
call ForGroup(udg_TempGroup, function MakeDamage)
и функцию нанесения урона:
function MakeDamage takes nothing returns nothing
    call UnitDamageTarget(GetTriggerUnit(), GetEnumUnit(), GetRandomInt(6, 11), false, false, null, null, null)
endfunction
только кастера по моему или атакера по твоему, придется все же вынести в глобалку, потому что GetTriggerUnit() мне тут совсем не нравится.

Осталось на вечер самое трудное, добавить еще мощные удары и заставить это сообща работать, по всей видимости будет перебиваться яд. Раз ты сказал, что потребуются разные хэш-таблицы, то нужно будет осознать и сделать работу с двумя таблицами. Хотя хотелось бы конечно через одну, потому как читал в статьях тут, что создание хэш-таблицы дорогое и лучше создавать одну на всю игру в карте.
Загруженные файлы
2
27
2 года назад
2
Блин, слушай, и верно, у тебя тоже тогда рядом стоящие не дамажатся, как от сферы огня, а было бы круто, ну это ничего, достаточно добавить будет после этой строки
ложь, открыл карту всё работает нормально, даже убрал огонь для наглядности, это ты что-то накосячил
Хотя хотелось бы конечно через одну, потому как читал в статьях тут, что создание хэш-таблицы дорогое и лучше создавать одну на всю игру в карте.
добро пожаловать в 2022 год, мифы разоблачаются

одна хэштаблица тебе нужна для яда, который будет сейвиться по ключу кастера и таргета, но её так же можно и для таймеров собственно юзать и прочего, нужна эта хэштаблица потому что если ты ещё что-то сохраняешь в кастера (в моём случае это эффекты сильного удара), то есть шанс перезаписи, естественно ты можешь сохранить допустим в ячейку 1, 2, 3 и так далее эффекты, ибо GetHandleId возвращает какие-то миллионные числа и шанс перезаписи крайне мал, но он всё равно есть, а значит лучше просто отдельную хэштаблицу для этого дела оставить, правда если у одного героя будет несколько ядовитых абилок, то тут видимо нужно как-то додумывать систему, оффсеты делать
Загруженные файлы
2
15
2 года назад
Отредактирован Meddin
2
rsfghd, просветился по твоим ссылкам, благодарю! Очень интересно на самом деле, буду знать, что не стоит бояться хэш-таблиц. Я перепроверил твою карту еще раз, нет же, у меня не дамажит соседних, если поправить в условии != на ==. Ты же инвертировал условие тоже и попробовал?
Что касается героя - нет, несколько способностей основанных на яде я не планирую, однако будет несколько героев, каждый с одной способностью с ядом. Буду проверять и тестить. Я не стремлюсь слишком уж злоупотреблять этим, хочу придумать разнообразные способности.
2
27
2 года назад
2
Meddin, зачем мне инвертировать условие? Тогда по сути юнит, которого бьют, получит 2 раза урон. В карте всё работает, я ж скинул видео, соседние дамажутся

Скинь мою карту после того как проверил и заметил, что соседние не дамажутся. Если ты вообще ничего не изменял, то фиг его знает если честно
2
15
2 года назад
2
rsfghd, нет, ты не понял меня. Я инвертировал условие, это так, но после того, как ты заметил, что там должно быть сравнение на равенство наоборот. А условие это с остальным кодом я же как раз взял у тебя, переписывая на чистый jass. Вот и получается такая петрушка, если там будет !=, то таргет не тот, бьет герой рыцаря к примеру, а дамажит большим основным уроном стоящего рядом пехотинца, а если == то все как полагается, цель та, тобишь рыцарь, однако не получают урон рядом стоящие небольшой... Ну это ладно, мелочи жизни, уже все работает так или иначе. Спасибо тебе! Вопрос можно закрыть, если у меня возникнут какие то вопросы, касательно хэш-таблиц, я потревожу тебя в личных сообщениях, если ты не против конечно, дружище.
2
27
1 год назад
2
Meddin, так убери просто условие и всё. Там изначальное условие чтобы юнит которого бьешь не получал ещё больше урона, только те что рядом, инвертировав условие получает дополнительный урон только юнит которого бьёшь, если убрать условие то будут и соседние дамажиться и тот которого бьёшь

Да пиши конечно
2
15
1 год назад
2
rsfghd, добро!
Чтобы оставить комментарий, пожалуйста, войдите на сайт.