Spell Arcane Explosion

darth-yoda

New Member
Reaction score
15
Arcane Explosion

Gives a chance that when ever a nearby unit casts a spell, random explosions of magical energy will appear around the casting unit. Number of explosions is equal to number of enemy units near the caster x2.

Coded in - JASS
MUI - No
Leaks - None I'm aware of
Constant Functions - Yes
Import/Edit Difficulty - Low

Yay my first (good) JASS spell :) It's not MUI because of 1 Global unit variable that I don't know how to get around :( Perhaps someone else knows how. Any and all comments on the spell/ coding are greatly appreciated.

Heres the code...

JASS:
//=============================================================================\\
//>>>>>>>>>>>>>>>>>>>>>>Arcane Explosion<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\\
//                          made by                                            \\
//                         darthyoda                                           \\
//                    with help from Steel                                     \\
//Things you'll need for this spell to work in your map from the Object Editor \\
//     1. Copy'n'paste the spell 'Arcane Explosion' into your map              \\
//     2. Copy'n'paste the buff 'Arcane Explosion' into your map               \\
//                                                                             \\
//Things you'll need for this spell to work in your map from the Trigger Editor\\                                                                   
//     1. Copy'n'paste the trigger named 'Set Arcane Explosion'                \\                                                
//     2. Copy'n'paste the trigger named 'Arcane Explosion'                    \\                                           
//     3. Set the First 2 functions named 'buffid' and 'abilityid' to the id   \\
//        codes of your spell and buff. Note press 'CTRL+D' to view them in the\\
//        Object Editor                                                        \\
//And now it should be working!! Edit the first set of functions to make the   \\
//spell just how you want it.                                                  \\
//=============================================================================\\

constant function ArcaneExplosion_buffid takes nothing returns integer
    return 'B000' //Set this to your Custom Buffs ID
endfunction

constant function ArcaneExplosion_abilityid takes nothing returns integer
    return 'A000' //Set this to Arcanes Explosions ID
endfunction

constant function ArcaneExplosion_chance takes integer lvl returns real
    return lvl * 10.  //Sets the chance of the spell activating
endfunction

constant function ArcaneExplosion_damage takes integer lvl returns real
     return lvl * 25. + 25. //How much damage each explosion deals
endfunction

constant function ArcaneExplosion_AOE_explosionMAX takes integer lvl returns real 
    return lvl * 0 + 350.   //The Max Distants the explosions can be made from the triggering unit
endfunction

constant function ArcaneExplosion_AOE_explosionMIN takes integer lvl returns real
    return lvl * 0 + 100. // The Min Distants the explosions can be made from the triggering unit
endfunction

constant function ArcaneExplosion_AOE_area takes integer lvl returns integer
    return lvl * 0 + 200   //The area around each explosion that takes damage
endfunction

constant function ArcaneExplosion_AOE_group takes integer lvl returns integer
    return lvl * 0 + 500    //Counts the number of enemy units around the triggering unit
endfunction 

constant function ArcaneExplosion_unitmultiplier takes integer lvl returns integer
    return lvl * 0 + 2   //Set the number of explosions. For example the Math currently is set to; number of nearby units x2
endfunction

constant function ArcaneExplosion_waittime takes nothing returns real
    return 0.20  //Ammount of time between each explosion 
endfunction

constant function ArcaneExplosion_SFX takes nothing returns string
    return "Units\\NightElf\\Wisp\\WispExplode.mdl"  //The explosions Model path name. Note: Path name must written as, Unit\\MyUnit\\Footman instead of Unit\MyUnit\Footman. 
endfunction

//=========================================================================================================
//========================DO NOT EDIT PAST HERE UNLESS YOU KNOW WHAT YOUR DOING============================
//=========================================================================================================  

function Trig_Arcane_Explosion_Conditions takes nothing returns boolean
    local integer lvl = GetUnitAbilityLevel(udg_AE_Owner, ArcaneExplosion_abilityid())
    local integer c = GetRandomInt(1,100)
    local boolean bool = ((GetUnitAbilityLevel(GetTriggerUnit(), ArcaneExplosion_buffid()) > 0))
    if c <= ArcaneExplosion_chance(lvl) then
    return (bool)
    endif
    return false
endfunction

function Arcane_Explosion_Check takes nothing returns boolean
    local boolean bool1 = not(IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE))
    local boolean bool2 = IsUnitAliveBJ(GetFilterUnit()) 
    local boolean bool3 = IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_AE_Owner))
    return (bool1 and bool2 and bool3)
