Spell Pillar of Lightning

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> Why?

Deleted the globals. Didn't want to rename all the variables in the code. :p
 

U are a noob

Mega Super Ultra Cool Member
Reaction score
152
Code:
Pillar of Lightning
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Pillar of Lightning 
    Actions
        Set TempPoint = ((Target point of ability being cast) offset by (0.00, 0.00))
        Special Effect - Create a special effect at TempPoint using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
        Special Effect - Destroy (Last created special effect)
        For each (Integer A) from 1 to 10, do (Actions)
            Loop - Actions
                Unit - Create 1 Effect Unit for (Owner of (Triggering unit)) at TempPoint facing Default building facing degrees
                Unit - Order (Last created unit) to Stop
                Animation - Play (Last created unit)'s stand animation
                Set Wisps[(Integer A)] = (Last created unit)
                Animation - Change Wisps[(Integer A)] flying height to (50.00 x ((Real((Integer A))) - 1.00)) at 500.00
        Wait 0.10 seconds
        For each (Integer A) from 1 to LightningIntervals, do (Actions)
            Loop - Actions
                For each (Integer B) from 1 to NumberofTargets, do (Actions)
                    Loop - Actions
                        Custom script:   if (bj_forLoopBIndex == 1 or GetRandomInt(1,100) <= udg_ChanceforBolt) then
                        Unit - Create 1 Effect Unit for (Owner of (Triggering unit)) at TempPoint facing Default building facing degrees
                        Set Caster = (Last created unit)
                        Unit - Hide Caster
                        Unit - Add a 3.00 second Generic expiration timer to Caster
                        Animation - Change Caster flying height to (Random real number between 100.00 and 450.00) at 4000.00
                        Set TempGroup = (Units within BoltRange of TempPoint matching (((Matching unit) belongs to an enemy of (Owner of (Triggering unit))) Equal to True))
                        Set Target = (Random unit from TempGroup)
                        Unit - Order Caster to Orc Far Seer - Chain Lightning Target
                        Custom script:   call DestroyGroup(udg_TempGroup)
                        Custom script:   endif
                Wait (Random real number between 1.00 and 3.00) seconds
        For each (Integer A) from 1 to 10, do (Actions)
            Loop - Actions
                Animation - Change Wisps[(Integer A)] flying height to 0.00 at 300.00
        Wait 2.50 seconds
        For each (Integer A) from 1 to 10, do (Actions)
            Loop - Actions
                Unit - Remove Wisps[(Integer A)] from the game
        Custom script:   call RemoveLocation(udg_TempPoint)
If this is all that is in your spell you can upgrade it to MUI easy.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> If this is all that is in your spell you can upgrade it to MUI easy.

Array-less? Doubt it. Already tried.

The JASS version is MUI. Just use that. :p
 
C

Crapling

Guest
This looks awesome, I'll have to try it out once I get home.
 

Exide

I am amazingly focused right now!
Reaction score
448
JASS:

exitwhen looping &gt; end


Could be:

JASS:

exitwhen looping &gt; 10



Anyway, nice spell. :)
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> Could be:
JASS:
exitwhen looping &gt; 10



Yes. In some cases. Not all. But, I was just going for the MUI, and merely replaced the GUI functions with more efficient ones, but didn't alter the structure a whole lot.
 

Exide

I am amazingly focused right now!
Reaction score
448
>Yes. In some cases. Not all. But, I was just going for the MUI, and merely replaced the GUI functions with more efficient ones, but didn't alter the structure a whole lot.
Also, I noticed that later in the trigger;

JASS:

set end = LightningIntervals


So I guess it will only work properly on the first loop, and since you're using a variable, 'end', later anyway so what the heck... :p
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
Well, at least you're critiquing my code.

That's a good thing.
I thought there'd be more problems with it. (I don't do JASS well - yet.)

I'm surprised so far. :p
 

Sim

Forum Administrator
Staff member
Reaction score
534
> I thought there'd be more problems with it. (I don't do JASS well - yet.)
> I'm surprised so far. :p

If you insist :p

