0
20
7 лет назад
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

Diaboliko, в варкрафте все массивы 8192, то что ты указал 64 ничего не значит, варкрафт все равно выделит 8192
А в моей памяти сидит что они сперва имеют какой-то минимальный сайз, выше которого по степени двойки делается realloc.
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

зачем ты ставишь 64 если оно всеравно преобразуется в 8192?
Поиск по 64 меня устраивает. И 64 так и останется 64 в моем случае. Я выделяю это пространство для юнита в этих массивах:
кат
scope UnitGroupEmulation
    globals
        constant integer       UGEAllocatedAmountOfCells = 64//per unit
        constant integer       UGEOverflow = 63
        constant integer       UGEStartingSize = 512
        constant integer       UGEInitExit = 511
        constant integer       UGESizeOfSubArray = 8// 512/64 and round it up to 2^X
        constant integer       UGESizeOfSubArrayExit = 8
                 //integer array UGEAllocatedCells
                 integer array UGEIntegers[UGEStartingSize]
                 unit    array UGEUnits[UGEStartingSize]
                 integer       UGENext = 0//*UGEAllocatedAmountOfCells to get the variable with minimal ID of allocated part of array
                 integer array UGENextUnitOfThisSpace[UGESizeOfSubArray]
    endglobals
    
    function FillUGEArray takes nothing returns nothing
        local integer i = 0
            loop
                set  UGEIntegers[i] = 0
                set  UGEUnits[i] = null
                exitwhen i == UGEInitExit
                set  i = i + 1
            endloop
    endfunction
    
    #define UGEGetSpace( nothing ) = {
             UGENext
        set  UGENextUnitOfThisSpace[UGENext] = UGENext * UGEAllocatedAmountOfCells
        set  UGENext = UGENext + 1
    }
    
    #define UGESimplyAddUnitToSpace( whichUnit, whichSpace ) = {//Base local code upon this. Would be wrong to use it raw.
        set  UGEUnits[UGENextUnitOfThisSpace[whichSpace]] = whichUnit
        if ( UGENextUnitOfThisSpace[whichSpace] == ( whichSpace * UGEAllocatedAmountOfCells ) + UGEOverflow ) then
            set  UGENextUnitOfThisSpace[whichSpace] = whichSpace * UGEAllocatedAmountOfCells
        endif
    }
endscope
и перерабатываю его. Благо я могу делать это без проблем т.к. не пишу на вжассе (scope используется для доп. табуляции)
зачем информация о числе задеваний таргета Т1 кастами кастера C1?
У меня конец времени дебаффа отсчитывается одним из "потоков" таймера, работая аналогично твоему отсчету времени до конца дебаффа. Информация о числе задеваний нужна чтобы из группы всех юнитов, задетых кастом кастера не удалять юнита, если тот содержится еще в какой-то группе(иначе лжедебафф, по-сути, еще активен, но будет снят).
твоё решение содержит часть моего + кучу ненужного говна
На твой взгляд оно, может, и ненужное говно, а в рамках используемых мной систем выглядит весьма адекватным решением.
по поводу твоих "потоков"
кривое дерьмо юзающее кучу триггеров и не имеющее никакого смысла
если будет не лень то завтра напишу этот спелл
Ну почему-же. Решение не кривее использования хэштэйблов. Все переменные сохраняются в глобальных массивах. Мне норм.
0
20
7 лет назад
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

