Tutorial Making MUI spells in GUI

Flare

Stops copies me!
Reaction score
662
Well, this is my first attempt at a tutorial, and I think I have covered the basics of MUI spells in GUI. If you have any suggestions on additions that can be made, please post them and I will add it in.

MUI spells in GUI
-So, you want to make MUI spells in GUI (only JASS required is for leak removal). Well, you've come to the right place :)

What is MUI?
--MUI is Multi-Unit-Instanceability. But what does this mean to all those who don't know? It means that if 2 or more units (owned by any player, but it still has to work with 2 units owned by Player 1 for example) cause a trigger to fire (casting a spell would be best example), the spell's effect will work properly for both units that cast the ability. Also, MUI is -nearly- impossible to achieve with waits. I've seen an MUI ability with waits before, but it was only AoE (since you can't ensure that a specific unit variable will be retained after a wait, if another unit casts the ability).

This tutorial will explain everything involved in creating an MUI spell (well, everything involved in my preferred method of doing it). This method of making spells MUI relies mainly on periodic events (you need something to cause the periodic events to fire i.e. units in a unit group), but you can do alot of things within that periodic event such as waiting (without using Wait action), a more precise periodic event (if you wanted something to occur every 1 second, but the timing had to be right i.e. cast a spell at 10.5 seconds gametime, the effect should occur at 11.5 seconds gametime. A 1 second periodic event trigger wouldn't be able to do this correctly and timing would be incorrect)

Index:
1. Where do I start?
2. What do I need?
3. MUI periodic events (DoT spell will be used as an example).
4. Avoiding waits with periodic events.
5. Buffs
6. Credits (order is a bit mixed up unfortunately)
7. Practical example of MUI periodic events and MUI wait avoidance.
8. Running trigger B from trigger A with Run Trigger action
<Additional topics will be added if they are requested>

Also, there's two big advantages to using this method of MUI:
1) If you have an MUI system (e.g. u are a noob's GUI MUI system), this will not conflict with it. You are not assigning custom values to units who are actively taking part in the game, just a 'ghost' unit, who just does nothing but lets you refer back to arrays.

2) Also, it allows the same unit to cast the spell/be affected by the spell more than once. The casting unit isn't being assigned 2 custom values (one of which will be overwritten by the other), he is just being given 2 dummies, each dummy having a different custom value.

1. Where do I start?
---Firstly, you need to make a base ability in the Object Editor which will allow the trigger to fire.
---Reasonable knowledge of GUI triggers is a bonus, but everything involved will be explained along the way so don't worry if you are a beginner.

2. What do I need?
---a) Your base ability which will cause the trigger to fire

---b) Some variables (here's a sample list for a DoT spell): CustomValue (integer, no array), Caster (unit, array), Target (unit, array), Damage (real, array), CurrentTime (real, array), MaxTime (real, array), SFX (special effect, array) DummyGroup (unit group, array), TempInteger (integer, no array) and finally, TempPt (point, no array)
---*Above is just a suggested, easy-to-recognise variable names, their variable type, and whether or not they require an array. The array size defined in the Variable Editor doesn't matter (that just defines an initial value for the array)

---c) An idea of what you want to do (in this case, a spell that does X damage per second for Y seconds). Knowing what you want to do is the hardest part once you figure out how to utilise the information in this tutorial.

---* If you are trying to make a non-MUI spell become MUI, you will need to add the arrays to existing variables, similar to those mentioned above (CustomValue, tempinteger and temppt will NEVER require arrays. temppt is just used to spawn the dummy without creating leaks, and tempinteger just makes it easy to refer back to custom value of dummies)

IMPORTANT!
You should never turn off a periodic trigger if there is a spell instance running, it is just plain wrong and will only break stuff. There is nothing wrong with setting a periodic trigger to Initially Off, then enabling it when an instance is created (and said instance is the only one running), then disabling the periodic trigger once all instances have finished

---Pictures of variables used in demo map

3. MUI periodic events
---First, we need a trigger that will specify all the information we need, so that we can refer back to it in the periodic event.

