JASS: An Introduction to Structs

DuckieKing

Elitist Through and Through
Reaction score
51
Structs
A basic tutorial by Duckieking

#T#
Table of Contents
#T# Table of Contents
#O1# Overview
#L1# Why use structs?
#L2# A glance at structs.
#O2# Syntax
#L3# Declaring structs.
#L4# Calling structs in functions.
#O3# Conclusion
#L5# Questions? Answers.
#L6# Links and attachments.
#C# Changelog

#O1#
Overview
#L1# Why use structs?
The purpose of structs and classes in real programming is encapsulation, the idea that tasks should be broken down into simpler tasks. The point of this is simpler, cleaner code that is easier to maintain.

The purpose of structs in WC3 is additional multi-instanceability. They are used for any real physics systems, and they aren't just good for that.

Structs are useful for creating MUI effects such as stacking abilities, stat systems, kill counters, timed abilities, item systems, and anything else you can think of. Normally, these things would confine you to one instance per player or else force you to use multiple arrays for each effect you wish to implement. Structs allow you to attach multiple variables to a unit or item, thus easing these things as much as cleaning leaks is easier in Jass.

#L2# A glance at structs.
Structs are not native to the World Editor. With his awesome programming skills, Vexorian has allowed us to create structs, or custom variable types. Structs can be declared to have member data (variables) and member functions (methods). Well, kind of...

Structs is a misnomer. To be entirely technical, structs can only have member data, but with Vexorian's World Editor hack, structs have methods.

A method is just a function able to be called from any function that has access to a struct. Member data are variables contained in a struct. What I mean by that is when a struct is created, memory is set aside for each of its variables, which in general are only set by the struct's member functions.

#O2#
Syntax
#L3# Declaring structs.
Structs are declared a lot like functions, but are really unique. I'll just show you:
JASS:
struct unitData //"struct" plus the name of the struct to be declared; since this tutorial is meant to show MUI struct-making it is named unitData
  unit u //this will be the subject of the struct, just to cut down on call arguments; there's no need to type "local"
  real statCredits=3 //this variable holds the number of stats a hero has left to spend
  integer kills=0 //this variable holds how many kills the hero has made, so that kills can be rewarded with extra stats; normally this would limit you to one hero per player, but with structs you can do more

  method ModifyStatCredits takes real statBonus returns nothing //this is our first method; it is used to add or remove stat credits; this value can be negative but won't remove already-bought stats
    if this.statCredits <= 0 and this.statCredits+statBonus > 0 then //"this." is a pointer to the struct, this will be elaborated on in the next section, but for now accept that you reach a variable from within the same struct with "this."
      call SetPlayerAbilityAvailable(GetOwningPlayer(this.u), 'A000', true) //note that a function is called in a struct, this is legal; this call reactivates the spellbook if it wasn't active and if credits are now positive
    endif
    set this.statCredits=this.statCredits+statBonus //the real purpose of the method
  endmethod
    

  method BuyStat takes integer whichStat returns nothing //this method is called when a hero spends a stat credit; this will remove one stat credit and raise the stat that was bought
    set this.statCredits=this.statCredits-1 //minus one credit...
    if whichStat == 'A001' then //obviously the buy agility spell
      call this.RaiseAgi()
    endif
    if whichStat == 'A002' then //buy int spell
      call this.RaiseInt()
    endif
    if whichStat == 'A003' then //buy str spell
      call this.RaiseStr()
    endif
    if this.statCredits < 1 then
      call SetPlayerAbilityAvailable(GetOwningPlayer(this.u), 'A000', false) //here we disable the spellbook if there are no more credits to spend
    endif
  endmethod

  method RaiseAgi takes nothing returns nothing //encapsulation specifies that we let functions do as little as possible on their own
    call SetHeroAgi(this.u, GetHeroAgi(this.u, false)+1, true) //the "false" says do not evaluate bonus agi; the "true" says do make it permanent
  endmethod
  method RaiseInt takes nothing returns nothing //no need for another empty line, all three of these methods do the same thing
    call SetHeroInt(this.u, GetHeroInt(this.u, false)+1, true)
  endmethod
  method RaiseStr takes nothing returns nothing
    call SetHeroStr(this.u, GetHeroStr(this.u, false)+1, true)
  endmethod

  method AddKill takes nothing returns nothing
    set this.kills=this.kills+1
    call this.StatBonusForKills(3) //aha, bonus stats for kills...
  endmethod

  method StatBonusForKills takes integer statBonusModifier returns nothing
    if this.kills != 0 and ModuloInteger(this.kills, 10) == 0 then //we don't want any crashes due to dividing by zero, so we check if this.kills is 0 before checking its modulo
      call this.ModifyStatCredits(this.KillsStatBonusModifier()) //encapsulation's a cur sometimes
    endif
  endmethod

  method KillsStatBonusModifier takes nothing returns real
    return Pow(this.kills/20) //.25 stats at 10, 1 stat at 20, 2.25 stats at 30, 4 extra stats at 40 kills
  endmethod
endstruct

Note that by itself, this code does nothing. It just tells the game engine how much memory a "unitData" needs, and supplies methods to affect that memory. You need a function to create a unitData and call the methods or it's just a wasted 2 kb in your map file.

