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

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

Ответ
 
Elf_Stratigo

offline
Опыт: 4,699
Активность:
Стрела не двигается и зависает
Код:
function ArrowMoveFunc takes nothing returns nothing
 local timer t=GetExpiredTimer()
 local unit u=GetHandleUnit(t,"unit")
 local real dist=GetHandleReal(t,"distance")
 local real speed=GetHandleReal(t,"speed")
 local real nd=GetHandleReal(t,"nd")
 local real ang=GetUnitFacing(u)
 local location tl = GetUnitLoc(u)
 local player tt = GetOwningPlayer(u)
 local group en
 local unit du
 set en = GetUnitsInRangeOfLocMatching(30., tl, null)
 loop
     set du = FirstOfGroup(en)
     exitwhen du == null
     if (not IsPlayerAlly(tt, GetOwningPlayer(du))) or (not IsUnitType(du, UNIT_TYPE_HERO))  then
         call UnitDamageTarget(u, du, 500., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)    
     endif
     call GroupRemoveUnit(en,du)
     endloop
 call DestroyGroup(en)
 set en = null
 if nd<dist and RectContainsCoords(bj_mapInitialPlayableArea, GetLocationX(tl), GetLocationY(tl)) and (GetUnitState(u, UNIT_STATE_LIFE) > 0.) then
  call SetUnitX(u,GetLocationX(tl)+speed*Cos(ang*bj_DEGTORAD))
  call SetUnitY(u,GetLocationY(tl)+speed*Sin(ang*bj_DEGTORAD))
  call SetHandleReal(t,"nd",nd+speed)
 else
  call KillUnit(u)
  call PauseTimer(t)
  call FlushHandleLocals(t)
  call DestroyTimer(t)
 endif
 call RemoveLocation(tl)
 set tl = null
 set t=null
 set u=null
 set tt=null
endfunction

function LaunchArrow takes unit whichUnit,real speed,real dist returns nothing
 local timer t = CreateTimer()
 local integer ind = GetConvertedPlayerId(GetOwningPlayer(whichUnit))
 //call UnitApplyTimedLife( whichUnit, 'BTLF', 8. )
 call SetHandleHandle(t,"unit",whichUnit)
 call SetHandleReal(t,"speed",speed)
 call SetHandleReal(t,"distance",dist)
 call TimerStart(t,.02,true,function ArrowMoveFunc)
 set t=null
 set udg_P_Shots[ind] = udg_P_Shots[ind] + 1
endfunction


Парни, ПОМОГИТЕ ПЛЗ!!! Это 2 функции, обеспечивающие полёт, скажем, стрел, оно используется в карте Archers ES (мб кто знает...). Направление полёта задаётся во время создания. Никаких утечек в памяти мною не наблюдается. СКАЖИТЕ ПОЖАЛУЙСТА, ПОЧЕМУ НЕКОТОРЫЕ СТРЕЛЫ ЗАСТРЕВАЮТ!!!!! Причём нет, чтобы в фиксированных местах, при фиксированном времени, фиксированная по счёту... Они застревают полностью когда хотят!!! Причём за всю игру это может быть 1-5 стрел! По моим наблюдениям, стрела, если хочет застрять, застревает сразу после создания (ниразу не двигается).
Эм, это код Archers ES - мб ктонить играл...
Застревает<=>висит в воздухе всю игру (дамагу не наносит)

Блин, я в шоке ><

