XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Elf_Stratigo

offline
Опыт: 4,699
Активность:
Зависшие снаряды
Здравствуйте, очень давно создавал аналогичную тему, напомню смысл: иногда некоторые снаряды "зависают", тогда мне предложили альтернативную систему. Но к сожалению баг не пропал. Но поскольку мне не удавалось смоделировать условия, чтобы чудо случилось во время отладки, а не в самой игре - баг происходил довольно редко - то решил закрыть глаза.
Но вот совершенно случайно удалось обнаружить некоторую закономерность. Однако хотя вроде всё проверил, причина всё ещё утаивается. Прошу подсказать мне где искать проблему.

Текущий код:
» код системы
Код:
globals
    unit array AMS_arrows
    unit AMS_dunit
    boolexpr AMS_targets
    integer AMS_arrows_count=0
endglobals

group AMS_move_en = CreateGroup()
function AMS_move takes nothing returns nothing
integer i=0
local real ang
local real x
local real y
    DisplayTextToPlayer(GetLocalPlayer(),0.,0.,I2S(AMS_arrows_count))
    loop
        exitwhen i>=AMS_arrows_count
        AMS_dunit=AMS_arrows[i]
        ang=GetUnitFacing(AMS_dunit)*bj_DEGTORAD
        x=GetUnitX(AMS_dunit)
        y=GetUnitY(AMS_dunit)
        GroupEnumUnitsInRange(AMS_move_en, x, y, 30., AMS_targets)
        ForGroup(AMS_move_en, function ArrowMoveFuncStrike)
        GroupClear(AMS_move_en)
        if RectContainsCoords(bj_mapInitialPlayableArea, x, y) and GetWidgetLife(AMS_dunit) > 0.405 then
            SetUnitX(AMS_dunit,x+GetUnitState(AMS_dunit, UNIT_STATE_MANA)*Cos(ang))
            SetUnitY(AMS_dunit,y+GetUnitState(AMS_dunit, UNIT_STATE_MANA)*Sin(ang))
            ang=GetWidgetLife(AMS_dunit)-GetUnitState(AMS_dunit, UNIT_STATE_MANA)
            if ang<=.405 then
                KillUnit(AMS_dunit)
                DisplayTextToPlayer(GetLocalPlayer(),0.,0.,"exs1")
                AMS_arrows_count--
                AMS_arrows[i]=AMS_arrows[AMS_arrows_count]
            else
                SetWidgetLife(AMS_dunit,ang)
                i++
            endif
        else
            KillUnit(AMS_dunit)
            DisplayTextToPlayer(GetLocalPlayer(),0.,0.,"exs2 "+GetUnitName(AMS_dunit))
            AMS_arrows_count--
            AMS_arrows[i]=AMS_arrows[AMS_arrows_count]
            i++
        endif
    endloop
endfunction

function LaunchArrow takes unit whichUnit, real speed, real dist returns nothing
local integer ind = GetConvertedPlayerId(GetOwningPlayer(whichUnit))
    call SetUnitState(whichUnit, UNIT_STATE_LIFE, dist*udg_AMR[ind])
    call SetUnitState(whichUnit, UNIT_STATE_MANA, speed*udg_AMS[ind])
    AMS_arrows[AMS_arrows_count]=whichUnit
    AMS_arrows_count++
    debug DisplayTextToPlayer(GetLocalPlayer(),0.,0.,"LaunchArrow: "+I2S(AMS_arrows_count)+" "+GetUnitName(whichUnit)+" "+R2S(GetUnitState(whichUnit, UNIT_STATE_LIFE))+" "+R2S(GetUnitState(whichUnit, UNIT_STATE_MANA)))
endfunction


AMS_move лежит в постоянном таймере
запуск снарядов происходит через LaunchArrow