#L4# Calling structs in functions.
Now we get to the real stuff.

To attach a struct to a unit and be able to use it in other functions, all you do is assign the struct to the unit's custom value, but first you have to know how to create the struct. The following function will create a new hero with the Id given and attach a struct to it.
(I know, it leaks a unit variable, but it's a miniscule leak and unavoidable for this demonstration. :))
JASS:
function CreateHero takes integer playerId, integer heroTypeId, real x, real y returns unit
  local unit u=CreateUnit(playerId, heroTypeId, x, y, 270) //creates the hero and puts it in the variable to be returned
  local unitData uD=unitData.create() //the only time you will put the full struct name on either side of the period; "create" is a standard constructor and you don't have to write this method
  call SetUnitUserData(u, uD) //that's it; you just set the unit's custom value to the unitData you just created
endfunction
And thus a new unit is created, with its own custom data. Now you need to know how to use and change those data.

Remember how you used "this." to call methods and change data? In a function, you would replace "this" with the name you gave the struct when you created or copied it. The following function would be the action of a trigger fired when any hero on the map levels.
JASS:
function HeroLevelsUp takes nothing returns nothing
  local unitData uD=GetUnitUserData(GetTriggerUnit()) //it's assumed every hero in the map has this struct attached
  call uD.ModifyStatCredits(3) //all methods except "create" are called by the variable name, not the variable type, and if you wish to set member data in a function it is true for them, too, but this is bad practice, it's convention to use accessor functions to modify member data
endfunction

You now have everything you need to know to make a basic struct.

#O3#
Conclusion
#L5# Questions? Answers.
Whats better at structs then at local vars?
For one, the syntax for using gamecaches can be bulky and confusing. They're also considered to use very slow functions. Like gamecaches, structs allow you to continuously redeclare variables of the same name like locals but still access these variables from any function you need to.

#L6# Links and attachments.
Jass NewGen Pack v3d -- is necessary to use structs. It also includes bunches of other nifty features like a Jass parser that doesn't crash.
TESH for NewGen -- is a syntax highlighter for the above World Editor hack. It's almost as pretty and easy-to-use as JassCraft with the added bonus of writing directly into WE.
Wc3mapoptimizer 4.3 -- can reduce your map's size by a huge amount. A bit out of place in this tutorial but an amazingly useful tool nonetheless. :)

I've lost my CD-key for RoC. I can't log onto b.net or even open the world editor. If you have something to add to the tutorial, PM me and I'll read it as soon as I can.

#C#
Changelog
v1.01 Fixed some minor syntax errors in the struct declaration.
 

WarLuvr3393

Hmmm...too many things to play (WoW, COD4, WC3)
Reaction score
54
Hmm...I read over the guide briskly and it looks nice.

+Rep.

~WarLuvr

Offtopic: First Post!
 

Tinki3

Special Member
Reaction score
418
A nice introduction to structures indeed.

>If this tutorial gets enough attention, I will create a demo map

It will recieve lots of attention soon enough, you'll see :)
I think a demo map is essential for this tutorial.

Also, would you consider renaming the thread's title to, "An Introduction to Structs", or do you think its fine the way it is?

Either way I enjoyed reading the tut, even though I already know how to use structs.

Keep up the good work ;)
 
T

Twyddli

Guest
Very good tutorial. I think you should make a demo map! ;)
It is simple and easy to read, and still informative. +Rep.
Edit: I have already given you before. Damn.
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
i....dont know any other programing languange...and what's this ''struct'' and ''method'' is used for and how to used it efficiently...i cant understand -.-
 

Ninja_sheep

Heavy is credit to team!
Reaction score
64
hmmm, I still dont get why i shall use structs. Whats better at structs then at local cars?
 

DuckieKing

Elitist Through and Through
Reaction score
51
Tinki >> True, that might be better. :)

GaLS >> Your question is explained in "A glance at structs."

Ninja_sheep >> Local vars, as in gamecaches? For one, the syntax for using them can be bulky and confusing. They're also considered to use very slow functions. Like gamecaches, structs allow you to continuously redeclare variables of the same name like locals but still access these variables from any function you need to.
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
ok...i totally an idiot to other programing language other than JASS...i didnt learn them nor understand them....

Thus ...after reading whole tut...I...Cant understand what is struct and how good is struct for
 

elmstfreddie

The Finglonger
Reaction score
203
K I have this random question.
I know in structs you can have sort of like an array, where's there's like one.variablename and you can have two.variable name, but lets say you call it 1.variablename, is there a way to run a loop that's like Index.variable?
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Good tutorial! +rep

i....dont know any other programing languange...and what's this ''struct'' and ''method'' is used for and how to used it efficiently...i cant understand -.-

Struct and Methods are vJASS enhancements. If you read the tutorial and have at least a basic or(more preferably) a medium knowledge of JASS, you can understand this.

hmmm, I still dont get why i shall use structs. Whats better at structs then at local cars?

Well, I'd rather have a Car than a struct, definitely. :D

Well, local vars stay within the function, and rusty ol' handle vars are a little slower and less efficient.

