Spell Energy Flow

Moridin

Snow Leopard
Reaction score
144
Energy Flow
View attachment Spell - Energy Flow.w3x

Description:

GUI
MUI
Leakless
Lagless


Summons 3 orbs of energy around the caster. These orbs spin in a circle, growing larger and more powerful as they spin. Whenever the caster targets a unit with another spell, one of the orbs breaks away from the circle to explode near the target, damaging all units in an AOE.

Orbs gain 1 charge per 360 degrees of spin. Damage depends on Base damage, level of Energy Flow and number of charges gained by the orb.

Requirements:

Hashtables (TFT, WC 1.24(e) recommended)

Implementation:

Read the README File in the map.

Screenshots:

energyflowstill.jpg


energyflowaction.jpg

Triggers:

Trigger:
  • Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Hashtable - Create a hashtable
      • Set EN_Hashtable = (Last created hashtable)


Trigger:
  • EN Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Energy Flow
    • Actions
      • -------- EDITABLE VALUES --------
      • Set EN_NoOfBombs = 3
      • Set EN_MaxBombCharge = 3
      • Set EN_Base_Damage = 50
      • Set EN_PerLevel_Damage = 50
      • Set EN_PerCharge_Damage = 10
      • Set EN_Splash = True
      • Set EN_AOE_Splash = 175
      • Set EN_FriendlyFire = False
      • -------- Total Bomb Damage = Base Damage + (PerLevelDamage*LevelOfAbility) + (PerChargeDamage*NoOfCharges) --------
      • -------- ------------------------------ --------
      • Trigger - Turn on EN Spin <gen>
      • Trigger - Turn on EN Activate <gen>
      • Hashtable - Save False as ((Key (Triggering unit)) - 2) of 1 in EN_Hashtable
      • Unit Group - Add (Triggering unit) to EN_casters
      • -------- Number of charges left --------
      • Hashtable - Save EN_NoOfBombs as ((Key (Triggering unit)) - 1) of 1 in EN_Hashtable
      • For each (Integer A) from 1 to EN_NoOfBombs, do (Actions)
        • Loop - Actions
          • Unit - Remove (Load (Key (Triggering unit)) of (Integer A) in EN_Hashtable) from the game
          • -------- --------------------- --------
          • Set temp_point = (Position of (Triggering unit))
          • Set temp_point_2 = (temp_point offset by 100.00 towards ((Real((Integer A))) x (360.00 / (Real(EN_NoOfBombs)))) degrees)
          • Unit - Create 1 Charge for (Triggering player) at temp_point_2 facing Default building facing degrees
          • Hashtable - Save Handle Of(Last created unit) as (Key (Triggering unit)) of (Integer A) in EN_Hashtable
          • Custom script: call RemoveLocation (udg_temp_point)
          • Custom script: call RemoveLocation (udg_temp_point_2)
          • -------- EDITABLE VALUES --------
          • -------- size and hover height --------
          • Animation - Change (Last created unit)'s size to (50.00%, 50.00%, 50.00%) of its original size
          • -------- ------------------------------ --------
          • -------- Degrees the charge has rotated --------
          • Hashtable - Save 0 as ((Key (Triggering unit)) + 1) of (Integer A) in EN_Hashtable
          • -------- Power of the charge --------
          • Hashtable - Save 0 as ((Key (Triggering unit)) + 2) of (Integer A) in EN_Hashtable
          • -------- Angle --------
          • Set EN_Current_angle[(Integer A)] = ((Real((Integer A))) x (360.00 / (Real(EN_NoOfBombs))))


