• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[JASS] Erm... I'm Kind Of A New JASS Triggerer, I Hope You'll Help Me Here...

Status
Not open for further replies.
Level 19
Joined
Oct 15, 2008
Messages
3,231
Oh, I think I've seen it in some tutorial, by the way, when trying to trigger something with:
JASS:
function Example takes unit returns nothing
endfunction

Is this:

JASS:
function Example takes unit('A000') returns nothing
endfunction

Different from this?

JASS:
function Example takes unit returns nothing
call CreateUnit('A000')
endfunction

I'm really sorry... But I'm quite confused. Also, if any of you know of anymore programming languages for Warcraft III besides the ones stated, please inform me, thank you:)
 
you cannot do that I think... unit is an object, 'A000' is an integer...

plus the takes part, takes a parameter to be used by the function

JASS:
function Example takes unit a returns nothing
   call KillUnit(a)
   //This would kill the unit passed onto this function
endfunction

function Init takes nothing returns nothing
   call Example(MyHero)
   //Doing this would pass the unit MyHero to the function Example, so MyHero would be killed
endfunction

function Init2 takes nothing returns nothing
   call Example(MyHero2)
   //now this would kill MyHero2
endfunction

IDK why, but this seems to be getting nowhere...

maybe you should start by doing triggers in GUI and then convert it into JASS, then study the resulting function...
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Because you seem a bit lost on functions, I shall post up chapter 7 from my secret tut : |

Chapter 7- Functions

What is a Function?
A function is like a task in programming. When a function is called (run), the function performs that task. Functions may have any amount of lines of code, including 0 lines, (as complicated a task as you want) and may even perform multiple tasks.

Functions are the only way to run maps. Looking back at the GUI layout:
  • Events:
  • Conditions:
  • Actions:
Functions would be what's put into the actions category.

Functions can take parameters (like the numbers plugged into a calculator) and return a single value.
The Syntax of a Function
The function block is
JASS:
function
endfunction

Because functions take values and return a value, some extra stuff is required in the first part of the function block. The function block layout reads: function (name) takes (something) returns (something)

The (name) portion is the label of the function, which is placed after the function keyword. The label is what is used when calling the function.
JASS:
function Label
endfunction

The takes keyword shows what values must be plugged into a function when running it. Takes uses a comma separated list of declared variables (these variables cannot be initialized since their values are plugged into the function): takes real x, integer y, boolean b

JASS:
function Label takes real x, integer y, boolean b
endfunction

Each variable declared in takes is associated to the value that is plugged into the function when it is run. For example, the first value put into a function would be the first variable declared in takes.

Whenever the Label function is run, it creates whatever variables are declared in takes for itself. When it ends, it destroys those variables. In this case, 3 variables would be declared every time Label is run
JASS:
Label
	real x
	integer y
	boolean b

Those variables would be initialized to whatever values are passed into Label when it is run (order matters). Whenever calling Label, 3 values would have to be passed in, the first one being a real, the second one being an integer, and the third one being a boolean (values**). This means that if 3.3, 5, and true were passed into the Label function, it'd be akin to
JASS:
Label
	real x = 3.3
	integer y = 5
	boolean b = true

Functions are run using the call keyword.

call MyFunction

Values are passed in by grouping them into () with a comma separated list. Even if a function doesn't take anything, the () must be used.

call MyFunction()

To run the Label function from before (remember Label tales a real, integer, and boolean):
call Label(3.3, 5, true)

Three values must always be passed in because Label takes 3 arguments. This wouldn't be legal
call Label(3.3, 5)

If Label didn't take anything
call Label()

Calls can only be done within functions.

The returns keyword shows the type of variable a function returns: returns real
JASS:
function Label takes real x, integer y, boolean b returns real
endfunction

The nothing keyword is used whenever a function takes nothing or returns nothing.
JASS:
function Label takes nothing returns nothing
endfunction