endfunction

function Trig_Arcane_Explosion_Damage takes nothing returns nothing
    local integer lvl = GetUnitAbilityLevel(udg_AE_Owner, ArcaneExplosion_abilityid())
    call UnitDamageTarget(udg_AE_Owner, GetEnumUnit(), ArcaneExplosion_damage(lvl), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
endfunction



function Trig_Arcane_Explosion_Actions takes nothing returns nothing
    local location cast =  GetUnitLoc(GetTriggerUnit())
    local location targ
    local group g = CreateGroup()
    local group h = CreateGroup()
    local integer a = 1
    local integer b
    local integer lvl = GetUnitAbilityLevel(udg_AE_Owner, ArcaneExplosion_abilityid())
    local boolexpr bexpr = (Condition(function Arcane_Explosion_Check))
        set g = GetUnitsInRangeOfLocMatching(ArcaneExplosion_AOE_group(lvl), cast, bexpr)
        set b = ( CountUnitsInGroup(g) * ArcaneExplosion_unitmultiplier(lvl) )
        loop
            exitwhen a > b
            set targ = PolarProjectionBJ(cast, GetRandomReal(ArcaneExplosion_AOE_explosionMIN(lvl), ArcaneExplosion_AOE_explosionMAX(lvl)), GetRandomReal(0, 360.00))
            call AddSpecialEffectLoc(ArcaneExplosion_SFX(), targ)
            call DestroyEffect( GetLastCreatedEffectBJ() )
            call PolledWait( ArcaneExplosion_waittime() )
            set h = GetUnitsInRangeOfLocMatching(ArcaneExplosion_AOE_area(lvl), targ, bexpr)
            call ForGroupBJ( h, function Trig_Arcane_Explosion_Damage )
            call DestroyGroup (h)
            call RemoveLocation (targ)
            set a = a + 1
        endloop
    call DestroyGroup (g)
    set g = null
    call DestroyBoolExpr(bexpr)
    set bexpr = null
    call RemoveLocation (cast)
    set cast = null
    set targ = null
    set h = null
endfunction

//===========================================================================
function InitTrig_Arcane_Explosion takes nothing returns nothing
    set gg_trg_Arcane_Explosion = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Arcane_Explosion, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Arcane_Explosion, Condition( function Trig_Arcane_Explosion_Conditions ) )
    call TriggerAddAction( gg_trg_Arcane_Explosion, function Trig_Arcane_Explosion_Actions )
endfunction


Edit: sry, best screenshots I could get. Looks much better in game.
Edit 2: Updated the spell. Improved the coding (Big thanks to Steel) Still working on making it MUI, my last attempt resulted in a Critical Error:rolleyes: :banghead:
Edit 3: A few slight change to coding (Just made it more flexible). Fixed a small glitch in the terrain. Also added the heal ability to the hero so it's easier to set off the spell.
 

Attachments

  • Arcane Explosion 1.jpg
    Arcane Explosion 1.jpg
    40.3 KB · Views: 451
  • Arcane Explosion 2.jpg
    Arcane Explosion 2.jpg
    41 KB · Views: 397
  • Arcane Explosion 3.jpg
    Arcane Explosion 3.jpg
    40.2 KB · Views: 393
  • Arcane Explosion (1.20).w3x
    51.5 KB · Views: 281

darth-yoda

