Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
mckill2009 - Handle ID
Magtheridon The Snail - Constantly calling same function
Lord Adiktuz - Damage formula
Garfield The Lazy Cat - SetUnit boundary limit
Tranquil - Thunder Model
SPELL DESCRIPTION
Summons a heavy thunder towards the targeted points dealing damage on first impact. Small fragments will be created later on due to the powerful strike. Any units in contact with the fragment, will receive the same amount of power value of the first thunder. Fragment holds the same quality as the thunder from all aspects such as damage and AOE. Also, if the unit dies (without in contact of any enemy unit around), it also sparks out but with reducing AOE as half of the original AOE.
[Level 1] - 300 damage upon impact covering 600 AOE. 3 fragments of lightning are created, each lasts 1 second.
[Level 2] - 350 damage upon impact covering 700 AOE. 4 fragments of lightning are created, each lasts 2 second.
[Level 3] - 400 damage upon impact covering 800 AOE. 5 fragments of lightning are created, each lasts 3 second.
[Level 4] - 450 damage upon impact covering 900 AOE. 6 fragments of lightning are created, each lasts 4 second.
TRIGGERS
Spell Setup
Events
Time - Elapsed game time is 0.00 seconds
Conditions
Actions
-------- This determines the "curvature" of the fragment travels. The smaller the value , the curver it gets per move interval --------
-------- Try to play with this value, and you'll find something amazing :) --------
Set Curvature = 1.00
-------- Creating hashtable for MUI trigger --------
Hashtable - Create a hashtable
-------- Setting it into a variable for easier understanding --------
Set Hashtable = (Last created hashtable)
-------- There are 2 methods to do a "Damage Formula" --------
-------- 1. Direct Multiplication Of Damage = X * (Level of Ability) --------
-------- 2. Plus and Multiplication Damage = 250 + (50 * Level of Ability) --------
-------- In this spell, I used the 2nd method because it is more edit-friendly --------
-------- If you want to have the first method, just set all value of a variable that starts with "Base" to 0 --------
-------- Base means the first position of the formula --------
-------- This arguement is brought to you by Adiktuz :) --------
Set BaseAOE = 500.00
Set BaseDamage = 250.00
-------- All variable that starts with "Multiply" indicates that it's the second position of the formula --------
-------- Eg: 250 + *This is what I meant by second position* x (Level of Ability) --------
Set MultiplyAOE = 100.00
Set MultiplyDamage = 50.00
Set MultiplyFragmentDuration = 1.00
-------- [1] is for the fragment to appear for the first cast --------
Set FragmentOffset[1] = 200.00
-------- [2] is for the fragment's speed --------
Set FragmentOffset[2] = 15.00
-------- This value is the detection range of enemy units near the fragment --------
Set UnitInRange = 150.00
-------- This is the Start Value of a Loop (To create multiple fragments, will be used on "Cast" trigger) --------
Set InitialValue = 1
-------- This is the formula for Polygon which is the (n - 2) * 180, but in this case, I'll be using full circle which is 360 --------
Set PolygonFormula[1] = 360.00
-------- [1] is for SFX to damage the enemy unit with Moonsoon Lightning --------
Set SFX_Path[1] = Abilities\Spells\Other\Monsoon\MonsoonBoltTarget.mdl
-------- [2] is for SFX that is created at the position of the fragment --------
-------- This is because the fragment has model or whatsoever, so this SFX can indicate its current position --------
Set SFX_Path[2] = Abilities\Spells\Orc\LightningShield\LightningShieldBuff.mdl
-------- Ability is set into a variable for proper loading (Maker said it) --------
Set AbilityName = Treacherous Thunder[/hidden]
Cast
Events
Unit - A unit Starts the effect of an ability
Conditions
(Ability being cast) Equal to AbilityName
Actions
-------- Setting variables --------
-------- This is to prevent a function being called so many times --------
-------- Credits to Magtheridon the "Snail-like Avatar" :p --------
Set Unit[1] = (Triggering unit)
Set Point[1] = (Target point of ability being cast)
Set PlayerOwning = (Triggering player)
Set AbilityLevel = (Real((Level of Treacherous Thunder for Unit[1])))
-------- This is the AOE of the first thunder strike / AOE upon impact with enemy units --------
Set AOE[1] = (BaseAOE + (MultiplyAOE x AbilityLevel))
-------- This is the AOE if the lightning doesn't contact with any enemy units and die on its own --------
-------- The AOE is however, has been reduced to half --------
-------- This is because the lightning creates more power if it contact with units rather than die on its own --------
Set AOE[2] = (AOE[1] / 2.00)
-------- Formulas --------
Set Damage = (BaseDamage + (MultiplyDamage x AbilityLevel))
-------- The duration of the fragment varies with level --------
Set FragmentDuration = (BaseFragmentDuration + (AbilityLevel x MultiplyFragmentDuration))
-------- This is the (n - 2) * 180 method (Polygon Formula) but I used 360 / (n + 2) --------
-------- n = number of sides of the polygon-shape --------
-------- [0] is the (n + 2) , where n = AbilityLevel --------
-------- Level 1 = Triagon --------
-------- Level 2 = Quadrilateral --------
-------- Level 3 = Pentagon --------
-------- Level 4 = Hexagon --------
Set PolygonFormula[0] = (2.00 + AbilityLevel)
-------- 360 / (n + 2) formula --------
Set PolygonFormula[2] = (PolygonFormula[1] / PolygonFormula[0])
-------- Some SFX created when thunder strikes the ground --------
Special Effect - Create a special effect at Point[1] using Great Lightning.mdx
Special Effect - Destroy (Last created special effect)
-------- Picks all enemy units and damage them accordingly to the earlier setup variable --------
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within AOE[1] of Point[1] matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) belongs to an enemy of PlayerOwning) Equal to True) and (((Triggering unit) is Magic Immune) Equal to False)))) and do (Actions)
Loop - Actions
Set Unit[2] = (Picked unit)
Unit - Cause Unit[1] to damage Unit[2], dealing Damage damage of attack type Spells and damage type Normal
Special Effect - Create a special effect attached to the origin of Unit[2] using SFX_Path[1]
Special Effect - Destroy (Last created special effect)
-------- This is where it determines the number of fragment created --------
For each (Integer A) from InitialValue to (Integer(PolygonFormula[0])), do (Actions)
Loop - Actions
-------- Fragment created each on its own respective angle --------
Set PolygonFormula[3] = (PolygonFormula[2] x (Real((Integer A))))
-------- Fragment position to be created --------
-------- NOTE: FragmentOffset[1] MUST BE GREATER THAN UnitInRange for this spell to properly calculates it --------
-------- Imagine if the fragment is created near the targeted point and the targeted poin contains enemy unit, what will happen? --------
-------- Yes, a direct all hit from the fragment, instantly --------
Set Point[2] = (Point[1] offset by FragmentOffset[1] towards PolygonFormula[3] degrees)
-------- A newborn baby, I mean baby thunder fragment is borned --------
Unit - Create 1 Dummy Lightning (fragment) for PlayerOwning at Point[2] facing Default building facing degrees
-------- Setting it into a variable and save it in hashtable (for loading its data and get a MUI trigger) --------
-------- Save the Handle ID with Integer variable for efficiency --------
-------- This method is introduced to me by mckill :) keep up the good work buddy ! --------
Set Unit[2] = (Last created unit)
Set HandleID = (Key (Last created unit))
Set Point[3] = (Position of Unit[2])
Set Angles[1] = (Angle from Point[1] to Point[3])
Hashtable - Save Handle OfUnit[2] as (Key Fragment) of HandleID in Hashtable
Hashtable - Save Damage as (Key Damage) of HandleID in Hashtable
-------- [1] is the main AOE, this will occur if the fragment succeed contacting any enemy units --------
Hashtable - Save AOE[1] as (Key AOE) of HandleID in Hashtable
-------- [2] is the half AOE, where the fragment fails to contact enemy unit --------
Hashtable - Save AOE[2] as (Key AOE[2]) of HandleID in Hashtable
Hashtable - Save Handle OfPlayerOwning as (Key PlayerOwning) of HandleID in Hashtable
-------- This is where the the fragment gets a bit cracky and begins to move in a swirl pattern --------
-------- This will make the lightning looks less identified as "Polygon-shaped movement" because it will move swirl and will disturb the orderly pattern --------
Unit - Make Unit[2] face Angles[1] over Curvature seconds
-------- Duration of the fragment --------
Unit - Add a FragmentDuration second Generic expiration timer to Unit[2]
-------- Adding it to a Unit Group for movement --------
Unit Group - Add Unit[2] to LightningFragmentGroup
-------- DON'T FORGET LEAKS ! --------
Custom script: call RemoveLocation(udg_Point[2])
Custom script: call RemoveLocation(udg_Point[3])
Custom script: call RemoveLocation(udg_Point[1])
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Loop <gen> is on) Equal to False
Then - Actions
Trigger - Turn on Loop <gen>
Else - Actions
Loop
Events
Time - Every 0.03 seconds of game time
Conditions
Actions
-------- This is where the fragment activities going on, movement, calculating enemy units in range, die = boom, etc --------
-------- boom = POW! (I'm bad at explaining things, lol) --------
Unit Group - Pick every unit in LightningFragmentGroup and do (Actions)
Loop - Actions
-------- LOADING DATA --------
Set HandleID = (Key (Picked unit))
Set Unit[1] = (Picked unit)
Set Angles[1] = (Facing of Unit[1])
Set Point[1] = (Position of Unit[1])
Set Point[2] = (Point[1] offset by FragmentOffset[2] towards Angles[1] degrees)
Set Damage = (Load (Key Damage) of HandleID from Hashtable)
Set PlayerOwning = (Load (Key PlayerOwning) of HandleID in Hashtable)
-------- If the unit is still alive, move it, if it doesn't then boom it (with half AOE) --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Unit[1] is alive) Equal to True
Then - Actions
-------- This checks whether the fragment is still on the map or not --------
-------- By using the SetUnitX , SetUnitY function, the unit tends to get pass the impassable terrain such as the "black area" at the edge of the map --------
-------- When the fragment goes too far to the edge of the map, this will make the game fatal error --------
-------- That is why I designed this condition to check --------
-------- If the unit is in playable map area, proceed, if it not, KILL `EM ALL --------
-------- Credits goes to the lazy cat, Garfield --------
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
((Playable map area) contains Point[1]) Equal to True
Then - Actions
-------- This is to keep track the movement of the fragment (dummy has no model) --------
Special Effect - Create a special effect at Point[1] using SFX_Path[2]
Special Effect - Destroy (Last created special effect)
-------- Basically you can do 2 method, either this or Unit - Move unit (Instantly) --------
-------- But this one more efficient (JASS-thingie, FFFFFFF haha) --------
-------- This is where the fragment calculates once every 0.03 second --------
-------- Calculate what ? Yes, calculating enemy units in range --------
-------- If it detects any, instantly kill the fragment and create a better spark (AOE) --------
Unit Group - Pick every unit in (Units within UnitInRange of Point[2]) and do (Actions)
Loop - Actions
Set Unit[2] = (Picked unit)
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Unit[2] is alive) Equal to True
(Unit[2] belongs to an enemy of PlayerOwning) Equal to True
Then - Actions
-------- This is the full AOE load --------
Set AOE[1] = (Load (Key AOE) of HandleID from Hashtable)
Unit - Kill Unit[1]
Special Effect - Create a special effect at Point[1] using Great Lightning.mdx
Special Effect - Destroy (Last created special effect)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within AOE[1] of Point[1] matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) belongs to an enemy of PlayerOwning) Equal to True) and (((Matching unit) is Magic Immune) Equal to False)))) and do (Actions)
Loop - Actions
Set Unit[2] = (Picked unit)
Unit - Cause Unit[1] to damage Unit[2], dealing Damage damage of attack type Spells and damage type Normal
Special Effect - Create a special effect attached to the origin of Unit[2] using SFX_Path[1]
Special Effect - Destroy (Last created special effect)
-------- After using it, clear the data in the hashtable and remove the unit from the group (cleaning data) --------
-------- If there is no more fragment in the map, instanly turn off this trigger (efficiency) --------
Hashtable - Clear all child hashtables of child HandleID in Hashtable
Unit Group - Remove Unit[1] from LightningFragmentGroup
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Number of units in LightningFragmentGroup) Equal to 0
Then - Actions
Trigger - Turn off (This trigger)
Else - Actions
Else - Actions
Else - Actions
Else - Actions
-------- This part of trigger where the fragment die on its own (duration limit) --------
-------- This is the half AOE load --------
Set AOE[2] = (Load (Key AOE[2]) of HandleID from Hashtable)
-------- Action above shows the same exact calculation of the full load AOE --------
Special Effect - Create a special effect at Point[1] using Great Lightning.mdx
Special Effect - Destroy (Last created special effect)
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within AOE[2] of Point[1] matching ((((Matching unit) is alive) Equal to True) and ((((Matching unit) belongs to an enemy of PlayerOwning) Equal to True) and (((Matching unit) is Magic Immune) Equal to False)))) and do (Actions)
Loop - Actions
Set Unit[3] = (Picked unit)
Unit - Cause Unit[1] to damage Unit[3], dealing Damage damage of attack type Spells and damage type Normal
Special Effect - Create a special effect attached to the origin of Unit[3] using SFX_Path[1]
Special Effect - Destroy (Last created special effect)
Hashtable - Clear all child hashtables of child HandleID in Hashtable
Unit Group - Remove Unit[1] from LightningFragmentGroup
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Number of units in LightningFragmentGroup) Equal to 0
18:40, 2nd Jun 2011
Maker:
You don't have to set point[3] int the cast trigger's loop. Use point[2] instead. It's basically the same point.
Unnecessary line:Hashtable - Save Handle OfUnit[2] as (Key Fragment) of HandleID in Hashtable
You could...
18:40, 2nd Jun 2011
Maker:
You don't have to set point[3] int the cast trigger's loop. Use point[2] instead. It's basically the same point.
Unnecessary line:
Hashtable - Save Handle OfUnit[2] as (Key Fragment) of HandleID in Hashtable
You could add some kind of maximum damage or maximum target limit.
You could use non-array variables if you only need one or few indexes but that's not a big issue.
Change the elapsed time to map initialization.
Although, I've got question on how to improve "Effects" ?
If you're reviewing something, you should include the "What's wrong" and "How to improve?", and you lack the "How to improve?"
Hope you tell me what to improve !
Thanks once again for the feedback, +rep
oh yeah, I always get confused between those models... anyway, put him on the credits... or better yet, just link the lightning model and remove it from the map...
For the arrays, its not about the file size, its about the performance... as arrays work slower than non-arrays... and since you only use about 1-3 indexes, its always better to just use diff variables...
arrays are only recommended if you have the chance of using a lot of the indexes...
ahh sure
*you dont need to use custom lighting effects to get some cool lighting effects
Mine example:
Spell Setup
Set SFX_Path[1]=Abilities\Spells\Orc\Purge\PurgeBuffTarget.mdl
Set SFX_Path[2]=Abilities\Weapons\FarseerMissile\FarseerMissile.mdl
Cast
Special Effect - Create a Special Effect at point [1] using Abilities\Spells\Undead\DeathPact\DeathPactTarget.mdl
Loop
Special Effect - Create a Special Effect at point [1] using Abilities\Spells\Human\Thunderclap\ThunderClapCaster.mdl
and Dummy Art - Model File Abilities\Spells\Orc\Purge\PurgeBuffTarget.mdl
and Spell Art - Caster Abilities\Weapons\Bolt\BoltImpact.mdl Art - Animation name - Spell Art - Caster Attachment Point 1 - Weapon
Art - Caster Attachment - 1
and when you use any custom model give credits to model creator
About your lighting effects:
That is mine own opinion, i'm just here to help
thats it!
Well, for me, I think that's just your personal opinion about the "Effect A (my effect) < Effect B (your effect)"
How can you be so sure that your SFX is more beautiful/appropriate than mine ?
Beauty cannot be measured.
EDIT:
Misunderstood the point lol
What I understand is, you ask me to use default effects rather than using custom ones, is it ?
Good to see you working with your coding skills still I have to point out a few flaws that the others seemed to miss.
-Should be map ini, it's not a multiboard
Time - Elapsed game time is 0.00 seconds
-All variables should be prefixed.
-Base variables and multiply variables are useless, just have one variable with the whole formula instead of wasting space on useless variables (yes they are useless as you can just have one instead of two, saving space (even if it's around a few bytes))
-These should be in some kind of formula like in the cast trigger
-------- [1] is for the fragment to appear for the first cast --------
Set FragmentOffset[1] = 200.00
-------- [2] is for the fragment's speed --------
Set FragmentOffset[2] = 15.00
-Applies with the same argument as above.
Set UnitInRange = 150.00
-SFX variables should be two non-arrayed variables instead of one arrayed as you are only using two array slots of 8192. Arrayed variables takes more space than two normal string variables.
-Basic I found out now in the cast trigger that you have loads of these arrayed variables. Make each of them non-arrayed and make more of the non-arrayed (yet as I said above not to have multiple variables, it doesn't apply to this as these are arrayed and you don't use enough index slots to make it worth it).
-Integer A should be switched into a custom integer variable, preferably prefixed.
-The Loop seems fine, just the setunitx/y calls are disturbing me for some reason. You're moving them to a point which you already called polar offset. And then you call GetLocX/Y to get their coordinates.
So as I'm lazy to explainit all, I'll keep it simple. Polar Offset BJ looks liek this:
JASS:
function PolarProjectionBJ takes location source, real dist, real angle returns location
local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
return Location(x, y)
endfunction
These points are those you are using:
Set Point[1] = (Position of Unit[1])
Set Point[2] = (Point[1] offset by FragmentOffset[2] towards Angles[1] degrees)
WHY DON'T ANYONE SEE THAT I CREDITED THE MODEL IN THE MA---....
Oh, on the first post ?
Will... Fix... That... (...and I was thinking that all people visit this spell, should download them, sorry for false thought) LOL
Haha I put the lightning model credit IN the test map loading screen
As I said it, I'm thinking that all people visit here and will surely to download my test map and test it themselves
I should be more specific about credits (fixed first post)
Well baassee, you should change your signature, from Marc to me, HAHA
hmmm... what can I say... this spell is... treacherous... haha...
anyway, nice idea there.
I only download test maps if I really wanted to test them out (either they're good or just want to experience the reported bugs), or if I needed the spell... but most likely, I don't download spells, only systems...
And I was thinking that I've arrived to the stage of "using many variable for same purpose"
Well, not gonna change the version for this spell, maybe it's for the next spell
I did.
Well, for me, I think that's just your personal opinion about the "Effect A (my effect) < Effect B (your effect)"
How can you be so sure that your SFX is more beautiful/appropriate than mine ?
Beauty cannot be measured.
EDIT:
Misunderstood the point lol
What I understand is, you ask me to use default effects rather than using custom ones, is it ?
its more of I don't have the luxury to download nice spells right now, as I'm nearing the limit for my HDD, I'm trying to reserve the spaces for icons and models and really needed systems for my map (and also reserving the space for my map, as I always enable JNGPs auto-back up so every time I hit the save-button, JNGP creates backups of the map)...
Custom scripting ?
That's more of a JASS... noooooo~ haha
How to load the data to my loop trigger ?
Cast Trigger (save data using that custom script) -> Loop Trigger (load data, how?)
Also, does that custom script only limited to (Last created unit) function ?
How about (Triggering unit) or other ?
bj_GetTriggerUnit ?
About variable count, well I think that using array is more efficient, guess it's using more variable works more efficient, lol
Apparently, I made 2 people made their day today by posting this spell by having a "little" discussion
Custom scripting ?
That's more of a JASS... noooooo~ haha
How to load the data to my loop trigger ?
Cast Trigger (save data using that custom script) -> Loop Trigger (load data, how?)
Also, does that custom script only limited to (Last created unit) function ?
How about (Triggering unit) or other ?
bj_GetTriggerUnit ?
It's an variable used by the CreateUnit BJs that exists in GUI. CreateUnit native itself doesn't set the bjvariable into the new unit while the BJs do.
It doesn't seem to be symmetric because it "curves" from the normal angle/shape
If you delete the Action "Unit - Make Unit Face Angle", you can actually see the symmetric shape formed on the ground
It forms a polygon-based shape starting with Triangle , Square , Pentagon , Hexagon , and so on
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.