Spell Lightning Ward (GUI/JASS/VJASS)

Septimus

New Member
Reaction score
58
spells_2256_screenshot.jpg


Status

Coding Type : GUI/JASS/VJASS
Spell Type : MUI

Ability Description

Unleash a ward around the targeted unit that would attack it, the ward would also release a energy bolt that destroy the hp of nearby enemy unit. Targeted unit get stun for 5 seconds by this ability.

Level 1 - Lasts 10 seconds.
Level 2 - Lasts 15 seconds.
Level 3 - Lasts 20 seconds.

Version 1.07 Update

Create a VJASS version of it (Full credit for VJASS version goes to Dark Dragon).

Version 1.06

Add additional code in order to remove 16 memory leaks of type boolexpr cause by TriggerRegisterAnyUnitEventBJ

Version 1.05

Create a JASS version of it.

Version 1.04

Further optimize the maths to enable beginner to modify this spell easier.

Version 1.03

Fix minor flaw.

Version 1.02

Improve coding.

Version 1.01

Disable documentation sample.​

Trigger:
  • Lightning Ward GUI
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Lightning Ward (GUI)
    • Actions
      • Set LW_Target_Unit = (Target unit of ability being cast)
      • Set LW_Target_Point = (Target point of ability being cast)
      • Set LW_Target_Position = (Position of LW_Target_Unit)
      • Set LW_Level = (Level of Lightning Ward (GUI) for (Triggering unit))
      • Set LW_Duration = (5.00 + (5.00 x (Real(LW_Level))))
      • Set LW_Loop_Number = 5
      • For each (Integer LW_Integer) from 1 to LW_Loop_Number, do (Actions)
        • Loop - Actions
          • Set LW_Spawn_Point = (LW_Target_Position offset by 500.00 towards (360.00 x ((Real(LW_Integer)) / (Real(LW_Loop_Number)))) degrees)
          • Unit - Create 1 Lightning Ward for (Owner of (Triggering unit)) at LW_Spawn_Point facing LW_Target_Point
          • Unit - Add a LW_Duration second Generic expiration timer to (Last created unit)
          • Unit - Add Lightning Bolt to (Last created unit)
          • Unit - Order (Last created unit) to Undead Crypt Lord - Locust Swarm
          • Unit - Order (Last created unit) to Attack LW_Target_Unit
          • Custom script: call RemoveLocation(udg_LW_Spawn_Point)
      • Custom script: call RemoveLocation(udg_LW_Target_Point)
      • Custom script: call RemoveLocation(udg_LW_Target_Position)


JASS:
function Trig_Lightning_Ward_JASS_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A003'
endfunction

function Trig_Lightning_Ward_JASS_Actions takes nothing returns nothing
    local unit LTR = GetTriggerUnit()
    local unit LV = GetSpellTargetUnit()
    local location LP = GetSpellTargetLoc()
    local location LT = GetUnitLoc(LV)
    local location LSP
    local integer LL = GetUnitAbilityLevel(LTR, 'A003')
    local real LD = 5.00 + 5.00 * LL
    local integer LI = 1
    local unit LU
    local real FA = AngleBetweenPoints(LT, LP)
    local integer DU = 5
    local real Deg = 360/DU
    loop
        exitwhen LI > DU
        set LSP = PolarProjectionBJ(LT, 500.00, LI * Deg)
        set LU = CreateUnitAtLoc(GetOwningPlayer(LTR), 'o000', LSP, FA)
        call UnitApplyTimedLife(LU, 'BTLF', LD)
        call UnitAddAbility(LU, 'A002')
        call IssueImmediateOrder(LU, "locustswarm" )
        call IssueTargetOrder(LU, "attack", LV )
        call RemoveLocation(LSP)
        set LU = null
        set LI = (LI+1)
    endloop
    call RemoveLocation(LP)
    call RemoveLocation(LT)
    set LP = null
    set LT = null
    set LTR = null
    set LV = null
    set LSP = null
endfunction

constant function DummyFilter takes nothing returns boolean
    return true
endfunction

