Spellpack Lightning & Fire Track

Trollvottel

never aging title
Reaction score
262
Generally: There could be some coding errors because i didnt write anything in jass or gui etc for a longer time. so dont kill me for errors i didnt find ;)

The spells use TT and a library i created to make the code not too long.
Library Code:
JASS:

library UsedFuncs initializer init
    globals
        constant real RTD = 57.29577951
        constant real DTR = 0.017353292
        private  real MaxX
        private  real MaxY
        private  real MinX
        private  real MinY
        boolexpr AliveFilter
    endglobals
    
    
 
    
    function SetSafeX takes unit which, real x returns nothing
        if x < MaxX then
            if x > MinX then
                call SetUnitX(which, x)
            else
                call SetUnitX(which,MinX)
            endif
        else
            call SetUnitX(which, MaxX)
        endif
    endfunction
    

    function SetSafeY takes unit which, real y returns nothing
        if y < MaxY then
            if y > MinY then
                call SetUnitY(which,y)
            else
                call SetUnitY(which,MinY)
            endif
        else
            call SetUnitY(which, MaxY)
        endif
    endfunction
        
    function SafeX takes real x returns real
        if x < MaxX then
            if x > MinX then
                return x
            else
                return MinX
            endif
        else
            return MaxX
        endif
    endfunction  
    
    function SafeY takes real y returns real
        if y < MaxY then
            if y > MinY then
                return y
            else
                return MinY
            endif
        else
            return MaxY
        endif
    endfunction   
    
    
 
    function GetFloorHeight takes real x, real y returns real
        local location whichUnitLocation = Location( x, y )
        local real z = GetLocationZ( whichUnitLocation )
        call RemoveLocation( whichUnitLocation )
        set whichUnitLocation = null
        return z
    endfunction

    function GetUnitZ takes unit whichUnit returns real
        local real z = ( GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ) + GetUnitFlyHeight( whichUnit ) )
        set whichUnit = null
        return z
    endfunction
    
     function SetUnitZ takes unit whichUnit, real z returns nothing
        local boolean whichUnitHasNotAmrf = ( GetUnitAbilityLevel( whichUnit, 'Amrf' ) <= 0 )
        if ( whichUnitHasNotAmrf ) then
            call UnitAddAbility( whichUnit, 'Amrf' )
            call UnitRemoveAbility( whichUnit, 'Amrf' )
        endif
        call SetUnitFlyHeight( whichUnit, z - GetFloorHeight( GetUnitX( whichUnit ), GetUnitY( whichUnit ) ), 0.00 )
        set whichUnit = null
    endfunction   

    function PolarX takes real x, real d, real a, real b returns real
        return x + ( d * Cos ( b * DTR ) * Cos ( a * DTR ) )
    endfunction

    function PolarY takes real y, real d, real a, real b returns real
        return y + ( d * Cos ( b * DTR ) * Sin ( a * DTR ) )
    endfunction

    function PolarZ takes real z, real d, real b returns real
        return z + ( d * Sin ( b * DTR ) )
    endfunction
 
    function SquareDistance takes real x0, real y0, real x1, real y1 returns real
        local real x = x1 - x0
        local real y = y1 - y0
        return ( x * x ) + ( y * y )
    endfunction
    
 
    private function Alive takes nothing returns boolean
        return GetWidgetLife(GetFilterUnit()) > 0
    endfunction
 
 
    public function init takes nothing returns nothing
            set MaxX = GetRectMaxX(bj_mapInitialPlayableArea)
            set MaxY = GetRectMaxY(bj_mapInitialPlayableArea)
            set MinX = GetRectMinX(bj_mapInitialPlayableArea)
            set MinY = GetRectMinY(bj_mapInitialPlayableArea)
            set AliveFilter = Condition(function Alive)
    endfunction
endlibrary
Lightning:
vJass
MUI
MPI
No lag

Spins an enemy unit around a point with Z-offset and this creates a static field.
Units in this field take 50% of the damage the spinned unit takes.

Screenshot( cant take a good one :/):
neubitmapcl7.jpg

