• 🏆 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] Learning JASS. Last Question

Status
Not open for further replies.
Level 16
Joined
Mar 3, 2006
Messages
1,564
JASS:
struct pair
    integer x=1
    integer y=2
endstruct
 
function pair_sum takes pair A, pair B returns pair
 local pair C=pair.create()
    set C.x=A.x+B.x
    set C.y=A.y+B.y
 return C
endfunction
 
function testpairs takes nothing returns nothing
 local pair A=pair.create()
 local pair B=pair_sum(A, A)
 local pair C=pair_sum(A,B)
 
    call BJDebugMsg(I2S(C.x)+" : "+I2S(C.y))
 
    //Dont forget, if you are not using an struct instance anymore, you destroy it
    call B.destroy()
    call C.destroy()
    call pair.destroy(A)
 
endfunction
It would display "3 : 6"
this what the manual says


Wouldn't it display "2 : 4"
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
globals can only be initialized by constants.
0 = a constant
pair.create() is a variable

The same goes for e.g. units:
null = a constant
CreateUnit(...) is a variable and isn't allowed either (if it's allowed by the compiler, it still won't work in-game)

That's also a good reason why you would use initializers.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Well that explains lot. Thanks
________________________

What are static members ? And their purpose ?
________________________

JASS:
scope cool
    public struct a
        integer x
    endstruct

    globals
        a x
        public a b
    endglobals


    public function test takes nothing returns nothing
        set b = a.create()
        set b.x = 3
        call b.destroy()
    endfunction

endscope

function test takes nothing returns nothing
 local cool_a x=cool_a.create()
    set a.x=6
    call a.destroy()
endfunction

In the globals block, removing public keyword from
JASS:
public a b
will yield different results ?

Also isn't public keyword supposed to be put in
JASS:
a x
because it is set outside the scope ?
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
What are static members ? And their purpose ?

Static members can be called on the type of the struct, instead of on an instance of the type. For example:

JASS:
struct Test
    static method func takes nothing returns nothing
    endmethod

    method func2 takes nothing returns nothing
    endmethod

endstruct

function One takes nothing returns nothing
    local Test t = Test.create()
    call t.func2()
    call t.destroy()
    call Test.func() // I don't need a variable t to be able to call func
endfunction

will yield different results ?
Yes. By using the public qualifier you can use b outside the scope by refering to it as "cool_b".
Without the public qualifier, you would use "b" instead of "cool_b".
With a private qualifier, you cannot reach variable b from outside the scope.

Also isn't public keyword supposed to be put in
No. If you make a public, then you must use cool_a outside the scope. Else, you can use "a".

JASS:
scope cool
    public struct Cooler
        integer x
    endstruct

    globals
        private Cooler a
        public Cooler b
        Cooler c
    endglobals


    public function test takes nothing returns nothing
        set a = Cooler.create()
        set a.x = 3
        call a.destroy()
    endfunction

endscope

function test takes nothing returns nothing
    set c = Cooler.create()
    set cool_b = Cooler.create() // since b is a public variable, it can only be reached outside the scope through adding a prefix "cool_".
    set cool_a = Cooler.create() // this is not allowed because a is private
endfunction
 
  • Initialization
    • Events
      • Map initialization
    • Conditions
    • Actions
When converted to JASS

JASS:
function Trig_Initialization_Actions takes nothing returns nothing
endfunction
//===========================================================================
function InitTrig_Initialization takes nothing returns nothing
    set gg_trg_Initialization = CreateTrigger(  )
    call TriggerAddAction( gg_trg_Initialization, function Trig_Initialization_Actions )
endfunction

Is this a native or BJ ? And where is the event 'Map Initialization' in the JASS code ?
Sorry if anyone already said this, but the Map Initialisation is nowhere.
Basicly its hidden in the InitTrig_Initialization function, which is called 'INIT' + 'TRIGGER' + 'NAME' Function. Basicly that runs the trigger on mapinit.

And how to learn: Everyone has another way (someone already pointed it out). I learned it by converting my GUI spells to vJASS, reading alot of Tutorials here and at Wc3c and getting teached by a few good projassers here.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
JASS:
struct point
        real x=0.0
        real y=0.0
        method move takes real tx, real ty returns nothing
            set this.x=tx
            set this.y=ty
        endmethod
    endstruct
    function testpoint takes nothing returns nothing
     local point p=point.create()
        call p.move(56,89)
        call BJDebugMsg(R2S(p.x))
    endfunction

