HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

The ways of MUI in GUI

08-28-2006, 09:00 PM#1
darkwulfv
This is my first tutorial, don't get angry here.

What is this?
This is about allowing your trigger enhanced spells to be MUI (multiinstanceable) when using GUI. MUI means that your triggered spells will work when they are used 2 more times at the same time, if they used variables. We all know that JASS is better than GUI when it comes to MUI, but for those of us who either don't know JASS or are just learning, this might come in handy. The reason why a spell must be MUI is because if more than one unit casts the spell at the same time, the variables will over write themselves at the wrong time, and bug up your spell.

Way #1
MUI can be achieved quite simply, however there are different methods for different situations. This first situation is if only one unit casts this spell. Period. In fact, I don't even have to show a trigger. This is becuase, if only one unit in the entire map casts this spell, it needn't be changed, because it doesn't need MUI!

Way #2
Let's say you have this situation.
More than one unit casts this spell in a map, but only one unit casts it per player.
You can achieve MUI here by using Global Variable Arrays, which I will show you how to do.
First: Open up your variable editor, and go make a variable like normal. Let's name it TutorialVariable, and it will be a unit.

Second: Put a check in the box next to Array. Then, make the Array Size the amount of players in your map. Let's set ours to 12.

Third: Make a trigger. Let's name our first one Example. It should look like this to begin with.
Trigger:
Example
Events
Conditions
Actions

Fourth: Set up your triggr for the spell. Let's say the spell name is Flaming Egg. I'm going to put in the action Create Unit Facing Angle, just as an example. Here's what your trigger should look something like:
Trigger:
Example
Collapse Events
Unit - A unit Begins the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Flaming Egg
Collapse Actions
Unit - Create 1 Footman for (Owner of (Triggering unit)) at (Center of (Playable map area)) facing Default building facing (270.0) degrees
Now, there is controversy over whether you should use A unit begins casting an ability, or A unit begins the effect of an ability. Choose whichever event works for your spell. The unit begins casting an ability event fires before mana cost and cooldown are applied, whereas A unit begins the effect of an ability fires after that. So if you're triggering the effect of an ability the second one would usually be appropriate.

Fifth: Here coimes the variable part! Let's say we need to set this unit to a variable. Use the Set Variable action, and insert our variable, TutorialVariable. But wait a second! There's an Index next to it. For this situation, set the index number to: (Player Number of(Ownerof Unit(Triggering Unit))), then set the value to Last Created Unit. (the value can also be for whatever you need it to be, this is all just an example) Our trigger should look like this now:
Trigger:
Example
Collapse Events
Unit - A unit Begins the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Flaming Egg
Collapse Actions
Unit - Create 1 Footman for (Owner of (Triggering unit)) at (Center of (Playable map area)) facing Default building facing (270.0) degrees
Set TutorialVariable[(Player number of (Owner of (Triggering unit)))] = (Last created unit)

Sixth: Proceed to finish your trigger. Our variable's index should always be what it was above, (Player number of (Owner of (Triggering Unit))), or whatever you set the Triggering Unit part to be.

Seventh: And your done!
Why this works? Because since only one unit uses this spell per player, it is indexed into that number. Therefor, it will only be changed by the same index number. That way, the variable won't overrite itself until need be.

Way #3
This works best if only one variable has to be changed. This should work for most any map for any number of castings. There is an action called Custom Script. You can use it to trick the editor into thinking ONE! (and only one) Global variable is a local variable (per trigger), which will not be overwritten by another running of the trigger at the same time.

First: Make your variable.

Second: The very first thing in your trigger should be custom script, which says: local (whatever variable type it may be) udg_(Variable name)
Continue with your trigger until you need to set the variable. Do that normally and use the variable as normal. However, make sure you null the variable using custom script at the end (set udg_(Variable name) = null) so it doesn't leak.
Here's an example of a finshed trigger, using this method.
Trigger:
Example
Collapse Events
Unit - A unit Begins the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Flaming Egg
Collapse Actions
Custom script: local unit udg_TutorialVariable
Unit - Create 1 Footman for (Owner of (Triggering unit)) at (Center of (Playable map area)) facing Default building facing (270.0) degrees
Set TutorialVariable = (Last created unit)
Unit - Kill TutorialVariable
Custom script: set udg_TutorialVariable = null

IMPORTANT NOTE: Do not use locals with If/Then/Else statements, or anything that makes a new function. This is because locals only work for the function they are declared in. if you want to use locals, just redeclare them.

I hope this comes in handy for people who aren't too good at JASS or don't know JASS at all.
BTW, I don't know how to get pictures of the variable editor, sorry if that's an inconvienience to anybody
08-29-2006, 03:34 AM#2
Vexorian
The event : "Unit - A unit Begins casting an ability " Is the devil, it happens before the unit spends mana/cooldown. In fact I am able to exploit it and cast spells for free if they are trigger enhanced and use that event, use Starts the effect of an ability instead
08-29-2006, 03:41 AM#3
darkwulfv
I did point out that it can go either way. I doubt 99% of people are going to know enough/think about it. However, I will change it for all intents and purposes. Anything else i should know about?
08-29-2006, 04:38 PM#4
darkwulfv
*bump*
err sorry mods and admins I'm just a little impatient :p
But uhh.. Is there anything this tutorial could improve on? Change? Add/Subtract?
09-10-2006, 06:16 PM#5
PitzerMike
Hey, this is pretty good, i like it.
And it covers pretty much all there is about the topic, congratulations!

*Approved*
09-10-2006, 07:17 PM#6
Daelin
I'd like to mention that the last method is quite tricky and should be explained more in detail than that. There are some seirous problems and when using the locals in loops or "pick up every unit"'s or "wait for condition" or similar codes which create a separate function, you will end up with LOADS of errors.