Trigger:
  • EN Spin
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (EN_casters is empty) Not equal to True
        • Then - Actions
          • Unit Group - Pick every unit in EN_casters and do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Load ((Key (Picked unit)) - 1) of 1 from EN_Hashtable) Equal to 0
                • Then - Actions
                  • Unit Group - Remove (Picked unit) from EN_casters
                  • Skip remaining actions
                • Else - Actions
              • For each (Integer A) from 1 to (Load ((Key (Picked unit)) - 1) of 1 from EN_Hashtable), do (Actions)
                • Loop - Actions
                  • Set Current_unit = (Load (Key (Picked unit)) of (Integer A) in EN_Hashtable)
                  • Set EN_Current_angle[(Integer A)] = (EN_Current_angle[(Integer A)] + 12.00)
                  • Set temp_point = (Position of (Picked unit))
                  • Set temp_point_2 = (temp_point offset by 50.00 towards EN_Current_angle[(Integer A)] degrees)
                  • Unit - Move Current_unit instantly to temp_point_2
                  • Custom script: call RemoveLocation (udg_temp_point)
                  • Custom script: call RemoveLocation (udg_temp_point_2)
                  • Hashtable - Save ((Load ((Key (Picked unit)) + 1) of (Integer A) from EN_Hashtable) + 12) as ((Key (Picked unit)) + 1) of (Integer A) in EN_Hashtable
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Load ((Key (Picked unit)) + 1) of (Integer A) from EN_Hashtable) Greater than 360
                      • (Load ((Key (Picked unit)) + 2) of (Integer A) from EN_Hashtable) Less than EN_MaxBombCharge
                    • Then - Actions
                      • Hashtable - Save ((Load ((Key (Picked unit)) + 2) of (Integer A) from EN_Hashtable) + 1) as ((Key (Picked unit)) + 2) of (Integer A) in EN_Hashtable
                      • Hashtable - Save 0 as ((Key (Picked unit)) + 1) of (Integer A) in EN_Hashtable
                    • Else - Actions
                  • -------- The actions below are just effects for the different levels of charge --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Load ((Key (Picked unit)) + 2) of (Integer A) from EN_Hashtable) Equal to 1
                    • Then - Actions
                      • Animation - Change Current_unit's size to (70.00%, 70.00%, 70.00%) of its original size
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Load ((Key (Picked unit)) + 2) of (Integer A) from EN_Hashtable) Equal to 2
                    • Then - Actions
                      • Animation - Change Current_unit's size to (90.00%, 90.00%, 90.00%) of its original size
                    • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Load ((Key (Picked unit)) + 2) of (Integer A) from EN_Hashtable) Equal to 3
                    • Then - Actions
                      • Animation - Change Current_unit's size to (110.00%, 110.00%, 110.00%) of its original size
                    • Else - Actions
        • Else - Actions
          • Trigger - Turn off EN Activate <gen>
          • Trigger - Turn off EN Blowing up <gen>
          • Trigger - Turn off (This trigger)


Trigger:
  • EN Activate
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • ((Triggering unit) is in EN_casters) Equal to True
      • (Target unit of ability being cast) Not equal to No unit
    • Actions
      • Set temp_boolean = (Load ((Key (Triggering unit)) - 2) of 1 from EN_Hashtable)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • temp_boolean Equal to False
        • Then - Actions
          • Hashtable - Save True as ((Key (Triggering unit)) - 2) of 1 in EN_Hashtable
          • Skip remaining actions
        • Else - Actions
      • Set temp_int = (Load ((Key (Triggering unit)) - 1) of 1 from EN_Hashtable)
      • Set EN_Activated_Charge = (Load (Key (Triggering unit)) of temp_int in EN_Hashtable)
      • Set EN_Activated_Charge_handle = (Load (Key (Triggering unit)) of temp_int in EN_Hashtable)
      • -------- for later use in the next trigger --------
      • Unit - Set the custom value of EN_Activated_Charge to temp_int
      • -------- Saving target --------
      • Hashtable - Save Handle Of(Target unit of ability being cast) as (Key EN_Activated_Charge_handle) of temp_int in EN_Hashtable
      • -------- Power of the charge --------
      • Hashtable - Save (Load ((Key (Triggering unit)) + 2) of temp_int from EN_Hashtable) as ((Key EN_Activated_Charge_handle) + 1) of temp_int in EN_Hashtable
      • Hashtable - Save (Level of Energy Flow for (Triggering unit)) as ((Key EN_Activated_Charge_handle) + 2) of temp_int in EN_Hashtable
      • -------- Deducting from number of charges (balls) left --------
      • Hashtable - Save (temp_int - 1) as ((Key (Triggering unit)) - 1) of 1 in EN_Hashtable
      • -------- For slide trigger --------
      • Unit Group - Add EN_Activated_Charge to EN_Bombs
      • Trigger - Turn on EN Blowing up <gen>


