Spell Blaze v2

emjlr3

Change can be a good thing
Reaction score
395
Blaze v2

Explanations:
  • What it does - upon casting the ability, conjures X flaming orbs, which circle the caster, and upon reaching their ascent, careen forth at random targets in the area, exploding upon impact, dealing damage to the unlucky foe.
  • Why I made it - I made it for a tower contest, and actually managed to place, which was kind of neat.
  • Why you should try it - I think it is a pretty neat ability. Makes use of vJASS to move lots of projectiles around, and you may actually find it useful, if not to use in a map, possibly to learn from.
  • Concerns - there is a lot of stuff flying about all at once, so it could get laggy with 10 or less firing at the same time on low end computers. I believe I have updated the trigger to be completely self sufficient, however if I missed something, let me know. Also, do not mind all the other triggers in the map, this was the test map I used for the ability, and I think it is an easy way to demo the spell as it is, simply look in the Spells folder for the abilities trigger.

JASS:
scope Blaze

//******************************************************************************************
//*
//* Blaze v2
//* 
//*
//*  A neat ability which throws homing fireballs all around at random enemies and 
//*  deals damage upon collision with them.
//* 
//*  Requires:
//*    - A blaze dummy and blaze abilty in your map, similar to the ones found here
//*    - This code copied to a trigger in your map
//*
//****************************************************************************************** 

globals
    //Config Options:
    
      //General:
      private constant integer abil_id = 'A001' //blaze ability rawcode
      private constant real int = .025 //timer interval for effect movement
      private constant integer dummy_id = 'n001' //blaze dummy rawcode
      private constant integer max_missiles = 6 //max number of missiles + 1, ever created for an instance of the spell
      
      //Twirl Portion:
      private constant real start_dist = 150. //start distance of missiles before they twirl, away from the caster
      private constant real end_height = 280. //end height of missiles when they reach the top of the twirl
      private constant real twirl_time = 1. //length in seconds of the twirl portion of the ability
      private constant real twirl_speed = 5. //rate of change per timer interval for the angle change of the missiles during the twirl
      
      //Homing Portion:       
      private constant real speed = 15. //missile speed per timer interval while homing in on a target
      private constant boolean new_target = true //whether missiles can get a new target if their original dies while in route
      private constant real height_diff = 35. //difference between targets current fly height and the height you want the missile to lower/raise to
      private constant attacktype a_type = ATTACK_TYPE_MAGIC //attack type for damage done
      private constant damagetype d_type = DAMAGE_TYPE_FIRE //damage type for damage done
endglobals 
private function damage takes integer lvl returns real
      return lvl*25. //damage done per missile
endfunction
private function range takes integer lvl returns real
      return (lvl*50.)+750. //range for missiles to check for targets
endfunction
private function count takes integer lvl returns integer
      return 4+lvl //number of missiles created
endfunction

//******************************************************************************************
//DON"T TOUCH PAST THIS POINT, UNLESS YOU PAIN FOR DEATH!
globals    
    //needed globals:
    private unit U = null
    private group G = CreateGroup()     
    private timer Tball = CreateTimer() 
    private integer Total1 = 0 
    private integer Total2 = 0
    private Blaze_data1 array structArray1
    private Blaze_data2 array structArray2
    
    public trigger Trigger = CreateTrigger()
endglobals

//angle between units
private function ABU takes unit a, unit b returns real
    return bj_RADTODEG * Atan2(GetUnitY(b) - GetUnitY(a), GetUnitX(b) - GetUnitX(a))
endfunction
//distance between units
private function DBU takes unit a, unit b returns real
    return SquareRoot(Pow(GetUnitX(b) - GetUnitX(a), 2) + Pow(GetUnitY(b)-GetUnitY(a),2))
endfunction
//filter for missiles, this can be edited as desired for further configuration
private function Filt takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit())>.405 and IsUnitEnemy(GetFilterUnit(),GetOwningPlayer(U))==true
endfunction

