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

ладно, ты наверное не разобрался либо занят, в общем я решил сделать пример
вот основной код
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
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...

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

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

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

rsfghd, благодарю за пояснения. Так, завтра продолжу, доброй тебе ночи, дружище!
15
rsfghd, пока что переписываю без некоторых эффектов для простоты и без мощных ударов. Яд не добавяю в способности в РО, а триггерно добавляю своей той функцией, что скидывал в карте. В общем оно заработало даже, но работает определенно криво, хотя бы потому что, я вывожу при ударах цель и игра выводит не того юнита, которого бьет в данный момент герой, а соседнего. Карту приложил, увидишь. Завтра попробую разобраться, в чем я накосячил и добавить мощные удары. Но все равно, даже так, я уже в восторге от того, что задумка притворяется в жизнь и очень тебе благодарен!
Загруженные файлы
28
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
Загруженные файлы
15
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() мне тут совсем не нравится.

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

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

Скинь мою карту после того как проверил и заметил, что соседние не дамажутся. Если ты вообще ничего не изменял, то фиг его знает если честно
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.