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: 827
  • emjlr3 - Blaze v2.w3x
    93.3 KB · Views: 479
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.
  • Varine Varine:
    How can you tell the difference between real traffic and indexing or AI generation bots?
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/

      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