When a function is called, that function will always return a value, even if that value is nothing. No variable type can be set to nothing, so setting a variable to a function that returns nothing isn't possible.

Variables can be set to functions as if the functions were values (because a function always returns a value). Functions can also be plugged into functions as if they were values. Keep in mind that the type a function returns is the type of value a function is treated as.

When a function is used as a value, the call keyword is not used.

JASS:
real x
real y
set x = Label(5, 6, true) //the above example of Label is used
set y = Label(Label(7, 8, true), 16, true) //Label is passed into Label as a parameter.

//this wouldn't be legal as Label returns a real
//set y = Label(6.6, Label(7, 8, true), true)
//Remember the function is: function Label takes real x, integer y, boolean b returns real
//This means that the y in the function is being set to Label(7, 8, true). 
//The y var in the function is an integer, and integer variables cannot store real values.

Function blocks cannot go into function blocks or global blocks (global blocks only store global variables) (functions only store lines of code)

Code can be written normally in a function block and the parameters can be used as regular variables within the function. A function can only call a function that is declared above it.

JASS:
function Label takes integer x returns nothing
endfunction

function Label2 takes integer y returns nothing
	call Label(y)
endfunction

function Label3 takes nothing returns nothing
	call Label2(3)
	call Label4() //syntax error, Label4 is declared after Label3
endfunction

function Label4 takes nothing returns nothing
endfunction

The return keyword is used to return values. Return will immediately exit out of a function.

Using the Add example from before:
JASS:
//this function can only return values of type integer
function Add takes integer number1, number2 returns integer
	return number1+number2
endfunction

//this function can only return values of type integer
function Add5And7 takes nothing returns integer
	return Add(5, 7) //returns 5+7, which is 12
endfunction

If a function returns something, it must always return that something at the last line.

JASS:
function Add takes integer x, integer y returns integer
	//syntax error because this function has to return an integer value
endfunction

function Add2 takes nothing returns notihng
	call Add(5, 7)
endfunction

JASS:
function Add takes integer x, integer y returns integer
	return 5.5 //syntax error because this function has to return an integer value. 5.5 is a real.
endfunction

function Add2 takes nothing returns notihng
	call Add(5, 7)
endfunction

JASS:
function Bleh takes nothing returns nothing
endfunction

//Bleh is never called because there is a return above it. This will still cause a syntax error even though the function always returns a value. The last line of code for a function must always be a return
function Add takes integer x, integer y returns integer
	return x+y
	call Bleh() //line is never reached because of the return above
endfunction

function Add2 takes nothing returns notihng
	call Add(5, 7)
endfunction

JASS:
function Bleh takes nothing returns nothing
endfunction

//this example does the exact same thing as the above, but it works.
function Add takes integer x, integer y returns integer
	return x+y
	call Bleh() //line is never reached because of the return above
	return 0
endfunction

function Add2 takes nothing returns notihng
	call Add(5, 7)
endfunction

A function that returns nothing may still have a return statement in it, but it doesn't need one. Returning nothing is just the return keyword by itself.
JASS:
function Bleh takes nothing returns nothing
	return
endfunction

//this works too
function Bleh2 takes nothing returns nothing
	return
	call Bleh() //line never reached
endfunction

A function that takes only a single argument does not need a comma separated list.
JASS:
function Bleh takes integer x returns nothing
endfunction

Function Naming Convention
Functions start with an uppercase letter and are camelcase-

HelloHello

JASS:
function HelloHello takes nothing returns nothing
endfunction

Exercises
Problem 1
Create a function called Add that takes an integer z and an integer z5 and returns a value. Make a function called Set that doesn't take anything and doesn't return anything.

Make it so that when Add is called, it returns the sum of z and z5 and two global integers whose values are 7 and 9. Make it so when Set is called, it sets the value of a third global integer value to Add and passes in the values of a global integer goo whose value is 16 and the value 4.

Name the globals add1, add2, and sets.