call UnitApplyTimedLife( whichUnit, 'BTLF', 8. ) - хоть не всю игру висеть будут ;(
[+] замечание от ShadoW DaemoN: название темы не отражает суть вопроса
Старый 24.02.2009, 17:35
Igores
НИИ 4А-Во! Кафедра Джасс.
offline
Опыт: 5,325
Активность:
Elf_Stratigo,
Почему стрела не наносит дамаг?
У тебя группа не создается.
Напиши в начале
Код:
local group en = CreateGroup()

естественно дамагу не наносит, когда юниты которых нужно дамажить не заносятся в группу. Тут помоему еще один косяк, может быть так что одному и тому же юниту будет нанесен урон одной стрелой два раза, чтобы это убрать: сделай либо радиус ренджа поменьше либо увеличь период таймера(есть еще одна причина, частота человеческого глаза 24 кадра в секунду, а при таком периоде создается 50 кадров, то есть 26 кадров будет проигрываться компьютером просто так, а следовательно больше половины операций компьютер будет высчитывать зря, что тоже не есть хорошо)
Почему стрела останавливается на месте и никуда не летит?
Ты не показал откуда у тебя берется переменная nd, скорее всего изза этого, так как она влияет на движение.
Еще вместо локейшна используй GetUnitX и GetUnitY.
Цикл тут тоже лишний, лучше просто использовать приатаченные к таймеру хендлы в колбэк функции ForGroup(). Просто для сведения: это конечно мелочь, но все таки лучше один раз в самом начале перевести угол в радианы, а не два раза высчитывать его, для процессора на одну операцию меньше))
Вообщем если засесть нормально, то можно уменьшить код почти в два раза и увеличить производительность на 50%.
Имхо, эти буржуйские функции кастрирования хендлов лишние, можно и без них обойтись.
Ошибаешься, в коде есть одна утечка:
Код:
call KillUnit(u)

лучше пиши сразу
Код:
call RemoveUnit(u)

У тебя в спелле стрела летит на всю карту?))

Отредактировано Igores, 25.02.2009 в 04:37.
Старый 25.02.2009, 04:14
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Igores, после килла (разложения и прочих вещей) юнит ремувится. Здесь ремув будет лучше только потому, что стрела не умирает, ее просто нужно удалять. И соответсвенно делать set u = null
Старый 25.02.2009, 04:35
Igores
НИИ 4А-Во! Кафедра Джасс.
offline
Опыт: 5,325
Активность:
Vampirrr, после смерти она все равно некоторое время будет забивать память, ее ведь не будут воскрешать, значит надо сразу ремувить.

Igores добавил:
Блин, жаль редактора нет под рукой, так бы переписал спелл на русский манер))
Старый 25.02.2009, 04:40
Vampirrr
O_o
offline
Опыт: 19,286
Активность:
Igores, не спорю, но предыдущий ответ к тому, что утечек КиллЮнит не вызывает..
Старый 25.02.2009, 04:55
Igores
НИИ 4А-Во! Кафедра Джасс.
offline
Опыт: 5,325
Активность:
Vampirrr, ты прав, с этим я лажанулся))
Старый 25.02.2009, 04:59
Elf_Stratigo

offline
Опыт: 4,699
Активность:
Код:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

функция из blizzard.j
содержит в се креайтгроуп :)
Цитата:
24 кадра в секунду, а при таком периоде создается 50 кадров

о:
спасибо :)
Цитата:
Ты не показал откуда у тебя берется переменная nd, скорее всего изза этого, так как она влияет на движение.

из пустоты :)
в части условия, которая решает, может ли двигаться стрела дальше есть:
Код:
nd<dist