выложил не все функции - считаю, что ошибка не здесь - это из "причин" когда стрела застревает:
1) это может произойти только (не могу гарантировать, но у меня только так получилось) в первые две минуты
2) необходимо первой стрелой убить вражеского героя, тогда при втором выстреле стрела застревает
3) если выполнить операцию 2 после двух минут игры - всё уже хорошо
4) AMS_move сообщает exs2 в первом вызове после выстрела зависшей стрелой, но стрела определённо на карте
5) провёл тест: выводил имя юнита во время запуска и после "должного уничтожения" - LaunchArrow успешна, а вот AMS_move сообщает просто exs2, т.е. хендл снаряда потерян
6) проверил места обращения к переменным AMS_arrows и AMS_arrows_count - это только эти две функции (извлёк весь код и в блокноте - поиск слов)

собственно хочу только чтобы вы мне подсказали, где искать причину, поскольку сам догадаться не могу,
если нужен ещё какой отрывок - напишите, выложу
всю карту просто не думаю, что есть смысл выкладывать

просто совсем не знаю, из-за чего происходит баг :(
Старый 06.07.2010, 13:41
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Elf_Stratigo:
endglobals
group AMS_move_en = CreateGroup()
function AMS_move takes nothing returns nothing
пардон, но когда это можно было объявлять переменные вне функций или раздела globals? O_o
Старый 06.07.2010, 15:42
Elf_Stratigo

offline
Опыт: 4,699
Активность:
ой, забыл сказать, это смесь обычного jass с cjass

писал когда ещё не было cjass, а щас некоторые "улучшения" ввожу уже с ним
Старый 06.07.2010, 15:54
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Elf_Stratigo, если честно, то код жесток..По-хорошему, если срабатывает вот этот участок кода
  if ang<=.405 then
                KillUnit(AMS_dunit)
                DisplayTextToPlayer(GetLocalPlayer(),0.,0.,"exs1")
                AMS_arrows_count--
                AMS_arrows[i]=AMS_arrows[AMS_arrows_count]
и представим, что i = 5, а AMS_arrows_count = 10, получим потерю 10 стрелы. Я бы посоветовал поменять местами 2 последние строчки данного кода и то же самое сделать в
 else
            KillUnit(AMS_dunit)
            DisplayTextToPlayer(GetLocalPlayer(),0.,0.,"exs2 "+GetUnitName(AMS_dunit))
            AMS_arrows_count--
            AMS_arrows[i]=AMS_arrows[AMS_arrows_count]
            i++
        endif
Старый 06.07.2010, 16:15
Elf_Stratigo

offline
Опыт: 4,699
Активность:
нумерация идёт с нуля (integer AMS_arrows_count=0),
AMS_arrows[AMS_arrows_count]==null при AMS_arrows_count=10

здесь идея верная)
допустим: i = 5, AMS_arrows_count = 10
значит сейчас массив AMS_arrows представим как (u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,null,...) - всего 10 элементов
тогда AMS_dunit==u5
AMS_arrows_count-- //AMS_arrows_count становится "9" => AMS_arrows[AMS_arrows_count]==u9
AMS_arrows[i]=AMS_arrows[AMS_arrows_count] // (u0,u1,u2,u3,u4,u9,u6,u7,u8,u9,null,...)
и так как условие выхода (i>=AMS_arrows_count) или (i>=9) то u9 будет пододвинута 1 раз в этот вызов

хотя действительно, у меня ошибка в нижнем случае: строки "i++" не должно быть

стрела здесь не теряется
Старый 06.07.2010, 16:43
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Elf_Stratigo:
AMS_arrows[AMS_arrows_count]==null при AMS_arrows_count=10
почему-это оно равно null? Я говорил с учетом того, что 10 элемент массива имеет дамми-юнита включительно.
Старый 06.07.2010, 16:51
Elf_Stratigo

offline
Опыт: 4,699
Активность:
делаем первый вызов LaunchArrow
получаем:
AMS_arrows=(u0,null,...)
AMS_arrows_count=1
второй
AMS_arrows=(u0,u1,null,...)
AMS_arrows_count=2
третий
AMS_arrows=(u0,u1,u2,null,...)
AMS_arrows_count=3
и пусть стрела u1 должна закончить свой полёт по условию (ang<=.405)
AMS_move при i=1:
AMS_arrows_count-- //AMS_arrows_count=2
AMS_arrows[i]=AMS_arrows[AMS_arrows_count] //AMS_arrows=(u0,u2,u2,null,...)
значит пришли в состояние:
AMS_arrows=(u0,u2,u2,null,...)
AMS_arrows_count=2
заметим, что условие выхода в цикле (i>=AMS_arrows_count), таким образом оставшиеся снаряды (u0,u2) будут продолжать движение с должной скоростью

