- Joined
- May 15, 2008
- Messages
- 147
Jump GUI Tutorial: Fully MUI/MPI using "custom value"
NOTE: This tutorial requires some basic knowledge of GUI, triggers and variables if you are new to the WE (world editor) I suggest you read some basic tutorials first!
Here is the link with the map posted in the
Spells Section of the Hive: JumpGUITutorial
IDEA
My general idea was to create a MUI/MPI Jumping System just in GUI. Due the "bad" reputation of GUI, it's problems with MUI/MPI due the usage of global variables (dunno what variables are? Variables) and the famous wait action, I got the idea for creating the MUI/MPI jump system that is easy to implement, and even uses the less number of variables that would normally use the standard Jump Spell.
OK so the general concept is this: what does each jump spell need, what is the jump spell? Jump Spell is the simple knockback that changes flying height of the unit so it looks like it's jumping. With the proper unit animations the results are fascinating. My idea is to save the values of parameters used by the spell in the custom value of the unit that is performing the jump and here it is how:
Jump Spell and custom value
Here is the general idea of what i thought under the "save the values of parameters used by the spell in the custom value of the unit"
NOTE: the current triggers are for the point target type ability, I based mine out of the W3 standard "Channel" ability.
Each Jump Spell has the following parameters:
-Angle - represents the angle between unit and point at which it is jumping, a.k.a. the direction in which the unit is jumping.
-Distance - represents the distance the unit is moving per execution of the moving trigger not the overall distance of the ability (example: if the ability distance (casting range) is 700 and number of executions is 20, it means that the parameter distance is 700/20 = 35, pure math)
-Unit - the unit that is jumping duh.
-Location (Point) - the location at which the unit is jumping and the location from which unit has started jumping.
-Execution Counter - which calculates the number of the times the moving trigger has runned for the unit. When trigger runs our unit moving(knockback) and that makes our unit looks like its jumping.
Based on the parameters above for the standard jump ability we would need 7 variables: Unit (jumping unit), 2x Integer Variable (to save the execution limit and execution counter), Real Variable (for distance), 2x Point Variables (to save the locations) and one Timer Variable.
Instead using the custom value system we will use only 6 variables and our system will be FULLY MUI/MPI!!! Here is why: We will save the parameters into our unit using the Unit - Set Custom Value action. So once added to the unit its custom value can be considered as a string(text) also, can't it? And sooOO that's the catch; by adding the parameter through the conversion of string to integer and vice verse we can save and access to our parameters with ease. I know it's a little complicated now but I'll explain it using the graphic:
Custom Value Parameter graphic