полный бред которого у меня нету и который хз зачем нужен
да и размер массива всегда фиксирован и равен 8192(2 в 13 степени)
Кто-то из нас явно понимает другого не-правильно. Либо оба :> Но я вижу в твоем описании свое решение.
nvc123:
Diaboliko:
Таймер реализован как отдельный поток работы одного глобального, так что использую ресурсы, находящиеся в простОе.
это не понял вообще
сколько таймеров(игровых объектов), с каким периодом работают таймеры и каким образом ты реализуешь свои таймеры?
Ну если тебе хочется взглянуть на индусский порнокод...
1 таймер для работ с нулевым временем(захил после нанесения урона и т.п.)
scope ZeroTimeEvent

    globals
        constant integer ZTEArraySize = 64//Even 32 is alot, 64 is too much! Exactly what I need!
        timer Zero//Used for 0. sec uses
        integer ZTECurrent = 0
        unit array ZTEUnits[ZTEArraySize]
        integer array ZTEIntegers[ZTEArraySize]
        real array ZTEReals[ZTEArraySize]
        trigger array ZTETriggers[ZTEArraySize]
    endglobals
    
    function ZeroTimeEvent takes nothing returns nothing
            loop
                set  ZTECurrent = ZTECurrent - 1
                call TriggerExecute( ZTETriggers[ZTECurrent] )
                exitwhen ZTECurrent == 0
            endloop
    endfunction
    
    #define ZTEAddUnit(u) = {
        set  ZTEUnits[ZTECurrent] = u
    }
    
    #define ZTEAddInteger(i) = {
        set  ZTEIntegers[ZTECurrent] = i
    }
    
    #define ZTEAddReal(r) = {
        set  ZTEReals[ZTECurrent] = r
    }
    
    #define ConfirmZTE(trig) = {
        set  ZTETriggers[ZTECurrent] = trig
        set  ZTECurrent = ZTECurrent + 1
        call TimerStart( Zero, ZeroTime, false, function ZeroTimeEvent )
    }
    
    
    
