Совсем недавно пробую что то писать на vjass. Решил сделать способность Maledict из доты, столкнулся с проблемой запоминания и передачи информации о нанесённом уроне для каждого юнита (конкретно в этой абилке не пойму как выкрутиться) , скидываю код [Я его только начал , тут даже таймеры не выключены ещё и ничего не обнулено и т.п] что бы показать что конкретно не могу и не понимаю.
library Maledict requires DamageInterface, RegisterPlayerUnitEvent
    
    /* ------------------------------ CONFIGURABLES ----------------------------- */
    globals
    endglobals



    /* --------------------------------- System --------------------------------- */
 private struct Maledict
        static thistype array n
  
        timer   timer
        timer   timer2
        unit Lcaster
        group Lgroup
         group Lgroup2
        real dps   
     
        real maledmg
 
//*****************************************************





        static method onDamage takes nothing returns nothing
             local thistype this = GetUnitUserData(BlzGetEventDamageTarget())
             local unit Ldamaged = BlzGetEventDamageTarget()
                 
   
      

   if   UnitHasBuffBJ(Ldamaged, 'B015') == true and GetEventDamage() > 0   then
         
     set maledmg = maledmg + (( GetEventDamage() / 100.00 ) * 16 )
     
   else
   endif

        endmethod


    private static method onPeriod2 takes nothing returns nothing
         local thistype this = GetTimerData(GetExpiredTimer())
         local unit Picked = null
         local integer i = CountUnitsInGroup(Lgroup2)
         local group Lgroup3 = CreateGroup()
         call GroupAddGroup( Lgroup2, Lgroup3 )
         



                 loop
     set Picked = FirstOfGroup(Lgroup3) 
     exitwhen i == 0
     call UnitDamageTargetBJ( Lcaster, Picked, maledmg, ATTACK_TYPE_HERO, DAMAGE_TYPE_UNIVERSAL )
     call GroupRemoveUnit(Lgroup3,Picked)
     set i = i-1
                endloop
         
  
    endmethod
 
 


     private static method onPeriod takes nothing returns nothing
         local thistype this = GetTimerData(GetExpiredTimer())
         local unit Picked = null
         local integer i = CountUnitsInGroup(Lgroup2)
         local group Lgroup3 = CreateGroup()
         call GroupAddGroup( Lgroup2, Lgroup3 )
         



                 loop
     set Picked = FirstOfGroup(Lgroup3) 
     exitwhen i == 0
     call UnitDamageTargetBJ( Lcaster, Picked, dps, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC )
     call GroupRemoveUnit(Lgroup3,Picked)
     set i = i-1
                endloop
         
  
    endmethod


      static method onCast takes nothing returns nothing
               local thistype this = thistype.allocate()
               local unit  source =GetSpellAbilityUnit()
               local unit Picked = null
                set timer  = NewTimerEx(this)
                set timer2  = NewTimer()
                set Lcaster   = source
                set Lgroup = CreateGroup()
                set Lgroup2 = CreateGroup()
                call  SetTimerData(timer2,this)
                set maledmg = 0
                set dps = 100
             
 
     call GroupEnumUnitsInRange(Lgroup,GetLocationX(GetSpellTargetLoc()),GetLocationY(GetSpellTargetLoc()),225,null)
     call CreateNUnitsAtLoc( 1, 'h003', GetOwningPlayer(Lcaster), GetUnitLoc(Lcaster), bj_UNIT_FACING )
     set Ldummy =GetLastCreatedUnit()
     call UnitAddAbilityBJ( 'A03F', Ldummy )

           loop
     set Picked = FirstOfGroup(Lgroup) 
     exitwhen Picked == null
if Lcaster != Picked  and IsUnitType(Picked, UNIT_TYPE_STRUCTURE) == false and  IsUnitDeadBJ(Picked) == false and BlzIsUnitInvulnerable(Picked) == false and IsPlayerEnemy(GetOwningPlayer(Picked), GetOwningPlayer(Lcaster)) == true then
     
     call IssueTargetOrderBJ( Ldummy, "slow", Picked )
     call GroupAddUnitSimple(Picked,Lgroup2)
     call SetUnitUserData(Picked,this)
     call GroupRemoveUnit(Lgroup,Picked)   
