function MC_Timer takes nothing returns nothing local timer t = GetExpiredTimer() local integer i = LoadInteger(D,GetHandleId(t),0) local real r = LoadReal(D,GetHandleId(t),1) local location l0 = LoadLocationHandle(D,GetHandleId(t),2) local location l1 = LoadLocationHandle(D,GetHandleId(t),3) local location l2 local unit u = LoadUnitHandle(D,GetHandleId(t),4) if (i >= 18) then call DestroyTimer(t) else set r = r + 38.00 set l2 = PolarProjectionBJ(l1, r, AngleBetweenPoints(l1, l0)) set u = CreateUnitAtLoc(GetOwningPlayer(GetSpellAbilityUnit()), 'h003', l2, AngleBetweenPoints(l1, l0)) set i = i + 1 call SaveInteger(D,GetHandleId(t),0,i) call SaveReal(D,GetHandleId(t),1,r) call SaveLocationHandle(D,GetHandleId(t),2,l0) call SaveLocationHandle(D,GetHandleId(t),3,l1) call SaveUnitHandle(D,GetHandleId(t),4,u) endif endfunction
function Trig_Spell_MC_Actions takes nothing returns nothing local timer t = CreateTimer() local real r = 0 local location l0 = GetSpellTargetLoc() local location l1 = GetUnitLoc(GetSpellAbilityUnit()) local unit u = null loop exitwhen r == 0.30 set r = r + 0.10 call TriggerSleepAction(0.10) endloop set r = 0 call SaveInteger(D,GetHandleId(t),0,0) call SaveReal(D,GetHandleId(t),1,r) call SaveLocationHandle(D,GetHandleId(t),2,l0) call SaveLocationHandle(D,GetHandleId(t),3,l1) call SaveUnitHandle(D,GetHandleId(t),4,u) call TimerStart(t,0.06,true,function MC_Timer) endfunction
Понял что когда дело доходит до создания дамми(h003), триггер пропускает это действие, а если поставить создание спецэффекта, то всё нормально работает. В чём проблема?
Сообщение отредактировал Titans - Вторник, 28 Июня 2011, 15:16:22
Это недоделанный код, обычно когда весь код готов, тогда я занимаюсь устранением бж и оптимизацией.
Зачем мучиться, когда это можно делать по ходу. Вместо тех же локаций куда быстрее использовать координаты х/у; слипэкшн в цикле категорически нельзя использовать, хотя его вообще лучше не использовать (таймеры работают безотказно); каждое выполнение сохранять в одни и те же ячейки одни и те же значения не нужно, они там и так будут висеть до удаления. Полярки - еще одна беда. Вместо них лучше использовать х/у координаты и угол наклона, применяя простейшие знания тригонометрии (синусы-косинусы). Ну обнуления всех переменных, наследуемых от типа handle сразу по ходу в конце функции надо делать, ибо оставляют утечки. Также при уничтожении таймера сперва чисти все записи в хештейбле, ибо опять же утечки.
Почему, что в нём плохого кроме того что нельзя задавать значения ниже 0.1 и время в нём странное?
Потому что он работает через зад, с ним багов хоть отбавляй. К тому же в цикле он вообще неправильно работает.
Quote (Titans)
Как я понял если запустить два таймера, то они работают одновременно?
Если создаешь 2 разных таймера - будут работать одновременно. Например
Code
... local timer t = CreateTimer() call SaveUnitHandle(ht, GetHandleId(t), 1, blablabla) call TimerStart(t, .5, true, function blablabla) set t = CreateTimer() call SaveUnitHandle(ht, GetHandleId(t), 1, blabla2) call TimerStart(t, .5, true, function blablabla) set t = null ...
Таким способом запустится два таймера. Если нужно сохранить что-то в хт к первому таймеру - делай это до присваивания переменной второго значения (то есть нового таймера), как в примере сохраняется юнит.
Хеш тейбл по умолчанию ужасен. Вообще не пойму нафиг его юзать. При написании больших и сложных систем с большими объемами данными хт сильно уступает в производительности массивам с прямой адресацией.
О нас думают плохо лишь те, кто хуже нас, а те кто лучше нас... Им просто не до нас. My Project: Nindogatari MAL
Что это значит? И почему второй таймер не запускается? (Точнее запускается но медлено)
Code
globals hashtable h = InitHashtable() endglobals
function T03 takes nothing returns nothing local timer t = GetExpiredTimer() local unit u local integer i = LoadInteger(h,GetHandleId(t),1) if i == 0 then call FlushChildHashtable(h, GetHandleId(t)) call DestroyTimer(t) set i = 0 else set u = LoadUnitHandle(h,GetHandleId(t),0) set i = i - 1 call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) + 2 )) call SaveInteger(h,GetHandleId(t),1,i) set u = null set i = 0 endif endfunction
function T02 takes nothing returns nothing local timer t = GetExpiredTimer() local unit u = LoadUnitHandle(h,GetHandleId(t),0) local integer i = LoadInteger(h,GetHandleId(t),1) if i == 250 then call FlushChildHashtable(h, GetHandleId(t)) call DestroyTimer(t) set t = CreateTimer() call SaveUnitHandle(h,GetHandleId(t),0,u) call SaveInteger(h,GetHandleId(t),1,i) call TimerStart(t,0.2,true,function T03) set t = null set u = null set i = 0 else set i = i + 1 call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) - 2 )) if GetUnitState(u, UNIT_STATE_LIFE) != 0 then call SaveInteger(h,GetHandleId(t),1,i) set u = null set i = 0 else call FlushChildHashtable(h, GetHandleId(t)) call DestroyTimer(t) call TransmissionFromUnitWithNameBJ( bj_FORCE_ALL_PLAYERS, u, GetUnitName(u), null, "мёртв", bj_TIMETYPE_ADD, 0, true ) set u = null set i = 0 endif endif endfunction
function T01 takes nothing returns nothing local timer t = CreateTimer() call SaveUnitHandle(h,GetHandleId(t),0,GetEnumUnit()) call SaveInteger(h,GetHandleId(t),1,0) call TimerStart(t,0.02,true,function T02) set t = null endfunction
function Trig_T00_Actions takes nothing returns nothing call ForGroup( GetUnitsSelectedAll(Player(0)), function T01 ) endfunction
//=========================================================================== function InitTrig_T00 takes nothing returns nothing set gg_trg_T00 = CreateTrigger( ) call TriggerRegisterPlayerChatEvent( gg_trg_T00, Player(0), "t", true ) call TriggerAddAction( gg_trg_T00, function Trig_T00_Actions ) endfunction
Сообщение отредактировал Titans - Среда, 29 Июня 2011, 14:31:41
Чем больше значений в ХТ, тем медленнее он массивов, т.к. ХТ требует времени на "поиск" нужной ячейки в таблице, и на сколько я знаю, даже после нахождения нужного значения продолжается поиск(хз зачем). В массивах же нет этого "поиска", а идет обращение на прямую.
Разница "на глаз" не заметна, однако я предполагаю что в глобальном проекте будет заметно, если в хт будут хранится сотни тысяч значений. Отмечу, что эта цифра в серьезном проекте очень быстро достигается=) У меня только в квестах уже задействовано 5к+ значений=)
Ну и еще есть слух, что большой объем данных ХТ не держит, типо фаталы будут.
О нас думают плохо лишь те, кто хуже нас, а те кто лучше нас... Им просто не до нас. My Project: Nindogatari MAL
function T02 takes unit u0 returns nothing local unit u = u0 call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) - 2 )) if GetUnitState(u, UNIT_STATE_LIFE) != 0 then set u = null else call TransmissionFromUnitWithNameBJ( bj_FORCE_ALL_PLAYERS, u, GetUnitName(u), null, "мёртв", bj_TIMETYPE_ADD, 0, true ) set u = null endif endfunction
function T01 takes nothing returns nothing local timer t local integer i = 0 loop exitwhen i == 250 set t = CreateTimer() set i = i + 1 call T02(GetEnumUnit()) call TimerStart(t,0.02,false,null) call DestroyTimer(t) endloop set t = null endfunction
function T03 takes nothing returns nothing local timer t = GetExpiredTimer() local unit u local integer i = LoadInteger(h,GetHandleId(t),1) if i == 0 then call FlushChildHashtable(h, GetHandleId(t)) call DestroyTimer(t) set i = 0 else set u = LoadUnitHandle(h,GetHandleId(t),0) set i = i - 1 call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) + 2 )) call SaveInteger(h,GetHandleId(t),1,i) set u = null set i = 0 endif endfunction
function T02 takes nothing returns nothing local timer t = GetExpiredTimer() local unit u = LoadUnitHandle(h,GetHandleId(t),0) local integer i = LoadInteger(h,GetHandleId(t),1) if i == 250 then call FlushChildHashtable(h, GetHandleId(t)) call DestroyTimer(t) set t = CreateTimer() call SaveUnitHandle(h,GetHandleId(t),0,u) call SaveInteger(h,GetHandleId(t),1,i) call TimerStart(t,0.2,true,function T03) set t = null set u = null set i = 0 else set i = i + 1 call SetUnitState(u, UNIT_STATE_LIFE, ( GetUnitState(u, UNIT_STATE_LIFE) - 2 )) if GetUnitState(u, UNIT_STATE_LIFE) != 0 then call SaveInteger(h,GetHandleId(t),1,i) set u = null set i = 0 else call FlushChildHashtable(h, GetHandleId(t)) call DestroyTimer(t) call TransmissionFromUnitWithNameBJ( bj_FORCE_ALL_PLAYERS, u, GetUnitName(u), null, "мёртв", bj_TIMETYPE_ADD, 0, true ) set u = null set i = 0 endif endif endfunction
function T01 takes nothing returns nothing local timer t = CreateTimer() call SaveUnitHandle(h,GetHandleId(t),0,GetEnumUnit()) call SaveInteger(h,GetHandleId(t),1,0) call TimerStart(t,0.02,true,function T02) set t = null endfunction
function Trig_T00_Actions takes nothing returns nothing call ForGroup( GetUnitsSelectedAll(Player(0)), function T01 ) endfunction
Сообщение отредактировал Titans - Среда, 29 Июня 2011, 16:19:59
На будующее, нужно обнулять только то что имеет хендл\агент, инты, реальные, булевые значения не нужно обнулять, т.к. они не имеют хендла или агента.
В коде ошибок явных не вижу, но логика алгоритма не ясна, но вероятно суть в том, что либо не верный эвент, т.е. вообще алгоритм не срабатывает, либо из за того что ты уничтожаешь таймер. В общем юзай BJDebugMsg, поможет.
1 утечка небольшая есть.
О нас думают плохо лишь те, кто хуже нас, а те кто лучше нас... Им просто не до нас. My Project: Nindogatari MAL
что либо не верный эвент, т.е. вообще алгоритм не срабатывает
Не дело в том что пишиш в игре сообщение "t" и у всех выделеных инитов отнимаются жизни и кто выжил тому возращяются жизни, но как отнимание жизней заканчивается, должен запуститься другой таймер на прибавку жизней, в игре они вродебы прибавляются, но с очень маленькой скоростью. (Можно подумать что реген чють больше стал)
Не дело в том что пишиш в игре сообщение "t" и у всех выделеных инитов отнимаются жизни и кто выжил тому возращяются жизни, но как отнимание жизней заканчивается, должен запуститься другой таймер на прибавку жизней, в игре они вродебы прибавляются, но с очень маленькой скоростью. (Можно подумать что реген чють больше стал)