32

» WarCraft 3 / Как сделать поглощение/блок урона в варкрафте 3.

Qulore, это работа с триггерами, суть заключается в повышение кол-ва задоровья юнита до кол-ва урона, которое нужно заблокировать, ровно перед уроном, а после все вернуть на место.
32

» WarCraft 3 / Как сделать поглощение/блок урона в варкрафте 3.

Какой патч?

Ну и придется работать с триггерами чтобы детектить урон.

когда то делал такую способность, код под като
код
Кода довольно много, и он несколько запутанный, от части из за визуального эффекта щита и кол-ва поглощенного урона.
function FormatAirportTrainingBar takes integer fp_n returns string
    local string str = ""

    if ( fp_n <= 0 ) then
        return str
    endif

    loop
        exitwhen fp_n < 10
        if ( udg__TempBarStyle == 0 ) then
            set str = str + "''''''''''"
        else
            set str = str + "||||||||||||||||||||"
        endif
        set fp_n = fp_n - 10
    endloop

    loop
        exitwhen fp_n <= 0
        if ( udg__TempBarStyle == 0 ) then
            set str = str + "'"
        else
            set str = str + "||"
        endif
        set fp_n = fp_n - 1
    endloop

    return str
endfunction

function UpdateAirportTrainingBar takes texttag tt, integer fp_nTick, integer fp_nTickMax returns nothing
    local integer nProgress
    local integer nLen
    local string strTT1
    local string strTT2

    if ( tt == null ) then
        call BJDebugMsg( "text tag hDZzRwuZxFQcXqaMPnML null" )
        return
    endif

    set nLen = R2I( I2R( fp_nTickMax ) / 300 * 100 )
    set nProgress = R2I( I2R( nLen ) / fp_nTickMax * fp_nTick )
    set strTT1 = "" + FormatAirportTrainingBar( nProgress )
    set strTT2 = FormatAirportTrainingBar( nLen - nProgress ) + ""
    call SetTextTagText( tt, "|cff0080c0" + strTT1 + "|r|cffff0000" + strTT2 + "|r", 0.023 )
endfunction

function Get_Staff_of_Purification takes unit runner returns item
    set bj_forLoopAIndex = 0
    set bj_lastCreatedItem = null
    
    if GetUnitAbilityLevel( runner, 'Arun' ) == 0 then
        return null
    endif
    
    loop
        exitwhen bj_forLoopAIndex > 5

        set bj_lastCreatedItem = UnitItemInSlot( runner, bj_forLoopAIndex )
        if GetItemTypeId( bj_lastCreatedItem ) == 'I01A' then
            return bj_lastCreatedItem
        endif

        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop

    return bj_lastCreatedItem
endfunction

function Trig_RunnerDamageDetect_Conditions takes nothing returns boolean
    if GetTriggerEventId( ) == EVENT_UNIT_DAMAGED then
        return GetEventDamage( ) > 0.00 and GetEventDamageSource( ) != GetTriggerUnit( ) and GetEventDamageSource( ) != DummyAttacker
    endif
    return true
endfunction

function HealRunner takes nothing returns nothing
    local DamageData dd = GetDataBX( GetExpiredTimer( ) )
    
    call UnitRemoveAbility( dd.attacked, 'AMhp' )
    call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp )
    
    call RemoveDataBX( dd.trix )
    call DestroyTimer( dd.trix )
    call dd.clear( )
    call dd.destroy( )
endfunction

function Trig_RunnerDamageLock_Actions takes nothing returns nothing
    local TriggerData st = GetDataBX( GetTriggeringTrigger( ) )
    local DamageData dd
    local eventid id = GetTriggerEventId( )
    
    if id == EVENT_GAME_TIMER_EXPIRED and st.id < st.time and st.attacked != null then
        set st.id = st.id + 1
        if GetUnitAbilityLevel( st.attacked, 'Bcyc' ) > 0  or GetUnitAbilityLevel( st.attacked, 'Bcy2' ) > 0 then
            call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 585.00 )
        else
            call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 80.00 + GetUnitFlyHeight( st.attacked ) )
        endif
        call UpdateAirportTrainingBar( st.tt, 100 - R2I( st.dmg / st.hp * 100.00 ), 100 )
        
    elseif id == EVENT_UNIT_DAMAGED and st.dmg < st.hp then
        set dd = DamageData.create( )
        set dd.trix = CreateTimer( )
        set dd.attacked = st.attacked
        set dd.dmg = GetEventDamage( )
        set dd.hp = GetUnitState( dd.attacked, UNIT_STATE_LIFE )
        
        call SetDataBX( dd.trix, dd )
        call UnitAddAbility( dd.attacked, 'AMhp' )
        call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp + dd.dmg )
        
        call TimerStart( dd.trix, 0.00, false, function HealRunner )
        if GetUnitAbilityLevel( st.attacked, 'B015' ) > 0 then
            set st.dmg = st.dmg + dd.dmg - dd.dmg * (0.10 * IMaxBJ( GetBuffLevel( GetUnitAbility( st.attacked, 'B015' ) ), 1 ) ) 
        else
            set st.dmg = st.dmg + dd.dmg
        endif
    else
        call UnitRemoveAbility( st.attacked, 'A08L' )
        call UnitMakeAbilityPermanent( st.attacked, false, 'A08L' )
        call DisableTrigger( st.trg )
        call SetTextTagVisibility( st.tt, false )
        
        if not IsUnitDead( st.attacked ) then
            call UnitRemoveAbility( st.attacked, 'B00A' )
        endif
        
        call RemoveSavedInteger( gg_htb_HashData, ExKeySoPRunner, GetHandleId( st.attacked ) )
        
        call st.RemoveTrigger( )
        call st.destroy( )
    endif
    
    set id = null