else
     call GroupRemoveUnit(Lgroup,Picked)
endif
 
           endloop

        call TimerStart(timer, 0.99, true, function thistype.onPeriod)
        call TimerStart(timer2, 4, true, function thistype.onPeriod2)
        set source = null
  
 
    
 
       endmethod

    
        static method onInit takes nothing returns nothing
                 call RegisterSpellEffectEvent('A03E', function thistype.onCast)
                  call RegisterAttackDamageEvent(function thistype.onDamage)
            call RegisterSpellDamageEvent(function thistype.onDamage)
        endmethod
    endstruct
endlibrary
Получается в функции OnDamage я ДОЛЖЕН запоминать 16% от дамага для каждого отдельного юнита из группы на которую наложен дебаф. и в OnPeriod2 наносить эти 16% (если они есть) тоже каждому отдельно. А по факту в OnPeriod2 у меня наносится всем в группе кто с дебафом урон каждому, в размере 16% от полученного ВСЕМИ из группы. В общем в надежде жду любые подсказки или объяснение что я делаю не так, и что структура моего начального кода настолько неправильная что можно вызвать сатану.и как сделать лучше.

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

Там все гораздо проще, на каждого юнита аттачится экземпляр структуры где хранится цель, заклинатель, кол-во урона в сек, и сколько хп у тебя было, по нему высчитывается урон каждые 4 секунды. Тебе ни 10 таймеров ни группы не нужны.

function WC5 takes nothing returns boolean
    local trigger t = GetTriggeringTrigger( )
    local integer S5I = GetHandleId( t )
    local unit P7I = ( LoadUnitHandle( HashData, ( S5I ), ( 2 ) ) )
    local unit P8I = ( LoadUnitHandle( HashData, ( S5I ), ( 17 ) ) )
    local integer SUI = GetUnitAbilityLevel( P7I, 'A0NO' )
    local integer NPI = GetTriggerEvalCount( t )
    local real WD5 = ( LoadReal( HashData, ( S5I ), ( 392 ) ) )
    local real H84 = 0
    if GetTriggerEventId( ) == EVENT_WIDGET_DEATH then
        call DestroyEffect( ( LoadEffectHandle( HashData, ( S5I ), ( 32 ) ) ) )
        call FlushChildHashtable( HashData, ( S5I ) )
        call S0I( t )
    else
        if NPI == 4 or NPI == 8 or NPI == 12 then
            call DestroyEffect( ( LoadEffectHandle( HashData, ( S5I ), ( 32 ) ) ) )
            if NPI == 12 then
                call FlushChildHashtable( HashData, ( S5I ) )
                call S0I( t )
            elseif NPI == 4 or NPI == 8 then
                call SaveEffectHandle( HashData, ( S5I ), ( 32 ), ( AddSpecialEffectTarget( "effects\\NetherInferno.mdx", P8I, "origin" ) ) )
            endif
            set H84 = ( 0.08 + SUI * 0.08 ) * QDI( WD5 - GetUnitState( P8I, UNIT_STATE_LIFE ), 0 )
            if H84 > 0 then
                call UYI( "+" + I2S( R2I( H84 ) ), 2, P8I, 0.023, 68, 0, 187, 216 )
            endif
        endif
        call DamageTarget( P7I, P8I, 1, 5 * SUI + H84 )
    endif
    set t = null
    set P7I = null
    set P8I = null
    return false
endfunction

