Как сделать MUI абилку при помощи глобальных массивов?

LastUchiha, нашел косяк, исправил проверку.
Систему можно еще оптимизировать, использовав хэш-таблицу, структуры и тд и тп. Но как пример ты уже можешь экспериментировать с этим.
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...
15
Вопрос очень общий: какую именно способность, сколько юнитов смогут ей пользоваться, почему массивы, а не хештаблица?
Ответы (17)
12
Ydav,
  1. Летящий огненный шар, который дамажит.
  2. 6 юнитов могут её юзать.
  3. Решил освоить MUI в массивах.
25
LastUchiha, сделай абилку на 1 юнита, я тебе помогу сделать с массивами для многА юнитов :D
Ну и скинь сюда эту карту с такой абилкой.
12
konvan5, сделать сейчас на глобальных массивах просто?
25
LastUchiha, просто саму способку, можешь попробовать на массивах, что не получится - помогу доделать
12
konvan5, ну вот просто на глобальных массивах, только MUI сделать нужно.
Загруженные файлы
25
LastUchiha, ну вот, у тебя тут была самая главная проблема, что есть таймер для каждого каста свой, и после каждого исхода таймера надо находить, какой там таймер закончился. С помощью цикла проходимся по ним, находим и выполняем действия с данными под индексом данного таймера.
При касте создаем таймер, группу и тд записываем в массив. Когда абилка закончила свое действие - удаляем таймер, группу и тд, а массив смещаем, чтобы не было пустых элементов.
Можно теперь юзать способку хоть 10 юнитов, хоть 100, пока движок варика не помрет от каста стольких абилок сразу :D
Загруженные файлы
25
LastUchiha, а так я сделал работу с массивом как и описывал ниже. Там еще есть пару моментов, как тот-же фильтр, туда нельзя передать напрямую индекс, по которому ему надо проверять. Для этого используем глобальную переменную LastI.
31
С помощью цикла проходимся по ним, находим и выполняем действия с данными под индексом данного таймера.
Прекрасней O(n) может быть только O(n!).
12
konvan5, почему каждый новый огненный шар летит быстрее предыдущего?
25
nazarpunk, я уверен, алгоритм можно оптимизировать. Осталось узнать, как там для каждого нового таймера передать аргумент в функцию. Вроде в стандартном джассе этого нет. vjass и другие инструменты и библиотеки я не рассматриваю для этой наработки.
25
LastUchiha, через полчаса проверю, по идее такого быть не должно, мб накосячил в коде при переносе переменных.
31
Осталось узнать, как там для каждого нового таймера передать аргумент в функцию.
Сохранить данные на хэндл таймера. Вот простой пример.
31
vjass и другие инструменты и библиотеки я не рассматриваю для этой наработки.
Ну так напиши на структурах грязножасса, скомпили и будет тебе чистожасс.
28
LastUchiha, какой-то ужас
я конечно понимаю что ты хотел на чистом джассе реализовать с глобалками, но хэштаблица со структурами будет удобнее, тем более, ты уже юзаешь вджасс
твои массивы на глобалках нужны разве что в гуишном варианте
Загруженные файлы
25
LastUchiha, нашел косяк, исправил проверку.
Систему можно еще оптимизировать, использовав хэш-таблицу, структуры и тд и тп. Но как пример ты уже можешь экспериментировать с этим.
Загруженные файлы
Принятый ответ
25
мммм, а в чем проблема?)
Сделаем абилку, которая будет хилять юнита (кастующего) каждую секунду на 10 хп а противника (цель) уменьшать хп на 10 в секунду в течении 5 секунд.
Ну как вариант:
  1. Создаем массивы всех данных, что использует твоя способка, к примеру Heroes, Targets, Times
  2. Создаем переменную, означающую количество активных способок ACount
Далее 2 варианта сохранения и удаления данных из массива. А именно, когда абилка завершила свое действие, надо удалить ее данные из массива. Что делаем с остальными абилками идущими после этого индекса? Если ничего, то остается пустое место в середине массива, куда сможем записать новую абилку. Либо лучше сместить все данные после текущей абилки влево, закрыв пустое место и уменьшив счетчик ACount.
Тут как раз таки главная проблема в том, как ты будешь ориентироваться и находить данные этой способки в течении всего жизненного цикла ее, чтобы не потерять связь между этими данными.
Как один из вариантов, будем сдвигать все данные влево при уничтожении абилки.
Использую псевдокод чтобы был понятен смысл и мне лень вспоминать какие там функции в варике и как они выглядят.
  1. При касте способки сохраняем все данные в массив под индексом ACount + 1:
index = ACount + 1
Heroes[index] = КастующийЮнит()
Targets[index] = ЦельКаста()
Times[index] = 5
  1. Далее будет какой-то глобальный таймер или событие "каждую секунду" запускающий триггер:
цикл для i от 1 до ACount делаем
	Если Heroes[i] жив и Target[i] жив то
		устанавливаем хп Target[i] на Target[i] - 10.
		устанавливаем хп Heroes[i] на Heroes[i] + 10.
		устанавливаем время Times[i] = Times[i] - 1
	Иначе 
		Times[i] = 0
  1. Далее надо сместить (удалить) все способки, что закончили свое действие. В этом же триггере:
free = -1 // индекс свободной ячейки
цикл для i от 1 до ACount делаем
	если Times[i] == 0 то
		если free < 0 то
			free = i
	иначе
		если free > 0 то
		Heroes[free] = Heroes[i]
		Targets[free] = Targets[i]
		Times[free] = Times[i]
		free = free + 1 
конец цикла
Если free > 0 то
	ACount = free - 1
  1. Если тебе нужно будет в какой-то момент получить данные способки, просто ищем этого юнита в массиве Heroes[] и далее используй тот-же индекс для получения остальных данных из других массивов. Усе.
Можно еще добавить про "правильное" очищение ссылок переменных но это уже вопрос оптимизации.

И да, хэштаблицу проще использовать, чем параллельные массивы данных. Но я постарался ответить именно на твой вопрос с примером, как можно было бы сделать и оно будет работать.
Ответы (2)
12
konvan5, тяжело это всё...
А проблема в том что я как раз таки не знаю как очищать место.
31
LastUchiha, попробуй исполльзовать Москву. Говорят помогает.
32
Зачем есть есть структуры vjass а так же хештаблицы...
28
Демонстрация работ

Код

Untitled Trigger 001
globals
    constant timer TempTimer = CreateTimer( )
    constant group TempGroup = CreateGroup( )
    
    integer max = 0
    
    unit array caster
    unit array dummy
    
    player array owningPlayer
    group array g
    
    real array x
    real array y
    real array angleX
    real array angleY
    real array radius
    real array speed
    real array distance
endglobals

native UnitAlive takes unit id returns boolean

function Move takes nothing returns nothing
    local integer i = 1
    local unit u
    
    loop
        exitwhen i > max
        
        if speed[i] > distance[i] then
            set speed[i] = distance[i]
        endif
        
        set x[i] = x[i] + speed[i] * angleX[i]
        set y[i] = y[i] + speed[i] * angleY[i]
        
        call SetUnitX( dummy[i], x[i] )
        call SetUnitY( dummy[i], y[i] )
        call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", x[i], y[i] ) )
        
        call GroupEnumUnitsInRange( TempGroup, x[i], y[i], radius[i] + 200.00, null )
        
        loop
            set u = FirstOfGroup( TempGroup )
            exitwhen u == null
            call GroupRemoveUnit( TempGroup, u )
            
            if IsUnitInRangeXY( u, x[i], y[i], radius[i] ) then
                if not IsUnitInGroup( u, g[i] ) then
                    if UnitAlive( u ) and IsUnitEnemy( u, owningPlayer[i] ) then
                        call GroupAddUnit( g[i], u )
                        call UnitDamageTarget( caster[i], u, 100.00, false, false, null, null, null )
                    endif
                endif
            endif
        endloop
        
        set distance[i] = distance[i] - speed[i]
        
        if distance[i] <= 0.00 then
            call KillUnit( dummy[i] )
            
            call DestroyGroup( g[i] )
            
            set caster[i] = caster[max]
            set dummy[i] = dummy[max]
            set owningPlayer[i] = owningPlayer[max]
            set g[i] = g[max]
            set x[i] = x[max]
            set y[i] = y[max]
            set angleX[i] = angleX[max]
            set angleY[i] = angleY[max]
            set radius[i] = radius[max]
            set speed[i] = speed[max]
            set distance[i] = distance[max]
            
            set max = max - 1
            set i = i - 1
            
            if max <= 0 then
                call PauseTimer( TempTimer )
            endif
        endif
        
        set i = i + 1
    endloop
endfunction

function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    local real a
    
    if max == 0 then
        call TimerStart( TempTimer, 0.03125, true, function Move )
    endif
    
    set max = max + 1
    
    set caster[max] = GetTriggerUnit( )
    set owningPlayer[max] = GetOwningPlayer( caster[max] )
    
    set g[max] = CreateGroup( )
    
    set x[max] = GetUnitX( caster[max] )
    set y[max] = GetUnitY( caster[max] )
    
    set a = Atan2( GetSpellTargetY( ) - y[max], GetSpellTargetX( ) - x[max] )
    
    set angleX[max] = Cos( a )
    set angleY[max] = Sin( a )
    
    set dummy[max] = CreateUnit( owningPlayer[max], 'h000', x[max], y[max], a * bj_RADTODEG )
    
    set radius[max] = 200.00
    set speed[max] = 1000.00 * 0.03125
    set distance[max] = 1000.00
endfunction

//===========================================================================
function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
endfunction

можешь в следующий раз по подобным спеллмейкерским вопросам обратиться в мою тему

а, я так понимаю там сама идея была в том, что огненный шар дамажит всё время при движении, а не один раз - достаточно тогда просто удалить всё, что связанно с переменной g
Загруженные файлы
Чтобы оставить комментарий, пожалуйста, войдите на сайт.