Добавлен , опубликован
Дисклеймер!
Я полный нуб/лох/помойка в джассе (называйте как хотите), ничего толком не знаю и короче юзай систему на свой страх и риск. По возможности буду стараться оптимизировать это говно
Предложения по улучшению пишите в комменты

типичная триггерная система стана, позволяет использовать один стан на всю карту
настолько каловая система стана, что игроки будут оглушены в реальной жизни и не смогут в это говно вообще играть, психанут и разобьют монитор, поэтому лучше вообще ничего не юзать и пойти пить чай
код
library StunSystemLib
globals
    private constant hashtable H = InitHashtable( )
    private constant timer TempTimer = CreateTimer( )
    private constant group TempGroup = CreateGroup( )
    private constant key StunKey
    private unit TempUnit
endglobals

native UnitAlive takes unit id returns boolean

function GetUnitStunTime takes unit u returns real
    return LoadReal( H, GetHandleId( u ), StunKey )
endfunction

function SetUnitStunTime takes unit u, real time returns nothing
	call SaveReal( H, GetHandleId( u ), StunKey, time )
endfunction

private function CheckStunTime_1 takes nothing returns nothing
    local unit u = GetEnumUnit( )
    local real r = LoadReal( H, GetHandleId( u ), StunKey ) - 0.01
    
    if r <= 0.00 or not UnitAlive( u ) then
        call UnitRemoveAbility( u, 'BPSE' ) // дебафф стану
        call RemoveSavedReal( H, GetHandleId( u ), StunKey )
        call GroupRemoveUnit( TempGroup, u )
    else
        call SaveReal( H, GetHandleId( u ), StunKey, r )
    endif
    
    set u = null
endfunction

private function CheckStunTime takes nothing returns nothing
    call ForGroup( TempGroup, function CheckStunTime_1 )
    
    if FirstOfGroup( TempGroup ) == null then
        call PauseTimer( TempTimer )
    endif
endfunction

function StunUnit takes unit u, real time returns nothing
    call IssueTargetOrder( TempUnit, "thunderbolt", u ) // приказ
    
    if FirstOfGroup( TempGroup ) == null then
        call TimerStart( TempTimer, 0.01, true, function CheckStunTime )
    endif
    
    if time > LoadReal( H, GetHandleId( u ), StunKey ) then
        call SaveReal( H, GetHandleId( u ), StunKey, time )
        call GroupAddUnit( TempGroup, u )
    endif
endfunction

//===========================================================================
function InitTrig_StunSystem takes nothing returns nothing
    //set gg_trg_StunSystem = CreateTrigger(  )
    set TempUnit = CreateUnit( Player( PLAYER_NEUTRAL_PASSIVE ), 'u000', 0.00, 0.00, 0.00 ) // дамі
endfunction
endlibrary



прикладываю так же карту с демонстрацией помойного кастомного стана на таких же помойных говноабилках

если лень смотреть, то распишу на словах
с кастомным станом можно сделать продолжительность оглушения например от какой-нибудь арвтгграптсч
кхм, характеристики героя, за 100 ед силы +0.10 секунд к стану, от какого-то времени можно взять зависимость, можно сделать, что если происходит серия станов, ослаблять последующие на 20%, через время снимать бафф к устойчивости станов, чтобы не стоять в контроле всю жизнь, в общем много идей, но лучшая, это чтобы я застрелился
самому молотку бурь нужно поставить длительность максимального возможного стана в карте выставить нулевое значение продолжительности стана
чтобы использовать, достаточно прописать в кастомскрипте StunUnit( какой юнит, время ), помимо этого есть функция GetUnitStunTime( какой юнит ), возвращающая значение оставшегося стана

upd
добавил в код функцию изменения продолжительности текущего стана SetUnitStunTime, первый аргумент юнит, второй - время (не проверял работоспособность)
updd
исправил пару багов с примерами

upd 13.09.2022 оптимизировал стан даммиком, теперь понял как использовать одного даммика для одновременного стана нескольких целей, игрока указывать больше не нужно, даммик принадлежит нейтралу который и так видит всю карту