Code( i hope its not too bad):
JASS:
scope Lightning

    globals 
        // spell rawcode
        private constant integer RAWID = 'A000'
        // circle radius
        private constant real RADIUS = 200. 
        // degrees per second -> turnspeed ( beta-angle )
        private constant real DEGSPS = 220.
        // percent of damage taken by units in the static field
        private constant integer PRCDMG = 50
        // amount of lightnings
        private constant integer EYECANDYAMOUNT = 7
        // code of the lightnings
        private constant string LIGHTCODE = "CLPB"
        // eyecandy appearing on the ground
        private constant string EYECANDYCODE = "Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl"
        // speed of the lightnings in degrees
        private constant real LIGHTSPEED = 10
        // Min light lenght of the eyecandy-lightnings 
        private constant real MINLIGHTLEN = 150.
        // Max light lenght of the eyecandy-lightnings
        private constant real MAXLIGHTLEN = 250.
        
    endglobals
    
    // configure your damage per second, lvl as current level of the spell
    private constant function DamagePerSecond takes integer lvl returns real
        return 35. + 12. * lvl
    endfunction
    
    // duration of the spell, lvl as current level of the spell
    private constant function Duration takes integer lvl returns real
        return 6.
    endfunction
    
    //================================================Spell Starts Here============================================\\
    
    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//DONT CHANGE BELOW\\//\\//\\//\\//\\\//\//\\//\\//\\//\\//\\//\\//\\
    private struct Ldata    
        unit caster
        unit victim
        real alpha
        real beta = 270
        real middlex
        real middley
        real middlez
        real newx
        real newy
        real newz
        real passedtime  = 0
        integer time = 0
        lightning connector 
        
        //Eyecandy section
        lightning array eyecandy[EYECANDYAMOUNT]
        real      array angle   [EYECANDYAMOUNT]
        real      array distance[EYECANDYAMOUNT]
        integer   array plusmin [EYECANDYAMOUNT]
        
        //Methods
            static method create takes unit caster, unit victim returns Ldata 
                local Ldata init       = Ldata.allocate(      )
                local real dx          = GetUnitX      (victim) - GetUnitX(caster)
                local real dy          = GetUnitY      (victim) - GetUnitY(caster)
                local real x           = 0.
                local real y           = 0.
                local real angle       = 0
                local real distance    = 0
                local integer index    = 0
                    set init.caster    = caster
                    set init.victim    = victim
                    set init.middlex   = GetUnitX      (victim)
                    set init.middley   = GetUnitY      (victim)
                    set init.middlez   = GetUnitZ      (victim) + RADIUS
                    set init.alpha     = Atan2         (dy,dx ) * RTD - 90
                    set init.connector = AddLightningEx(LIGHTCODE,false,init.middlex,init.middley,init.middlez-RADIUS,GetUnitX(caster),GetUnitY(caster),GetUnitZ(caster))
                    call PauseUnit                     (    victim, true      )
                    call SetUnitPathing                (    victim, false     )
                    
                        loop
                            // Eyecandy
                            exitwhen index > EYECANDYAMOUNT-1
                                set init.angle      [index] = GetRandomReal(0,360 )
                                set init.distance   [index] = GetRandomReal(MINLIGHTLEN,MAXLIGHTLEN)
                                
                                if GetRandomInt(0,100) < 50 then
                                    set init.plusmin[index] =  1
                                else
                                    set init.plusmin[index] = -1
                                endif
                                
                                set x = init.middlex + distance * Cos( init.angle[index] * DTR )
                                set y = init.middley + distance * Sin( init.angle[index] * DTR )
                                
                                set init.eyecandy   [index] = AddLightningEx(LIGHTCODE,false,init.middlex,init.middley,init.middlez-RADIUS,x,y,0)
                            set index = index + 1
                        endloop
                        
                return init
            endmethod
            
            
            method turn takes nothing returns nothing
                local group g = CreateGroup(   )
                local unit  u
                // Spin the unit
                set this.beta = this.beta + DEGSPS*TT_PERIOD
                set this.newx = PolarX( this.middlex,RADIUS,this.alpha,this.beta )
                set this.newy = PolarY( this.middley,RADIUS,this.alpha,this.beta )
                set this.newz = PolarZ( this.middlez,RADIUS,this.beta            )
                
                call SetSafeX         (          this.victim, this.newx          )
                call SetSafeY         (          this.victim, this.newy          )
                call SetUnitZ         (          this.victim, this.newz          )
                // damage units in the field
                call GroupEnumUnitsInRange(g,this.middlex,this.middley,MAXLIGHTLEN, AliveFilter)
                loop
                    set u = FirstOfGroup      ( g    )
                    call GroupRemoveUnit      ( g, u )
                    
                    exitwhen u == null
                    if IsUnitEnemy            ( this.caster, GetOwningPlayer( u ) ) == true and u != this.victim then
                        call UnitDamageTarget ( this.caster, u, TT_PERIOD*DamagePerSecond(GetUnitAbilityLevel(this.caster,RAWID))*PRCDMG/100, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
                    endif
                endloop
                call DestroyGroup     ( g )
                // damage spinned unit
                call UnitDamageTarget ( this.caster, this.victim, TT_PERIOD*DamagePerSecond(GetUnitAbilityLevel(this.caster,RAWID)), true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
                // make caster look at target
                call SetUnitFacing    ( this.caster, this.alpha + 90 )
                call SetUnitPosition  ( this.caster, GetUnitX(this.caster), GetUnitY(this.caster))
                
                // move lightning between caster and victim
                call MoveLightningEx  (this.connector,false,GetUnitX(this.caster),GetUnitY(this.caster),GetUnitZ(this.caster),this.newx,this.newy,this.newz)
                
                set this.passedtime = this.passedtime + TT_PERIOD
                set g = null
            endmethod
            
            method movelights takes nothing returns nothing
                local real x
                local real y 
                local integer index = 0
                    set this.time = this.time + 1
                    loop
                        // moves lightnings
                        exitwhen index > EYECANDYAMOUNT-1
                            set this.angle[index]        =   this.angle[index] + (  LIGHTSPEED * this.plusmin[index]  )
                            set x = SafeX( this.middlex + this.distance[index] * Cos(this.angle[index] * DTR) )
                            set y = SafeY( this.middley + this.distance[index] * Sin(this.angle[index] * DTR) )

                            call MoveLightningEx  (this.eyecandy[index],false, x, y, 0, this.newx, this.newy, this.newz+15)
                            if ModuloInteger(this.time,6) == 0 then
                                call DestroyEffect(AddSpecialEffect(EYECANDYCODE,x,y))
                            endif

                        set index = index + 1
                    endloop
                    // after every TT_PERIOD*50 seconds the casters animation is set to "spell"
                    if ModuloInteger(this.time,50) == 0 then
                        call SetUnitAnimation ( this.caster, "spell"         )
                    endif
            endmethod
            
            method onDestroy takes nothing returns nothing
                local integer index = 0
                // make the victim able to move & so on . . .
                call PauseUnit                     (this.victim,false )
                call SetUnitPathing                (this.victim,false )
                call SetUnitFlyHeight              (this.victim,0,800 )
                call DestroyLightning              (this.connector    ) 
                // destroy eyecandy
                loop
                    exitwhen index > EYECANDYAMOUNT-1
                        call DestroyLightning      (this.eyecandy[index])
                    set index = index + 1
                endloop
            endmethod
    endstruct
    
    
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == RAWID
    endfunction

    private function test takes nothing returns boolean
        local Ldata dat = TT_GetData()
            // call methods
            call dat.turn()
            call dat.movelights()
            // abort the spell if neccessary
            if GetWidgetLife(dat.victim) == 0 or GetWidgetLife(dat.caster) == 0 or dat.passedtime >= Duration(GetUnitAbilityLevel(dat.caster,RAWID)) then
                    call dat.destroy()
                return true
            endif
        return false
    endfunction
    
    private function Actions takes nothing returns nothing
        // Start all the shit
        local Ldata dat = Ldata.create(GetTriggerUnit(), GetSpellTargetUnit())
        call TT_Start(function test, dat)
    endfunction

    //===========================================================================
    public function InitTrig takes nothing returns nothing
        set gg_trg_Lightning = CreateTrigger(  )
        call TriggerRegisterAnyUnitEventBJ(gg_trg_Lightning, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddAction( gg_trg_Lightning, function Actions )
        call TriggerAddCondition(gg_trg_Lightning, Condition(function Conditions))
    endfunction

endscope


Fire Track:
MUI,MPI,vJass, etc....

Tracks a unit with a line of fire and when its hit it takes damage after it was surrounded by fireballs which made it unable to move.

Screenshot (also not very good, just look at the map ^^):
neubitmap2hz8.jpg

Code:
JASS:

scope FireTrack


    globals
        private constant integer RAWID = 'A001' // ID for the ability
        private constant integer DUMMYID = 'h000' // ID for your dummy unit
        private constant integer DUMMYAMOUNT = 12 // amount of dummys surrounding the hit unit
        private constant real SPEEDPS = 300. // speed of tracking
        private constant real RANGETOGET = 75. // neccessary minimum distance to reach the tracked unit
        private constant real RADIUS = 400. // radius of the dummy circle
        private constant string EFFECT = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl" // track-effect
    endglobals
    
    
    private function Damage takes integer lvl returns real
        return lvl*125.
    endfunction
    
    //================================================Spell Starts Here============================================\\

    //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//DONT CHANGE BELOW\\//\\//\\//\\//\\\//\//\\//\\//\\//\\//\\//\\//\\
    
    private function Conditions takes nothing returns boolean 
        return GetSpellAbilityId() == RAWID
    endfunction
    
    
    private struct Surrounder
        unit caster
        unit surrounded
        unit array dummy[DUMMYAMOUNT]
        real array angle[DUMMYAMOUNT]
        real initx
        real inity
            static method create takes unit caster, unit victim returns Surrounder
                local Surrounder init = Surrounder.allocate()
                local integer index = 0
                local real x = 0
                local real y = 0
                set init.surrounded = victim
                set init.caster     = caster
                set init.initx      = GetUnitX ( victim )
                set init.inity      = GetUnitY ( victim )
                loop
                    exitwhen index > DUMMYAMOUNT-1
                        
                        set init.angle[index] = index*360./DUMMYAMOUNT
                        set x = init.initx + RADIUS * Cos(init.angle[index]*DTR)
                        set y = init.inity + RADIUS * Sin(init.angle[index]*DTR)
                        set init.dummy[index] = CreateUnit(GetOwningPlayer(caster), DUMMYID, x,y,init.angle[index]-180) 
                        
                        call SetSafeX( init.dummy[index],x )
                        call SetSafeY( init.dummy[index],y )
                        
                        set init.angle[index] = (init.angle[index] - 180)*DTR
                    set index = index + 1
                endloop
                return init
            endmethod
    endstruct
    
    private struct Tracker
        unit caster
        unit tracked
        real curX
        real curY
        integer ticks = 0
            static method create takes unit caster, unit tracked returns Tracker
                local Tracker dat   = Tracker.allocate(        )
                    set dat.caster  = caster
                    set dat.tracked = tracked
                    set dat.curX    = GetUnitX        ( caster )
                    set dat.curY    = GetUnitY        ( caster )
                return dat
            endmethod
    endstruct
    
    private function SurroundAndSoOn takes nothing returns boolean
        local Surrounder dat = TT_GetData()
        local real x
        local real y
        local real nx
        local real ny
        local integer index  = 0
        local real distance
        local boolean flag   = false
        
        loop
            exitwhen index > DUMMYAMOUNT-1
            
                set x = GetUnitX(dat.dummy[index])
                set y = GetUnitY(dat.dummy[index])
                
                set nx = x + SPEEDPS * TT_PERIOD * Cos(dat.angle[index])
                set ny = y + SPEEDPS * TT_PERIOD * Sin(dat.angle[index])
                
                call SetSafeX(dat.dummy[index], nx)    
                call SetSafeY(dat.dummy[index], ny)
                
                call SetSafeX(dat.surrounded, dat.initx)    
                call SetSafeY(dat.surrounded, dat.inity)
                
                set distance = SquareDistance(nx,ny,dat.initx,dat.inity)
                if distance <= RANGETOGET*RANGETOGET then
                    set flag = true
                endif
                
            set index = index + 1
            
        endloop
        set index = 0
        if flag == true then
            loop
                exitwhen index > DUMMYAMOUNT-1
                    call KillUnit(dat.dummy[index])
                set index = index + 1
            endloop
            call UnitDamageTarget(dat.caster, dat.surrounded, Damage(GetUnitAbilityLevel(dat.caster, RAWID)), false,true, ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS)
            call dat.destroy()
            return true
        endif
        
        
        return false
    endfunction
    
    private function SurroundTheFuckinUnit takes unit caster, unit toSurround returns nothing
        local Surrounder dat = Surrounder.create(caster,toSurround)
        call TT_Start(function SurroundAndSoOn,dat)
    endfunction
    

    private function ticktrack takes nothing returns boolean
        local Tracker this = TT_GetData()
        local real tx        = GetUnitX      (        this.tracked         )
        local real ty        = GetUnitY      (        this.tracked         )
        local real angle     = Atan2         ( ty-this.curY, tx-this.curX  )
        local real squaredis = SquareDistance( tx, ty, this.curX, this.curY)
        
        set this.ticks = this.ticks + 1
        
        set this.curX = this.curX + SPEEDPS * TT_PERIOD * Cos(angle)
        set this.curY = this.curY + SPEEDPS * TT_PERIOD * Sin(angle)
        
        if ModuloInteger(this.ticks, 3) == 0 then
            call DestroyEffect(AddSpecialEffect(EFFECT,this.curX,this.curY))
        endif
            
        if squaredis <= RANGETOGET*RANGETOGET then
            call SurroundTheFuckinUnit(this.caster, this.tracked)
            call this.destroy()
            return true
        endif
        
        return false
    endfunction
    
    private function Actions takes nothing returns nothing
        local Tracker dat = Tracker.create(GetTriggerUnit(),GetSpellTargetUnit())
        call TT_Start(function ticktrack,dat)
    endfunction

    //===========================================================================
    public function InitTrig takes nothing returns nothing
        set gg_trg_FireTrack = CreateTrigger(  )
        call TriggerAddAction( gg_trg_FireTrack, function Actions )
        call TriggerAddCondition(gg_trg_FireTrack,Condition(function Conditions))
        call TriggerRegisterAnyUnitEventBJ(gg_trg_FireTrack, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    endfunction

endscope
 

Attachments

  • Lightning&FireTrack.w3x
    77.9 KB · Views: 286

GoGo-Boy

You can change this now in User CP
Reaction score
40
Two very nice spells. The lightning looks wonderful, very nice effects... multiple lightnings + ground static effects rocks! It would be cool if you were able to stop the spell if you want. +Rep

Edit: Can't^^ ahh and coding looks uberclean .s
 

Trollvottel

never aging title
Reaction score
262
thank you for the reply <3
well I found a bug:
-If the caster dies, the spell doesnt get aborted

i will fix it as soon as possible, which means this evening or monday-later.
 

Hatebreeder

So many apples
Reaction score
381
Very Nice ^.-
I realy like the lightning ^^
But I don't like the fact that it keeps switching between attack and stop whilst channeling...
Other than that... You get a +Rep and a <3
 

Trollvottel

never aging title
Reaction score
262
He doesnt switch between his animations. he has two different spell animations.
And:

Updated.
 

Kazuga

Let the game begin...
Reaction score
110
>What's against approval?
Be patient, I'm sure the moderators have alot of other work to and they are doing a great job.:rolleyes:

I really loved the lightning spell, imo it's the most realistic lightning attack I have ever seen. The fire ability was real nice also, altough it looked more like an aoe attack than a single attack. Don't know jass so I can't comment the codes^^.
Lightning 10/10
Fire 8/10
 

hasslarn

New Member
Reaction score
20
first one looks like a forked lightning remix
its nice
and the secound well u dont see mutch but u see the fire ^^ gonna try it
nice anyway +rep
 
1

131ackout

Guest
loved the lightning spell!

the fire looks just little bitty

+rep for lightning spell
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top