Spell Tsunami

Tom_Kazansky

--- wraith it ! ---
Reaction score
157
TSUNAMI

Calls forth the power of the sea, sending out a powerful tidal wave that travels a long distance, damages and knocks enemy units in its wake.

Some Info:
  • vJass
  • MUI
  • Leakless (I think)
  • Lagless

Screenshots
attachment.php

Code
JASS:

//===============================================================
//|
//|        Tsunami
//|        ¯¯¯¯¯¯¯
//|  Requires:
//| - JassNewGen
//| - TimerUtils
//|
//|  How to Import:
//| - Copy ability: "Tsunami" (A000)
//| - Copy unit: Dummy Unit - Tidal Wave (n000)
//| - Copy trigger: Tsunami and TimerUtils (if you don't have it)
//| - Changes the raw id of abilities, units,... in the globals block
//|
//|  Modification:
//| - Values in the globals block and functions below it
//|
//|  Credit
//| - Thanks Vexorian for TimerUtils
//| - Thanks Tinki3 for the Test Map Template
//|
//===============================================================
scope Tsunami initializer Init 

globals
    private constant integer AbilId = 'A000' //raw id of the ability
    private constant integer WaveId = 'n000' //raw id of Wave dummy
    private constant real SPEED = 1000. //speed of the wave
    private constant string HITSFX = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl"  //sfx when the wave hit a unit
    private constant string HITSFX_A = "origin" //attachment point of the above effect
endglobals

private function GetInitialDamage takes integer lvl returns real
    return 100.+50*lvl //inital damage of the wave
endfunction

private function GetAdditionalDamage takes integer lvl returns real
    return 50. * lvl //additinal damage of the wave
endfunction

private function GetWaveDistance takes integer lvl returns real
    return 600. + 100 * lvl //distance of  Tsunami
endfunction

//------ do not touch those below --------
//------ unless you know what are you doing -----

globals
    private group ENUMER = CreateGroup()
    private integer TEMPINT = 0
    private real MinX
    private real MinY
    private real MaxX
    private real MaxY
endglobals

private function GetPPX takes real x, real dist, real angle returns real
    local real X = x + dist * Cos(angle * bj_DEGTORAD)
    if X < MinX then
        return MinX
    endif
    if X > MaxX then
        return MaxX
    endif
    return X
endfunction

private function GetPPY takes real y, real dist, real angle returns real
    local real Y = y + dist * Sin(angle * bj_DEGTORAD)
    if Y < MinY then
        return MinY
    endif
    if Y > MaxY then
        return MaxY
    endif
    return Y
endfunction

private function GeometricDistance takes real x1,real y1, real x2, real y2,real x0,real y0 returns real
    local real d
    set d = ((y2-y1)*(x0-x1)-(x2-x1)*(y0-y1))/(SquareRoot( (y2-y1)*(y2-y1) + (x2-x1)*(x2-x1) ))
    if d < 0 then
        return -d
    endif
    return d
endfunction

private struct data
    unit c
    real cx
    real cy
    real dx
    real dy
    real cf
    real dmg
    real dps
    unit array d [10]
    group h
    integer tick
    integer tickmax
    timer t
endstruct

private function TsunamiF takes nothing returns boolean
    local data d = TEMPINT
    local unit f = GetFilterUnit()
    local boolean ok = false
    if GetWidgetLife(f) > 0.405 then
        if IsUnitEnemy(f,GetOwningPlayer(d.c)) then
            if not IsUnitType(f,UNIT_TYPE_STRUCTURE ) then
                set ok = true
            endif
        endif
    endif
    set f = null
    return ok
endfunction