New Member
Reaction score
15
did you read what i wrote?

Also no screen shots because I have no Photo Editing software sense my Hard drive crashed and the Unedited screen shots are 5meg (If someone else could get some screen shots for me it would be great).
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Ifranview -- FREE!

Also, just because it has waits doesn't mean that it isn't MUI. Does it use globals? If so, then it isn't. If it doesn't, it is MUI. Also, PolledWait() is much better than TriggerSleepAction() [TSA for Short]... ;)

EDIT: Nvm... It uses globals, but handles are muuchh better and they keep the MUIness. :D
 

darth-yoda

New Member
Reaction score
15
Yeah i'm downloading Infaview now...My internet is very slow...

@PurgeandFire
If you could post a example of how to make my spell MUI that would be great, I'v been trying for a while.
 

darth-yoda

New Member
Reaction score
15
Global is set in a different trigger and is a Unit Variable
Its call 'AE_owner' Should be easy to find if you open the map.

Ill post screen shots tomorrow. My internet is being dumb and wont download( keeps stopping at either 7% or 42%-48%:rolleyes: )
 

Steel

Software Engineer
Reaction score
109
Your code:
You need to nullify your variables after you destroy (or remove) them.

A tip is that you should use when making spells, you should try and include your spell name in your constant functions. Because the generic name of buffid, chance, damage, etc may already be used by something else, and this would cause compile errors.

I believe the easiest way for you to make this MUI would be to include different buff ID's. 1 for each level. This way you do not have to reference the caster and find out what level the spell is. For example, you check the udg_AE_Owner's skill level, say it is 2. Well if each different level has a different buff id (b000, b001, b002) then you could just see if the unit has the buff. If it has b000, then it is level 1, b001, level 2, etc...

Example:
JASS:
function Arcane_Explosion_Conditions_Level takes unit u returns integer
if (GetUnitAbilityLevel(u, 'B000')>0) then 
return 1
elseif (GetUnitAbilityLevel(u, 'B001')>0) then
return 2
elseif (GetUnitAbilityLevel(u, 'B002')>0) then
return 3
else
return 0
endif
endfunction

function Arcane_Explosion_Conditions takes nothing returns boolean
return (Arcane_Explosion_Conditions_Level(GetTriggerUnit())!=0)
endfunction


Also you should try and clean up all of those triggers that you have running booleans for. Each time you call another function it takes a small amount of time (Yes it may be insignificant, but it is still time). If you slim it all down and put it into 1 function and return it, you should be much better, and it will look cleaner. To help yourself you can make a bunch of local boolean variables to keep track of everything and just compare the variables. I highly recommend this, it will make your code look much cleaner.

Finally, and very simply you have a few BJ functions you should try and clear up.

Buff Itself
I would like to say sorry if everything above I said sounded harsh, but I wanted to help you advance you skills as a spell maker. This was a very nice change, to see someone make a buff in the form of an aura. This is a very nice concept and I really enjoyed it.
 

darth-yoda

New Member
Reaction score
15
Thank you Steel. I have only been learning Jass off and on for the past few days so I have a question.

Also you should try and clean up all of those triggers that you have running booleans for. Each time you call another function it takes a small amount of time (Yes it may be insignificant, but it is still time). If you slim it all down and put it into 1 function and return it, you should be much better, and it will look cleaner. To help yourself you can make a bunch of local boolean variables to keep track of everything and just compare the variables. I highly recommend this, it will make your code look much cleaner.
How do I do that?

Also, your idea for different level buffs is good, but how would I determine who (witch player) deals the damage? Thats the main reason for the global unit variable. Maybe it's something simple and I'm just noob but I can't figure it out.
Also I got rid of all the BJ's I knew how, but the ones left I don't understand:eek:

I would like to say sorry if everything above I said sounded harsh, but I wanted to help you advance you skills as a spell maker. This was a very nice change, to see someone make a buff in the form of an aura. This is a very nice concept and I really enjoyed it.
I didn't think it was harsh, exactly what I wanted actually:eek: Glad you liked the overall spell.
 

