Spell Pulse Nova

gref

New Member
Reaction score
33
Pulse Nova

MUI: Yes.
Leakless: Yes.
Lagless: Yes.
JESP: Yes.
Jass/GUI: Jass

Screenshot:
PulseNovaScreen.jpg


Description:
This is a nova spell that pushes back enemies caught in it, and deals a fixed amount of damage to them. If an enemy is pushed out of range, they stop being pushed and taking damage.
Reasons why I think this is better than the couple of other pushback spells I've seen:
1. Units don't get stuck being continually pushed. The spell is fast, and so units are moved, and then can be back in the game.
2. It looks so damn cool and well timed.
3. Units get damaged periodically throughout the spell summing exactly to the predefined damage. If a unit is pushed out of the spells range by at any point it will stop being damaged.
4. The targets are entirely chosen by the Pulse Nova spell. So if you want different types of units to be affected/not affected, its very simple.

Made in Jass
JASS:
//===============================>
// Pulse Nova by gref.
//===============================>

scope PulseNova
    // Follows JESP
    
    //Change the type of units affected by changing the Targets in the Pulse Nova ability. 
    //===========================>
    //Constants
    //===========================>
    globals
        private constant integer AbilCode = 'A002' //Pulse Nova ability
        private constant integer BuffCode = 'B000' //Buff Given by the Pulse Nova Ability
        private constant integer Nova_Effect_Number = 30 //Number of missiles in nova. More = better
        // looking, less = less laggy
        private constant integer Dummy_Unit = 'h000' //The unit used to cast the nova missiles
        private constant integer Nova_Ability = 'A001' //The Nova missiles
        private constant string Nova_Order = "shockwave" //The nova order string
        private constant real Move_Duration = 1.00 //The length of time the pushback lasts
        private constant real Movement_Speed = 40.0 //The speed at which units are pushed back
        private constant real Timer_Interval = 0.05 //The interval between unit movements
        private constant real Damage_Amount = 100.0 // The damage. Scales per level. eg. Level 5=5x
        private constant real Pulse_Range = 800.0 //The range to which units are pushed back. This
        //needs to be the same as the range of the Pulse Nova ability.
        private constant real Delay_Time = 0.2 //The delay before units are pushed back. Some 
        // missiles take time to cast, ie. Breath of fire/frost
    endglobals          
    //===========================>
    //Data Types
    //===========================>
    struct GroupStruct
        group g
        
        method onDestroy takes nothing returns nothing      
            local unit u
            
            loop
                set u = FirstOfGroup(.g)
                exitwhen u == null
                
                call GroupRemoveUnit(.g, u)
                call RemoveUnit(u)
            endloop
            call DestroyGroup(.g)
            
            set u = null
            set .g = null
        endmethod
    
        static method create takes nothing returns GroupStruct
            local GroupStruct g = GroupStruct.allocate()
            
            set g.g = CreateGroup()
            
            return g
        endmethod
    endstruct 
    
    struct PulseStruct
        integer g
        real count
        unit caster
        
        method onDestroy takes nothing returns nothing
            call GroupStruct.destroy(.g)
            
            set .caster = null
        endmethod
        
        static method create takes unit caster, integer g returns PulseStruct
            local PulseStruct p = PulseStruct.allocate()
            
            set p.count = 0
            set p.caster = caster
            set p.g = g
            
            return p
        endmethod
    
    endstruct  
    
    //===========================>
    //Private Functions
    //===========================>

    private function GroupFilter takes nothing returns boolean
        if(GetUnitAbilityLevel(GetFilterUnit(), BuffCode) > 0) then
            return true
        endif
        return false
    endfunction

    private function TimerTick takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local PulseStruct p = GetAttachedInt(t, "PulseStruct")
        local group g = CreateGroup()
        local unit u
        local real y
        local real x
        local real angle   
        
        set p.count = p.count + Timer_Interval
          
        call GroupEnumUnitsInRange(g, GetUnitX(p.caster), GetUnitY(p.caster), Pulse_Range, Condition(function GroupFilter))
        
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            
            call UnitDamageTarget(p.caster, u, I2R(GetUnitAbilityLevel(p.caster, AbilCode))*Damage_Amount*(Timer_Interval/Move_Duration), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)  
                
            set angle = Atan2(GetUnitY(u)-GetUnitY(p.caster), GetUnitX(u)-GetUnitX(p.caster))
                
            set x = GetUnitX(u)+Movement_Speed*Cos(angle) 
            set y = GetUnitY(u)+Movement_Speed*Sin(angle)                      
            call SetUnitPosition(u, x, y)
            call GroupRemoveUnit(g, u)
        endloop
        
        
        if(p.count == Move_Duration) then
            call CleanAttachedVars(t)
            call DestroyTimer(t)
            call PulseStruct.destroy(p)
        endif
        
        call DestroyGroup(g)
        set u = null
        set g = null
        set t = null           
    endfunction    

    //===========================>
    //Trigger Functions
    //===========================>
    function Trig_PulseNova_Conditions takes nothing returns boolean
        return GetSpellAbilityId() == AbilCode
    endfunction

    function Trig_PulseNova_Actions takes nothing returns nothing 
        local real angle = 6.28318/I2R(Nova_Effect_Number)
        local integer i = 0
        local unit u
        local GroupStruct g = GroupStruct.create()
        local real x
        local real y
        local PulseStruct p = PulseStruct.create(GetTriggerUnit(), g)
        local timer t = CreateTimer()
        
        loop
            exitwhen i == Nova_Effect_Number
            
            set u = CreateUnit(GetOwningPlayer(GetTriggerUnit()), Dummy_Unit, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), I2R(i)*angle)
            call UnitAddAbility(u, Nova_Ability)
            
            set x = GetUnitX(GetTriggerUnit())+300.0*Cos(I2R(i)*angle) 
            set y = GetUnitY(GetTriggerUnit())+300.0*Sin(I2R(i)*angle)
            call GroupAddUnit(g.g, u)
            
            call IssuePointOrder(u, Nova_Order, x, y)
            
            set i = i + 1        
        endloop  
                    
        call AttachInt(t, "PulseStruct", p)
        
        call PolledWait(Delay_Time)
        
        call TimerStart(t, Timer_Interval, true, function TimerTick)
        
        set u = null
        set t = null
    endfunction