endfunction

function Trig_Staff_of_Purification_Actions takes nothing returns nothing
    local TriggerData dd
    local unit Runner = GetSpellAbilityUnit( )
    local integer RunnerId = GetHandleId( Runner )
    local item Staff = LoadItemHandle( gg_htb_HashData, RunnerId, ExKeySoP )
    local integer ChargesCount = 0
    local trigger trig = LoadTriggerHandle ( gg_htb_HashData, ExAtomShield, RunnerId )
    local integer pBuff = 0
    
    if Staff == null then
        set Staff = Get_Staff_of_Purification( Runner )
         
        if Staff == null then
            //call DisplayTextToPlayer( Player( CrashPlayerNumber ), 0.00, 0.00, I2Sx( 'A01Q', CrashPlayerNumber ) )
            call BJDebugMsg( DEBUG + I2Sx( 'A02O', 0 ) + INFO )
            return
        endif
        
        call SaveBoolean( gg_htb_HashData, RunnerId, ExKeyHasStaff, true )
        call SaveItemHandle( gg_htb_HashData, RunnerId, ExKeySoP, Staff )
    endif
    
    set ChargesCount = GetItemCharges( Staff )
    
    if ChargesCount < 1 then
        set Runner = null
        set Staff = null
        set trig = null
        return
    endif
    
    call SetItemCharges( Staff, 0 )
    
    // блокирующие урон способности не складываются.
    //============================================================================================
    if trig != null then
        call TriggerExecute( trig )
    endif
    
    set trig = LoadTriggerHandle( gg_htb_HashData,  ExEtherialShell, RunnerId )
    
    if trig != null then
        call TriggerExecute( trig )
    endif
    
    set trig = null
    
    // Необходимо сбросить PhaseShift для корректной работы щита.
    
    if GetUnitAbilityLevel( Runner, 'Bpsh' ) > 0 then
        call UnitRemoveAbility( Runner, 'Bpsh' )
        call SetUnitInvulnerable( Runner, false )
    endif
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    set dd = TriggerData.create( )
    set dd.attacked = Runner
    set dd.pl = GetOwningPlayer( Runner )
    set dd.trg = CreateTrigger( )
    set dd.trc = TriggerAddCondition( dd.trg, Condition( function Trig_RunnerDamageDetect_Conditions ) )
    set dd.tra = TriggerAddAction ( dd.trg, function Trig_RunnerDamageLock_Actions )
    set dd.tt = CreateTextTag( )
    set dd.hp = 1000.00 * ChargesCount
    set dd.dmg = 1.00
    set dd.id = 0
    set dd.time = 480
    set dd.c = 0.03125
    
    call UnitAddAbility( Runner, 'A07E' )
    set pBuff = GetUnitAbility( Runner, 'A07E' )
    if pBuff > 1  then
       call  SetAbilityHidden( pBuff, 1 )
    endif
  
    call UnitAddAbility( Runner, 'A08L' )
    call UnitMakeAbilityPermanent( Runner, true, 'A08L' )
    
    call SetDataBX( dd.trg, dd )
    call SaveInteger( gg_htb_HashData, ExKeySoPRunner, RunnerId, dd )
    
    call TriggerRegisterPlayerEvent( dd.trg, dd.pl, EVENT_PLAYER_LEAVE )
    call TriggerRegisterDeathEvent( dd.trg, Runner )
    call TriggerRegisterUnitEvent( dd.trg, Runner, EVENT_UNIT_DAMAGED )
    
    call TriggerRegisterTimerEvent( dd.trg, 0.03125, true )
    
    if GetLocalPlayer( ) == dd.pl or IsPlayerAlly( GetLocalPlayer( ), dd.pl ) then
        call SetTextTagVisibility( dd.tt, true )
    else
        call SetTextTagVisibility( dd.tt, false )
    endif
    
    set pBuff = GetUnitAbility( Runner, 'B00A' )
    
    if pBuff < 1 then
        call BJDebugMsg(DEBUG+" " + GetAbilityEffectById( 'A07E', EFFECT_TYPE_TARGET, 1) )
        call BJDebugMsg(INFO)
        return
    endif
    
    set dd.c = TimerGetElapsed( DispTimer )
    call WMem( RMem( pBuff + 0x90 ) + 0x4, mR2I( dd.c + 15.10 ) )
    call WMem( RMem( pBuff + 0x90 ) + 0x8, mR2I( dd.c + 10.408 ) )
    call UpdateAirportTrainingBar( dd.tt, 100, 100 )
    call UnitRemoveAbilityTimed( Runner, 'A07E', 0.00)
    
    set Runner = null
