если я не ошибаюсь юнита нельзя создать через глобалку при её объявлении, поэтому и присвоить константное значение с учётом интеллекта героя ты не сможешь, только при инициализации присваивать это всё дело
Unryze, смешно получается, суть как раз была что IsTerrainPathable медленнее чем сместить тот же предмет, спрятать его, а потом сравнивать координаты предмета и нужной точки
даже откопал старый вопрос с комментариями от сильных людей: xgm.guru/p/wc3/168497
а, стоп, IsTerrainPathable имеет ещё один косяк если не ошибаюсь, оно не проверяет по нормальному проходимость путей от декораций
раскрыть
local item it = CreateItem( 'spsh', 500.00, 500.00 )
local real x
local real y
call CreateDestructable( 'ATtr', 0.00, 0.00, 270.00, 1.00, 0 )
call SetItemVisible( it, false )
if not IsTerrainPathable( 0.00, 0.00, PATHING_TYPE_WALKABILITY ) then
call BJDebugMsg( "IsTerrainPathable: проходимо" )
else
call BJDebugMsg( "IsTerrainPathable: непроходимо" )
endif
call SetItemPosition( it, 0.00, 0.00 )
call SetItemVisible( it, false )
set x = GetItemX( it )
set y = GetItemY( it )
if ( x + 1.00 < 0.00 or x - 1.00 > 0.00 ) or ( y + 1.00 < 0.00 or y - 1.00 > 0.00 ) then
call BJDebugMsg( "Предмет: непроходимо" )
else
call BJDebugMsg( "Предмет: проходимо" )
endif
Unryze, не раз замечал как люди пытаются обойти функцию IsTerrainPathable путём проверки проходимости предметом (SetItemPosition) или юнитом (SetUnitPosition), по привычке сам начал использовать проверку предметом, можно об этом тоже пару слов добавить
дисклеймер: я не прошёл даже 10% карты, так что вероятно я ещё не увидел того, что перевернуло бы моё мнение с ног до головы, следующий текст основывается на моём опыте 15-и минутной игры
не очень понравился скиллсет героев и монстров, всё скучное, половина будто вообще из редактора объектов, ланд простой, клиффы используются, ну в общем тема олдскула, есть секретики, нет выбора режима сложности, например чтобы счётчик смертей не падал и можно было бы пройти игру (желание заново проходить опять же, не очень, из-за не особо интересного геймплея)
блинк за ворота чтобы их открыть не сопровождается звуками будто шаман взламывает замок с другой стороны, да и ему не надо даже у ворот стоять, просто что-то там тикает ты бегаешь и дверь сама по себе открывается, у первого скелета минибосса таргетный лик смерти, больно дамажит увернуться нельзя, неприятно, приходится отбегать, хиляться и обратно нападать, щит от механика вроде вообще не спасает от него, короче нудненький кайт, который растягивает геймплей, урон от кушки орка не сильно ощущается, будто там множитель в 1.50, а не 2.50 урона
возможно конечно всё приведенное выше нивелируется какими-то супер классными боссами которые используют нонтаргет скиллы от которых можно увернуться, заблочить или парировать, и между атаками босса наносить ему урон, но мы не дошли до них
моя СУБЪЕКТИВНАЯ оценка: 3/10
сыро, стоит реворкнуть полностью скиллсет героев и монстров (хотя бы чтобы на ро не напоминали) и добавить выбор режима сложности (вплоть до бесконечного воскрешения)
но опять же напомню про дисклеймер, т.е. эта оценка вообще не имеет веса как и сам комментарий, потому я даже половину игры не прошёл
upd оказывается ворота не шаманом открывались, это напарник по совпадениям после блинка открывал их)
library SpellCastLib
globals
private constant timer TempTimer = CreateTimer( )
private constant real timerPeriodic = 0.01
private integer max = 0
private unit array dummy
private real array startx
private real array starty
private real array startz
private real array midx
private real array midy
private real array midz
private real array endx
private real array endy
private real array endz
private real array lastx
private real array lasty
private real array time
private real array maxTime
private location LFZ = Location( 0.00, 0.00 )
endglobals
private function GetLocZ takes real x, real y returns real
call MoveLocation( LFZ, x, y )
return GetLocationZ( LFZ )
endfunction
private function move takes nothing returns nothing
local real x
local real y
local real z
local integer i
set i = 1
loop
set x = startx[i] + ( ( 2.00 * ( midx[i] - startx[i] ) ) + ( startx[i] - 2.00 * midx[i] + endx[i] ) * time[i] ) * time[i]
set y = starty[i] + ( ( 2.00 * ( midy[i] - starty[i] ) ) + ( starty[i] - 2.00 * midy[i] + endy[i] ) * time[i] ) * time[i]
set z = startz[i] + ( ( 2.00 * ( midz[i] - startz[i] ) ) + ( startz[i] - 2.00 * midz[i] + endz[i] ) * time[i] ) * time[i]
call SetUnitX( dummy[i], x )
call SetUnitY( dummy[i], y )
call SetUnitFlyHeight( dummy[i], z - GetLocZ( x, y ), 0.00 )
call SetUnitFacing( dummy[i], Atan2( y - lasty[i], x - lastx[i] ) * bj_RADTODEG )
set lastx[i] = x
set lasty[i] = y
set time[i] = time[i] + timerPeriodic / maxTime[i]
if time[i] >= 1.00 then
call KillUnit( dummy[i] )
call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl", x, y ) )
call CreateDestructable( 'ATtr', x, y, 270.00, 1.00, GetRandomInt( 0, 4 ) )
if i != max then
set dummy[i] = dummy[max]
set startx[i] = startx[max]
set starty[i] = starty[max]
set startz[i] = startz[max]
set lastx[i] = lastx[max]
set lasty[i] = lasty[max]
set endx[i] = endx[max]
set endy[i] = endy[max]
set endz[i] = endz[max]
set midx[i] = midx[max]
set midy[i] = midy[max]
set midz[i] = midz[max]
set time[i] = time[max]
set maxTime[i] = maxTime[max]
endif
set dummy[max] = null
set i = i - 1
set max = max - 1
if max <= 0 then
call PauseTimer( TempTimer )
endif
endif
set i = i + 1
exitwhen i > max
endloop
endfunction
function Trig_SpellCast_Actions takes nothing returns nothing
local unit caster = GetTriggerUnit( )
local real x = GetSpellTargetX( )
local real y = GetSpellTargetY( )
local real angle
local real angle1
local real angle2
local real distance
local integer i
local integer count = 10 // кол-во деревьев
local boolean b
local real d
set b = count / 2 * 2 == count
if b then
set d = 32.00 // начальная дистанция между деревьями
set angle2 = 5.00 // начальный угол полёта
else
set d = 0.00
set angle2 = 0.00
endif
set angle1 = Atan2( y - GetUnitY( caster ), x - GetUnitX( caster ) )
set i = 1
loop
set max = max + 1
set startx[max] = GetUnitX( caster )
set starty[max] = GetUnitY( caster )
set startz[max] = GetLocZ( startx[max], starty[max] ) + 50.00 + GetUnitFlyHeight( caster )
set lastx[max] = startx[max]
set lasty[max] = starty[max]
set dummy[max] = CreateUnit( GetOwningPlayer( caster ), 'u000', startx[max], starty[max], angle1 * bj_RADTODEG )
call UnitAddAbility( dummy[max], 'Arav' )
call UnitRemoveAbility( dummy[max], 'Arav' )
call SetUnitPathing( dummy[max], false )
call SetUnitX( dummy[max], startx[max] )
call SetUnitY( dummy[max], starty[max] )
call SetUnitFlyHeight( dummy[max], startz[max], 0.00 )
if b then
set endx[max] = x + d * Cos( angle1 + 90.00 * bj_DEGTORAD )
set endy[max] = y + d * Sin( angle1 + 90.00 * bj_DEGTORAD )
else
set endx[max] = x + d * Cos( angle1 - 90.00 * bj_DEGTORAD )
set endy[max] = y + d * Sin( angle1 - 90.00 * bj_DEGTORAD )
endif
set endz[max] = GetLocZ( endx[max], endy[max] )
set angle = Atan2( endy[max] - starty[max], endx[max] - startx[max] )
set distance = SquareRoot( ( endx[max] - startx[max] ) * ( endx[max] - startx[max] ) + ( endy[max] - starty[max] ) * ( endy[max] - starty[max] ) )
if b then
set midx[max] = startx[max] + distance / 2.00 * Cos( angle + angle2 * bj_DEGTORAD )
set midy[max] = starty[max] + distance / 2.00 * Sin( angle + angle2 * bj_DEGTORAD )
set midz[max] = GetLocZ( midx[max], midy[max] )
set b = false
else
set midx[max] = startx[max] + distance / 2.00 * Cos( angle - angle2 * bj_DEGTORAD )
set midy[max] = starty[max] + distance / 2.00 * Sin( angle - angle2 * bj_DEGTORAD )
set midz[max] = GetLocZ( midx[max], midy[max] )
set angle2 = angle2 + 10.00 // доп угол
set d = d + 64.00 // расстояние между деревьями
set b = true
endif
if startz[max] < endz[max] then
set midz[max] = midz[max] + endz[max]
else
set midz[max] = midz[max] + startz[max]
endif
set midz[max] = midz[max] + 50.00
set time[max] = 0.00
set maxTime[max] = distance * timerPeriodic * 0.20 // скорость полёта
if max == 1 then
call TimerStart( TempTimer, timerPeriodic, true, function move )
endif
set i = i + 1
exitwhen i > count
endloop
set caster = null
endfunction
endlibrary
function Trig_SpellCast_Conditions takes nothing returns boolean
return GetSpellAbilityId( ) == 'A000' // равкод абилки
endfunction
//===========================================================================
function InitTrig_SpellCast takes nothing returns nothing
set gg_trg_SpellCast = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_SpellCast, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_SpellCast, Condition( function Trig_SpellCast_Conditions ) )
call TriggerAddAction( gg_trg_SpellCast, function Trig_SpellCast_Actions )
endfunction
если нужна помощь в импорте или переделать всё на корню - пиши, но подробнее в этот раз
Daro, если кому-нибудь надо то пусть хоть статью из этой функции делают, я хвастаться не хочу потому что знаю что я самый помойный чел на хгм, который самостоятельно добился ровно ничего
большая часть материалов из этой страницы даже не моё и не благодаря мне, а благодаря NightSiren'у и Hate'у, которых добавил в благодарности, это они всё придумали, даже видео хейта без его разрешения взял, найтсирен мне не раз помогал подобными функциями и формулами
и ты не представляешь как мне будет стыдно если кто-то посмотрит на это и подумает "оо, dfgdfhg такие прикольные штуки делает крута", мысль об этом заставляет застрелиться
globals
constant group TempG = CreateGroup( )
constant timer TempTimer = CreateTimer( )
constant real timerPeriodic = 0.01
boolean AbilityDamage = false
integer max = 0
unit array dummy
unit array target
real array startx
real array starty
real array startz
real array midx
real array midy
real array midz
real array endx
real array endy
real array endz
real array time
real array maxTime
real array damage
constant location LFZ = Location( 0.00, 0.00 )
endglobals
function GetLocZ takes real x, real y returns real
call MoveLocation( LFZ, x, y )
return GetLocationZ( LFZ )
endfunction
function IsEven takes integer a returns boolean
return a / 2 * 2 == a
endfunction
function move takes nothing returns nothing
local real x
local real y
local real z
local integer i
set i = 1
loop
set endx[i] = GetUnitX( target[i] )
set endy[i] = GetUnitY( target[i] )
set endz[i] = GetLocZ( endx[i], endy[i] ) + 50.00
set x = startx[i] + ( ( 2.00 * ( midx[i] - startx[i] ) ) + ( startx[i] - 2.00 * midx[i] + endx[i] ) * time[i] ) * time[i]
set y = starty[i] + ( ( 2.00 * ( midy[i] - starty[i] ) ) + ( starty[i] - 2.00 * midy[i] + endy[i] ) * time[i] ) * time[i]
set z = startz[i] + ( ( 2.00 * ( midz[i] - startz[i] ) ) + ( startz[i] - 2.00 * midz[i] + endz[i] ) * time[i] ) * time[i]
call SetUnitFacing( dummy[i], Atan2( y - GetUnitY( dummy[i] ), x - GetUnitX( dummy[i] ) ) * bj_RADTODEG )
call SetUnitX( dummy[i], x )
call SetUnitY( dummy[i], y )
call SetUnitFlyHeight( dummy[i], z - GetLocZ( x, y ), 0.00 )
set time[i] = time[i] + timerPeriodic / maxTime[i]
if time[i] >= 1.00 or GetUnitFlyHeight( dummy[i] ) < 30.00 then
if time[i] >= 1.00 then
set AbilityDamage = true
call UnitDamageTarget( dummy[i], target[i], damage[i], false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, null )
set AbilityDamage = false
endif
call KillUnit( dummy[i] )
if i != max then
set dummy[i] = dummy[max]
set target[i] = target[max]
set startx[i] = startx[max]
set starty[i] = starty[max]
set startz[i] = startz[max]
set endx[i] = endx[max]
set endy[i] = endy[max]
set endz[i] = endz[max]
set midx[i] = midx[max]
set midy[i] = midy[max]
set midz[i] = midz[max]
set time[i] = time[max]
set maxTime[i] = maxTime[max]
set damage[i] = damage[max]
endif
set dummy[max] = null
set target[max] = null
set i = i - 1
set max = max - 1
if max <= 0 then
call PauseTimer( TempTimer )
endif
endif
set i = i + 1
exitwhen i > max
endloop
endfunction
function DamageEvent_Actions takes nothing returns boolean
local unit attacker
local unit damaged
local real dmg = GetEventDamage( )
local real x
local real y
local real angle
local real angleOffset
local real distance
local real distanceOffset
local real height
local integer i
if not AbilityDamage and dmg > 0.00 then
set attacker = GetEventDamageSource( )
set damaged = GetTriggerUnit( )
set x = GetUnitX( damaged )
set y = GetUnitY( damaged )
call NegateDamage( damaged, dmg )
set dmg = dmg / 2.00
set height = 50.00
set angleOffset = 5
set distanceOffset = 0.00
set i = 0
loop
set max = max + 1
set startx[max] = GetUnitX( attacker )
set starty[max] = GetUnitY( attacker )
set startz[max] = GetLocZ( startx[max], starty[max] ) + height
set endx[max] = x
set endy[max] = y
set endz[max] = GetLocZ( endx[max], endy[max] ) + 50.00
set angle = Atan2( endy[max] - starty[max], endx[max] - startx[max] )
set distance = SquareRoot( ( endx[max] - startx[max] ) * ( endx[max] - startx[max] ) + ( endy[max] - starty[max] ) * ( endy[max] - starty[max] ) )
set target[max] = damaged
set dummy[max] = CreateUnit( GetOwningPlayer( attacker ), 'u000', startx[max], starty[max], angle * bj_RADTODEG )
call UnitAddAbility( dummy[max], 'Arav' )
call UnitRemoveAbility( dummy[max], 'Arav' )
call SetUnitPathing( dummy[max], false )
call SetUnitX( dummy[max], startx[max] )
call SetUnitY( dummy[max], starty[max] )
call SetUnitFlyHeight( dummy[max], startz[max], 0.00 )
set distance = distance + distanceOffset
if IsEven( i ) then
set midx[max] = startx[max] + ( distance / 2.00 ) * Cos( angle + angleOffset * bj_DEGTORAD )
set midy[max] = starty[max] + ( distance / 2.00 ) * Sin( angle + angleOffset * bj_DEGTORAD )
else
set midx[max] = startx[max] + ( distance / 2.00 ) * Cos( angle - angleOffset * bj_DEGTORAD )
set midy[max] = starty[max] + ( distance / 2.00 ) * Sin( angle - angleOffset * bj_DEGTORAD )
endif
set midz[max] = 0.00
if startz[max] < endz[max] then
set midz[max] = midz[max] + endz[max]
else
set midz[max] = midz[max] + startz[max]
endif
set midz[max] = midz[max] + height
if not IsEven( i ) then
set distanceOffset = distanceOffset + 50.00
set angleOffset = angleOffset + 180.00 / 16.00
set height = height + 20.00
endif
set time[max] = 0.00
set maxTime[max] = distance * 0.25 * timerPeriodic
set damage[max] = dmg
if max == 1 then
call TimerStart( TempTimer, timerPeriodic, true, function move )
endif
set i = i + 1
exitwhen i > 15
endloop
set damaged = null
set attacker = null
endif
return false
endfunction
//===========================================================================
function Regist takes unit u returns nothing
if GetUnitAbilityLevel( u, 'Aloc' ) == 0 then
call TriggerRegisterUnitEvent( gg_trg_DamageEvent, u, EVENT_UNIT_DAMAGED )
endif
endfunction
function RegistCond takes nothing returns boolean
call Regist( GetTriggerUnit( ) )
return false
endfunction
function RegistCond_1 takes nothing returns boolean
call Regist( GetFilterUnit( ) )
return false
endfunction
function RegistEvent takes nothing returns nothing
if gg_trg_DamageEvent != null then
call DestroyTrigger( gg_trg_DamageEvent )
endif
set gg_trg_DamageEvent = CreateTrigger( )
call GroupEnumUnitsInRect( TempG, bj_mapInitialPlayableArea, Condition( function RegistCond_1 ) )
call TriggerAddCondition( gg_trg_DamageEvent, Condition( function DamageEvent_Actions ) )
call TimerStart( GetExpiredTimer( ), 600.00, false, function RegistEvent )
endfunction
function InitTrig_DamageEvent takes nothing returns nothing
local trigger t = CreateTrigger( )
local region rectRegion = CreateRegion( )
call RegionAddRect( rectRegion, bj_mapInitialPlayableArea )
call TriggerRegisterEnterRegion( t, rectRegion, null )
call TriggerAddCondition( t, Condition( function RegistCond ) )
call TimerStart( CreateTimer( ), 0.00, false, function RegistEvent )
set t = null
set rectRegion = null
endfunction
» WarCraft 3 / Как получить стат юнита в Jass и есть ли коллекция всех функций?
» WarCraft 3 / Как получить стат юнита в Jass и есть ли коллекция всех функций?
» WarCraft 3 / Шахтерские модели из Dota 2
Ред. rsfghd
» WarCraft 3 / Combat Zone
Ред. rsfghd
» WarCraft 3 / Jass MythBusters
даже откопал старый вопрос с комментариями от сильных людей: xgm.guru/p/wc3/168497
» WarCraft 3 / Jass MythBusters
» WarCraft 3 / Замок (The Castle)
блинк за ворота чтобы их открыть не сопровождается звуками будто шаман взламывает замок с другой стороны, да и ему не надо даже у ворот стоять, просто что-то там тикает ты бегаешь и дверь сама по себе открывается, у первого скелета минибосса таргетный лик смерти, больно дамажит увернуться нельзя, неприятно, приходится отбегать, хиляться и обратно нападать, щит от механика вроде вообще не спасает от него, короче нудненький кайт, который растягивает геймплей, урон от кушки орка не сильно ощущается, будто там множитель в 1.50, а не 2.50 урона
возможно конечно всё приведенное выше нивелируется какими-то супер классными боссами которые используют нонтаргет скиллы от которых можно увернуться, заблочить или парировать, и между атаками босса наносить ему урон, но мы не дошли до них
моя СУБЪЕКТИВНАЯ оценка: 3/10
сыро, стоит реворкнуть полностью скиллсет героев и монстров (хотя бы чтобы на ро не напоминали) и добавить выбор режима сложности (вплоть до бесконечного воскрешения)
но опять же напомню про дисклеймер, т.е. эта оценка вообще не имеет веса как и сам комментарий, потому я даже половину игры не прошёл
» WarCraft 3 / Способности и алгоритмы на заказ
Заклинание готово!
Способность: Лесная Стена
Выполнено: Да
» WarCraft 3 / Способности и алгоритмы на заказ
» WarCraft 3 / Отловить нажатие ЛКМ по области
» WarCraft 3 / Сплеш
» WarCraft 3 / Скорость Света "скилы под ключ"
» WarCraft 3 / Где задается значение flat урона боевых барабанов?
» WarCraft 3 / Содрогание "скилы под ключ"
» WarCraft 3 / Скорость Света "скилы под ключ"
» Блог им. rsfghd / движение по безье
» Блог им. rsfghd / Миниспеллпак
и карта для которой делался этот спеллпак не аниме
» Блог им. rsfghd / движение по безье
большая часть материалов из этой страницы даже не моё и не благодаря мне, а благодаря NightSiren'у и Hate'у, которых добавил в благодарности, это они всё придумали, даже видео хейта без его разрешения взял, найтсирен мне не раз помогал подобными функциями и формулами
и ты не представляешь как мне будет стыдно если кто-то посмотрит на это и подумает "оо, dfgdfhg такие прикольные штуки делает крута", мысль об этом заставляет застрелиться
» WarCraft 3 / В карте скрыты триггеры
» WarCraft 3 / как зделать так чтобы вурдалак не добывал дерево
» WarCraft 3 / как зделать так чтобы вурдалак не добывал дерево
» WarCraft 3 / Дальнобойные атаки сквозь препятствия
» WarCraft 3 / Условие 1 итем в количестве 3-х штук
» Блог им. rsfghd / движение по безье
» WarCraft 3 / Дальнобойные атаки сквозь препятствия