upd 05.10.2022
забыл добавить последнюю функцию в код выше, поправил

upd 14.10.2022
максимальное время возможного стана не нужно указывать молотку, достаточно вписать нулевое значение, поправлен пример

upd 15.10.2022
добавил дисклеймер
`
ОЖИДАНИЕ РЕКЛАМЫ...
2
17
2 года назад
2
Если
  1. Застанить героя на минуту
  2. Через 2 секунды снять бафф стана
  3. Попытаться застанить на 5 секунд, то застанит на 58 секунд
1
27
2 года назад
1
Vlod, действительно, попробовал побороть но не получилось)
возможно только кастомное снятие придётся делать, чтобы вместе со снятием обнулять время
думал просто в периодик закинуть, но это не то, а при получении урона всё равно нужна нулевая задержка на отключение триггера, пока даммик застанит, чтобы не снимать стан сразу при его получении, что тоже нехорошо
1
27
2 года назад
1
по хорошему, нужно просто выбросить эту "наработку", если так можно вообще выразиться (нет), и
пойти пить чай
0
29
2 года назад
0
Если стан кастуется через молоток, почему даммик не двигается под цель заклинания?
Хэштаблица на каждое заклинание это плохо, лучше использовать одну глобальную, резервируя ключи на каждое заклинание.
Таймер лучше вешать прям на хэндл юнита и не заморачиваться с группами.
Одним словом довольно странная реализация довольно банальной задачи.
0
27
2 года назад
Отредактирован rsfghd
0
Если стан кастуется через молоток, почему даммик не двигается под цель заклинания?
потому что можно выставить радиус, соответствующий карте?
nazarpunk:
Хэштаблица на каждое заклинание это плохо, лучше использовать одну глобальную, резервируя ключи на каждое заклинание.
спокойно можно убрать строку с хэштаблицей и автозаменой пройтись, подставив свою, если названия не совпадают, у меня одна глобальная хэштаблица, но есть некоторые исключения
как видишь, ключ уже есть, но если до этого работа с юнитами не была через ключи вджасса, то лучше само собой вместо key подставить integer и вписать своё число, короче это больше в силу возможностей импортирующего человека зависит, банальные знания джасса в принципе, хотя тем, кому оно бы пригодилось, джасс вероятно не знают
nazarpunk:
Таймер лучше вешать прям на хэндл юнита и не заморачиваться с группами.
я не знал что лучше, таймера на каждого юнита или один таймер с группой, выбрал второе
nazarpunk:
Одним словом довольно странная реализация довольно банальной задачи.
rsfghd:
типичная триггерная система стана, позволяет использовать один стан на всю карту
настолько каловая система стана, что игроки будут оглушены в реальной жизни и не смогут в это говно вообще играть, психанут и разобьют монитор, поэтому лучше вообще ничего не юзать и пойти пить чай
я и не хвастался этим помойным ресурсом, поэтому оно и лежит в блоге и даже не заявлялось на публикацию, ты хочешь чтобы я это попросил в бездну закинуть из моего блога?)

я понимаю твоё недовольство, но на данный момент интересует факт в чём группа хуже, переделаю на таймера
0
29
2 года назад
0
потому что можно выставить радиус, соответствующий карте?
У молотка скорость полёта как-бы есть, и если он вылетит прям по цели, то сразу стриггерит стан.
спокойно можно убрать строку с хэштаблицей и автозаменой пройтись, подставив свою
Если в дизайне присутвует автозамена, то с дизайном явно что-то не так.
хотя тем, кому оно бы пригодилось, джасс вероятно не знают
Почему это? Иногда проще импортировать оттестированную либу и ставить её в зависимость, чем каждый раз писать свою.
я не знал что лучше, таймера на каждого юнита или один таймер с группой, выбрал второе
Таймер на каждого юнита лучше, ибо к нему поверх всего можно ещё данных прикрутить. В идеале вообще на таймер вешать struct и хранить всё в ней, а хэштаблицы использовать только для привязки структуры к таймеру.
я и не хвастался этим помойным ресурсом
Упоминание через каждые два слова "помойности" ресурса не оправдывает качество кода.

Система довольно таки простая. Переписать её на zinc со структурами, вывести хэштаблицу в глобал ивыложить как наработку. Так можно получить больше обЪективной критики и научиться писать более качественный код, а не прятаться за отмазками о "помойности".
0
27
2 года назад
0
У молотка скорость полёта как-бы есть, и если он вылетит прям по цели, то сразу стриггерит стан.
у молотка скорость нулевая, но он же долетает?
SetUnitFlyHeight, если выставить третий аргумент на 0.00, тоже ведь изменит свою высоту мгновенно? ты уверен что знаешь механику?
nazarpunk:
Если в дизайне присутвует автозамена, то с дизайном явно что-то не так.
предлагай в таком случае как решить вопрос двух хэштаблиц с разным названием у пользователя
я должен как-то предугадывать название у человека?
nazarpunk:
Таймер на каждого юнита лучше, ибо к нему поверх всего можно ещё данных прикрутить. В идеале вообще на таймер вешать struct и хранить всё в ней, а хэштаблицы использовать только для привязки структуры к таймеру.
зачем мне в этой системе прикручивать другие параметры? зачем мне структуры для одного параметра? ты не про библиотеку и её назначение говоришь, а уже за реальные возможности другого кодера и насколько просто это интегрировать будет для его работы
nazarpunk:
Упоминание через каждые два слова "помойности" ресурса не оправдывает качество кода.
чего? может в том то и дело, что я говорю, что он не качественный, не претендует ни на что, что можно тупо забить, где я оправдываю качество кода если он говно? я говорил что ресурс говно а то что внутри нет?
nazarpunk:
Система довольно таки простая. Переписать её на zinc со структурами, вывести хэштаблицу в глобал ивыложить как наработку.
система простая, для кодеров, да
а дальше чушь пошла, чтобы использовать конкретно мою хэштаблицу как глобальную, нужно как минимум 2 ресурса моих закинуть, чтобы был реальный профит, и тем не менее, человек может закидывать много других ресурсов от разных авторов где хэштаблицы с разными названиями, но выполняют одну и ту же функцию, например, привязка к таймеру данных, автозамена тут необходима, если не хочешь плодить хэштаблицы
nazarpunk:
Так можно получить больше обЪективной критики и научиться писать более качественный код, а не прятаться за отмазками о "помойности".
твоя "обЪективная" критика завязана на субъективном мышлении, где каждый случай уникален, одному нужны структуры, кто-то делает всё на одной структуре и хранит её в юните, а кто-то не юзает и даже не знает что это такое, у второго может быть другая хэштаблица с другим названием уже, ты говоришь про удобство работы для кодеров, хотя кодерам оно нафиг не нужно, ибо сделают они это за пару минут и интегрируют куда надо вместе с этим, я же сделал в первую очередь для гуишников и показал варианты применения в карте, где используется гуи, где достаточно в кастомскрипте указать переменную юнита и время, вот и всё, практически так же легко как и кастомскриптное call RemoveLocation( udg_loc )
2
27
2 года назад
2
вот что я нашёл вбив "система стана" в поиск хгма
и минусы на мой субъективный взгляд, которые можно и объективно вынести
  1. сджасс, особенно с дефайнами, стрёмная вещь ибо иногда ты вообще ничерта не можешь разобрать где ошибка, потому что компилятор сам без понятия, пол часа будешь искать если не психанёшь
  2. ненужная функция CastTarget, использующая игрока, у меня была, но я выпилил
  3. проверка неуязвимости юнита через функцию Invuled, тоже бесполезно, у меня в примере можно дать неуязвимость юнитам и всё спокойно работает
  4. стан нельзя наложить друг на друга, будет работать только самый первый, потому что каждый раз запускается новый таймер, удаляющий дебафф стана через время
  5. нельзя настроить время стана
  6. нельзя достать время стана
  7. структура, имеющая лишь одно значение, юнита - бесполезно
  8. вообще что эта система зачем-то сделана на структуре, в коде оно всяко будет выглядеть хуже моего примера на вджассе
вот пример его кода скомпилированного и моего
его
//JASSHelper struct globals:
constant integer si__StunSystem___Data=1
integer si__StunSystem___Data_F=0
integer si__StunSystem___Data_I=0
integer array si__StunSystem___Data_V
hashtable s__StunSystem___Data_HashTable=InitHashtable()
unit array s__StunSystem___Data_target

endglobals


//Generated allocator of StunSystem___Data
function s__StunSystem___Data__allocate takes nothing returns integer
 local integer this=si__StunSystem___Data_F
    if (this!=0) then
        set si__StunSystem___Data_F=si__StunSystem___Data_V[this]
    else
        set si__StunSystem___Data_I=si__StunSystem___Data_I+1
        set this=si__StunSystem___Data_I
    endif
    if (this>8190) then
        call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,1000.,"Unable to allocate id for an object of type: StunSystem___Data")
        return 0
    endif

   set s__StunSystem___Data_target[this]=null
    set si__StunSystem___Data_V[this]=-1
 return this
endfunction

//Generated destructor of StunSystem___Data
function s__StunSystem___Data_deallocate takes integer this returns nothing
    if this==null then
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,1000.,"Attempt to destroy a null struct of type: StunSystem___Data")
        return
    elseif (si__StunSystem___Data_V[this]!=-1) then
            call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,1000.,"Double free of type: StunSystem___Data")
        return
    endif
    set si__StunSystem___Data_V[this]=si__StunSystem___Data_F
    set si__StunSystem___Data_F=this
endfunction

//library cjLib75hJKJ374s4e597nba9o7w45gf:
function cj_group_copy_75hJKJ3745gf takes nothing returns nothing
//# optional
call GroupAddUnit(cj_tmpgr_copy_nw509ert7, GetEnumUnit())
endfunction

//library cjLib75hJKJ374s4e597nba9o7w45gf ends
//library StunSystem:
function s__StunSystem___Data_CastTarget takes player p,unit u returns nothing
local unit DummyCaster=CreateUnit(p, 0x75303030, GetUnitX(u), GetUnitY(u), 0)
call IssueTargetOrder(DummyCaster, "thunderbolt", u)
call UnitApplyTimedLife(DummyCaster, 0, 1.00)
set DummyCaster=null
endfunction
function s__StunSystem___Data_Invuled takes unit u returns boolean
local real HP=GetWidgetLife(u)
local real MP=GetUnitState(u, UNIT_STATE_MANA)
local boolean res
call SetWidgetLife(u, HP + 0.001)
if ( HP != GetWidgetLife(u) ) then
call UnitDamageTarget(u, u, 0.001, false, true, null, null, null)
set res=( GetWidgetLife(u) == HP + 0.001 )
else
call UnitDamageTarget(u, u, 0.001, false, true, null, null, null)
set res=( GetWidgetLife(u) == HP )
call SetWidgetLife(u, HP)
endif
if ( res ) then
return not ( GetUnitState(u, UNIT_STATE_MANA) != MP )
endif
return res
endfunction
function s__StunSystem___Data_onEffect takes nothing returns nothing
local timer TIMER=GetExpiredTimer()
local integer DATA=LoadInteger(s__StunSystem___Data_HashTable, GetHandleId(TIMER), 0)
call UnitRemoveAbility(s__StunSystem___Data_target[DATA], 0x42303030)
call FlushChildHashtable(s__StunSystem___Data_HashTable, GetHandleId(TIMER))
call DestroyTimer(TIMER)
set TIMER=null
endfunction
function s__StunSystem___Data_onStun takes unit u,real dur returns nothing
local timer TIMER=CreateTimer()
local integer DATA=s__StunSystem___Data__allocate()
set s__StunSystem___Data_target[DATA]=u
if ( s__StunSystem___Data_Invuled(u) ) then
call SetUnitInvulnerable(u, false)
call s__StunSystem___Data_CastTarget(Player(15) , u)
call SetUnitInvulnerable(u, true)
else
call s__StunSystem___Data_CastTarget(Player(15) , u)
endif
call SaveInteger(s__StunSystem___Data_HashTable, GetHandleId(TIMER), 0, DATA)
call TimerStart(TIMER, dur, false, function s__StunSystem___Data_onEffect)
set TIMER=null
endfunction
function StunUnit takes unit u,real dur returns nothing
call s__StunSystem___Data_onStun(u , dur)
endfunction

//library StunSystem ends
мой
//JASSHelper struct globals:

endglobals
native UnitAlive takes unit id returns boolean


//library StunSystemLib:



function GetUnitStunTime takes unit u returns real
    return LoadReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey)
endfunction

function SetUnitStunTime takes unit u,real time returns nothing
	call SaveReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey, time)
endfunction

function StunSystemLib__CheckStunTime_1 takes nothing returns nothing
    local unit u= GetEnumUnit()
    local real r= LoadReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey) - 0.01
    
    if r <= 0.00 or not UnitAlive(u) then
        call UnitRemoveAbility(u, 'BPSE') // дебафф стану
        call RemoveSavedReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey)
        call GroupRemoveUnit(StunSystemLib__TempGroup, u)
    else
        call SaveReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey, r)
    endif
    
    set u=null
endfunction

function StunSystemLib__CheckStunTime takes nothing returns nothing
    call ForGroup(StunSystemLib__TempGroup, function StunSystemLib__CheckStunTime_1)
    
    if FirstOfGroup(StunSystemLib__TempGroup) == null then
        call PauseTimer(StunSystemLib__TempTimer)
    endif
endfunction

function StunUnit takes unit u,real time returns nothing
    call IssueTargetOrder(StunSystemLib__TempUnit, "thunderbolt", u) // приказ
    
    if FirstOfGroup(StunSystemLib__TempGroup) == null then
        call TimerStart(StunSystemLib__TempTimer, 0.01, true, function StunSystemLib__CheckStunTime)
    endif
    
    if time > LoadReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey) then
        call SaveReal(StunSystemLib__H, GetHandleId(u), StunSystemLib__StunKey, time)
        call GroupAddUnit(StunSystemLib__TempGroup, u)
    endif
endfunction

//===========================================================================
function InitTrig_StunSystem takes nothing returns nothing
    //set gg_trg_StunSystem = CreateTrigger(  )
    set StunSystemLib__TempUnit=CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'u000', 0.00, 0.00, 0.00) // дамі
endfunction

//library StunSystemLib ends
Vlod дал объективную, реальную оценку имеющейся проблемы, и вероятно он знал об этом с самого начала, я согласился, что решить это не смогу, поэтому предложил альтернативу решения, которая всё равно может не устроить, я извиняюсь за это - можете предложить как исправить если реально
ты же напротив, дал субъективную оценку, выдавая её за объективную, помимо этого вероятно не знал о механике нулевого времени, как и я собственно, посмотрев вышеуказанный ресурс, где время стана вообще стоит на 0.00, так что я поправлю это в своём примере
если бы ты даже вышеупомянутую мелочь назвал, что так можно, было бы намного больше пользы чем от всего остального, ибо ты назвал бы прямое упрощение и открыл новую механику для меня
а не очевидные вещи вроде этого:
nazarpunk:
Хэштаблица на каждое заклинание это плохо, лучше использовать одну глобальную, резервируя ключи на каждое заклинание.
и субъективные вроде этого
nazarpunk:
Таймер на каждого юнита лучше, ибо к нему поверх всего можно ещё данных прикрутить. В идеале вообще на таймер вешать struct и хранить всё в ней, а хэштаблицы использовать только для привязки структуры к таймеру.
0
27
2 года назад
0
кстати, в дополнение к первому пункту, на рефе встроенного сджасса нет

про зинк не знаю

5 пункт перефразирую, нельзя настроить время уже наложенного стана*
сама функция стана работает само собой

а не прятаться за отмазками о "помойности".
это не отмазки, а факт.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.