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: 656

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.
  • Ghan Ghan:
    Howdy
  • 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 Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top