• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Spell] Need some help with spells

Status
Not open for further replies.
Level 2
Joined
Jun 17, 2012
Messages
17
Hi

I'm wondering if you guys know of a better way to put this together. Or have any tips to improve it.

  • Fireball
    • Events
      • Unit - Hero (Mage)<gen> Beins casting an ability
    • Conditions
      • (Ability being cast) Equal to Q (Mage))
    • Actions
      • Trigger - Turn off(This trigger)
      • Unit create 1 Fireball for Player 1 (Red) at (Position of (Triggering unit)) facing (Facing of(Triggering unit)) degrees
      • Unit - Order (Last created unit) to Attack(Target unit of ability being cast)
      • Special Effect - Create a special effect at(position of(Last created unit)) using Doodads\Cinematic\FirePillarMedium\FirePillarMedium.mdl
      • Wait 0.25 seconds
      • Special Effect - Create a special effect at(position of(Last created unit)) using Doodads\Cinematic\FirePillarMedium\FirePillarMedium.mdl
      • Wait 0.25 seconds
      • Special Effect - Create a special effect at(position of(Last created unit)) using Doodads\Cinematic\FirePillarMedium\FirePillarMedium.mdl
      • Wait 0.25 seconds
      • Special Effect - Create a special effect at(position of(Last created unit)) using Doodads\Cinematic\FirePillarMedium\FirePillarMedium.mdl
      • Wait 0.25 seconds
      • Trigger - Turn on(This trigger)
The idea behind this is to have a fireball shot forward from the front of the casting unit and incinerate the ground it travels over. and finally hit the target and deal damage.

So i began with creating a dummy from a gobiln zapper gave him flying and adjusted the speed and height and changed the model(I know the zapper isn't using his kaboom spell because im orderin him to attack, I haven't fixed that yet).

Is there a better way? Coz im fazing the problem with the speed of the unit being to slow 522 is not enough. I'm using a dummy only because I want the ground to burn in its wake.

And to make the ground to damage units moving over it I'm going to create additional dummys that will spawn on the fireball dummys locations as it moves forward. these dummys I will put some form of AOE on(I haven't put in timers or stuff that will remove the effects coz I don't know how to do it yet, I'm kinda grasping in the dark here).

In a better way. Eternally grateful for help. Feel free to point out any errors and correct me.
 
Level 25
Joined
Jul 10, 2006
Messages
3,315
Firstly, your code has memory leaks.

Secondly, because you are referring to (last created unit), if any other triggers that create units fire during that time, the fire pillar will be created there instead.

If you want the spell to look like DotA Jakiro's Macropyre, the idea is that you create dummy units that cast Flame Strike at locations in a line.

A simple GUI way to do it:
You'll need another trigger - a looping trigger.
In the main trigger, you enable the looping trigger and assign variables that the looping trigger will use. At the minimum you'll need a DummyUnit variable and a Ticker integer variable (to count how many times it has run).

The looping trigger in this case will run every 0.25 seconds. As for the actions, you need to first of all move the DummyUnit a distance towards the angle you want it to move. Then create another dummy caster unit that will cast flame strike. Finally, increment the Ticker integer by 1, and if it is past the number of times you want it to run, say 4 times, turn off the trigger.

You'll want to take a look at: http://www.hiveworkshop.com/forums/triggers-scripts-269/things-leak-35124/
to learn how to remove memory leaks.

In the tutorials section, there are also many good tutorials on MUI in GUI (MUI = Multi Unit Instanceability)
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
rulerofiron99 already gave you a good explenation on how to fix some of the mistakes you've made.

Here are some add-ons from my perspective:

Never use waits inside your spells, why? because waits are inaccurate and are processed for each client differently (depending on how fast the clients computer is) causing it to be different times for different players. Use a repeating timer instead. Timers are accurate to use when creating spells.

Remove the trigger turn on and trigger turn off, it's of no use to do that.

Destroy the special effects you've created or they will keep existing inside your RAM memory and will eventually cause your game to become slow (too many handles). When you destroy a special effect it will exist until it's animation is done playing and will then be removed from the game.

There is 1 position leak you need to clean up:
(Position of (Triggering unit))