да, в AMS_arrows[3] (или 10 как в твоём примере) может и лежать какойто объект, но его ссылка будет встречаться раньше, и он будет убит по завершению движения, а полное обновление памяти произойдёт когда игроки запустят одновременно 3 стрелы
Старый 06.07.2010, 17:22
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Elf_Stratigo, ок, понял. Значит у тебя arrows_count всегда на 1 больше, чем реальное количество снарядов? Я бы на твоем месте пробегался циклом по массиву со стрелами, перезаписывая их следующим образом:
if ang<=.405 then
	KillUnit(AMS_dunit)
	DisplayTextToPlayer(GetLocalPlayer(),0.,0.,"exs1")
	n = i
	loop
    	    AMS_arrows[n]=AMS_arrows[n+1]
   	    exitwhen n == AMS_arrows_count-1
	    n++
	endloop
	AMS_arrows_count--
Старый 06.07.2010, 17:40
Elf_Stratigo

offline
Опыт: 4,699
Активность:
да да

когда один из снарядов завершает движение - задача состоит в том, чтобы занять "дырку" в массиве другим снарядом

можно конечно и пододвигать остальные, как ты предлагаешь, а можно "в дырку" положить самый последний снаряд и тогда не нужен будет цикл

ты предлагаешь (n-AMS_arrows_count-1) перемещений, а можно в одно управиться - ведь порядок то в этом массиве не важен
к тому же заметь, внутри цикла у тя происходит пересчёт (AMS_arrows_count-1) для каждой итерации, достаточно один раз вызвать AMS_arrows_count-- до цикла

к сожалению, как видишь, это не причина зависания
Старый 06.07.2010, 17:55
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Elf_Stratigo, скажем, что мой вариант еще и немного оптимизировать можно, но это не главное. В общем ладно, у каждого свой стиль) Но судя по тому, что никто кроме менять тут пока что не отписался, без карты-примера не обойдется. Скинул бы ты мувинг-системку свою, да выложил тут..
Старый 06.07.2010, 18:09
Elf_Stratigo

offline
Опыт: 4,699
Активность:
в том и дело, что система работает гуд
но стрелы зависают
я как бы и прошу, чтобы мне подсказали, где рыть - гдето происходит какойто конфликт, но ума не приложу где - всё вроде проверил
всю мапу бессмысленно выкладывать - овер 8000 строк
ну если поможет, прикрепил карту-демонстрацию

как видно, псины не застревают ибо система гуд
Прикрепленные файлы
Тип файла: w3x test.w3x (17.6 Кбайт, 19 просмотров )
Старый 06.07.2010, 19:00
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Elf_Stratigo, в общем последнее, что приходит в голову - ты где-то ненароком перезаписываешь переменную, при чем не в системе. Ибо за 5 минут клацанья по абилке, ни один волк не завис..
Старый 06.07.2010, 19:21
Elf_Stratigo

offline
Опыт: 4,699
Активность:
6) проверил места обращения к переменным AMS_arrows и AMS_arrows_count - это только эти две функции (извлёк весь код и в блокноте - поиск слов)
Старый 06.07.2010, 19:47
Elf_Stratigo

offline
Опыт: 4,699
Активность:
в попытках фикса:
добавил строчку
TriggerSleepAction(.01)
перед
AMS_arrows[AMS_arrows_count]=whichUnit
AMS_arrows_count++
в LaunchArrow
и стрелы перестали зависать!!!
но такой фикс меня не устраивает :(
и не совсем понимаю, почему это вдруг помогло...
Старый 08.07.2010, 15:28
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 14:26.