function WE5 takes nothing returns nothing
    local trigger t = CreateTrigger( )
    local integer S5I = GetHandleId( t )
    local unit P7I = GetTriggerUnit( )
    local unit P8I = GetEnumUnit( )
    call DestroyEffect( AddSpecialEffectTarget( "effects\\NetherInferno.mdx", P8I, "origin" ) )
    call TriggerRegisterTimerEvent( t, 1, true )
    call TriggerRegisterDeathEvent( t, P8I )
    call TriggerAddCondition( t, Condition( function WC5 ) )
    call SaveUnitHandle( HashData, ( S5I ), ( 17 ), ( P8I ) )
    call SaveUnitHandle( HashData, ( S5I ), ( 2 ), ( P7I ) )
    call SaveReal( HashData, ( S5I ), ( 392 ), ( ( GetUnitState( P8I, UNIT_STATE_LIFE ) ) * 1.0 ) )
    call SaveEffectHandle( HashData, ( S5I ), ( 32 ), ( AddSpecialEffectTarget( "effects\\NetherInferno.mdx", P8I, "origin" ) ) )
    set t = null
    set P7I = null
    set P8I = null
endfunction

function WF5 takes nothing returns nothing
    local unit P7I = GetTriggerUnit( )
    local location l = GetSpellTargetLoc( )
    local real x = GetLocationX( l )
    local real y = GetLocationY( l )
    local group g = NTI( )
    local integer SUI = GetUnitAbilityLevel( P7I, 'A0NO' )
    call GroupEnumUnitsInRange( g, x, y, 180 + 25, Condition( function D01 ) )
    call ForGroup( g, function WE5 )
    call NSI( g )
    call RemoveLocation( l )
    set l = null
    set g = null
endfunction

function WG5 takes nothing returns boolean
    if GetSpellAbilityId( ) == 'A0NO' then
        call WF5( )
    endif
    return false
endfunction

function NI1 takes nothing returns nothing
    local trigger t = CreateTrigger( )
    call UMI( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function WG5 ) )
    set t = null
endfunction
Как видишь все очень примитивно.Точно так же делаешь структуру с данными кто, где, когда. Нет смысла пытатся хранить сразу группу.
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
4 года назад
0
Похожие вопросы:

ответ
Вопросы - не стол заказов.
ответ
Sergey105, проблема в способе хранения а не в вджасс
цикл бегает от 1 до count включительно
первый объект будет в 1 ячейке
второй во 2
третий в третьей
count равен 3
раз время везде 6 секунд то первой освободиться первая ячейка
count станет равен 2
и цикл будет обрабатывать ячейки 1(пустая) и 2
но объект в 3 ячейке всё ещё остался так как время для него не закончилось
а так как мы его не удалили а просто потеряли то и эффект и экземпляр структуры остаются
и того утечка памяти
вот статья которую можно юзать как пример
и на будущее
для кода используй форматирование код
а большие куски кода вноси под кат
вот статья про форматирование
ответ
FogModifierStart(CreateFogModifierRect(GetLocalPlayer(), FOG_OF_WAR_VISIBLE, bj_mapInitialPlayableArea, true, false))
Создаем модификатор видимости локально.
ответ
FabulousTiger, большенству людей сложно влиться в чужой проект если тот абсолютно не отвечает некоторым критериям либо человеку может просто не нравится задумка. И это далеко не та ситуация когда нужно проглотить свое негодование, уровень роботы такого человека будет напрямую зависеть от того насколько ему нравится проект.
KaneThaumaturge, твоя скорость изучения JASS будет напрямую зависеть от того насколько ты в это захочешь втянуться. Правда должен предупредить что есть люди которые просто не приспособлены к тому что-бы понять програмирование в его ярчайшем проявлении, такие люди обычно при разработке проекта опираются на то что умею лучше всего.
Я из опыта скажу что: есть некоторые вещи которые возможно создать только при помощи JASS, но реализацию большенства идей можно выполнить при помощи GUI. Покопайся в чужих наработка пойми что ты хочешь и что можешь использовать из предоставленного тебе и вперед делать проект.

2
32
4 года назад
2
Там все гораздо проще, на каждого юнита аттачится экземпляр структуры где хранится цель, заклинатель, кол-во урона в сек, и сколько хп у тебя было, по нему высчитывается урон каждые 4 секунды. Тебе ни 10 таймеров ни группы не нужны.

