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

Help With an MUI Chain Spell

Status
Not open for further replies.
Level 2
Joined
Jul 28, 2009
Messages
14
So I have been trying to make an MUI Chain Spell that causes a small Thunder Clap on each unit hit, and it'll work everytime after the first 2 casts, but I want to get it to work on every cast.
The very first cast absolutely nothing happens
The second cast it hits one target and doesn't jump
My triggers are:

Concussive Thunder (Init)
  • Concussive Thunder
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Concussive Thunder
    • Actions
      • If (CTCastNumber Equal to 0) then do (Trigger - Turn on Concussive Thunder Loop <gen>) else do (Do nothing)
      • Set CTCastNumber = (CTCastNumber + 1)
      • Set CTSwitch = (CTSwitch + 1)
      • Set CTJumps[CTCastNumber] = 3
      • Set TempUnit = (Casting unit)
      • Set CTTargTest[TempInteger] = (Target unit of ability being cast)
      • Set TempTarget = (Target unit of ability being cast)
      • Set CTPlayer[CTCastNumber] = (Owner of TempUnit)
      • Set CTDamage[CTCastNumber] = (40.00 + (45.00 x (Real((Level of (Ability being cast) for TempUnit)))))
      • Custom script: set udg_TempUnit = null
Concussive Thunder Loop
  • Concussive Thunder Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer TempInteger) from 1 to CTCastNumber, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CTJumps[TempInteger] Greater than 0
              • (CTTargTest[TempInteger] has buff Concussive Thunder ) Equal to True
            • Then - Actions
              • Set TempPoint = (Position of CTTargTest[TempInteger])
              • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
              • Set Dummy = (Last created unit)
              • Unit - Add Concussive Thunder (Dummy Buff Spell) to Dummy
              • Unit - Order Dummy to Human Mountain King - Thunder Clap
              • Unit - Add a 1.00 second Generic expiration timer to Dummy
              • Unit - Cause Dummy to damage CTTargTest[TempInteger], dealing CTDamage[TempInteger] damage of attack type Spells and damage type Unknown
              • Floating Text - Create floating text that reads (- + (String((Integer(CTDamage[TempInteger]))))) above CTTargTest[TempInteger] with Z offset 0.00, using font size 9.00, color (49.41%, 75.94%, 94.51%), and 0.00% transparency
              • Set TempText = (Last created floating text)
              • Floating Text - Change TempText: Disable permanence
              • Floating Text - Set the velocity of TempText to 50.00 towards 60.00 degrees
              • Floating Text - Change the lifespan of TempText to 5.00 seconds
              • Floating Text - Change the fading age of TempText to 4.00 seconds
              • Custom script: set udg_TempText = null
              • Custom script: set udg_Dummy = null
              • Special Effect - Create a special effect at TempPoint using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
              • Special Effect - Destroy (Last created special effect)
              • Set TempGroup = (Units within 312.00 of TempPoint matching (((Matching unit) belongs to an ally of CTPlayer[TempInteger]) Equal to False))
              • Unit Group - Pick every unit in TempGroup and do (Actions)
                • Loop - Actions
                  • Set TempUnit = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Or - Any (Conditions) are true
                        • Conditions
                          • (TempUnit is A structure) Equal to True
                          • (TempUnit is dead) Equal to True
                          • (TempUnit is Mechanical) Equal to True
                          • (TempUnit has buff Concussive Thunder ) Equal to True
                    • Then - Actions
                      • Unit Group - Remove TempUnit from TempGroup
                    • Else - Actions
                  • Custom script: set udg_TempUnit = null
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in TempGroup) Greater than 0
                • Then - Actions
                  • Set CTDamage[TempInteger] = (CTDamage[TempInteger] - (CTDamage[TempInteger] x 0.10))
                  • Set TempTarget = (Random unit from TempGroup)
                  • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
                  • Set Dummy = (Last created unit)
                  • Unit - Add Concussive Thunder (Dummy Ability) to Dummy
                  • Unit - Order Dummy to Neutral - Firebolt TempTarget
                  • Unit - Add a 1.00 second Generic expiration timer to Dummy
                  • Custom script: set udg_Dummy = null
                  • Custom script: set udg_CTTargTest[udg_TempInteger] = null
                  • Set CTTargTest[TempInteger] = TempTarget
                  • Custom script: set udg_TempTarget = null
                  • Custom script: set udg_Dummy = null
                  • Set CTJumps[TempInteger] = (CTJumps[TempInteger] - 1)
                • Else - Actions
                  • Set CTJumps[TempInteger] = 0
                  • Custom script: set udg_CTTargTest[udg_TempInteger] = null
              • Unit Group - Remove all units from TempGroup
              • Custom script: call RemoveLocation(udg_TempPoint)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CTJumps[TempInteger] Less than or equal to 0
                • Then - Actions
                  • Wait until ((CTTargTest[TempInteger] has buff Concussive Thunder ) Equal to True), checking every 0.10 seconds
                  • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
                  • Set Dummy = (Last created unit)
                  • Unit - Add Concussive Thunder (Dummy Buff Spell) to Dummy
                  • Unit - Order Dummy to Human Mountain King - Thunder Clap
                  • Unit - Add a 1.00 second Generic expiration timer to Dummy
                  • Unit - Cause Dummy to damage CTTargTest[TempInteger], dealing CTDamage[TempInteger] damage of attack type Spells and damage type Unknown
                  • Floating Text - Create floating text that reads (- + (String((Integer(CTDamage[TempInteger]))))) above CTTargTest[TempInteger] with Z offset 0.00, using font size 9.00, color (49.41%, 75.94%, 94.51%), and 0.00% transparency
                  • Set TempText = (Last created floating text)
                  • Floating Text - Change TempText: Disable permanence
                  • Floating Text - Set the velocity of TempText to 50.00 towards 60.00 degrees
                  • Floating Text - Change the fading age of TempText to 4.00 seconds
                  • Custom script: set udg_Dummy = null
                  • Custom script: set udg_TempText = null
                  • Custom script: set udg_CTPlayer[udg_TempInteger] = null
                  • Custom script: set udg_CTTargTest[udg_TempInteger] = null
                  • Floating Text - Change the lifespan of TempText to 5.00 seconds
                  • Set CTSwitch = (CTSwitch - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CTSwitch Less than or equal to 0
                    • Then - Actions
                      • Set CTCastNumber = 0
                      • Set CTSwitch = 0
                    • Else - Actions
                • Else - Actions
            • Else - Actions
I used to have a "Trigger - Turn off Concussive Thunder Loop" action in the loop but I deleted it testing to see if I could fix the problem
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
At first I'll just inform you that you are using old indexing system, it's inefficient and nowadays you better use dynamic ones - enables you do immidiately recycle each finished instance => less instances are running in loop.

Okey - they are a lot things that need to be fixed. Of you reasons why your spell isn't MUI are waits:
  • Wait until ((CTTargTest[TempInteger] has buff Concussive Thunder ) Equal to True), checking every 0.10 seconds
In case you are using global variables you do not need to null non aray unit/text/player variables.
What have you done with creating/selecting unit group? There is a lot of unneeded actions. Instead of this:
  • Set TempGroup = (Units within 312.00 of TempPoint matching (((Matching unit) belongs to an ally of CTPlayer[TempInteger]) Equal to False))
  • Unit Group - Pick every unit in TempGroup and do (Actions)
    • Loop - Actions
      • Set TempUnit = (Picked unit)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (TempUnit is A structure) Equal to True
              • (TempUnit is dead) Equal to True
              • (TempUnit is Mechanical) Equal to True
              • (TempUnit has buff Concussive Thunder ) Equal to True
          • Then - Actions
            • Unit Group - Remove TempUnit from TempGroup
          • Else - Actions
        • Custom script: set udg_TempUnit = null
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Number of units in TempGroup) Greater than 0
    • Then - Actions
      • Set CTDamage[TempInteger] = (CTDamage[TempInteger] - (CTDamage[TempInteger] x 0.10))
      • Set TempTarget = (Random unit from TempGroup)
      • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
      • Set Dummy = (Last created unit)
      • Unit - Add Concussive Thunder (Dummy Ability) to Dummy
      • Unit - Order Dummy to Neutral - Firebolt TempTarget
      • Unit - Add a 1.00 second Generic expiration timer to Dummy
      • Custom script: set udg_Dummy = null
      • Custom script: set udg_CTTargTest[udg_TempInteger] = null
      • Set CTTargTest[TempInteger] = TempTarget
      • Custom script: set udg_TempTarget = null
      • Custom script: set udg_Dummy = null
      • Set CTJumps[TempInteger] = (CTJumps[TempInteger] - 1)
    • Else - Actions
      • Set CTJumps[TempInteger] = 0
      • Custom script: set udg_CTTargTest[udg_TempInteger] = null
  • Unit Group - Remove all units from TempGroup
  • Custom script: call RemoveLocation(udg_TempPoint)
