• 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!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Electric Rend

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
"Launches blades of electricity that damage enemies they impact. The blades travel a fixed distance from the caster before changing direction randomly and traveling a random distance Blades that travel too far will choose an angle that sends closer them to their initial bounce point. Each enemy can be hit once per direction change."

A simple spell I made inspired by Heat Engine Mario's final smash shown in this video:

See triggers for import instructions and credits

Edit: I included the previous version where the blades seek enemies for those who prefer it
Contents

Electric Rend (Map)

Electric Rend (Map)

Reviews
Antares
The indentation is wild once again. 🫠 You're not using the UnitDead and DoesUnitExist functions. Would be nice if you can dissolve that library and simply put a note to make sure the UnitAlive function is defined. Similarly, I'm no fan of these three...
Level 45
Joined
Feb 27, 2007
Messages
5,578
If you built some sort of angle bias function into this I think it would be both more visually appealing and functionally useful. Depending on random walks for random directions is kind of boring to me (as a player) since whether I succeed isn't dependent on using it skillfully but rather just RNG luck. But say you restrict the possible random angles in some intelligent way to make the waves generally travel approximately in the direction of the cast or towards a specific type of target. I immediately think of 5.5 ways:
  1. Save the original angle between caster and cast point. When randomizing new angles, reject any that are within a sector directly opposite the original cast angle. Vary the width of this sector (in degrees) to see what works best and choose that. 15°, 30°, 50°, 90°, 120°? When a rejected angle is found just randomize new ones until you don't reject it.

  2. Only randomize a new angle within a (relatively) small sector around the current angle. Try different angular widths as before.

  3. Apply tracking towards targets instead of any specific angle rejection. You could compute a new random angle with no bias and then take some sort of weighted average between that angle and the angle towards, say, the closest enemy unit. Or the closest building. Or towards the caster or whatever else; pick different types of targets and see about the behavior.

  4. Give the angles a fixed angular increment in a specific random direction every time they 'end' their current travel. This would give it a curved shape in a particular direction depending on what specifically is chosen to be randomized, so specifically restricting that randomness to only some of the projectiles (to give the others consistency) would probably be good.

  5. Scale the distance a projectile can travel inversely with how far the random angle is from the original cast angle, such that projectiles will travel large distances close to the angle and only short distances approximately opposite it.
My 'half' way is to apply 1 or 2 to an angle chosen by some nearby phenomena like a unit or building or tree or spellcaster or <whatever>. So instead of a static base angle the projectiles react to these phenomena, if randomly and only vaguely.
 
If you built some sort of angle bias function into this I think it would be both more visually appealing and functionally useful. Depending on random walks for random directions is kind of boring to me (as a player) since whether I succeed isn't dependent on using it skillfully but rather just RNG luck. But say you restrict the possible random angles in some intelligent way to make the waves generally travel approximately in the direction of the cast or towards a specific type of target. I immediately think of 5.5 ways:
  1. Save the original angle between caster and cast point. When randomizing new angles, reject any that are within a sector directly opposite the original cast angle. Vary the width of this sector (in degrees) to see what works best and choose that. 15°, 30°, 50°, 90°, 120°? When a rejected angle is found just randomize new ones until you don't reject it.

  2. Only randomize a new angle within a (relatively) small sector around the current angle. Try different angular widths as before.

  3. Apply tracking towards targets instead of any specific angle rejection. You could compute a new random angle with no bias and then take some sort of weighted average between that angle and the angle towards, say, the closest enemy unit. Or the closest building. Or towards the caster or whatever else; pick different types of targets and see about the behavior.

  4. Give the angles a fixed angular increment in a specific random direction every time they 'end' their current travel. This would give it a curved shape in a particular direction depending on what specifically is chosen to be randomized, so specifically restricting that randomness to only some of the projectiles (to give the others consistency) would probably be good.

  5. Scale the distance a projectile can travel inversely with how far the random angle is from the original cast angle, such that projectiles will travel large distances close to the angle and only short distances approximately opposite it.
My 'half' way is to apply 1 or 2 to an angle chosen by some nearby phenomena like a unit or building or tree or spellcaster or <whatever>. So instead of a static base angle the projectiles react to these phenomena, if randomly and only vaguely.
I agree that its a bit too random. My original plan was to have the projectiles bounce around without leaving a circle of customizable size and when they hit the edges of the circle they bounce towards the center but after what happened here Unit Face Mouse System I doubt I know the math for that.

After reading this I have an idea for how I can update this though

edit: Moderators please wait to review until I've done the update
 
