Tutorial Switching from GUI to vJASS

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
Introduction
When you read the title of the thread, you probably thought "GUI straight to vJASS? That's too big of a jump! I'd rather learn JASS first!" However, this is a misconception about vJASS. As you probably already know, the GUI is based off of JASS, but worded so that a human can understand it. JASS is the text-based coding language that is very free in the way it can perform actions, compared to the GUI. vJASS simply makes things easier for you to code, and more readable at the same time. In a way, saying you have to learn JASS before you can learn vJASS is like saying you have to learn "C" before you learn "C++". The languages are very similar, but instead, you're learning how to code in an object-oriented programming language. vJASS does require Newgen in order to be used in your map, so lets go ahead and get that first.

Download and install Newgen from Here

Once you've installed Newgen, you are ready to start learning JASS and vJASS.

Trigger Layout
In the GUI, a trigger has a different layout than a trigger does in JASS.

In the GUI, you think of a trigger as a combination of Events, Conditions, and Actions, right? JASS is a bit more complicated.

A JASS trigger starts with a function that is run at Map Initialization (during the loading screen). Every trigger has to have one, otherwise the trigger will not have any events, conditions or actions. This function is called the Trigger Initialization, commonly known as "InitTrig" or "Init" for short. It is ALWAYS at the bottom, because in order to run another function, or "call" it, the function has to be below the function it is calling. Otherwise, the World Editor cannot find the function you are calling.

If you were to convert a function from GUI to JASS (Edit -> Convert to Custom Text), it would be a little more complicated. The Init function would actually be named "InitTrig_Map_Initialization", if the trigger was actually named "Map Initialization". This is because the GUI puts a suffix onto "InitTrig" so that the game can recognize the difference between the InitTrig function in your Map Initialization trigger, and the one in your Unit Spawning Trigger (for example).

Lets make a very simple trigger, so that we can look at what a function looks like:

JASS:
whichTrigger
    Events
        Map initialization
    Conditions
        True Equal to True
    Actions
        Do nothing


This will become:

JASS:
function Trig_whichTrigger_Conditions takes nothing returns boolean
    if ( not ( true == true ) ) then
        return false
    endif
    return true
endfunction

function Trig_whichTrigger_Actions takes nothing returns nothing
    call DoNothing(  )
endfunction

//===========================================================================
function InitTrig_whichTrigger takes nothing returns nothing
    set gg_trg_whichTrigger = CreateTrigger(  )
    call TriggerAddCondition( gg_trg_whichTrigger, Condition( function Trig_whichTrigger_Conditions ) )
    call TriggerAddAction( gg_trg_whichTrigger, function Trig_whichTrigger_Actions )
endfunction


It looks pretty confusing, doesn't it? Don't worry, we're just using this as a visual example.

Here is an image we can use to connect JASS to GUI:

Trigger.jpg


Now this probably looks overwhelming to you when you first see such a huge block of code, but once it is broken down, it becomes simpler. First, let's take a look at the InitTrig function (the block of code at the bottom).

JASS:
function InitTrig_whichTrigger takes nothing returns nothing


1. The first line is simply identifying it is a function. InitTrig_whichTrigger is its name. "takes nothing" means that it is not going to be called with any variables, and "returns nothing" means it's not going to have a variable set to it. In the GUI trigger, this would be the Trigger itself on the left side of the screen. Now we'll take a look at the next line:

JASS:
    set gg_trg_whichTrigger = CreateTrigger(  )


1. Each trigger that you create has to be created before it can be given any events, actions, or conditions. The GUI automatically creates a variable called gg_trg_ + "Your_Trigger_Name" for you. Since I named my trigger whichTrigger, it is gg_trg_whichTrigger. Every trigger will have a line similar to this, first in the InitTrig function.

2. The trigger is run at map Initialization, so just below the buttons at the top of the trigger window, you will see a box labelled "Run on Map Initialization" is checked. This is the event for this particular trigger, but normally you will call the function "TriggerAddEvent", which is where the event itself is added.

Now we'll take a look at the next line:

JASS:
    call TriggerAddCondition( gg_trg_whichTrigger, Condition( function Trig_whichTrigger_Conditions ) )