Even though the method solving this problem is very stupid especially for someone using JASS, here is the thing:

1. Create the local like always
2. Just before the structure using a separate function store the local into a temporary global.
3. Into the structure first thing to do is create the local and give it the value of the temporary global.

Voila, problem solved!

Edit: Oh, and the fact that the spell is cast only by a single unit on the map, doesn't make it multiinstanceable. It is wrong to say that. It just does NOT REQUIRE to be MUI.

~Daelin
09-10-2006, 08:00 PM#7
PitzerMike
Oh yes, I've edited out the wording error you pointed out, Daelin.
09-11-2006, 05:06 AM#8
Karawasa
Quote:
Originally Posted by Daelin
I'd like to mention that the last method is quite tricky and should be explained more in detail than that. There are some seirous problems and when using the locals in loops or "pick up every unit"'s or "wait for condition" or similar codes which create a separate function, you will end up with LOADS of errors.

Even though the method solving this problem is very stupid especially for someone using JASS, here is the thing:

1. Create the local like always
2. Just before the structure using a separate function store the local into a temporary global.
3. Into the structure first thing to do is create the local and give it the value of the temporary global.

Voila, problem solved!

Edit: Oh, and the fact that the spell is cast only by a single unit on the map, doesn't make it multiinstanceable. It is wrong to say that. It just does NOT REQUIRE to be MUI.

~Daelin

Can you give me example code to make Locals work in an if/then statement? I am having troubles with it. Particularly, if the CONDITIONS of the if/then statement use the local.
09-11-2006, 06:12 AM#9
Daelin
Well... it's something like this.

Edit: Crap, it doesn't work for condition functions because I simply don't have where to set the local. :( For anything else it would go like this:

Trigger:
Custom Script: local unit udg_targ
set targ = (Target Unit of Ability Being Cast)
Wait for 1.00 seconds
set temp = targ
Collapse Unit Group - Pick Up Every Unit within 500 range from (Triggering Unit) and do actions
local unit udg_targ = udg_temp
[..] //do whatever

I really doubt it is possible to make looping conditions MUI. Sorries.

Edit: Found how to make the "Wait for condition" stuff. It works if doing something like this:

Trigger:
For each Loop_Variable from 1 to 1, do (Actions)
Collapse Loop - Actions
Collapse If (All Conditions are True) then do (Then Actions) else do (Else Actions)
Collapse If - Conditions
CONDITION_STOP_LOOP
Then - Actions
Collapse Else - Actions
Set Loop_Variable = 0
Wait x seconds

Replace x with the delay between checking if condition to exit the loop has become true. All trigger's locals work in this loop because it is created in the initial trigger. This way, you can make "Wait for condition" work with the locals in GUI trick.

I still need to think about locals in conditions though...

~Daelin
09-13-2006, 12:06 AM#10
darkwulfv
yay, approved at last. Haven't been on lately, kinda gave up modding until i can get Warcraft onto my new computer. So is the error Daelin pointed out fixed? I did forget to mention that in If/Then/Else you would have to redeclare the variable. I forgot about that completely. *do'h* I did have problems trying to use locals with If/Then/Else. Thanks for pointingf that out Daelin, I'll add that now.
09-13-2006, 12:08 PM#11
Daelin
Wulf... I actually explained how the stuff works in some cases. If you have just a pick up every unit you can first initialize the local to a global, then in the pick up just recreate the local and give it the variable of the global.

~Daelin
09-14-2006, 09:11 AM#12
Krelian
Acording to this tutorial, the "local variable" method is the best one, right?
I had already found the 2nd method by myself but i had the problem that Neutral Hostile units couldn't had the ability becouse they dont have player number. With method 3 that would be solved right?

I have 1 question though... I didn't understand very good the last part:

Quote:
ou can use it to trick the editor into thinking ONE! (and only one) Global variable is a local variable, which will not be overwritten by another running of the trigger at the same time.

This means... only 1 ability in the map can have this trick? Or i can apply this to only 1 variable in the whole map?... im confused....
09-14-2006, 09:15 AM#13
Daelin
Quote:
Originally Posted by Krelian
I had already found the 2nd method by myself but i had the problem that Neutral Hostile units couldn't had the ability becouse they dont have player number.

They do... neutral players are between 13 and 16 in GUI. In JASS players are 0-15.
09-16-2006, 09:17 PM#14
darkwulfv
Quote:
This means... only 1 ability in the map can have this trick? Or i can apply this to only 1 variable in the whole map?... im confused....

Thank you for reading my tutorial :D.
What I mean is, you can only use this trick once per trigger. Probably should clarify on that. Thanks for pointing that out for me.
10-09-2006, 11:52 PM#15
Krelian
I got a problem using method 3 plus daelin advice...

It says "expected a endloop"

Trigger:
Bind
Collapse Events
Unit - A unit Starts the effect of an ability
Collapse Conditions
(Ability being cast) Equal to Bind
Collapse Actions
Custom script: local unit udg_SkillsTarget
Set SkillsTarget = (Target unit of ability being cast)
Set random_pa_bind = (Random integer number between 2 and 5)
Set tempunit = SkillsTarget
Collapse For each (Integer loop01) from 2 to random_pa_bind, do (Actions)
Collapse Loop - Actions
Custom script: local unit udg_SkillsTarget = udg_tempunit
Wait 2.00 seconds
Unit - Cause (Triggering unit) to damage SkillsTarget, dealing (Real((Strength of (Triggering unit) (Include bonuses)))) damage of attack type Normal and damage type Normal
Custom script: set udg_SkillsTarget = null



(it is supposed to damage the target of Bind 2 to 5 times for the Strength of the caster.)