When I say
JASS:
call p.move(56,89)

this means that tx = 56 and ty = 89 and set this.x = tx will set the real x to the value of tx (which is 56) and the same for ty. If what I said is right, what is the function of method keyword; I can set the value of point p in another function.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
This simply doesn't make any sense at all. Try to use more words and a better sentence speach. What you said is right, but I doubt I understand what this sentence was trying to mean.

What I mean is, if I could set each member of the struct without using the method keyword then what is the purpose of this keyword ?

Eleandor gave me an example and I understood how the example works yet I still don't know when to use this keyword.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Sorry if anyone already said this, but the Map Initialisation is nowhere.
Basicly its hidden in the InitTrig_Initialization function, which is called 'INIT' + 'TRIGGER' + 'NAME' Function. Basicly that runs the trigger on mapinit.
It's not hidden in there. Regardless of what event you use, InitTrig ALWAYS runs on map initialization. The "map initialization" event in GUI is converted to a "run on map init" checkbox on top of your trigger. InitTrig has nothing to do with the event.
The special thing about "map initialization" event is that it runs Trig_Initialization_Actions function, and not the InitTrig_Initialization function.

this means that tx = 56 and ty = 89 and set this.x = tx will set the real x to the value of tx (which is 56) and the same for ty. If what I said is right, what is the function of method keyword; I can set the value of point p in another function.
Well, one reason would be that you can convert a lot of "set x = y" lines to 1 single line. For example:
call point.move(x, y)
would otherwise have to be written as
set point.x = x
set point.y = y

Secondly, it's a common rule to make variables inside structs private. This means that any struct's member cannot be reached from outside the struct, e.g.
JASS:
struct point
    private real x=0.0
    private real y=0.0

    method move takes real tx, real ty returns nothing
        set this.x=tx
        set this.y=ty
    endmethod
endstruct

function testpoint takes nothing returns nothing
    local point p=point.create()
    call p.move(56,89) // this is allowed now
    set p.x = 56 // this is not allowed, since p.x is only visible to the struct itself, not to code using the struct.
    call BJDebugMsg(R2S(p.x))
endfunction

Thirdly, methods are basically functions that are "owned" by the struct, and written specifically for this struct. It can have many advantages, modularity being one of them.
Another advantage is that you hide the implementation of your new variable. Let's say I have:

JASS:
struct Car
    private Engine e
    private Wheel array wheel[4]

    method start takes nothing returns nothing
        call this.e.start()
    endmethod

    method turn takes boolean left returns nothing
        call this.wheel[0].turn(left)
        call this.wheel[1].turn(left)
    endmethod

endstruct
I, as a jass scripter who wants to use the Car struct, don't have to worry about making sure BOTH wheels turn to the left if I wish to turn. All I have to say is:
local Car c = Car.create()
call c.turn(false)

I never have to bother about thinking of turning both wheels, and I never have to worry about forgetting to turn one of my front wheels. I am certain that if I ask my car to turn to the left, my car will take care of the details. It's like in real life: if I turn left, I don't worry about making sure my left- and my rightwheel both turn to the same direction. I assume that whoever made the car has made sure it turns like it's supposed to turn.

Whenever you need to make a function that is very strongly related to your struct, you should make it a method.

Some other examples:
local Vector3D v1 = Vector3D.create(1, 2, 5)
local Vector3D v2 = Vector3D.create(5, 1, 0)
local Vector3D v3 = v1.sum(v2) // v3 is equal to v1 + v2. "sum" is a method of Vector3D, because it makes the sum of 2 vectors. Rather than having to say
set v3.x = v1.x + v2.x
set v3.y = v1.y + v2.y
set v3.z = v1.z + v2.z
// I can simply make the sum since it's part of vectors.
// Another good thing is that by saying v3 = v1.sum(v2), I hide the implementation of adding v1 to v2, so the implementation is hidden. When you decide to change the implementation of a vector (to make it more efficient, for example), you don't need to change ALL your code that sets v3.x = v1.x + v2.x. No, all you have to do is modify how the sum method works.