to do this create a temporary location variable, set it to be the position of the triggering unit, use the variable inside the create unit action. And then use the following line of custom script to destroy the memory leak:

  • Custom script: call RemoveLocation(udg_MyTemporaryLocationVariable)
where MyTemporaryLocationVariable is your GUI variable.

is there a better way? Coz im fazing the problem with the speed of the unit being to slow 522 is not enough. I'm using a dummy only because I want the ground to burn in its wake.

Well you could use a library that allows you to increase the maximum movement speed of the unit:

http://www.hiveworkshop.com/forums/spells-569/movespeedx-gui-v1-1-0-0-a-207607/

Or you could calculate the position of the caster and target and then create an array with steps as index that will be enumerated in order to move the unit instantly between those steps towards the target.
(I created this very thing a few days ago, so if you need the source code tell me).
This will give you full control over the unit's movement instead of using MoveSpeedX, but it will be harder to use.

It's pretty simple to create dummy units every ... seconds and group units in range of them in order to damage them. You should have no problem getting that to work when looking in a tutorial or two.

Also, when creating a spell that needs to be MUI. (multiple units need to be abled to cast it simultaniously without causing problems)

You will need to use local variables instead of global ones.
"A local variable only exists within the function it is declared in, therefore a local variable can not be retrieved nor altered outside its parent function."
Basically this means that when 2 unit will cast the same spell almost simultaniously, they will not use the same global variables for the spell but will have local ones for each unit casting the spell.
However, local variables can not be used in other triggers as they would only exist within the trigger you've declared them in.
To declare a local variable you can use the following custom script:

  • Custom script: local integer i = 0
Remember that a local variable always needs to be declared on top of all GUI actions (at the top of a function).

You can them simply use i (instead of udg_i, a global GUI variable called i) in custom script to referr to the local variable.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
First, change "Unit - Hero (Mage)<gen> Begins casting an ability" to
"Unit - A unit Starts the effect of an ability". It has the same effect, but mine is MUI.

Actually, the event is not what makes the spell MUI or not ;)
Begins casting an ability can also work but it depends on your situation.
It's commonly better to use starts the effect of an ability because the event will be triggered when something starts to take effect instead of before the actual effect starts. In case of using channel ability's you might want to do some things beforehand with begins casting an ability, but this is very unusual and most likely not a smart thing to do.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
The best explenation for Multi Unit Instanceability would be:
each Instance works for Multiple Units.

There is also: MPI which means Multi Player Instanceability which means:
each Instance works for Multiple Players.

P.S. please don't call me master xD It makes me feel dissorientated.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
OKAY MAS--! I mean...
I just explained it in more details because he is a beginner! Still, I am right!

Very true.

But it would be best to explain what an (Instance) is and that MUI basically means that an instance works for multiple units.
In GUI you can see the trigger as the class and every time the event occurs a new instance is created of that class. (multiple instances)
In this case for the player or unit specified in the event. (for each unit or player)

Understanding this makes you understand how triggers evaluate and can really come in handy for completely understanding how to make a trigger MUI.

Since waits are calculated by the clients computer the values for the amount of time to wait within the instance can be different for each player.
That is why waits are inaccurate and will cause problems when making triggers MUI.

Timers however will be calculated over the host instead of the client, causing it to be the same for every player and thus is MUI.
 
Last edited:
Level 2
Joined
Jun 17, 2012
Messages
17
  • Create Fireball
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Q(Mage)
    • Actions
      • Unit - Create 1 Fireball for player 1 (Red) at (Triggering unit)) facing (Target of(Target unit of ability being cast))
      • Set Fireball = (Last created unit)
      • Unit - Order Fireball to Neutral - Kaboom! (Target unit of ability being cast)
      • Trigger - Turn on Fireball Burn Ground<gen>
  • Fireball Burn Ground
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Special Effect - Create a special effect at(Position of Fireball) using Doodads\Cinematic\FirePillarMedium\FirePillarMedium.mdl
      • Set FirePillar = (Last created special effect)
  • Fireball Alive Check
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • If(All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Fireball is dead) Equal to True
        • Then - Actions
          • Set Fireball = No unit
          • Special Effect - Destroy FirePillar
          • Trigger - Turn off Fireball Burn Ground <gen>
        • Else - Actions
          • Do nothing