где dist задаётся - дальность полёта
nd - скоко уже пролетела
если нд меньше dist (даже если вдруг отрицательное), то стрела совершит движение
иначе стрела будет уничтожена
НО НИКАК НЕ ДОЛЖНА ЗАВИСНУТЬ! :(((((((
nd получается по умолчанию равным 0
Цитата:
Еще вместо локейшна используй GetUnitX и GetUnitY.

я использую location, т.к. она требуется для выше описанной функции GetUnitsInRangeOfLocMatching
Цитата:
Цикл тут тоже лишний, лучше просто использовать приатаченные к таймеру хендлы в колбэк функции ForGroup().

мне просто почемуто кажется, что функция ForGroup - "долгая" чтоли, но я мб неправ? :)
просто подозрительно, када один из параметров функция, которая будет вызвана для каждого юнита - а тут вродь тоже самое, и вроде бы минимум вызовов...
Цитата:
тому же юниту будет нанесен урон одной стрелой два раза

у всех уязвимых юнитов хп меньше 100 )))))
Мне нужен киллюнит, т.к. я отлавливаю это событие - допустим подожжёная стрела после своей смерти должна воспламениться...

п.с. насчёт location - да, наверное нужно мясо из функции выдрать и перейти на GetUnitX и GetUnitY
Старый 25.02.2009, 16:37
Igores
НИИ 4А-Во! Кафедра Джасс.
offline
Опыт: 5,325
Активность:
Поробуй сделать тоже без бж и в координатах. Вообще, потерпишь ровно 24 часа? Я тебе завтра в это же время выложу свой вариант этой функции.
Старый 26.02.2009, 00:44
agentex

offline
Опыт: 34,834
Активность:
Да и без кеша, мб там вобще на таймере хендл абсолютно другого обьекта возвращается..
По поводу фор груп: как раз таки она в разы быстрее цикла
набор в группу осуществляется функцией GroupEnumUnitsInRange() :/
Старый 26.02.2009, 00:57
Elf_Stratigo

offline
Опыт: 4,699
Активность:
Цитата:
Вообще, потерпишь ровно 24 часа?

у меня нет выхода ))
Цитата:
Да и без кеша, мб там вобще на таймере хендл абсолютно другого обьекта возвращается..

Дык скорее всего, вот я и хочу узнать, почему?! Ведь оно случается не постоянно... За всю игру игру может ни одна стрела не застрять, или застрять, но не больше 5...

со всеми коментами, что были написаны, я переписал функцию ArrowMoveFunc так:
Код:
function ArrowMoveFuncTargets takes nothing returns boolean
    return (not IsPlayerAlly(udg_AMS_p, GetOwningPlayer(GetFilterUnit()))) or (not IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO))
endfunction

function ArrowMoveFuncStrike takes nothing returns nothing
    call UnitDamageTarget(udg_AMS_u, GetEnumUnit(), 500., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
endfunction

function ArrowMoveFunc takes nothing returns nothing
 local timer t=GetExpiredTimer()
 local real dist=GetHandleReal(t,"distance")
 local real speed=GetHandleReal(t,"speed")
 local real nd=GetHandleReal(t,"nd")
 local real ang
 local real X
 local real Y
 local group en = CreateGroup()
 set udg_AMS_u = GetHandleUnit(t,"unit")
 set udg_AMS_p = GetOwningPlayer(udg_AMS_u)
 set ang=GetUnitFacing(udg_AMS_u)*bj_DEGTORAD
 set X=GetUnitX(udg_AMS_u)
 set Y=GetUnitY(udg_AMS_u)
 call GroupEnumUnitsInRange(en, X, Y, 30., udg_AMS_f)
 call ForGroup(en, function ArrowMoveFuncStrike)
 call DestroyGroup(en)
 set en = null
 if nd<dist and RectContainsCoords(bj_mapInitialPlayableArea, X, Y) and (GetUnitState(udg_AMS_u, UNIT_STATE_LIFE) > 0.) then
  call SetUnitX(udg_AMS_u,X+speed*Cos(ang))
  call SetUnitY(udg_AMS_u,Y+speed*Sin(ang))
  call SetHandleReal(t,"nd",nd+speed)
 else
  call KillUnit(udg_AMS_u)
  call PauseTimer(t)
  call FlushHandleLocals(t)
  call DestroyTimer(t)
 endif
 set t=null
endfunction


udg_AMS_u - глобалка типа юнит
udg_AMS_p - глобалка типа плеер
udg_AMS_f - глобалка типа boolexpr, проходит инициализацию при загрузке:
Код:
set udg_AMS_f=Condition(function ArrowMoveFuncTargets)


ток у меня возникло 2 вопроса:
1)
получается udg_AMS_f - какоето константное условие, то будет ли нормально ArrowMoveFuncTargets фильтровать врагов, если внутри неё глобалка udg_AMS_p, ну тоесть, чтоб не было:
игрок 1 убил игрока 7 (врага)
игрок 7 убил игрока 8 (союзника) т.к. функция проверяла себя для игрока 1

