Advanced Scripting

From HIVE
Jump to: navigation, search

With galaxy code you can do much more than just simply execute small actions. Although the time a trigger is allowed to execute is rather short (eg. you cannot just loop through a huge array and do stuff), it is still very powerful.

Some Keypoints

Code must be "short": If you try looping over an array of 128 integers and do an action for each of them, you will very likely get an error that the trigger execution time is too long... (Silly, for such a short period, one might think, but reasonable when considering the purpose of triggers...)

Code can still be executed over a longer period of time: You can put together multiple actions in triggers, by having one start a timer for the next one. (Although to allow the trigger to be executed in parallel you'll have to dynamically create triggers.)

How to learn the language, and why?

How

It is very useful to be able to write custom-scripts, and it is not even that hard. The language uses a very restricted C-like syntax. If you go through some hello-world C tutorials, you have nearly everything you need to start coding your own custom scripts. What you then still need to "learn" is the functions available to you. You can always use the non-custom-script version, and then look at the generated code in the code-viewer, or you can look at the library description in the trigger editor.

Why

There are some things you cannot do without Custom-Script elements. One such thing includes the dynamic generation and destruction of triggers.

For example: Consider a towerdefense game that consists of several smaller parts you have to beat before you can proceed to the next part. Let us consider 3 such parts. Now the mapper creates 3 regions, in each region there will be some point the creep has to move to, and some spawning points. Now for each of the 3 parts, he'd create a trigger to spawn the creep, to make them move, and to remove them when they reach the base.


Dynamic Trigger Creation

With dynamic trigger creation, the process would look as follows: The mapper still creates the 3 regions in the Terrain editor of course, but decides on some convention of what a spawn point, and a target point looks like. For example, a beacon (or just an invisible unit), to spawn creep at, and a "TD Base" unit the creep has to move to. Now, the triggers are created once, but as "Function Definitions", with the trigger function signature, that is, return type = boolean, and 2 boolean parameters (testConds and runActions).

Additionally, there's a trigger to setup the map, which assigns the global variables referring to the current map region, and with that region, finds the current Base and SpawnPoints. The SpawnPoints can be put into a unit group, and the spawn-trigger can then loop through that unit group and spawn creep at each spawn-point. For each "wave" that should spawn, the mapper creates a Function Definition, named "Map_X_Wave_Y", with X and Y being the map-sub-part ID and the wave number respectively, and while the player is fighting in a map, dynamic wave-spawning triggers are created using:

wavetrigger = TriggerCreate("gf_Map_" + IntToString(gv_currentMap) + "_Wave_" + IntToString(gv_currentWave));
TriggerAddEventTimeElapsed(wavetrigger, 0.1, c_timeGame);

This can only be done in a Custom-Script, and creates a new trigger, which will look for a function named "gf_Map_<X>_Wave_<Y>", and then add a "Time-Elapsed" trigger event, to be executed at "0.1" seconds game-time, which essentially means the trigger will just fire right away. Now all there's to do is create the desired Function Definitions Map_X_Wave_Y, with return type boolean, and 2 boolean parameters (so it matches the trigger-signature), which sets up the next wave, and then does:

TriggerDestroy(TriggerGetCurrent()); // Do not leak triggers.

TriggerDestroy() is important, otherwise the map would leak triggers for each wave...

If you set everything up well, the only thing you need to do, is define somewhere how man waves each map has, and create a Function for each wave. This is much more comfortable than the huge "If-Then-Else" combinations found in various Tower-Defense tutorials, where you essentially have a huge "if wave = 1 then <blah> else if wave = 2 then <blah> else..."

Notes

There's a reason why these functions are hidden

The reason for "TriggerCreate()" and "TriggerDestroy()" and all the "TriggerAddEvent***" functions to be hidden is simply: If you need to manage the amount of triggers yourself, and need to carefully destroy all the unused ones, otherwise your map will keep creating more and more triggers until SC2 eventually eats up all your memory...

Powerful Triggers

Just think about this: GalaxyCode allows you to put together function-names at runtime, using variables and constant strings, and then allows you to have these functions executed. This means Galaxy Code is much more powerful than it first appears to be. If you're a C/C++ coder, and have ever thought how cool it would be to have function-pointers and objects, then this information will put a big smile on your face :)

Some more ideas

This, in conjunction with unit's custom-values, even allows you to link abilities for players to different functions. Use a custom value of the player as a function ID, and make triggers for when a certain ability is executed, create new triggers to call "gf_AbilityFunction_<custom value>"... You can have 1 ability which does different things each time it is cast...