Steel

Software Engineer
Reaction score
109
Ill post a mock up example from your own trigger about how to clean it up in a bit for you.

As for the whole using a global thing and having to determine who's buff it is, this could be tricky. If you are trying to make it MUI, say you have 2 units with the same buff in the same area killing the same units together. How would you determine who's to use? Well I would say, when a unit casts the spell, you could do a simple check. Check the area around the caster for the Hero, when you find the first hero (it is the closest one when using FirstOfGroup to cycle through the units), reference the owner of the unit as the player to use to damage.
 

darth-yoda

New Member
Reaction score
15
But then the closest hero would always get the kill, right? I'd rather pick the hero at random and have him get to deal the damage, that seems slightly more fair to me.
 

waaaks!

Zinctified
Reaction score
255

darth-yoda

New Member
Reaction score
15
Thank you waaaks! I changed it.
Will update the spell once Steel shows me how to shorten the rest of the functions.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Instead of using a global variable you can actually check which unit close to the caster has the skill Arcane Explosion, and give the credit to this unit.

Would make your spell MUI.

Please add a regeneration feature, such as "Press ESC to regen hp/mana".
 

Steel

Software Engineer
Reaction score
109
Tada!
JASS:
globals
unit udg_AE_Owner
endglobals

//=============================================================================\\
//>>>>>>>>>>>>>>>>>>>>>>Arcane Explosion<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\\
//                          made by                                            \\
//                         darthyoda                                           \\
//                                                                             \\
//Things you'll need for this spell to work in your map from the Object Editor \\
//     1. Copy'n'paste the spell 'Arcane Explosion' into your map              \\
//     2. Copy'n'paste the buff 'Arcane Explosion' into your map               \\
//                                                                             \\
//Things you'll need for this spell to work in your map from the Trigger Editor\\                                                                   
//     1. Copy'n'paste the trigger named 'Set Arcane Explosion'                \\                                                
//     2. Copy'n'paste the trigger named 'Arcane Explosion'                    \\                                           
//     3. Set the First 2 functions named 'buffid' and 'abilityid' to the id   \\
//        codes of your spell and buff. Note press 'CTRL+D' to view them in the\\
//        Object Editor                                                        \\
//And now it should be working!! Edit the first set of functions to make the   \\
//spell just how you want it.                                                  \\
//=============================================================================\\

constant function buffid takes nothing returns integer
    return 'B000' //Set this to your Custom Buffs ID
endfunction

constant function abilityid takes nothing returns integer
    return 'A000' //Set this to Arcanes Explosions ID
endfunction

constant function chance takes integer lvl returns real
    return lvl * 10.  //Sets the chance of the spell activating
endfunction

constant function damage takes integer lvl returns real
     return lvl * 25. + 25. //How much damage each explosion deals
endfunction

constant function AOE_explosionMAX takes nothing returns real 
    return 350.   //The Max Distants the explosions can be made from the triggering unit
endfunction

constant function AOE_explosionMIN takes nothing returns real
    return 100. // The Min Distants the explosions can be made from the triggering unit
endfunction

constant function AOE_area takes nothing returns integer
    return 200   //The area around each explosion that takes damage
endfunction

constant function AOE_aura takes nothing returns integer
    return 1000    //This should be set to your base spells AOE (Checks units in range with buff)
endfunction

constant function AOE_group takes nothing returns integer
    return 500    //Counts the number of enemy units around the triggering unit
endfunction 

constant function unitmultiplier takes integer lvl returns integer
    return lvl * 0 + 2   //Set the number of explosions. For example the Math currently is set to; number of nearby units x2
endfunction

constant function waittime takes nothing returns real
    return 0.20  //Ammount of time between each explosion 
endfunction