2)
а ничего, что я использую глобалки, от этого стрелы не будут "путаться" как-нибудь? )

насчёт периода таймера:
у меня есть стрела, которая летит со скоростью 17. для периода .02
если я увеличу период таймера до .04, то не получится ли так, что при заданном радиусе повреждения стрела сможет пролететь "сквозь" лучницу, если её "физический размер (ucol)" есть 32.
я собственно такой период и ставил, чтоб злостность не происходила, но мб этот параметр - "физический размер (ucol)" - вообще другая вещь, т.к. я лично не замечал, чтоб эт этого чтото зависило...

п.с.
стрелы всё ещё виснут :(
Старый 26.02.2009, 12:22
agentex

offline
Опыт: 34,834
Активность:
Цитата:
а ничего, что я использую глобалки, от этого стрелы не будут "путаться" как-нибудь? )

дык ты их не напротяжении какогото времени юзаеш, а мгновенно, так что не будут
Цитата:
1)
получается udg_AMS_f - какоето константное условие, то будет ли нормально ArrowMoveFuncTargets фильтровать врагов, если внутри неё глобалка udg_AMS_p, ну тоесть, чтоб не было:
игрок 1 убил игрока 7 (врага)
игрок 7 убил игрока 8 (союзника) т.к. функция проверяла себя для игрока 1

нихрена не понял, напиши какие глобалки юзаются и где им присваиваются значения
Цитата:
насчёт периода таймера:
у меня есть стрела, которая летит со скоростью 17. для периода .02
если я увеличу период таймера до .04, то не получится ли так, что при заданном радиусе повреждения стрела сможет пролететь "сквозь" лучницу, если её "физический размер (ucol)" есть 32.
я собственно такой период и ставил, чтоб злостность не происходила, но мб этот параметр - "физический размер (ucol)" - вообще другая вещь, т.к. я лично не замечал, чтоб эт этого чтото зависило...

Хз я всегда ставлю 0.01 чтобы без дерганий всяких снаряд летел, ну максимум - это 0.05

Физический размер не учитывается при GroupEnumUnitsInRange, берется центр юнита GetUnitX\Y.
Старый 26.02.2009, 12:29
Elf_Stratigo

offline
Опыт: 4,699
Активность:
Код:
local real dist=GetHandleReal(t,"distance")


лишнее выделение памяти - я обращаюсь туда ток 1 раз)))

Цитата:
1)

играет игрок1 против союз(игрок6, игрок7, игрока8)

выстрел №1
whichUnit(игрок1,...)
в результате стрелой убит герой игрока8

прошло время...

выстрел №2
whichUnit(игрок6,...)
на траектории стрелы стоит герой игрока7 --- она убьёт его?

Цитата:
Хз я всегда ставлю 0.01 чтобы без дерганий всяких снаряд летел, ну максимум - это 0.05

в своих версиях серии 4.2 я ставил .01
эт приводило к странному замедлению при полёт стрел (ну новички не заметят..) - хотя это мб изза корявой оптимизации))
ну и добавил сотую - чоуж)

Цитата:
Физический размер не учитывается при GroupEnumUnitsInRange, берется центр юнита GetUnitX\Y.

пасиб )
Старый 26.02.2009, 13:23
Igores
НИИ 4А-Во! Кафедра Джасс.
offline
Опыт: 5,325
Активность:
Код:
// то что нам понадобится
globals
 unit array Unit
 real array speed
 real array dist
 real array nd
endglobals

function H2I takes handle h returns integer
 return h
 return 0
endfunction

// сам код

function ArrowCallBack takes nothing returns nothing
 local timer t=GetExpiredTimer()
 local integer h=H2I(t)-0x100000
 if IsUnitEnemy(Unit[h],GetEnumUnit()) or not IsUnitType(GetEnumUnit(), UNIT_TYPE_HERO) and GetWidgetLife(GetEnumUnit())>0.405 then
         call UnitDamageTarget(Unit[h], GetEnumUnit(), 500., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL,  WEAPON_TYPE_WHOKNOWS)   
 set t=null