function Lightning_Ward_JASS takes nothing returns nothing
    local trigger T = CreateTrigger()
    local integer TI = 0
    local filterfunc FF = Filter(function DummyFilter)
    loop
    exitwhen (TI >= bj_MAX_PLAYER_SLOTS)
    call TriggerRegisterPlayerUnitEvent(T, Player(TI), EVENT_PLAYER_UNIT_SPELL_EFFECT, FF)
    set TI = TI + 1
    endloop
    call DestroyFilter(FF)
    set FF = null
    set T = null
endfunction

//===========================================================================
function InitTrig_Lightning_Ward_JASS takes nothing returns nothing
    set gg_trg_Lightning_Ward_JASS = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Lightning_Ward_JASS, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Lightning_Ward_JASS, Condition( function Trig_Lightning_Ward_JASS_Conditions ) )
    call TriggerAddAction( gg_trg_Lightning_Ward_JASS, function Trig_Lightning_Ward_JASS_Actions )
endfunction


JASS:
library_once LightningWard initializer Init

globals
    private constant integer LIGHTNING_WARD = 'A004'
    private constant integer DUMMY_RAWCODE  = 'o000'
    private constant integer SWARM_RAWCODE  = 'A002'
    private constant real    OFFSET_DISTANCE = 500.
    private constant integer MAX_WARDS = 5
endglobals

private function LightningWard takes nothing returns boolean
    local unit LTU
    local unit LV
    local player P
    local real X
    local real Y
    local real LD
    local integer LI
    local unit LU
    local real RAD
    if (GetSpellAbilityId() == LIGHTNING_WARD) then
    set LTU = GetTriggerUnit()
    set LV = GetSpellTargetUnit()
    set X = GetUnitX(LV)
    set Y = GetUnitY(LV)
    set LD = (GetUnitAbilityLevel(LTU, LIGHTNING_WARD)*5)+5.
    set RAD = (2.*bj_PI)/MAX_WARDS
    set P = GetOwningPlayer(LTU)
    set LI = 0
    loop
    exitwhen (LI >= MAX_WARDS)
        set LU = CreateUnit(P, DUMMY_RAWCODE, X+OFFSET_DISTANCE*Cos(RAD*LI), Y+OFFSET_DISTANCE*Sin(RAD*LI), 0.)
        call UnitApplyTimedLife(LU, 'BTLF', LD)
        call UnitAddAbility(LU, SWARM_RAWCODE)
        call IssueImmediateOrder(LU, "locustswarm" )
        call IssueTargetOrder(LU, "attack", LV)
        set LI = LI + 1
    endloop
    set LU = null
    set P = null
    set LTU = null
    set LV = null
    endif
    return (FALSE)
endfunction

// ===========================================================================
private constant function DummyFilter takes nothing returns boolean
    return true
endfunction

private function Init takes nothing returns nothing
    local trigger T = CreateTrigger()
    local integer I = 0
    local filterfunc FF = Filter(function DummyFilter)
    loop
    exitwhen (I >= bj_MAX_PLAYER_SLOTS)
        call TriggerRegisterPlayerUnitEvent(T, Player(I), EVENT_PLAYER_UNIT_SPELL_EFFECT, FF)
        set I = I + 1
    endloop
    call TriggerAddCondition(T, Condition(function LightningWard))
    call DestroyFilter(FF)
    set FF = null
    set T = null
endfunction

endlibrary
 

Attachments

  • Lightning Ward v1.07.w3x
    22.5 KB · Views: 288

WolfieeifloW

WEHZ Helper
Reaction score
372
The vJASS version should be a scope, not a library.
And a lot of those locals look like they could be set at initialization, could they not?
The whole vJASS trigger looks weird actually :p .

Spell looks good though;
Nice job!


EDIT: Locations in the vJASS too;
Why not X/Y, it's JASS, c'mon :p .
(And if normal JASS can do X/Y, why not in that one too)

EDITEDIT: Explain the globals with a commented line.
 

simonake

New Member
Reaction score
72
Trigger:
  • Set LW_Loop_Number = 5


If the number always stay 5, you should put, in the loop, the number "5", it will save you place, time and energy. And in this case, it's useless. (Maybe I'm wrong) Am I?
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Your coding style so weird, boolexpr no need to care about. U only do double work to get 1 only result.Y u pt whole spell trigger in Condition???? It is bad, becauz it generate lots of variables and slow down whole spells trigger in ur game, i think.... You should follow the usual way. AddAction to trigger.
 