The purpose of the keyword is to use it when you want. I've spent the last few weeks coverting spells to vjass and I haven't once used methods. The important part is that you can.
Good code should use methods. If you avoid methods, because you don't need to use them, then why bother using vJass anyway because in the end, there's nothing vJass can do that jass can't do...
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
Methods are just functions in a struct, don't let it scare you :D

One question to Eleandor, why making a struct member private? I know that I make functions private because I don't want them to conflict with other functions, so I can for example have tons of private function Actions takes nothing returns nothing, but struct members can't conflict with anything, because it gets the prefix after the struct name, right?

The only reason I can think of right now would be in case when interfaces are involved...

EDIT: Hmm, it seems that [icode=jass] tags don't highlight the word "nothing" correctly.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
1) When I say a struct member, the word member does it include structs or just the standard variable-types ?

2) What is meant by class as in the manual:

Methods are just like functions, the difference is that they are associated with the class
and
Static methods or class methods do not use an instance

3) What is the difference between static and instance ?
 
Last edited:
It's not hidden in there. Regardless of what event you use, InitTrig ALWAYS runs on map initialization. The "map initialization" event in GUI is converted to a "run on map init" checkbox on top of your trigger. InitTrig has nothing to do with the event.
The special thing about "map initialization" event is that it runs Trig_Initialization_Actions function, and not the InitTrig_Initialization function.
Am I totally wrong or are you wrong? I mean the INIT_TRIG_XXX activated the trigger to be runned on the map init. The function which is runned is the _Action function, but without the init trigger, the action function won't be runned, would it?
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Am I totally wrong or are you wrong? I mean the INIT_TRIG_XXX activated the trigger to be runned on the map init. The function which is runned is the _Action function, but without the init trigger, the action function won't be runned, would it?

I noticed that in GUI if you have the event |Map Initialization| then turned the trigger to custom text there is a check box above says "Run on Map Initialization", when I deleted the event |Map Initialization| I found the the check box is unchecked. Also, every trigger that don't have this event I found the check box is unchecked which means that in order to run the trigger at map initialization you need only to check that box and there is no function or special name for the trigger to run at map initialization.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
I need help with the topic #120 please.

Also, I don't understand the purpose of using interface ?
________________________________________________

When I say
JASS:
struct complex
real r
real i
endstruct
 
function ComplexNumber takes real r1 , real r2 returns complex
local complex C = complex.create()
return C
endfunction

Is C called an Instance ? and if I used static keyword I don't need to make the Instance C; just use the struct type (complex). Is that right ?
 
Last edited:
Level 8
Joined
Aug 4, 2006
Messages
357
why making a struct member private?
it's good to make struct variables private to create a sense of encapsulation. encapsulation allows structs to fulfill their intended purpose without being tampered with from the outside. say you have a "watch" struct. on the inside, it works in complicated ways with gears and electronics that interact with each other. from the outside, all you care about is that the watch keeps track of time, and can tell you the current time when you ask for it. you don't want to be able to access those gears and things individually because you might screw them up and keep the struct from telling you the proper time. you would want to use private methods and variables for all the internal time keeping. the only thing you would want to be public would be a method that tells the current time and a method that allows you to reset the time.

@Starquizer 1) When I say a struct member, the word member does it include structs or just the standard variable-types ?

I am actually getting a little confused over what the word "member" means. :hohum: sorry.

2) What is meant by class as in the manual:

the word "class" is synonymous with "struct", in this case. what the manual means is that methods are functions that are defined inside a struct.

3) What is the difference between static and instance ?

an instance of a struct is a variable that is defined as that struct variable. for example,
JASS:
struct cup
    real radius
    real height
endstruct

//this is creating an instance of the cup struct
cup fattyCup = cup.create()
set fattyCup.radius = 500
set fattyCup.height = 800

static variables or methods are things that are the same for the whole struct. did you notice that to create an instance of the cup class we did "cup.create()"? create is a static method! it makes sense that all cups should be created in the same manner. here's another example of static usage.

JASS:
struct cup
    private real radius
    private real height
    private static string description = "this is the cup struct"

    static method printDescription takes nothing returns nothing
        call BJDebugMsg(cup.description)
    endmethod
