Удивительные вещи происходят в варкрафте. Я разрабатываю карту, есть несколько версий. Я сделал триггер для воскрешения героя после смерти уже давно. Он хорошо работал, проблем не замечал. Из версии в версию триггер не менялся. Но в новой версии возникла проблема, я её сразу не заметил. Тот же самый триггер перестал работать - всего лишь на 2 секунды (хотя должен появляться на 9-20 секунд) появляется таймер (скорее, его диалоговое окно, т.к. никаких действий в таймере не происходит). Герой в итоге не воскрешается, диалоговое окно слишком рано закрывается. Я уже день сижу целый, и не могу понять в чём дело. Искал ошибки, но ничего толком не находил, ничего не помогает.
Так в чём же может быть дело? Прошу найти ошибки в коде. Хэш-таблицу инициализировал при загрузке карты, также было и в прошлых версиях карты, где триггер работал. Если не знаете, в чём проблема, то можно предложить свой вариант кода (только с объяснениями:)). Буду сильно благодарен за помощь.
function Trig_DeadHero_Conditions takes nothing returns boolean
    if ( not ( IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    return true
   // if ( not ( IsUnitAlly(GetDyingUnit(), Player(0)) == true ) ) then
     //   return false
   // endif
   // return true
endfunction

function Deathtimer takes nothing returns nothing
local timer dt1 = GetExpiredTimer()
local integer tid1 = GetHandleId(dt1)
local unit hero1 = LoadUnitHandle(udg_Hash, tid1, 0)
local integer hid1 = GetHandleId(hero1)
local integer ran1 = LoadInteger(udg_Hash, hid1, 2)
local integer c1 = LoadInteger(udg_Hash, tid1, 1)
local timerdialog tdial1 = LoadTimerDialogHandle(udg_Hash, tid1, 2) 
//local real desx = GetRectCenterX(gg_rct_Resivedark)
//local real desy = GetRectCenterY(gg_rct_Resivedark)
call SaveInteger(udg_Hash,tid1,1,c1 + 1)
if c1 >= ran1 then
    call PauseTimer(dt1)
    call DestroyTimer(dt1)
    call DestroyTimerDialog(tdial1)
    if ( IsPlayerAlly(GetOwningPlayer(hero1), Player(0)) == true ) then
       call ReviveHeroLoc( hero1, GetRectCenter(gg_rct_Resiveali), true )
    else
       call ReviveHeroLoc( hero1, GetRectCenter(gg_rct_Resivedark), true )
    endif
    call SelectUnitForPlayerSingle( hero1, GetOwningPlayer(hero1) )
    call FlushChildHashtable(udg_Hash, tid1)
endif
set dt1 = null
set hero1 = null
set tdial1 = null
endfunction

function Trig_DeadHero_Actions takes nothing returns nothing
local unit hero1 = GetDyingUnit()
local integer hid1 = GetHandleId(hero1)
local integer rand1 = GetRandomInt(9, 20)
local timer dt1 = CreateTimer()
local timer det1
local integer tid1 = GetHandleId(dt1)
local timerdialog tdial1
local integer score1 = GetRandomInt(( ( 1 * GetHeroLevel(hero1) ) + 10 ), ( ( 1 * GetHeroLevel(hero1) ) + 20 ))
call AdjustPlayerStateBJ( score1, GetOwningPlayer(GetKillingUnitBJ()), PLAYER_STATE_RESOURCE_FOOD_USED )
call DisplayTextToForce( GetPlayersAll(), ( ( ( udg_Player_Colors[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnitBJ()))] + ( GetPlayerName(GetOwningPlayer(GetKillingUnitBJ())) + "|r" ) ) + ( " убил " + ( ( udg_Player_Colors[GetConvertedPlayerId(GetOwningPlayer(hero1))] + GetPlayerName(GetOwningPlayer(GetDyingUnit())) ) + "|r" ) ) ) + "" ) )
/*if GetUnitTypeId(hero1) == 'H007' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01A',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00G',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01U',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A036',true)
endif
if GetUnitTypeId(hero1) == 'H006' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00B',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02Y',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02D',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A039',true)
endif
if GetUnitTypeId(hero1) == 'O002' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00N',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02W',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01E',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'AHtc',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'Aprg',true)
endif
if GetUnitTypeId(hero1) == 'O003' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A038',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00J',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01M',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00D',true)
endif
if GetUnitTypeId(hero1) == 'H008' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A037',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A008',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00C',true)
endif
if GetUnitTypeId(hero1) == 'E002' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A033',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00W',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00K',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A017',true)
endif
if GetUnitTypeId(hero1) == 'N001' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A007',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00Q',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A005',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'Acyc',true)
endif
if GetUnitTypeId(hero1) == 'H009' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00T',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A03G',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00V',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A009',true)
endif
if GetUnitTypeId(hero1) == 'U00C' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A022',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A015',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A024',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'AOsw',true)
endif
if GetUnitTypeId(hero1) == 'U00D' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A026',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00Y',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A013',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'Adis',true)
endif
if GetUnitTypeId(hero1) == 'U00B' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02X',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00I',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'AOsf',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A03D',true)
endif
if GetUnitTypeId(hero1) == 'U00F' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A030',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'AUcs',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'AUim',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A03C',true)
endif
if GetUnitTypeId(hero1) == 'U00H' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02N',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01Y',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02P',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'Aens',true)
endif
if GetUnitTypeId(hero1) == 'U00G' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01B',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A020',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A021',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A027',true)
endif
if GetUnitTypeId(hero1) == 'U00E' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02S',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02O',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'AEim',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A03F',true)
endif
if GetUnitTypeId(hero1) == 'U005' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A02U',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A016',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01L',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01P',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A03B',true)
endif
if GetUnitTypeId(hero1) == 'U00I' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00E',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01N',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A019',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A010',true)
endif
if GetUnitTypeId(hero1) == 'U00J' then
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A00E',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A01N',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A019',true)
call SetPlayerAbilityAvailable(GetOwningPlayer(hero1),'A010',true)
endif*/
call SaveAgentHandle(udg_Hash, tid1, 0, hero1)
call SaveAgentHandle(udg_Hash, hid1, 0, dt1)
call SaveInteger (udg_Hash, tid1, 1, 1)
call SaveInteger (udg_Hash, hid1, 2, rand1)
call TimerStart( dt1, 1.0, true, function Deathtimer )
set det1 = GetLastCreatedTimerBJ()
call StartTimerBJ(det1, false, rand1 )
call CreateTimerDialogBJ( det1, "drgrd" )
set tdial1 = GetLastCreatedTimerDialogBJ()
call TimerDialogDisplayBJ( false, tdial1 )
call TimerDialogDisplayForPlayerBJ( true, tdial1, GetOwningPlayer(hero1) )
call SaveAgentHandle(udg_Hash, tid1, 2, tdial1)
set det1 = null
set dt1 = null
set hero1 = null
set tdial1 = null
endfunction

