1. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  2. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  3. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  4. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  5. The results are out! Check them out.
    Dismiss Notice
  6. The poll for Hive's 12th Concept Art Contest is up! Go cast your vote for your favourite genie!
    Dismiss Notice
  7. The raddest synthwave tracks were chosen - Check out our Music Contest #12 - Results and congratulate the winners!
    Dismiss Notice
  8. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Chapter 2 - Dynamic Effects (GUI)

Discussion in 'Trigger (GUI) Editor Tutorials' started by Daelin, Nov 26, 2006.

  1. Daelin

    Daelin

    Joined:
    Jul 20, 2004
    Messages:
    3,111
    Resources:
    41
    Models:
    22
    Icons:
    3
    Tutorials:
    16
    Resources:
    41
    Table of Contents
    1. Introduction
    2. Timers
    3. First dynamic effect – orbiting
    4. Knockbacking
    5. Turn static shapes to dynamic effects
    6. Tips and tricks

    1. Introduction
    This tutorial is part of a sequel. Before going on with reading this tutorial I suggest you first read chapter 1. I am not going to retake all the ideas mentioned there since it would be pointless.

    In this tutorial we will continue with the shapes learnt in the previous tutorial (circle, line etc.) and develop certain effects made similarly but this time dynamically. The effect is not simply created on the ground and end of story. We will actually learn how to move units on their “path” (for example make an unit move in circles around another, concept also known as orbiting) or even make some effects created previously “move”.

    2. Timers
    Before we will actually study the path of the movement, I will stop at a very important concept: the concept of timers. Timers are like a chronometer. They have an “expiration time” which is a value given by the user during the creation of the timer. When starting the timer, it will have a “remaining time” which is actually a value starting from the “expiration time” and its value lowers until it reaches 0 (real time value). The most used event related to timers is the “timer expires”. It occurs when a certain timer’s “remaining time” reaches 0.

    Why would we want to use timers? Because normally when moving units, we will have a waiting period between two changes of position. This waiting period can be really tricky, because it is related mostly to how the human eyes percepts the images displayed on the screen. We give the impression of “movement” by doing successive position changes to the element (in this case, the unit). If the waiting period is too big so that the human eye can notice the pauses, the animation will look jumpy. However, if the waiting period is too small then the processor needs to make a lot of calculations, for each position change follows an exact set of operations. It is important to find the best waiting period.

    I present you below 5 animations with different waiting periods (0; 0.04; 0.07; 0.15; 0.27 - from left to right). Decide which one looks the best:

    TimerDuration_0.gif TimerDuration_0-1.gif TimerDuration_0-2.gif TimerDuration_0-3.gif
    TimerDuration_0-4.gif

    Ok, we have two horrible extremes. Value of 0 looks so jumpy that it’s not even worth mentioning it. 0.15 is already slow and 0.27 is far too slow. You agree to me when I say that somewhere around 0.04, 0.07 is the right value. I’d go either for 0.035 or 0.05. It depends on the type of effect, how fast you move the units and so on.

    So why do we need timers? The wait function works for values down to 0.01, right? Actually, it’s not like this. I did not choose the value of 0.27 randomly. Wait function is not that great. Whenever the action is used with a value lower than 0.27, it will be treated as if it were equal with 0.27. Blizzard imposed this limit, so they might have had their reasons. However, this is extremely inconvenient for us.

    The solution is clear: we can use a timer. However, there is an even better solution. There is a way to attach a timer to a trigger by using the event “Time - Every x seconds of game time”. Setting x to 0.035, 0.05 or the value you want, you can execute a series of actions (moving the unit(s)) multiple times. How to control when the actions to take place, and when not to? Well, really simple! Initially turn the trigger off. When you want to start executing the actions (moving the unit) turn the trigger on. When you want to stop the effect destroy it.

    There are some limitations though. Using this method will make your code non-MUI. You cannot have multiple active effects at the same time unless you make a separate repetitive function for each, with a separate group in which you keep the effects.

    3. First dynamic effect – orbiting
    Okay, as I said before, the simplest dynamic effect is orbiting, more specifically having an unit rotate around a point (or another unit). I trust that by now you are familiar with the process of creating one static effect and so I don’t have to explain you that. I will focus on the process of strictly moving the unit. I simply stored it into a variable, called “Orbiting_Projectile”. Now moving it is like creating a circle, yet done inside a timer. Let’s study the process:

    Orbiting.jpg

    This is obviously extremely confusing if not interpreted correctly. You do not have multiple objects in the image. You have a single object rotating around P. All the points represent separates positions. The orange line represents its trace. It is clear that the distance between the center and the positions is equal, just that the angle increases with each. The red points are identical with the orange ones.

    Note: In warcraft 3, there is no difference between 30 degrees and 390. They are interpreted as the same angle so you do not have to worry about substracting once you get over 360. And nevertheless, “Angle between points” does not return values greater than or equal with 360.

    I will write you completely this code since it is probably something new and may be difficult for you. Some more variables you need a point variable (CENTER) in which to store the center and a variable in which to store your effect unit (Effe_Unit). Here are the two triggers needed to make things work. Keep in mind that I did not take care of creating the object and the variables. This will greatly modify in different situations.

    • Initial Trigger
    • ---This trigger starts and ends the orbitation---
    • Actions
      • Trigger - Turn On Movement Trigger
      • Wait 5.00 seconds
      • Trigger - Turn Off Movement Trigger

    • Movement Trigger (initially off)
    • ---This trigger executes the orbiting until disabled---
    • Events
      • Time - Every 0.04 seconds of game time
    • Actions
      • Unit - Move Effe_Unit instantly to (CENTER offset by (Distance between CENTER and (Position of (Effe_Unit))) towards ((Angle from CENTER to (Position of (Effe_Unit))) + 5.00) degrees)


    You can modify the wait duration depending on how much you want to orbit the effect unit. If you want to stop the orbiting when a spell ends for example, disable the trigger that way. The Initial Trigger can be really flexible.

    Note: It’s pretty clear that orbiting an unit around another unit means changing CENTER with (position of target).
    Note2: Depending on whether you add or subtract from the current value of the angle, you can actually determine the way the unit moves. Increasing the angle makes if move counter-clockwise (trigonometric) while substracting makes it move clockwise (anti-trigonometric).
    Challenge: Create a circle similar to the one from chapter 1 and then spin the whole circle around an unit.

    4. Knockbacking
    This effect does not require any additional special units, yet can be used for some spells (even for effects… does shockwave ring a bell?). It is similar to creating a line just that instead of creating multiple units, you gradually change the distance between the two units while leaving the angle intact. To change the effect, you should go like above, like this:

    • Movement Trigger (initially off)
    • ---This trigger executes the orbiting until disabled---
    • Events
      • Time - Every 0.04 seconds of game time
    • Actions
      • Unit - Move Effe_Unit instantly to (CENTER offset by (Distance between CENTER and (Position of (Effe_Unit))+5.00) towards ((Angle from CENTER to (Position of (Effe_Unit)))) degrees)


    There are two ways of disabling it. First is to disable it after a period of time. That way you can determine the final distance relatively by calculating it mathematically based on the wait period, the frequency of the timer and the increase range of the distance with each timer cycle. Formula is this:
    Code (Text):
    Wait period = Timer_Frequency*Final Range/Ration Range
    For example, to acquire a final range of 800 with the options above, we apply the formula like this:
    Code (Text):
    Wait period = 800*0,04/5=6,4
    Hmm… 6.4 is quite a lot for a range of 800. It is clear that in this case, you should increase the distance dramatically. Experiment with values and see what you get.

    The second variant is to simply disable the trigger if the unit has reached the range needed. That way the result will always be the one required, even if you calculate the distance based on the other unit’s position.

    5. Turn static shapes to dynamic effects
    It is possible to make the shapes from the last chapter move. However, as we come to this, we have to study two types of dynamic shapes:

    a) Channeling – the movement of the effect has to be continuous. It would be an effect that repeats on and on until, for example, the spell ends.
    b) One-shot – these type of dynamic effects happen once (example: shockwave) and then they are gone.

    It is very important to understand how both the effects actually work. Then you will be able to choose and code whichever you want. The problem is the “planning”.

    The vital difference between these two types of effects is their path. Channeling effects will have a cyclic path. Think at a formula one track. The start point must become the end point, regardless how complicated the trace is. It’s the same here too. Our effect is the car. It moves on a certain path until the spell for example ends. The important element in a cyclic effect is the center. All such effects will normally require a center, no matter how complicated they are.
    A good example of cyclic path is a circle. A bad example is a line or semi-linear curve (example: a spiral’s spire). You can also turn the line path into a cycle but you will need to move the effect back and forward on it. This kind of effect is used in very few cases.

    CyclicShapes.gif

    However, this doesn’t mean that one-shot effects do not have their purpose and that they are not useful. There are spells with instant effects that either have a one-shot missile even multiple ones. Sometimes missiles need to be generated from multiple effects around the caster. Other times you need to manually move the missile from the caster to the target. It is important to know about these effects.
    We now go back to the spiral effect I presented you in the previous tutorial. There was once a spell (can’t remember its name) made by Daminon which created a dynamic spiral. The spiral would be made out of lightning and it would come from within the center (caster) and spread around it. If you usually have such instant effects made out of multiple units, you may want to even give up units and use special effects that you create and destroy immediately. Most effects will first end their animation before disappearing if destroyed, so the destruction will only ensure that once the effect has finished its visual eye-candy, it is gone both as a model and an object.

    The trick here is to use the timer for the duration between two elements of a spire. I will remind you that the spiral is made out of multiple concentric circles with a phase difference called deviation angle. The trick is to create these circles one after another at a short time delay between each other. That way it will look as if the spiral is spreading from the inside to the outside. You can also use units if you wish, but then make sure you add an expiration timer to them big enough so that the spiral does not look sectioned, and small enough not to turn the spiral into a static effect.
    Here are some tips for the code. It would be a bit too easy and non-didactic to give you everything with the spoon. Consider this code a challenge through which you can prove your skills.

    1. You will need to keep into a variable the number of the current concentric circle. Otherwise you cannot determine which the current step in the timer trigger is. Do not forget to increment it at each execution of trigger’s actions.
    2. Use the formula from the first tutorial to create the spiral. Instead of a loop which determines the number of the concentric circle, you will need to use the variable mentioned above.
    3. Watch out for endless timers! Disable the trigger after you have reached a number of concentric circles or else you’ll be in trouble.

    6. Tips and tricks
    a) Unit Groups – groups are essential for dynamic effects. Arrays are less practical when it comes to manipulating multiple units in order to dynamically change their position. Unit Groups were designed to make masses of units easier to manipulate.
    b) Multi-instance – The problem can no longer be solved with Custom Script locals trick, considering that you need to transfer the group and perhaps other values to another trigger. Keep in mind that you are using a timer, and not a trigger!

    This trick is a bit longer since I will try to teach you how to make your effects multi-instanceable.
    Warning: Complex pieces of code and concepts are used here. I do not expect everyone to understand this but if you feel that this is just too much for you, try not to use your effects for non-hero spells or just use them for cinematics and other purposes.

    The only way to make the timers work in multiinsceanbility is to actually use local variables to store the timers. However, the problem doesn’t end here, because transferring objects/values to timers’ code through original GUI (unless you’re using global variables) is impossible! Since global variables ruin the MUI, we have to reconsider some other variant.

    I recommend that you download this tool. It has everything you need, from allowing you to create local timers easily to linking values and objects to them.

    If you have difficulties with this tool or with dynamic effects in general, post here and I will provide more information about it!

    ~Daelin