endstruct

//then you could do
call cup.printDescription()
//and it would display "this is the cup struct"
notice that i made the static description variable private? this is so that outside sources cannot set cup.description = "this is a gay struct. roflcopter. owned" (or something else) yet we can still display the description.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
One question to Eleandor, why making a struct member private? I know that I make functions private because I don't want them to conflict with other functions, so I can for example have tons of private function Actions takes nothing returns nothing, but struct members can't conflict with anything, because it gets the prefix after the struct name, right?


Firstly because it's considered to be a rule amongst programmers. It's a design choice to hide the implementation of your structs.
Just look at units. To get the unit's hit points you must use GetUnitState(u, UNIT_STATE_LIFE). They've written a function that does this. They could have also just added something like set u.hitpoints = u.hitpoints +5, but then didn't.
Secondly because it can be the cause of bugs. To give a similar example with units:

If I could say:
set u.hitpoints = -1

Then the unit would STILL be on the map, because u.hitpoints is nothing more than a variable. Still, it would be logical to assume a unit to be dead when he's got negative hit points, right?
SetUnitState() however takes care of other details too. On top of changing u.hitpoints, SetUnitState also checks if the new hitpoints are negative. If it's negative, SetUnitState will make sure the unit actually dies. Therefor, it is important that you, as the programmer of the new datatype, make sure that whoever uses the datatype uses it correctly, in order to avoid bugs.

Often it will still be useful to make members readonly. As you could guess from the name: this means you can "read" the member but cannot modify it (unless through methods). This allows you to safely retrieve info from a struct without screwing things up.

1) When I say a struct member, the word member does it include structs or just the standard variable-types ?
A struct member is... well, a member of a struct :p
JASS:
struct MyStruct
    private integer var // this is a member
    method Test takes nothing returns nothing // this is also a member.
    endmethod
    // Still, 90% of the time that we speak of structmembers, we refer to the variables, and not to the methods. Generally, the "variables" are the struct's members, and the "functions" are the struct's methods.

2) What is meant by class as in the manual:
structs and classes, while not being completely the same in many languages, are the same thing in jass. Well, technically, there's no such thing as a "class" in jass. But talking about classes and talking about structs is talking about the same thing.

3) What is the difference between static and instance ?
Let me give some examples to explain the terminology:
JASS:
struct Human
    readonly string name
    public static integer default_legs = 2
    readonly integer legs = 2

    method CarAccident takes nothing returns nothing
        set this.legs = 1 // ouch
    endmethod
endstruct

// ...
local Human eleandor = Human.create()
local Human starguizer = Human.create()
call eleandor.CarAccident()
call BJDebugMsg(I2S(eleandor.legs)) // display 1
call BJDebugMsg(I2S(eleandor.default_legs)) // display 2
set eleandor.default_legs = 1 // I know: wtf am I doing now?
call BJDebugMsg(I2S(starguizer.default_legs)) // display 1

A "Human" is a definition. It "defines" what a Human is. In this case, a Human is defined as something that has a name, and an amount of legs.
eleandor is called an "instance" of a human. eleandor behaves like a human, but has specific characteristics. In this case, I've had a caraccident which is why I only have 1 leg. But even though I have special attributes, I'm still a human. Because I'm able to have special attributes, I'm called an "instance" of a human.
You too are an "instance" of a Human.
eleandor.legs will clearly display "1", because I only have 1 leg.
eleandor.default_legs will show "2". default_legs is the same for every instance of "Human". It is an attribute of "Humans" in general.
If eleandor.default_legs would be changed into 1, starguizer.default_legs TOO will now be 1. However, starguizer.legs will still be 2.

static methods or static variables are variables that are "generic", they count for the whole struct type. normal methods/variables however perform specific actions on an instance of a struct. For example: a specific instance can have a car accident which changes that specific instance's legs.

The same is said for other variables:
local unit u = CreateUnit(...) // u is an "instance" of type "unit".

P.s. I still have both legs, this is just an example ;)
P.p.s. ok, maybe that's a really strange example... but it's the best I can do :p
P.p.p.s. Indeed, "C" in your example is an instance of the "complex" type.