Kenny

Back for now.
Reaction score
202
Use this for your vJass one, it should work:

Note: It Requires GTrigger by Jesus4Lyf, found in the systems section here on thehelper.

JASS:
scope LightningWard initializer Init

    globals
        private constant integer LIGHTNING_WARD  = 'A004'
        private constant integer DUMMY_RAWCODE   = 'o000'
        private constant integer SWARM_RAWCODE   = 'A002'
        private constant integer MAX_WARDS       = 5
        private constant real    OFFSET_DISTANCE = 500.00
    endglobals

    private function Actions takes nothing returns boolean
        local unit    cast  = GetTriggerUnit()
        local unit    targ  = GetSpellTargetUnit()
        local player  owner = GetOwningPlayer(cast)
        local real    targx = GetUnitX(targ)
        local real    targy = GetUnitY(targ)
        local real    life  = (GetUnitAbilityLevel(cast,LIGHTNING_WARD) * 5.00) + 5.00
        local real    rad   = (2.00 * bj_PI) / MAX_WARDS
        local unit    dummy = null
        local integer i     = 0

        loop
            exitwhen i >= MAX_WARDS
            set dummy = CreateUnit(owner,DUMMY_RAWCODE,targx + OFFSET_DISTANCE * Cos(rad * i),targy + OFFSET_DISTANCE * Sin(rad * i),0.00)
            call UnitApplyTimedLife(dummy,'BTLF',life)
            call UnitAddAbility(dummy,SWARM_RAWCODE)
            call IssueImmediateOrder(dummy,"locustswarm")
            call IssueTargetOrder(dummy,"attack",targ)
            set i = i + 1
        endloop
        
        set cast  = null
        set targ  = null
        set dummy = null
        // set owner = null players don't need to be nulled.
        
        return false
    endfunction

    private function Init takes nothing returns nothing
        call GT_AddStartsEffectAction(function Actions,LIGHTNING_WARD)
    endfunction

endscope


@ kingkingyyk3:

Putting your script inside a condition does not matter that much, many people do it as conditions are safer than actions.
 

Septimus

New Member
Reaction score
58
EDIT: Locations in the vJASS too;
Why not X/Y, it's JASS, c'mon .
(And if normal JASS can do X/Y, why not in that one too)

GUI and JASS version are made by me, the vjass are made by Dark Dragon. I have request him to make a simple version of vjass to enable newbie in jass to import it without having much problem (Unless they are too lazy to figure out how to use vjass, then they could use jass).

If the number always stay 5, you should put, in the loop, the number "5", it will save you place, time and energy. And in this case, it's useless. (Maybe I'm wrong) Am I?

Design for user friendly (For those who are too freaking noob to use JASS and GUI). If you read the documentation, you would know how detail the information had been provided.

Your coding style so weird, boolexpr no need to care about. U only do double work to get 1 only result.Y u pt whole spell trigger in Condition???? It is bad, becauz it generate lots of variables and slow down whole spells trigger in ur game, i think.... You should follow the usual way. AddAction to trigger.

According to dark dragon, it would leak if you do not fix it. Also condition work faster than action.

Use this for your vJass one, it should work:

Note: It Requires GTrigger by Jesus4Lyf, found in the systems section here on thehelper.

The purpose of this spells coding was set this way is to make it easy, efficient and does not require any system (So it would be convenient.)

This spells was highly recommended at hiveworkshop.com for the efficiency and user friendly.

http://www.hiveworkshop.com/forums/resource.php?t=125624&prev=u=Septimus
 

Azlier

Old World Ghost
Reaction score
461

wraithseeker

Tired.
Reaction score
122
The BJ for EVENT_PLAYER_UNIT_SPELL_EFFECT do not leak a boolexpr.

I don't understand why people from THW always say it's highly recommended there though, it's weird when it still have rooms for improvement but yeah it's neat still.

X and Y for locations are good.

EDIT: *rants* azlier.
 

RMX

