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