ok...i totally an idiot to other programing language other than JASS...i didnt learn them nor understand them....

Thus ...after reading whole tut...I...Cant understand what is struct and how good is struct for

Well, that's why you first need to know basic/medium JASS.

K I have this random question.
I know in structs you can have sort of like an array, where's there's like one.variablename and you can have two.variable name, but lets say you call it 1.variablename, is there a way to run a loop that's like Index.variable?

Structs are arrays I think.

Well, I think you can use a textmacro to do it, if I understand you eg:
JASS:

//! textmacro structs takes INTEGER
struct $INTEGER$
    real x
    real y
endstruct
//! endtextmacro

//! runtextmacro structs("1")
//! runtextmacro structs("2")
//! runtextmacro structs("3")
//! runtextmacro structs("4")
...


If that is what you mean. But I don't know why you need that many. If you mean this (below), than do this:
JASS:

struct data
    real x
    real y
endstruct
//! textmacro structs takes INTEGER, NUMBER
function StructCreate$INTEGER$ takes nothing returns nothing
    local data S$NUMBER$ = data.create()
endfunction
//! endtextmacro

//! runtextmacro structs("1","1")
//! runtextmacro structs("2","2")
//! runtextmacro structs("3","3")
//! runtextmacro structs("4","4")


That should work. :D
 

Ghan

Administrator - Servers are fun
Staff member
Reaction score
888
I have a question. What is a struct? I don't think you ever answered that. I'm still having problems understanding what they do, let alone coding one. :p Tell me if I'm correct about this: A struct is a group of functions/variables that can be 'attached' to a unit and basically follow it around and only work for that unit and no others. That's kind of what I get out of that tutorial, and I hope it's right.

> I believe the ones to approve this would be staff such as Tom Jones, Daxtreme, Acehart, Tinki3, or Ghan_04.

What about emjlr3? Actually, I don't think I've ever seen AceHart approve something, (not to say he couldn't, of course) and as for me, I'm not qualified to approve this tutorial, since I don't understand it. :p
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
@Ghan_04: Yea, I forgot about Emjlr3. But I don't think he approves many things.

Also, structs, are technically just globals that are made. Yes, they are attached to an object and can be used from function to function. :)

Just like spiderman. :D
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
first....my english are noob...i cant even understand the first 3 or 4 lines....anyway i gonna clear these out here...

I has saw that u explained "this.'' with:
""this." is a pointer to the struct, this will be elaborated on in the next section, but for now accept that you reach a variable from within the same struct with "this.""

this. is a pointer to the struct? what is a pointer??

>>By ghan04
A struct is a group of functions/variables that can be 'attached' to a unit and basically follow it around and only work for that unit and no others. That's kind of what I get out of that tutorial, and I hope it's right.

i am also wondering about this question... what is a struct?
It is a group of functions or variables that ''attached''?! to a unit?

Code:
local unitData uD=unitData.create() //the only time you will put the full struct name on either side of the period; "create" is a standard constructor and you don't have to write this method
Blurred about this code... what is that "unitData"?
unitData. ?! the dot is for what?
 

Waaaaagh

I lost all my rep and my title being a jerk
Reaction score
70
A struct is a capsule.

JASS:
struct Cache
    unit caster
    unit victim
    timer t
endstruct


You use a struct really to declare a new variable type. It is a 'capsule' variable. Once you define a struct (what it will look like/contain), you can then use it in your code. Structs are really all about creating this interface, so that it is clean to look at (you can tell, by looking up at the type of struct you are using, what that struct type contains). That's why you declare structs as

JASS:
local Cache data


You are not creating a local struct. You are creating a local Cache (a 'type' that you defined above). You should treat each struct you define as a separate type, just like integers, units, and all other types - they each have their own rules to follow.

So yeah. A struct is a capsule used for building a clean interface.
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
capsule?
my english are poor....what is the capsule u talking about??
i only knew that the place to put medicine is call capsule also...

Since u explained struct...so struct is as same as this:
JASS:
globals
endglobals


right??

Then what is method?
 

Sooda

Diversity enchants
Reaction score
318
That tutorial is one of few ones what tries to explane what are structs and maybe even how to use them.
I know how to create structs and work with them (On basic level) but I found that tutorial vague though. One theme what would be from tutorial start to the end would make learning process easier for people who aren' t familiar with structs.
Structs aren' t used only for attaching to newly created unit. They are used like ordinary data (info like unit, unit group, player, force, effect, real, integer, etc, handle) transmitters. You can save info into struct and retrieve same info after back from another function.
Maybe examples where for beginners a bit too complicated. Where were left these old school examples where you could save to struct unit and it' s owner (player) then kill unit with another function. Would be easy and simple to understand. In my opinion structs are alternative for game cache but if you need flexibility then game cache is still required in some cases. Did you explaned struct syntax ? Anyway I haven' t seen another similar tutorial (Except Vexorian tutorial(s).). Nice still +rep.
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
>>You can save info into struct and retrieve same info after back from another function

i wonder how to retrieve?
i am completely not understand about the example gave by duckieking...

And i wonder what is the "this." is use at...and how to use..
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top