> set TempGroup = GetUnitsInRangeOfLocMatching(BoltRange, TempPoint, Condition(function Trig_Pillar_of_Lightning_Func008Func001Func007002003))

You could use the native directly by first setting TempGroup to "CreateGroup()" and then calling the function "GroupEnumUnitsInRangeOfLocMatching" (NOT setting the variable to the function. Call it and give it the created group).

You might want to name your functions better.

> set TempPoint = OffsetLocation(GetSpellTargetLoc(), 0, 0)

Technically, you should set first another location variable to "GetSpellTargetLoc()" because it leaks and then set TempPoint to this location offset by 0...

But, why not just set TempPoint directly to GetSpellTargetLoc()? :p

> call AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", TempPoint )
> call DestroyEffect( GetLastCreatedEffectBJ() )

Sorry, AddSpecialEffectLoc doesn't work with GetLastCreatedEffectBJ() :p

You should do this instead:

call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl", TempPoint ))

JASS:
    call CreateNUnitsAtLoc( 1, &#039;e000&#039;, GetOwningPlayer(GetTriggerUnit()), TempPoint, bj_UNIT_FACING )
    call IssueImmediateOrder( GetLastCreatedUnit(), &quot;stop&quot; )
    call SetUnitAnimation( GetLastCreatedUnit(), &quot;stand&quot; )
    set Wisps[looping] = GetLastCreatedUnit()


If you're going to use "GetLastCreatedUnit()" many times, you're better off setting it to a variable to prevent useless function calls.

While doing so, using the native "CreateUnit()" would also be better :p

Don't know why, but you did set the last created unit to a variable in the second loop!

So... that's about it!
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> You could use the native directly by first setting TempGroup to "CreateGroup()" and then calling the function "GroupEnumUnitsInRangeOfLocMatching" (NOT setting the variable to the function. Call it and give it the created group).


No idea what you mean there. :p
Why would I want to create the group when I just set the variable?

> You might want to name your functions better.

Bah! Who cares about that? Useless, that's what it is. :p

> Technically, you should set first another location variable to "GetSpellTargetLoc()" because it leaks and then set TempPoint to this location offset by 0...
But, why not just set TempPoint directly to GetSpellTargetLoc()?

Yes, I think I already mentioned this, but I thought that was causing a problem earlier. Didn't change it back. Fixed.

> Sorry, AddSpecialEffectLoc doesn't work with GetLastCreatedEffectBJ()

You should do this instead:

call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\ThunderCl ap\\ThunderClapCaster.mdl", TempPoint ))



Interesting. What does it do? How can it destroy an effect that has not been created?

> If you're going to use "GetLastCreatedUnit()" many times, you're better off setting it to a variable to prevent useless function calls.

Oh, now you're just being silly.
Don't expect consistency from me. Expect it to work. :p


> While doing so, using the native "CreateUnit()" would also be better

Boo! Hiss! I refuse to define X's and Y's. :p

> Don't know why, but you did set the last created unit to a variable in the second loop!

Consistency....
 

Sim

Forum Administrator
Staff member
Reaction score
534
> Why would I want to create the group when I just set the variable?

To use the native directly. Saves function calls :p

> Interesting. What does it do? How can it destroy an effect that has not been created?

I'll go in deep explanations of "what" and "why".

what?

Quite simple :p

Here is the function "AddSpecialEffectLocBJ" (which you didn't use)

JASS:
function AddSpecialEffectLocBJ takes location where, string modelName returns effect
    set bj_lastCreatedEffect = AddSpecialEffectLoc(modelName, where)
    return bj_lastCreatedEffect
endfunction


It sets bj_lastCreatedEffect to the newly created effect. (bj_lastCreatedEffect is returned by the function GetLastCreatedEffect)

Then, the function you used:

JASS:
native AddSpecialEffectLoc          takes string modelName, location where returns effect


Oops, no bj_lastCreatedEffect!

So it won't work.

why?

Why use the DestroyEffect before and how can you create and destroy an effect right away?

Well, to destroy an effect you need an already existing effect. Which is why we create an effect... to destroy it!

Point is, the editor will never destroy an effect (Few exceptions may apply...) until it reaches a full "cycle" of action.

Which means, it has to "play" his whole animation before dying.

SO, it saves a function call and it works anyway. Use it!

The thing you did previously didn't clean the leak.

> Don't expect consistency from me. Expect it to work. :p

I'm criticizing your code!

> Boo! Hiss! I refuse to define X's and Y's. :p

CreateUnitAtLoc anyone?

It's a native too, you can use it!

> Consistency....

:confused: Gha...! (n_04)
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> I'll go in deep explanations of "what" and "why".

Cool. All I really needed to see was the two code comparisons and the Destroy part. :p

> I'm criticizing your code!

Yes! It's just that bad! :p

> CreateUnitAtLoc anyone?

Hmm... I could do that.

> Gha...! (n_04)

What? Don't look at me like that. It works. :p
 

Sim

Forum Administrator
Staff member
Reaction score
534
> It works. :p

It is my philosophy too.

BUT, I had to criticize your work. (I was forced by... *insert unknown reason here*)

As for the GUI...

It works good without leaks? Fine.
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
> It works good without leaks? Fine.

Works good? Debatable. Not MUI. The pillar animation can get bugged a bit. Doesn't affect the spell's execution, but may cause eye torture. :p

Without leaks? Yes.
 

Sim

Forum Administrator
Staff member
Reaction score
534
MUI is not a requirement ;)

> The pillar animation can get bugged a bit.

:confused: Didn't notice that.
 

0zaru

Learning vJASS ;)
Reaction score
60
> You could use the native directly by first setting TempGroup to "CreateGroup()" and then calling the function "GroupEnumUnitsInRangeOfLocMatching" (NOT setting the variable to the function. Call it and give it the created group).