Okay I started using variable and fixed dat stuff. Now I got this insted.

I've never thought about this MUI thing... realizing it's actually worth looking into because I don't want to create unique triggers for each unit that would happen to use this spell with its own variables.

Btw Mr.Master how do I use a local variable. xD I simply sez Custom script: local integer i = 0 and then somehow tell it to die when I so please, like a private session that is magically linked to the triggering unit or something? Or am I totally misunderstanding this. I can almost feel this is the solution to my firepillar problems coz I can only assign 1 firepillar to the removelist after the fireball has hit the target.

Or perhaps I'm doing it wrong, maybe I shouldn't use a special effect to make the groun burn. Still I will get problem when I'm removing them after fireball has hit.

I don't think I have to create a dummy to cast flamestrike on the fireball dummy... Maybe I can do that by using a trigger that will do a spell on the dummy each .05, gonna look into that.
 
Level 12
Joined
Sep 11, 2011
Messages
1,176
  • Create Fireball
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Q(Mage)
    • Actions
      • Set tempPoint = (Position of (Triggering unit))
      • Unit - Create 1 Fireball for Player 1 (Red) at tempPoint facing (Target of(Target unit of ability being cast))
      • Custom script : call RemoveLocation(udg_tempPoint)
      • Set Fireball = (Last created unit)
      • Unit - Order Fireball to Neutral - Kaboom! (Target unit of ability being cast)
      • Trigger - Turn on Fireball Burn Ground<gen>
to remove leaks :D
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
realizing it's actually worth looking into because I don't want to create unique triggers for each unit that would happen to use this spell with its own variables.

You've almost completely understood it the first time ;)
But it's actually like this: when you have a trigger, every time an event occurs a new instance of this trigger is created for the unit or player in the event.

If you are using global variables (variables that can be changed outside the current instance).
This simply means that if you have for example 2 units that cast a spell (2 instances that are created for the trigger due to the event being a unit casts a spell), then the global variables might change for one instance while the other is still executing.
Causing for example a variable like: Set Unit = (Triggering Unit) be the unit of the second instance instead of the first, causing all the actions with the global variable Unit to be for the wrong unit of the other instance.

There are several ways of making a spell MUI. One of them is using local variables instead of global ones. Another way of making a spell MUI is by using hashtables (this is for whenever you want to pass variable data from one trigger to another. using arrays with Unit Indexing is a better solution IMO since it's faster but that's just personal preference.). There are loads of tutorials on hashtables and MUI in the trigger editor tutorials section over here:
http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/

Here is a good tutorial that will come in handy when learning more about MUI (Allthough I think I gave a pretty good example):

http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/essentials-tutorial-141191/

Here is a good tutorial on memory leaks which is worth looking into:

http://www.hiveworkshop.com/forums/...quick-tutorial-common-triggering-tips-190802/


Using local variables might be a little bit confusing at first, but it gets quite simple once you get the hang of it. (This is also one of your first steps into learning Jass, since Custom script is basically Jass code)

if you want to set a local variable you simply use:

  • Custom script: set myvariable = 1
to declare the variable at the top of the function (create it) use:

  • Custom script: local integer myvariable
The first keyword local means that the variable is local, the second keyword integer tells it that it's of type integer and the third keyword is the name of the variable.
To create local arrays you could do something like this:

  • Custom script: local integer array myvariable
Where the keyword array simply indicates that the integer variable is an array.

Remember: local variables cannot be altered outside it's parent function. So whenever a second or even third instance is created, they will all use their own local variables instead of the same global ones.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Well you could use a library that allows you to increase the maximum movement speed of the unit:

http://www.hiveworkshop.com/forums/spells-569/movespeedx-gui-v1-1-0-0-a-207607/

Or you could calculate the position of the caster and target and then create an array with steps as index that will be enumerated in order to move the unit instantly between those steps towards the target.
(I created this very thing a few days ago, so if you need the source code tell me).
This will give you full control over the unit's movement instead of using MoveSpeedX, but it will be harder to use.
In refference to my earlier answer:

I'll release my source code on moving units instantly (over the actual line which it needs to move towards) instead of using issue order to move them from one point to another.
And I'll try to create it in GUI to make it user friendly. I'll probably even release it as a resource to GUI users.

