These functions are available as GUI actions in the Catalog category. They allow you to change the "templates" of Units, Abilities and any other object that can be edited in the data editor via triggers.
References one of the following constants which refer to the 51 GameData files in SC2:
Refers to the ID of the data object you are trying to modify. This ID can be viewed in the data editor by using View Raw Data and using the Name of the object in the left panel (or using the 'id' Token of the object).
Refers to the data field that you are trying to modify. If the data field is a a simple value (not an array and not a structure), you can simply put the name here. For example for for Unit Speed, put "Speed". Again use View Raw Data for find the name of the field.
If the field is a complex structure (field with multiple internal values inside it), use the "." operator to access those fields. For example to access a Unit's Figet values, use "Fidget.TurnAngle", "Fidget.TurningRate", etc.
If the field is part of an array (for example AbilityArray of a unit), you can use indexes to access elements of the array. For example to access the first element of CUnit_AbilArray_Link (full name of the ability array), I would use "AbilArray.Link". Here's an example:
A Zealot has the following abilities:
Field Zealot (Zealot)
In order to change the Zealot's ability from Charge to Blink, I would call:
CatalogFieldValueSet (c_gameCatalogUnit, "Zealot", "AbilArray.Link, 1, "Blink");
There are some arrays that are indexed with IDs. For example the 'Build' ability's InfoArray is indexed by "BuildXX". You can check if an array is indexed if when modifying this array via Raw Data, you can see an ID-Value pair in the array viewer, like this:
In this case, each entry of the array is indexed by a constant 'e_abilCmdBuild'. However these constants are part of the editor and are not accessible via triggers. Additionally many Data Editor fields have custom GUIs (Command Card for example) that make it very difficult to figure out how to modify them. In these cases it is better to open up the XML file from GameData and read how it references these values. Here's an example:
Here we see the InfoArray is indexed by "Build1", "Build2", etc. Similarily the Resource array inside it is indexed by "Minerals" or "Vespene". Note that any tag that appears twice inside 1 XML node is effectively an array. Therefore to access the first element of the array, and get the unit, one would use "InfoArray[Build1].Unit". To get the cost of that unit, one would use "InfoArray[Build1].Resource[Minerals].
Example 1: Lets say we want to set the cost NuclearReactors build from a barracks to 100 gas, we would use:
CatalogFieldValueSet(c_gameCatalogAbil, "BarracksAddOns", "InfoArray[Build2].Resource[Vespene]", 1, "100");
Example 2: Lets say I want to move the position of the Stimpack button on the Marine 1 to the right. The command card of a Marine looks like:
To change the Column of Stim, I would use:
CatalogFieldValueSet (c_gameCatalogUnit, "Marine", "CardLayouts.LayoutButtons.Column",1,"1");
As you can see, you can use this to change almost anything editiable with GE in realtime. Dynamic tooltips? Trigger-based global upgrades? There are tons of possibilities. More testing has to be done on whether this would work for modifying things like Actors or Tilesets.
As you've noticed, these functions all take in a player argument. It turns out that the game stores Catalog data on a per-player basis. That is each player has a unique copy of all data and it can be modified independently of other players. When a player trains an upgrade, it actually modifies the Catalog data to apply the changes listed in that upgrade. The functions above work in the same way.
That's wonderful! I was looking for something like that a while back :)
But as I'm just beginning to use custom scripts and Galaxy, I have some questions. When you use CatalogFieldValueSet all the data objects are modified?
I.E If I modify the command card of an unit, it will be modified for all units of the same type, won't it ?
What would one use to modify just one specific unit ?
Plus, when I tried to use one of your example (CatalogFieldValueSet (c_gameCatalogUnit, "Marine", "CardLayouts.LayoutButtons.Column",1,"1");), I got an error ('ErrorCatalogFielNotWritten').
This might be related to the fact I didn't extract or import any xml file as suggested in the API, but hey, I'm beginning :)
It works, and writes "32" on the screen. When you go in the Data Editor and you look the Raw Data values, the "Collide" one is something like : (0|1|1|0|0|1|0|1|1|0|0|0|0|0|0|0|0|1|0|0|0|0|0|1|1|0|0|0|0|0|0|0|1|0|0|0|0|0|0|0|0|0|0|0|0|1|0|0|0|0|0) (32 values, of course). So I guess we can access the values, I just don't know how. I read this tutorial, and the page on the wiki, but I don't found.
I tried to move my unit's button column but it gives me an error. Can you use this to move a unit's button position?
But very cool thread. Thanks.
edit: let me reiterate. the error says the "field" value is wrong. which means "CardLayouts.LayoutButtons['X'].Column" is incorrect.
I tested "catalog set value" on "MaxLife" and that worked. So it has to be the field value.
edit (again): i did a test with a debug message to show the value of CardLayouts.LayoutButtons.Column and it gave me "1". which means the field value is actually right. but we aren't allowed to change it with catalog set value
Looks like we can't change complex fields like CardLayout.
has anyone gotten this to work? im using behaviors and requirements to move my buttons and its a pain in the arse. if i could get catalog set value to work for moving buttons it would save a lot of time
It's prohibited to modify certain field values. Sadly button positions are one of them. Unless Blizz devs change that (if it's even possible that easily) there's nothing we can do about.
Isn't it because CatalogFieldValueSet works like upgrade? I'm sure you can only change what you can change through upgrades. I find this a pain, because in world editor it was easier to add new abilities through triggers.
If that is true, this function is kinda useless. I mean you can research upgrades with triggers... (its maybe a bit easier though)
Testing it right now. Darn, I thought you guys found a way to change behaviours...
EDIT: Jepp, looks like you can only change fields that can also be changed by upgrades.
Yes, but the function is not useless at all. First you can read any value you like. This is huge for many applications; for example custom uis or hero pick dialogues; you can actually read all vital information from the units, which makes adding new heroes very easy.
Also the CatalogSetValue- function is more dynamic, you don't need an additional data object and you can use more complex functions for the values you enter (upgrades can only use some basic functions like linear progression; triggers can easily incorporate other functions, for example an exponential growth or randomized values)
I usually go by modifying the apply behavior effect to apply another behavior, or for behaviors with periodic effects modify those effects. No chance to avoid multiple behaviors when you need different modifications for the behavior levels.