Альтернативы добавлению юнита в группу дважды(что невозможно)?
Хотелось бы знать какие пути решения без использования отдельных массивов/хэштэйбла видит кто-либо для разрешения ситуации следующего характера:
Скилл поражает цели в выбранной зоне и оставляет даммика, находясь возле которого юниты, задетые заклинанием, получают урон. В один момент времени может существовать хоть с десяток таких даммиков, но они должны наносить повреждения лишь целям, задетыми заклинанием их создателя. Проверка на бафф не актуальна, поскольку два таких кастера будут перебивать баффы друг друга.
В данный момент под каждый каст скилла выделяется перерабатываемая группа на время жизни этого скилла, которая содержит юнитов, задетых этим конкретным кастом, а также группа, содержащие все цели, пораженные этими же заклинаниями кастера. Поскольку нельзя добавить в группу юнита, который уже содержится в ней, нерешенным остается вопрос о том, как же удалять юнита из второй группы, только когда он не содержится в первых группах. Сейчас на ум приходит только выделение, скажем, 64 перерабатываемых элементов параллельных массивов юнит+интегер, куда в интегер записывается число групп, в которых содержится юнит. Солюшн весьма хреновый, поскольку придется каждый раз искать этого юнита в 64 элементах массива...

Без ответа.


Просмотров: 1 110