No idea what you mean there.
Why would I want to create the group when I just set the variable?


He means something like this
JASS:
local grup g=CreateGroup()
call GroupEnumUnitsInRangeOfLocMatching(all arguments here...)


>Interesting. What does it do? How can it destroy an effect that has not been created?


it creates the effect and destroy it playing the effect death animation (With some effects it doesn't work)

It's like this
JASS:
call RemoveUnit(CreateUnit(bla bla))

It creates the unit and then removes it

> If you're going to use "GetLastCreatedUnit()" many times, you're better off setting it to a variable to prevent useless function calls.

Oh, now you're just being silly.
Don't expect consistency from me. Expect it to work.


You can even do this directly
set bj_lastCreatedUnit=CreateUnit(arguments bla bla...) X's and Y's are easy to set :p

The "GetLastCreatedUnit()" function just returns bj_lastCreatedUnit
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
@ Daxtreme:

Yes. Completely random. Difficult to prevent. I've tried. See the latest version.

@ 0zaru:

Already got it, but thanks anyway. :D
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Yup, the master Purge has come to Purge your code, and renew it in an optimized way! Muahahahaa!

Here it is, optimized:

Just update your map and remove the globals. I really optimized your code, it was a big hassle, but I optimized it anyways!! :D

JASS:
//Constant functions, you may edit these//
constant function POL_rawcode takes nothing returns integer
    return &#039;A000&#039; //The rawcode of the spell//
    //POL means Pillar_Of_Lightning//
endfunction

constant function POL_ThunderClap takes nothing returns string
    return &quot;Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl&quot;
endfunction

constant function LightningIntervals takes nothing returns integer
    return 50
endfunction
constant function NumberofTargets takes nothing returns integer
    return 3
endfunction
constant function ChanceforBolt takes nothing returns integer
    return 20
endfunction
constant function BoltRange takes nothing returns real
    return 600.
endfunction
//Do NOT edit past this point unless you know what you are doing//

function Pillar_Of_Lightning_UnitEnemy takes nothing returns boolean
    return ( IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) == true )
endfunction

function Trig_Pillar_of_Lightning_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == POL_rawcode()
endfunction