Code:
MUI demonstration cast
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to DPS test 
    Actions
        -------- This will cycle the custom value used for the particular instance of the spell, so that it will always be changing when the ability is cast. --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                CustomValue Less than 1000
            Then - Actions
                Set CustomValue = (CustomValue + 1)
            Else - Actions
                Set CustomValue = 1
        -------- Setting our variables, making sure that the array value is [CustomValue] --------
        Set Caster[CustomValue] = (Triggering unit)
        Set Target[CustomValue] = (Target unit of ability being cast)
        Set CurrentDuration[CustomValue] = 0.00
        Set MaxDuration[CustomValue] = 5.00
        -------- If you didn't set a value for the DPS, this will assign it a random value between 10 and 25 --------
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                DPS[CustomValue] Equal to 0.00
            Then - Actions
                Set DPS[CustomValue] = (Random real number between 10.00 and 25.00)
            Else - Actions
        Set temppt = (Center of (Playable map area))
        -------- Creating a dummy unit, giving it a custom value of (CustomValue). We will need to refer back to this later to find out who is the correct target and what is the correct damage to be dealt. --------
        Unit - Create 1 Dummy Unit for (Owner of Caster[CustomValue]) at temppt facing Default building facing degrees
        Unit - Set the custom value of (Last created unit) to CustomValue
        -------- Adding the dummy unit to the dummy group, so we can pick all dummy units, and refer to each of their custom values, and the DPS and Target variables to which the dummy unit is 'attached' to. --------
        Unit Group - Add (Last created unit) to DummyGroup
        Custom script:   call RemoveLocation (udg_temppt)

---Now, notice that the custom value variable is always increasing in value by 1, until it gets to 1000. Once it is at 1000, the next cast will set it back to 1, cycling the values.
---Also, notice that the dummy unit's custom value, and ALL the variable arrays have the same value. This means that we always know which dummy refers back to which unit, number or point. Dummy with custom value of 17, always refers back to Caster[17], Target[17] etc
---Also, the dummy unit was added to a unit group. Why? Well, in the periodic trigger, we want to be able to handle all existing dummy units, without a really large trigger. So, if we add them to a unit group, we can just use the action "Pick every unit in Unit Group".

Now, let's get to the periodic event.

Code:
MUI demonstration periodic
    Events
        Time - Every 1.00 seconds of game time
    Conditions
        (Number of units in DummyGroup) Greater than 0
    Actions
        -------- Above condition prevents the trigger from firing when there are no units under the abilities effect --------
        -------- This is going to pick every dummy unit that was added to the group in the spellcast. Once the duration ends or the target unit dies, the dummy will be totally removed from the game --------
        -------- This way, the condition won't be met if there are no units under the spell's effect. --------
        Unit Group - Pick every unit in DummyGroup and do (Actions)
            Loop - Actions
                -------- This is just to make referencing the dummy unit's custom value MUCH easier than going through the lists of integers to find it. --------
                Set tempinteger = (Custom value of (Picked unit))
                -------- This is checking the conditions that are necessary for the spell to end. If the target unit dies, or the duration expires, the dummy is removed so nothing more will happen. --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        Or - Any (Conditions) are true
                            Conditions
                                (Target[tempinteger] is dead) Equal to True
                                CurrentDuration[tempinteger] Greater than or equal to MaxDuration[tempinteger]
                    Then - Actions
                        Unit - Remove (Picked unit) from the game
                    Else - Actions
                        -------- This will deal the damage to the target unit. --------
                        Unit - Cause Caster[tempinteger] to damage Target[tempinteger], dealing DPS[tempinteger] damage of attack type Spells and damage type Normal
                        -------- This will add some floating text above the unit, to show the damage that should be dealt without armor type/reduction. --------
                        Floating Text - Create floating text that reads (String((Integer(DPS[tempinteger])))) above Target[tempinteger] with Z offset 0.00, using font size 10.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
                        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
                        Floating Text - Change (Last created floating text): Disable permanence
                        Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
                        Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
                        -------- And the elapsed time for the ability will increase here. --------
                        Set CurrentDuration[tempinteger] = (CurrentDuration[tempinteger] + 1.00)

---Now, first things first, the event. Using "Every 1.00 seconds" is a small bit inefficient in this case, since if a unit casts the spell at 10.5 seconds of gametime, the damage will be taken 0.5 seconds earlier than it should, but that's negligible.
---Second, the condition. This just prevents the trigger from firing if there are no units in DummyGroup (it MAY cause lag with numerous triggers firing needlessly, and doing absolutely nothing when firing)
---Third, we are picking every unit in the unit group. This just makes it easier than doing the actions for each unit individually (which could take forever) and more reliable than using an integer loop (since you can't attempt to refer to a dummy unit who doesn't exist with groups, or mistakenly do something that shouldn't have been done i.e. deal damage when the unit isn't under the spells effect)