You can try this:
  • Set TempGroup = (Units within 312.00 of TempPoint matching (((Matching unit) belongs to an ally of CTPlayer[TempInteger]) Equal to False) and (((Matching unit) is A structure) Equal to False) and (((Matching unit) is dead) Equal to False)) and (((Matching unit) is Mechanical) Equal to False) and (((Matching unit) has buff Concussive Thunder ) Equal to False))
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Number of units in TempGroup) Greater than 0
    • Then - Actions
      • Set CTDamage[TempInteger] = (CTDamage[TempInteger] - (CTDamage[TempInteger] x 0.10))
      • Set TempTarget = (Random unit from TempGroup)
      • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
      • Unit - Add Concussive Thunder (Dummy Ability) to (Last created unit)
      • Unit - Order (Last created unit) to Neutral - Firebolt TempTarget
      • Unit - Add a 1.00 second Generic expiration timer to (Last create unit)
      • Set CTTargTest[TempInteger] = TempTarget
      • Set CTJumps[TempInteger] = (CTJumps[TempInteger] - 1)
    • Else - Actions
      • Set CTJumps[TempInteger] = 0
  • Custom script: set udg_CTTargTest[udg_TempInteger] = null
  • Custom script: call RemoveLocation (udg_TempPoint)
  • Custom script: call DestroyGroup (udg_TempGroup)
