• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Lightning Ward (GUI/JASS/VJASS)

Detail
Status

Forum: http://septimus.invisionplus.net
Coding: GUI/JASS/VJASS
Current Version: 1.08

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.08 Update

Fix documentation.

Version 1.07

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.



Dark_Dragon - For hinting a tiny flaw in the coding and fix JASS. He is also responsible for making VJASS version of it.
-BerZeKeR- - Showing a efficient maths coding.
GhostWolf - For pointing a silly mistake I made in JASS version and help me optimize the JASS version.
hvo-busterkomo - Helping me fix loop issue at JASS version.
Purplepoot - For guiding me in loop issue at JASS version.
Ralle - For guiding me in loop issue at JASS version.

  • 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
Keywords:
Wards, Lightning, Electricity, Multi Effect, Impressive
Contents

Lightning Ward Spell (Map)

Reviews
19:50, 7th May 2009 Dr Super Good: Highly Recommended Very impressive spells. I feared that they might lag on my PC looking at the screenshot but was suprized to see that even with multile casts of multiple version, no lag occured. It...
Status
Not open for further replies.

Moderator

M

Moderator

19:50, 7th May 2009
Dr Super Good:
Evaluation

Rating

Highly Recommended
Rating Comment

Very impressive spells. I feared that they might lag on my PC looking at the screenshot but was suprized to see that even with multile casts of multiple version, no lag occured. It seems completly leakless and obviously is fully MUI, as the test proves. It also looks cool, which is important and I can see many maps using this spell with no problems. It also seems to be easilly balencable as quite a few of its effects are object editor related, but there is also some customizability in the actual spell itself. Testing this spell was not that good, as the test conditions are poor as multiple versions are cast with the same button.

Suggestions . . .
- Improve test map, fixing it so that you can choose which version is cast properly and that it is easier to test (better creep arangement).
Advice: If you do not understand why this spell was given the rating it received or if you would like to ask questions about how to improve this spell. Feel free to send a private message to spell moderator Dr Super Good.
 