---*Note the "Set tempinteger" part. This isn't required but is highly recommended because (1) it saves time, referring to "Custom value of picked unit" is very time-consuming compared to referring to a variable and (2) it allows you to pick units in another unit group, within that dummy group loop (say if you wanted to damage multiple units in an area of effect)

---The If/Then/Else just checks if the dummy unit isn't needed anymore i.e. the target is dead, it doesn't need to take more damage OR duration has expired, target should no longer take damage. In this case, the dummy is removed from the game (with Remove Unit). This frees up the custom value used by the dummy, so it can be re-used later, when the CustomValue variable goes from from 1000, back down to 1 and repeats it's cycle.

---The Damage Unit action explains itself. Caster[the array is tempinteger, and tempinteger is the picked unit's custom value. This links the dummy unit to Caster, and every other variable that is used in a similar way i.e. Target, DPS, CurrentTime] will damage Target[tempinteger]. Then a floating text is created just to prove that the damage being damage being dealt is (somewhat) unique to that unit. In my demo, it's not unique since it can only be 1 of 15 values which is fairly limited but that's not really relevant ^^.

4. Avoiding waits with periodic events.
---I'm sure that everyone here knows about waits. They are a pain, they can be useful if you only need an ability to be used once at a time, but if you want to make an MUI ability, they are your worst enemy. So, we have to work around them to make something that works in much the same way, but without the limitations that waits can impose.

---Firstly, we make a spellcast trigger, which will do the very same thing as before (set your custom value figure, our variables and assign a dummy unit to a unit etc)

Code:
Spellcast
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Slam (Neutral Hostile)
    Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                CV2 Less than 1000
            Then - Actions
                Set CV2 = (CV2 + 1)
            Else - Actions
                Set CV2 = 1
        Set TextUnit[CV2] = (Triggering unit)
        Set WaitTime[CV2] = 0.00
        Set Ticks[CV2] = 0
        Set temppt = (Center of (Playable map area))
        Unit - Create 1 Dummy Unit for (Owner of TextUnit[CV2]) at temppt facing Default building facing degrees
        Unit - Set the custom value of (Last created unit) to CV2
        Unit Group - Add (Last created unit) to DummyGroup2
        Custom script:   call RemoveLocation (udg_temppt)

---I used a different custom value variable this time, since using the same custom value variable can limit the amount of times the spells can be cast i.e. using 2 spells and 1 custom value variable can limit the MUI to alot less possible instances for each which could be potentially bad.
I also used a different unit group variable, for similar reasons and also to prevent text appears over units who have nothing to do with the testing ability (which is Slam)
*Ignore the Ticks variable, that's unused.

---WaitTime is the only big thing in this trigger, this will determine the time before each floating text appears in the periodic trigger.
Also, the variable A is the equivalent of the tempinteger variable used in section 3.

Code:
Text creation
    Events
        Time - Every 0.05 seconds of game time
    Conditions
        (Number of units in DummyGroup2) Greater than 0
    Actions
        Unit Group - Pick every unit in DummyGroup2 and do (Actions)
            Loop - Actions
                Set A = (Custom value of (Picked unit))
                Set WaitTime[A] = (WaitTime[A] + 0.05)
                -------- Create text after 0.15 seconds --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        WaitTime[A] Equal to 0.15
                    Then - Actions
                        Floating Text - Create floating text that reads (MUI wait time. Time since spell cast:  + (String(WaitTime[A]))) above TextUnit[A] with Z offset 0.00, using font size 8.50, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
                        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
                        Floating Text - Change (Last created floating text): Disable permanence
                        Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
                        Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
                    Else - Actions
                -------- Create text after 1.25 seconds --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        WaitTime[A] Equal to 1.25
                    Then - Actions
                        Floating Text - Create floating text that reads (MUI wait time. Time since spell cast:  + (String(WaitTime[A]))) above TextUnit[A] with Z offset 0.00, using font size 8.50, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
                        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
                        Floating Text - Change (Last created floating text): Disable permanence
                        Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
                        Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
                    Else - Actions
                -------- Create text after 2.5 seconds --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        WaitTime[A] Equal to 2.50
                    Then - Actions
                        Floating Text - Create floating text that reads (MUI wait time. Time since spell cast:  + (String(WaitTime[A]))) above TextUnit[A] with Z offset 0.00, using font size 8.50, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
                        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
                        Floating Text - Change (Last created floating text): Disable permanence
                        Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
                        Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
                        Unit - Remove (Picked unit) from the game
                    Else - Actions

---That may look like an awfully long trigger, but everything within the if/then/else grouping is practically copy-pasting with changed values for the conditions (and the Remove Unit in the last if/then/else).
As you can see, we are progressively increasing the WaitTime variable for each unit in DummyGroup2, and when it becomes a certain value, a text will appear to display the current wait time. Also, it is advisable to do something like

Code:
WaitTime greater than or equal to (your inteded wait value - 0.03)
WaitTime less than or equal to (your intended wait value + 0.03)

NOTICE: For periodic sliding triggers, this part of very important since slide triggers aren't really used with a periodic event greater than 0.04
---If your periodic trigger goes every... 0.04 seconds, and you want a wait for 0.25 seconds, you will never be able to multiply 0.04 by any whole number and get 0.25, it's impossible. So you have to get as close as you can. From the example above, the first multiple of 0.04 between (0.25-0.03) and (0.25+0.03), which would be 0.24, would trigger the actions. It's not as precise, but if you want absolute precision, you would need a periodic event of 0.01, and that can be laggy.

---This is also needed if you want to do something such as create a special effect every 0.25 seconds, all within the slide trigger so you don't have to create another trigger, and repeat everything you've already done

*If you use another method to control when an action occurs (say you wanted to check when a slide should end, based on the unit's distance travelled from the original position), this isn't of much use since it's based around elapsed time.

Also, if you had
Code:
Wait 0.3 seconds
//Some actions
Wait 0.7 seconds

*Make sure the conditions are right. When you are checking WaitTime = X, you must add the wait value of your current wait, to all previous waits so

Code:
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    If - Conditions
        WaitTime[A] Equal to 0.30
    Then - Actions
        Floating Text - Create floating text that reads (MUI wait time. Time since spell cast:  + (String(WaitTime[A]))) above TextUnit[A] with Z offset 0.00, using font size 8.50, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
        Floating Text - Change (Last created floating text): Disable permanence
        Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
        Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
    Else - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    If - Conditions
        WaitTime[A] Equal to 1.00
    Then - Actions
        Floating Text - Create floating text that reads (MUI wait time. Time since spell cast:  + (String(WaitTime[A]))) above TextUnit[A] with Z offset 0.00, using font size 8.50, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
        Floating Text - Set the velocity of (Last created floating text) to 64.00 towards 90.00 degrees
        Floating Text - Change (Last created floating text): Disable permanence
        Floating Text - Change the lifespan of (Last created floating text) to 2.50 seconds
        Floating Text - Change the fading age of (Last created floating text) to 2.00 seconds
    Else - Actions

That would replace the 2 waits shown above.

5. Buffs
Some things about using buffs with this:
---Using buffs with this can be slightly problematic (if the duration of abilities is randomized, or based on a variable such as hero stats etc). Since you can't guarantee that a buff from a spell (like Slow for example) will be removed immediately once the unit is no longer under the spell's effect. If you wish to use buffs, make them so that they only use a tooltip and an icon, no special effect. This way, you can trigger the special effect so that if the buff is removed too early or too late, it will be possible to tell if a unit is under the effects of an ability or not.

---Alternatively, you could use an infinite duration ability with nullified values (e.g. Slow with 0% speed reduction). Then, when a unit is no longer affected by the spell, we set the variable it was assigned (Target for example) to No Unit. Then, we check if any dummy units are assigned to unit X (the unit under the abilities effect). If there are dummies assigned to unit X, we don't do anything to the buff, since it's still required. But, if no dummies are assigned to unit X (therefore, the unit is no longer under the abilities effect), we can safely remove the buff from unit X.


---Another problem with buffs is that they may be overwritten by another buff, from another ability (let's take slow for example). If you cast your dummy slow (which is only used to apply a buff), and another unit casts a normal slow (which actually slows the unit), your dummy buff may be overwritten so SFX could disappear.
---An alternative is using dummy auras, with all values set to 0, and add it to the unit. This will give an special FX, a buff, and from what I remember, the buff won't be overwritten by another aura, but the aura with greater values should take precedence, so your dummy aura -shouldn't- cause a unit's auras to be negated. Anyway, your dummy aura will always be level 1. Aura levels take priority from what I remember, so a level 2 normal aura should always override the dummy aura, leaving 2 buffs, but only the level 2 aura will have an effect.


6. Credits: If you use the Meteor Shower demo spell in your map, please give credits.



7. Now, a practical example of MUI periodic events, and MUI wait avoidance in action

---Beware: This is a bit more advanced than the previous stuff (nothing too great, just uses an extra unit group and a few more variables for easy referencing). Extra unit group just makes it less likely for the MUI-ness to be ruined (if I added meteor dummies to the same group as unused dummies, it could very easily cause problems i.e. if you had 200 units casting the ability at the same time, it would only take about 3.5 seconds before the meteor dummy gets a custom value of 1, which could cause conflict with ownership (MeteorDummy[1] may not be owned by Caster[1])


Basically, an ability that rains down meteors (starfall FX) every 0.75 seconds (periodic event), dealing damage upon impact (wait avoidance).

---This will also show you how to clear variables and remove the correct dummy unit when a unit stops channelling (absolute requirement if you want GUI MUI channelling spells, otherwise you could have permanent effects)

Code:
Meteor Shower Cast
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Meteor Shower 
    Actions
        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            If - Conditions
                CV1 Less than 1000
            Then - Actions
                Set CV1 = (CV1 + 1)
            Else - Actions
                Set CV1 = 1
        Set Caster[CV1] = (Triggering unit)
        Set CasterLoc[CV1] = (Position of Caster[CV1])
        Unit - Create 1 Dummy Unit for (Owner of Caster[CV1]) at CasterLoc[CV1] facing Default building facing degrees
        Unit - Set the custom value of (Last created unit) to CV1
        Unit Group - Add (Last created unit) to DummyGroup



-----------------------------------------------------------------


Meteor Shower Periodic
    Events
        Time - Every 0.05 seconds of game time
    Conditions
    Actions
        Unit Group - Pick every unit in DummyGroup and do (Actions)
            Loop - Actions
                Set TempInt1 = (Custom value of (Picked unit))
                Set SpawnInterval[TempInt1] = (SpawnInterval[TempInt1] + 0.05)
                -------- This If/Then/Else determines how often a meteor falls --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        SpawnInterval[TempInt1] Equal to 0.75
                    Then - Actions
                        Set SpawnInterval[TempInt1] = 0.00
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                CV2 Less than 1000
                            Then - Actions
                                Set CV2 = (CV2 + 1)
                            Else - Actions
                                Set CV2 = 1
                        Set Temp_Point = (CasterLoc[TempInt1] offset by (Random real number between 0.00 and 500.00) towards (Random angle) degrees)
                        Unit - Create 1 Meteor Dummy for (Owner of Caster[TempInt1]) at Temp_Point facing Default building facing degrees
                        Unit - Set the custom value of (Last created unit) to CV2
                        Set Meteor[CV2] = (Last created unit)
                        -------- This determines the damage dealt by the meteors upon impact. I made it 1x (INT) to make it much easier to configure the multiplier damage. --------
                        Set Damage[CV2] = (1.00 x (Real((Intelligence of Caster[TempInt1] (Exclude bonuses)))))
                        Unit Group - Add (Last created unit) to MeteorGroup
                        Custom script:   call RemoveLocation (udg_Temp_Point)
                    Else - Actions
        Unit Group - Pick every unit in MeteorGroup and do (Actions)
            Loop - Actions
                Set TempInt2 = (Custom value of (Picked unit))
                Set ImpactDelay[TempInt2] = (ImpactDelay[TempInt2] + 0.05)
                -------- It is advised to leave impact delay as it is, it's almost exactly the right timing when damage/SFX occurs and meteor impacts --------
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        ImpactDelay[TempInt2] Equal to 0.90
                    Then - Actions
                        Set ImpactDelay[TempInt2] = 0.00
                        Set Temp_Point = (Position of (Picked unit))
                        Special Effect - Create a special effect at Temp_Point using Abilities\Spells\Human\Thunderclap\ThunderClapCaster.mdl
                        Special Effect - Destroy (Last created special effect)
                        Set TempGroup = (Units within 250.00 of Temp_Point matching ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Owner of Meteor[TempInt2])) Equal to True)))
                        -------- Change the "within X of" to increase/decrease the damage radius --------
                        Unit Group - Pick every unit in TempGroup and do (Actions)
                            Loop - Actions
                                Unit - Cause Meteor[TempInt2] to damage (Picked unit), dealing Damage[TempInt2] damage of attack type Spells and damage type Normal
                        Custom script:   call RemoveLocation (udg_Temp_Point)
                        Custom script:   call DestroyGroup (udg_TempGroup)
                        Unit - Remove Meteor[TempInt2] from the game
                    Else - Actions