Similar situation happens here:
  • Floating Text - Create floating text that reads (- + (String((Integer(CTDamage[TempInteger]))))) above CTTargTest[TempInteger] with Z offset 0.00, using font size 9.00, color (49.41%, 75.94%, 94.51%), and 0.00% transparency
  • Set TempText = (Last created floating text)
  • Floating Text - Change TempText: Disable permanence
  • Floating Text - Set the velocity of TempText to 50.00 towards 60.00 degrees
  • Floating Text - Change the lifespan of TempText to 5.00 seconds
  • Floating Text - Change the fading age of TempText to 4.00 seconds
  • Custom script: set udg_TempText = null
Your test is just temporary and disablinf it's permanence + adding lifespan is enough - variable and nulling is not needed. Try:
  • Floating Text - Create floating text that reads (- + (String((Integer(CTDamage[TempInteger]))))) above CTTargTest[TempInteger] with Z offset 0.00, using font size 9.00, color (49.41%, 75.94%, 94.51%), and 0.00% transparency
  • Floating Text - Change (Last created floating text): Disable permanence
  • Floating Text - Set the velocity of (Last created floating text) to 50.00 towards 60.00 degrees
  • Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
  • Floating Text - Change the fading age of (Last created floating text) to 4.00 seconds
 
Level 2
Joined
Jul 28, 2009
Messages
14
Okay,
@rysnt, thanks for pointing that out though, I have taken both setting the TempTarget and nulling the casting unit out.

@Spin, you had a lot of good points, I never thought of using the "And" condition for the unit group. On a different site a long time ago when I asked for help people told me I needed to set all the handles to variables and clear them (meaning on the dummys and temp text, I already put everything else to variables) and I've been doing that ever since then, but if it is uneeded for the last created unit stuff then I can easily revert back to how I used to do it. But If I put the
"Custom script: set udg_CTTargTest[udg_TempInteger] = null" underneath of the If, Then, Else (Multiple Actions) then it will clear the unit I just set with "Set CTTargTest[TempInteger] = TempTarget". I guess I can make the trigger loop an additional time to get rid of the wait, I just needed it to look more smooth.
Also about the "call DestroyGroup (udg_TempGroup)", I was told that that will make the variable unusable in all future triggers and thats why I don't use it, so was that just some guy's assumption and that does clear unit groups like nulling or Removing a location?

Even after doing everything you guys suggested though I still have the problem that:
The spell does absolutely nothing first cast

If I do not have the loop trigger Initially Disabled then the first cast works though, and if the first cast doesn't work then that would mean there would always be a CTSwitch of 1 so the trigger would never be turned off, heres the current triggers:

Concussive Thunder Init:
  • Concussive Thunder
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Concussive Thunder
    • Actions
      • If (CTCastNumber Equal to 0) then do (Trigger - Turn on Concussive Thunder Loop <gen>) else do (Do nothing)
      • Set TempUnit = (Casting unit)
      • Set CTCastNumber = (CTCastNumber + 1)
      • Set CTSwitch = (CTSwitch + 1)
      • Set CTJumps[CTCastNumber] = 4
      • Set CTTargTest[TempInteger] = (Target unit of ability being cast)
      • Set CTPlayer[CTCastNumber] = (Owner of TempUnit)
      • Set CTDamage[CTCastNumber] = (40.00 + (45.00 x (Real((Level of (Ability being cast) for TempUnit)))))
Concussive Thunder Loop:
  • Concussive Thunder Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • For each (Integer TempInteger) from 1 to CTCastNumber, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CTJumps[TempInteger] Greater than 0
              • (CTTargTest[TempInteger] has buff Concussive Thunder ) Equal to True
            • Then - Actions
              • Set TempPoint = (Position of CTTargTest[TempInteger])
              • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
              • Unit - Add Concussive Thunder (Dummy Buff Spell) to (Last created unit)
              • Unit - Order (Last created unit) to Human Mountain King - Thunder Clap
              • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
              • Unit - Cause (Last created unit) to damage CTTargTest[TempInteger], dealing CTDamage[TempInteger] damage of attack type Spells and damage type Unknown
              • Floating Text - Create floating text that reads (- + (String((Integer(CTDamage[TempInteger]))))) above CTTargTest[TempInteger] with Z offset 0.00, using font size 9.00, color (49.41%, 75.94%, 94.51%), and 0.00% transparency
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Set the velocity of (Last created floating text) to 50.00 towards 60.00 degrees
              • Floating Text - Change the lifespan of (Last created floating text) to 5.00 seconds
              • Floating Text - Change the fading age of (Last created floating text) to 4.00 seconds
              • Special Effect - Create a special effect at TempPoint using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
              • Special Effect - Destroy (Last created special effect)
              • Set TempGroup = (Units within 312.00 of TempPoint matching ((((Matching unit) belongs to an enemy of CTPlayer[TempInteger]) Equal to True) and ((((Matching unit) is A structure) Equal to False) and ((((Matching unit) is Mechanical) Equal to False) and (((Matching unit) has b
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Number of units in TempGroup) Greater than 0
                • Then - Actions
                  • Set CTDamage[TempInteger] = (CTDamage[TempInteger] - (CTDamage[TempInteger] x 0.10))
                  • Set CTTargTest[TempInteger] = (Random unit from TempGroup)
                  • Unit - Create 1 Dummy for CTPlayer[TempInteger] at TempPoint facing Default building facing degrees
                  • Unit - Add Concussive Thunder (Dummy Ability) to (Last created unit)
                  • Unit - Order (Last created unit) to Neutral - Firebolt CTTargTest[TempInteger]
                  • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                  • Set CTJumps[TempInteger] = (CTJumps[TempInteger] - 1)
                • Else - Actions
                  • Set CTJumps[TempInteger] = 0
                  • Custom script: set udg_CTTargTest[udg_TempInteger] = null
              • Custom script: call RemoveLocation(udg_TempPoint)
              • Custom script: call DestroyGroup (udg_TempGroup)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CTJumps[TempInteger] Less than or equal to 0
                • Then - Actions
                  • Custom script: set udg_CTPlayer[udg_TempInteger] = null
                  • Custom script: set udg_CTTargTest[udg_TempInteger] = null
                  • Set CTSwitch = (CTSwitch - 1)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CTSwitch Less than or equal to 0
                    • Then - Actions
                      • Set CTCastNumber = 0
                      • Set CTSwitch = 0
                      • Trigger - Turn off Concussive Thunder Loop <gen>
                    • Else - Actions
                • Else - Actions
            • Else - Actions
 
Last edited:

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
But If I put the
"Custom script: set udg_CTTargTest[udg_TempInteger] = null" underneath of the If, Then, Else (Multiple Actions) then it will clear the unit I just set with "Set CTTargTest[TempInteger] = TempTarget".
Nulling array variable should be done when it is not needed anymore (e.g end of function) and btw dont use custom script if it's unneeded - if you want custom scripts better move to jass.
  • Set CTTargTest[udg_TempInteger] = No unit
I guess I can make the trigger loop an additional time to get rid of the wait, I just needed it to look more smooth.
Yes loop with duration stored in real variable should hlep you get rid of waits.
Also about the "call DestroyGroup (udg_TempGroup)", I was told that that will make the variable unusable in all future triggers and thats why I don't use it, so was that just some guy's assumption and that does clear unit groups like nulling or Removing a location?
Function call DestroyGroup (udg_TempGroup) helps you to free up memory and removes group leak. I dont know who told you that thing but for sure it's a lie. You can immidiately use removed/destroyed variable after you call those functions.
It helps much - egzample: you need less amount of variables.
  • Set tempp1 = (Position of unitX)
  • Set tempp2 = tempp1 offset by 200 towards (Random angle)
  • Unit Group - Pick every unit in 300 range from tempp2 and do actions
    • Loop - Actions
      • Set tempp3 = (Position of (Picked unit))
      • Set tempp4 = tempp3 offset by 30 towards (Facing of (Picked unit))
      • Unit - Move (Picked unit) instantly to tempp4
      • Custom script: call RemoveLocation(udg_tempp3)
      • Custom script: call RemoveLocation(udg_tempp4)
  • Custom script: call RemoveLocation(udg_tempp1)
  • Custom script: call RemoveLocation(udg_tempp2)
Can be cut to this:
  • Set tempp1 = (Position of unitX)
  • Set tempp2 = tempp1 offset by 200 towards (Random angle)
  • Unit Group - Pick every unit in 300 range from tempp2 and do actions
    • Loop - Actions
      • Custom script: call RemoveLocation(udg_tempp1)
      • Custom script: call RemoveLocation(udg_tempp2)
      • Set tempp1 = (Position of (Picked unit))
      • Set tempp2 = tempp1 offset by 30 towards (Facing of (Picked unit))
      • Unit - Move (Picked unit) instantly to tempp2
      • Custom script: call RemoveLocation(udg_tempp1)
      • Custom script: call RemoveLocation(udg_tempp2)
EDIT:
  • (CTTargTest[TempInteger] has buff Concussive Thunder ) Equal to True
Remove that condition.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Probably you got wrong conditions in group creating and therefore group units count reaches 0 => no actions. You should learn debugging art, its usefull in finding mistakes in code by your own.

Post map if you are in blank spot - will fix that for you.

EDIT: Man you haven't added action:
  • Trigger - Turn on Concussive Thunder Loop <gen>
- in your Concussive Thunder trigger.

By the way:
  • Set CTSwitch = (CTSwitch - 1)
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • CTSwitch Less than or equal to 0
    • Then - Actions
      • Set CTCastNumber = 0
      • Set CTSwitch = 0
      • Trigger - Turn off Concussive Thunder Loop <gen>
    • Else - Actions
Isn't that silly? You check if CTSwitch is equal or less than 0 and after all you set to 0? Such action isn't needed neither for nulling in case it's integer nor for savety (being sure that its 0 when all instances have finished).

Remove:
  • Set CTSwitch = 0
 
Level 2
Joined
Jul 28, 2009
Messages
14
Please read the trigger before making assumptions, the very first line in the trigger is:
If (CTCastNumber Equal to 0) then do (Trigger - Turn on Concussive Thunder Loop <gen>) else do (Do nothing)

I cannot post map because it is a friend's, I will copy the spell into a dummy map though and post it here
 
Level 2
Joined
Jul 28, 2009
Messages
14
Ha! You're not gonna believe what the issue was! I was putting the dummy map together and I was checking to make sure all the variables were there and I noticed this line in the initiation trigger:
  • Set CTTargTest[TempInteger] = (Target unit of ability being cast)
So I changed TempInteger to CTCastNumber and the spell works beautifully now!
Thanks though, Spin, I learned a lot from this, and when I'm talking to someone is when I think the most clearly ^^

I can't believe it took me this long to realize that though, usually I'd notice something like that in my first scan through the trigger, oh well.
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Was looking on that trigger thousand times and you know why I haven;t thought about that TempInteger?
Because I always use that as index in my spells if doing in GUI - TempInt serves me as temporary index. But It's for dynamic indexing, you should go learn that too - link here.
After all, hope you take my advices because everything I've told you (even previous post, yes avoid 'do nothing' action - its sometimes buggy) should improve your's trigger efficiency.
 
Status
Not open for further replies.
Top