function Trig_Pillar_of_Lightning_Actions takes nothing returns nothing
    local unit array Wisps
    local location TempPoint
    local unit Caster
    local unit Target
    local group TempGroup
    local integer i                      = 0   
    local integer i2                     = 0 
    set TempPoint = GetSpellTargetLoc()
    call DestroyEffect(AddSpecialEffectLoc(POL_ThunderClap(), TempPoint  ))
    set i = 1
    loop
        exitwhen i &gt; 10
        set Wisps<i> = CreateUnitAtLoc(GetOwningPlayer(GetTriggerUnit()) , &#039;e000&#039;, TempPoint, bj_UNIT_FACING )
        call IssueImmediateOrder( Wisps<i>, &quot;stop&quot; )
        call SetUnitAnimation( Wisps<i>, &quot;stand&quot; )
        call ResetUnitAnimation( Wisps<i> )
        call SetUnitFlyHeight( Wisps<i>, ( 50.00 * ( I2R(i) - 1 ) ), 500.00 )
        set i = i + 1
    endloop
    call TriggerSleepAction( 0.10 )
    set i = 1
    loop
        exitwhen i &gt; LightningIntervals()
        set i2 = 1
        loop
            exitwhen i2 &gt; NumberofTargets()
            if (i2 == 1 or GetRandomInt(1,100) &lt;= ChanceforBolt()) then
                set Caster = CreateUnitAtLoc(GetOwningPlayer(GetTriggerUnit()) , &#039;e000&#039;, TempPoint, bj_UNIT_FACING )
                call ShowUnitHide( Caster )
                call UnitApplyTimedLife(Caster, &#039;BTLF&#039;, 3.00 )
                call SetUnitFlyHeight( Caster, GetRandomReal(100.00, 450.00), 4000.00 )
                set TempGroup = CreateGroup()
                call GroupEnumUnitsInRangeOfLoc(TempGroup, TempPoint, BoltRange(), Condition(function Pillar_Of_Lightning_UnitEnemy))
                set Target = GroupPickRandomUnit(TempGroup)
                call IssueTargetOrder( Caster, &quot;chainlightning&quot;, Target )
                call DestroyGroup(TempGroup)
                set TempGroup            = null
                set Caster               = null
                set Target               = null
            endif
            set i2 = i2 + 1
        endloop
        call TriggerSleepAction( GetRandomReal(1.00, 3.00) )
        set i = i + 1
    endloop
    set i = 1
    loop
        exitwhen i &gt; 10
        call SetUnitFlyHeight( Wisps<i>, 0.00, 300.00 )
        set i = i + 1
    endloop
    call TriggerSleepAction( 2.50 )
    set i = 1
    loop
        exitwhen i &gt; 10
        call RemoveUnit( Wisps<i> )
        set Wisps<i>                     = null
        set i = i + 1
    endloop
    call RemoveLocation(TempPoint)
    set TempPoint                        = null
endfunction

//===========================================================================
function InitTrig_Pillar_of_Lightning takes nothing returns nothing
    set gg_trg_Pillar_of_Lightning = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Pillar_of_Lightning, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(gg_trg_Pillar_of_Lightning,Condition(function Trig_Pillar_of_Lightning_Conditions))
    call TriggerAddAction( gg_trg_Pillar_of_Lightning, function Trig_Pillar_of_Lightning_Actions )
endfunction</i></i></i></i></i></i></i></i>
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
889
Constant Functions? We don't need constant functions. :p

No, seriously. How are people supposed to be able to set the globals? You don't even include them. I left them for a reason.

I guess it's just as easy to edit them in the code with them not being globals, but it would be easier if they could set them with GUI for the newer mappers.

Either way works.

Thanks for the optimization. :D
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Well, I think I understand you correctly. See, the global variables should only be for the GUI version. Instead of using locals that are set to globals, you can just make constant functions. It is much more easier to edit. You just need to type. Not click the value and go through all those selection junk.

Since you are setting locals to globals, why not just use the globals? Since you don't have two triggers or functions in which those globals are needed, why use the globals? It just adds more implementation difficulty.

Besides, constant functions are so easy to edit. In fact, I should make a tutorial about it.

~Reserved tutorial idea until further notice~ :D

Your welcome! Thanks for making the spell! :p
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Monovertex Monovertex:
    How are you all? :D
    +1
  • 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 Discord

      Staff online

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top