Trigger:
  • EN Blowing up
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in EN_Bombs and do (Actions)
        • Loop - Actions
          • Set Current_unit = (Load (Key (Picked unit)) of (Custom value of (Picked unit)) in EN_Hashtable)
          • Set temp_point = (Position of (Picked unit))
          • Set temp_point_2 = (Position of Current_unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between temp_point and temp_point_2) Greater than or equal to 50.00
            • Then - Actions
              • Set temp_point_3 = (temp_point offset by 50.00 towards (Angle from temp_point to temp_point_2) degrees)
              • Unit - Move (Picked unit) instantly to temp_point_3
              • Custom script: call RemoveLocation (udg_temp_point)
              • Custom script: call RemoveLocation (udg_temp_point_2)
              • Custom script: call RemoveLocation (udg_temp_point_3)
            • Else - Actions
              • Custom script: call RemoveLocation (udg_temp_point_2)
              • Set EN_Current_Damage = (EN_Base_Damage + ((EN_PerLevel_Damage x (Load ((Key (Picked unit)) + 2) of (Custom value of (Picked unit)) from EN_Hashtable)) + (EN_PerCharge_Damage x (Load ((Key (Picked unit)) + 1) of (Custom value of (Picked unit)) from EN_Hashtable))))
              • Set temp_unit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • EN_Splash Equal to True
                • Then - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • EN_FriendlyFire Equal to True
                    • Then - Actions
                      • Unit - Cause temp_unit to damage circular area after 0.00 seconds of radius (Real(EN_AOE_Splash)) at temp_point, dealing (Real(EN_Current_Damage)) damage of attack type Spells and damage type Normal
                    • Else - Actions
                      • Set temp_group = (Units within (Real(EN_AOE_Splash)) of temp_point matching (((Matching unit) belongs to an enemy of (Owner of temp_unit)) Equal to True))
                      • Unit Group - Pick every unit in temp_group and do (Actions)
                        • Loop - Actions
                          • Unit - Cause temp_unit to damage (Picked unit), dealing (Real(EN_Current_Damage)) damage of attack type Spells and damage type Normal
                      • Custom script: call DestroyGroup (udg_temp_group)
                • Else - Actions
                  • Unit - Cause (Picked unit) to damage Current_unit, dealing (Real(EN_Current_Damage)) damage of attack type Spells and damage type Normal
              • Unit - Remove temp_unit from the game
              • Special Effect - Create a special effect at temp_point using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
              • Special Effect - Destroy (Last created special effect)
              • Custom script: call RemoveLocation (udg_temp_point)


Credits:

Spell Resource template map by Tinki3.
Spell concept by Dest. (Originally called Energitism)
Icon by bigapple90. Check the page here.
Model by RED BARON. Check the page here.

Additional notes:

This is the first time I'm submitting a resource :). Also this spell is somewhat old, so it's probably not as efficient as I thought it might be.
I'm not exactly sure as to clearing hashtable leaks, so if there ARE leaks that I haven't removed, give me a heads up. :D

Changelog:

26/06/10 - Fixed numerous leaks pointed out. Optimized triggers to switch off when not needed. Added Friendly_Fire editable.

07/07/10 - Optimized code a little bit more. Fixed a bug where the third charge didn't move or detonate correctly.
 

Ayanami

칼리
Reaction score
288
Just seeing through triggers quickly. Spotted some leaks, I think.

Firstly, your EN Spin trigger.

Trigger:
  • Unit - Move Current_unit instantly to ((Position of (Picked unit)) offset by 50.00 towards EN_Current_angle[(Integer A)] degrees)


Leaks. You set temp_point = (Position of (Picked unit)) yet didn't use it. But the offset leaks at well. Should be:

Trigger:
  • Actions
    • Set temp_point = (Position of (Picked unit))
    • Set temp_offset = (temp_point offset by 50.00 towards EN_Current_angle[(Integer A)] degrees)
    • Unit - Move Current_unit instantly to temp_offset
    • <Remember to remove leaks>


Now, your EN Blowing up trigger.

Trigger:
  • (Distance between (Position of (Picked unit)) and (Position of Current_unit)) Greater than or equal to 50.00


I believe this leaks.

Trigger:
  • Unit - Move (Picked unit) instantly to (temp_point offset by 50.00 towards (Angle from temp_point to temp_point_2) degrees)


Same leak as mentioned above. Offsets needs to be set as a variable and removed after using it.

Trigger:
  • Unit - Cause (Picked unit) to damage circular area after 0.00 seconds of radius (Real(EN_AOE_Splash)) at temp_point, dealing (Real(EN_Current_Damage)) damage of attack type Spells and damage type Normal


Are you trying to deal damage in an area? I suggest you set a unit group and deal damage to picked units instead. Circular area deals damage to friends and foes alike.

Well, I just read through roughly. Might have more leaks, etc.

Anyways, concept-wise, looks nice. May I suggest that you alter the skill a bit, so that point-targeted spells also trigger the orbs to explode at the targeted point?
 

Moridin

Snow Leopard
Reaction score
144
Thanks :). Yeah I need to run through this spell again and eliminate all the leaks.

I was thinking of picking units in a group and then damaging them so I can choose whether or not friendly fire is switched on (planning on making this an editable).

I was also thinking of the target point idea. Right now though, I'm still thinking of how to implement it properly....because most of the variables change depending on whether a unit or a point is targeted.