Proshel_Doty #1 - 8 месяцев назад -2
А зачем? И что к чему, собственно?
Hate #2 - 8 месяцев назад 0
которая содержит юнитов, задетых этим конкретным кастом, а также группа, содержащие все цели, пораженные этими же заклинаниями кастера
и зачем тебе 2 группы? храни одну на каждого игрока
nvc123 #3 - 8 месяцев назад 0
немного не понял по поводу того что должно быть
1 каст спелла - 1 даммик?
если 2 спела одновременно попали на 1 юнита то они оба дамажат или только 1 из них?
mishanka122 #4 - 8 месяцев назад 0
nvc123, Стакающийся эффект.
разве баффы нельзя разбить на лвлы? Тогда и лвл баффа юзать как множитель.
Proshel_Doty #5 - 8 месяцев назад 0
Если урон от одного игрока складывается при нескольких применениях скила, то:
КОгда кастуется эта способность, делам переменную типа integer cast count = cast count +1
Юнит кастер[cast count] = GetSpellAbilityUnit()
Группа юнитов[cast count] = юниты которых надо дамажить
И в триггере с переодиком через цикл перебираем от 1 до cast count
в нём перебираем юнитов в определённой группе и в каждой группе наносим урон от кастера всем юнитам в этой группе.
В итоге: способность можно кастовать любое количество раз, разными героями, а также складывается урон от 1 перса.
Если нужно, чтобы урон не складывался, то тогда для одного героя 1 группа, или проще для игрока, так как герой такой у игрока будет 1 скорее всего
Hate:
храни одну на каждого игрока
Diaboliko #6 - 7 месяцев назад (отредактировано ) 0
немного не понял по поводу того что должно быть
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, Стакающийся эффект.
разве баффы нельзя разбить на лвлы? Тогда и лвл баффа юзать как множитель.
Как упоминалось в этом посте - такой вариант реализации не желателен.
Proshel_Doty #7 - 7 месяцев назад (отредактировано ) 0
Во-вторых, суть именно том, чтобы попав под бафф такого каста юнит старался избегать созданных даммиков до окончания времени действия мнимого баффа. Мнимого - поскольку реальный бафф будет перебиваться, например, таким же юнитом союзника. Если желаемого адекватного решения возникшей проблемы не возникнет - скорее всего прибегну к этому решению.
Честно, ничего не понял
Особенно сути этих даммиков, ты бы хоть способность описал, что она делает...
Diaboliko:
наношу урон от даммиков
Я бы так не делал, хотя бы потому, что тогда такой предмет как Octarine Core как в доте2 (ну суть понятна - хилит от способностей) не будет просто хилить героя из-за того, что не он наносит урон.
Это на всякий, а пока ещё раз скажу, что вообще не понятно, что за способность ты делаешь и суть этих даммиков
Кинь описание
Diaboliko #8 - 7 месяцев назад (отредактировано ) 0
Diaboliko:
наношу урон от даммиков
Я бы так не делал, хотя бы потому, что тогда такой предмет как Octarine Core как в доте2 (ну суть понятна - хилит от способностей) не будет просто хилить героя из-за того, что не он наносит урон.
Внезапно решается базами данных. Я храню в UnitUserData юнитов их позицию в БД, а в UnitUserData даммиков, являющихся снарядами и прочей подобной фигней - позицию в БД их создателя. Ссылка на даммиков в БД хранится в таймерах, использующих их. Для мгновенного урона также есть два даммика, которые постоянно меняют владельца перед нанесением урона. Первый - для блокируемого урона, второй - для не блокируемого.
Попытка описать дубль два:
Герой кидает молнию
да, да, привет фанатам дарк соулс //
Она задевает огра мага в момент достижения указанной точки
На месте взрыва появляется даммик, к которому этот огр притягивается, при этом ему наносится урон. При текущей реализации огр будет притягиваться лишь к тем даммикам, которые, грубо говоря, задели его своим появлением(если его заденет снаряд во время полета или непосредственный взрыв). Задумка в том, чтобы подвергнуть огра эффекту двух таких даммиков, если его заденет хотя-бы один каст. Проблема реализации через баффы в том, что два и более таких персонажей, будучи союзниками, засрут все поле боя и будут держать всех противников под дебаффом.
прикреплены файлы
Proshel_Doty #9 - 7 месяцев назад 0
Для мгновенного урона также есть два даммика, которые постоянно меняют владельца перед нанесением урона. Первый - для блокируемого урона, второй - для не блокируемого.
При чём тут владелец
Когда урон надо наносить от определённого юнита - кастера, т.е. героя в данном случае
Proshel_Doty:
Я бы так не делал, хотя бы потому, что тогда такой предмет как Octarine Core как в доте2 (ну суть понятна - хилит от способностей) не будет просто хилить героя из-за того, что не он наносит урон.
Diaboliko #10 - 7 месяцев назад (отредактировано ) 0
При чём тут владелец
Когда урон надо наносить от определённого юнита - кастера, т.е. героя в данном случае
Proshel_Doty:
Я бы так не делал, хотя бы потому, что тогда такой предмет как Octarine Core как в доте2 (ну суть понятна - хилит от способностей) не будет просто хилить героя из-за того, что не он наносит урон.
Поскольку я знаю что даммика создал конкретный юнит под нужды нанесения урона - я утверждаю что урон, в итоге, наносит этот конкретный юнит. Если я захочу прохилить этого юнита - у меня есть ссылка на него в UnitUserData даммика.
Однако я бы предпочел услышать в этом конкретном топике мысли по решению возникшей у меня задачи. Если хочется дальше поспорить о превосходстве гибкости метода нанесения всего магического урона от даммика против нанесения урона от того же юнита - пиши в ЛС.
nvc123 #11 - 7 месяцев назад 0
Diaboliko, насколько я понял ситуация следующая
есть 2 юнита-кастера C1 и C2 являющихся союзниками
C1 кастует этот спел и задевает вражеского юнита T
создаётся даммик D1
C2 кастует этот спел и не задевает вражеского юнита T
создаётся даммик D2
в результате D1 наносит урон T если T находится в радиусе досягаемости D1
и D2 наносит урон T если T находится в радиусе досягаемости D2
да или нет?
Diaboliko #12 - 7 месяцев назад 0
в результате D1 наносит урон T если T находится в радиусе досягаемости D1
и D2 наносит урон T если T находится в радиусе досягаемости D2
да или нет?
Это как раз тот солюшн, которого я хочу избежать. D2 не должен наносить урон T, поскольку сам каст его не задел. Такое поведение в данный момент реализовано в рамках каждого каста. Если каст задевает юнита - даммик этого каста будет наносить задетому юниту урон. Сабж в том чтобы если персонаж применяет дважды этот скилл и задевает противника T лишь одним из них, то даммики D1 и D2, созданные по итогам применения обоих кастов наносили этому юниту урон. Проблема именно в ведении счета того, сколько раз юнит был добавлен в эту "глобальную" группу, содержащую всех юнитов, которых своими кастами задел этот персонаж.
В прочем, спустя два дня тыканья палкой, я уже уверен что "красивого" решения здесь нет. Разве что я что-то упускаю...
Hate #13 - 7 месяцев назад (отредактировано ) 0
в результате D1 наносит урон T если T находится в радиусе досягаемости D1
и D2 наносит урон T если T находится в радиусе досягаемости D2
Сабж в том чтобы если персонаж применяет дважды этот скилл и задевает противника T лишь одним из них, то даммики D1 и D2, созданные по итогам применения обоих кастов наносили этому юниту урон.
разве это не противоречие самому себе?
лично мне до сих пор непонятно как должно работать и как работает сейчас.
Diaboliko #14 - 7 месяцев назад 0
разве это не противоречие самому себе?
В первой цитате говорилось о двух разных кастерах.
Сейчас касты работают каждый сами по себе(задел кастом - даммик будет дпсить), но от задевания одним кастом, даммику, появившемуся от другого каста, ни горячо, ни холодно.
Это сообщение удалено
Doc #16 - 7 месяцев назад 0
Кто-нибудь уже объяснил зачем нужна глобальная группа?
Есть такое понятие как скоупинг. В чем проблема использовать одну группу на один каст? Я что-то не так понял?
Hate #17 - 7 месяцев назад 0
Doc:
Кто-нибудь уже объяснил зачем нужна глобальная группа?
Есть такое понятие как скоупинг. В чем проблема использовать одну группу на один каст? Я что-то не так понял?
Hate:
и зачем тебе 2 группы? храни одну на каждого игрока
я с самого начала задал этот вопрос
biridius #18 - 7 месяцев назад (отредактировано ) 0
Сабж в том чтобы если персонаж применяет дважды этот скилл и задевает противника T лишь одним из них, то даммики D1 и D2, созданные по итогам применения обоих кастов наносили этому юниту урон.
Создавать группу для каждого кастера в которой хранить задетых юнитов
Каждую сек. очищаем группу, далее каждый даммик перебирает юнитов вокруг себя добавляя их в группу, затем каждый даммик перебирает группу нанося урон
Diaboliko #19 - 7 месяцев назад (отредактировано ) 0
Doc:
Кто-нибудь уже объяснил зачем нужна глобальная группа?
Есть такое понятие как скоупинг. В чем проблема использовать одну группу на один каст? Я что-то не так понял?
Одна группа на один каст имеется. Глобальная группа выделяется для каждого такого юнита дабы при добавлении в первую группу, юнит также добавлялся в глобальную. При поиске целей для нанесения урона от даммика используется глобальная группа(дабы обеспечить желаемый эффект двух войд-зон, дамажащих юнитов, задетых хотя бы одним кастом своего кастера). Первая упомянутая в этом посте группа (назовем ее локальной, т.к. используется в рамках 1 каста) нужна для удаления из глобальной всех юнитов, содержащихся в ней(своего рода удаление дебаффа без использования оного).
Опять же - единственный солюшн, который я вижу - использовать 2 параллельных массива(юнит+интегер), где массив юнитов заменит глобальную группу, а параллельный этому массиву массив интегеров будет работать как счетчик. Недостаток этого метода в необходимости искать задетых каждым следующим кастом юнитов из массива юнитов.
Если этого описания все еще недостаточно, то пора закрывать эту тему -_-
В общем, прибегнул к эмуляции группы юнитов через цикл + два параллельных массива, пространство которых выделяется под кастеров этого заклинания.
nvc123 #20 - 7 месяцев назад 0
Diaboliko, крайне кривое решение
не проще ли создать 2 структуры
1 содержит группу всех задетых юнитов и крепится к кастеру
2 содержит оставшееся время баффа, даммика который наносит урон и структуру 1 и крепится к юнитам попавшим под спелл
Diaboliko #21 - 7 месяцев назад 0
nvc123:
Diaboliko, крайне кривое решение
не проще ли создать 2 структуры
1 содержит группу всех задетых юнитов и крепится к кастеру
2 содержит оставшееся время баффа, даммика который наносит урон и структуру 1 и крепится к юнитам попавшим под спелл
Что, ятп, преобразуется как раз в несколько параллельных массивов, пространство которых выделяется под юнитов, попавших под спелл.
nvc123 #22 - 7 месяцев назад 0
преобразуется как раз в несколько параллельных массивов
и что в этом плохого?
Diaboliko:
пространство которых выделяется под юнитов, попавших под спелл
тут вообще бред
Diaboliko #23 - 7 месяцев назад (отредактировано ) 0
nvc123:
преобразуется как раз в несколько параллельных массивов
и что в этом плохого?
Ятп, что предлагаемое тобой решение заключается в создании нескольких массивов чисто под этот спелл. В прочем, я не до конца понимаю во что превратятся такие структуры в конечном итоге. :>
Дубль 2: Ятп,
nvc123:
2 содержит оставшееся время баффа, даммика который наносит урон и структуру 1 и крепится к юнитам попавшим под спелл
что здесь крепление к юнитам, попавшим под спелл, подразумевает крепление ко всем и сразу, т.е. к группе юнитов внутри структуры, а также обработки этих структур из под единственного таймера. Как раз в этой ситуации я и прибег к своим костылям. Как ты собрался удалять юнита из структуры 1, если он содержится в двух структурах 2(задет двумя кастами)? Как узнать что время действующего на него лжебаффа закончилось во всех структурах 2 типа? Только перебором.
nvc123 #24 - 7 месяцев назад 0
даммиков кстати лучше хранить не во 2 а в 1 структуре
Diaboliko:
Как ты собрался удалять юнита из структуры 1, если он содержится в двух структурах 2(задет двумя кастами)?
перебираем по таймеру все структуры 2 и уменьшаем оставшееся время
если время равно 0 то удаляем экземпляр
Diaboliko:
Как узнать что время действующего на него лжебаффа закончилось во всех структурах 2 типа?
а это зачем?
если бафы от 1 кастера то просто обновляется время
а если от разных то они действую порознь
Diaboliko:
Только перебором
тут как не крути будет перебор всех бафов по таймеру
Diaboliko #25 - 7 месяцев назад (отредактировано ) 0
nvc123, тогда я не понимаю почему ты назвал мое решение кривым. Каким ты увидил принцип работы?
Просто я все больше вижу в твоем решении свое. Подход немного другой, но в целом - я делаю тоже самое. Я храню в массиве из 64 элементов(сохранив ссылку на выделенное пространство там, где надо) информацию о числе задеваний таргета Т1 кастами кастера C1. Прогоняюсь через этот массив каждый раз при непосредственном задевании дабы увеличить или уменьшить счетчик, плюс при проверке на нахождение целей вблизи даммиков для нанесения урона. Уменьшаю этот счетчик при звонке таймера на окончание действие дебаффа(/жизни даммика). Считай тот же отсчет времени дебаффа. Таймер реализован как отдельный поток работы одного глобального, так что использую ресурсы, находящиеся в простОе.
nvc123 #26 - 7 месяцев назад (отредактировано ) 0
Я храню в массиве из 64 элементов(сохранив ссылку на выделенное пространство там, где надо) информацию о числе задеваний таргета Т1 кастами кастера C1. Прогоняюсь через этот массив каждый раз при непосредственном задевании дабы увеличить или уменьшить счетчик, плюс при проверке на нахождение целей вблизи даммиков для нанесения урона
полный бред которого у меня нету и который хз зачем нужен
да и размер массива всегда фиксирован и равен 8192(2 в 13 степени)
Diaboliko:
Таймер реализован как отдельный поток работы одного глобального, так что использую ресурсы, находящиеся в простОе.
это не понял вообще
сколько таймеров(игровых объектов), с каким периодом работают таймеры и каким образом ты реализуешь свои таймеры?
Diaboliko #27 - 7 месяцев назад 0
полный бред которого у меня нету и который хз зачем нужен
да и размер массива всегда фиксирован и равен 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]
nvc123 #28 - 7 месяцев назад (отредактировано ) 0
Кто-то из нас явно понимает другого не-правильно. Либо оба :> Но я вижу в твоем описании свое решение.
как ты можешь видеть своё решение если
полный бред которого у меня нету и который хз зачем нужен
зачем информация о числе задеваний таргета Т1 кастами кастера C1?
зачем ты ставишь 64 если оно всеравно преобразуется в 8192?
твоё решение содержит часть моего + кучу ненужного говна
по поводу твоих "потоков"
кривое дерьмо юзающее кучу триггеров и не имеющее никакого смысла
если будет не лень то завтра напишу этот спелл
Diaboliko #29 - 7 месяцев назад (отредактировано ) 0
зачем ты ставишь 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?
У меня конец времени дебаффа отсчитывается одним из "потоков" таймера, работая аналогично твоему отсчету времени до конца дебаффа. Информация о числе задеваний нужна чтобы из группы всех юнитов, задетых кастом кастера не удалять юнита, если тот содержится еще в какой-то группе(иначе лжедебафф, по-сути, еще активен, но будет снят).
твоё решение содержит часть моего + кучу ненужного говна
На твой взгляд оно, может, и ненужное говно, а в рамках используемых мной систем выглядит весьма адекватным решением.
по поводу твоих "потоков"
кривое дерьмо юзающее кучу триггеров и не имеющее никакого смысла
если будет не лень то завтра напишу этот спелл
Ну почему-же. Решение не кривее использования хэштэйблов. Все переменные сохраняются в глобальных массивах. Мне норм.
darkowlom #30 - 7 месяцев назад 2
Diaboliko, в варкрафте все массивы 8192, то что ты указал 64 ничего не значит, варкрафт все равно выделит 8192
Diaboliko #31 - 7 месяцев назад 0
Diaboliko, в варкрафте все массивы 8192, то что ты указал 64 ничего не значит, варкрафт все равно выделит 8192
А в моей памяти сидит что они сперва имеют какой-то минимальный сайз, выше которого по степени двойки делается realloc.
nvc123 #32 - 7 месяцев назад 0
Diaboliko, указания размера массивам это фича вджасса для создания массивов с размером больше 8192
так что твоё 64 при компиляции попросту исчезает
Maniac_91 #33 - 1 неделю назад 0
Вместо массива-счётчика можно использовать userdata.
pro100master #34 - 1 неделю назад 0
а чем не угодил баф яд который стакает.... оптимальный без изобретении велосипеда