private function TsunamiE takes nothing returns nothing
    local data d = GetTimerData( GetExpiredTimer() )
    local integer i = 0
    local unit p
    local real x
    local real y
    local real gd
    set d.tick = d.tick - 1
    if d.tick == 0 then
        loop
            exitwhen i > 9
            call SetUnitVertexColor(d.d<i>,255,255,255,0)
            call SetUnitTimeScale(d.d<i>,1.)
            call UnitApplyTimedLife(d.d<i>,&#039;BTLF&#039;,0.2)
            set i = i + 1
        endloop
        call DestroyGroup(d.h)
        call ReleaseTimer(d.t)
        call d.destroy()
        return
    endif
    
    if d.tick == d.tickmax - 1 then
        loop
            exitwhen i &gt; 9
            call SetUnitTimeScale(d.d<i>,3.)
            set i = i + 1
        endloop
    endif
    
    if d.tick == d.tickmax - 5 then
        loop
            exitwhen i &gt; 9
            call SetUnitTimeScale(d.d<i>,0.)
            set i = i + 1
        endloop
    endif
    
    set d.cx = GetPPX( d.cx, SPEED / 25., d.cf)
    set d.cy = GetPPY( d.cy, SPEED / 25., d.cf)
    set i = 0
    loop
        exitwhen i &gt; 9
        set x = GetPPX(d.cx, 200 - 50 * i ,d.cf+90)
        set y = GetPPY(d.cy, 200 - 50 * i ,d.cf+90)
        call SetUnitX(d.d<i>,x)
        call SetUnitY(d.d<i>,y)
        set i = i + 1
    endloop
    
    set d.dx = GetPPX( d.cx, 250, d.cf+90 )
    set d.dy = GetPPY( d.cy, 250, d.cf+90 )
    set TEMPINT = d
    call GroupEnumUnitsInRange( ENUMER,  d.cx, d.cy, 300., Condition( function TsunamiF ) ) 
    loop
        set p = FirstOfGroup(ENUMER)
        exitwhen p == null
        call GroupRemoveUnit(ENUMER,p)
        set x = GetUnitX(p)
        set y = GetUnitY(p)
        set gd = GeometricDistance( d.cx, d.cy, d.dx, d.dy, x, y )
        if gd &lt;= 100. then
            if not IsUnitInGroup(p,d.h) then
                call DestroyEffect( AddSpecialEffectTarget( HITSFX,p,HITSFX_A))
                call UnitDamageTarget(d.c,p,d.dmg,false,true,null,DAMAGE_TYPE_COLD ,null)
                call GroupAddUnit(d.h,p)
            else
                call UnitDamageTarget(d.c,p, d.dps/25. ,false,true,null,DAMAGE_TYPE_COLD,null)
            endif
            call SetUnitPosition(p, GetPPX( x, 100. - gd , d.cf ), GetPPY( y, 125. - gd , d.cf ) )
        endif
    endloop
    
endfunction

private function Cond takes nothing returns boolean
    return GetSpellAbilityId() == AbilId
endfunction

private function Act takes nothing returns nothing
    local data d = data.create()
    local integer i = 0
    local location loc = GetSpellTargetLoc()
    local integer lvl
    local real x
    local real y
    set d.c = GetTriggerUnit()
    set d.cx = GetUnitX(d.c)
    set d.cy = GetUnitY(d.c)
    set d.cf = bj_RADTODEG * Atan2(GetLocationY(loc) - d.cy,GetLocationX(loc) - d.cx)
    set d.h = CreateGroup()
    loop
        exitwhen i &gt; 9
        set x = GetPPX(d.cx, 200 - 50 * i ,d.cf+90)
        set y = GetPPY(d.cy, 200 - 50 * i ,d.cf+90)
        set d.d<i> = CreateUnit(Player(15),WaveId, x,y,d.cf)
        call SetUnitVertexColor(d.d<i>,255,255,255,67)
        call SetUnitAnimation(d.d<i>,&quot;Birth&quot;)
        call SetUnitTimeScale(d.d<i>,0.)
        set i = i + 1
    endloop
    
    set lvl = GetUnitAbilityLevel(d.c,AbilId )
    set d.dmg = GetInitialDamage( lvl )
    set d.dps = GetAdditionalDamage( lvl )
    set d.tick = R2I( GetWaveDistance(lvl) / 25. )
    set d.tickmax = d.tick
    set d.t = NewTimer()
    call SetTimerData(d.t,d)
    call TimerStart( d.t, 0.04, true, function TsunamiE )
    
    call RemoveLocation(loc)
    set loc = null
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, Condition( function Cond ) )
    call TriggerAddAction( t, function Act )
    
    set MinX = GetRectMinX( bj_mapInitialPlayableArea )
    set MaxX = GetRectMaxX( bj_mapInitialPlayableArea )
    set MinY = GetRectMinY( bj_mapInitialPlayableArea )
    set MaxY = GetRectMaxY( bj_mapInitialPlayableArea )
endfunction

endscope
</i></i></i></i></i></i></i></i></i></i></i>


-----
Please comment :)
 

Attachments

  • [Spell] Tsunami.w3x
    53.6 KB · Views: 242
  • Tsunami.JPG
    Tsunami.JPG
    94.7 KB · Views: 469
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top