3. There is a function called "TriggerAddCondition", which gives a trigger a condition. If you look at the function, you will see that it takes two arguments, a trigger and a boolexpr. A boolexpr is basically a function that returns a boolean. If you look up, you will see a function called "Trig_whichTrigger_Conditions". This is the "True is equal to True" section of the GUI trigger. However, in order for this code to become a boolexpr, it has to be called with the Condition function, so it is placed inside a set of parenthesis after "Condition". Now we'll take a look at the next line:

JASS:
    call TriggerAddAction( gg_trg_whichTrigger, function Trig_whichTrigger_Actions )


4. The TriggerAddAction function works very similar to the TriggerAddCondition, but the Action function does not have to return true or be converted into a boolexpr. If you look up, you'll see a function called "Trig_whichTrigger_Actions". That is the "Do Nothing" section of the GUI trigger. Now we'll take a look at the last line:

JASS:
endfunction


This is simply here to tell the game that the function has ended, so that the game will know when one function ends, and another starts.

Understanding Functions
The first question everyone will always ask is, "What is a function?" That question isn't exactly easy to answer, because a function has many properties, listed below:

  • A function is an instruction to the computer to run actions, which could include running other functions.
  • A function can take data to use in its actions.
  • A function can return data to be used in the calling function
  • Functions can not be nested (created inside other functions)

Here is the most basic function:

JASS:
function Empty takes nothing returns nothing
endfunction


As you can see, this function is named "Empty", does not take or return any arguments, and does not perform any actions.

A function can also take arguments, and return a value:

JASS:
function DoStuff takes unit pie, integer cake returns integer
    call KillUnit(pie)
    set cake = cake + 42
    return cake
endfunction


This function takes two arguments (separated by a comma), a unit that I named "pie", and an integer that I named "cake". It also returns an integer value.

The rest of the function is pretty self explanatory. When this function is called, it kills the pie unit, increases cake by 42, and returns that value back to the calling function.

Now I want to run this function.

JASS:
function AnotherOne takes nothing returns nothing
    call DisplayTextToPlayer(Player(0),0,0,I2S(DoStuff(gg_unit_hfoo_0000,0)))
endfunction