Once I get home I'll develop it.
You might want to use it for your spell if you want to have full control over the unit's movement speed and whatever other actions you want to do within the steps that the unit makes.
(Every step can be manipulated with this system)

You'll need to know some basic math in order to understand the entire system (not to use it since I'll probably make that easier).

Also, I will give you a complete example on how to create this spell in GUI when I get home Mirdamor.
 
Level 2
Joined
Jun 17, 2012
Messages
17
use Integer A Loop and polar offset to create fire at the dummy..
Or here's my idea.. delete the dummy, make a spell which effect is the dummy's model, then use offset to add incineration effects.

This Off-set you speak of, will it give me reference points of positions?

You see the only reason I'm using a dummy is because I was told there is no way to get position data from a traveling projectile.

Therefor I made a dummy which looks like a fireball so I can do a loop which add AOE+EFFECT at the locations it has been at.

The problems I'm faceing at the moment is that I cannot handle the removal of special effects generated.

The solution should be a hashtable which I will fill with values given to each special effect created from my trigger like an array, and after the spell is complete empty the array(destroy or something). Dat is what I'm struggling with atm coz I don't understand hashtables.

All I got at the moment is this. lol

Create hashtable
Set last created hashtable = FirepillarsHashtable

And I'm also having problems with making my spell 100% MUI but Master Hashjie has been a great help with explaning(even tho I still don't understand jack but I get therz). And Kyousuke Imadori got me mindfull of memory leaks and its risks that could cause your whole friggin map to go full retard online.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
Sorry for not responding earlier Mirdamor, I am kind of bussy doing all sorts of stuff. If you could PM me on what you exactly want the spell to do I'll quickly create it for you.

This Off-set you speak of, will it give me reference points of positions?

He is talking about Polar Projection offsets. More about geometrics can be found in this tutorial:

http://www.wc3c.net/showthread.php?t=87364

You see the only reason I'm using a dummy is because I was told there is no way to get position data from a traveling projectile.

This information is wrong. It is always possible to get the X and Y co-ordinates of units. In this case you would need to use a custom script line like this:

  • Custom script: set udg_myLocationX = GetUnitX(GetTriggerUnit())
This will get the X position of the triggering unit and put it in a GUI variable called: myLocationX (which needs to be a real variable).
You can also replace GetTriggerUnit() with udg_yourUnitVariable.
This same thing can be done for position Y.

If you preferr using locations instead of co-ordinates you can also do this (myLocation is a point variable ofcourse):
  • Custom script: set udg_myLocation = GetUnitLoc(GetTriggerUnit())
Be sure to clean the leak in this case ;)

Therefor I made a dummy which looks like a fireball so I can do a loop which add AOE+EFFECT at the locations it has been at.

The problems I'm faceing at the moment is that I cannot handle the removal of special effects generated.

Why so? It should be pretty straight forward, tell me what exactly is happening and what you are doing. (A trigger can give us insight on what you are perhaps making mistakes in)
All you need to do is destroy the special effect right?
  • Set temp_point = (Position of (Triggering unit))
  • Special Effect - Create a special effect at temp_point using Abilities\Spells\Human\ThunderClap\ThunderClapCaster.mdl
  • Special Effect - Destroy (Last created special effect)
  • Custom script: call RemoveLocation(udg_temp_point)
This will destroy the special effect as soon as the animation of the effect ends. Also I cleaned a location leak in case you didn't yet know how to do that ;)

The solution should be a hashtable which I will fill with values given to each special effect created from my trigger like an array, and after the spell is complete empty the array(destroy or something). Dat is what I'm struggling with atm coz I don't understand hashtables.

All I got at the moment is this. lol

Create hashtable
Set last created hashtable = FirepillarsHashtable

And I'm also having problems with making my spell 100% MUI but Master Hashjie has been a great help with explaning(even tho I still don't understand jack but I get therz). And Kyousuke Imadori got me mindfull of memory leaks and its risks that could cause your whole friggin map to go full retard online.

Basically a hashtable is a 2 Dimensional array. Which means instead of 1 index:
  • Set myArray[index1] = value
it has 2 indexes:
  • Hashtable - Save value as index1 of index2 in your_hashtable
