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
889
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.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top