---------------------------------------------------------------


Meteor Shower End
    Events
        Unit - A unit Stops casting an ability
    Conditions
        (Ability being cast) Equal to Meteor Shower 
    Actions
        -------- This just checks which unit stopped casting the ability, and removes it's assigned dummy and cleans up a leak --------
        Unit Group - Pick every unit in DummyGroup and do (Actions)
            Loop - Actions
                Set TempInt1 = (Custom value of (Picked unit))
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                        (Triggering unit) Equal to Caster[TempInt1]
                    Then - Actions
                        Set Caster[TempInt1] = No unit
                        Custom script:   call RemoveLocation (udg_CasterLoc[udg_TempInt1])
                        Unit - Remove (Picked unit) from the game
                    Else - Actions

---This is just a nice example spell I thought of making, and can be used for learning purposes, or for adding to a map if you wish.

---Update: Just added an alternative meteor shower demo which uses the starfall's projectile explosion effect, rather than creating a new special effect. It's nothing major, but it just looks a little bit more natural than thunder clap (although the size of the impact is a bit large ^^). Meteor shower update is the alternate file


8. Running trigger B from trigger A using Run Trigger action

---Just thought of something else. If you want to use the Run Trigger action, you will need a boolean variable (name it whatever you want) with an array of 1000 (or whatever your instance limit is). When you initially cast the spell, set your variables, make your dummy and set its custom value, add it to your dummy group THEN set <Boolean>[Custom value variable] = True, and run the other trigger.