endscope
Плюс немного отличающаяся версия(но руки не доходят один момент пофиксить), с выделением "потока" таймера пот статический, этого
ужаса
scope GlobalTimerEvent

    globals
        constant integer       GTE002ArrayMaxSize = 64
        constant integer       GTE002ArrayOverflow = 63//While < then this - do stuff else - start from zero
        constant integer       GTE002ArrayOverflowExit = 62//If something > this, then start from zero
        constant integer       GTE010ArrayMaxSize = 125
        constant integer       GTE010ArrayOverflow = 124
        constant integer       GTE010ArrayOverflowInitExit = 123//Whatever you wanna call it like. Its for proper init :P
        constant integer       GTE010ArrayOverflowExit = 119//5 ticks per second with increment of 5 are limited at 125 variables([124])
                                                            //  (starting from zero). So 124 - 5 = exit so it gets up to 124, but no more.
        constant integer       GTEDataArrayMaxSize = 2048
        constant integer       GTEDataArrayOverflow = 2047
        constant integer       GTEDataArrayOverflowExit = 2046
        constant integer       GTEDataArrayCheckOverflow = 2000//Проверка на переполнение запускается после добавления всех нужных объектов
                                                               //   могут теряться до 46 переменных, но памяти на них хватит :)
        constant real          GlobalTimerTickRate = 0.02
        constant real          GlobalTimerTicksPerSecond = 50.
                 timer         GlobalTimer
                 integer       GTE002NextEvent = 0//Ячейка, в которую будет произведена запись
                 integer       GTE010NextEvent = 0//Ячейка, в которую будет произведена запись
        //constant integer       GTE010MaxLoopStartingValue = 4
                 integer       GTE010CurrentLoopStartingValue = 0//Why not to make it go from 4 to zero, avoiding the need of var. above?
                 integer       TimedLoopOf3 = 0//Switches between 0,1,2 every GlobalTimer tick
                 integer       LoopOf3 = 0//Increased whenever registering a knockback event. Switches between 1,2,3. If I'll make it to switch between 1 and 2 only, there will  be no need really for local variable(its barely profitable now already)
                 integer       GTENextVariable = 0
                 integer       GTELoopCounter = 0
                 integer array GTE002Loops             [GTE002ArrayMaxSize]
                 integer array GTE002CurrentTime       [GTE002ArrayMaxSize]
                 integer array GTE002Timeout           [GTE002ArrayMaxSize]
                 trigger array GTE002TriggerToExecute  [GTE002ArrayMaxSize]
                 integer array GTE002FirstVariable     [GTE002ArrayMaxSize]
                 integer array GTE010Loops             [GTE010ArrayMaxSize]
                 integer array GTE010CurrentTime       [GTE010ArrayMaxSize]
                 integer array GTE010Timeout           [GTE010ArrayMaxSize]
                 trigger array GTE010TriggerToExecute  [GTE010ArrayMaxSize]
                 integer array GTE010FirstVariable     [GTE010ArrayMaxSize]
                 integer array GTEIntegers             [GTEDataArrayMaxSize]
                 real    array GTEReals                [GTEDataArrayMaxSize]
        //Как это устроено:
        //Массив  64 переменных - для экзекута с периодом 0.02
        //Массив 128 переменных - для экзекута с периодом 0.10 (делятся на 5 периодов для снижения нагрузки).
        //Два массива по 1024 переменных - для сохраняемых данных.
        //Массив в 1024 переменные, ссылающийся на первую ячейку в дате. По дефолту использовал столько же массивов дабы ссылались
        //  каждый на свой массив, но 1024 значения и так дохрена, плюс я могу использовать одновременно 2 переменные на халяву
        //  короче это, имхо, самый оптимальный вариант по расходу памяти, хотя и усложняет кодинг, да.
        //Поскольку два массива - массивы Real и Integer, может возникнуть вопрос как же сейвить юнитов?
        //  Я использую базу данных, так что Integer может ссылаться на базу.
    endglobals
    
    //Эти дефайны использованы, в общем то, только потому что система переделывается 2 раз.
    //Первый раз был хэштейбл.
    //Второй раз были 3 массива с 3 поинтерами.
    //И вот сейчас я решил сделать все ну совсем кошерно. Хотя названия все-равно оставляют желать мне пойти в задницу.
    
    #define GTE002InitVariableAdding() = {
                                             set GTE002FirstVariable[GTE002NextEvent] = GTENextVariable
                                         }
    #define GTE010InitVariableAdding() = {
                                             set GTE010FirstVariable[GTE010NextEvent] = GTENextVariable
                                         }
    #define GTEIncreaseVariablePointer() = {
                                             set  GTENextVariable = GTENextVariable + 1
                                         }
    #define GTEIncreaseVariablePointer(n) = {
                                             set  GTENextVariable = GTENextVariable + n
                                         }
    #define GTEAddInteger(variable1) = {
                                           set  GTEIntegers[GTENextVariable] = variable1
                                       }
    #define GTEAddReal(variable1) = {
                                        set  GTEReals[GTENextVariable] = variable1
                                    }
    #define GTECommitVariableAdding() = {
                                            if ( GTENextVariable > GTEDataArrayCheckOverflow ) then
                                                set  GTENextVariable = 0
                                            endif
                                        }
    
    function GTE002AddEventAndCommit takes integer periods, integer timeOut, trigger triggerToExecute returns nothing
        set  GTE002Loops[GTE002NextEvent] = periods
        set  GTE002CurrentTime[GTE002NextEvent] = 0
        set  GTE002Timeout[GTE002NextEvent] = timeOut
        set  GTE002TriggerToExecute[GTE002NextEvent] = triggerToExecute
        if ( GTE002NextEvent < GTE002ArrayOverflow) then
            set  GTE002NextEvent = GTE002NextEvent + 1
        else
            set  GTE002NextEvent = 0
        endif
    set  triggerToExecute = null
    return
    endfunction
    
    function GTE010AddEventAndCommit takes integer periods/*AKA amount of ticks*/, integer timeOut/*AKA tickrate*/, trigger triggerToExecute returns nothing
        set  GTE010Loops[GTE010NextEvent] = periods
        set  GTE010CurrentTime[GTE010NextEvent] = 0
        set  GTE010Timeout[GTE010NextEvent] = timeOut
        set  GTE010TriggerToExecute[GTE010NextEvent] = triggerToExecute
        if ( GTE010NextEvent < GTE010ArrayOverflow) then
            set  GTE010NextEvent = GTE010NextEvent + 1
        else
            set  GTE010NextEvent = 0
        endif
    set  triggerToExecute = null
    return
    endfunction
    
    function GTE002Tick takes nothing returns nothing
        loop
            if ( GTE002Loops[GTELoopCounter] > -1 ) then
                if ( GTE002CurrentTime[GTELoopCounter] < GTE002Timeout[GTELoopCounter] ) then
                    set  GTE002CurrentTime[GTELoopCounter] = GTE002CurrentTime[GTELoopCounter] + 1
                else
                    call TriggerExecute(GTE002TriggerToExecute[GTELoopCounter])
                    if ( GTE002Loops[GTELoopCounter] > 0 ) then
                        set  GTE002CurrentTime[GTELoopCounter] = 0
                        set  GTE002Loops[GTELoopCounter] = GTE002Loops[GTELoopCounter] - 1
                    else
                        set  GTE002Loops[GTELoopCounter] = -1
                    endif
                endif
            endif
            exitwhen GTELoopCounter > GTE002ArrayOverflowExit
            set  GTELoopCounter = GTELoopCounter + 1
        endloop
        return
    endfunction
    
    function GTE010Tick1 takes nothing returns nothing
        loop
            if ( GTE010Loops[GTELoopCounter] > -1 ) then
                if ( GTE010CurrentTime[GTELoopCounter] < GTE010Timeout[GTELoopCounter] ) then
                    set  GTE010CurrentTime[GTELoopCounter] = GTE010CurrentTime[GTELoopCounter] + 1
                else
                    call TriggerExecute(GTE010TriggerToExecute[GTELoopCounter])
                    if ( GTE010Loops[GTELoopCounter] > 0 ) then
                        set  GTE010CurrentTime[GTELoopCounter] = 0
                        set  GTE010Loops[GTELoopCounter] = GTE010Loops[GTELoopCounter] - 1
                    else
                        set  GTE010Loops[GTELoopCounter] = -1
                    endif
                endif
            endif
            exitwhen GTELoopCounter > GTE010ArrayOverflowExit
            set  GTELoopCounter = GTELoopCounter + 5
        endloop
        return
    endfunction
    
    function UpdateCustomBars takes unit u returns nothing
        local integer i = 0
        local real maxhp = GetUnitState( u,UNIT_STATE_MAX_LIFE )
        local real hp = GetWidgetLife(u)
        local integer color = R2I( 100. * hp / maxhp + 0.5 )
            loop
                call SetUnitAnimationByIndex( UnitDBHeroHPBar[i], color )
                if ( color > 50. ) then
                    call SetUnitVertexColor( UnitDBHeroHPBar[i], ( 100 - color ) * 6, 255, 0, 255 )
                else
                    call SetUnitVertexColor( UnitDBHeroHPBar[i], 255, color * 6, 0, 255 )
                endif
                call SetUnitAnimationByIndex( UnitDBHeroMPBar[i], R2I( 100. * GetUnitState( u, UNIT_STATE_MANA )/GetUnitState( u, UNIT_STATE_MAX_MANA ) + 0.5 ) )
                set  hp = 100. * ( hp + UnitDBAdditionalHealth[i] ) / maxhp - 0.5//So it doesnt show up if shield = 0
                if ( hp > 100. ) then
                    set hp = 100.
                endif
                call SetUnitAnimationByIndex( UnitDBHeroSPBar[i], R2I( hp ) )
                exitwhen i > UnitDBPreviousHero
                set  i = i + 1
                set  u = UnitDBUnit[i]
                set  maxhp = GetUnitState( u,UNIT_STATE_MAX_LIFE )
                set  hp = GetWidgetLife(u)
                set  color = R2I( 100. * hp / maxhp + 0.5 )
            endloop
        set  u = null
    endfunction
    
    function GlobalTimerTick takes nothing returns nothing
        local integer i = GTE010CurrentLoopStartingValue
        local unit u = UnitDBUnit[0]
            set  GTELoopCounter = 0
            call GTE002Tick()
            set  GTELoopCounter = i// - 1
            call GTE010Tick1()
            //call GTE010Tick2()//128 is low enough to never reach stream overflow.
            call ImpaleMechanicsOnTimerTick( i )
            if ( GTE010CurrentLoopStartingValue > 0 ) then
                set  GTE010CurrentLoopStartingValue = i - 1
            else
                set  GTE010CurrentLoopStartingValue = 4
                call UpdateCustomBars( u )//its actually not for just a single unit. loop is inside of called func
            endif
            if ( ICTicks < ICPeriod ) then
                set  ICTicks = ICTicks + 1
            else
                set  ICTicks = 0
                call TriggerExecute( gg_trg_SECore )
            endif
            set  i = 0
            loop
                call SetUnitX( UnitDBHeroHPBar[i], GetUnitX(u) )
                call SetUnitY( UnitDBHeroHPBar[i], GetUnitY(u) )
                call SetUnitX( UnitDBHeroMPBar[i], GetUnitX(u) )
                call SetUnitY( UnitDBHeroMPBar[i], GetUnitY(u) )
                call SetUnitX( UnitDBHeroSPBar[i], GetUnitX(u) )
                call SetUnitY( UnitDBHeroSPBar[i], GetUnitY(u) )
                exitwhen i > UnitDBPreviousHero
                set  i = i + 1
                set  u = UnitDBUnit[i]
            endloop
            if ( LoopOf3 < 2 ) then
                set  LoopOf3 = LoopOf3 + 1
            else
                set LoopOf3 = 0
            endif
        set  u = null
        return
    endfunction
    
