• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Burning Waves JASS [v1.0]

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
Oh YEAH jass is great + i not need to bother anymore translating triggers :D

ok... The caster summons evil fire in a line ahead the point damaging the area
waves and damage increases with each level
easy to make it one level or 55 levels :)
almost all in the spell are easly configurable
i think i removed all the leaks this time
FULLY MUI TESTED!
Hard to take screenshots srry


JASS:
//===========================================================================
//A vJASS and JESP (i think)
//@author Kratoz-X
//
//@credits 
//Flame_Phoenix for it great turorial "Making a spell in vJass" :D
//
//@version 1.0
//
//vJASS is soo Cooool :)
//===========================================================================
scope BurningWaves initializer Init
//===========================================================================
//=============================SETUP START===================================
//===========================================================================
    globals
    
        private constant integer SPELL_ID = 'A001'  //the rawcode of the spell
        private constant integer DUMMY_ID = 'h000'  //rw of the dummy unit my omnidummy is used in all my spells :)
        private constant string AOE_EFFECT = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"  //effect that will be created when we cast the spell on the AOE
        private constant string AOE2_EFFECT = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"  //another thing used to make this spell cool
        private constant damagetype D_TYPE = DAMAGE_TYPE_FIRE //the attack type of the spell
        private constant attacktype A_TYPE = ATTACK_TYPE_MAGIC  //the damage type of the spell
        private constant string RAY_ID1 = "FORK"  //The rw of ligthing used for the waves
        private constant real RAY_R1 = 0.75 //Red color of the ray
        private constant real RAY_G1 = 0.5 //Green color 
        private constant real RAY_B1 = 0.0 //blue color
        private constant real RAY_A1 = 1.0 //Alpha of color 1=no transparency 0=FULL transparency
        private constant string RAY_ID2 = "FORK"  //The rw of ligthing used for the waves
        private constant real RAY_R2 = 1.0 //Red color of the ray
        private constant real RAY_G2 = 0.2 //Green color 
        private constant real RAY_B2 = 0.05 //blue color
        private constant real RAY_A2 = 1.0 //Alpha of color 1=no transparency 0=FULL transparency
        private constant real Spellaoe = 150 //not sugested to be more than 200 for balance things but whatever
        
    endglobals
    
    private function Range takes integer level returns real
    //Real range betwen waves
        return 150.
    endfunction
    
    private function Waves takes integer level returns real
    //Number of waves per level
        return level * 2. //3 waves are from default to evade the spell was too long of too short
    endfunction
    
    
    private function Delay takes integer level returns real 
    //delay in seconds betwen waves CANT be les than 0.1 ¬¬ why not Blizzard?????
    //this also affect true sigtht
        return  0.1
    endfunction
    
    private function Damage takes integer level returns real
    //The damage enemies will take
        return level * 25.
    endfunction
    
//===========================================================================
//=============================SETUP END=====================================
//===========================================================================
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == SPELL_ID
    endfunction
//===========================================================================
    private function Actions takes nothing returns nothing
        local location spellLoc = GetSpellTargetLoc()
        local unit caster = GetTriggerUnit()
        local real spellX = GetLocationX(spellLoc)
        local real spellY = GetLocationY(spellLoc)
        local location curentwave = GetUnitLoc(caster)
        local real waveX = GetLocationX(curentwave)
        local real waveY = GetLocationY(curentwave)
        local integer level = GetUnitAbilityLevel(caster, SPELL_ID)
        local real facing = GetUnitFacing(caster)
        local real Loopspell = 0
        local lightning array wavesray
        set Loopspell = 0
        call TriggerSleepAction( .1 )
        set facing = GetUnitFacing(caster)