constant function SFX takes nothing returns string
    return "Units\\NightElf\\Wisp\\WispExplode.mdl"  //The explosions Model path name. Note: Path name must written as, Unit\\MyUnit\\Footman instead of Unit\MyUnit\Footman. 
endfunction

//=========================================================================================================
//========================DO NOT EDIT PAST HERE UNLESS YOU KNOW WHAT YOUR DOING============================
//=========================================================================================================  


//Changed this function to include the buff check and the chance check
//Did this so you don't have to include a huge IF statement in your main
//Remember the Boolean and Integers do not have to cleaned
function Trig_Arcane_Explosion_Conditions takes nothing returns boolean
local integer lvl = GetUnitAbilityLevel(udg_AE_Owner, abilityid())
local integer c = GetRandomInt(1,100)
local boolean bool = ((GetUnitAbilityLevel(GetTriggerUnit(), buffid()) > 0))
if c <= chance(lvl) then
return (bool)
endif
return false
endfunction

function Arcane_Explosion_Check takes nothing returns boolean
local boolean bool1 = not(IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE))//Cleanup of one trigger
local boolean bool2 = IsUnitAliveBJ(GetFilterUnit()) //Clean up of another trigger
local boolean bool3 = IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(udg_AE_Owner)) //Clean up of another trigger
return (bool1 and bool2 and bool3) //Return all of them
endfunction

function Trig_Arcane_Explosion_damage takes nothing returns nothing
    local integer lvl = GetUnitAbilityLevel(udg_AE_Owner, abilityid())
    call UnitDamageTarget(udg_AE_Owner, GetEnumUnit(), damage(lvl), true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNIVERSAL, WEAPON_TYPE_WHOKNOWS)
endfunction



function Trig_Arcane_Explosion_Actions takes nothing returns nothing
    local location cast =  GetUnitLoc(GetTriggerUnit()) //Set the caster loc here, not later
    local location targ //Don't set this now, since its changed later, frequently
    local group g = CreateGroup() //Setup a group
    local group h = CreateGroup() //Setup a group
    local integer a = 1 //Set the integer here
    local integer b
    local integer lvl = GetUnitAbilityLevel(udg_AE_Owner, abilityid())//Set the integer here
    local boolexpr bexpr = (Condition(function Arcane_Explosion_Check))//Create this to prevent leaks
    
        set g = GetUnitsInRangeOfLocMatching(AOE_group(), cast, bexpr)//Replaced the function call with a boolexpr
        set b = ( CountUnitsInGroup(g) * unitmultiplier(lvl) )
        loop
            exitwhen a > b
            set targ = PolarProjectionBJ(cast, GetRandomReal(AOE_explosionMIN(), AOE_explosionMAX()), GetRandomReal(0, 360.00))
            call AddSpecialEffectLoc(SFX(), targ)//Cleaned up the BJ
            call DestroyEffect( GetLastCreatedEffectBJ() )
            call TriggerSleepAction( waittime() )
            set h = GetUnitsInRangeOfLocMatching(AOE_area(), targ, bexpr)//Replaced the function call with a boolexpr
            call ForGroupBJ( h, function Trig_Arcane_Explosion_damage )
            call DestroyGroup (h)
            call RemoveLocation (targ)
            set a = a + 1
        endloop
//Cleanup
    call DestroyGroup (g)
    set g = null
    call DestroyBoolExpr(bexpr)
    set bexpr = null
    call RemoveLocation (cast)
    set cast = null
    set targ = null
    set h = null
endfunction

//===========================================================================
function InitTrig_Arcane_Explosion takes nothing returns nothing
    set gg_trg_Arcane_Explosion = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Arcane_Explosion, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Arcane_Explosion, Condition( function Trig_Arcane_Explosion_Conditions ) )
    call TriggerAddAction( gg_trg_Arcane_Explosion, function Trig_Arcane_Explosion_Actions )
endfunction


BTW your tooltips are inconsistent. Level 1 learning tooltip says 10%, learned says 15%. Level 2 is fine, 3 is off as well.
 
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