The DisplayTextToPlayer will display some text to a player. Player(0) is actually Player 1, Red (JASS starts out at 0 for arrays and most values, rather than 1 as in the GUI). I2S is a function that converts an integer into a string (since we're displaying a string to the player). Finally, we're displaying the returned value of our DoStuff function, which will end up being "42" (since we are calling it with the number 0).

If you ever need to know what a function is called, you can use the Function List in Newgen to search for functions. Almost all the time, they will be named according to what they do, such as "RemoveUnit" which removes a unit from the game.

Creating a Trigger from Scratch
Now that you understand functions and the layout of a trigger, you can start to create your own triggers. Delete everything in the textbox, and get ready to start from scratch. I know it's scary. Go ahead, wipe it out.

Now you have a blank textbox. Now you're going to recreate a layout so that you can make your own Conditions and Actions, but now we're going to make it more readable, using vJASS. We're going to start with this block:

JASS:
scope whichTrigger





endscope


This is a basic layout for a trigger in vJASS. It makes things more readable and lets you use a few extra features. Here's an explanation on why we're going to use a scope:

vJASS has 2 features that lets you make blocks of code with the "public " and "private " prefix. The two features are called scopes and libraries.

A library is basically a block of code that Newgen will put in the Map Header. You can put it in a trigger instead, so that it is easier to find, and so that you can make a library use another library, so that one library can call the functions in another library.

A scope is basically a block of code that lets you use the public and private prefixes. The public prefix means that in your scope, you can call a function called "Actions" like this:

JASS:
scope whichTrigger

public function Actions takes nothing returns nothing
endfunction

function whichTrigger takes nothing returns nothing
    call Actions()
endfunction

endscope


However, if you were to call that function from another scope, you would have to use the scope's name as a prefix, like so:

JASS:
scope JustAnotherScope

function something takes nothing returns nothing
    call whichTrigger_Actions()
endfunction

endscope


Private functions can also be used inside the scope they are in, but they cannot be called from anywhere else.

Basically, the concept is, if you are not going to call a function outside the scope, give it a private prefix, to prevent functions having duplicate names. If you are, give it the public prefix.

Now that you understand what a scope is, and why we're using it, let's start with the Init trigger. Because we're in a scope, we should use either the public or private prefix. We're not going to ever call it, so let's just use the private prefix. You can name it anything you like, but Init or InitTrig are common because it makes it easier to read for everyone. An Init trigger never takes or returns anything, because it is only run at map initialization, and never by the coder. So here's our trigger:

JASS:
scope whichTrigger

private function Init takes nothing returns nothing

endfunction

endscope


However, since your function can be named anything, you have to add something to the end of the first line, so that Newgen knows which function is the InitTrig/Initializer:

JASS:
scope whichTrigger initializer Init


Now the game will run the Init function at Map Initialization, so we can create a trigger, and Events, Conditions, and Actions for that trigger.

Remember how the trigger used to be named gg_trg_whichTrigger? That's really long to type out. Lets create our own trigger instead:

JASS:
scope whichTrigger initializer Init

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    
endfunction

endscope


The word "local" means that the trigger will only be used in the Init function. Normally, you used global variables in the GUI, but since creating a local is faster to type out, and it's only going to be used in this trigger, lets just use a local trigger. Now we can just use "t" for our Events, Conditions, and Actions. Lets create an event for our trigger. How about whenever a unit dies?

We don't know what the correct syntax is for this event. There are two ways to go about solving this problem:
1. Create a new trigger with the event, convert it to custom text, copy the TriggerAddEvent function, and change the trigger to "t".

2. Click on the button above the Textbox called "Function List". At the top right of the window that popped up, there is a box. Type in there to search for a function by its name.

Number 1 is probably faster if you don't know very much about JASS, but if you try out number 2, you'll soon memorize all the common functions, and you'll rarely need to look it up.

Lets try method number 2, and search for "death". You'll see several options, most of which don't make much sense. However, the TriggerRegisterDeathEvent function has 3 words that look like what we're looking for (trigger, death, and event). However, if you click on it, and take a look at what the function takes, you'll see that it takes a widget.

A widget is anything with health: a unit, a destructible, or an item. That means that this will only register an event for the death of one unit. That's not what we're looking for!

However, I know of a function that registers an event for EVERY unit. Search for "anyunit". You'll see only one function, called "TriggerRegisterAnyUnitEventBJ". We're going to use this function to give our trigger an any unit death event. So we'll start filling it out like so:



However, we don't know what type of event the Unit Dies Event is. Fortunately, events are simple to figure out. the function needs a "playerunitevent". All events will start with the "EVENT_" prefix, and then you can just add the rest of the words with capitalization and an underscore between words, like so:


Both Newgen and JASSCraft have the capability to search for constants or functions.

Now that we have the hard part down, we can just create the exterior for the Conditions and Actions functions like so:

JASS:
scope whichTrigger initializer Init

private function Conditions takes nothing returns boolean
    return true
endfunction

private function Actions takes nothing returns nothing

endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    
endfunction

endscope


In order for the game to be able to save, a function that returns something has to return something. Since we don't have any conditions yet, I just put "return true". functions that don't return anything can be left blank without any problems.

Now we can add these Conditions and Actions to the trigger t.

JASS:
scope whichTrigger initializer Init

private function Conditions takes nothing returns boolean
    return true
endfunction

private function Actions takes nothing returns nothing

endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddAction(t,function Actions)
    call TriggerAddCondition(t,Condition(function Conditions))
endfunction

endscope


And that's it. Now you've created your first trigger, and you can put whatever Conditions and Actions you like. :)

Now that you've learned the basics for creating triggers, try creating a few by yourself. You can always come back here and take a look at the guide if you forget a step. Just remember that there are 2 ways to find a function you are looking for, and that much of the time, simply searching for a few key words will find the function you are looking for. I'm now going to go more in-depth, so you may want to take a break, and come back later.

Here's a few tips:
  • Spacing does not matter. It is only for readability.
  • Capitalization DOES matter!

Creating Your Own Function
Now that you've got the basics, we're going to go a little more in-depth, starting with creating your own functions.

You are probably thinking "but I just created my own functions for the Init, Conditions, and Actions!" Well you are correct. However, these functions are very simple, and many things will be made easier if you know how to make your own, and if you understand their purpose.

A function that doesn't take any arguments (function X takes nothing...) is pointless a lot of the time. Unless it is using a global variable, there is no point to the function, since you can actually make it faster by putting the whole code in the function which calls it. However, a function that takes an argument or arguments can be very useful, because it can change the argument in some way, or return information about the argument.