endscope
Понятия не имею куда заведут комментарии, поэтому предлагаю им не верить. Это было так давно что я уже и не помню как их писал. А с тех пор изменения были, да...
Эти "потоки" так или иначе сидят в простое и персонаж сам по себе ест не много этих "потоков", поэтому я их с легким сердцем пускаю в оборот.
Реализуется поток примерно так:
GTE002InitVariableAdding
             GTEAddInteger( ticks )//amount of ticks(to get to target point)
        set  r = x * lightning_spear_projectile_speed1
             GTEAddReal( r )
             GTEIncreaseVariablePointer
             GTEAddInteger( UGRGetGroup() )
             GTEAddReal( x2 + r )
             GTEIncreaseVariablePointer
             GTEAddInteger( UnitDBAddDummy( CreateUnit( P, lightning_spear_projectile_unit, x2 + lightning_spear_projectile_initial_offset * x, y2 + lightning_spear_projectile_initial_offset * y, angle * RadToDeg ), i ) )
        set  r = y * lightning_spear_projectile_speed1
             GTEAddReal( r )
             GTEIncreaseVariablePointer
             GTEAddInteger( GetPlayerId( P ) )
             GTEAddReal( y2 + r )
             GTEIncreaseVariablePointer
             GTEAddInteger( i )//caster user data for lifesteal
             GTEAddReal( 25. * GetUnitAbilityLevel( u, QLightningSpearId ) + GetUnitAbilityLevel( u, QLightningSpear2Id ) )//Spell damage           //GTEAddReal( x2 )//Unused because of aoe-check usage
             //GTEIncreaseVariablePointer
             //UNUSED INT
             //GTEAddReal( y2 )//Unused because of aoe-check usage
             GTEIncreaseVariablePointer
             GTECommitVariableAdding
        call GTE002AddEventAndCommit( 9999, 0, gg_trg_Lightning_spear_on_tick )