Thanks for the feedback. Will work on getting it fixed.

Edit: How do you remove offset leaks? The custom script isn't given in emjlr3's tutorial on leak removal.
 

Ayanami

칼리
Reaction score
288
Offsets are basically locations.

Trigger:
  • Custom script: RemoveLocation(udg_temp_offset)
 

Ayanami

칼리
Reaction score
288
Looks good. Except you might want to track the number of units in a unit group rather than using "Unit Group is Empty". I heard it's inefficient. Thus, you could use a integer variable to count. Set GroupInteger = GroupInteger +1 when you add a unit into the group. Then you decrease it when removed. Then you can make an integer comparison rather than "Unit Group is Empty".

Your hashtables are confusing, at least to me. I normally use Handle of a unit, similar to yours, in the parent key and stringhash for the child key.

For example:

Trigger:
  • Custom script: call SaveReal(udg_Hashtable, GetHandleId(GetTriggerUnit()), StringHash("damage"), 500.00)


But it's just all up to personal preferences. As long as your method works, it's fine :)
 

Moridin

Snow Leopard
Reaction score
144
Yeahh :p What you're doing is using a string as the second key in your hashtable. Unfortunately, because I don't know JASS or custom script (same thing technically) yet, I have to stick to integer keys. :p Which is why I have all my values stored as (Triggering unit), 1 and so on.

I've gotten used to it by now, mainly by making a mental map of a 2D array in my head that remembers where everything goes. It is confusing at a first read though, I admit :p.

Also, for the boolean "unit group is empty" innefficiency, I'd like another opinion on this. Converting it to an integer condition would add another few confusing lines of code to an already confusing to read spell. If it does indeed reduce lag, then I don't mind changing it. It should be pretty easy.

Edit: I would also like someone to comment on hashtable leaks. I'm definitely sure my hashtable leaks, but I have no idea how to solve that problem.
 

Ayanami

칼리
Reaction score
288
Wait, GUI hashtables are in the sequence of child key and parent key right? If that's so, aren't you setting all your child key to Handle Id of the caster? You're going to have a hard time flushing the values as the parent keys are all different while the child keys are all the same.
 

Moridin

Snow Leopard
Reaction score
144
StringHash("damage") = String Id (found under Handle Id)

Woops. Yeah I just saw that there right now. I really should learn how to use it then, would make hashtable a lot easier to read :p. Ty for pointing that out btw.

Wait, GUI hashtables are in the sequence of child key and parent key right? If that's so, aren't you setting all your child key to Handle Id of the caster? You're going to have a hard time flushing the values as the parent keys are all different while the child keys are all the same.
Reply With Quote

I actually don't know. This is what I was talking about in terms of leaking.

Edit: Also where do you guys get your info from on hashtables? The only tutorial I've ever seen or read on hashtables is the "Hashtables and MUI" tutorial on the hive... :S
 

hgkjfhfdsj

Active Member
Reaction score
55
This is what I was talking about in terms of leaking.
seeing that youre using child key for the caster rather than the parent, just flush the unit values (i think thats all i see)>> non-handles dont need to be flushed anyways. otherwise revamp the trigger and use string id as child.

Edit: Also where do you guys get your info from on hashtables? The only tutorial I've ever seen or read on hashtables is the "Hashtables and MUI" tutorial on the hive... :S
click me
 

Ayanami

칼리
Reaction score
288
Edit: Also where do you guys get your info from on hashtables? The only tutorial I've ever seen or read on hashtables is the "Hashtables and MUI" tutorial on the hive... :S

Well, I just happened to hear that you can use strings for keys. So I experimented and found out that StringHash("string") is the one. This site also lists all the natives for hashtable. Considering that BJ reverses the arguments for the hashtables, you ARE saving Handle Id of the caster in the child key and not the parent key. As you can see, the native function's sequence is hashtable, parent key, child key, value. So if the arguments are reversed, it becomes value, child key, parent key, hashtable. Thus, I suggest you rework the hashtable parts.
 

Moridin

Snow Leopard
Reaction score
144
Thanks for the comments. As of now, this isn't my highest priority because it works as is and I'm working on another spell, but I'll definitely optimise the hashtable when i get time.
 

Ayanami

칼리
Reaction score
288
Well, at least from now on, you know the correct positions for the child key and the parent key ;)
 

Moridin

Snow Leopard
Reaction score
144
Yeah thats true :). I've optimised my other spell's code. Also, the string keys make everything SO much easier :D.
 

Moridin

Snow Leopard
Reaction score
144
Bump. Fixed a bug where a trigger switched off too early, resulting in the third charge always failing. Optimized the code a little more.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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 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 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