endscope

//===========================================================================
function InitTrig_PulseNova takes nothing returns nothing
    set gg_trg_PulseNova = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_PulseNova, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_PulseNova, Condition(function Trig_PulseNova_Conditions))
    call TriggerAddAction( gg_trg_PulseNova, function Trig_PulseNova_Actions )
endfunction
How to Implement:
Spell Requirements:
1. A vJass preprocessor (If you don't have one you can download one from wc3campaigns.net)

How to implement this in your map:
1. Copy the CSCache and PulseNova triggers to your map. (If you have CSCache, don't worry about it)
2. Copy the unit called Dummy in the object editor.
3. Copy the abilities called Pulse Nova and Dummy Wave in the object editor.
4. Copy the buff Pulse Nova in the object editor.
5. Make sure all the values at the top of the PulseNova triggers are the right rawcodes for the
abilites, buff and unit, and make sure Pulse Nova is the buff in the Pulse Nova spell.
 

Attachments

  • PulseNova.w3x
    156.9 KB · Views: 655

Hatebreeder

So many apples
Reaction score
381
I noticed that you have some value called "g" in two different structs... Wouldn't something malfunction if you have two values that have the same name?
 

0zaru

Learning vJASS ;)
Reaction score
60
No, since the struct id varies...

I notice that you use a conversion to degrees, i don't know if this is bad but why don't work always in radians? (Exept for some unit facing things)
 

gref

New Member
Reaction score
33
1. I don't know that map, I don't play that many custom games. The last spell like this I saw was a leaky non-mui gui version called Pushback Nova about 2 years on wc3sear.ch. And I like the idea so I thought I'd remake it.

2. Won't conflict, and less typing = less time.

3. It's radians now. I just assumed most people would find degrees more comfortable.

Thanks for feedback...any feedback...even if you haven't actually used the spell :D
 

Sim

Forum Administrator
Staff member
Reaction score
534
> Lagless: Yes.

First cast did lag. :)
 

gref

New Member
Reaction score
33
The Buff takes care of that... I keep it like that because then all someone has to do make it move the allies etc is change the target fields in the Pulse Nova ability.

I'll make it filter the buffed units only. It's probably faster than grouping + conditioning all of them.
 

gref

New Member
Reaction score
33
Updated. The units are checked for the buff in the filter now, rather than when already in the group.
 

Sim

Forum Administrator
Staff member
Reaction score
534
Thanks!

Naturally, if the author is to fix these spells, they will most probably be approved once again!
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      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