A function is a set of actions used either to do a sequence of actions, or to get a value. For example, the CreateUnit function is used to do both. It not only creates a unit at the desired location, facing the desired angle, but it also returns that unit to be used as a variable.

It's hard to come up with "ideas" for a function, because in general they are created when they are needed. However, we can still create some functions for practice and teaching purposes.

Since I'm explaining everything down to the last detail, let's start with a somewhat complicated function: A spell. First, we'll start simple, learning how to build a function.

I want to create a function that creates a dummy unit, and orders him to cast "Slam". Let's start out with our scope header and footer, and an empty function:

JASS:
scope Stomp

public function Stomp takes nothing returns nothing

endfunction

endscope


Right now, we don't know if it's going to be called from another function, or how it is going to be run, so let's just make it a public function.

OK, now to create our dummy unit. Let's use the CreateUnit function, for simplicity. We can always change it once we figure out how the spell is going to be run.

The create unit function takes an a player, an integer, and 3 reals.

First we need a player. We don't know which player started the ability yet (which player that will own the dummy unit), so let's just use Player 1. To get a player by number, use the Player(#) function. Just remember that in JASS, everything starts with 0 instead of 1, so Player 1 would actually be Player(0), and the same for the other players (Player 2 is Player(1), Player 3 is Player(2), etc).

JASS:


The second argument, an integer is the unitID of the unit to be created. If you go into the object editor, and find the unit you are looking for, and press "Ctrl + D", the first four characters it shows to you are the unit's ID. (It should look something like u000). 'u000' is the very first id created in the unit editor, so let's just use that, since the dummy unit's id will change in every map.

JASS:
call CreateUnit(Player(0),'u000',


Now we need X and Y coordinates for where the unit will be. Let's just use (0,0) for the center of the map, since we don't know where it's going to be.

JASS:
call CreateUnit(Player(0),'u000',0,0,


Last, and least, we need a facing angle. Basically, this doesn't matter, since the unit will turn to face any direction if it needs to. Just use 0.

JASS:
call CreateUnit(Player(0),'u000',0,0,0)


Now it will create a dummy unit for player 1 at the center of the map.

Next, we have to order the unit to cast stomp. However, in order for a unit to cast stomp, it has to have the ability, and we have to be able to reference the unit. The native function, CreateUnit does not set bj_lastCreateUnit to the unit, it only returns the unit. Let's directly set a variable to the unit:

JASS:
local unit dummy = CreateUnit(Player(0),'u000',0,0,0)


This simply creates a local variable of type unit, named dummy, and sets it to the created unit. Note that the "call " is left out, when a function is used directly, rather than simply called.

A local variable is different from the variables you used in GUI, in that it is created at the beginning of a function, and can only be used inside the function. It is also unique to each time the function runs (each time the variable is created), which means it won't be overwritten after time.

Now we can add it to our unit. A quick function look up will show the function "UnitAddAbility" takes a unit and an integer, which is the ability id.

Go into the Ability Editor inside the Object Editor window, and press "Ctrl+D" to see the Ability ID's. The first 4 characters are the ability's raw data, and the second 4 are the raw data that the custom ability is based upon. Since the very first generated id is 'A000', let's just use that one for simplicity.

JASS:
call UnitAddAbility(dummy,'A000')


Would add the 'A000' ability to the "dummy" unit.

Now we need to issue the stomp order. This one is a bit more tricky to look up. Usually, it's a good idea to look this up by converting GUI text to JASS if you have tried looking it up and still can't figure it out, but I know it off the top of my head as "IssueImmediateOrder".

Let's order our dummy to cast the ability. IssueImmediateOrder takes a unit and a string. Wait. A string? What string is that?

Well put simply, every ability has an "order string" which is used to order the unit to cast the ability. Find the ability in the Ability Editor, and look for "Text - Order String - Use/Turn On". The value of this is the string you need to issue the order. For War Stomp it is "stomp". Now let's call the function:

JASS:
call IssueImmediateOrder(dummy,"stomp")


Last but not least, we have to clean up the leaks.

The first thing we can do is remove the unit. However, we don't want to remove the unit right away. It won't have time to cast the spell.

Let's add an expiration timer, so we don't have to put in waits. This is another hard function to look up, and one I really suggest converting from GUI to JASS to find out the function name, as well as a few other things.

The function is called "UnitApplyTimedLife" which takes a unit, an integer, and a real. What's that integer doing there if the real is the "duration", you're probably wondering. It is the type of expiration timer. I know you don't know any of them off the top of your head, so I'll just give you the "generic" buffId: 'BTLF' (stands for BUFF TIMED LIFE {F?}). Now lets add it to the unit:

JASS:
call UnitApplyTimedLife(dummy,'BTLF',1)


1 second should be enough time for the unit to finish casting the ability.

Lastly, we need to get rid of the local handle leak (UGH! Not another term to learn!).

Here's how and why local handles leak:

Basically, a handle is any object. Anything from a unit, or item, to a timer or floating text. You can see if something is a handle by looking up the name of the variable, and seeing what it "extends". If it extends handle, it IS a handle. Basically, the types that are not handles are: real, string, integer, boolean, and code (a function).

Basically, if you are ever going to remove the object, or if it is ever going to get removed (a unit dies, and then is removed from the game automatically, for example), you have to set the variable to null, in order to prevent a leak. For globals, this is not a problem, since globals get reused, and re-set all the time. The "leak" only lasts until the global is re-set, and then the leak disappears. However, locals are tricky.

Locals cannot be referred to outside the function they were declared to (except when passing them to another function as an argument). This means that they will stay in the game until they are nulled. If the function doesn't null them, they will never be removed.

So to take care of that, we can set "dummy" to null.

JASS:
set dummy = null


Now that we've finished, let's take a look at the entire code:
JASS:
scope Stomp

public function Stomp takes nothing returns nothing
    local unit dummy = CreateUnit(Player(0),'u000',0,0,0)
    call UnitAddAbility(dummy,'A000')
    call IssueImmediateOrder(dummy,"stomp")
    call UnitApplyTimedLife(dummy,'BTLF',1)
    set dummy = null
endfunction

endscope


Now we have a working function.

Configuring a Trigger

Our trigger is very generic. It creates a unit for one player that we cannot change, in the center of the map, which is not very useful.

There are many ways to go about making a function dynamic, but here are the most common:

  • Creating a Trigger
  • Creating Configurable Options
  • Passing data as an argument
  • Callback timers and attachment

Now, although we have made our created trigger dynamic, we haven't added in any of the Event Responses, such as the dieing unit.

Lets change the function so that it creates the dummy "stomp" at the position of our dieing unit, so it looks like he exploded upon death.

First, we need to reanalyze our function, and find out where a 'location' for this stomp function can be specified.

A quick function look-up shows that the CreateUnit function asks for 2 reals: an "x" and "y" location for the unit.

However, don't we have to use a point to get a unit's location?

Not in JASS. In JASS, you have the availability of all the functions, and I'll guarantee you that there is a way to do just about everything you can do with points, with coordinates instead. Coordinates are faster, and don't create a memory leak, too!

In JASS, you can use GetUnitX and GetUnitY functions instead of GetUnitLoc to get a unit's position.

So, let's replace that first 0 with GetUnitX(GetTriggerUnit()) and the second with GetUnitY(GetTriggerUnit()). GetTriggerUnit() is the unit that triggered the trigger.

JASS:
scope Stomp

public function Stomp takes nothing returns nothing
    local unit dummy = CreateUnit(Player(0),'u000',GetUnitX(GetTriggerUnit(),GetUnitY(GetTriggerUnit()),0)
    call UnitAddAbility(dummy,'A000')
    call IssueImmediateOrder(dummy,"stomp")
    call UnitApplyTimedLife(dummy,'BTLF',1)
    set dummy = null
endfunction

endscope


Now our function will create a unit for Player 1, at the triggering unit's position, order it to stomp, and remove it after 1 second. Let's change it so it creates the unit for the owner of the triggering unit. Who wants something that only works for one player? :p

A quick function look-up will find the GetOwningPlayer function, which takes a unit.

JASS:
scope Stomp

public function Stomp takes nothing returns nothing
    local unit dummy = CreateUnit(GetOwningPlayer(GetTriggerUnit()),'u000',GetUnitX(GetTriggerUnit(),GetUnitY(GetTriggerUnit()),0)
    call UnitAddAbility(dummy,'A000')
    call IssueImmediateOrder(dummy,"stomp")
    call UnitApplyTimedLife(dummy,'BTLF',1)
    set dummy = null
endfunction

endscope


Now, we could go in one of two directions. We could either proceed to make this an Actions function, and add an Init function with an event and Conditions, or we could proceed to making this a callable function, similar to a system. We've already discussed how to create a trigger, so I'm going to show you ways to make your function into a callable function.

Arguments and Configuration

===To Be Continued===
 

ReVolver

Mega Super Ultra Cool Member
Reaction score
608
Great Job :thup: I hope you finish soon.
 

Fluffball

Well-Known Member
Reaction score
35
<3 this tutorial... It also explains some things that were a bit hazy for me. (What is vJass?), not wanting to sound like a total noob... (I thought that vJass was like EGUI, for Jass, but it isn't) And it also tells me that massive codes can still be understood Thanks and +rep
 

Romek

Super Moderator
Reaction score
963
Awesome. This would be very helpful for beginners.

5 star from me.
 

Flare

Stops copies me!
Reaction score
662
you can search for all of these events (using EVENT_ is an easy way to do it), but Newgen will not let you search for it.
Actually, you can get those in NewGen - when you open the Function List window, click the Constants button, and you can get all the events, ATK/DMG/WPN types, and all those other sorta things.
 
Reaction score
456
Because it's unfinished. If you had actually read the tutorial, you would've noticed.
 

Darthfett

Aerospace/Cybersecurity Software Engineer
Reaction score
615
Because it's unfinished. If you had actually read the tutorial, you would've noticed.

Yep. Still have a long way to go, I'm going to try and cover just about everything, including basic structs with callback timers and attachment systems.

Actually, you can get those in NewGen - when you open the Function List window, click the Constants button, and you can get all the events, ATK/DMG/WPN types, and all those other sorta things.

Fixed: I didn't even know that myself when I was writing this. :p Thanks! +rep

Both Newgen and JASSCraft have the capability to search for constants or functions.

EDIT: Forgot to add that I added the -basic- spell section.
 

Mike889

New Member
Reaction score
15
Nice one, now I'll really try to learn JASS =P
I'm trying to make a hero revive using the trigger you gave, however I'm getting an errors and don't know what it is xD

JASS:
scope whichTrigger initializer Init

private function Conditions takes nothing returns boolean
    return true
endfunction
//-----------------------------------------------------------------------------------------------------//
private function Actions takes nothing returns nothing
    
    local unit u = GetDyingUnit
    local Location l = GetUnitLoc
    call ReviveHeroLoc(u,l,true)    
    call RemoveLocation(l)
    
endfunction
//-----------------------------------------------------------------------------------------------------//
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
    
endfunction

endscope
 

saw792

Is known to say things. That is all.
Reaction score
280
JASS:
local unit u = GetDyingUnit() //brackets show it&#039;s a function, even with no arguments
local location l = GetUnitLoc(u) //lower-case l, and you must specify the unit to get the loc of
call ReviveHeroLoc(u,l,true)    
call RemoveLocation(l)
set u = null //null handles to prevent leaks
set l = null // ^


Also, you haven't added the conditions or actions in the init function. Don't forget to use TriggerAddCondition and TriggerAddAction to set the conditions and actions.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
hah very nice turtorial, i think even i could learn Jass now. unfortunately i wont because i am using GUI for about 3 years and i am happy with it.
but nice work!
 

Mike889

New Member
Reaction score
15
JASS:
scope MT initializer Init

private function Conditions takes nothing returns boolean
    if ( not ( IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) == true ) ) then
        return false
    endif
    return true
endfunction
//-----------------------------------------------------------------------------------------------------//
private function Actions takes nothing returns nothing
    local unit u = GetDyingUnit()
    local location l = GetUnitLoc(u)
    call ReviveHeroLoc(u,l,true)
    call RemoveLocation(l)
    set u = null
    set l = null

endfunction
//-----------------------------------------------------------------------------------------------------//
private function Init takes nothing returns nothing
    local trigger MT = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(MT,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(MT, Condition(function Conditions) )
    call TriggerAddAction(MT, function Actions)

endfunction

endscope


Thanks!! Now I'll keep training until I can create spells with vJass!
"And it is actually easy! You just type TriggerAddAction and NewGen says what you must type next!
 

Romek

Super Moderator
Reaction score
963
Is this going to be finished anytime soon, or can I graveyard it (discontinued)?
 

Arie

Cool Member
Reaction score
5
Awww.... Finish it man....
I learned alot from this ultra guide.
Thanks before. :thup::thup:
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • 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

      • Ghan
        Administrator - Servers are fun

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top