с последующим запуском при звонке потока таймера шапки кода, выглядящей для данного примера как
local integer i = GTE002FirstVariable[GTELoopCounter]
    local integer ticksRemaining = GTEIntegers[i]
    local real r
    //GTEReals[i] contains x offset per step
    set  G = UGRGroups[GTEIntegers[i + 1]]
    set  X2 = GTEReals[i + 1]
    set  U2 = UnitDBUnit[GTEIntegers[i + 2]]//dummy
    //GTEReals[i + 2] contains y offset per step
    set  P = PlayerArray[GTEIntegers[i + 3]]
    set  Y2 = GTEReals[i + 3]
    set  U3 = UnitDBUnit[GTEIntegers[i + 4]]//caster
    set  R = GTEReals[i + 4]
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

nvc123, тогда я не понимаю почему ты назвал мое решение кривым. Каким ты увидил принцип работы?
Просто я все больше вижу в твоем решении свое. Подход немного другой, но в целом - я делаю тоже самое. Я храню в массиве из 64 элементов(сохранив ссылку на выделенное пространство там, где надо) информацию о числе задеваний таргета Т1 кастами кастера C1. Прогоняюсь через этот массив каждый раз при непосредственном задевании дабы увеличить или уменьшить счетчик, плюс при проверке на нахождение целей вблизи даммиков для нанесения урона. Уменьшаю этот счетчик при звонке таймера на окончание действие дебаффа(/жизни даммика). Считай тот же отсчет времени дебаффа. Таймер реализован как отдельный поток работы одного глобального, так что использую ресурсы, находящиеся в простОе.
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

