• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Galaxy Coding - Share What You Know!

Status
Not open for further replies.
Level 15
Joined
Oct 16, 2010
Messages
941
Recently I decided to open up the SC2 editor for the first time in like 6 months and start learning galaxy. I was surprised to see that its syntax was almost identical to Java (I think galaxy is based on C), which made it very easy to learn because I am used to Java. For the past two days I have delved into the galaxy language and attempted to do some basic things with it.

This forum is for me to share what I have learned and also for others to share their knowledge with the galaxy language. Everything I write here is what I have either learned doing on my own in the past two days or learned from asking questions on various forums. If anything I say here is incorrect (which it very well may be) please correct me. Also if you have anything to add to what i've written or have another way of doing something, please make a post!




Galaxy Coding


Initial Observations
I was so excited to start programming in galaxy because I thought it would give me alot more control over gameplay and it wouldn't have alot of the problems that Jass had. I must say so far I am extremely dissapointed and I don't think that I will be modding SC2 anytime soon until something similar to JNGP comes out for it. It seems to me Blizzard really only cared about catering to GUI-users and didn't give people who want to write in Galaxy a second thought (which isn't surprising seeing as the campaign and all blizz custom maps are all written in GUI).

Pros
- Alot more natives than WC3
- Gives alot more of control over things like UI boxes and Unit Properties
- Garbage collector takes care of most simple local memory leaks
- Waits are pretty close to actual timers as far as accuracy is concerned

Cons
- Syntax highlighting sucks and is buggy as all hell
- You cannot declare libraries/classes and therefore there are no private variables or functions
- You cannot write functions within structs (wtf?)
- You cannot destroy objects you create via structs
- Very trigger-dependant (timers are practically useless without incorporating triggers)
- You can only have one function that runs on initialization per page
Basics


Script Viewer
Libraries
Where To Write
Functions
If/Then/Else
Variables
Arrays
Loops
Triggers
Structs



Script Viewer
To my knowledge, you cannot convert a GUI trigger into galaxy code. Instead, if you want to know the native for something, you must first write it in GUI and then go to (Data --> View Script) or press (Ctrl + F12) and find the code your looking for.

The script window that will come up represents your entire map script. Blizzard, in it's infinite wisdom, decided not to allow you to write code directly in this window. Making things much more difficult than they need to be.


Libraries
In the trigger editor you will notice thre windows. The big one to the right is obviously where you write your code, the smaller one in the bottom left is for declaring custom scripts/triggers/variables etc. (i'll get to this later), and the tiny window in the top left is for libraries.

My understanding here is that these aren't actually "libraries" in the sense that they do not have any of the properties that you would normally see in a library. All they are is a way of organizing and seperating your code but have absolutely no effect on how the code is interpreted (i.e. variables you declare here aren't automatically set to private). Basically these are fake libraries that are practically useless other than giving you the ability to seperate the code of one system from another (which you could do anyway by just opening another custom script window).

If you open up the "Built-In" library that blizzard created you will notice that it contains all of the GUI functions that GUI-users utilize. At first I thought this was pretty cool becuase you could easily create your own GUI functions but after a little toying it doesn't seem like you can modify these or add new functions in any way.


