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

[JASS] Learning JASS. Last Question

Discussion in 'Triggers & Scripts' started by Starquizer, Jun 9, 2009.

  1. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    I didn't understand how stubs work, can someone please explain this method to me.
     
  2. Eleandor

    Eleandor

    Joined:
    Aug 21, 2005
    Messages:
    3,681
    Resources:
    2
    Models:
    1
    Tutorials:
    1
    Resources:
    2
    A stub method is a method that can be expanded by a struct's children.

    For example:

    Code (vJASS):

    struct Parent
        stub method sayHello takes nothing returns nothing
            call BJDebugMsg("Hello from the parent!")
        endmethod
    endstruct

    struct Child extends Parent // see: extend
        stub method sayHello takes nothing returns nothing // See: sayHello is already defined by the parent struct. This is not allowed, except when the method is a stub method.
            call BJDebugMsg("Hello from the child!")
        endmethod
    endstruct

    struct Grandchild extends Child
        stub method sayHello takes nothing returns nothing
            call super.sayHello() // super refers to the original struct, i.e. "Parent".
        endmethod
    endstruct

    struct Child2 extends Parent
        // We don't HAVE to redefine sayHello
    endstruct

    // In your code:
    local Parent p = Parent.create()
    local Parent c = Child.create() // Note: this is of local type "Parent", but it IS in fact a Child.
    local Parent g = GrandChild.create()
    local Child2 c2 = Child2.create()

    call p.sayHello() // displays: "Hello from the parent!"
    call c.sayHello() // displays: "Hello from the child!"
    call g.sayHello() // displays: "Hello from the parent!" --> because g calls super.sayHello()
    call c2.sayHello() // displays: "Hello from the parent!" --> because Child2 did not redefine sayHello, it simply uses sayHello that was already defined by Parent.
     
  3. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    I stumbled to another problem when I was trying to understand Vexorian's Table, the problem is that I can't understand the operator keyword, I tried to read the JassHelper manual about this many times and still don't understand this keyword or its examples, can someone help me with it please ?

    Thanks in advance.
     
  4. Element of Water

    Element of Water

    Joined:
    Aug 3, 2008
    Messages:
    2,298
    Resources:
    5
    Spells:
    3
    Tutorials:
    1
    JASS:
    1
    Resources:
    5
    Code (vJASS):
    struct Test
        private real x
        private real y
        unit u
        method operator x= takes real x returns nothing
            call SetUnitX(.u, x)
            set .x = x
        endmethod
        method operator x takes nothing returns real
            return .x
        endmethod
        method operator y= takes real y returns nothing
            call SetUnitY(.u, y)
            set .y = y
        endmethod
        method operator y takes nothing returns real
            return .y
        endmethod
    endstruct


    This is a common use of a method operator. Basically, putting the operator keyword there means you can call a method like it's just a variable. This means you can make the assignment of variables change things, such as the unit's position, really easily.
     
  5. maskedpoptart

    maskedpoptart

    Joined:
    Aug 4, 2006
    Messages:
    351
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Actually, it displays: "Hello from the child!" (I tested it). super actually gives you the struct that this struct extends from. Since GrandChild extends Child, it calls Child.sayHello().

    @Starguizer
    Table 3.0 code
    Code (vJASS):
    library Table
    //***************************************************************
    //* Table object 3.0
    //* ------------
    //*
    //*   set t=Table.create() - instanceates a new table object
    //*   call t.destroy()     - destroys it
    //*   t[1234567]           - Get value for key 1234567
    //*                          (zero if not assigned previously)
    //*   set t[12341]=32      - Assigning it.
    //*   call t.flush(12341)  - Flushes the stored value, so it
    //*                          doesn't use any more memory
    //*   t.exists(32)         - Was key 32 assigned? Notice
    //*                          that flush() unassigns values.
    //*   call t.reset()       - Flushes the whole contents of the
    //*                          Table.
    //*
    //*   call t.destroy()     - Does reset() and also recycles the id.
    //*
    //*   If you use HandleTable instead of Table, it is the same
    //* but it uses handles as keys, the same with StringTable.
    //*
    //*  You can use Table on structs' onInit  if the struct is
    //* placed in a library that requires Table or outside a library.
    //*
    //*  You can also do 2D array syntax if you want to touch
    //* mission keys directly, however, since this is shared space
    //* you may want to prefix your mission keys accordingly:
    //*
    //*  set Table["thisstring"][ 7 ] = 2
    //*  set Table["thisstring"][ 5 ] = Table["thisstring"][7]
    //*
    //***************************************************************

    //=============================================================
        globals
            private constant integer MAX_INSTANCES=8100 //400000
            //Feel free to change max instances if necessary, it will only affect allocation
            //speed which shouldn't matter that much.

        //=========================================================
            private hashtable ht
        endglobals

        private struct GTable[MAX_INSTANCES]

            method reset takes nothing returns nothing
                call FlushChildHashtable(ht, integer(this) )
            endmethod

            private method onDestroy takes nothing returns nothing
                call this.reset()
            endmethod

            //=============================================================
            // initialize it all.
            //
            private static method onInit takes nothing returns nothing
                set ht = InitHashtable()
            endmethod

        endstruct

        //Hey: Don't instanciate other people's textmacros that you are not supposed to, thanks.
        //! textmacro Table__make takes name, type, key
        struct $name$ extends GTable

            method operator [] takes $type$ key returns integer
                return LoadInteger(ht, integer(this), $key$)
            endmethod

            method operator []= takes $type$ key, integer value returns nothing
                call SaveInteger(ht,  integer(this)  ,$key$, value)
            endmethod

            method flush takes $type$ key returns nothing
                call RemoveSavedInteger(ht, integer(this), $key$)
            endmethod

            method exists takes $type$ key returns boolean
                return HaveSavedInteger( ht,  integer(this)  ,$key$)
            endmethod

            static method flush2D takes string firstkey returns nothing
                call $name$(- StringHash(firstkey)).reset()
            endmethod

            static method operator [] takes string firstkey returns $name$
                return $name$(- StringHash(firstkey) )
            endmethod

        endstruct
        //! endtextmacro

        //! runtextmacro Table__make("Table","integer","key" )
        //! runtextmacro Table__make("StringTable","string", "StringHash(key)" )
        //! runtextmacro Table__make("HandleTable","handle","GetHandleId(key)" )

    endlibrary


    Basically, operators are methods with different notation in vJass. The only types of method operators supported are "[]", "[]=", "<", and ">" (Edit: and the kind EOW talks about above). They are converted to regular method calls when you compile your map from vJass to regular Jass. "[]" is converted to a method that takes one parameter and returns something. "[]=" takes two parameters and returns nothing. "<" takes one parameter and returns a boolean. ">" takes one parameter and returns a boolean. Why would you want methods with different notation? Sometimes the modified notation is easier to understand and shorter to write.

    Let's look at how [] and []= operators work with Table. Suppose we make a Table object of integers.
    Code (vJASS):
    local Table intTable = Table.create()
    Then let's store the integer 5 at index 20.
    Code (vJASS):
    set intTable[20] = 5
    Wasn't that easy? It's just like storing stuff in an array. Suppose instead Vexorian used a regular method "setIndex" that takes two parameters.
    Code (vJASS):
    call intTable.setIndex(20, 5)
    Hmm... that's longer to type and not as easy to understand. Which one is the index and which is the integer we're storing? They're both in the parentheses so it's hard to tell. I like using the method operator better. Anyway, the method operator []= is really just a method in disguise. When vJass compiles, it creates a setindex method whose first parameter is the stuff between the [] and whose second parameter is the stuff after the =.
    Now let's get the integer we stored at index 20.
    Code (vJASS):
    intTable[20]
    Again, that was easy and intuitive. Better than having to do
    intTable.getIndex(20)
    .
    You still may be wondering what the static method operator [] does. Well, since it's static, it has to be called with the struct name. It takes a string and returns an instance of the struct. So, we can do
    Table["category1"]
    . Used by itself, this static method operator is useless. However, since it returns a struct instance, we can use it in combination with the regular method operators. For example,
    Code (vJASS):
    set Table["category1"][0] = 4
    Just pretend that it said "intTable" instead of "Table["category1"]".

    Anyway, I think that's enough for now. Just remember that method operators are really just methods with different syntax and limited uses.
     
  6. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    When I tested the manual example.

    manual example
    Code (vJASS):
        struct operatortest
            string str=""

            method operator [] takes integer i returns string
                return SubString(.str,i,i+1)
            endmethod

            method operator[]= takes integer i, string ch returns nothing
                set .str=SubString(.str,0,i)+ch+SubString(.str,i+1,StringLength(.str)-i)
            endmethod

        endstruct


        function test takes nothing returns nothing
         local operatortest x=operatortest.create()
            set x.str="Test"
            call BJDebugMsg( x[1])
            call BJDebugMsg( x[0]+x[3])

            set x[1] = "."
            call BJDebugMsg( x.str)
        endfunction


    It gave me during test:

    e
    Tt
    T.s

    But when I tracked it, I get different result:

    Te
    Tst
    T.es

    At the line
    call BJDebugMsg(x[1])


    i = 1 then the operator [] method return will be like this:
    SubString("Test",1,2) = Te

    And at the line
    call BJDebugMsg(x[0] + x[3])


    i = 0 then the operator [] method return will be:
    SubString("Test",0,1) = T

    i = 3 then SubString("Test",3,4) = st

    When concatinated: Tst

    for the last one:
    i = 1 , ch = "."
    SubString("Test",0,1) + "." + SunString("Test",2,3) = T.es

    I know this may seems nonsense but that is what I get. Anyway I get different results from game testing.
     
  7. Eleandor

    Eleandor

    Joined:
    Aug 21, 2005
    Messages:
    3,681
    Resources:
    2
    Models:
    1
    Tutorials:
    1
    Resources:
    2
    Element of Water: that won't compile because you're redefining x as an operator when it's already defined as a real.

    Mathematically speaking, an operator is "+", "-", "/", "*", "=", etc.
    There are some non-mathematical operators such as () for functions and [] for arrays.

    vJass allows you to redefine the [] operator, as well as the [] = operator. Table is a good example of this: the Table struct redefines [] and []= so you can use handles and strings as indices.
    e.g.
    table[GetTriggerUnit()] = 5
    ==> normally, you must use integers inbetween [] for arrays (e.g. arr[0]) but struct HandleTable has redefined the [] operator so you can use handles too.

    In addition to this, vJass allows you to create your own pseudo-operators. A pseudo-operator is just like a method, except that it doesn't require () to be called. For example:

    Code (vJASS):

    struct Test
        private real fx

        method getX takes nothing returns real
            return this.fx
        endmethod

        method operator x takes nothing returns real
            return this.fx
        endmethod
    endstruct

    // in a function:
    local Test s = Test.create()
    local real x = s.getX() // notice the ()
    local real y = s.x // notice no () are used.
    set s.x = 5 // NOT ALLOWED. s.x is an operator, NOT a variable, therefor you cannot assign a new value to it.

     

    In this example, s.x returns this.fx. Why can it be useful? Since this.fx is private, you cannot read the value of fx outside the struct. To solve this you could make a new method, or you could create a new operator. The advantage of the operator is that it looks like no method is being called, as if you're directly reading x.
     
  8. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    So Whats wrong with what I said in post #226 ?

    That means operators only allows me to use methods outside a struct ?
     
    Last edited: Aug 7, 2009
  9. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    I found what is the problem, it seems SubString is different than SubStringBJ in the start and end integers.

    Code (vJASS):
    function SubStringBJ takes string source, integer start, integer end returns string
        return SubString(source, start-1, end)
    endfunction


    Thanks for any attempts to help me.
     
  10. maskedpoptart

    maskedpoptart

    Joined:
    Aug 4, 2006
    Messages:
    351
    Resources:
    1
    Spells:
    1
    Resources:
    1
    Eleandor, when you want to be able to get a variable directly but not modify it, I think it's easier to specify the variable as readonly. You can put "readonly real fx" instead of "private real fx" and it will allow you to do the same thing without making method operators. However, when you need to do more than just return a variable (or set a variable), operators can be useful.
     
  11. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    Must [] operator takes integer and return ANYTHING ?

    and

    [] = operator takes 2 arguments, can't they take more than that ?
     
  12. Element of Water

    Element of Water

    Joined:
    Aug 3, 2008
    Messages:
    2,298
    Resources:
    5
    Spells:
    3
    Tutorials:
    1
    JASS:
    1
    Resources:
    5
    1. [] operator can take anything as an index, it can also return anything.
    2. The []= operator can only take two things - the index and the new value.
     
  13. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    Eleandor mentioned that in order to change a struct private member's value you need an operator, is that the only thing that an operator can do ?
     
  14. Element of Water

    Element of Water

    Joined:
    Aug 3, 2008
    Messages:
    2,298
    Resources:
    5
    Spells:
    3
    Tutorials:
    1
    JASS:
    1
    Resources:
    5
    Yeah. It basically makes it easier for the user. It won't make your code any more efficient in any way.
     
  15. Eleandor

    Eleandor

    Joined:
    Aug 21, 2005
    Messages:
    3,681
    Resources:
    2
    Models:
    1
    Tutorials:
    1
    Resources:
    2
    Operators are actually just like methods. The main difference is that you don't need to write (). And another difference is that methods cannot redefine [], []=, < or >.

    Other than that, operators are nothing more than syntactical sugar.
     
  16. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    I am confused a little, does tracking of triggers and functions is a good way to learn JASS and vJASS. I don't know, I feel that I have wasted a lot of time learning vJASS in that way.

    So I am asking learning that way is fruitfull or not ?
     
  17. Element of Water

    Element of Water

    Joined:
    Aug 3, 2008
    Messages:
    2,298
    Resources:
    5
    Spells:
    3
    Tutorials:
    1
    JASS:
    1
    Resources:
    5
    Tracking of triggers and functions???
     
  18. Vulcano

    Vulcano

    Joined:
    Mar 8, 2009
    Messages:
    335
    Resources:
    1
    Maps:
    1
    Resources:
    1
    I think he means reading other peoples code.

    @Starquizer: Maybe read Flaming Phoenix tutorial (here)and Silvenon knockback tutorial here.

    Those were quite useful to me.
     
  19. Starquizer

    Starquizer

    Joined:
    Mar 3, 2006
    Messages:
    1,526
    Resources:
    6
    Maps:
    1
    Spells:
    2
    Tutorials:
    3
    Resources:
    6
    Yes, like in loops you track the loop's index and see how variables' value change, its a slow method but effective especially when a code contains an error some where. Its like when you insert a msg function to display the value of a certain variable. That's what I mean by tracking a code.
     
  20. Element of Water

    Element of Water

    Joined:
    Aug 3, 2008
    Messages:
    2,298
    Resources:
    5
    Spells:
    3
    Tutorials:
    1
    JASS:
    1
    Resources:
    5
    You can't learn by doing that. You just correct stuff.