nvc123:
преобразуется как раз в несколько параллельных массивов
и что в этом плохого?
Ятп, что предлагаемое тобой решение заключается в создании нескольких массивов чисто под этот спелл. В прочем, я не до конца понимаю во что превратятся такие структуры в конечном итоге. :>
Дубль 2: Ятп,
nvc123:
2 содержит оставшееся время баффа, даммика который наносит урон и структуру 1 и крепится к юнитам попавшим под спелл
что здесь крепление к юнитам, попавшим под спелл, подразумевает крепление ко всем и сразу, т.е. к группе юнитов внутри структуры, а также обработки этих структур из под единственного таймера. Как раз в этой ситуации я и прибег к своим костылям. Как ты собрался удалять юнита из структуры 1, если он содержится в двух структурах 2(задет двумя кастами)? Как узнать что время действующего на него лжебаффа закончилось во всех структурах 2 типа? Только перебором.
0
20
7 лет назад
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

nvc123:
Diaboliko, крайне кривое решение
не проще ли создать 2 структуры
1 содержит группу всех задетых юнитов и крепится к кастеру
2 содержит оставшееся время баффа, даммика который наносит урон и структуру 1 и крепится к юнитам попавшим под спелл
Что, ятп, преобразуется как раз в несколько параллельных массивов, пространство которых выделяется под юнитов, попавших под спелл.
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

Doc:
Кто-нибудь уже объяснил зачем нужна глобальная группа?
Есть такое понятие как скоупинг. В чем проблема использовать одну группу на один каст? Я что-то не так понял?
Одна группа на один каст имеется. Глобальная группа выделяется для каждого такого юнита дабы при добавлении в первую группу, юнит также добавлялся в глобальную. При поиске целей для нанесения урона от даммика используется глобальная группа(дабы обеспечить желаемый эффект двух войд-зон, дамажащих юнитов, задетых хотя бы одним кастом своего кастера). Первая упомянутая в этом посте группа (назовем ее локальной, т.к. используется в рамках 1 каста) нужна для удаления из глобальной всех юнитов, содержащихся в ней(своего рода удаление дебаффа без использования оного).
Опять же - единственный солюшн, который я вижу - использовать 2 параллельных массива(юнит+интегер), где массив юнитов заменит глобальную группу, а параллельный этому массиву массив интегеров будет работать как счетчик. Недостаток этого метода в необходимости искать задетых каждым следующим кастом юнитов из массива юнитов.
Если этого описания все еще недостаточно, то пора закрывать эту тему -_-
В общем, прибегнул к эмуляции группы юнитов через цикл + два параллельных массива, пространство которых выделяется под кастеров этого заклинания.
0
20
7 лет назад
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

разве это не противоречие самому себе?
В первой цитате говорилось о двух разных кастерах.
Сейчас касты работают каждый сами по себе(задел кастом - даммик будет дпсить), но от задевания одним кастом, даммику, появившемуся от другого каста, ни горячо, ни холодно.
0
20
7 лет назад
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

в результате D1 наносит урон T если T находится в радиусе досягаемости D1
и D2 наносит урон T если T находится в радиусе досягаемости D2
да или нет?
Это как раз тот солюшн, которого я хочу избежать. D2 не должен наносить урон T, поскольку сам каст его не задел. Такое поведение в данный момент реализовано в рамках каждого каста. Если каст задевает юнита - даммик этого каста будет наносить задетому юниту урон. Сабж в том чтобы если персонаж применяет дважды этот скилл и задевает противника T лишь одним из них, то даммики D1 и D2, созданные по итогам применения обоих кастов наносили этому юниту урон. Проблема именно в ведении счета того, сколько раз юнит был добавлен в эту "глобальную" группу, содержащую всех юнитов, которых своими кастами задел этот персонаж.
В прочем, спустя два дня тыканья палкой, я уже уверен что "красивого" решения здесь нет. Разве что я что-то упускаю...
0
20
7 лет назад
0

» WarCraft 3 / native DisplayTextToPlayer takes player toPlayer, real x, real y

Там вроде X Y в диапазоне [0.,1.]. Отвечают за положение сообщения на экране. Однако при этом сдвигаются все существующие сообщения. Контрится чисткой экрана
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