//needed struct 2
struct Blaze_data2
    unit ball = null 
    unit targ = null   
    real height = end_height 
    integer lvl = 0
    
    //init struct
    method Start takes unit ball, integer lvl returns nothing
        //update missile        
        set .ball = ball         
        //grab first target
        set .targ = GroupPickRandomUnit(G)
        set .lvl = lvl
    endmethod
    //move missile towards target
    method Effects takes nothing returns nothing
        local real ang = ABU(.ball,.targ)
        
        call SetUnitX(.ball,GetUnitX(.ball) + speed * Cos(ang * bj_DEGTORAD))
        call SetUnitY(.ball,GetUnitY(.ball) + speed * Sin(ang * bj_DEGTORAD))
        call SetUnitFacing(.ball,ang)
        set .height = .height - 10. //this makes it look pretty fluent IMO
        if .height<GetUnitFlyHeight(.targ)+height_diff then
            set .height = GetUnitFlyHeight(.targ)+height_diff
        endif
        call SetUnitFlyHeight(.ball,.height,0.0)
    endmethod
    //update globals
    method Update takes integer i returns nothing
        set structArray2<i> = structArray2[Total2]
        set Total2 = Total2 - 1
    endmethod
    //end struct
    method onDestroy takes nothing returns nothing         
        //damage target, destroy missile   
        if .targ!=null then 
            call UnitDamageTarget(.ball,.targ,damage(.lvl),false,false,a_type,d_type,null)
        endif
        call KillUnit(.ball)
    endmethod
endstruct
//needed struct 1 
struct Blaze_data1
    integer runs = 0
    unit tower = null
    unit array ball[max_missiles]
    real array ang[max_missiles]
    real xtower
    real ytower
    integer total = 0
    real increment = 0.
    real change = 0.
    real Hchange = 0.
    integer total_runs = 0
    
    //initiate all needed struct data
    method Start takes unit tower returns nothing
        local integer i = 1
        local real x = GetUnitX(tower)
        local real x2 
        local real y = GetUnitY(tower)
        local real y2
        local player p = GetOwningPlayer(tower)
        
        set .total = count(GetUnitAbilityLevel(tower,abil_id))
        set .increment = 360/.total
        set .total_runs = R2I(twirl_time/int) 
        set .change = start_dist/.total_runs
        set .Hchange = end_height/.total_runs
        //loop from 1-total, create balls, store angles
        loop
            exitwhen i&gt;.total
            set .ang<i> = i*.increment
            
            set x2 = x + start_dist * Cos(.ang<i> * bj_DEGTORAD) 
            set y2 = y + start_dist * Sin(.ang<i> * bj_DEGTORAD)
        
            set .ball<i> = CreateUnit(p,dummy_id,x2,y2,0.)
        
            set i = i + 1
        endloop
        
        //store tower and target
        set .tower = tower
        set .xtower = x
        set .ytower = y
    endmethod
    //effects for each run, update angle, move ball, update fly height
    method Effects takes nothing returns nothing
        local integer i = 1
        local real height = .runs * .Hchange 
        local real distance = start_dist-(.runs*.change) //get closer as we twirl up, eventually meeting in the middle
        
        loop
            exitwhen i&gt;.total             
            
            set .ang<i> = .ang<i> + twirl_speed
            call SetUnitX(.ball<i>, .xtower + distance * Cos(.ang<i> * bj_DEGTORAD))
            call SetUnitY(.ball<i>, .ytower + distance * Sin(.ang<i> * bj_DEGTORAD))
            call SetUnitFlyHeight(.ball<i>,height,0.0)   
                   
            set i = i + 1
        endloop
    endmethod
    //update globals
    method Update takes integer i returns nothing
        set structArray1<i> = structArray1[Total1]
        set Total1 = Total1 - 1
    endmethod
    //when our struct is destroyed, loop through balls and possibly destroy
    method onDestroy takes nothing returns nothing
        local integer i = 1
        local Blaze_data2 dat 
        local integer lvl
        
        //tower is dead, end
        if GetWidgetLife(.tower)&lt;.405 then
            loop
                exitwhen i&gt;.total             
                call KillUnit(.ball<i>)          
                set i = i + 1
            endloop 
        else  
            //tower is not dead, add missiles to new struct, and begin the detonation phase 
            set lvl = GetUnitAbilityLevel(.tower,abil_id)
            call GroupClear(G)
            set U = .tower
            call GroupEnumUnitsInRange(G,.xtower,.ytower,range(lvl),Condition(function Filt))          
            loop
                exitwhen i&gt;.total
                set dat = Blaze_data2.create()
                call dat.Start(.ball<i>,lvl)
                set Total2 = Total2 + 1 
                set structArray2[Total2] = dat  
                set i = i + 1
            endloop
        endif          
    endmethod