loop
      exitwhen Loopspell == (Waves(level) + 3.)
        set curentwave = PolarProjectionBJ(GetUnitLoc(caster), ( Range(level) * (Loopspell + 1.50 ) ), facing)
        set waveX = GetLocationX(curentwave)
        set waveY = GetLocationY(curentwave)
        call AddLightningLoc( RAY_ID1, GetUnitLoc(caster), curentwave )
        set wavesray[1] = GetLastCreatedLightningBJ()
        call AddLightningLoc( RAY_ID2, GetUnitLoc(caster), curentwave )
        set wavesray[2] = GetLastCreatedLightningBJ()
        call DestroyEffect(AddSpecialEffect(AOE_EFFECT, waveX, waveY))
        call SetLightningColorBJ( wavesray[1], RAY_R1, RAY_G1, RAY_B1, RAY_A1 )
        call SetLightningColorBJ( wavesray[2], RAY_R2, RAY_G2, RAY_B2, RAY_A2 )
        call TriggerSleepAction( Delay(level) )
        call DestroyEffect(AddSpecialEffect(AOE2_EFFECT, waveX, waveY))
        set Loopspell = (Loopspell + 1)
        call UnitDamagePointLoc( caster, Delay(level), Spellaoe, curentwave, Damage(level), A_TYPE, D_TYPE )
        //Someone can tell me whow make unitgroups to make this optional damage allies???????????
        call DestroyLightning( wavesray[1] )
        call DestroyLightning( wavesray[2] )
endloop
        call RemoveLocation(spellLoc)
        call RemoveLocation(curentwave)
        set spellLoc = null
        set curentwave = null
        set Loopspell = 0
        set caster = null
    endfunction
//===========================================================================
    private function Init takes nothing returns nothing
        local trigger BurningWavesTrg = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(BurningWavesTrg, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition(BurningWavesTrg, Condition( function Conditions ) )
        call TriggerAddAction( BurningWavesTrg, function Actions )
        //preloading effects
        call Preload(AOE_EFFECT)
        call Preload(AOE2_EFFECT)
        //preloading the ability
        set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), DUMMY_ID, 0, 0, 0)
        call UnitAddAbility(bj_lastCreatedUnit, SPELL_ID)
        call KillUnit(bj_lastCreatedUnit)
    endfunction
endscope

Keywords:
fire, waves, evil, burning, blast
Contents

Otro mapa de Warcraft III (Map)

Reviews
12th Dec 2015 IcemanBo: Too long as NeedsFix. Rejected. Use coordinates, not locations. set spellX = GetSpellTargetX() for example. Hotkeys are wrong. Learn tooltip level 3 data is missing "damage". Learned tooltip has an extra space. Get...

Moderator

M

Moderator

12th Dec 2015
IcemanBo: Too long as NeedsFix. Rejected.


Maker, Burning Waves JASS v1.0, 11:20, 12th Nov 2011

Use coordinates, not locations.
set spellX = GetSpellTargetX() for example.
Hotkeys are wrong.
Learn tooltip level 3 data is missing "damage".
Learned tooltip has an extra space.
Get rid of the BJ functions.
I think you should enumerate units within radius and use a filter function to damage units. UnitDamagePoint damages all units.
If you're using only two indexes of an array, it is better to make two non-array variables.
Waves function should return an integer.
LoopsSpell should be an integer. You don't have to set it to 0 at the end.
Trigger sleep action gives random results. A 0.1 second wait is either 0.1, 0.125, 0.15, 0.175 or 0.2 seconds, chosen seemingly randomly. Maybe timers would work better here.
 
Level 10
Joined
Sep 19, 2011
Messages
527
1. Don't use bj functions.
2. Don't use locations (instead use coordenates)
3. Its not recommended that you use TriggerSleepAction
4. Move the actions to Condition function

set Loopspell = 0 is not necessary, you're already set the value when you declare it.

JASS:
call AddLightningLoc( RAY_ID1, GetUnitLoc(caster), curentwave )
        set wavesray[1] = GetLastCreatedLightningBJ()

->

set wavesray[1] = AddLightningLoc( RAY_ID1, GetUnitLoc(caster), curentwave )

Mmm... you need to use a timer instead the loop.

Sry for my english.
Nice effects :).
 