endfunction

function ArrowMoveFunc takes nothing returns nothing
 local timer t=GetExpiredTimer()
 local integer h=H2I(t)-0x100000
 local real ang=GetUnitFacing(Unit[h])*bj_DEGTORAD
 local real x=GetUnitX(Unit[h])
 local real y=GetUnitY(Unit[h])
 local group en=CreateGroup()

 call GroupEnumUnitsInRange(60., x,y, null)
 call ForGroup(en, function ArrowCallBack)   
 call DestroyGroup(en)
 set en = null
 if nd[h]<dist[h] and RectContainsCoords(bj_mapInitialPlayableArea, x, y) and GetWidgetLife(Unit[h]) > 0.405 then
  call SetUnitX(Unit[h],x+speed[h]*Cos(ang))
  call SetUnitY(Unit[h],y+speed[h]*Sin(ang))
  set nd[h]=nd[h]+speed[h]
 else
// освобождаем память
  set Unit[h]=null
  set dist[h]=0
  set speed[h]=0
  set nd[h]=0
  call KillUnit(Unit[h])
  call DestroyTimer(t)
 endif

 set t=null
endfunction

function LaunchArrow takes unit whichUnit,real speed,real dist returns nothing
 local timer t = CreateTimer()
 local integer h=H2I(t)-0x100000
 set Unit[h]=whichUnit
 set speed[h]=speed
 set dist[h]=dist
 set nd[h]=0
 call TimerStart(t,.04,true,function ArrowMoveFunc)
 set t=null
endfunction


проверь этот код, должен работать)) вместо кеша сделал, через хэндлы, так быстрее))
Если честно, я его еще сам не проверял)) просто написал по памяти, так что могут быть синтаксические ошибки))) код работает для любого числа стрел.
кстати, в твоем первом посте всетаки была утечка, ты не обнулял переменную du))

Igores добавил:
вообще лучше переходи на хэндлы или массивы, таким методом восновном только буржуи пользуются))

Отредактировано Igores, 27.02.2009 в 02:50.
Старый 27.02.2009, 02:55
Elf_Stratigo

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

Цитата:
ты не обнулял переменную du))

Цитата:
set du = FirstOfGroup(en)
exitwhen du == null

оно само обнулялось :)

Цитата:
хэндлы или массивы

ну мне очень понравился код, токо если объяснишь, следующее, то буду переходить :)
Цитата:
0x100000

что это за число )
размер сегмента памяти - 65536 - здесь это както учтено?
будет ли корректно работать это чудо, если я возьму число 0x010000
почему ты вычитаешь, ведь сложение работает быстрее

кста, стрелы всёравно зависают, по крайне мере в той ситуации, на которой я енто всё проверял
однако мне удалось обнаружить "повреждённую функцию", щас буду разбираться, но уже сам...
если интересно, могу выложить...
если ничё не пойму то опять к вам приду )
Старый 27.02.2009, 17:34
alexkill

offline
Опыт: 18,872
Активность:
Цитата:
H2I(t)-0x100000 что это за число )

минимальный хэндл объекта (в данном случае таймера). Также можно использовать мин. хэндл триггера, юнита и т.п.
Цитата:
размер сегмента памяти - 65536 - здесь это както учтено?

это здесь не нужно
Цитата:
будет ли корректно работать это чудо, если я возьму число 0x010000

и будут у тебя индексы массива с одним и тем же значением. подумай
Цитата:
почему ты вычитаешь, ведь сложение работает быстрее

уже объяснил

Igores, указал бы, кто научил =)
Старый 27.02.2009, 17:47
Igores
НИИ 4А-Во! Кафедра Джасс.
offline
Опыт: 5,325
Активность:
Elf_Stratigo, без проблем обращайся, если что обращайся:) а еще лучше к алексу, он мне эту систему объяснял:-)
Старый 27.02.2009, 20:04
Ответ

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

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

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

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



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