Am I totally wrong or are you wrong? I mean the INIT_TRIG_XXX activated the trigger to be runned on the map init. The function which is runned is the _Action function, but without the init trigger, the action function won't be runned, would it?

No, you're wrong (sorry :p)
The InitTrig action runs on map initialization, regardless of whether you want or not. InitTrig makes sure the trigger itself gets initialized by adding events, conditions and actions to it.
Without the InitTrig function, there IS no trigger.
However, through 'run on map init', you can run the Actions, regardless of whatever you wrote in InitTrig.

Also, I don't understand the purpose of using interface ?
An interface is there so you can use the same rules for your structs. For example, if you implement:
JASS:
interface Creature
    method moveTo takes real x, real y returns nothing
endinterface

struct Human extends Creature // Notice: a human "extends" a Creature. It means that a Human "is" a creature, just with some more specific features
    method moveTo takes real x, real y returns nothing
        // Do stuff to make the human move
    endmethod
endstruct

struct Fish extends Creature
    method moveTo takes real x, real y returns nothing
        // Do different stuff to make the fish move
    endmethod
endstruct

// Somewhere...
local Creature c = Human.create() // c is of type "Human" but can also be called "Creature" because a "Creature" is a more general way of calling you "Human".
local Creature d = Fish.create()

call c.moveTo(-2.0, 52.0)
call d.moveTo(-5.0, 50.0)

A struct that extends an interface inherits all of the interface's abilities (this means: a struct must have all the interface's members and methods), and is supposed to extend on this interface.

I personally don't use interfaces now that struct inheritance & stub methods are possible (read more on this further in the vjass manual).
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Another really-good-example (Total Rep owed +2 :thumbs_up:)
<<EDIT>>
P.s. I still have both legs, this is just an example ;)
Yes, I know its an example but a funny one :smile:
________________________________________________

JASS:
interface withpos
        real x
        real y
    endinterface
 
    struct rectangle extends withpos
        real a
        real b
 
        static method from takes real x, real y, real a, real b returns rectangle
         local rectangle r=rectangle.create()
            set r.x=x
            set r.y=y
            set r.a=a
            set r.b=b
            return r
        endmethod
 
    endstruct
 
    struct circle extends withpos
        real radius=67.0
 
        static method from takes real x, real y, real rad returns circle
         local circle r=circle.create()
            set r.x=x
            set r.y=y
            set r.radius=rad
            return r
        endmethod
 
    endstruct
 
 
    function distance takes withpos A, withpos B returns real
     local real dy=A.y-B.y
     local real dx=A.x-B.x
 
     return SquareRoot( dy*dy+dx*dx)
    endfunction
 
    function test takes nothing returns nothing
     local circle c= circle.from(12.0, 45.0 , 13.0)
     local rectangle r = rectangle.from ( 12.3 , 67.8, 12.0 , 10.0)
 
         call BJDebugMsg(R2S(distance(c,r)))
 
    endfunction
Will the message displayed be 22.801 ?

If it is right then I have understood how interface works.

Also another question, the function distance takes withpos A, withpos B yet when it was called through BJDebugMsg(R2S(distance(c,r)) neither c nor r are withpos, this is allowed because both circle and rectangle extend withpos ?
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
:confused: I don't understand.

Not that you'll get it, but this is what I mean:
Code:
class withpos
{
    ...
};

class rectangle:public withpos
{
    ...
};

class circle:public withpos
{
    ...
};

float distance(withpos* A,withpos* B)
{
    ...
}

It isn't important to you, don't worry about it.

Also, about the "what's the difference between a struct and a class" question - originally in the 'C' programming language you could define your own data types called structures (structs for short) which could contain other data types inside them (not functions).
Later on, 'C++' - which is kind of an extension to C - added 'classes', which are structs, but you can also put instance functions in them (aka methods). In C++ you can also do this to structs, so today they basically have no differences (there are a few, but they don't really matter).

Anyway, most programming languages today just have classes, which are equivalent to JASS's structs.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564

JASS:
interface A
    integer x
endinterface
 
struct B extends A
    integer y
endstruct
 
struct C extends A
    integer y
    integer z
endstruct
 
function test takes A inst returns nothing
   if (inst.getType()==C.typeid) then
     // We know for sure inst is actually an instance of type C
       set C(inst).z=5 //notice the typecast operator
   endif
   if (inst.getType()==B.typeid) then
       call BJDebugMsg("It was of type B with value "+I2S( B(inst).y  ) )
   endif
endfunction


1) How can we compare inst type (Which is an interface) by C type (Which is a struct) like in this line
JASS:
inst.getType()==C.typeid

2) C(inst).z What is this argument of C; C is a struct type how can a it take an argument, also the integer z is already in C struct so I should say
  • set C.z = 5
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
You would like to know the type of the sturct in case it has different members and/or methods then the other extending structs.