Level 4
Joined
Apr 18, 2011
Messages
60
i dont know mayber not all BJ are evil (well almost all) but now use cordinates because is a facing spell (360 degrees) ?
how use corretly natives?
why tutorials made quick no explain nothing?
i think set 0 was necesary
what instead of wait then? (i never understanded that)
what exatly you mean with condition function??? is a cond or is a function????? :S
thanx or the corrections man
 
Level 10
Joined
Sep 19, 2011
Messages
527
This is how your spell would be like:

JASS:
library BW requires TimerUtils
    globals
        private constant integer SPELL_ID = 'A001'  //the rawcode of the spell
        private constant integer DUMMY_ID = 'h000'  //rw of the dummy unit my omnidummy is used in all my spells :)
        private constant string AOE_EFFECT = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"  //effect that will be created when we cast the spell on the AOE
        private constant string AOE2_EFFECT = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"  //another thing used to make this spell cool
        private constant damagetype D_TYPE = DAMAGE_TYPE_FIRE //the attack type of the spell
        private constant attacktype A_TYPE = ATTACK_TYPE_MAGIC  //the damage type of the spell
        private constant string RAY_ID1 = "FORK"  //The rw of ligthing used for the waves
        private constant real RAY_R1 = 0.75 //Red color of the ray
        private constant real RAY_G1 = 0.5 //Green color 
        private constant real RAY_B1 = 0.0 //blue color
        private constant real RAY_A1 = 1.0 //Alpha of color 1=no transparency 0=FULL transparency
        private constant string RAY_ID2 = "FORK"  //The rw of ligthing used for the waves
        private constant real RAY_R2 = 1.0 //Red color of the ray
        private constant real RAY_G2 = 0.2 //Green color 
        private constant real RAY_B2 = 0.05 //blue color
        private constant real RAY_A2 = 1.0 //Alpha of color 1=no transparency 0=FULL transparency
        private constant real Spellaoe = 150 //not sugested to be more than 200 for balance things but whatever
    endglobals
    
    private function Range takes integer level returns real
    //Real range betwen waves
        return 150.
    endfunction
    
    private function Waves takes integer level returns real
    //Number of waves per level
        return level * 2. //3 waves are from default to evade the spell was too long of too short
    endfunction
    
    
    private function Delay takes integer level returns real 
    //delay in seconds betwen waves CANT be les than 0.1 ¬¬ why not Blizzard?????
    //this also affect true sigtht
        return  0.1
    endfunction
    
    private function Damage takes integer level returns real
    //The damage enemies will take
        return level * 25.
    endfunction

    private struct Spell extends array
        private static integer instanceCount = 0
        private static thistype recycle = 0
        private thistype recycleNext
        
        private unit caster
        private real facing
        private integer level
        private integer exit
        private lightning l1
        private lightning l2
        
        private method destroy takes nothing returns nothing
            set this.caster = null
            set this.l1 = null
            set this.l2 = null
            
            set recycleNext = recycle
            set recycle = this
        endmethod
        
        private static method periodic takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            local real waveX
            local real waveY
            local real distance
            
            call DestroyLightning(this.l1)
            call DestroyLightning(this.l2)
            
            if this.exit == Waves(this.level) + 3 then
                call this.destroy()
                call ReleaseTimer(GetExpiredTimer())
            else
                set this.exit = this.exit + 1
                
                set distance = Range(this.level) * (this.exit + 1.50)
                set waveX = GetUnitX(this.caster) + distance * Cos(this.facing * bj_DEGTORAD)
                set waveY = GetUnitY(this.caster) + distance * Sin(this.facing * bj_DEGTORAD)
                
                set this.l1 = AddLightning(RAY_ID1, true, GetUnitX(this.caster), GetUnitY(this.caster), waveX, waveY)
                set this.l2 = AddLightning(RAY_ID2, true, GetUnitX(this.caster), GetUnitY(this.caster), waveX, waveY)
            
                call DestroyEffect(AddSpecialEffect(AOE_EFFECT, waveX, waveY))
                call DestroyEffect(AddSpecialEffect(AOE2_EFFECT, waveX, waveY))
                
                call SetLightningColor(this.l1, RAY_R1, RAY_G1, RAY_B1, RAY_A1)
                call SetLightningColor(this.l2, RAY_R2, RAY_G2, RAY_B2, RAY_A2)
                
                call UnitDamagePoint(this.caster, Delay(level), Spellaoe, waveX, waveY, Damage(this.level), false, false, A_TYPE, D_TYPE, null)
            endif
        endmethod
        
        private static method create takes nothing returns thistype
            local thistype this
            local timer t = NewTimer()
            
            if (recycle == 0) then
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = recycle
                set recycle = recycle.recycleNext
            endif
            
            set this.caster = GetTriggerUnit()
            set this.facing = GetUnitFacing(this.caster)
            set this.level = GetUnitAbilityLevel(this.caster, SPELL_ID)
            set this.exit = 0
            
            call SetTimerData(t, this)
            call TimerStart(t, Delay(this.level), true, function thistype.periodic)
            
            set t = null
            
            return this
        endmethod
        
        private static method condition takes nothing returns boolean
            if GetSpellAbilityId() == SPELL_ID then
                call thistype.create()
            endif
            
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
            call TriggerAddCondition(t, Condition(function thistype.condition))
            
            call Preload(AOE_EFFECT)
            call Preload(AOE2_EFFECT)
            
            set bj_lastCreatedUnit = CreateUnit(Player(15), DUMMY_ID, 0, 0, 0)
            call UnitAddAbility(bj_lastCreatedUnit, SPELL_ID)
            call KillUnit(bj_lastCreatedUnit)
        endmethod
    endstruct
