Добавлен , опубликован
Способ реализации:
Версия Warcraft:
Заклинание с движением огненного шара для новичков и не только. С правильным рассчётом в движении и плавностью.

Видео

Код

globals    
    hashtable HT = InitHashtable()
    group Group = CreateGroup()

    unit Caster
    unit Dummy
    unit Target
    
    real Angle
    real CasterX
    real CasterY
    real DummyX
    real DummyY
    
    timer Timer
    integer TimerId
    integer Tick
    real Time
    real TimeEase //Переменная для просчёта плавности

    constant real Fireball_TimerPeriod = 0.03
    constant real Fireball_Distance = 1000
    constant real Fireball_Speed = 900
    constant real Fireball_Range = 250
    constant real Fireball_Damage = 3
    constant integer Fireball_EffectLimit = 3
endglobals

native UnitAlive takes unit id returns boolean

function Fireball_Group takes nothing returns nothing
    set Target = GetEnumUnit()
    
    if UnitAlive( Target ) and IsUnitEnemy( Target, GetOwningPlayer( Caster ) ) and not IsUnitType( Target, UNIT_TYPE_STRUCTURE ) then
        call UnitDamageTarget( Caster, Target, Fireball_Damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS )
    endif
endfunction

function Fireball_Timer takes nothing returns nothing
    set Timer = GetExpiredTimer()
    set TimerId = GetHandleId( Timer )
    
    set Caster = LoadUnitHandle( HT, TimerId, 'cstr' )
    set Dummy = LoadUnitHandle( HT, TimerId, 'dumm' )
    set Tick = LoadInteger( HT, TimerId, 'tick' )
    
    set Time = ( Tick * Fireball_TimerPeriod ) / ( Fireball_Distance / Fireball_Speed ) //Пройденное время делится на общее время
    set TimeEase = Time * Time //Для плавности, если она не нужна, то удалить строчку, удалить переменную TimeEase, и ниже везде в 2 функциях заменить эту переменную на Time
    //set TimeEase = Sin( Time * bj_PI ) / 2  //Ещё одна приколюха :)
    set DummyX = LoadReal( HT, TimerId, 'minX' ) * ( 1 - TimeEase ) + LoadReal( HT, TimerId, 'maxX' ) * TimeEase //Для правильного движения фаерболла по оси X
    set DummyY = LoadReal( HT, TimerId, 'minY' ) * ( 1 - TimeEase ) + LoadReal( HT, TimerId, 'maxY' ) * TimeEase //Тоже самое но с Y
    
    if GetRectMinX( bj_mapInitialPlayableArea ) <= DummyX and DummyX <= GetRectMaxX( bj_mapInitialPlayableArea ) and GetRectMinY( bj_mapInitialPlayableArea ) <= DummyY and DummyY <= GetRectMaxY( bj_mapInitialPlayableArea ) then //Условие что-бы фаерболл не вылетел за карту, и не произошёл Fatal Error
        call SetUnitX( Dummy, DummyX )
        call SetUnitY( Dummy, DummyY )
        
        if Tick == ( Tick / Fireball_EffectLimit ) * Fireball_EffectLimit then //Ограничение по эффектам, менять как и всё остальное сверху в константах
            call DestroyEffect( AddSpecialEffect( "Objects\\Spawnmodels\\Other\\NeutralBuildingExplosion\\NeutralBuildingExplosion.mdl", DummyX, DummyY ) )
            call DestroyEffect( AddSpecialEffect( "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl", DummyX, DummyY ) )
        endif
    endif
    
    call GroupEnumUnitsInRange( Group, DummyX, DummyY, Fireball_Range, null )
    call ForGroup( Group, function Fireball_Group )
    call GroupClear( Group )
    
    call SaveInteger( HT, TimerId, 'tick', Tick + 1 )
    
    if Time >= 1 then
        call RemoveUnit( Dummy )
        call PauseTimer( Timer )
        call DestroyTimer( Timer )
        call FlushChildHashtable( HT, TimerId )
    endif
endfunction

function Fireball_Actions takes nothing returns nothing
    if GetSpellAbilityId() == 'A000' then
        set Caster = GetTriggerUnit()
        set CasterX = GetUnitX( Caster )
        set CasterY = GetUnitY( Caster )
        
        set Angle = Atan2( GetSpellTargetY() - CasterY, GetSpellTargetX() - CasterX ) //Просчитывается угол от позиции кастера в сторону каста
        set CasterX = CasterX + 50 * Cos( Angle ) //Просчитывается смещение в сторону ранее просчитанного угла
        set CasterY = CasterY + 50 * Sin( Angle ) //Тоже что и CasterX но CasterY
        
        set Timer = CreateTimer()
        set TimerId = GetHandleId( Timer )
        
        call SaveUnitHandle( HT, TimerId, 'cstr', Caster )
        call SaveUnitHandle( HT, TimerId, 'dumm', CreateUnit( GetTriggerPlayer(), 'h001', CasterX, CasterY, Angle ) )
        call SaveReal( HT, TimerId, 'minX', CasterX )
        call SaveReal( HT, TimerId, 'minY', CasterY )        
        call SaveReal( HT, TimerId, 'maxX', CasterX + Fireball_Distance * Cos( Angle ) ) //Тут сохраняется координата X, но смещённая на + 1000 в сторону каста
        call SaveReal( HT, TimerId, 'maxY', CasterY + Fireball_Distance * Sin( Angle ) ) //Тоже самое что и X но Y
        call SaveInteger( HT, TimerId, 'tick', 0 )
        call TimerStart( Timer, Fireball_TimerPeriod, true, function Fireball_Timer )
    endif