Where to Write
See the lower-left window in the trigger editor? Right click that, go down to (New --> New Custom Script) or press (Ctrl + Alt + T). This will create a new custom script window that you can name and write code in (the name doesn't effect anything).


Functions
You can not declare functions private in galaxy, they are automatically global and usable by all functions written beneath them.

There are two types of functions, void and return methods. void methods simple do not return anything, return methods do. When writing a void method simply write "void" before the function name, when writing a return method simply write whatever the returning variable type is before the function name.

Instead of writing Function + Code + EndFunction like in VJass you simple write a header (which I will get to in a second) and then use { and } to encapsulate your code.

In order to call a function you simply write the function name followed by the necessary parameters in parenthesis or just "()" if there are no parameters.

Examples:

Galaxy.jpg


If/Then/Else
You don't use the keyword "then" in galaxy. You just write "if" followed by your condition in parenthesis () and then encapsulate what code you want to run if the condition is true within brackets {}.

(see example in next section)


Variables
Variables declared outside of a function are global, whilst variabls declared inside of a function are considered local. You do not need to write "global" or "local" before variables.

When assigning variables to a value you do not need to write the prefix "set" you simply need to write the variable name following by an "=".

To test if a variable is equal to another you use the equivilency operator "==".

A few variable types are:

unit
int (short for integer)
bool (short for boolean)
fixed (alias for real or double)
timer
unitgroup

GalaxyVariables.jpg

GalaxyExample.jpg
___________

timers and unitgroups are special object variables that must be initialized via a constructer.

timers
You declare and initialize a timer like so:

timer TimerName = TimerCreate();

And can start a timer like so:

TimerStart(timer WhichTimer?, int Duration, boolean Periodic?, timetype WhichTimeType?);

Where timetypes are the following:

c_timeGame (game-time seconds)
c_timeAI (AI-time seconds) (no idea what this means)
c_timeReal (Real-time seconds)

You cannot start a timer and pass a function to it. The only way to use timers like this is to start a timer and setup a trigger event that runs when that timer expires (stupid I know).
Unit Groups
You can declare and initialize a unitgroup to empty like so:

unitgroup GroupName = UnitGroupEmpty();

Otherways to initialize a unitgroup:

unitgroup GroupName = UnitGroupCopy(unitgroup WhichUnitGroup?); (copies another unit group)
unitgroup GroupName = UnitLastCreatedGroup(); (adds the last created unit(s))

Arrays
Unlike in Jass, galaxy arrays are not automatically made fully dynamic. Instead you must declare the size of the array along with the array.

To declare an array, write the variable type (such as integer) followed by the size of the array in brackets [] and then the name of the array.

Remember that if you have an array size of 5, the index range goes from 0-4 not from 1-5.

Example:

GalaxyArrayExample.jpg


Multidimensional arrays (or matrixes) can be declared by supplying two or more array dimensions like so:

GalaxyArrayExample2.jpg


Loops
Galaxy seems to only give us access to pre-condition while loops. To write a loop in galaxy do the following:

while (enter condtion here)
{
enter code here
}

which will execute the code periodically until the condition is met.

Example:

GalaxyLoopExample.jpg


Triggers
Triggers work much the same as they did in Jass except that in the absence of libraries we must setup trigger functions that we want to run on map init in a different way (explained below) and theres a few more useless things that GUI uses that we have to live with.

For every galaxy script page you have you'll notice a very small box at the bottom of the page that says "Initialization Function (Optional):". Write the name of whatever function on that page you want to run on map init (such as a function that sets up and defines triggers). Do NOT include the (), JUST write the name of the function.

To my knowledge you can only have 1 initialization function per galaxy script page.

Once you add the name of a function to the initialization box, you can go to (Data --> View Script) and scroll down to the bottom where you'll see a function called "InitMap ()". You'll see that "InitMap ()" calls a function called "InitCustomScript ()", scroll up until you find "InitCustomScript ()". Inside the "InitCustomScript ()" function you should see that it calls whichever function you chose to run on map init. Why can't you just write all the functions you want to run on map init right there you ask? Ask blizzard...

functions that are called when a trigger event procs must be boolean returns and must have two boolean parameters.

The boolean returned represents if the code within the function actually ran or not (if the conditions were met). Its pretty much completely useless, just return true every time.

The two boolean parameters represent if there are any conditions to check and if there are any actions to run (respectively). These are also completely useless and only really succeed in making it so GUI code (when converted) has a few double conditions for no reason. You must write the function as if it takes two boolean parameters, but I can't see a scenario where you would ever use either one.

Example:

GalaxyTriggerExample.jpg


Structs
Blizzard apparently decided to take the "object-oriented" out of "object-oriented programming" when it came to galaxy and you'll see why.

Structs are (as you know) a way of creating custom data types (objects) and saving data to them. In galaxy there is no way to destroy an object created via a struct and you cannot write functions inside of structs.

Why are structs useful then? Well you can still write a struct and declare variables inside of it that you can save to objects you declare, but memory is wasted (unless re-used) with every object created and alot of functionality is lost.

Example:

GalaxyStructExample.jpg


Advanced


Unit Properties and Handle ID's

Using the function:

UnitGetPropertyInt (unit WhichUnit?, int WhichProperty?, bool Current?)

you can get a units properties such as life, maxlife, percent life, life regen, shields, kills, speed, accelleration, height, and more.

Apparently if you give an int value for the property that is higher than 35, an integer unique to that unit is returns (that can be used as a handle). I have not tested this.

Here is the list of property indexes btw to be used with the above function:

c_unitPropLife = 0
c_unitPropLifePercent = 1
c_unitPropLifeMax = 2
c_unitPropLifeRegen = 3
c_unitPropEnergy = 4
c_unitPropEnergyPercent = 5
c_unitPropEnergyMax = 6
c_unitPropEnergyRegen = 7
c_unitPropShields = 8
c_unitPropShieldsPercent = 9
c_unitPropShieldsMax = 10
c_unitPropShieldsRegen = 11
c_unitPropSuppliesUsed = 12
c_unitPropSuppliesMade = 13
c_unitPropKills = 14
c_unitPropVitality = 15
c_unitPropVitalityPercent = 16
c_unitPropVitalityMax = 17
c_unitPropAcceleration = 18
c_unitPropHeight = 19
c_unitPropMovementSpeed = 20
c_unitPropTurnRate = 21
c_unitPropResources = 22
c_unitPropRadius = 23
c_unitPropXP = 24
c_unitPropLevel = 25
c_unitPropBountyMinerals = 26
c_unitPropBountyVespene = 27
c_unitPropBountyTerrazine = 28
c_unitPropBountyCustom = 29
c_unitPropKillXP = 30
c_unitPropCarriedMinerals = 31
c_unitPropCarriedVespene = 32
c_unitPropCarriedTerrazine = 33
c_unitPropCarriedCustom = 34

35 and above represents the internal unit ID


If anything I wrote is wrong or if you want to add something please post it below
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
It is largly based on old C specifications. As such you can only declare locals at the start of functions.

- Syntax highlighting sucks and is buggy as all hell
Yes, but worst is it is slow (O(n) slow by the looks). They should get rid of it like they had before so that atleast we can use the feature without dieing of old age when moving large script blocks.
- You cannot declare libraries/classes and therefore there are no private variables or functions
Libraries do exist... You can import other scripts via them. They do however use the same variable pool as the rest of the scripts as is convention with C and its languages (Java is C based but is OO as opposed to procedural). The private stuff is only needed on large projects and if you keep a decent naming convention it will never be a problem or be needed although it can speed editing up if there was a decent IDE.
- You cannot write functions within structs (wtf?)
You could ever do that in C? A struct is a collection of data elements in memory and not an element for object orientated programming. Giving it functions would be prety retarded as you could just as well make a normal function take it as a parameter. This is not an OOPL.

- You cannot destroy objects you create via structs
This is all about memory management. In C, if you could do this it was because the compiler handled recycling and stuff. Galaxy is like dumbed down C thus it is only logical it does not support this. Especially since you can not allocate new structs, they only have limited use. To use them dynamically you need a recycling system but since that locks up huge areas of memory it may not be viable for large projects.

- Very trigger-dependant (timers are practically useless without incorporating triggers)
And? Big deal... Notice how triggers are now a lot simpler. It is only 1 function per trigger which acts as both condition and action (instead of 2 in WC3). The code is given to the trigger when it is made (unlike WC3 where it was on separate lines). Thus you could make perfectly good trigger hooks in only 2 calls! that includes an event, condition and action. Also 1 call will remove everything (events, trigger and its hook). Yes more needs triggers in SC2 but triggers definatlly need less.

- You can only have one function that runs on initialization per page
Uh hu.... And you need to run more than that?

Blizzard apparently decided to take the "object-oriented" out of "object-oriented programming" when it came to galaxy and you'll see why.
Uh hu.... yeh right... This hamburger takes the fish out of brocli when it comes to vegetables!!! Yup makes as much sense as you did. C was and never will be object orientated, thus why C++ exists which is. To be honest, galaxy is more based on C than java is. Stop expecthing something to be something that it can not possibly be. You can not expect a PS3 to run SC2 for example.

The main problems with galaxy are...
1. Virtual machine memory limit. You can only have like 2 MB of compiled byte code worth of triggers at any one time and you can not allocate new areas of the space on the fly.
2. Can not change memory allocation on the fly. This means that unless you use the full 2MB of the virtual machine you will always be wasting space which could be used for code or globals. There is no way to set up new areas of memory for structs, for stacks or for any form of data structure meaning that it will be left blank. Do not think it saves space as the machine probably allocates the 2MB anyway since the game easilly exceedes 1.5GB during ultra setting play so who cares.
3. Pointers removed. This makes structs unable to be passed from function to function greatly hampering their use. Further more it is a C specified capability so there is no excuse it was removed (yes in beta it did have it).
4. For loops. Like pointers they were also removed but did orignally exist.
5. Locals only at start of function. Ok I know old C standards do not allow locals anywhere in a function, but new C (since the 80s) has. There is no excuse that they can not support this, even if they had to make a pre compiled trigger file to do so (which would be better than compile at run time).

I am tired, the byte code size may be larger than 2MB but a limit does exist.
 
Level 7
Joined
May 3, 2007
Messages
210
Just wanted to mention Andromeda, a kind of "vJass" for galaxy, it brings various OOP structures that are lost on Galaxy, as well as sensible visibility keywords, like "private" instead of "static". Classes, iterators, enrichments, and various other stuffs, geX at sc2mods is the author, simple google search will take you there.

There is also a syntax highlighter for Notepad++ for it.
 
Status
Not open for further replies.
Top