При чём тут владелец
Когда урон надо наносить от определённого юнита - кастера, т.е. героя в данном случае
Proshel_Doty:
Я бы так не делал, хотя бы потому, что тогда такой предмет как Octarine Core как в доте2 (ну суть понятна - хилит от способностей) не будет просто хилить героя из-за того, что не он наносит урон.
Поскольку я знаю что даммика создал конкретный юнит под нужды нанесения урона - я утверждаю что урон, в итоге, наносит этот конкретный юнит. Если я захочу прохилить этого юнита - у меня есть ссылка на него в UnitUserData даммика.
Однако я бы предпочел услышать в этом конкретном топике мысли по решению возникшей у меня задачи. Если хочется дальше поспорить о превосходстве гибкости метода нанесения всего магического урона от даммика против нанесения урона от того же юнита - пиши в ЛС.
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

Diaboliko:
наношу урон от даммиков
Я бы так не делал, хотя бы потому, что тогда такой предмет как Octarine Core как в доте2 (ну суть понятна - хилит от способностей) не будет просто хилить героя из-за того, что не он наносит урон.
Внезапно решается базами данных. Я храню в UnitUserData юнитов их позицию в БД, а в UnitUserData даммиков, являющихся снарядами и прочей подобной фигней - позицию в БД их создателя. Ссылка на даммиков в БД хранится в таймерах, использующих их. Для мгновенного урона также есть два даммика, которые постоянно меняют владельца перед нанесением урона. Первый - для блокируемого урона, второй - для не блокируемого.
Попытка описать дубль два:
Герой кидает молнию
да, да, привет фанатам дарк соулс //
Она задевает огра мага в момент достижения указанной точки
На месте взрыва появляется даммик, к которому этот огр притягивается, при этом ему наносится урон. При текущей реализации огр будет притягиваться лишь к тем даммикам, которые, грубо говоря, задели его своим появлением(если его заденет снаряд во время полета или непосредственный взрыв). Задумка в том, чтобы подвергнуть огра эффекту двух таких даммиков, если его заденет хотя-бы один каст. Проблема реализации через баффы в том, что два и более таких персонажей, будучи союзниками, засрут все поле боя и будут держать всех противников под дебаффом.
Загруженные файлы
0
20
7 лет назад
Отредактирован Diaboliko
0

» WarCraft 3 / Альтернативы добавлению юнита в группу дважды(что невозможно)?

немного не понял по поводу того что должно быть
1 каст спелла - 1 даммик?
если 2 спела одновременно попали на 1 юнита то они оба дамажат или только 1 из них?
Тогда дамажат с течением времени оба даммика. Если было бы скастованно в одну точку 2 таких скилла и лишь один из них задел бы цель - цель бы получала урон от обоих даммиков. Если ни одного - могла бы спокойно гулять возле даммиков. Если бы два разных кастера скастовали скилл в одну точку и только один из них задел бы цель - цель получала бы урон от даммика кастера, который ее задел.
Proshel_Doty:
Если урон от одного игрока складывается при нескольких применениях скила, то:
КОгда кастуется эта способность, делам переменную типа integer cast count = cast count +1
Юнит кастер[cast count] = GetSpellAbilityUnit()
Группа юнитов[cast count] = юниты которых надо дамажить
И в триггере с переодиком через цикл перебираем от 1 до cast count
в нём перебираем юнитов в определённой группе и в каждой группе наносим урон от кастера всем юнитам в этой группе.
В итоге: способность можно кастовать любое количество раз, разными героями, а также складывается урон от 1 перса.
Если нужно, чтобы урон не складывался, то тогда для одного героя 1 группа, или проще для игрока, так как герой такой у игрока будет 1 скорее всего
Hate:
храни одну на каждого игрока
Во-первых, я с тем же успехом наношу урон от даммиков через ForGroup внутри ForGroup.
Во-вторых, суть именно том, чтобы попав под бафф такого каста юнит старался избегать созданных даммиков до окончания времени действия мнимого баффа. Мнимого - поскольку реальный бафф будет перебиваться, например, таким же юнитом союзника. Если желаемого адекватного решения возникшей проблемы не возникнет - скорее всего прибегну к этому решению.
mishanka122:
nvc123, Стакающийся эффект.
разве баффы нельзя разбить на лвлы? Тогда и лвл баффа юзать как множитель.
Как упоминалось в этом посте - такой вариант реализации не желателен.
0
20
7 лет назад
0