endfunction

function InitTrig_Fireball takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer i = 0
    
    loop
        call TriggerRegisterPlayerUnitEvent( t, Player( i ), EVENT_PLAYER_UNIT_SPELL_EFFECT, null )
        set i = i + 1
        exitwhen i == bj_MAX_PLAYER_SLOTS
    endloop
    
    call TriggerAddAction( t, function Fireball_Actions )  
    set t = null
    
    call FogEnable( false )
    call FogMaskEnable( false )
endfunction

Требования

Скопировать код из шапки карты и триггера со спеллом к себе на карту, если такие глобальные переменные уже имеются, то копировать не надо. Поменять равкод способности в константах если он другой (скорее всего другой). Скопировать импортированные файлы к себе на карту.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Этот комментарий удален
24
Красиво, а с практической точки зрения, 3-4 игрока выполняющие каст одновременно, не заминусуют Fps в игре? 😅
10
фпс дроп как от ульта шейкера в 2008
чего не хватает, чтобы избежать его?
Ответы (6)
24
Slonick, у шейкера разве было так много эффектов, его фиссура кажется проходила куда быстрее, чем эти огненные столбы.
Что ешо за фпс дроп?
+ Вопрос, про одновременные касты, причем тут шейкер...
26
RvzerBro, речь про эхо-слэм - ульт Шейкера, на основе веера ножей который, там много шок-вейвов разлетается.
24
Extremator, опять же, ответ не в те ворота, причём тут шейкер и способ его реализации, он кастует Один, а я спросил про несколько кастеров 😡
18
Slonick, скорее всего такую нагрузку дает создание такого кол-ва эффектов с этой моделькой огня.
24
Extremator, а лол я понил, он не ответил мне) а написал про тоже, шо и я 😅 Пардоньте
26
RvzerBro, он спросил про просадку FPS как при ульте Шейкера - там создаётся много дамми и они спавнят много моделек шок-вейва. Это обычно поднагружало рендер. На видео спамятся модельки оставляющие что-то типа уберсплатов, и их довольно много, поэтому при мульти-юзе будет тонна этих эффектов. Это всё же проблема, но не большая, т.к. точно такой же скилл раньше юзали называя его "катон" во всех "наруто-картах", и даже в больших масштабах.
RvzerBro, ты же упомянул фиссуру Шейкера, которая спавнила деструктейблы (разрушаемые объекты) в виде груд камней, которые временно существовали и мешали пройти. Да, в момент их спавна проигрывается спецэффект вулкана, который раскидывает искры, но это совсем не то, видимо.
Одновременные касты скиллов со спамом таких эффектов явно не являются пиком среди красивых и правильных реализаций, но - почему нет?))
15
if Tick == ( Tick / Fireball_EffectLimit ) * Fireball_EffectLimit then
=
if Tick == Tick then
ограничение создания эффектов не работает отсюда и проседы фпс
Ответы (5)
15
LastUchiha, если и работает то крайне неинтуитивно (мне сонному в 4 часа ночи непонятно :) ), стоит объяснить в комментах либо переписать понятно ИМХО.
Типа, вот Fireball_EffectLimit = 3, и чё это 3 значит? Мне надо больше или меньше ставить чтобы не лагало?
А так спелл норм, но этот момент непонятен вообще.
30
ограничение создания эффектов не работает
У тебя с математекой всё в порядке? Сколько будет в целых числах 10 / 3 * 3?
15
nazarpunk, ладно, да, проглядел что константа интовая. Непривычный для меня способ такие вещи делать. Пойду спать...
30
Мне надо больше или меньше ставить чтобы не лагало?
Это значит что эффект будет спавниться каждое третье срабатывание таймера. Поставь больше, спавна станет меньше.
15
Отлично подойдет для ульты какому-нибудь магу! Единственное что, не хватает горения жертв после "прокатки" по ним огненного шара.
Ответы (4)
16
Meddin, ну если ульту делать, мне кажется неплохо было бы в конце взрыв накинуть, ну и да, поджигать тоже.
26
Meddin, временный бафф с периодическим уроном - это по сути как отдельный скилл. Просто делаешь его и добавляешь активацию в момент нанесения урона юнитам - они дамажатся и поджигаются.
26
LastUchiha, оно же и так "взрывается" по мере своего движения.))
16
Extremator, ну ты всё равно понял что я имел ввиду)
Можно же ещё красотуль натаскать...
2
没有想到,在国外还有这么有趣的论坛,在讨论这一个我童年回忆的游戏。
Этот комментарий удален
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.