New Member
Reaction score
8
Great Spell love the effects........
And the coding is hmmmmmmmm Priceless ..... VERY GREAT ....... still learning vJASS thought ....... THW RULES !!! .

Keep the Ideas flow coming :p
 

Kenny

Back for now.
Reaction score
202
Using action would just increase the handle.

First off, no. Secondly, if your worried about the handle count, then import GTrigger into your maps and use the script I posted.

Or use this:

JASS:
scope LightningWard initializer Init

    globals
        private constant integer LIGHTNING_WARD  = 'A004'
        private constant integer DUMMY_RAWCODE   = 'o000'
        private constant integer SWARM_RAWCODE   = 'A002'
        private constant integer MAX_WARDS       = 5
        private constant real    OFFSET_DISTANCE = 500.00
        private boolexpr         True_filt       = null // Do not touch!
    endglobals

    private function Actions takes nothing returns nothing
        local unit    cast  = GetTriggerUnit()
        local unit    targ  = GetSpellTargetUnit()
        local player  owner = GetOwningPlayer(cast)
        local real    targx = GetUnitX(targ)
        local real    targy = GetUnitY(targ)
        local real    life  = (GetUnitAbilityLevel(cast,LIGHTNING_WARD) * 5.00) + 5.00
        local real    rad   = (2.00 * bj_PI) / MAX_WARDS
        local unit    dummy = null
        local integer i     = 0

        loop
            exitwhen i >= MAX_WARDS
            set dummy = CreateUnit(owner,DUMMY_RAWCODE,targx + OFFSET_DISTANCE * Cos(rad * i),targy + OFFSET_DISTANCE * Sin(rad * i),0.00)
            call UnitApplyTimedLife(dummy,'BTLF',life)
            call UnitAddAbility(dummy,SWARM_RAWCODE)
            call IssueImmediateOrder(dummy,"locustswarm")
            call IssueTargetOrder(dummy,"attack",targ)
            set i = i + 1
        endloop
        
        set cast  = null
        set targ  = null
        set dummy = null
        // set owner = null players don't need to be nulled.
    endfunction

    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == LIGHTNING_WARD
    endfunction

    private function True_filter takes nothing returns boolean
        return true
    endfunction

    private function Init takes nothing returns nothing
        local trigger trig = CreateTrigger()
        local integer i    = 0

        set True_filt = Filter(function True_filter)
  
        loop
            call TriggerRegisterPlayerUnitEvent(trig,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,True_filt)
            set i = i + 1
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop

        call TriggerAddCondition(trig,Condition(function Conditions))
        call TriggerAddAction(trig,function Actions)
    endfunction

endscope


Its quite similar to yours, just neater. And this doesn't require GTrigger.
 

Viikuna

No Marlo no game.
Reaction score
265
vJass version looks good.
Player variables dont have to be nulled ( but you can null them if you want, Im not complaining ).
You could use TriggerRegisterAnyUnitEventBJ ( There is nothing wrong with that, it seems that null boolexprs only malfunctions with GroupEnum for some weird reason )

And yes, you should use only condition, because actions are slow and usually pretty useless. ( Like in this case )



JASS:
set LD = (GetUnitAbilityLevel(LTU, LIGHTNING_WARD)*5)+5.


You could use some constant function for this, like: function DURATION takes integer level returns real

Its easier for people to modify spell, when you use constants for stuff like this. ( I see you already have stuff like MAX_WARDS there, which is exactly how it should be )
 

BlackRose

Forum User
Reaction score
239
That is pretty electrical. The weird bolt moving along looks weird, when the target dies -.- Make a channeling version?
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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 The Helper:
    I think we need to add something to the bottom of the front page that shows the Headline News forum that has a link to go to the News Forum Index so people can see there is more news. Do you guys see what I am saying, lets say you read all the articles on the front page and you get to the end and it just ends, no kind of link for MOAR!
  • The Helper The Helper:
    Happy Wednesday!
    +1
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    Sticking with the desserts for now the latest recipe is Fried Apple Pies - https://www.thehelper.net/threads/recipe-fried-apple-pies.194297/
  • The Helper The Helper:
    Finally finding about some of the bots that are flooding the users online - bytespider apparently is a huge offender here - ignores robots.txt and comes in from a ton of different IPs

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top