• 🏆 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!

Shockwave System 1.5 Reforged

Credit to xyzier_24 for the original shockwave system which can be found here: Shockwave Carrion Swarm System (See the original for a full description).

Updated by me to use reforged features instead of excessive dummy units. See the example spells for documentation. Also includes a dummy caster library that I'm not sure who to credit for in order to make the sample spells work without excessive dummy units. One other feature I added is the ability to set the scale of special effects used by the system.

Note: If you are updating from 1.4 to 1.5 you must set SW_FXEndScale in your existing shockwave triggers (set it equal to shockwave_FXScale if you aren't using it)

  • v1.0 - Release
  • v1.2 - Shockwave spells now ignore invulnerable units (including units with locust). Also shockwave spells no longer ignore amphibious units.
  • v1.3 - Code cleanup based on review
  • V1.4 - Fixed Issue with Cliffs. Also renamed TempUnit variable to SW_TargetUnit for readability.
  • V1.5 - Added the ability to have the Shockwave visual effect change size as it travels (this was already implemented for the AOE)

Contents

Shockwave (Map)

Reviews
Wrda
Changes were made, and it's now a pretty solid GUI, flexible Shockwave System. Approved

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
For a shockwave-based system, I'd rather have it extend off of a damage event that checks for the Sonic damage type and runs the on-hit events when a given unit is affected by the shockwave. The special effect itself could be amended in Object Editor for a minimalistic approach.

Damage types are mapped here: REPO: Mapping Abilities to their Damage Types . The only consideration to ensure is that the casting unit does not have any other spells that deal Sonic damage that could confuse it.

The end result is much smaller triggers and a much lower overhead.

Such a system wouldn't work on older WarCraft 3 versions, but since you are using the new Special Effect natives anyway, it wouldn't change anything about the requirements.
 

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,864
  • Set VariableSet SW_Coordinates[SW_Max] = (SW_Point[0] offset by (0.00, 0.00))
Why does this use point with offset? You can use SW_Point[0] directly.
  • Set VariableSet SW_NextPoint[0] = (SW_Coordinates[SW_Loop] offset by (0.00, 0.00))
  • Set VariableSet SW_Coordinates[SW_Loop] = (SW_NextPoint[1] offset by (0.00, 0.00))
In Shockwave Loop too.

The (1.00 /0.03) math parts, the interval 0.03 could be stored into a variable in a map init trigger for the spell, where then you would add the periodic event to the Shockwave Loop trigger.
I wouldn't use the one line if/then/else, even though I understand why you did it. It's better to get rid of the "Do Nothing" parts.
  • Or - Any (Conditions) are true
    • Conditions
      • ((TempUnit is A flying unit) Equal to SW_AffectAir[SW_Loop]) and (SW_AffectAir[SW_Loop] Equal to True)
      • ((TempUnit is A structure) Equal to SW_AffectStructure[SW_Loop]) and (SW_AffectStructure[SW_Loop] Equal to True)
      • ((TempUnit is A ground unit) Equal to SW_AffectGround[SW_Loop]) and (SW_AffectGround[SW_Loop] Equal to True)
      • (((Unit: TempUnit's Integer Field: Targeted as ('utar')) And 2) Equal to 2) and (SW_AffectGround[SW_Loop] Equal to True)
Why are the first 3 conditions duplicated? You don't need the last condition.
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (TempUnit is invulnerable) Equal to False
      • (TempUnit belongs to an ally of (Owner of SW_Caster[SW_Loop]).) Equal to SW_AffectAlly[SW_Loop]
      • SW_AffectAlly[SW_Loop] Equal to True
      • (TempUnit is in SW_GroupDone[SW_Loop].) Equal to False
      • Or - Any (Conditions) are true
        • Conditions
          • ((TempUnit is A flying unit) Equal to SW_AffectAir[SW_Loop]) and (SW_AffectAir[SW_Loop] Equal to True)
          • ((TempUnit is A structure) Equal to SW_AffectStructure[SW_Loop]) and (SW_AffectStructure[SW_Loop] Equal to True)
          • ((TempUnit is A ground unit) Equal to SW_AffectGround[SW_Loop]) and (SW_AffectGround[SW_Loop] Equal to True)
          • (((Unit: TempUnit's Integer Field: Targeted as ('utar')) And 2) Equal to 2) and (SW_AffectGround[SW_Loop] Equal to True)
    • Then - Actions
      • If (SW_ExtraEffectTargetCheck[SW_Loop] Equal to True) then do (Trigger - Run SW_ExtraEffectTarget[SW_Loop] (checking conditions)) else do (Do nothing)
      • If (SW_OneInstance[SW_Loop] Equal to True) then do (Unit Group - Add TempUnit to SW_GroupDone[SW_Loop]) else do (Do nothing)
    • Else - Actions
  • (TempUnit belongs to an ally of (Owner of SW_Caster[SW_Loop]).) Equal to SW_AffectAlly[SW_Loop]
should be
  • (TempUnit belongs to an ally of (Owner of SW_Caster[SW_Loop]).) Equal to True
  • Set VariableSet SW_ExtraEffectCheck[SW_Max] = False
was missing in Carrion Swarm trigger, which made units get silenced when they shouldn't.

  • Set VariableSet SW_ExtraEffectCheck[SW_Max] = True
  • Set VariableSet SW_ExtraEffect[SW_Max] = Silence Wave Extra <gen>
These are causing the extra sounds when units get silenced, should be SW_ExtraEffectTarget instead.
I don't really understand much the existence of SW_ExtraEffectCheck and SW_ExtraEffect to be honest. At least the way you describe and use it. Feels like an "on period" event.

I feel like you should make an empty trigger on Shockwave folder, with all the ability variable members that the user can utilize (you won't need to delete the comments in the sample). Basically the whole Shockwave spell sample's actions (no events and shouldn't be executed at all), and the missing ones such as SW_WaveEffectLoop and SW_ExtraEffectTarget. And also should have a very short explanation that the user must always start the set up the way you do on the samples:
  • Actions
    • -------- You must follow this format for all spells, and what is similar, follows the samething --------
    • Set VariableSet SW_Max = (SW_Max + 1)
    • Set VariableSet SW_Caster[SW_Max] = (Triggering unit)
    • Set VariableSet SW_Point[0] = (Position of (Triggering unit))
    • Set VariableSet SW_Point[1] = (Target point of ability being cast)
    • Set VariableSet SW_Lvl[SW_Max] = (Level of (Ability being cast) for (Triggering unit))
Else users would have to spend some time figuring out what/how to set up properly.

SW_attachment isn't used Shockwave Cast or Shockwave Loop at all? Is it obsolete? It's only used in the samples.
You should set up some other variables before SW_ExtraEffectTarget fires (inside an if/then/else [ITE] obviously) so that the user can have more accessibility instead of trying to remember the variables used in the periodic loop. I think the caster, unit hit, damage dealt, level of ability, and maybe angle of the shockwave would be enough.

Currently, if you cast a shockwave on a lower cliff level and it continues to a higher cliff level, the effect's height is "inside" the cliff. And the reverse, the effect height will be in the air. It feels weird.

It's a promising shockwave system, with some fixes to do still.
 
  • Set VariableSet SW_Coordinates[SW_Max] = (SW_Point[0] offset by (0.00, 0.00))
Why does this use point with offset? You can use SW_Point[0] directly.
  • Set VariableSet SW_NextPoint[0] = (SW_Coordinates[SW_Loop] offset by (0.00, 0.00))
  • Set VariableSet SW_Coordinates[SW_Loop] = (SW_NextPoint[1] offset by (0.00, 0.00))
In Shockwave Loop too.
Actually this is needed because I'm instantiating a new point object in memory with the same xy values as the old one, a copy in other words, rather than having both variables point to the same point object. If you don't believe me feel free to test it yourself.
The (1.00 /0.03) math parts, the interval 0.03 could be stored into a variable in a map init trigger for the spell, where then you would add the periodic event to the Shockwave Loop trigger.
I wouldn't use the one line if/then/else, even though I understand why you did it. It's better to get rid of the "Do Nothing" parts.
Done in v1.3
  • Or - Any (Conditions) are true
    • Conditions
      • ((TempUnit is A flying unit) Equal to SW_AffectAir[SW_Loop]) and (SW_AffectAir[SW_Loop] Equal to True)
      • ((TempUnit is A structure) Equal to SW_AffectStructure[SW_Loop]) and (SW_AffectStructure[SW_Loop] Equal to True)
      • ((TempUnit is A ground unit) Equal to SW_AffectGround[SW_Loop]) and (SW_AffectGround[SW_Loop] Equal to True)
      • (((Unit: TempUnit's Integer Field: Targeted as ('utar')) And 2) Equal to 2) and (SW_AffectGround[SW_Loop] Equal to True)
Why are the first 3 conditions duplicated? You don't need the last condition.
Yes I do need the 4th condition in order to handle amphibious units. Feel free to test it yourself if you don't believe me.

  • Set VariableSet SW_ExtraEffectCheck[SW_Max] = False
was missing in Carrion Swarm trigger, which made units get silenced when they shouldn't.
Fixed
  • Set VariableSet SW_ExtraEffectCheck[SW_Max] = True
  • Set VariableSet SW_ExtraEffect[SW_Max] = Silence Wave Extra <gen>
These are causing the extra sounds when units get silenced, should be SW_ExtraEffectTarget instead.
I don't really understand much the existence of SW_ExtraEffectCheck and SW_ExtraEffect to be honest. At least the way you describe and use it. Feels like an "on period" event.
The difference is that ExtraEffect runs every period as opposed to extra effect target which runs on each unit that is hit.

SW_attachment isn't used Shockwave Cast or Shockwave Loop at all? Is it obsolete? It's only used in the samples.
Removed it in 1.3
 

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,864
Actually this is needed because I'm instantiating a new point object in memory with the same xy values as the old one, a copy in other words, rather than having both variables point to the same point object. If you don't believe me feel free to test it yourself.
You're absolutely right.
Yes I do need the 4th condition in order to handle amphibious units. Feel free to test it yourself if you don't believe me.
I believe you and I am aware of it. I meant the the first 3 conditions of the "Or - Any (Conditions)" block.
Essentially should become
  • Or - Any (Conditions) are true
    • Conditions
      • ((TempUnit is A flying unit) Equal to SW_AffectAir[SW_Loop] Equal to True
      • ((TempUnit is A structure) Equal to SW_AffectStructure[SW_Loop] Equal to True
      • ((TempUnit is A ground unit) Equal to SW_AffectGround[SW_Loop] Equal to True
      • (((Unit: TempUnit's Integer Field: Targeted as ('utar')) And 2) Equal to 2) and (SW_AffectGround[SW_Loop] Equal to True)
I shall quote a part of the review that weren't still addressed:
You should set up some other variables before SW_ExtraEffectTarget fires (inside an if/then/else [ITE] obviously) so that the user can have more accessibility instead of trying to remember the variables used in the periodic loop. I think the caster, unit hit, damage dealt, level of ability, and maybe angle of the shockwave would be enough.
By this I mean you create some new variables, and set before the SW_ExtraEffectTarget[SW_Loop] trigger is run, so that the user can use them in that same trigger, instead of using TempUnit for the unit hit, SW_Caster[SW_Loop] for the caster for example. Usually it isn't a good idea to make the user go look through the triggers to figure out which variables are accessible without breaking them.

Currently, if you cast a shockwave on a lower cliff level and it continues to a higher cliff level, the effect's height is "inside" the cliff. And the reverse, the effect height will be in the air. It feels weird.
If you add cliffs to the test map, you'll experience this. Should be easily solvable by having one permanent location, moving it to the next x, y location, then using GetLocationZ(udg_LocVar) to get the Z (height) value, and use it on special effect.

This last one is more important.
 

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,864
This is the only thing that keeps me out of approving the system:
Currently, if you cast a shockwave on a lower cliff level and it continues to a higher cliff level, the effect's height is "inside" the cliff. And the reverse, the effect height will be in the air. It feels weird.

If you add cliffs to the test map, you'll experience this. Should be easily solvable by having one permanent location, moving it to the next x, y location, then using GetLocationZ(udg_LocVar) to get the Z (height) value, and use it on special effect.
If you don't understand what this method is, look up here:

I still find the way the first 3 conditions of the "or any conditions" block are checked in a redudant manner, specially talking about these:
  • Or - Any (Conditions) are true
    • Conditions
      • ((TempUnit is A flying unit) Equal to SW_AffectAir[SW_Loop]) and (SW_AffectAir[SW_Loop] Equal to True)
      • ((TempUnit is A structure) Equal to SW_AffectStructure[SW_Loop]) and (SW_AffectStructure[SW_Loop] Equal to True)
      • ((TempUnit is A ground unit) Equal to SW_AffectGround[SW_Loop]) and (SW_AffectGround[SW_Loop] Equal to True)
I'm looking forward to seeing the first change, as it is more important than the rest.
 
Top