I know globals =)
I just didn't know if there were two sets of globals - one for the game and one for the library.
Blizzard's Variable Editor is real trash. I hate the udg_ prefix. They should have given you an option to include udg_. Same with when you click a unit in the Trigger Editor - do we really need gg_unit_hk10_0007?? Why can't it just be hk10_0007...
Also, it's a problem that locals can't be accessed without the Custom script: line in GUI. Only having access to globals is problematic when trying to help noobs with something complex.
Anyway, back on point, I would like to know more about the capabilities of structs... that tutorial doesn't help. He jumps around with "data" and "info" and what-not... blew my mind. I could count the illustrations that made sense to me on one hand.
udg_ is just user-defined globals and gg_ is generated globals. I guess blizzard just likes their globals to have specific prefixes.
http://world-editor-tutorials.thehelper.net/cat_usersubmit.php?view=63595
^Quick intro to structs. vJASS acts as kind of a GUI for actual coding. Structs would be nothing if not for global declaration. Without global declaration, and even with global declaration, vanilla structs are ugly global array systems. They are just very confusing to code with, that's why most of us used simpler systems like local handle vars and all that, but mostly since importing globals in JASS is a pain.
Ok, well structs make for kind of a clean interface. They allow us to neatly organize members and allow for easy encapsulation.
That declares a struct.
JASS:
struct Haha
real myReal
endstruct
That is how you'd add a member. You can also add prefixes to it, eg: private and public. Private makes it so that you cannot access the struct member outside of the struct, and public allows for easy access outside the struct. However, you don't really need the prefix at all if you don't want to, it is usually just to avoid naming collisions and allow what you want to be used outside the struct:
JASS:
struct Haha
public real a //You can use this both outside and in the struct
private real b //You can use this only inside the struct
real c //Normal struct member.
endstruct
Now, you'll find out how to use structs outside of the struct and inside the struct.
Outside the struct, you'll need a normal create:
JASS:
struct Hehe
real x
endstruct
function CreateOneHehe takes nothing returns nothing
local Hehe H = Hehe.create() //We use .create()
set H.x = 0 //We use "H." to state that it is a member of the struct
endfunction
Local Hehe H. In normal JASS, it is local "type" "name". This follows the same method, kinda. Basically, pretend Hehe is a new type that you can use. (It is actually an integer) Then you type the "name". The name can be
anything you want it to be. In functions outside of structs, you'll use the "name" followed by a "." to declare its members.
Example, this WON'T work:
JASS:
function CreateOneHehe takes nothing returns nothing
local Hehe H = Hehe.create()
set Hehe.x = 0 //syntax error
endfunction
You might've noticed that there is .allocate() and .create(). Why can't you use them interchangeably? They call the same function, but if you use it outside the function it will cause a syntax error since the allocate function is private. They both call the same function, but just remember that .allocate() is only within the struct, and .create() is outside or inside the struct. It isn't really creating some sort of struct object that was magically added to the editor, it is merely retrieving a unique id.
Anyway, why methods and not functions? They are the same. But people prefer to use methods, a lot since you can use private members and they are associated with the struct. Think of them as just functions that love the struct and are endlessly bound to the struct.
JASS:
struct Conflict
method HahaICanUsePrivateMembers takes nothing returns nothing
endmethod
method IAmBoundToMyStruct_ILoveIt takes nothing returns nothing
endmethod
endstruct
function IFeelLonely takes nothing returns nothing
endfunction
Normal methods, basically ones without any "static" prefix, are associated with an instance. People use methods for this neat feature, where you can use "this" or a mere "." as a prefix for members. "This" kind of acts as a reference to this struct, it points to the current instance.
JASS:
struct Jooboojoo
real x
real y
method ThisInstance takes nothing returns nothing
set this.x = 0
set .y = 0 //legal, these both cause no errors
endmethod
method Jooboo takes nothing returns nothing
local thistype this = thistype.allocate() //you can use "thistype"
//to refer to the current struct, this is useful in static methods
endmethod
endstruct
The difference between "
static" methods and non-static methods is that static methods are NOT associated with an instance. These are more like normal functions than normal methods are. Now you must be thinking wtf are the point of these? Well, first off, they can be used as code while normal methods can't.
JASS:
struct Whee
public real a
private real b
static method FunFunStaticMethod takes nothing returns nothing //you don't have to name your methods like this
//also, when using callback for codes, it must take nothing and return nothing, like normal syntax
local Whee x = Whee.create() //you can create them like this, or with a mere create()
local thistype this = thistype.allocate() //or something like this
//^this allows you to use "." to refer to members again, you can't normally do that
//in static methods without declaring it
set .a = 0 //legal
set x.b = 0 //legal
endmethod
endstruct
function Argh takes nothing returns nothing
call TimerStart(CreateTimer(),0.035,true,function Whee.FunFunStaticMethod)
endfunction
Static methods also let you override the create functions.
JASS:
scope MySpell initializer Init
struct Whee
unit caster
unit target
real sourceX
real sourceY
method onDestroy takes nothing returns nothing
call RemoveUnit(.target)
//just an example, this is called when you use the .destroy()
endmethod
method DoCoolSpellFunctions takes nothing returns nothing
//do awesome spell functions
call this.destroy()
//calls the onDestroy function
endmethod
static method create takes unit cast, unit tar returns Whee
//now creating makes a difference
local thistype this = thistype.allocate()
//we use allocate, since create will call this function and require arguments
set .caster = cast
set .target = tar
set .sourceX = GetUnitX(cast)
set .sourceY = GetUnitY(cast)
return this
endmethod
endstruct
private function Cond takes nothing returns boolean
if GetSpellAbilityId() == 'A000' then
call Whee.create(GetTriggerUnit(),GetSpellTargetUnit()).DoCoolSpellFunctions()
return true
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function Cond))
set t = null
endfunction
endscope
This way, you can do your initial settings organized into a neat function. This will allow you to easily set your members. If you want, you could probably do a big majority of your spell in the create method if it allows for it.
Well, I hope that gives you a basic understanding of them and how to use them. You should install WE and Wc3 though again, since it is much easier to code vJASS with plenty of tests rather than doing it freehand, otherwise it might get messy and you could easily make mistakes.