Level 31
Joined
May 3, 2008
Messages
3,155
This is my first spell and I still trying to figure out a even more effective coding, right now I try to figure out how to set the If/Then/Else of the level and duration in much appropriate way so it would not restrain the level into max 3 (Maybe you won't understand what I trying to say at here :p).

Creating spell really tough, it need a good creativity to make even 1 spell. Do not worry about this spell, it was leak free unless I forgot about something.

I think my spell description need to be change, any idea how to make it sound better?
 
  • Like
Reactions: Rmx
Level 15
Joined
Jul 19, 2007
Messages
618
very good for beginner spell!

things i would suggest are as following:

1. --------------------------------------
Change your spell event to:

  • Unit - A unit Starts the effect of an ability
2. --------------------------------------
Change your if then else [(if then else) if then else] with following line:

  • Set LW_Duration = (5.00 + (5.00 x (Real(LW_Level))))
3. --------------------------------------
In your variable LW_Target_Unit store Target unit of ability being cast and create new variable LW_Target_Pos and store target's position. Then instead of whole the time calling Target Unit of ab... use LW_Target_Unit

its not coz of speed its coz when calling that function multiple times in same trigger might bug. Its blizzard bug, so that is why i suggest you to use variable coz 1. when called it will work 100%.

4. --------------------------------------
I would add few comments but since code is simple it does not need to have any comments. Well for other beginners it should but as said not needed.


that would be all fix this and it will be 5/5 coz this is your first spell.
+rep anyway
~Dark Dragon

EDIT: :O you said if you where better at math? maybe i might help you...
 
Level 31
Joined
May 3, 2008
Messages
3,155
2. --------------------------------------
Change your if then else [(if then else) if then else] with following line:

Ahh, yes. That is what I been thinking about it, I been trying to fix this. But, I don't know how cause my maths sucks... :p

Thanks, +rep

3. --------------------------------------
In your variable LW_Target_Unit store Target unit of ability being cast and create new variable LW_Target_Pos and store target's position. Then instead of whole the time calling Target Unit of ab... use LW_Target_Unit

its not coz of speed its coz when calling that function multiple times in same trigger might bug. Its blizzard bug, so that is why i suggest you to use variable coz 1. when called it will work 100%.

I don't know there is a existence of such a bug.
 
Level 15
Joined
Jul 19, 2007
Messages
618
no no no xD

you got me wrong i mean you should store unit in LW_Target_Unit not point here is the code how it should look like:

  • Lightning Ward
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Lightning Ward
    • Actions
      • Set LW_Target_Unit = (Target unit of ability being cast)
      • Set LW_Target_Point = (Target point of ability being cast)
      • Set LW_Target_Pos = (Position of LW_Target_Unit)
      • Set LW_Level = (Level of Lightning Ward for (Triggering unit))
      • Set LW_Duration = (5.00 + (5.00 x (Real(LW_Level))))
      • For each (Integer LW_Integer) from 1 to 5, do (Actions)
        • Loop - Actions
          • Set LW_Spawn_Point = (LW_Target_Pos offset by 500.00 towards (LW_Real + 72.00) 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
          • Set LW_Real = (LW_Real + 72.00)
          • Custom script: call RemoveLocation(udg_LW_Spawn_Point)
      • Custom script: call RemoveLocation(udg_LW_Target_Point)
      • Custom script: call RemoveLocation(udg_LW_Target_Pos)
anyway its 5/5 now gj on ur first spell and if you need help with math or coding...
feel free to ask me ill try to help!

Greets!
~Dark Dragon
 
Level 31
Joined
May 3, 2008
Messages
3,155
Wow, you say this is your first spell?
Gj, i mean it is refreshing to see someones first spell and that i don't have to implicate how to fix leaks and use variables...
Well deserves 5/5 +rep^^

I know how to fix leak and use variable/array. The only main problem with spell is, it require maths such as radian, offset, degree and etc etc. Which are my natural weak spot in spell making.. XD
 
Level 15
Joined
Jul 19, 2007
Messages
618
since its your first jass spell i think its really awesome. I can say only great job on it its well optimized and leakless. Well i am not sure do you know but actually that AnyUnitEventBJ cause 16 memory leaks of type boolexpr to fix that make function which returns true and takes nothing, the in init trigger:

JASS:
local filterfunc ff = Filter(function ThatTrueFunc)
set i = 0
loop
exitwhen (i >= bj_MAX_PLAYER_SLOTS)
call TriggerRegisterPlayerUnitEvent(trig, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, ff)
set i = i + 1
endloop

call DestroyFilter(ff)
set ff = null

Greets!
~DD
 
Level 31
Joined
May 3, 2008
Messages
3,155
Update with vjass version.

User now have the option to use this spells in GUI, JASS or VJASS.

If you are newbie and refuse to use JASS; you're welcome to use GUI.
If you are JASS user, but not familiar with VJASS; you're welcome to use JASS.
If you are JASS user, but want 100% perfect coding; you're welcome to use VJASS.

3 selectable option, have a nice day. :grin:
 
Level 6
Joined
Jul 25, 2005
Messages
221
Interesting first spell. Well done!

[Change]
You should probably change the order strings for the spells used for each type of triggering,
because, as it is, if you learn all of them and you want to cast one, the unit is ordered to cast
all of them.

[Suggestions]
I suggest that in the future you make your variables* more descriptable, so that you above all know what they are/stand for.
Don't worry about the name size, it's more important that you know what they are used for.

Again, this is a suggestion, because when you get into it more you start dealing with more variables
and it can get a bit messy if you use abbreviations

*Referring to programming in general, but in this case JASS scripts

What is vJass? I might already have it, but I'm unsure. :cute:
Does it come in the NewGen Pack?

What I can do with my current GDI:

  • Define globals
  • Use structs (love)
  • Define scope
 
Last edited:
Level 6
Joined
Jul 25, 2005
Messages
221
One tip:
Use large letters for global variables and normal letters for local variables.
This makes jassers easier to read and understand the code + i think it's a standard now :p

Yah, they made it standard. Read it in the latest JASShelper readme. :wink:
 
Status
Not open for further replies.
Top