index1 is usually named parent key and index2 child key but that doesn't really give a shit.

This gives you the ability to put in the (custom value of your casting unit) in the first index
and attach any value to that unit by saving it on the second index in order to make it MUI.

An example of how this is done:

  • Hashtable - Save 12 as (Custom value of (Triggering unit)) of 1 in your_hashtable
Now you have attached number 12 to Triggering unit on the second index which is 1. To retrieve number 12 in a different trigger you use:

  • Set myInteger = (Load (Custom value of Your_Unit) of 1 from your_hashtable)
Custom value of Your_Unit will be the first index and 1 will be the second in this case.

But in order to correctly do this you will need a Unit Indexing system like this one:

http://www.hiveworkshop.com/forums/spells-569/gui-unit-indexer-1-2-0-2-a-197329/

A unit indexing system basically assigns a unique custom value to each unit created, making sure that each unit has it's own unique value which you can then use to attach any data to.
Just make sure you are not already setting any custom values for units (as this would be a shame since it can be used for adding any data to a unit instead of just one value with this system).

So make sure not to use this when using a Unit Indexing system:
  • Unit - Set the custom value of Your_unit to some number
This means it would be completely Multi Unit Instanceable since each unit has it's own data.
(there are also other "faster" methods then hashtables for accomplishing this, but it requires more knowledge to use)

If you want to learn more about the actual Unit Indexing system you might want to take a look at creating stacks (quite a bit more advanced)

I hope this helped a bit. Tell me if anything is unclear ;)
 
Last edited:
Level 2
Joined
Jun 17, 2012
Messages
17
  • Q Create
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Q (Mage)
    • Actions
      • Set tempPoint = (Position of (Triggering unit))
      • Unit - Create 1 Fireball for (Owner of (Triggering unit)) at tempPoint facing (Target point of ability being cast)
      • Unit - Order (Last created unit) to Neutral - Kaboom! (Target unit of ability being cast)
      • Custom script call RemoveLocation(udg_tempPoint)
  • Q Trace
    • Events
      • Time - Every 0.70 seconds of game time
    • Conditions
      • (Number of units in (Units of type Fireball)) Greater than 0
    • Actions
      • Set tempGroup = (Units of type Fireball)
      • Unit group - Pick every unit in tempGroup and do (Actions)
        • Loop - Actions
          • Set tempPoint=(Position of (Picked unit))
          • Unit - Create 1 FirePillar for (Owner of (Picked unit)) at tempPoint facing (Target point of ability being cast)
          • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
      • Custom script call DestroyGroup(udg_tempGroup)
      • Custom script call RemoveLocation(udg_tempPoint)
Thanks for the help.
 
Level 14
Joined
Apr 20, 2009
Messages
1,543
  • Q Create
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Q (Mage)
    • Actions
      • Set tempPoint = (Position of (Triggering unit))
      • Unit - Create 1 Fireball for (Owner of (Triggering unit)) at tempPoint facing (Target point of ability being cast)
      • Unit - Order (Last created unit) to Neutral - Kaboom! (Target unit of ability being cast)
      • Custom script call RemoveLocation(udg_tempPoint)
  • Q Trace
    • Events
      • Time - Every 0.70 seconds of game time
    • Conditions
      • (Number of units in (Units of type Fireball)) Greater than 0
    • Actions
      • Set tempGroup = (Units of type Fireball)
      • Unit group - Pick every unit in tempGroup and do (Actions)
        • Loop - Actions
          • Set tempPoint=(Position of (Picked unit))
          • Unit - Create 1 FirePillar for (Owner of (Picked unit)) at tempPoint facing (Target point of ability being cast)
          • Unit - Add a 5.00 second Generic expiration timer to (Last created unit)
      • Custom script call DestroyGroup(udg_tempGroup)
      • Custom script call RemoveLocation(udg_tempPoint)
Thanks for the help.

This seems great so far, good work :)
1 little mistake though: put the call RemoveLocation(udg_tempPoint) inside the Loop actions, else only the last location will be destroyed.

Also I suppose you want to have Q Trace initially off (there should be a little button on top of your trigger called Initially On) and turn the trigger on (through the action) when Q Create is being executed.
 
Last edited:
Status
Not open for further replies.
Top