endstruct 

//filter for attackers
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId()==abil_id
endfunction 
//movement for missiles  
private function Movement takes nothing returns nothing
    local integer i = 1
    local Blaze_data1 dat1
    local Blaze_data2 dat2
    
    loop
        //loop through all current structs 1
        exitwhen i &gt; Total1
        set dat1 = structArray1<i>
       
        //update our runs total
        set dat1.runs = dat1.runs + 1
        //effects are over, remove struct and clean up
        if dat1.runs&gt;dat1.total_runs or GetWidgetLife(dat1.tower)&lt;.405 then               
            call dat1.destroy()            
            call dat1.Update(i)            
            set i = i - 1               
        else
            //runs are not over, continue with effects
            call dat1.Effects()
        endif
       
        set i = i + 1
    endloop
    
    set i = 1
    
    loop
        //loop through all current structs 2
        exitwhen i &gt; Total2
        set dat2 = structArray2<i>
       
        //target is nothing, or is dead
        if dat2.targ==null or GetWidgetLife(dat2.targ)&lt;.405 then
            //if the missile can get another target, try and do so
            if new_target then
                call GroupClear(G)
                set U = dat2.ball
                call GroupEnumUnitsInRange(G,GetUnitX(dat2.ball),GetUnitY(dat2.ball),range(dat2.lvl),Condition(function Filt))
                set dat2.targ = GroupPickRandomUnit(G)
                //no new target available
                if dat2.targ==null then
                    call dat2.destroy()
                    call dat2.Update(i)  
                endif
                //so it runs this missile again, though it is now what was the last missile
                set i = i + 1
            else
                call dat2.destroy()
                call dat2.Update(i)            
                set i = i - 1
            endif
        //unit is close enough to damage, remove struct and clean up
        elseif DBU(dat2.ball,dat2.targ)&lt;speed then //distance between missile and target is less then speed, therefore another movement would most likely carry us past the target               
            call dat2.destroy()             
            call dat2.Update(i)             
            set i = i - 1               
        else
            //runs are not over, continue with effects
            call dat2.Effects()
        endif
       
        set i = i + 1
    endloop
    
    //no more active structs, pause timer
    if Total1==0 and Total2==0 then
        call PauseTimer(Tball)
    endif      
endfunction
//init for missiles
private function Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local Blaze_data1 dat = Blaze_data1.create()
    
    //init struct data, add it to array, start timer if not already done so
    if Total1==0 and Total2==0 then
        call TimerStart(Tball,int,true,function Movement)
    endif 
    call dat.Start(u)
    set Total1 = Total1 + 1 
    set structArray1[Total1] = dat  
    
    set u = null
endfunction

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

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


Updates:
  • v2 -fixed some spelling/grammar errors in my documentation and explanations
    some functions renamed
    added a public global trigger named Blaze_Trigger which is now used at the abilities global trigger
    ported to an active instant cast ability
    updated the Blaze_data1 arrays to a size so it works properly
    changed setunitposition to setunitx/y
    reduced groupenum call from max missiles to 1 when grabbing targets for the missiles
    removed getunitx/y calls for each missile and during every twirl interval, now done only once
    added many configuration parameters
    removed all unneeded systems from map
  • v1 - Initial release

Thoughts? Suggestions? Concerns? Mal contempt?
 

Attachments

  • hreshers.jpg
    hreshers.jpg
    70.4 KB · Views: 832
  • emjlr3 - Blaze v2.w3x
    93.3 KB · Views: 480
R

Rawne87

Guest
Hi i have been browsing these forums for a while, and decided to register because i just can't get your ability to work in my map. I am kindof a newb on jass and such, so it could just be a stupid mistake somewhere.
When i copy the trigger/ability/dummy unit to my map and edit the abilty id and unit id i still get like 50 errors. Any help would be appreciated.
 

emjlr3

Change can be a good thing
Reaction score
395
yea i should have mentioned that in the documentation, my bad
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      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