Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
vJass
Тип:
Способность
Версия Warcraft:
1.26+

Пирокластическое уничтожение

Герой призывает древнее энтропическое существо, которое подготавливает мощный луч солнечного ветра, что стирает всё на своём пути
код
library PyroclasticDestructionLib
globals
    private constant hashtable H = InitHashtable( )
    private constant group TempGroup  = CreateGroup( )
    private constant group TempGroup1 = CreateGroup( )
    private constant timer TempTimer  = CreateTimer( )
    private constant location LFZ = Location( 0.00, 0.00 )
    private constant real DamagePeriodic = 0.10
    
    private constant integer ExplosionID          = 'u006'
    private constant integer SalamanderID         = 'u009'
    private constant integer DarkRitualID         = 'u00A'
    private constant integer ItemStrengthGainID   = 'u00B'
    private constant integer MirrorImageID        = 'u00C'
    private constant integer ReviveHeroInstanlyID = 'u00D'
    private constant integer WarStompID           = 'u00E'
    private constant integer SmallFlameSpawnID    = 'u00F'
    private constant integer DoomID               = 'u00G'
    private constant integer IncinerateID         = 'u00H'
    private constant integer Explosion90ID        = 'u00I'
    private constant integer FireID               = 'u00J'
    private constant integer ReviveHeroID         = 'u00K'
    private constant integer BloodLustID          = 'u00L'
    private constant integer RedLightOmniID       = 'u00M'
    
    private real MaxX
    private real MinX
    private real MaxY
    private real MinY
    private real TempReal = 0.00
    private unit TempUnit = null
endglobals

private function GetLocZ takes real x, real y returns real
    call MoveLocation( LFZ, x, y )
    return GetLocationZ( LFZ )
endfunction

private function CreateUnitEx takes player id, integer unitid, real x, real y, real face returns unit
    if x > MaxX then
        set x = MaxX
    elseif x < MinX then
        set x = MinX
    endif
    
    if y > MaxY then
        set y = MaxY
    elseif y < MinY then
        set y = MinY
    endif
    
    set TempUnit = CreateUnit( id, unitid, x, y, face )
    call SetUnitX( TempUnit, x )
    call SetUnitY( TempUnit, y )
    
    return TempUnit
endfunction

private struct PyroclasticDestructionS
    unit caster
    unit dummy
    player p
    boolexpr b
    
    real x
    real y
    real a
    real ax
    real ay
    real time
    real damage
endstruct

private function PyroclasticDestructionDamage takes nothing returns nothing
    local PyroclasticDestructionS A = LoadInteger( H, GetHandleId( GetExpiredTimer( ) ), 0 )
    local unit u
    local real x = A.x
    local real y = A.y
    local integer i = 8
    
    set TempUnit = A.caster
    
    loop
        call GroupEnumUnitsInRange( TempGroup, x, y, 700.00, A.b )
        
        loop
            set u = FirstOfGroup( TempGroup )
            exitwhen u == null
            call GroupRemoveUnit( TempGroup, u )
            
            if not IsUnitInGroup( u, TempGroup1 ) and IsUnitInRangeXY( u, x, y, 500.00 ) then
                if A.damage >= 0.00 then
                    call UnitDamageTarget( A.caster, u, A.damage, false, false, null, null, null )
                else
                    call SetWidgetLife( u, GetWidgetLife( u ) - A.damage )
                endif
                
                call GroupAddUnit( TempGroup1, u )
            endif
        endloop
        
        set i = i - 1
        exitwhen i <= 0
        set x = x + 300.00 * A.ax
        set y = y + 300.00 * A.ay
    endloop
    
    call GroupClear( TempGroup1 )
    
    set A.time = A.time - DamagePeriodic
    
    if A.time <= 0.00 then
        call PauseTimer( GetExpiredTimer( ) )
        call FlushChildHashtable( H, GetHandleId( GetExpiredTimer( ) ) )
        call DestroyTimer( GetExpiredTimer( ) )
        
        call SetUnitTimeScale( A.dummy, 0.30 )
        call UnitApplyTimedLife( A.dummy, 'BTLF', 0.50 )
        
        set A.dummy = null
        set A.caster = null
        call A.destroy( )
    endif
