1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
  2. Welcome to the new Hive! Be advised that we're still working on the site. There are still many rough edges, so please bear with us.
    Dismiss Notice
  3. The member Kam is making HIVE coasters. Take a look. For every coaster you buy, Hive gets $1.
    Dismiss Notice
  4. The poll for Icon Contest #14 - Seven Deadly Sins is out!
    Dismiss Notice
  5. The 25th Texturing Contest has started! Contestants are to create a skin representing a dark elf person/being or any construct related to it using the vanilla models or the custom ones found on the site.
    Dismiss Notice
  6. Buy it, use it, break it, fix it, trash it, change it, mail - upgrade it. Join (Optionally) Paired Techtree Contest #11 - Techno Magic now!
    Dismiss Notice
  7. Voting squad, line up! Cast your vote on the poll for Modeling Contest #29 - Squads!
    Dismiss Notice
  8. Hero Contest #8 is up and running! This time it's a joint contest between artists and coders. Go here for team matchmaking.
    Dismiss Notice
  9. The poll for the theme of our StarCraft II Terraining Contest is up. Cast your note now!
    Dismiss Notice
  10. The ninth Concept Art Contest has launched. Enter now!
    Dismiss Notice

Basic Introduction to JASS

Discussion in 'World Editor Help Zone' started by Dezs, Dec 15, 2007.

  1. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Hmm, so if BJ functions leak, does it mean all of them? When I converted some of the GUI triggers, functions like expirationtimer got a BJ suffix, so those are leaky? If so, then my tower would be a hell of a leak esp since it adds up on every attack. How do I settle this (In simple coding of course)?

    Another problem I encourntered after a little thought is regarding the upgrading method I'm using. What I want to create is upgrades that stack on a tower without changing the base unit (simply adding abilities), but I can't figure out a method to perform this smoothly.

    I tried using the train unit, but obviously if I remove availability when the ability reaches max, all other towers lose it.

    If I use the upgrade method, The icon is messed up sicne it must upgrade into a building of the same type (An upgrade button with the same icon as the tower looks wierd). If I apply a different icon (just to illustrate the upgrade) from the tower's standard, it shows when the player selects multiple towers and looks wierd.

    If I use the research method (research, then reset the research to enable research again), I can't remove the research button when the ability reaches cap. Although I can create a trigger to refund and display a message, the research button stays there, which is not so nice.
     
    Last edited: Dec 18, 2007
  2. Dracula

    Dracula
    Joined:
    Jun 26, 2005
    Messages:
    511
    yea i tried to learn jass too before, but i dont get what their saying on most of the tuts but that counter strike spell is on youtube.
     
  3. Need_O2

    Need_O2
    Joined:
    Aug 24, 2007
    Messages:
    2,878
    umm DONT USE TUTORIALS :p
    find a jass example and learn

    Sorry Tutorial Submissionators (english has pwn3d)
     
  4. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    First of all, read this: http://www.hiveworkshop.com/forums/showthread.php?t=16456

    It's a great tutorial. I read it when I was first learning JASS and it helped me A LOT. After reading the tutorial I suggest you start making simple custom spells with JASS or open up spell demo maps and looking at the code - that's the fastest way to learn JASS once you know the basics.

    Now, as for your questions:

    1. No, you can't do it with GUI (at least not very efficiently if you want multi-instanceability) I'll let Daelin explain the rest here: http://www.hiveworkshop.com/forums/showthread.php?t=22710 (even includes instructions on how to create a knockback effect with JASS)
    2. Jasscraft (http://www.hiveworkshop.com/resources_new/tools/469/) has a function list for every function in existence in JASS (as well as names for blizzard-coded global variables like bj_lastCreatedUnit and such). The functions are listed with their parameters, what they return, and if they are not natives, what code they contain.
    3. No. I don't know how else you would expect to write JASS without typing it. But don't worry, if you are going into even slightly complex code (like knockback, for example), typing out JASS is actually faster than trying to do it with GUI. And btw, JASS is more similar to C++ than to Java.
     
  5. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Thanks a lot for the links, but some of the resources are no longer avaiable (well those cna wait for now, i'm still getting the hang of the GUI) at the moment I've tried to get my first custom 'tower' working, but there are some problems around it.

    Basically I want to create a Castle that fires multiple arrows from different positions, different firing times to create an arrow shower.

    So, at the moment, I created a dummy ability for the upgrade icon on the Castle, a dummy unit that can be trained (renamed as an upgrade) for extra attacks, dummy archers that can attack created on the Castle (small x,y variations).

    I'm using a simple trigger that tracks the creation of the dummy upgrade unit to apply the updated icon label, and to remove availability of the unit once it reaches cap level. Up till here the upgrade works fine, but I can't destroy the dummy archers if the Castle dies - I looked up the pick units, and didn't work with units having locust, and the only way I've managed to destroy the dummy archers is with a unit group variable, but its global so if I use that i can only have 1 castle.

    How do I change the trigger to be able to record every single instance of a Castle and efefctively preserve the destroy trigger? (I'm still working on GUI, obviously)

    Also, is there a setting to make projectiles inaccurate? I think I havent noticed any of those in the object editor.
     
  6. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    Jeez, I haven't worked in GUI for that kind of stuff for so long I have NO idea how to do it without JASS lol...

    Don't you wish WE supported 2 dimensional arrays?

    If you don't mind a little bit of JASS, however, I can give you a system:

    In the Custom Scripts section of your map (click on the tft map icon at the very top of your trigger tree), copy-paste these functions:

    Code (vJASS):

    function H2I takes handle h returns integer
        return h
        return 0
    endfunction

    function HandleVars takes nothing returns gamecache
        return InitGameCache( "jasshandlevars.w3v" )
    endfunction


    function AttachObject takes handle h, string key, handle value returns nothing
        call StoreInteger( HandleVars(), I2S(H2I(h)), key, H2I(value) )
    endfunction

    function GetAttachedGroup takes handle h, string key returns group
        return GetStoredInteger( HandleVars(), I2S(H2I(h)), key )
        return null
    endfunction

    function FlushVars takes handle h returns nothing
        call FlushStoredMission( HandleVars(), I2S(H2I(h)) )
    endfunction

     



    Then:

    Make a trigger detect every time a castle is built (Event - Unit Finishes Construction)

    For Actions, put:

    Custom Script: local unit castle = GetConstructedStructure()
    Custom Script: local group g = CreateGroup()
    Custom Script: call AttachObject( castle, "dummygroup", g )
    Custom Script: set castle = null
    Custom Script: set g = null

    Have a trigger detect every time one of your dummy archers is trained (Event-Unit Finishes Training a unit)

    For Actions, put:

    Custom Script: local unit dummy = GetTrainedUnit()
    Custom Script: local unit castle = GetTriggerUnit()
    Custom Script: call GroupAddUnit( GetAttachedGroup( castle, "dummygroup" ), dummy )
    Custom Script: set dummy = null
    Custom Script: set castle = null

    Then, have another trigger detect when a castle dies (Event - A unit Dies, Conditions - Unit Type of <Triggering Unit> is equal to...)

    For Actions:
    Custom Script: local unit castle = GetTriggerUnit()
    Custom Script: local group g = GetAttachedGroup( castle, "dummygroup" )
    Custom Script: local unit u
    Custom Script: loop
    Custom Script: set u = FirstOfGroup( g )
    Custom Script: exitwhen ( u == null )
    Custom Script: call RemoveUnit( u )
    Custom Script: call GroupRemoveUnit( g, u )
    Custom Script: endloop
    Custom Script: call DestroyGroup( g )
    Custom Script: call FlushVars( castle )
    Custom Script: set castle = null
    Custom Script: set g = null

    I've basically used what is known as "attached handles" to save dummy archers to the castle that built them. So, when the castle dies, you can easily retrieve the archers assigned to that castle and remove them from the game. If you want to know more about attached handles, read Daelin's advanced JASS tutorial: http://www.hiveworkshop.com/forums/s...ad.php?t=22710 (same link as in my previous post).

    One caveat is that what I've given you above will leak. It won't be as bad as leaking special effects or lightning (in other words your game won't start to lag horribly within 2 minutes of building castles) but the leaks will nevertheless be present. The leak issue (and incidentally the problem with 2-dimensional arrays) can be solved using more advanced JASS but since you're a beginner I'm not going to get into that.

    If you were wondering its the constant calling of the HandleVars() function that causes the leaks because InitGameCache() leaks every time you call it. But don't worry, it's a very minor issue that should not cause any problems.

    Btw, I'm not sure what you mean by "inaccurate projectiles". There's an option on unit attacks to make them not homing so they don't always hit (like with mortar teams and such).
     
  7. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Okay . . . gimme a while to comprehend that lol . . I've been spending most of the day staring into walls of text here and there, trouble is I find that the tutorials are throwing me pieces from everywhere -.-

    In terms of programming concepts, I'm fine with that since I already know C++, so the concepts like leaks, how to make this do that and then do that is not much of a problem. I'm still trying to find a good resource that can apply the JASS language step by step (Well, not to the extent of what is a function -.-) - almost like when you're tkaing up the your first class for Java (Yeah, I remember it sucked, and I still hate Java).

    Oh, ya and regarding the inaccurate projectile thingy, what I mean is say like when I was playing around with CnC:Generals, the INI's had inaccuracy built into the units, it had a value called inaccurracy radius or something like that. What it does is to make the attacker inherently inaccurate, not that the projectile can't track, but his hand can't aim straight. Currently, even if the tracking is removed, the tower is still precisely accurate over the rnage of thousands (aiming ahead). So, is there a simple value that can make the unit aim with less precision?

    Thanks a lot for the help . . I'll take some time to look around again later -.- Now I need let go of stress a bit -.-
     
  8. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    Lol I need to get rid of stress too, but that won't be happening anytime soon....

    Well if you know C++ then JASS should be no issue cuz in my opinion JASS is just a dumbed down version of C++. It's just memorizing what function does what and what JASS can and can't do (i guess mostly wut it can't do if you already know C++)

    Regarding the inaccuracy, I don't know of any way to make a unit inherently inaccurate.
     
  9. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    ALrite, aftera good nites sleep, I'm ready to ge tback to work again . . anyway I've figured out another solution around it, say:

    Train dummy upgrade unit -> Increase ability level -> When castle attack -> Create dummy archer -> Wait -> Remove Dummy Archer -> When castle attack -> .. .

    So technically, this allows multiple castles, each being wacthed by the trigger, but my guess is that it would be a very processor intensive thing since every attack we have units spawning and being removed, so I just wanna ask how efficient is this algorithm? I've seen various maps also having like every second events, I'm not sure but these kind of events are also processor intensive right?

    Another thing I'd like to clarify is with regard to variables, say I have a global variable I use to temporarily store a point, but I don't nullify it, so there is a leak. However, the next time I use that variable, I replace the value, so tehnically the leak doesn't increase in size, right? I'm not sure about dynamic variables like those in C++, or does it occur whenever we decalre our own locals only, then we have leak problems? I also read that many standard/library functions also leak, so does that mean that the GUI functions provided themselvs are leaking internally?
     
  10. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    I'm not sure how processor intensive your new system is. Really the best way to find out is just to test it in-game.

    If you don't nullify globals, it's no problem because theres only one variable. It's only with locals where every time the function is called a new local is created and if you don't nullify those variables eventually you have a bunch of local variables using up memory (strings, integers, reals, and booleans don't leak, though).

    As for functions, natives usually don't leak, lots of BJ functions (functions with the suffix BJ, like ForGroupBJ) do leak. Not all GUI functions call BJ functions, though most do. BJ functions are also less efficient than natives because all they do is call other natives.
     
  11. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Oh i see, so these variables don't automatically close after the end of a function. .

    About the processing thing, what I mean is comparing towards the solution you provided, that is instead of continously create - destroy vs create then wait till death - remove. I gues what I'm trying to say is whether it is worthwhile -
     
  12. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    I really don't know how efficient or inefficient creating/removing units every time castles attack is, but I would guess that my way of just using the attached handle variables is more efficient.

    My advice is use my system if you can understand it well enough. If you have no clue how my system works and will spend hours just figuring out how to implement it/tweak it to fit in your map then just go with your idea.
     
  13. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Hmm, so if BJ functions leak, does it mean all of them? When I converted some of the GUI triggers, functions like expirationtimer got a BJ suffix, so those are leaky? If so, then my tower would be a hell of a leak esp since it adds up on every attack. How do I settle this (In simple coding of course)?

    Another problem I encourntered after a little thought is regarding the upgrading method I'm using. What I want to create is upgrades that stack on a tower without changing the base unit (simply adding abilities), but I can't figure out a method to perform this smoothly.

    I tried using the train unit, but obviously if I remove availability when the ability reaches max, all other towers lose it.

    If I use the upgrade method, The icon is messed up sicne it must upgrade into a building of the same type (An upgrade button with the same icon as the tower looks wierd). If I apply a different icon (just to illustrate the upgrade) from the tower's standard, it shows when the player selects multiple towers and looks wierd.

    If I use the research method (research, then reset the research to enable research again), I can't remove the research button when the ability reaches cap. Although I can create a trigger to refund and display a message, the research button stays there, which is not so nice.
     
  14. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    Not all BJ functions leak, only some do. But all of them are less efficient than natives because all they do is call natives, and useless repetitive function calls will just slow down your game for nothing.

    By the way, just because a function doesn't have a BJ suffix doesn't mean it is a native. Take, for example:

    Code (vJASS):


    function GroupAddUnitSimple takes unit whichUnit, group whichGroup returns nothing
        call GroupAddUnit(whichGroup, whichUnit)
    endfunction

     



    GroupAddUnitSimple() is not a native, all it does is take the parameters, flip the order, and call GroupAddUnit(), which is a native. Basically Blizzard uses two functions to do the job of one. Pretty useless...and you can find lots more like these.

    If you are talking about TimerStartBJ(), no the function itself does not leak, but if you don't destroy the timer after you are done with it, it will take up memory.

    An example of a leaky non-native would be:

    Code (vJASS):


    function GetUnitsOfTypeIdAll takes integer unitid returns group
        local group   result = CreateGroup()
        local group   g      = CreateGroup()
        local integer index

        set index = 0
        loop
            set bj_groupEnumTypeId = unitid
            call GroupClear(g)
            call GroupEnumUnitsOfPlayer(g, Player(index), filterGetUnitsOfTypeIdAll)
            call GroupAddGroup(g, result)

            set index = index + 1
            exitwhen index == bj_MAX_PLAYER_SLOTS
        endloop
        call DestroyGroup(g)

        return result
    endfunction

     



    If you notice, the local groups g and result are never nullified and so those variables (being handles) will continue to use up memory even after the function closes.

    Regarding your tower upgrade problem, I can't think of a system much better than the ones you've already considered.
     
  15. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Okay, so if I want to clear out the leaks, I'll have to convert them and then add my own codes to clean them up? Or do I have rewrite the entire block (that settles leaks) that the non-native is supposed to do?

    Or is it possible to create function overrides for JASS? Then I could write a global function that can be called in place of the non-natives.

    I've been looking into the resource pages as well, so is there anything there that is reccomended for me to install? Theres quite a lto of stuff, but I'm trying out WorldEditorUnlimited, LeakCheck, etc

    Another thing I realised during my experimentation by creating dummy achers only when the castle attacks is that it interfered with another castle attacking as well (initially I used a wait trigger then proceded to remove last created unit), ending up with units not beign removed. After changing it to use expiration timers, it works fine.

    So does this mean that only one instance of the trigger can execute at once and must be finished before it can execute again? Is the trigger limited to track one event and condition (Meaning that say like I upgrade 6 towers simultaneously, only one instance will trigger, not all 6)?
     
    Last edited: Dec 18, 2007
  16. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    I've attached JassCraft to save you some time.

    If you want to get rid of leaks, it depends on what leaks you're trying to get rid of. You basically have to learn what leaks are, what kinds of variables leak, and how to get rid of leaks. There isn't a universal step-by-step guideline to get rid of leaks.

    There are, however, some very common leaks in GUI:

    1. Pick Every Unit in Unit Group and Do Actions: People use the "For Group" GUI function lots of times to do actions on a group that is created on the spot - basically the group wasn't saved in a global and isn't a bj global. For example, you might have something like Pick Every Unit Within 500.00 of <some unit> and Do Actions. Well, the problem is, the GUI function will create the unit group as it is called and by default WILL NOT DESTROY IT when it's done using the group.

      The easiest way to fix this is to go to Custom Script in GUI and type in: set bj_wantDestroyGroup = true right before the For Group GUI function is called. This tells the function to destroy the group after it's done using it, preventing memory leaks. Note you have to do set bj_wantDestroyGroup = true every time before a For Group function because the function resets the value to false whenever it is called.

      IMPORTANT: Don't set bj_wantDestroyGroup equal to true if you don't want the group to be destroyed, i.e. if you are using a group saved in a global that you want to use later, or if you are using a bj global.

    2. Locations: Locations are used a lot in GUI, from Location of <unit> to Location of Issued Order. The problem is that all of those functions create and return locations that use up memory, and thus can cause memory leaks. If you don't store those locations in variables and later destroy them (and of course nullify the variables once you're done) the locations will remain in memory as long as the map is running.

      There are two ways to fix this: use Custom Script to assign the locations to local variables, then at the end of the trigger just call RemoveLocation() and then nullify your locals,

      OR

      Avoid locations altogether. Locations are nothing but a pair of (x,y) coordinates in handle form. Almost every function that returns or uses locations has a counterpart that returns or uses (x,y) coordinates. The benefit of coordinates is that they are reals, and never leak. Unfortunately, GUI avoids those functions altogether (even the "Coordinates" function just takes reals as parameters and then turns around and returns a location). So, if you want to use reals, you have to use JASS in lieu of GUI.


    There's really no point in that, since your new function would basically end up calling more natives. Therefore, you might as well use the native functions to begin with, since it's faster that way with less function calls.

    As for resources, use JASS NewGen pack, it's way btr than WEU, especially if you're getting more into JASS. WEU's custom GUI functions and stuff basically just call standard JASS functions that already exist, and so there's nothing WEU can do that you can't already do with JASS in normal WE. NewGen, however, among other things, comes with a custom syntax checker/compiler that DOESN'T crash whenever you're missing an endif or and endloop. It also allows you to use structs and makes JASS more in-line with OOP (does this by way of preprocessor, not a hack, so it's 100% compatible with wc3 and battle.net). Get it here: http://www.hiveworkshop.com/forums/profile.php?do=editattachments (wc3campaigns.net, where I would normally point you, is down at the moment)


    Well, you know C++ so you should know that computers can only only run one line of code at a time (wc3 does not support parallel processing). However, you should assume that multiple instances of triggers can, for simplicity's sake, be triggered at one time, because the script DOES NOT NECESSARILY HAVE TO RUN IN ORDER. If you have a Wait function in your trigger, all it does is stop the script for that instance of the trigger and cause the wc3 engine to process pending code from other triggers (even other instances of the same trigger); it's not like if you use a wait function the part of the wc3 engine that processes the script all grinds to a halt.

    The problem you had with waits is that the function Get Last Created Unit in GUI actually just returns a bj global unit variable that changes every time a GUI function creates a unit (all BJ functions that create units update the bj global when called, natives do not). So, lets say you have two Castles. One attacks, triggering your trigger. The trigger creates the unit and sets bj_lastCreatedUnit to the dummy it just created. Then, the trigger hits the wait function; it stops running scripts on that trigger for the time being. While it's waiting, another castle attacks, and another instance of the SAME TRIGGER is triggered and another dummy is created (for the second castle). Now, when this happens, bj_lastCreateUnit is updated to hold the SECOND dummy archer (there's only one variable and it only holds one unit). Now, when the wait is over for the first instance of the trigger, when you call Remove Last Created Unit, the Last Created Unit function will no longer return the first dummy archer, but rather the second (because bj_lastCreatedUnit was updated during the Wait).
     

    Attached Files:

  17. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Hmm, the reason I was thinking of using overrides was simply to avoid having me rewrite the code everytime I want to use a leaky function. Well its true it would prolly be slower, just for my convenience, I guess.

    So if based on what u're saying about locations, everytime I want to use one, I add custom scripts to create a local, use the function and return the location into the local first, then do what I need to do, finally clear the local?

    Another thing is say regarding the leaking expiration timers, what do I have to do to clear them out when they expire? Is there a value like wantDestroyTimer or something like that? Even though I'm just starting off my TD, I just want to make sure I'm doing the steps right so I don't have to run back again later.

    Thanks a lot for the explanations, I really appreciate it since I havent been able to get clear answers from the tutorials. I'll take some time off to look into JassCraft.
     
  18. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Oh yeah, I also just downloaded Leak Check. I'm just wondering how effective it is . . Is the current version capable of detecting every possible leak from GUI? Maybe I'd use this to check then only use custom scripts to deal with lekay parts for the time being. I'm looking around at the list of functions, so for now maybe 1 or 2 lines at most -.-
     
  19. aznricepuff

    aznricepuff
    Joined:
    Feb 22, 2006
    Messages:
    749
    Yes, you need to remove the location when you are done with it using the function RemoveLocation(), then make sure you nullify your local location variable.


    There's no bj_wantDestroyTimer. In fact, wantDestroyGroup is the only bj local that makes GUI functions destroy handles.

    If you are going to only use a timer ONCE (it's not periodic), then for the function or trigger that is called when the timer expires, just destroy the expired timer (not sure if there's a GUI function for that, if there isn't, then do:

    Code (vJASS):


    set local timer t = GetExpiredTimer()
    //...your actions here
    call DestroyTimer( t )
    set t = null

     



    Needless to say, once you destroy a timer, it will stop working, so only destroy timers when you have no more use for them.

    Regarding Leak Check, I've never used it so I have no idea how it works or how good it is.

    Btw, the best way to learn JASS functions is just to take some GUI triggers in your map, copy them and convert the copy into Custom Script. Then, look at the JASS (since you already know what the trigger is supposed to do cuz you originally made it in GUI, you can get a feel for what the JASS does). Then afterwards you can try identifying leaks or use Jasscraft to search for native counterparts to replace all the BJ functions and make the code more efficient.
     
  20. Dezs

    Dezs
    Joined:
    Dec 15, 2007
    Messages:
    15
    Yep, for the time being thats what I'm trying to do, though theres so many things around. I'll be trying to open a few other TD maps to see what they have inside too. .

    Just another concern thta I came across a while ago:

    The function CreateNUnitsAtLoc leaks right?

    Or does it only leak when I use a return function like getunitposition to set the create location? If I use a location variable directly it doesn't right?

    For some reason, Leak Check is telling me its not a leak -.- Even tho I'm using the leaky method (based on the leak tut)