28

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

Desgul, если не принципиально, то бишь не включая тех. хар-ки, то это без проблем делается
28

» WarCraft 3 / Autumn

как же радуют глаз такие ланды, качественные, ты шикарен, продолжай делать такое добро
28

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

Гуванч, что непонятного?)
10 секунд висит бафф который позволяет накладывать кровотечение с атак и умений длиной 6 сек, сам спелл упирается либо в мемхак либо наличие триггерных спеллов у данного героя, потому что там не все источники урона от юнита, а с указанием конкретных спеллов
28

» WarCraft 3 / Пытаюсь создать кастомного героя.

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

» WarCraft 3 / Движение по кругу

Гуванч, чёт кривовато вышло

ну.. наверное так надо, хз

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

у Анашина движение совсем по другому реализовано, покрасивее но механически похоже не подошло автору
Загруженные файлы
28

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

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

Заказчик: Desgul
Способность: Рывок урсока
Выполнено: Да

инструкция по иморту
копируешь триггер Spell и смотришь на код, там всего 100 строк, а основное, что нужно отредактировать имеет комментарии
ты не просил, но я накинул рандомные эффекты, можешь их удалить, они находятся в функции Move и имеют начало call DestroyEffect( ...
код
library SpellLib
globals
    constant hashtable H = InitHashtable( )
    private constant integer SpellID = 'A000' // спелл прыжка
    private constant integer SpellCD = 'A000' // спелл которому сбросить кд
endglobals

private struct SpellS
    unit caster
    unit target
    real speed
    real damage
    real range
    attacktype AttackType
    damagetype DamageType
endstruct

native UnitAlive takes unit id returns boolean

// само движение
private function Move takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local real x   = GetUnitX( A.caster )
    local real y   = GetUnitY( A.caster )
    local real x1  = GetUnitX( A.target )
    local real y1  = GetUnitY( A.target )
    local real d   = SquareRoot( ( x - x1 ) * ( x - x1 ) + ( y - y1 ) * ( y - y1 ) )
    local integer i
    
    set x = x + A.speed * ( ( x1 - x ) / d )
    set y = y + A.speed * ( ( y1 - y ) / d )
    
    call SetUnitX( A.caster, x )
    call SetUnitY( A.caster, y )
    call IssueImmediateOrder( A.caster, "stop" )
    
    if SquareRoot( ( x - x1 ) * ( x - x1 ) + ( y - y1 ) * ( y - y1 ) ) <= A.range + A.speed or GetUnitTypeId( A.target ) == 0 or not UnitAlive( A.caster ) then
        if UnitAlive( A.caster ) and GetRandomInt( 0, 100 ) <= 15 then // восстановить хп юниту с 15% шансом
            call SetWidgetLife( A.caster, GetWidgetLife( A.caster ) + GetUnitState( A.caster, UNIT_STATE_MAX_LIFE ) * 0.15 )
            call DestroyEffect( AddSpecialEffectTarget( "Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl", A.caster, "origin" ) )
        endif
        
        if GetRandomInt( 0, 100 ) <= 15 then // ресетнуть абилку с 15% шансом
            set i = GetUnitAbilityLevel( A.caster, SpellCD )
            call UnitRemoveAbility( A.caster, SpellCD )
            call UnitAddAbility( A.caster, SpellCD )
            call SetUnitAbilityLevel( A.caster, SpellCD, i )
        endif
        
        call UnitDamageTarget( A.caster, A.target, A.damage, false, false, A.AttackType, A.DamageType, null )
        call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\Human\\HumanLargeDeathExplode\\HumanLargeDeathExplode.mdl", x1, y1 ) )
        
        call SetUnitPathing( A.caster, true )
        call FlushChildHashtable( H, GetHandleId( GetExpiredTimer( ) ) )
        call PauseTimer( GetExpiredTimer( ) )
        call DestroyTimer( GetExpiredTimer( ) )
        set A.caster = null
        set A.target = null
        call A.destroy( )
    endif
endfunction

private function SetAnim takes nothing returns nothing
    local SpellS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    
    // выставление анимок кастеру
    call SetUnitAnimation( A.caster, "attack slam" )
    call QueueUnitAnimation( A.caster, "stand" )

    call TimerStart( GetExpiredTimer( ), 0.01, true, function Move ) // периодичность полёта
endfunction

function Spell_Actions takes nothing returns boolean
    local timer t
    local SpellS A
    
    if GetSpellAbilityId( ) == SpellID then
        set t = CreateTimer( )
        set A = SpellS.create( )
        
        set A.caster = GetTriggerUnit( )     // тот, кто полетит
        set A.target = GetSpellTargetUnit( ) // тот, в кого полетят
        set A.range  = 100.00 // дистанция столкновения
        set A.speed  = ( SquareRoot( ( GetUnitX( A.caster ) - GetUnitX( A.target ) ) * ( GetUnitX( A.caster ) - GetUnitX( A.target ) ) + ( GetUnitY( A.caster ) - GetUnitY( A.target ) ) * ( GetUnitY( A.caster ) - GetUnitY( A.target ) ) ) - A.range ) * 0.015 // скорость
        set A.damage = GetHeroAgi( A.caster, true ) * ( 2.25 * GetUnitAbilityLevel( A.caster, SpellID ) ) // урон
        set A.AttackType = ATTACK_TYPE_NORMAL // тип атаки
        set A.DamageType = DAMAGE_TYPE_NORMAL // тип урона
        
        call SetUnitPathing( A.caster, false )
        call SaveInteger( H, GetHandleId( t ), 0, A )
        call TimerStart( t, 0.00, false, function SetAnim )
        
        set t = null
    endif
    
    return false
endfunction

//===========================================================================
function InitTrig_Spell takes nothing returns nothing
    local integer index = 0
    set gg_trg_Spell    = CreateTrigger(  )
    
    loop
        call TriggerRegisterPlayerUnitEvent( gg_trg_Spell, Player( index ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )
        set index = index + 1
        exitwhen index >= 16
    endloop
    call TriggerAddCondition( gg_trg_Spell, Condition( function Spell_Actions ) )
endfunction

endlibrary


Загруженные файлы
28

» WarCraft 3 / Движение по кругу

в карте для конкурса Crusader есть светляк ночью, вот его код движения
function Wisp_Actions takes nothing returns nothing
    local real x1 = GetUnitX( Wisp )
    local real y1 = GetUnitY( Wisp )
    local real x  = GetUnitX( MainUnit ) + Distance * Cos( CircleA )
    local real y  = GetUnitY( MainUnit ) + Distance * Sin( CircleA )
    local real a  = Atan2( y - y1, x - x1 )
    local real d  = SquareRoot( ( x1 - x ) * ( x1 - x ) + ( y1 - y ) * ( y1 - y ) ) * 0.01
    
    set CircleA = CircleA + 1 * bj_DEGTORAD

    call SetUnitX( Wisp, x1 + d * Cos( a ) )
    call SetUnitY( Wisp, y1 + d * Sin( a ) )
    if WispExplodeB then
        call SetUnitFlyHeight( Wisp, GetUnitFlyHeight( MainUnit ) + 90, 0 )
    endif
endfunction
ничего сложного, MainUnit вокруг которого движется висп, CircleA, угол для движения в точку вокруг юнита, Distance - расстояние движения от юнита, чтобы постепенно оно влетало в юнита можно просто уменьшать эту дистанцию, но у меня оно было фиксированным

хотя код и механика одинакова
код не одинаков же
28

» WarCraft 3 / Движение по кругу

какой-то знакомый код, неужели Анашина?

Гуванч, почему ты не хочешь помочь человеку тут? все смогут увидеть решение проблемы
28

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

Заказ принят

Заказчик: Desgul
Способность: Рывок урсока
Спелл будет завершен к: примерно через час

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

» WarCraft 3 / Дополнительные ресурсы

Komkozavr, я и так мало кому своё слово сдержал, не обламывай меня хотя бы на обычной таблице с кастомными ресурсами
28

» WarCraft 3 / Дополнительные ресурсы

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

» WarCraft 3 / Дополнительные ресурсы

Komkozavr, делать локальную таблицу для каждого игрока с его ресурсами, вот и всё

в любом случае работа с мультибордом утечна, и для этого желательно разобрать джасс
28

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

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

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

утечек нет, можешь не волноваться, закинул счётчик хэндлов как показатель, он растёт разово только потому что идёт присвоение глобалкам в первый раз, в общем-то, можно не ориентироваться на него
инструкция по импорту
триггер Spell это сам спелл (кэп), там редачить нечего в принципе, только переменная хэш-таблицы (об этом ниже)
триггер SpellCast включает в себя настройки и прочую пургу, ты разберёшься, я везде комменты расставил что можно редачить
триггер OnDamage вызывается после нанесения урона юниту, там ты можешь свои действия пихать, я оставил там пример с созданием эффекта на юните
триггер отделенный комментарием тебе не нужен
если у тебя есть переменная с названием H, то пройдись по коду триггера Spell автозаменой по этой букве, если у тебя уже есть хэш-таблица, то можешь закомментить третью строку и опять же, пройтись автозаменой с указанием своей хэш-таблицы, если всё это делать лень, добавь приставку private, тогда никаких несостыковок не будет, но имей ввиду, макс колво объявлений хэш-таблиц 255 вроде
если что-то не работает или работает не так, как ты хотел, или же нужна помощь с импортом - пиши в лс
код
library SpellLib
globals
    constant hashtable H           = InitHashtable( )
    private constant group TempG   = CreateGroup( )
    private constant group TempG_1 = CreateGroup( )
    private attacktype AttackType  = null
    private damagetype DamageType  = null
    private boolexpr TempBoolexpr  = null
    private real TempReal
endglobals

private struct SpellS
    unit caster
    real damage
    real radius
    real damagePeriodic
    real time
    group g
    attacktype AttackType
    damagetype DamageType
    boolexpr b
endstruct

private function Damage_2 takes nothing returns nothing
    set udg_TempUnit = GetEnumUnit( )
    if not IsUnitInGroup( udg_TempUnit, TempG_1 ) then
        call GroupAddUnit( TempG_1, udg_TempUnit )
        call UnitDamageTarget( udg_LastCaster, udg_TempUnit, TempReal, false, false, AttackType, DamageType, null )
        call TriggerExecute( gg_trg_OnDamage )
    endif
endfunction

private function Damage_1 takes nothing returns nothing
    call GroupEnumUnitsInRange( TempG, GetUnitX( GetEnumUnit( ) ), GetUnitY( GetEnumUnit( ) ), TempReal, TempBoolexpr )
    call ForGroup( TempG, function Damage_2 )
    call GroupClear( TempG )
endfunction

private function Damage takes nothing returns nothing
    local timer t  = GetExpiredTimer( )
    local SpellS A = LoadInteger( H, GetHandleId( t ), 0 )
    local unit u
    
    set A.time = A.time - A.damagePeriodic
    
    set AttackType     = A.AttackType
    set DamageType     = A.DamageType
    set TempBoolexpr   = A.b
    set udg_LastCaster = A.caster
    set TempReal       = A.radius
    call ForGroup( A.g, function Damage_1 )
    call GroupClear( TempG_1 )
    
    if A.time <= 0.00 then
        call FlushChildHashtable( H, GetHandleId( t ) )
        call DestroyTimer( t )
        
        loop
            set u = FirstOfGroup( A.g )
            exitwhen u == null
            call KillUnit( u )
            call GroupRemoveUnit( A.g, u )
        endloop
        
        call DestroyGroup( A.g )
        set A.g      = null
        set A.caster = null
        call A.destroy( )
    else
        call TimerStart( t, A.damagePeriodic, false, function Damage )
    endif
    
    set t = null
endfunction

function Spell_Actions takes unit caster, integer id, attacktype at, damagetype dt, real damage, real x, real y, real weight, real radius, real distance, real damagePeriodic, real time, boolexpr blxpr returns nothing
    local timer t   = CreateTimer( )
    local SpellS A  = SpellS.create( )
    local boolean b = true
    local real d    = distance / 2
    local real a    = Atan2( y - GetUnitY( caster ), x - GetUnitX( caster ) )
    local real xl   = Cos( a + ( 90 * bj_DEGTORAD ) )
    local real yl   = Sin( a + ( 90 * bj_DEGTORAD ) )
    local unit u
    
    set A.damage = damage
    set A.caster = caster
    set A.radius = radius
    set A.time   = time
    set A.b      = blxpr
    set A.AttackType     = at
    set A.DamageType     = dt
    set A.damagePeriodic = damagePeriodic
    
    set A.g    = CreateGroup( )
    set weight = weight / 2
    set bj_groupEnumOwningPlayer = GetOwningPlayer( A.caster )
    loop
        if b then
            set u = CreateUnit( bj_groupEnumOwningPlayer, id, x + d * xl, y + d * yl, 0.00 )
            set b = false
        else
            set u = CreateUnit( bj_groupEnumOwningPlayer, id, x - d * xl, y - d * yl, 0.00 )
            set b = true
            set d = d + distance
        endif
        call GroupAddUnit( A.g, u )
        exitwhen d >= weight
    endloop
    
    call SaveInteger( H, GetHandleId( t ), 0, A )
    call TimerStart( t, 0.00, false, function Damage )
    
    set u = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Spell takes nothing returns nothing
    //set gg_trg_Spell = CreateTrigger(  )
endfunction
endlibrary
Загруженные файлы
28

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

Заказ принят

Заказчик: mistwood
Способность: Призрачная стена
Спелл будет завершен к: без понятия
28

» WarCraft 3 / Что может вызвать утечки в этой системе инкома?

ай упс, только не уничтожай группу, а очищай её, протупил

на гуи есть функция очистки группы, но если что вот кс: call GroupClear( udg_TempGroup )

т.к. новая группа не создаётся, если ты удалишь её, то оно перестанет работать

на самом деле это ещё один плюс к твоей оптимизации
28

» WarCraft 3 / Что может вызвать утечки в этой системе инкома?

VinerX, лол, то есть в моей карте ты эту переменную видишь, она там есть в наличии? В твоей собственной её нет?

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

» WarCraft 3 / Что может вызвать утечки в этой системе инкома?

вот пример юза

Перечитал несколько раз, чет нету. В рефордже она остается?
без понятия, я за реф не шарю, мб как-то по другому называется, на скрине определить это не могу
Загруженные файлы
28

» WarCraft 3 / Что может вызвать утечки в этой системе инкома?

VinerX, делать выбор группы через кастомскрипт

т.к. ты гуишник могу посоветовать в редакторе переменных создать переменную булекспра (она в самом низу списка где-то находится), потом через кастом скрипт call GroupEnumUnitsInRect( udg_Group, bj_mapInitialPlayableArea, udg_Boolexpr ), можешь дальше обращаться к этой группе на гуи, очистив потом

в данном случае оно выбирает всех юнитов на карте, но через условия указанные в твоём булекспре

есть так же
native GroupEnumUnitsOfPlayer takes group whichGroup, player whichPlayer, boolexpr filter returns nothing
это выбор всех юнитов игрока

ну и
native GroupEnumUnitsInRangeOfLoc takes group whichGroup, location whichLocation, real radius, boolexpr filter returns nothing

остальное смотри уже сам, по необходимости
28

» WarCraft 3 / Что может вызвать утечки в этой системе инкома?

quq_CCCP, а, да, точно
function GetUnitsInRectMatching takes rect r, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRect(g, r, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction
локалка не обнуляется в создании группы
28

» WarCraft 3 / Система снаряда с настройками

under11, не в этом дело, для демонстрации нужно всегда закидывать счётчик хэндлов и показатель сколько урона нанесено