function InitTrig_DeadHero3 takes nothing returns nothing
    set gg_trg_DeadHero3 = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_DeadHero3, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_DeadHero3, Condition( function Trig_DeadHero_Conditions ) )
    call TriggerAddAction( gg_trg_DeadHero3, function Trig_DeadHero_Actions )
endfunction

call BJDebugMsg(string) отладка в редакторе.
`
ОЖИДАНИЕ РЕКЛАМЫ...
5
Код не смотрел, но в варкрафте есть баг, даже странновато, что мало афишированный - иногда при смерти герой просто пропадает навсегда.
При обычных условиях это бывает очень-очень редко, но гарантированно, например - если умирает очень много героев одновременно (точное число не помню, кому надо, сами поэкспериментируйте).
Может, какие-то гарантированные условия (эти, или неизвестные мне другие) - в карте и появились.
Выход только один, тяжело, но надо один раз сделать - запоминать все значимые данные героя при его смерти и, если обнаружится, что герой исчез, пересоздавать его.
Вроде и в EWIX и в BFS герои пропадали в очень старых версиях.
21
Pippetz:
Код не смотрел, но в варкрафте есть баг, даже странновато, что мало афишированный - иногда при смерти герой просто пропадает навсегда.
При обычных условиях это бывает очень-очень редко, но гарантированно, например - если умирает очень много героев одновременно (точное число не помню, кому надо, сами поэкспериментируйте).
Может, какие-то гарантированные условия (эти, или неизвестные мне другие) - в карте и появились.
Выход только один, тяжело, но надо один раз сделать - запоминать все значимые данные героя при его смерти и, если обнаружится, что герой исчез, пересоздавать его.
Вроде и в EWIX и в BFS герои пропадали в очень старых версиях.
интересно, но нет, герой даже в первый раз не воскрешается, тем более даже диалоговое окно таймера удаляется раньше времени.
25
Почему такое извращенное условие?
З.Ы: Окно таймера должно отображатся только для владельца героя или еще для кого-то?
28
if ( not ( IsUnitType(GetDyingUnit(), UNIT_TYPE_HERO) == true ) ) then
return false
endif
return true
нефиг юзать хэш и кучу таймеров
21
Ancient:
Почему такое извращенное условие?
В чём извращение?
З.Ы: Окно таймера должно отображатся только для владельца героя или еще для кого-то?
Только для владельца героя
Tobi123:
Сделайте отладку, говорят помогает.
ни разу не делал, но если скажете как, то может быть и стоит попробовать
nvc123:
нефиг юзать хэш и кучу таймеров
О, старый знакомый. Мне припоминается, что вы когда-то скидывали код с таймером, однако я ничего не понял в нём. Может быть ещё раз покажешь? Только прошу объяснить, я уж, надеюсь, пойму, всё-таки последние полгода занимался программированием в институте.
Кстати, почему куча таймеров? Что конкретно не так?
15
ни разу не делал, но если скажете как, то может быть и стоит попробовать
Вставляете дебаг сообщения с различным содержанием в разных кусках кода. Проверяете переменные таким образом и находите ошибку.
21
nvc123:
почитаю, придётся во многом разбираться.
Tobi123:
Вставляете дебаг сообщения с различным содержанием в разных кусках кода. Проверяете переменные таким образом и находите ошибку.
что за дебаг сообщения?
И да, ещё раз обратите внимание, что точно такой же код работал в предыдущих версиях карты.
15
Стратег:
nvc123:
почитаю, придётся во многом разбираться.
Tobi123:
Вставляете дебаг сообщения с различным содержанием в разных кусках кода. Проверяете переменные таким образом и находите ошибку.
что за дебаг сообщения?
И да, ещё раз обратите внимание, что точно такой же код работал в предыдущих версиях карты.
21
Чувак, как я понимаю, в каждой среде программирования отладка запускается по-своему, я без понятия как это сделать в редакторе, и как это будет выглядеть. Не вижу смысла в скинутой тобою ссылке.
21
nvc123:
Стратег, боже
да просто вывод текста на экран
ты про отладку? Так как её запустить?
Во-вторых, посмотрел твою статью, в vjasse, конечно, не шарю ещё, но по примеру сделал своё. Редактор выдаёт ошибку.
Что за проблема?
Загруженные файлы
28
отсутствует конец блока
написано же
просто запускаешь игру и всё
и смотришь что на экран пишет
BJDebugMsg("текст")
21
отсутствует конец блока
написано же
что за блок, и как это исправить?
nvc123:
просто запускаешь игру и всё
и смотришь что на экран пишет
BJDebugMsg("текст")
я такой понимаю встроенной в редактор отладки нет?
15
call BJDebugMsg(string) отладка в редакторе.
Принятый ответ
28
Стратег, встроенной нет
Стратег, закрыть блок
откуда мне знать что за блок ты там создал
21
Стратег, закрыть блок
откуда мне знать что за блок ты там создал
я никакой блок не создавал, это сделал редактор. Я даже не знаю, что это. Я воспользовался лишь тем кодом, на который ты скинул ссылку, я подумал, что такая проблема возникала уже, и ты знаешь ответ.
28
Стратег, блок это в коде
ты вставил код не полностью либо сделал ещё какуюто хрень и не закрыл блок
редактор не умеет создавать блоки
это делает юзер с помощью кода
и вообще
как ты можешь учить программирование когда ты не знаешь что такое блок?
это ведь основа
21
nvc123:
Стратег, блок это в коде
ты вставил код не полностью либо сделал ещё какуюто хрень и не закрыл блок
редактор не умеет создавать блоки
это делает юзер с помощью кода
М, я выключил и включил триггер, при включении мне выдалась следующая ошибка: "Триггер должен содержать функцию инициализации". Не понимаю, что это за функция, что в ней должно быть.
nvc123:
и вообще
как ты можешь учить программирование когда ты не знаешь что такое блок?
это ведь основа
Чувак, я изучаю в институте язык с++, и мы начали с условных операторов, заканчивали функциями, никаких блоков пока не встречалось.
28
Стратег, функция это тоже блок
функция,библиотека,структура,иф,цикл
это всё блоки
блок имеет начало и конец
в сиджасс и с++ начало обозначается {
а конец }
21
nvc123:
Стратег, функция это тоже блок
функция,библиотека,структура,иф,цикл
это всё блоки
блок имеет начало и конец
в сиджасс и с++ начало обозначается {
а конец }
я проверю.
Вообще всем спасибо, ошибки нашёл. Во-первых, значение времени для таймера перестало сохранятся в новой версии карты, а второе - самое забавное, что в способностях одного из героев завалялся триггер, который удаляет определённого воина из игры, когда тот умирает. Но условие сломалось (возможно, удалил воина из редактора), и триггер стал работать для всех юнитов в карте, в том числе и для героев. Поэтому герои не воскрешались, т.к. были удалены из игры.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.