endlibrary

I don't know why is lagging on the first cast, maybe is TimerUtils?

Another thing, to make aoe damage, you need to have a group.

JASS:
local group g = CreateGroup()
local unit j

loop
    set j = FirstOfGroup(g)
    exitwhen j == null
    call GroupRemoveUnit(g, j)
    
    // make the damage
    // the target would be "j"
    call UnitDamageTarget(...)
endloop

call DestroyGroup(g)
set g = null

Greetings
 
Level 10
Joined
Sep 19, 2011
Messages
527
Mmm, yes, I can recommend you one library for the lightning effects.
Uh... I forget to comment the code, sorry (I'll/will I) comment it now.

Here you go:

JASS:
library BW requires TimerUtils
    globals
        private constant integer SPELL_ID = 'A001'  //the rawcode of the spell
        private constant integer DUMMY_ID = 'h000'  //rw of the dummy unit my omnidummy is used in all my spells :)
        private constant string AOE_EFFECT = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"  //effect that will be created when we cast the spell on the AOE
        private constant string AOE2_EFFECT = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"  //another thing used to make this spell cool
        private constant damagetype D_TYPE = DAMAGE_TYPE_FIRE //the attack type of the spell
        private constant attacktype A_TYPE = ATTACK_TYPE_MAGIC  //the damage type of the spell
        private constant string RAY_ID1 = "FORK"  //The rw of ligthing used for the waves
        private constant real RAY_R1 = 0.75 //Red color of the ray
        private constant real RAY_G1 = 0.5 //Green color 
        private constant real RAY_B1 = 0.0 //blue color
        private constant real RAY_A1 = 1.0 //Alpha of color 1=no transparency 0=FULL transparency
        private constant string RAY_ID2 = "FORK"  //The rw of ligthing used for the waves
        private constant real RAY_R2 = 1.0 //Red color of the ray
        private constant real RAY_G2 = 0.2 //Green color 
        private constant real RAY_B2 = 0.05 //blue color
        private constant real RAY_A2 = 1.0 //Alpha of color 1=no transparency 0=FULL transparency
        private constant real Spellaoe = 150 //not sugested to be more than 200 for balance things but whatever
    endglobals
    
    private function Range takes integer level returns real
    //Real range betwen waves
        return 150.
    endfunction
    
    private function Waves takes integer level returns real
    //Number of waves per level
        return level * 2. //3 waves are from default to evade the spell was too long of too short
    endfunction
    
    
    private function Delay takes integer level returns real 
    //delay in seconds betwen waves CANT be les than 0.1 ¬¬ why not Blizzard?????
    //this also affect true sigtht
        return  0.1
    endfunction
    
    private function Damage takes integer level returns real
    //The damage enemies will take
        return level * 25.
    endfunction

    private struct Spell extends array
        // Recycle
        private static integer instanceCount = 0
        private static thistype recycle = 0
        private thistype recycleNext
        
        private unit caster     // caster unit
        private real facing     // caster's facing
        private integer level   // spell's level
        private integer exit    // the same as exitwhen Loopspell == (Waves(level) + 3.) in your spell
        private lightning l1    // lightning
        private lightning l2    // lightning
        
        private method destroy takes nothing returns nothing
            set this.caster = null
            set this.l1 = null
            set this.l2 = null
            
            // Recycle
            set recycleNext = recycle
            set recycle = this
        endmethod
        
        private static method periodic takes nothing returns nothing
            local thistype this = GetTimerData(GetExpiredTimer())
            local real waveX
            local real waveY
            local real distance
            
            // Destroying the latest lightnings
            call DestroyLightning(this.l1)
            call DestroyLightning(this.l2)
            
            // If this is true, then stop the timer
            // and destroy it (the same what you did in your spell)
            if this.exit == Waves(this.level) + 3 then
                call this.destroy()
                call ReleaseTimer(GetExpiredTimer())
            else
                set this.exit = this.exit + 1
                
                set distance = Range(this.level) * (this.exit + 1.50)
                set waveX = GetUnitX(this.caster) + distance * Cos(this.facing * bj_DEGTORAD)
                set waveY = GetUnitY(this.caster) + distance * Sin(this.facing * bj_DEGTORAD)
                
                set this.l1 = AddLightning(RAY_ID1, true, GetUnitX(this.caster), GetUnitY(this.caster), waveX, waveY)
                set this.l2 = AddLightning(RAY_ID2, true, GetUnitX(this.caster), GetUnitY(this.caster), waveX, waveY)
            
                call DestroyEffect(AddSpecialEffect(AOE_EFFECT, waveX, waveY))
                call DestroyEffect(AddSpecialEffect(AOE2_EFFECT, waveX, waveY))
                
                call SetLightningColor(this.l1, RAY_R1, RAY_G1, RAY_B1, RAY_A1)
                call SetLightningColor(this.l2, RAY_R2, RAY_G2, RAY_B2, RAY_A2)
                
                call UnitDamagePoint(this.caster, Delay(level), Spellaoe, waveX, waveY, Damage(this.level), false, false, A_TYPE, D_TYPE, null)
            endif
        endmethod
        
        private static method create takes nothing returns thistype
            local thistype this
            local timer t = NewTimer()
            
            // Recycle
            if (recycle == 0) then
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = recycle
                set recycle = recycle.recycleNext
            endif
            
            set this.caster = GetTriggerUnit()
            set this.facing = GetUnitFacing(this.caster)
            set this.level = GetUnitAbilityLevel(this.caster, SPELL_ID)
            set this.exit = 0
            
            // Starting the timer
            // The timer will run the periodic's method
            // when expires
            call SetTimerData(t, this)
            call TimerStart(t, Delay(this.level), true, function thistype.periodic)
            
            set t = null
            
            return this
        endmethod
        
        // Condition's method
        private static method condition takes nothing returns boolean
            if GetSpellAbilityId() == SPELL_ID then
                call thistype.create()
            endif
            
            return false
        endmethod
        
        // onInit is the method that runs on start
        private static method onInit takes nothing returns nothing
            local trigger t = CreateTrigger()
            
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
            call TriggerAddCondition(t, Condition(function thistype.condition))
            
            call Preload(AOE_EFFECT)
            call Preload(AOE2_EFFECT)
        endmethod
    endstruct
endlibrary

You need to know what structs are to read better the code.

Greetings
 
Top