endfunction

private function SetAnim_1 takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    
    call SetUnitTimeScale( LoadUnitHandle( H, GetHandleId( t ), 0 ), 1.00 )
    
    call FlushChildHashtable( H, GetHandleId( t ) )
    call DestroyTimer( t )
    
    set t = null
endfunction

private function ShakeCamera takes nothing returns nothing
    local real richter
    set TempReal = TempReal - 0.50
    set richter = TempReal
    
    if (richter > 5.0) then
        set richter = 5.0
    endif
    if (richter < 2.0) then
        set richter = 2.0
    endif
    
    call CameraSetTargetNoiseEx(TempReal*2.0, TempReal*Pow(10,richter),true)
    call CameraSetSourceNoiseEx(TempReal*2.0, TempReal*Pow(10,richter),true)

    if TempReal <= 0.00 then
        call SetDayNightModels( "Environment\\DNC\\DNCAshenvale\\DNCAshenValeTerrain\\DNCAshenValeTerrain.mdx", "Environment\\DNC\\DNCAshenvale\\DNCAshenValeUnit\\DNCAshenValeUnit.mdx" )
        call CameraSetSourceNoise(0, 0)
        call CameraSetTargetNoise(0, 0)
        call PauseTimer( TempTimer )
    endif
endfunction

private function LightScale takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local integer i = GetHandleId( t )
    local real r = LoadReal( H, i, 1 ) - 0.50
    
    call SetUnitScale( LoadUnitHandle( H, i, 0 ), r, r, r )
    
    if r <= 1.00 then
        call KillUnit( LoadUnitHandle( H, i, 0 ) )
        
        call PauseTimer( t )
        call DestroyTimer( t )
        call FlushChildHashtable( H, i )
    else
        call SaveReal( H, i, 1, r )
    endif
    
    set t = null
endfunction