endfunction
    
//===========================================================================
function InitTrig_Staff_of_Purification takes nothing returns nothing
    set udg__TempBarStyle = 0
endfunction
32

» WarCraft 3 / Проблема с наклоном юнитов через РО и отображением в игре

Maxsavin, да чему удивляться, игра еще очень сырая, и нужно ждать стабильной версии.
Кстати, к модели даммика можно крепить эффект если есть соответствующие кости, так к примеру шипы анубарака и смерч кенариуса сделан. Сделай дамми у которого на модели есть кости которые вращаются исходя из анимации.
32

» WarCraft 3 / Проблема с наклоном юнитов через РО и отображением в игре

Мб юзать дамика с анимацией наклона, где 1 анимация это 1 градус наклона, была где то такая модель...
32

» WarCraft 3 / Уточнение по поводу текстур.

Для каждого типа ландшавта свои имена текстур, придется копировать для всех типов ланда или сделать хак который в памяти игры уже работал с текстурами ланда. Но зачем это нужно, нельзя разработать карту с 10 видами тайслетов, тайслет может быть только 1 и вроде 16 тайлов, которые можно выбрать кастомные. Лимит никак не убрать, т.к это особенность формата тайлов ни у одного ландшавта больше N быть не может.
32

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

newtone, есть 2 рева, рев медведей и рев рексара (это 2 разные способности с разными баффами).
32

» WarCraft 3 / Условие победы, N-ое количество юнитов

Если некромант именно призывает скелетов стандартной способностью, То событие триггера - Юнит игрока (указываешь нужного тебе игрока) Призывает юнита. ( Player Unit Event, Event player unit summon). В условии указываешь что TypeId призванного юнита == скелету ( через or можно указать несколько типов скелетов, обычные и скелеты маги к примеру). И действие, записать в переменную + 1, если кол-во в переменной 100 или больше то делать че ты там хочешь.
32

» WarCraft 3 / Вылетает лобби при попытке захостить карту

Возможно проблема в способностях или строках, близзарды че только не сломали и нужно ждать стабильной версии игры где вылечат 99% глюков, багов и завезут максимальную совместимость со старыми картами.
32

» WarCraft 3 / Не всегда срабатывает триггер

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

» WarCraft 3 / Не всегда срабатывает триггер

Ну самого кастера я заношу в отдльную переменную и исключаю его из группы, ищем только ближайших союзников не фулл хп, случайных.
На юнитах хил это своего рода бафф, он висит на них все время дейсвия или до их сметри.
Кстати запоминать кол-во статов героя на момент каста или опрашивать каждый тик?
32

» WarCraft 3 / Не всегда срабатывает триггер

Desgul, я не совсем понял что там, по видео задумку скилла понять сложно, поэтому и опрашиваю че да как.

Юниты берутся в группу только при касте или и во время работы скилла, вот так всегда, попробуй пойти что хочет заказчик?
32

» WarCraft 3 / Не всегда срабатывает триггер

Desgul, а ну ок, я думал что случайных.

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

» WarCraft 3 / Не всегда срабатывает триггер

Ну вот склепл на скорую руку, все по минимуму, абилка учитывает смерть кастера и кол-во хп, лечит ближайших юнитов, хотел добавить проверку на фулл хп, чтобы исключить лечение фулл-хп юнитов, но пока не сделал, это уже автору виднее.
Загруженные файлы
32

» WarCraft 3 / Урон после наведения и использования способности

8gabriel8, больше скажу, 0 урона наносится 100500 раз, ибо с ним связаны всякие модификаторы, этот урон юзаетсся для агра нейтралов (типа ты спелл пустил). Настройка канала - универсальное заклинание, уберет 0 урона при касте и канал перестанет вызывать срабатывание амулета защиты и аналога.
Удары из инвиза тоже наносят 0 урона в линку, основной урон блокируется, в структуру атаки пишутся флаги и всякие адресса то цели, то абилки то еще хз чего, не ясно что хотели сделать близзарды, но это факт технический урон юзается очень широко.
32

» WarCraft 3 / Не всегда срабатывает триггер

ну я могу сделать плавное лечение, каждые 0.25 сек, но в 1 секунду герой будет поулчать твои 70% от разума хп (или как там у тебя).
32

» WarCraft 3 / Не всегда срабатывает триггер

Т.е после каста начинает лечить всех вокруг включая кастера, кастера приоритетнее чем союзника, допустимые цели?
Там живые, союзники, не здания, не варды?
32

» WarCraft 3 / Вылетает лобби при попытке захостить карту

Наверное карта не совместима из за каких то особенностей, что такого есть в карте? Хекс защиты, мемхаки, специфический импорт?