Here's an example:
JASS:
interface Rect
    real x
    real y
    real z // not really needed in warcraft
    
    method setPosition takes real x,real y,real z returns nothing
        .x = x
        .y = y
        .z = z
    endmethod
endinterface

struct Rect2D extends Rect
    real width
    real length
    
    method setSize takes real width,real length returns nothing
        .width = width
        .length = length
    endmethod
endstruct

struct Rect3D extends Rect
    real width
    real length
    real height
    
    method setSize takes real width,real length,real height returns nothing
        .width = width
        .length = length
        .height = height
    endmethod
endstruct

In order to know what setSize() to call, you need to know the type of the struct.

I am not sure if you actually HAVE to use it in Jass, but looking at the example you gave it looks like you do.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
What was shown there is a concept called typecasting, in which you make a type "act" like another type.

A C++ easy example would be int i = (int)1.5 which will make the 1.5 which is a float (equivalent to Jass's "real") to act like an integer and by that it will convert it to 1.
In Jass that would be the R2I function.

Now, by saying inst.getType()==C.typeid you compare the type of the instance called "inst" to the type of the struct 'C'.
I -suppose- that Vexorian stuck an integer that represents that type.
So, for example, the first struct you define will get the type '0', the second '1', etc. Of course this is just a guess, I have no idea how he actually did it.

By C(inst).z what that example means is - make the struct instance called "inst" act like a C type. This is used here because you do not know before-hand what the type is.

Again, I am not sure if you must use these things, although in C++ you'd probably end up with the same thing (a constant member that represents what that struct/class is).
 

Cokemonkey11

Code Reviewer
Level 29
Joined
May 9, 2006
Messages
3,522
Why in some (or most) vJASS spells we use structs; since they already contain variables like integers, units and unit group etc why can't we use them in the functions directly without using structs ?

In the backend after jasshelper compiles it to standard jass, that's exactly what it does.

structs are just easier to read and handle.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564

This is as far as I read, must I continue to read all the contents ?
There are many things that I read I still not understand it properly. (It marked in the hidden part)
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
SCOPE_PREFIX and SCOPE_PRIVATE

It's basically used when you want to get the prefix of a private member outside the scope, but you probably don't.

The onDestroy method

Useful little fella. It's mostly for organizing your code, this method will run when you destroy that struct instance. So there you can do all the detaching, destroying effects blabla, since it runs right before the struct is destroyed (I think).

The onInit method

Like an initializer in libraries and scopes. This method will run on map initialization. What don't you understand about it?

Interfaces

Handy thingies, but I never seem to use them. For example, you know that units are widgets and widgets are handles? So widget is everything that has a health bar (destructable, unit, item etc.) so it's like a parent, but a handle is everything except real, integer, string, boolean and code, so handle is a parent to widget. Get it?

In the same manner, interfaces are parents to some structs which extend them. When you have multiple structs which extend a single interface and you need a function which takes those structs as parameters, you can use that interface as parameter (if you don't know which struct you're going to pass as a parameter).
 
Level 3
Joined
Aug 9, 2008
Messages
60
SCOPE_PREFIX and SCOPE_PRIVATE

It's basically used when you want to get the prefix of a private member outside the scope, but you probably don't.

The onDestroy method

Useful little fella. It's mostly for organizing your code, this method will run when you destroy that struct instance. So there you can do all the detaching, destroying effects blabla, since it runs right before the struct is destroyed (I think).

The onInit method

Like an initializer in libraries and scopes. This method will run on map initialization. What don't you understand about it?

Interfaces

Handy thingies, but I never seem to use them. For example, you know that units are widgets and widgets are handles? So widget is everything that has a health bar (destructable, unit, item etc.) so it's like a parent, but a handle is everything except real, integer, string, boolean and code, so handle is a parent to widget. Get it?

In the same manner, interfaces are parents to some structs which extend them. When you have multiple structs which extend a single interface and you need a function which takes those structs as parameters, you can use that interface as parameter (if you don't know which struct you're going to pass as a parameter).

Actually onInit method doesn't run on map initialization, it runs when the first instance of the struct is created.
 
This is a template for creating spells which need to, for example, move something smoothly (such as a missile). Use it if you want.
JASS:
scope SpellTemplate initializer Init

private keyword Data

globals
    private constant real TIMER_INTERVAL = 0.035
    private constant integer ABIL_ID = 'A000' //change this to the rawcode of your spell
    //Other constant globals here...
    

    private Data array data
    private integer index=0
    private timer tim
    
    //Other changeable globals here...
    
endglobals

private function Execute takes nothing returns nothing
    local integer i=0
    local Data d
    //Other local variables here...
    
    
    loop
        exitwhen i>=index
        
        set d=data[i]
        
        //Code to run each timer execution here...
        
        
        set i=i+1
    endloop
    //Any leak cleaning code here...
    
endfunction

private struct Data
    //Declare struct members here...
    unit caster
    
    integer ID
    
    static method create takes unit caster returns Data //make sure you change this based on what data you need
        local Data d = Data.allocate()
        
        //Other create code here...
        
        
        set data[index]=d
        set d.ID=index
        if index==0 then
            call TimerStart(tim, TIMER_INTERVAL, true, function Execute)
        endif
        set index=index+1
        
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        set index=index-1
        set data[this.ID]=data[index]
        set data[this.ID].ID=this.ID
        
        if index==0 then
            call PauseTimer(tim)
        endif
        //Other destroy code here (such as leak cleaning, removing units etc)...
        
    endmethod
    
endstruct

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction

private function Actions takes nothing returns nothing
    call Data.create(GetTriggerUnit()) //make sure you change this based on what data your spell needs
endfunction

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

    set tim = CreateTimer()
    //Other initialisation things here...
    
endfunction

endscope
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
JASS:
scope SpellTemplate initializer Init
 
private keyword Data
 
globals
    private constant real TIMER_INTERVAL = 0.035
    private constant integer ABIL_ID = 'A000' //change this to the rawcode of your spell
    //Other constant globals here...
 
 
    private Data array data
    private integer index=0
    private timer tim
 
    //Other changeable globals here...
 
endglobals
 
private function Execute takes nothing returns nothing
    local integer i=0
    local Data d
    //Other local variables here...
 
 
    loop
        exitwhen i>=index
 
        set d=data[i]
 
        //Code to run each timer execution here...
 
 
        set i=i+1
    endloop
    //Any leak cleaning code here...
 
endfunction
 
private struct Data
    //Declare struct members here...
    unit caster
 
    integer ID
 
    static method create takes unit caster returns Data //make sure you change this based on what data you need
        local Data d = Data.allocate()
 
        //Other create code here...
 
 
        set data[index]=d
        set d.ID=index
        if index==0 then
            call TimerStart(tim, TIMER_INTERVAL, true, function Execute)
        endif
        set index=index+1
 
        return d
    endmethod
 
    method onDestroy takes nothing returns nothing
        set index=index-1
        set data[this.ID]=data[index]
        set data[this.ID].ID=this.ID
 
        if index==0 then
            call PauseTimer(tim)
        endif
        //Other destroy code here (such as leak cleaning, removing units etc)...
 
    endmethod
 
endstruct
 
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction
 
private function Actions takes nothing returns nothing
    call Data.create(GetTriggerUnit()) //make sure you change this based on what data your spell needs
endfunction
 
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Actions)
    call TriggerAddCondition(t, Condition(function Conditions))
 
    set tim = CreateTimer()
    //Other initialisation things here...
 
endfunction
 
endscope

Some Questions:

1) I can't find the action that moves the unit (Missile Unit) to the destination.

2) There are lines that displays:
JASS:
set d=data[i]
What are this signs ?
 
Status
Not open for further replies.
Top