private function SetAnim takes nothing returns nothing
    local timer t = GetExpiredTimer( )
    local PyroclasticDestructionS A = LoadInteger( H, GetHandleId( t ), 0 )
    local integer i
    local real x = A.x
    local real y = A.y
    local real richter
    
    call TimerStart( t, DamagePeriodic, true, function PyroclasticDestructionDamage )
    set i = 15
    
    loop
        call SetUnitFlyHeight( CreateUnitEx( A.p, Explosion90ID, x, y, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 5.00, 5.00, 5.00 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 15.00 )
        
        call SetUnitScale( CreateUnitEx( A.p, ExplosionID, x, y, A.a * bj_RADTODEG ), 2.00, 2.00, 2.00 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 15.00 )
        
        set i = i - 1
        exitwhen i <= 0.00
        set x = x + 150.00 * A.ax
        set y = y + 150.00 * A.ay
    endloop
    
    set x = A.x
    set y = A.y
    set i = 5
    
    loop
        call SetUnitFlyHeight( CreateUnitEx( A.p, FireID, x, y, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 5.00, 5.00, 5.00 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', A.time )
        
        set i = i - 1
        exitwhen i <= 0
        set x = x + 300.00 * A.ax
        set y = y + 300.00 * A.ay
    endloop
    
    call SetUnitFlyHeight( CreateUnitEx( A.p, BloodLustID, A.x, A.y, 270.00 ), 300.00, 0.00 )
    
    set t = CreateTimer( )
    
    call SaveUnitHandle( H, GetHandleId( t ), 0, TempUnit )
    call SaveReal( H, GetHandleId( t ), 1, 100.00 )
    
    call TimerStart( t, 0.01, true, function LightScale )
    
    set TempReal = 100.00
    set richter = TempReal
    
    if (richter > 5.0) then
        set richter = 5.0
    endif
    if (richter < 2.0) then
        set richter = 2.0
    endif
    
    call CameraSetTargetNoiseEx(TempReal*2.0, TempReal*Pow(10,richter),true)
    call CameraSetSourceNoiseEx(TempReal*2.0, TempReal*Pow(10,richter),true)
    
    call TimerStart( TempTimer, 0.01, true, function ShakeCamera )
    
    call SetUnitFlyHeight( CreateUnitEx( A.p, SmallFlameSpawnID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
    call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
    call SetUnitAnimation( TempUnit, "birth" )
    call UnitApplyTimedLife( TempUnit, 'BTLF', 7.00 )
    
    call SetUnitFlyHeight( CreateUnitEx( A.p, RedLightOmniID, A.x, A.y, 0.00 ), 50.00, 0.00 )
    call UnitApplyTimedLife( TempUnit, 'BTLF', A.time )
    call SetDayNightModels( "", "" )
    
    set i = 2
    
    loop
        call SetUnitFlyHeight( CreateUnitEx( A.p, Explosion90ID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 5.00, 5.00, 5.00 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 15.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, IncinerateID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 5.00, 5.00, 5.00 )
        call SetUnitTimeScale( TempUnit, 0.70 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, IncinerateID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 5.00, 5.00, 5.00 )
        call SetUnitTimeScale( TempUnit, 0.50 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, DoomID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call SetUnitTimeScale( TempUnit, 0.20 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call SetUnitTimeScale( TempUnit, 0.65 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
        call SetUnitTimeScale( TempUnit, 0.65 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call SetUnitTimeScale( TempUnit, 0.40 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
        call SetUnitTimeScale( TempUnit, 0.40 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call SetUnitTimeScale( TempUnit, 0.25 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, WarStompID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
        call SetUnitTimeScale( TempUnit, 0.25 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, ItemStrengthGainID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call SetUnitTimeScale( TempUnit, 0.50 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, ItemStrengthGainID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
        call SetUnitTimeScale( TempUnit, 0.50 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, MirrorImageID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 3.00, 3.00, 3.00 )
        call SetUnitTimeScale( TempUnit, 0.50 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        call SetUnitFlyHeight( CreateUnitEx( A.p, MirrorImageID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
        call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
        call SetUnitTimeScale( TempUnit, 0.50 )
        call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
        
        set i = i - 1
        exitwhen i <= 0
    endloop
    
    call SetUnitFlyHeight( CreateUnitEx( A.p, ReviveHeroInstanlyID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
    call SetUnitTimeScale( TempUnit, 7.00 )
    call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
    call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
    
    set t = CreateTimer( )
    
    call SaveUnitHandle( H, GetHandleId( t ), 0, TempUnit )
    call TimerStart( t, 0.15, false, function SetAnim_1 )
    
    call SetUnitFlyHeight( CreateUnitEx( A.p, ReviveHeroID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
    call SetUnitScale( TempUnit, 4.00, 4.00, 4.00 )
    call SetUnitTimeScale( TempUnit, 7.00 )
    call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
    
    set t = CreateTimer( )
    
    call SaveUnitHandle( H, GetHandleId( t ), 0, TempUnit )
    call TimerStart( t, 0.15, false, function SetAnim_1 )
    
    call SetUnitTimeScale( A.dummy, 0.10 )
    
    set t = null
endfunction

function PyroclasticDestruction_Actions takes unit caster, real damage, real angle, boolexpr b returns nothing
    local timer t = CreateTimer( )
    local PyroclasticDestructionS A = PyroclasticDestructionS.create( )
    
    set A.caster = caster
    set A.damage = damage
    set A.b = b
    set A.p = GetOwningPlayer( A.caster )
    set A.x = GetUnitX( A.caster )
    set A.y = GetUnitY( A.caster )
    
    set A.a = angle * bj_DEGTORAD
    
    set A.ax = Cos( A.a )
    set A.ay = Sin( A.a )
    
    set A.time = 2.00
    
    set A.dummy = CreateUnitEx( A.p, SalamanderID, A.x - 500.00 * A.ax, A.y - 500.00 * A.ay, A.a * bj_RADTODEG )
    call SetUnitVertexColor( A.dummy, 255, 200, 200, 100 )
    call SetUnitScale( A.dummy, 3.00, 3.00, 3.00 )
    call SetUnitTimeScale( A.dummy, 0.50 )
    call SetUnitAnimation( A.dummy, "attack" )
    call QueueUnitAnimation( A.dummy, "stand" )
    
    call SetUnitFlyHeight( CreateUnitEx( A.p, DarkRitualID, A.x - 100.00 * A.ax, A.y - 100.00 * A.ay, A.a * bj_RADTODEG ), 50.00, 0.00 )
    call SetUnitScale( TempUnit, 2.00, 2.00, 2.00 )
    call UnitApplyTimedLife( TempUnit, 'BTLF', 5.00 )
    
    call SaveInteger( H, GetHandleId( t ), 0, A )
    call TimerStart( t, 1.00, false, function SetAnim )
    
    set t = null
endfunction

//===========================================================================
function InitTrig_PyroclasticDestruction takes nothing returns nothing
    local rect r = GetWorldBounds( )
    //set gg_trg_PyroclasticDestruction = CreateTrigger(  )
    
    set MaxX = GetRectMaxX( r ) - 32.00
    set MinX = GetRectMinX( r ) + 32.00
    set MaxY = GetRectMaxY( r ) - 32.00
    set MinY = GetRectMinY( r ) + 32.00
    
    call RemoveRect( r )
    
    set r = null
endfunction
endlibrary

инструкция по импорту
  • скопировать триггер PyroclasticDestruction и вставить в карту
  • заполнить равкоды в триггере PyroclasticDestruction в соответствии с названиями переменных
  • создать переменную с названием TempUnit для гуи пользования

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


в карте присутствует отредактированная модель источника освещения

upd я не думаю что кто-то всерьёз (мб гуишники) будет этот спелл где-то использовать, так что просто демонстрирую идею

upd 11.01.2024 немного оптимизированная версия, даммики кроме огня не попадают в перебор группы, для лучшей оптимизации можно увеличить периодичность урона либо шаг поиска целей, а так же уйти нафиг с гуи булекспром)
для ещё большей оптимизации можно попробовать переработать выбор юнитов в группу и нанесения урона, т.е.:
код
globals
	private constant group TempGroup = CreateGroup
	private boolexpr Cond = null
	private unit bj_lastFilterUnit = null
	private real TempX = 0.00
	private real TempY = 0.00
endglobals

native UnitAlive takes unit id returns boolean

...

private function DamageCond takes nothing returns boolean
	set bj_lastFilterUnit = GetFilterUnit( )

	return UnitAlive( bj_lastFilterUnit ) and IsUnitEnemy( bj_lastFilterUnit, bj_groupEnumOwningPlayer ) and IsUnitInRangeXY( bj_lastFilterUnit, TempX, TempY, 500.00 )
endfunction

...

	set Cond = Condition( function DamageCond )

...
	
	set bj_groupEnumOwningPlayer = GetOwningPlayer( A.caster )
	set TempX = A.x
	set TempY = A.y
	set i = 8

	loop
        call GroupEnumUnitsInRange( TempGroup, TempX, TempY, 700.00, Cond )
        
		set i = i - 1
        exitwhen i <= 0
        set TempX = TempX + 300.00 * A.ax
        set TempY = TempY + 300.00 * A.ay
    endloop
        
    loop
    	set u = FirstOfGroup( TempGroup )
        exitwhen u == null
        call GroupRemoveUnit( TempGroup, u )

        if A.damage >= 0.00 then
            call UnitDamageTarget( A.caster, u, A.damage, false, false, null, null, null )
        else
            call SetWidgetLife( u, GetWidgetLife( u ) - A.damage )
        endif
    endloop
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
1
2 месяца назад
0
Добрый день! У меня не получается его вставить в карту. Выдает вот такую ошибку (на скриншоте). Может подскажите как правильно его вставить? В инструкции для новичка кодов непонятно. Написано изменить равкоды) Сорри, но можно объяснить что именно?

И что делать с кодом, который прилагается на этой странице?
Ответы (1)
0
27
2 месяца назад
0
Auron1993, реализация на вджассе, соответственно тебе нужен JNGP, который скомпилирует код в джасс. Код на этой странице нужен только тем, кто не хочет или не имеет возможность посмотреть карту
Чтобы оставить комментарий, пожалуйста, войдите на сайт.