» WarCraft 3 / идексы переменных

Конвертни в код и посмотри. Там шарить в джассе нет нужды.
9
20
7 лет назад
9

» WarCraft 3 / Ограничение дальности атаки Героя 650. Как снять?

Если не ошибаюсь - нужно еще дистанцию получения приказа поднять
0
20
7 лет назад
0

» WarCraft 3 / Невыделяемый юнит

Как я уже понял таким образом просто через редактор объектов его сделать не получится, да?
Да. Возиться с триггерами придется и, при этом, углубляться придется далеко.
0
20
7 лет назад
0

» WarCraft 3 / Невыделяемый юнит

Я могу понять зачем нужен даммик, но зачем нужна уязвимость этого юнита(иначе чем плохи москиты)? Отлов урона должен быть триггерным, нет?
3
20
7 лет назад
3

» WarCraft 3 / Конкурс карт WC3 на 50 000 рублей!

16GB:
ClotPh,
Тут надо делать карту чисто для подпивасов (это не значит что она будет лёгкой), никакие глубокие механики, они не оценят. А уж про модели и ландшафт тем более.
Вообще ещё проблема тестить карту, гарена огорожена от сторонних хостботов, на одном айкапе можешь и не собрать.
Звучит как "Утро после бодуна v2"
0
20
7 лет назад
0

» Hanabishi's Blog / Jass New Gen Pack - Rebuild

Hanabishi:
Diaboliko:
Никогда не запускал WE от админа. Почему-то после определенного момента просто перестали создаваться бэкапы(возможно после некорректного завершения работы). Никто с подобным не сталкивался?
Удаление файла backupsdata эффекта не дает?
Удалил. Все ок. Вопрос в том, почему это начало происходить :)
1
20
7 лет назад
1

» WarCraft 3 / Баф на уменьшение физ. размера.

Событие: Юнит приводит способность в действие
Условие: Примененная способность = Увечье(или что там)
Действие: Уменьшить размер цели заклинания(не имею понятия как там это будет называться, но суть такова)
0
20
7 лет назад
Отредактирован Diaboliko
0

» Hanabishi's Blog / Jass New Gen Pack - Rebuild

Никогда не запускал WE от админа. Почему-то после определенного момента просто перестали создаваться бэкапы(возможно после некорректного завершения работы). Никто с подобным не сталкивался?
Загруженные файлы
0
20
7 лет назад
0

» WarCraft 3 / Лагает РО - войска

их слишком мало xD
Полагаю, можно в одном из файлов архива карты накопипастить нужное количество, а затем загрузить карту в редакторе и править как душе угодно. Хотя я не представляю под какие такие нужды может не хватать ~200 юнитов.
1
20
7 лет назад
1

» WarCraft 3 / Лагает РО - войска

Чем создавать новых юнитов, лучше редактируйте существующих по умолчанию :>
2
20
7 лет назад
2

» Dota 2 / Конкурс героев для Dota 2

В рамках джолли кооперейшн есть ли моделлер под работу с WC3, желающий ворваться в тему желтого электричества? Главным образом речь идет о подборе/создании/правке спецэффектов, однако правка модели, взятую за основу(ветряной элемент панды пивовара(у него куча лишних анимаций)) под нужную тематику(ретекстурирование + опциональное изменение самой модели), также имеет место быть в опциональном режиме. В рамках кооперирования также будет дискуссия на тему концепта героя(надо на победку же мутить :) ) и, если с молниями совсем уж тлен, изменения тематики(однако многие элементы уже готовы, поэтому хотелось бы подгонять тематику под скиллы, а не скиллы под тематику :>). Пока подробности не освещаю, т.к. настроение сейчас из разряда "дико в падлу", однако осознаю что в одиночку визуальную составляющую не осилю в силу отсутствия прямых рук. Прошу изъявлять желание в ЛС.
0
20
7 лет назад
0

» WarCraft 3 / Блестяшки или симуляция Specular карт

С партикл эмиттерами подобный трюк, полагаю, не прокатит?