Paste this code below your Set function
JASS:
scope Display initializer init
	private function Print takes integer value returns nothing
		call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 90000, I2S(value))
	endfunction

	private function init takes nothing returns nothing
		call Set()
		call Print(sets)
	endfunction
endscope

After creating the code, run the map and see what number it displays.

Check the solution to see if you did it right.


Output: 36

JASS:
globals
	integer add1 = 7
	integer add2 = 9
	integer sets
	integer goo = 16
endglobals

function Add takes integer z, integer z5 returns nothing
	return z+z5+add1+add2
endfunction

function Set takes nothing returns nothing
	set sets = Add(goo, 4)
endfunction

scope Display initializer init
	private function Print takes integer value returns nothing
		call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 90000, I2S(value))
	endfunction

	private function init takes nothing returns nothing
		call Set()
		call Print(sets)
	endfunction
endscope
Problem 2
Make a function called Do that takes a real z. Set the z value to whatever it is times 5 and then return it divided by a global integer q that has a value of 8. Make it return z.

Make a function called DoDo that passes 4 into Do and passes the result of Do into Print
JASS:
function Print takes real value returns nothing
	call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 90000, R2S(value))
endfunction

Paste this code below DoDo
JASS:
scope Display initializer init
	private function init takes nothing returns nothing
		call DoDo()
	endfunction
endscope

After creating the code, run the map and see what number it displays.

Check the solution to see if you did it right.


Output: 10

JASS:
globals
	real q = 8
endglobals

function Do takes real z returns real
	set z = z*5/q
	return z
endfunction

function Print takes real value returns nothing
	call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 90000, R2S(value))
endfunction

function DoDo takes nothing returns nothing
	call Print(Do(4))
endfunction

scope Display initializer init
	private function init takes nothing returns nothing
		call DoDo()
	endfunction
endscope
 
Level 19
Joined
Oct 15, 2008
Messages
3,231
I'm really really sorry... I just seem really confused at programming. But I won't mind, I'll just keep trying until I get it:)
Uhm... Are there other programming languages in Warcraft III too?
 
Level 19
Joined
Oct 15, 2008
Messages
3,231
Hmm... Well I'll try learning JASS first then, do pop by to give me a question Nestharus:)

PS: Oh, and by any language do you really mean any language? Meaning even Java and C ?
 
Level 19
Joined
Oct 15, 2008
Messages
3,231
Hmm... Is there another program then, which allows majority of the players to play on maps using other languages?
 
Level 19
Joined
Oct 15, 2008
Messages
3,231
Okay then:)
Would you give me a basic question to test my current knowledge of JASS, I'd love to see how far I've come.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
1. What are two methods for achieving recursive event data when creating custom events?

2. How are structs instantiated? Please create an array struct with a create and destroy method.

3. What is a dequeue? Create a single instance. Create a multiple instance dequeue.

4. What is a stack? Show two types of stacks.

5. What is a queue?

6. With a dequeue, show another method of recycling instantiated instances.

7. What is faster? Looping through an array or looping through a linked list?

8. How would you desync a game with GetLocalPlayer?

9. What is the proper method for enumerating over all units on the map? Please write out the code.

10. Should initialization for a script be done in a module onInit method, a struct onInit method, a library initializer, or a scope initializer?

11. What precisely is the difference between a boolexpr and a filterfunc?

12. Why is it bad practice to use TriggerRemoveCondition?

13. How are triggers run in events? Show the entire model.

14. What is faster on an event: an action or a condition? Why?

15. What is faster: TriggerExecute or TriggerEvaluate? Why?

16. Why do people avoid ExecuteFunc?

17. How would you retrieve the name of a method and then display its entire name including proper scoping.

18. How would you check to see if a method exists in a module that's implemented into a struct?

19. How would you only put a global into a map if another global was true?

20. How do you chain boolexprs together?

21. What is the order of operations in boolean expressions.

