28

» WarCraft 3 / Как получить стат юнита в Jass и есть ли коллекция всех функций?

если я не ошибаюсь юнита нельзя создать через глобалку при её объявлении, поэтому и присвоить константное значение с учётом интеллекта героя ты не сможешь, только при инициализации присваивать это всё дело
28

» WarCraft 3 / Как получить стат юнита в Jass и есть ли коллекция всех функций?

native GetHeroStr takes unit whichHero, boolean includeBonuses returns integer
native GetHeroAgi takes unit whichHero, boolean includeBonuses returns integer
native GetHeroInt takes unit whichHero, boolean includeBonuses returns integer
я даже больше скажу, ты мог просто конвертировать функцию гуишную и самому посмотреть
function GetHeroStatBJ takes integer whichStat, unit whichHero, boolean includeBonuses returns integer
    if (whichStat == bj_HEROSTAT_STR) then
        return GetHeroStr(whichHero, includeBonuses)
    elseif (whichStat == bj_HEROSTAT_AGI) then
        return GetHeroAgi(whichHero, includeBonuses)
    elseif (whichStat == bj_HEROSTAT_INT) then
        return GetHeroInt(whichHero, includeBonuses)
    else
        // Unrecognized hero stat - return 0
        return 0
    endif
endfunction

private constant real MaxHeightStart = 200.0 + GetHeroInt( whichUnit, true ) * 3.00
28

» WarCraft 3 / Jass MythBusters

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
Загруженные файлы
28

» WarCraft 3 / Jass MythBusters

Unryze, не раз замечал как люди пытаются обойти функцию IsTerrainPathable путём проверки проходимости предметом (SetItemPosition) или юнитом (SetUnitPosition), по привычке сам начал использовать проверку предметом, можно об этом тоже пару слов добавить
28

» WarCraft 3 / Замок (The Castle)

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

не очень понравился скиллсет героев и монстров, всё скучное, половина будто вообще из редактора объектов, ланд простой, клиффы используются, ну в общем тема олдскула, есть секретики, нет выбора режима сложности, например чтобы счётчик смертей не падал и можно было бы пройти игру (желание заново проходить опять же, не очень, из-за не особо интересного геймплея)
блинк за ворота чтобы их открыть не сопровождается звуками будто шаман взламывает замок с другой стороны, да и ему не надо даже у ворот стоять, просто что-то там тикает ты бегаешь и дверь сама по себе открывается, у первого скелета минибосса таргетный лик смерти, больно дамажит увернуться нельзя, неприятно, приходится отбегать, хиляться и обратно нападать, щит от механика вроде вообще не спасает от него, короче нудненький кайт, который растягивает геймплей, урон от кушки орка не сильно ощущается, будто там множитель в 1.50, а не 2.50 урона
возможно конечно всё приведенное выше нивелируется какими-то супер классными боссами которые используют нонтаргет скиллы от которых можно увернуться, заблочить или парировать, и между атаками босса наносить ему урон, но мы не дошли до них
моя СУБЪЕКТИВНАЯ оценка: 3/10
сыро, стоит реворкнуть полностью скиллсет героев и монстров (хотя бы чтобы на ро не напоминали) и добавить выбор режима сложности (вплоть до бесконечного воскрешения)
но опять же напомню про дисклеймер, т.е. эта оценка вообще не имеет веса как и сам комментарий, потому я даже половину игры не прошёл

upd оказывается ворота не шаманом открывались, это напарник по совпадениям после блинка открывал их)
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заклинание готово!

Заказчик: NilasAran_39
Способность: Лесная Стена
Выполнено: Да

короче подробностей было очень мало поэтому остальное я сделал на своё усмотрение, все настройки в коде, я добавил комменты что можешь изменять
код
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


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

» WarCraft 3 / Способности и алгоритмы на заказ

NilasAran_39, лесная стена по направлению к точке каста или перпендикулярно кастующему?
28

» WarCraft 3 / Скорость Света "скилы под ключ"

XmegatronX, я на видео всё продемонстрировал уже, если у тебя не получается не значит что у других этого не произойдёт)

стоит фиксить я думаю
28

» WarCraft 3 / Где задается значение flat урона боевых барабанов?

В data только процентный урон который выше 1 или 100% не ставится.
а через шифт пробовал?
28

» WarCraft 3 / Содрогание "скилы под ключ"

молния на одном из светлячков на 0:20 не выглядит так, будто это было задумано
28

» Блог им. rsfghd / Миниспеллпак

Daro, но тут же нет аниместрелялок)
и карта для которой делался этот спеллпак не аниме
28

» Блог им. rsfghd / движение по безье

Daro, если кому-нибудь надо то пусть хоть статью из этой функции делают, я хвастаться не хочу потому что знаю что я самый помойный чел на хгм, который самостоятельно добился ровно ничего
большая часть материалов из этой страницы даже не моё и не благодаря мне, а благодаря NightSiren'у и Hate'у, которых добавил в благодарности, это они всё придумали, даже видео хейта без его разрешения взял, найтсирен мне не раз помогал подобными функциями и формулами
и ты не представляешь как мне будет стыдно если кто-то посмотрит на это и подумает "оо, dfgdfhg такие прикольные штуки делает крута", мысль об этом заставляет застрелиться
28

» WarCraft 3 / Дальнобойные атаки сквозь препятствия

код
не весь
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
Загруженные файлы
28

» WarCraft 3 / Условие 1 итем в количестве 3-х штук

Нейни, я на словах объяснил, можно даже не смотреть на тот код и результат сказанного не изменится
28

» Блог им. rsfghd / движение по безье

Vlod, без понятия, но если судить по истории сообщений он сделал это благодаря функции от найтсирена