OK I know it's still confusing but just read it a few more times and you will get it. Let's say we set the custom value of unit to 22937. In the numeric system it's a number, but in a string system its a text, and we can access to each part of that text using the function Substring(String, #,#) where # represents the number of the character position we want to access. So as I said if we have the custom value of our unit set to 22937, in the string system it is like this:
2 2 9 3 7
1 2 3 4 5
So if we for an exapmle want to access to "93" part of the 22937 we will convert our integer 22937 into string and use function Substring(String(22937), 3, 4). If we on the other hand want to get the "229" from our integer we will convert it to string and use the function Substring(String(22937), 1, 3). If we by any chance want to get the "7" we'll just use the conversion and Substring(String(22937), 5, 5), get it? If you don't read it a few times it will become more clear with each reading!
So I'm going on, now that we know how the accessing to our values goes its time to move on our Jump System. Since the custom value of unit can have a maximum number of 9 digits, if you add tenth digit it turns into number "2" dunno why, it's one of those standard Warcraft mysteries, lol. Also if you have more than 9 digits in the custom value it will bug (shows some weird numbers you didn't added at all). So, the Jump System, look again:
Custom Value Parameter graphic

You remember the talk about parameters the Jump abilities use? Here are the 3 parameters that we will save into our unit's custom value, I'll explain each parameter separately (why, how,...etc.)
Angle - As we said earlier it represents the angle between the unit and the point at which unit is jumping, a.k.a. it is the direction in which the unit will be jumping. When calculated using the Math - Angle Between Points function the angles come in manner of 1 to 180 degrees and -1 to -180 degrees, so we have positive and negative integer value. That is why we use 4 digits for the angle parameter, since we need 3 digits for the maximum value of angle which is 180 (either for + or -), and one digit so we can store if it is the positive or negative. Oh yes one more thing, if you for example set the units custom value to 003471, it's custom value will be 3471, so any kind of zero's before the other numbers are deleted. So in the Substring(String, #,#) system we will set at the position Substring(Custom Value(Parameters), 1,1) the digit that will represent the positive or negative value. I'm using number 1 for positive (+) values (angles):
Custom Value Parameter graphic

and digit 2 for negative (-) values (angles):
Custom Value Parameter graphic

Why is this important?? By setting this values in front on the position (1,1) we override the thing that if we have an angle that is less than three digits, example 60 degrees, we must enter it into the custom value like 060. If there were no digits before 0, the custom value will be set to 60 and that will cause bug since we will get some other angle than the one we need. So if we have an angle of -60 degrees our custom value parameter will look like this: 2060.
Distance - Earlier mentioned the distance is not the overall distance of the spell (casting range - the max range of the ability or casted range - the distance at which the spell has been cast), its the distance which the unit is moved per execution of moving trigger, and it is mathematically calculated using the formula: (casted range) / (num of executions) = (distance). So if casted range ii let's say 600 and num of executions is 25 distance is 600/25=24. For that also we need three digits, mostly the distance will be one or two digits number, but if someone wants an overmap jump, it can become three digit number. Also here we need to add zeros in front of the value if its less than three number, so if the distance is 24, it is 024 in the custom value parameter or if it is 7 it will be 007.
Execution Counter - here we store the number of times the moving trigger is runned, which is used to detect the end of jump, animating the jumping unit, and lowering it's height. It starts from 0 and goes +1 whenever trigger is executed and when it reaches the Execution Limit it runs the end of the jump.
Now that these parameters are cleared, let us proceed to the other parameters. We'll need only 6 variables:
-Unit Group Variable - inside we store all of the jumping units.
-Integer Variable - so we can calculate the integers inside we don't store anything in this variable.
-Real Variable - so we can calculate the real's inside we don't store anything in this variable.
-Point Variable - to move the unit's and remove location leeks
-Timer Variable - for the trigger execution trigger that performs all the thing about jump (heightening, animation, lowering, end...)
-String Variable - So we can perform conversions, it will be more clearer when we come to the real triggers.
Now that the base idea is clear we'll proceed to the trigger part where I'll explain each action separately.
Jump Triggers
So believe it or not we will only need 2 triggers, 2 abilites and 6 variables to make our GUI Jump ability fully MUI/MPI using the custom value and conversion of integer's to string and vice verse. Firstly, create these Variables:
-JumpGUIGroup (Unit Group, Empty Unit Group)
-JumpGUIInt (Integer, 0)
-JumpGUIReal (Real, 0)
-JumpGUIPoint (Point, none)
-JumpGUIString (String, Empty String)
-JumpGUITimer (Timer)

Abilities:
-Jump (GUI Tutorial) - based of the Warcraft 3 "Channel" ability as point target ability.
-Flight Trick - Ability based out of Spell Book in which we add Medivh's Crow Form ability, and we disable the Flight Trick so we can add this ability to jumping unit and alter it's flying height.
Now that we've made our variable it is time for us to create our triggers. I'll post the whole triggers here and than proceed to the explanation of the same. I called the first trigger Jump GUI and here is how it look's like:
-
Jump GUI
-
Events
-
Unit - A unit Starts the effect of an ability
-
-
Conditions
-
(Ability being cast) Equal to Jump (GUI Tutorial)
-
-
Actions
-
Set JumpGUIReal = (Angle from (Position of (Triggering unit)) to (Target point of ability being cast))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIReal Less than 0.00
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + 2)
-
-
Else - Actions
-
Set JumpGUIString = (JumpGUIString + 1)
-
-
-
Unit - Set the custom value of (Triggering unit) to (Integer(JumpGUIString))
-
Set JumpGUIInt = (Abs((Integer(JumpGUIReal))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 10
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (00 + (String(JumpGUIInt))))
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 100
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (0 + (String(JumpGUIInt))))
-
-
Else - Actions
-
Set JumpGUIString = (JumpGUIString + (String(JumpGUIInt)))
-
-
-
-
-
Unit - Set the custom value of (Triggering unit) to (Integer(JumpGUIString))
-
Set JumpGUIReal = (Distance between (Position of (Triggering unit)) and (Target point of ability being cast))
-
Set JumpGUIInt = (Abs((Integer((JumpGUIReal / 26.00)))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 10
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (00 + (String(JumpGUIInt))))
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 100
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (0 + (String(JumpGUIInt))))
-
-
Else - Actions
-
Set JumpGUIString = (JumpGUIString + (String(JumpGUIInt)))
-
-
-
-
-
Unit - Set the custom value of (Triggering unit) to (Integer(JumpGUIString))
-
Unit Group - Add (Triggering unit) to JumpGUIGroup
-
Unit - Add Flight Trick to (Triggering unit)
-
Animation - Change (Triggering unit) flying height to 225.00 at 350.00
-
Unit - Turn collision for (Triggering unit) Off
-
Countdown Timer - Start JumpGUITimer as a Repeating timer that will expire in 0.03 seconds
-
Set JumpGUIPoint = (Position of (Triggering unit))
-
Special Effect - Create a special effect at JumpGUIPoint using Abilities\Weapons\AncientProtectorMissile\AncientProtectorMissile.mdl
-
Special Effect - Destroy (Last created special effect)
-
Custom script: call RemoveLocation(udg_JumpGUIPoint)
-
Set JumpGUIReal = 0.00
-
Set JumpGUIInt = 0
-
Set JumpGUIString = <Empty String>
-
-
-
Jump GUI Timer
-
Events
-
Time - JumpGUITimer expires
-
-
Conditions
-
Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(JumpGUIGroup is empty) Equal to True
-
-
Then - Actions
-
Countdown Timer - Pause JumpGUITimer
-
-
Else - Actions
-
-
Unit Group - Pick every unit in JumpGUIGroup and do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 1, 1)))) Equal to 2
-
-
Then - Actions
-
Set JumpGUIInt = (Integer((- + (Substring((String((Custom value of (Picked unit)))), 2, 4)))))
-
-
Else - Actions
-
Set JumpGUIInt = (Integer((Substring((String((Custom value of (Picked unit)))), 2, 4))))
-
-
-
Set JumpGUIPoint = ((Position of (Picked unit)) offset by (Real((Substring((String((Custom value of (Picked unit)))), 5, 7)))) towards (Real(JumpGUIInt)) degrees)
-
Unit - Move (Picked unit) instantly to JumpGUIPoint, facing (Real(JumpGUIInt)) degrees
-
Custom script: call RemoveLocation(udg_JumpGUIPoint)
-
Unit - Set the custom value of (Picked unit) to (Integer(((Substring((String((Custom value of (Picked unit)))), 1, 7)) + (String(((Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) + 1))))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Greater than or equal to 1
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Less than 3
-
-
Then - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
Or - Any (Conditions) are true
-
Conditions
-
(Unit-type of (Picked unit)) Equal to Alchemistycal Jumer
-
(Unit-type of (Picked unit)) Equal to Pit Jumper Lord
-
(Unit-type of (Picked unit)) Equal to Warden Jumperess
-
-
-
-
Then - Actions
-
Custom script: call SetUnitAnimationByIndex(GetEnumUnit(),6)
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Unit-type of (Picked unit)) Equal to Bladejumper
-
-
Then - Actions
-
Custom script: call SetUnitAnimationByIndex(GetEnumUnit(),2)
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Unit-type of (Picked unit)) Equal to Shadow Jumper
-
-
Then - Actions
-
Custom script: call SetUnitAnimationByIndex(GetEnumUnit(),11)
-
-
Else - Actions
-
-
-
-
-
-
Animation - Queue (Picked unit)'s stand animation
-
-
Else - Actions
-
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Equal to 17
-
-
Then - Actions
-
Animation - Change (Picked unit) flying height to 0.00 at 400.00
-
-
Else - Actions
-
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Greater than or equal to 26
-
-
Then - Actions
-
Animation - Change (Picked unit) flying height to 0.00 at 4000.00
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
((Picked unit) is dead) Equal to False
-
-
Then - Actions
-
Unit - Remove Flight Trick from (Picked unit)
-
-
Else - Actions
-
-
Unit Group - Remove (Picked unit) from JumpGUIGroup
-
Unit - Turn collision for (Picked unit) On
-
Unit - Set the custom value of (Picked unit) to 0
-
-
Else - Actions
-
-
-
-
-
Explanation
Jump GUI trigger
So let's go over the triggers action by action. I'll start with the Jump GUI trigger first.-
Events
-
Unit - A unit Starts the effect of an ability
-
-
Conditions
-
(Ability being cast) Equal to Jump (GUI Tutorial)
-
-
Set JumpGUIReal = (Angle from (Position of (Triggering unit)) to (Target point of ability being cast))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIReal Less than 0.00
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + 2)
-
-
Else - Actions
-
Set JumpGUIString = (JumpGUIString + 1)
-
-
-
Unit - Set the custom value of (Triggering unit) to (Integer(JumpGUIString))
-
Set JumpGUIInt = (Abs((Integer(JumpGUIReal))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 10
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (00 + (String(JumpGUIInt))))
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 100
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (0 + (String(JumpGUIInt))))
-
-
Else - Actions
-
Set JumpGUIString = (JumpGUIString + (String(JumpGUIInt)))
-
-
-
-
-
Unit - Set the custom value of (Triggering unit) to (Integer(JumpGUIString))
-
Set JumpGUIReal = (Distance between (Position of (Triggering unit)) and (Target point of ability being cast))
-
Set JumpGUIInt = (Abs((Integer((JumpGUIReal / 26.00)))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 10
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (00 + (String(JumpGUIInt))))
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
JumpGUIInt Less than 100
-
-
Then - Actions
-
Set JumpGUIString = (JumpGUIString + (0 + (String(JumpGUIInt))))
-
-
Else - Actions
-
Set JumpGUIString = (JumpGUIString + (String(JumpGUIInt)))
-
-
-
-
-
Unit - Set the custom value of (Triggering unit) to (Integer(JumpGUIString))
-
Unit Group - Add (Triggering unit) to JumpGUIGroup
-
Unit - Add Flight Trick to (Triggering unit)
-
Animation - Change (Triggering unit) flying height to 225.00 at 350.00
-
Unit - Turn collision for (Triggering unit) Off
-
Countdown Timer - Start JumpGUITimer as a Repeating timer that will expire in 0.03 seconds
-
Set JumpGUIPoint = (Position of (Triggering unit))
-
Special Effect - Create a special effect at JumpGUIPoint using Abilities\Weapons\AncientProtectorMissile\AncientProtectorMissile.mdl
-
Special Effect - Destroy (Last created special effect)
-
Custom script: call RemoveLocation(udg_JumpGUIPoint)
-
Set JumpGUIReal = 0.00
-
Set JumpGUIInt = 0
-
Set JumpGUIString = <Empty String>
Jump GUI Timer trigger
-
Events
-
Time - JumpGUITimer expires
-
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(JumpGUIGroup is empty) Equal to True
-
-
Then - Actions
-
Countdown Timer - Pause JumpGUITimer
-
-
Else - Actions
-
-
Unit Group - Pick every unit in JumpGUIGroup and do (Actions)
-
Loop - Actions
-
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 1, 1)))) Equal to 2
-
-
Then - Actions
-
Set JumpGUIInt = (Integer((- + (Substring((String((Custom value of (Picked unit)))), 2, 4)))))
-
-
Else - Actions
-
Set JumpGUIInt = (Integer((Substring((String((Custom value of (Picked unit)))), 2, 4))))
-
-
-
Set JumpGUIPoint = ((Position of (Picked unit)) offset by (Real((Substring((String((Custom value of (Picked unit)))), 5, 7)))) towards (Real(JumpGUIInt)) degrees)
-
Unit - Move (Picked unit) instantly to JumpGUIPoint, facing (Real(JumpGUIInt)) degrees
-
Custom script: call RemoveLocation(udg_JumpGUIPoint)
-
Unit - Set the custom value of (Picked unit) to (Integer(((Substring((String((Custom value of (Picked unit)))), 1, 7)) + (String(((Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) + 1))))))
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Greater than or equal to 1
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Less than 3
-
-
Then - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
Or - Any (Conditions) are true
-
Conditions
-
(Unit-type of (Picked unit)) Equal to Alchemistycal Jumer
-
(Unit-type of (Picked unit)) Equal to Pit Jumper Lord
-
(Unit-type of (Picked unit)) Equal to Warden Jumperess
-
-
-
-
Then - Actions
-
Custom script: call SetUnitAnimationByIndex(GetEnumUnit(),6)
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Unit-type of (Picked unit)) Equal to Bladejumper
-
-
Then - Actions
-
Custom script: call SetUnitAnimationByIndex(GetEnumUnit(),2)
-
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Unit-type of (Picked unit)) Equal to Shadow Jumper
-
-
Then - Actions
-
Custom script: call SetUnitAnimationByIndex(GetEnumUnit(),11)
-
-
Else - Actions
-
-
-
-
-
-
Animation - Queue (Picked unit)'s stand animation
-
-
Else - Actions
-
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Equal to 17
-
-
Then - Actions
-
Animation - Change (Picked unit) flying height to 0.00 at 400.00
-
-
Else - Actions
-
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer((Substring((String((Custom value of (Picked unit)))), 8, 9)))) Greater than or equal to 26
-
-
Then - Actions
-
Animation - Change (Picked unit) flying height to 0.00 at 4000.00
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
((Picked unit) is dead) Equal to False
-
-
Then - Actions
-
Unit - Remove Flight Trick from (Picked unit)
-
-
Else - Actions
-
-
Unit Group - Remove (Picked unit) from JumpGUIGroup
-
Unit - Turn collision for (Picked unit) On
-
Unit - Set the custom value of (Picked unit) to 0
-
-
Else - Actions
-
Final Note
This is just something I thought of and tried to make it since it's totally unusual and shows some of the advanced GUI techniques, since I use custom value for many things in my maps. I think this is a good way to introduce our GUI-ers of medium and beginner level into more advanced GUI feats. I know that this system can never be in rank with those Jass Jump systems, but it is easy to implement in the map that won't have 1000 units jumping around at once, I'm sure that it will be useful to many beginners out there, as well as to the pros.