Last edited:
Level 45
Joined
Feb 27, 2007
Messages
5,578
Seeking hostile units does seem much more thematic for electric ability; I think that's a great improvement. I personally don't like how far away they can ricochet like your video shows but that's a configuration thing that ultimately doesn't matter. The only other thing that comes to mind is that it's possible for all 3 waves to seek toward the same enemy at any given time. It would be unlikely but it is possible. Considering they definitively come from different angles because the initial launch ARC exists, this probably doesn't matter either.
 
The indentation is wild once again. 🫠

You're not using the UnitDead and DoesUnitExist functions. Would be nice if you can dissolve that library and simply put a note to make sure the UnitAlive function is defined. Similarly, I'm no fan of these three line libraries and I would incorporate them as private function into your Electric Rend. There's really no issue with having 6 lines of code more than necessary and it just makes the importing easier.

JASS:
if GetUnitTypeId(u)!=0 then
This could be simplified to:
JASS:
if u != null then

The math behind coding it in a way that it reflects back when it hits the circle is not trivial, so I wouldn't recommend that. But an easier implementation would be force the missile to choose an angle that is moving closer to the origin if it is further away than a certain threshold.
JASS:
local real newAngle = ModuloReal(Atan2(origin.y - missile.y, origin.x - missile.x) + bj_DEGTORAD*GetRandomReal(-60,60), 2*bj_PI)
The fact that the missiles right now tend to move like a Chain Lightning doesn't really evoke the flair of the ability you linked in that video for me.

Other than that, works well.

Simple
 
The indentation is wild once again. 🫠

You're not using the UnitDead and DoesUnitExist functions. Would be nice if you can dissolve that library and simply put a note to make sure the UnitAlive function is defined. Similarly, I'm no fan of these three line libraries and I would incorporate them as private function into your Electric Rend. There's really no issue with having 6 lines of code more than necessary and it just makes the importing easier.

JASS:
if GetUnitTypeId(u)!=0 then
This could be simplified to:
JASS:
if u != null then

The math behind coding it in a way that it reflects back when it hits the circle is not trivial, so I wouldn't recommend that. But an easier implementation would be force the missile to choose an angle that is moving closer to the origin if it is further away than a certain threshold.
JASS:
local real newAngle = ModuloReal(Atan2(origin.y - missile.y, origin.x - missile.x) + bj_DEGTORAD*GetRandomReal(-60,60), 2*bj_PI)
The fact that the missiles right now tend to move like a Chain Lightning doesn't really evoke the flair of the ability you linked in that video for me.

Other than that, works well.

Simple
Thanks for the math hint. I'll add updating this to my todo list.
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
The math behind coding it in a way that it reflects back when it hits the circle is not trivial
A proper angle-of-incidence interaction would be somewhat difficult because of the curved wall, but ultimately it's just one transformation. Wanting to go always towards the center (as they described) is super easy because you don't need to compute the output angle as if it reflected. Determining 'when' to bounce is as simple as measuring distance or duration traveled if the bounding circle is centered on their origin point, no matter the initial angles.
 
Last edited:
The indentation is wild once again. 🫠

You're not using the UnitDead and DoesUnitExist functions. Would be nice if you can dissolve that library and simply put a note to make sure the UnitAlive function is defined. Similarly, I'm no fan of these three line libraries and I would incorporate them as private function into your Electric Rend. There's really no issue with having 6 lines of code more than necessary and it just makes the importing easier.

JASS:
if GetUnitTypeId(u)!=0 then
This could be simplified to:
JASS:
if u != null then

The math behind coding it in a way that it reflects back when it hits the circle is not trivial, so I wouldn't recommend that. But an easier implementation would be force the missile to choose an angle that is moving closer to the origin if it is further away than a certain threshold.
JASS:
local real newAngle = ModuloReal(Atan2(origin.y - missile.y, origin.x - missile.x) + bj_DEGTORAD*GetRandomReal(-60,60), 2*bj_PI)
The fact that the missiles right now tend to move like a Chain Lightning doesn't really evoke the flair of the ability you linked in that video for me.

Other than that, works well.

Simple
JASS:
        method onFinish takes nothing returns boolean
        local real distance
        local real tx
        local real ty
        local real angle
        if bounces > 0 then
            set bounces = bounces - 1
            set distance = GetRandomReal(MIN_DISTANCE,MAX_DISTANCE)
            if DistanceBetweenPointsReal(x,y,originx,originy) > LEASH_DISTANCE then
                set angle = ModuloReal(Atan2(originy - y, originx - x) + bj_DEGTORAD*GetRandomReal(-60,60), 2*bj_PI)
            else
                set angle = GetRandomReal(0.,360.)
            endif
            set tx = x + distance * Cos(angle * bj_DEGTORAD)
                    set ty = y + distance * Sin(angle * bj_DEGTORAD)
            call flushAll()
            call deflect(tx,ty,z)
            return false
        endif
        return true
        endmethod

Am I using your formula right? I tried this and the projectiles don't change direction
 
Top