22. How many seconds can decay run for before it fires off the decay event.

23. Why does undefend fire one to two times in unit indexing?

24. How would you retrieve the gold cost of an item?

25. What's faster, SetUnitPosition or SetUnitX + SetUnitY and why?

26. What is an indexed array?

If you can answer all of those, you are well on your way to becoming a pro : P.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Well, you guys could do a little research so that you can better learn this stuff. I know some of the answers are in my old vjass guide on TH, like the order of operations in boolean expressions. Other answers can be found in common.j.

If you look at Event scripts as well as the TriggerRegister stuff, you can figure out how events run in JASS as well as the answers on conditions and actions.

If you read up on ExecuteFunc, especially concerning benchmarks, you'll learn why it is typically avoided.

If you look at SC2, you'll learn why strings are slow in wc3 ; P.

Etc etc

Yes, I know all the answers, but it's best to learn them on your own and discuss your findings so that they stick with you and so that you fully understand them ; D.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
1. What are two methods for achieving recursive event data when creating custom events?

When events are run, data is normally associated with that event.
GetTriggerUnit
GetAttacker
GetTriggerPlayer

When creating custom events, it is easy enough to do this
JASS:
globals
    private trigger myEvent = CreateTrigger()
    private integer data = 0
endglobals

function OnMyEvent takes boolexpr c returns nothing
    call TriggerAddCondition(myEvent, c)
endfunction
function FireMyEvent takes integer d returns nothing
    set data = d
    call TriggerEvaluate(myEvent)
endfunction
function GetEventData takes nothing returns nothing
    return data
endfunction

But this can result in a problem.
JASS:
function Test takes nothing returns boolean
    local integer d = GetEventData() //d is now 1
    if (d == 1) then
        call FireMyEvent(2) //set d to 2
    endif
    if (d != GetEventData()) then
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "RECURSION ERROR!")
    endif
    return false //to prevent trigger actions from being run for no reason
endfunction
function Init takes nothing returns nothing
    call OnMyEvent(Condition(function test))
    call FireMyEvent(1) //data is now 1
endfunction

In events, event data should always be the same data as it was when the event first fired. In the above scenario, the data was first 1 but then becomes corrupted at 2. While this doesn't seem to be an issue, it can be a serious issue.

JASS:
//this will fire second
function Test2 takes nothing returns boolean
    //remember that the event data become corrupt on the first fire?
    local integer d = GetEventData() //2 on first and second fires
    return false
endfunction

//this will fire first
function Test takes nothing returns boolean
    local integer d = GetEventData() //d is now 1
    if (d == 1) then
        call FireMyEvent(2) //set d to 2
    endif
    if (d != GetEventData()) then
        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "RECURSION ERROR!")
    endif
    return false //to prevent trigger actions from being run for no reason
endfunction
function Init takes nothing returns nothing
    call OnMyEvent(Condition(function Test))
    call OnMyEvent(Condition(function Test2))
    call FireMyEvent(1) //data is now 1
endfunction

And thus the major recursion error.

Fire (1)
----run test1 (1->2)
--------Fire (2)
------------run test1 (2)
------------run test2 (2)
----run test2 (2)

There are two methods for solving this recursion error. The first poor way is to create an array type stack.

JASS:
globals
    private trigger myEvent = CreateTrigger()
    private integer stack = 0
    private integer array data
endglobals

function OnMyEvent takes boolexpr c returns nothing
    call TriggerAddCondition(myEvent, c)
endfunction
function FireMyEvent takes integer d returns nothing
    set stack = stack + 1 //increase the stack, thus making a new spot for event data
    set data[stack] = d //event the new spot to our current data
    call TriggerEvaluate(myEvent) //fire
    set stack = stack - 1 //revert to previous data
endfunction
function GetEventData takes nothing returns nothing
    return data[stack]
endfunction