---Now, in the other trigger, pick every unit in the dummy group, set your reference integer variable (tempinteger = custom value of picked unit) and add an If/Then/Else. The condition will be <Boolean>[tempinteger] = True. After that, add your actions and set <Boolean>[tempinteger] back to false, to prevent issues (re-occurence of spell effect for a unit who hasn't casted recently perhaps ^^)

Credits to Tinki3 for the great spell test map template.
 

Attachments

  • Meteor Shower.w3x
    49.5 KB · Views: 403
  • Meteor Shower update.w3x
    49.7 KB · Views: 396
  • meteor shower and firebolt.w3x
    51.5 KB · Views: 505
T

Tubba

Guest
Yup, really excellent system. Thanks a lot for showing it before.
 

Flare

Stops copies me!
Reaction score
662
A GUI MUI system has already been done by uareanoob, but a tutorial is obviously more informative.

I will take a read as soon as I can.

Take a look at the text just below the index. It says that it can work side-by-side ureanoob's system, as long as you configure the GUI MUI system so that it doesn't automatically give dummy units a custom value when they are created.

Well, I assume it would work, I can't see why it shouldn't ^^
 

Draphoelix

It's not the wintercold that's killing me
Reaction score
132
Wow.. Excactly what I need. I didn't read everything but I'm sure it works. I always used GUI but I tried to learn JASS because of the MUI thing, but this tutorial will come in handy when I'm going to make "some" spells :D
 
T

Tubba

Guest
A GUI MUI system has already been done by uareanoob, but a tutorial is obviously more informative.

I will take a read as soon as I can.

Yeah, but tutorial is really overly complicated.



Here's a spell I made with the system, BTW.


Code:
Light And Dark
    Events
        Unit - A unit Starts the effect of an ability
    Conditions
        (Ability being cast) Equal to Light and Darkness
    Actions
        If (IntegerArray Equal to 1000) then do (Set IntegerArray = 0) else do (Set IntegerArray = (IntegerArray + 1))
        ---------------Set caster and target and target point---------
        Set tempCaster[IntegerArray] = (Triggering unit)
        Set tempTarget[IntegerArray] = (Target unit of ability being cast)
        Set tempUnitPoint = (Position of (Target unit of ability being cast))
        --------------Custom value, group, etc----------
        Unit - Create 1 Dummy Unit for (Owner of (Triggering unit)) at tempUnitPoint facing Default building facing degrees
        Unit - Set the custom value of (Last created unit) to IntegerArray
        Unit Group - Add (Last created unit) to DummyGroup
        Custom script:   call RemoveLocation (udg_tempUnitPoint )

Code:
LightAndDarkStream
    Events
        Time - Every 0.50 seconds of game time
    Conditions
        (Number of units in DummyGroup) Greater than 0
    Actions
        Unit Group - Pick every unit in DummyGroup and do (Actions)
            Loop - Actions
                ---------------Should be self-explanatory, TrueArrayInteger can now be used to refer to what we did in the other spell---------
                Set TrueArrayInteger = (Custom value of (Picked unit))
                If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    If - Conditions
                         -------------------Is the target dead or has the spell been finished?---------------
                        ((tempTarget[TrueArrayInteger] is dead) Equal to True) or ((Integer(timeLeft[TrueArrayInteger])) Greater than or equal to 20)
                    Then - Actions
                        Unit - Remove (Picked unit) from the game
                    Else - Actions
                        ------------------Setting point of target, and the group which will be used later-----------
                        Set PointLnD[TrueArrayInteger] = (Position of tempTarget[TrueArrayInteger])
                        Set GroupHealorDie[TrueArrayInteger] = (Units within 600.00 of PointLnD[TrueArrayInteger] matching (((Matching unit) Not equal to tempTarget[TrueArrayInteger]) and ((Matching unit) Not equal to (Picked unit))))
                        If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            If - Conditions
                                (Random integer number between 1 and 3) Equal to 1
                            Then - Actions
                                 ------------Basic stuff, this either heals or damages units around tempTarget.------------
                                Set tempTargetDarkLight[TrueArrayInteger] = (Random unit from GroupHealorDie[TrueArrayInteger])
                                 ------------Just wanted to use this to test so that it didn't damage the dummy and stuff.---------
                                Game - Display to (All players) the text: (Name of tempTargetDarkLight[TrueArrayInteger])
                                Set tempTargetLnDPoint[TrueArrayInteger] = (Position of tempTargetDarkLight[TrueArrayInteger])
                                Unit - Create 1 Dummy Unit for (Owner of tempCaster[TrueArrayInteger]) at tempTargetLnDPoint[TrueArrayInteger] facing tempTargetLnDPoint[TrueArrayInteger]
                                Unit - Add Dummy Light (Neutral Hostile) to (Last created unit)
                                Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning tempTargetDarkLight[TrueArrayInteger]
                                Unit - Add a 1.50 second Generic expiration timer to (Last created unit)
                            Else - Actions
                                Set tempTargetDarkLight[TrueArrayInteger] = (Random unit from GroupHealorDie[TrueArrayInteger])
                                Game - Display to (All players) the text: (Name of tempTargetDarkLight[TrueArrayInteger])
                                Set tempTargetLnDPoint[TrueArrayInteger] = (Position of tempTargetDarkLight[TrueArrayInteger])
                                Unit - Create 1 Dummy Unit for (Owner of tempCaster[TrueArrayInteger]) at tempTargetLnDPoint[TrueArrayInteger] facing tempTargetLnDPoint[TrueArrayInteger]
                                Unit - Add Dummy Darkness (Neutral Hostile) to (Last created unit)
                                Unit - Order (Last created unit) to Orc Far Seer - Chain Lightning tempTargetDarkLight[TrueArrayInteger]
                                Unit - Add a 1.50 second Generic expiration timer to (Last created unit)
                        --------------------Leak fixing and time setting-----------
                        Set timeLeft[TrueArrayInteger] = (timeLeft[TrueArrayInteger] + 0.50)
                        Custom script:   call RemoveLocation (udg_PointLnD [udg_TrueArrayInteger] )
                        Custom script:   call RemoveLocation (udg_tempTargetLnDPoint [udg_TrueArrayInteger] )
                        Custom script:   call DestroyGroup (udg_GroupHealorDie [udg_TrueArrayInteger])

Yeah, while I have quite a bit of trigger experience, I made this after just a few looks at Flare's system. So it's a really easy system to work with.
 

GoGo-Boy

You can change this now in User CP
Reaction score
40
Wow.. Excactly what I need. I didn't read everything but I'm sure it works. I always used GUI but I tried to learn JASS because of the MUI thing, but this tutorial will come in handy when I'm going to make "some" spells :D

*wrong*

DO learn JASS. Honestly making stuff MUI in JASS is freaking easy :<
 

Flare

Stops copies me!
Reaction score
662
*wrong*

DO learn JASS. Honestly making stuff MUI in JASS is freaking easy :<

learning JASS takes time and effort, and this tutorial just helps people to make MUI spells without diving headfirst into JASS and everything associated.

also, if you want to discuss how easy it is to do stuff in JASS, could you do it somewhere else other than the topic that deals purely with GUI?
 

soulreaping

New Member
Reaction score
17
Very nice tutorial, but have you thought maybe explaining what is MUI first?

I'm sure there are a lot of new map makers, like i was, who have always heard this term but never knew what is its meaning.

If you'll add a 4-5 lines paragraph on what MUI is it'll be a much better tutorial and will have more audience.

Besides that, good tutorial +rep.
 

Hatebreeder

So many apples
Reaction score
380
2 Things:
This Tut is usefull for advanced GUI users, proberbly the best one out there. Just try to keep the tut simple (I kinda got lost at some point).

There is one thing I don't understand.
Why the hell don't you Jass/vJass?
I mean, it's much easier than having to go thru all this...
Also, I bet you can learn Jass/vJass in less than 2 Weeks... You seem to be an intelligent Guy ( You see, I learned Jass, and I realy am NOT intelligent. Thank god if I were :p ).

Tip: Make you use of the Jass Help Forum
 

Flare

Stops copies me!
Reaction score
662
I like using GUI (O RLY?), and I'm good with it and to be honest, would you rather do something you like doing, or learning stuff? Also, even though people (so far, you and Cohadar) seem to think I'm intelligent enough to learn JASS relatively easily, I have a VERY low learning capacity (if that's a correct term). I have tried to learn stuff, but JASS coding just baffles me (namely attachment systems like ABC). If I could learn to do things like a periodic movement trigger using locals, but without TT or KT2, I would be on my way (but I can't)

Also, take a look at post 16 (i think) in my Dark Spirits thread for some more info on the cons of me bothering to learn JASS.

I tried to keep the tutorial as simple as possible (well, maybe my standards are a bit high, I don't really know) but I tried to explain everything in reasonable detail, so people would understand why it's used, and how it makes stuff MUI

Why the hell don't you Jass/vJass?
This tutorial isn't for my use, I just wanted to pass on what I know to everyone else so they can use it too.

Thanks for the comments :)
 

Insane!

Shh I didn't edit this, go away.
Reaction score
122
There is one thing I don't understand.
Why the hell don't you Jass/vJass?
I mean, it's much easier than having to go thru all this...
Also, I bet you can learn Jass/vJass in less than 2 Weeks... You seem to be an intelligent Guy ( You see, I learned Jass, and I realy am NOT intelligent. Thank god if I were :p ).

Tip: Make you use of the Jass Help Forum

I finaly made breakthough with jass, but its freakin hard to learn. :(

and this gui mui is easy :D
 

Flare

Stops copies me!
Reaction score
662
Bump, any more comments?

At the moment, I'm working on a slightly more advanced example (creating a secondary dummy unit for the primary dummy unit [primary dummy unit being the one created in the casting trigger, secondary will be a periodic spawn]. It's not hugely relevant to the tutorial, but it's just showing a combination of MUI periodic events, and MUI wait avoidance [the periodic spawn is gonna be a meteor that deals damage at the moment it hits the ground, but damage is going to be triggered]).

Any suggestions on things that should be added to the tutorial, or any specific section that I should cover in more detail?

UPDATE: I've completed the spell that combines periodic event with wait avoidance, check the first post for more details.
 

Draphoelix

It's not the wintercold that's killing me
Reaction score
132
I used your tutorial with a spell but I couldn't make it in MUI. Do you mind if I PM you the spell so you can take a look at it?
 
General chit-chat
Help Users
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top