function WC5 takes nothing returns boolean
    local trigger t = GetTriggeringTrigger( )
    local integer S5I = GetHandleId( t )
    local unit P7I = ( LoadUnitHandle( HashData, ( S5I ), ( 2 ) ) )
    local unit P8I = ( LoadUnitHandle( HashData, ( S5I ), ( 17 ) ) )
    local integer SUI = GetUnitAbilityLevel( P7I, 'A0NO' )
    local integer NPI = GetTriggerEvalCount( t )
    local real WD5 = ( LoadReal( HashData, ( S5I ), ( 392 ) ) )
    local real H84 = 0
    if GetTriggerEventId( ) == EVENT_WIDGET_DEATH then
        call DestroyEffect( ( LoadEffectHandle( HashData, ( S5I ), ( 32 ) ) ) )
        call FlushChildHashtable( HashData, ( S5I ) )
        call S0I( t )
    else
        if NPI == 4 or NPI == 8 or NPI == 12 then
            call DestroyEffect( ( LoadEffectHandle( HashData, ( S5I ), ( 32 ) ) ) )
            if NPI == 12 then
                call FlushChildHashtable( HashData, ( S5I ) )
                call S0I( t )
            elseif NPI == 4 or NPI == 8 then
                call SaveEffectHandle( HashData, ( S5I ), ( 32 ), ( AddSpecialEffectTarget( "effects\\NetherInferno.mdx", P8I, "origin" ) ) )
            endif
            set H84 = ( 0.08 + SUI * 0.08 ) * QDI( WD5 - GetUnitState( P8I, UNIT_STATE_LIFE ), 0 )
            if H84 > 0 then
                call UYI( "+" + I2S( R2I( H84 ) ), 2, P8I, 0.023, 68, 0, 187, 216 )
            endif
        endif
        call DamageTarget( P7I, P8I, 1, 5 * SUI + H84 )
    endif
    set t = null
    set P7I = null
    set P8I = null
    return false
endfunction

function WE5 takes nothing returns nothing
    local trigger t = CreateTrigger( )
    local integer S5I = GetHandleId( t )
    local unit P7I = GetTriggerUnit( )
    local unit P8I = GetEnumUnit( )
    call DestroyEffect( AddSpecialEffectTarget( "effects\\NetherInferno.mdx", P8I, "origin" ) )
    call TriggerRegisterTimerEvent( t, 1, true )
    call TriggerRegisterDeathEvent( t, P8I )
    call TriggerAddCondition( t, Condition( function WC5 ) )
    call SaveUnitHandle( HashData, ( S5I ), ( 17 ), ( P8I ) )
    call SaveUnitHandle( HashData, ( S5I ), ( 2 ), ( P7I ) )
    call SaveReal( HashData, ( S5I ), ( 392 ), ( ( GetUnitState( P8I, UNIT_STATE_LIFE ) ) * 1.0 ) )
    call SaveEffectHandle( HashData, ( S5I ), ( 32 ), ( AddSpecialEffectTarget( "effects\\NetherInferno.mdx", P8I, "origin" ) ) )
    set t = null
    set P7I = null
    set P8I = null
endfunction

function WF5 takes nothing returns nothing
    local unit P7I = GetTriggerUnit( )
    local location l = GetSpellTargetLoc( )
    local real x = GetLocationX( l )
    local real y = GetLocationY( l )
    local group g = NTI( )
    local integer SUI = GetUnitAbilityLevel( P7I, 'A0NO' )
    call GroupEnumUnitsInRange( g, x, y, 180 + 25, Condition( function D01 ) )
    call ForGroup( g, function WE5 )
    call NSI( g )
    call RemoveLocation( l )
    set l = null
    set g = null
endfunction

function WG5 takes nothing returns boolean
    if GetSpellAbilityId( ) == 'A0NO' then
        call WF5( )
    endif
    return false
endfunction

function NI1 takes nothing returns nothing
    local trigger t = CreateTrigger( )
    call UMI( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function WG5 ) )
    set t = null
endfunction
Как видишь все очень примитивно.Точно так же делаешь структуру с данными кто, где, когда. Нет смысла пытатся хранить сразу группу.
Принятый ответ
Чтобы оставить комментарий, пожалуйста, войдите на сайт.