If I were to fire the second example, it would run in this order-
Test1- data 1
Test1- data 2
Test2- data 2
Test2- data 1

For a clearer understanding-
Fire (1)
----run test1 (1)
--------Fire (2)
------------run test1 (2)
------------run test2 (2)
----run test2 (1)

As can be seen, the data is maintained ; D.

The other and better way is by using locals to store the data to save on an array and a global declaration.

JASS:
globals
    private trigger myEvent = CreateTrigger()
    private integer data = 0
endglobals

function OnMyEvent takes boolexpr c returns nothing
    call TriggerAddCondition(myEvent, c)
endfunction
function FireMyEvent takes integer d returns nothing
    local integer prev = data //store the previous data in a local
    set data = d
    call TriggerEvaluate(myEvent)
    set data = prev //set the data back to the previous value
endfunction
function GetEventData takes nothing returns nothing
    return data
endfunction

This essentially does the same thing as the stack method but faster. Array reads are also quite a bit slower than var reads, so it's a better design.

I'll answer this tomorrow
->2. How are structs instantiated? Please create an array struct with a create and destroy method.

I'd prefer someone else to answer it on this thread by tomorrow. Please answer if you learned the answer to this within the last day. The answer and fully commented code can be found on this thread *hint hint*


Interesting new Question
What do you suppose this does? //! i local id = getvarobject("nfr2", "units", "UNITS_UNIT_EVENT")

Inside of script that uses
Somewhere
//! import "luajass.FILE_NAME.j"

The imported file before that function was run (doesn't exist)
--------------------------------------------------
After function was run for ABILITIES_UNIT_INDEXER
JASS:
globals//globals
constant integer ABILITIES_UNIT_INDEXER='A!!!'
endglobals//endglobals

After function was run for UNITS_UNIT_EVENT
JASS:
globals//globals
constant integer ABILITIES_UNIT_INDEXER='A!!!'
constant integer UNITS_UNIT_EVENT='n!!!'
endglobals//endglobals
--------------------------------------------------

In a function in map script
set u = CreateUnit(Player(14), UNITS_UNIT_EVENT, WorldBounds.maxX, WorldBounds.maxY, 0)

OM code (generates objects)
JASS:
   //! i createobject("nfr2", id)
    //! i makechange(current, "unam", "Unit Event")
    //! i makechange(current, "unsf", "(Unit Event)")
    //! i makechange(current, "uico", "")
    //! i makechange(current, "uine", "0")
    //! i makechange(current, "udro", "-")
    //! i makechange(current, "usnd", "")
    //! i makechange(current, "ushb", "")
    //! i makechange(current, "umdl", "")
    //! i makechange(current, "uubs", "")
    //! i makechange(current, "ides", "")
    //! i makechange(current, "utip", "")
    //! i makechange(current, "usca", ".01")
    //! i makechange(current, "ussc", ".01")

    //! i local j = ((jass.globals.create(jassread())):read("ABILITIES_UNIT_INDEXER")).value:sub(2,5)
    //! i makechange(current, "uabi", "Aloc," .. j)
    //! i makechange(current, "ubdg", "0")


Grimoire Samples omtest.lua file (in case you don't know om tool)
Code:
setobjecttype("units") -- units, items, doodads, destructables, abilities, buffs, upgrades
mergefile("input.w3u", import) -- merge, replace, import

setobjecttype("doodads")
mergefile("input.w3d", replace)

setobjecttype("abilities")
mergefile("input.w3a", merge)
mergefile("more.w3a", merge)

if objectexists("AHbz") then
  modifyobject("AHbz")
  if (currentobject() == "AHbz") then
    logf(currentobjecttype(), currentobject()) -- write debug information to log
    makechange(current, "Tip", 3, "Lame Level 3 Tooltip")
    makechange(current, "Cool", 2, 99.5)
    makechange(current, "achd", 1)
    makechange(current, "alev", 4)
  end 
end

if objectexists("S000") then
  createobject("S000", "Sxyz") -- new id will be Sxyz
  if (currentobject() == "Sxyz") then
    logf(currentobjecttype(), currentobject()) -- write debug information to log
    makechange(current, "Hotkey", "Q")
    makechange(current, "Name", "My Chaos")
    makechange(current, "EditorSuffix", "(Peasant)")
    makechange(current, "CheckDep", 0)
    makechange(current, "Cha1", 1, "hpea")
  end
end

if objectexists("AHbz") then
  createobject("AHbz", generateid("AHbz")) -- new id will be generated as substitute for the passed AHbz id
  if (currentobject() ~= "") then -- "" would indicate that we do not have a current object
    logf(currentobjecttype(), currentobject()) -- write debug information to log
    makechange(current, "Levels", 10)
    makechange(current, "Tip", 6, "Blizzard Level 6")
    makechange(current, "ResearchTip", "Learn Blixxard")
    makechange(current, "Tip", 5, "fuckfuckfuckfuckfuck")
    resetchange(current, "Tip", 5) -- due to bad language
  end
  createobject("AHbz", generateid("AHbz"))
  if (currentobject() ~= "") then
    logf(currentobjecttype(), currentobject()) -- write debug information to log
    makechange(current, "Name", "LOL")
    resetobject(current)
  end
end

setobjecttype("doodads")
createobject("ZOss", generateid("ZOss"))
createobject("ZOss", generateid("ZOss"))
createdid = currentobject()

-- we set this again because the modded, unmodded and custom groups refer to the state of the last time we called setobjecttype
setobjecttype("doodads")
makechange(custom, "dmis", 0.55) -- min scale for all custom doodads
makechange(original, "dmas", 300) -- max scale for all original doodads
makechange(unmodded, "dmis", 0.99) -- min scale for all unmodded original doodads
resetchange(modded, "dmas") -- max scale for all modded original doodads
modifyobject(createdid)
resetobject(current) -- resetobject also works with custom, original, unmodded, modded groups


And this is the resource-
http://www.hiveworkshop.com/forums/submissions-414/snippet-lua_get_var_object-185944/

This is pretty much most of what you need to know concerning lua ;P.
 
Level 19
Joined
Oct 15, 2008
Messages
3,231
Thank you so much Nes!
I'll try figuring them out first though, before reading the answers.
Also, I hope this isn't too much but, would you give me a simple question about JASS (Just one) just so that I can test out what I've learnt in terms of placing words in JASS?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
->Also, I hope this isn't too much but, would you give me a simple question about JASS (Just one) just so that I can test out what I've learnt in terms of placing words in JASS?

Try the exercises in chapter 7 functions
http://www.hiveworkshop.com/forums/1805960-post153.html

edit
New lua Convention up >: D

JASS:
//! externalblock extension=lua FileExporter $FILENAME$
    //! runtextmacro LUA_FILE_HEADER()
    //! i installscript([[function Hello() print("hi") end]], "1.0", "MyScript")
    //! i usescript("MyScript")
    //! i installjass([[
        //! i struct Tester extends array
            //! i private static method onInit takes nothing returns nothing
                //! i call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "hello world")
            //! i endmethod
        //! i endstruct
    //! i ]], "1.0", "MyScript")
//! endexternalblock

http://www.hiveworkshop.com/forums/submissions-414/snippet-lua_file_header-186775/


Since I'm like the only lua coder in entire community across wc3c, th, and thw, I GET TO DECIDE CONVENTION, FUAHAHAHAA >: D

I will change convention daily cuz I rock so much! >: O

I have released 140 hidden scripts on to the net for installing lua scripts. It is your mission to collect them all >: O.
 
Level 19
Joined
Oct 15, 2008
Messages
3,231
That's great to hear:)
I'll try answering them, do keep the questions flowing!

About the first question, how did you get the answer?
 
Last edited:
Status
Not open for further replies.
Top