Latest Additions
More UI Strings
The number of available UI Strings (StartString, etc.) is being increased from 4 to 16.
UI Screen Edge Attachment
The ATTACH tag can now be used to have a UI object attach to a screen edge. The data for ATTACH is in the form of a string, with valid values being L, R, T, B for left, right, top, and bottom edges respectively. So, e.g:
ATTACH TL
would position a control at the top left of the screen in all resolutions. ATTACH can be used (for example with SQUAREASPECT or the DX/DY tags) on a parent object to build a control panel which is in a given position onscreen irrespective of it's actual size and positioning.
UI Square Aspect
You can now denote controls to maintain their aspect, along with all their children. This differs from the KEEPSQUARE logic in that the actual positioning of child objects will retain a constant aspect (rather than just their control dimensions, as with KEEPSQUARE). Effectively, setting SQUAREASPECT on a control will cause it to be centered around it's usual position, with all its children positions as they would have been in their 1024x768 defined coordinates. So a popup (for example) will have the same look and layout all screen resolutions, but will scale uniformly to the appropriate size. Note that while it is possible to turn off SQUAREASPECT on child objects of SQUAREASPECT parents, the results will likely be undesired.
Script Command Update: GetUnitAssetFilename
Can now be used without requiring an existing unit, by setting bit 16 in the id value.
//puts the base asset filename for the unit in the workString requested, default 0. If bit 16 is set (+65536) then id is assumed to be the type index of the unit type, allowing this to be used when no unit exists. GetUnitAssetFilename(id, [workString])
Multiple Variable Definitions Per Line
You can now declare multiple variable definitions per line, e.g.
int x,y,z ;
Note that you cannot have multiple variables per line in structure definitions, nor if you are setting up static data in a global variable.
Updated Unit Texture Functions
Tile. Updated SetUnitTexture and added CheckUnitTextureFile. You can now set a texture in any of the 4 texture paths on a model, or reset back to the model default. Note that (as before) when looking for a texture in either function it first checks the campaign, and then the main data folder, and if no path is set it uses DATA/BATTLE/UNITTEXTURES.
//set the unit to use a new texture. A unit can only have a single texture on all its men. If path is omitted or empty uses DATA/BATTLE/UNITTEXTURES (either local or main). index [0,3]. Empty filename means reset. SetUnitTexture(me, filename [,path][,index]) //return 1 if the given texture exists, 0 otherwise. The type on the filename is optional and success is returned if any valid texture file type exists. CheckTextureFile(filename [,path])
Skirmish Map Size Scripting
Tile. The function RandomMap_MapSize can now take a 7th parameter, which is the skirmish type index. As before the parameters for this function need to be in order in the definition.
FUNCTION RandomMap_MapSize(mapSize, width, height, mapType, points0, points1, scenarioType)
User Data for MP Games
Tile. You can now add user data to MP games which can then by parsed by your game setup, and shown as tooltips. To do this you need two functions inside the UI script for the lobby (lobby.txt):
FUNCTION MULTIPLAYER_USERDATA_CALLBACK() { // this should fill the work array with up to 16 values // generally this would be driven by custom UI } FUNCTION MULTIPLAYER_USERDATA_TOOLTIP_CALLBACK() { // this is called with the user data in the work array, and should fill the UI string with the appropriate tooltip // only adds a tooltip if it returns != 0 return 1 ; }
The user data is available in the work array at the start of the battle (e.g. in the initial StartTurn calls etc). Note that this data can be overwritten by user code and should thus be extracted and stored as soon as possible. Also note that because the logic for the userdata is part of the UI script it cannot be customised on a per-campaign basis (this is because loading custom scripts for all campaigns (including possibly ones that the user does not have installed) would be prohibitive. NOTE: The current limit for the number of user data integers is 16.
ConfirmEndTurn
Tile. A new option ConfirmEndTurn pops up a confirmation when you try and end the turn. This requires a new string IDS_ENDTURN_CONF. The confirmation only occurs when ConfirmEndTurn has the value 1. The default value is 2, and zero is also a valid value. This allows games to tell whether the option is in default or has been set by the user (so a game could turn it to 1 if it wished at start if the default is set).
ClearUIListbox Update
This script command now allows for an optional value which sets the size of the listbox. This aids performance with adding large numbers of items to a list. Note that the list can still grow beyond this size as needed.
//clear a listbox UI object and reset its selection. numberOfItems pre-allocates space for that many items, speeding up large list filling. ClearUIListbox(objectName, [numberOfItems])
Clickable Links
It is now possible to include clickable links in text controls by using correct markup. See Here for details. Note that if you include DATA/UI/MOUSE/LINK.TGA (or DDS of course) cursor image then it will be used when over a clickable link.
ShaderValue Attrib
Tile. If an attrib exists named ShaderValue then the value for a given unit is passed in as the .w component of c30 (which is usually filled with pseudo-random values when rendering units) to the vertex and pixel shaders. This can allow for conditional shader code to be executed based on either static (from the squads file) or dynamic values in the attrib.
New UI Animation Commands
New commands SCALE and ROTATE. Format is:
ANIM SCALE <object> <frame> <startScaleX> <startScaleY> <endScaleX> <endScaleY> <ticks> ANIM ROTATE <object> <frame> <startRot> <endRot> <ticks> <loop>
Antialias Support
Tile. You can enable AA support in the options panel by providing a listbox (OptionsAAList) and the appropriate strings (IDS_AA_NONE and IDS_AA_SAMPLES). Note that IDS_AA_SAMPLES expects to be a formatted string which takes the number of samples to be used.
IDS_AA_SAMPLES,"%d samples",
Per-Man Status Display
Tile. You can display status information over the selected and moused-over units. This is in the form of a bar over each man. To use it you need a callback of the form
FUNCTION STATUS_BAR_CALLBACK(me, man)
Which returns the percentage value for the bar. Returning -1 hides the bar for that man. The positioning and appearance can be controlled by optional per-unit attributes
StatusOffset // the percentage of the IconHeight attribute to position the bar at (in 100ths), defaults to 80 StatusSize // height of the bar in 100ths, defaults to 50 StatusWidth // multiple of the height for the width of the bar, in 16ths. Cannot be larger than 255.
The default shader uses the center 50% of the texture (DECALBAR0 and 1 in UI/DATA/TEXTURES) for the area around the percentage position, and repeats the outer 25% on each side along the remaining bar. The decalbar.txt shader can be customised as desired.
ShowConfirm Script Command
You can show a confirm popup using the new command
//show a confirm popup using UI string 0, and callback the given function with the result (see wiki for details) empty string for no callback. flags denote the buttons to show, zero for off, 1 for on, for OK and Cancel buttons for bits 0 and 1 respectively ShowConfirm(callbackFunction, [flags])
The callback function should be of the form
FUNCTION MyCallback(ok)
Where ok will be 1 or 0 depending upon the choice the user makes. Note that you cannot use Get/SetGlobal calls in this callback function.
Reaction Display
Tile. The reaction display was failing to display. This has now been fixed, but there is also a new tweak DISPLAYREACTION which allows it to be disabled as desired. This defaults to 1, but a value of zero disables display of the reaction ring.
CUSTOM_UNIT_ANIM_CALLBACK
Tile. You can intercept and change requests by the game to change the animation. The format of the function is
FUNCTION CUSTOM_UNIT_ANIM_CALLBACK(me, man, flags, currentRand, currentIndex)
Where me is the unit, man is the index in the unit of the specific man, flags is various helper flags (see below), currentRand is the random animation value, and currentIndex is the animation variation of the currently playing animation. The string tags for the upcoming and current animations are in work strings 0 and 1 respectively.
If you wish to change the animation that gets played, put the new tag into work string 0, and return the new random index value (or the incoming currentRand if you wish to leave it as is).
Note that this function can be called almost every frame with the same animation, depending on the internal unit state, not just when animations finish or are triggered.
Additionally, you can now add a FLAGS byte to animation definitions. If you wish for an animation to act like a MOVE or DIE animation, you need to set bits 0 and 1 respectively in a FLAGS value. E.g.
[MOVE_CUSTOM00] FLAGS 1 ...
flags bit values: 1 - attempting to change from a move animation to wait after movement finishes
Zoom Speed Option
Allows zoom speed to be altered between 25% and 500%. Requires options screen controls OptionsZoomSpeedLabel and OptionsZoomSpeedButton (works in the same way as scroll speed). Also IDS_ZOOMSPEED string for descriptor.
Key Mapping
You can map keys in the options. It requires a listbox named OptionsKeyList. This gets a list of the remappable keys (these are defined in code). The user can then remap them and the remapping is saved in the options file. Note that ESC cannot be used as a remapped key.
You need to define strings for each of the remappable keys in the form IDS_KEYDESC_<keyname>, so examples would be IDS_KEYDESC_W and IDS_KEYDESC_LEFT.
Please speak to us if you desire other keys to be remappable.
SetMusicFile
Allows you to point to a music file which is used.
//set a music file to be loaded and used. Looks in local then core files. A ? as filename means leave the existing music entry. SetMusicFile(filename)
Hexadecimal Values and Colour Strings
You can now use hex values in script as integer literals. So
var = 0xFF8800FF ;
is now a valid script line.
As part of this change, most script functions which take a colour string can now also take integer values. So these are both valid and equivalent
SetUITooltipColour( "FFFF00FF" ) ; SetUITooltipColour( 0xFFFF00FF ) ;
NOTE: one caveat is that due to the fact you can pass strings around as integers (for historical reasons) you should note that passing a string into a user function that takes a parameter can strip the type information from the value, meaning you get an incorrect result.
FUNCTION SetTT(colourString) { SetUITooltipColour( colourString ) ; } ... SetTT( "FFFF00FF" ) ;
This will set the colour incorrectly (SetUITooltipColour will treat colourString as an integer value and set the colour to whatever the internal string pointer value happens to be). To prevent this, type your functions appropriately:
FUNCTION SetTT(char colourString[32]) { SetUITooltipColour( colourString ) ; } ... SetTT( "FFFF00FF" ) ;
SetShowAIMoves
Tile. New script command.
//if state is 0 then automatic viewing of AI moves is disabled, otherwise it is enabled (default). Note this resets at the start of each turn. SetShowAIMoves(state)
PlayUIAnimation
Tile. New script command.
//play the animation on the denoted UI screen (the objectName must be the root object of the screen). PlayUIAnimation(objectName, animationName)
LoadVariableFromParserFile
This command loads data from a parser file into a variable. The chunks should be named [0], [1], etc for each element in the array.
//read a parser file to the named var (must be an array of structs). Only int values currently supported. Numbered chunks (base 0) are read to the corresponding array element in the named array. Each value is read to corresponding item in the structure. See wiki for details. LoadVariableFromParserFile(variableName, filename)
An example input file might be of the form:
[0] side 10 data[0] 89 data[2] 5 [3] side 33
And would be used as such:
struct TLoad { int side ; int data[4] ; } TLoad gLoad[256] ; ... LoadVariableFromParserFile("gLoad", "MapData") ;
SetCameraPositionPrecise & StopSFX
Tile. New script commands.
//set the camera to instantly point to the given point (defined in 100ths), centering it on the screen SetCameraPositionPrecise(x, y) //stop a playing sample using a playback ID. Has no effect if the sample is over, or has been stopped by the system. StopSFX(playbackID)
Note that the playbackID is newly returned from SFX playback functions.
Object Terrain Priority
Tile. You can add a tag to an object PRIORITY. The default value is 0. Of the objects on a tile, the object with the highest priority value will denote the terrain (assuming it has a terrain override set). PRIORITY value must be [0,255].
Unit Scaling
Tile. You can add an attrib UnitScaling which allows for scaling of unit sizes. The value is in 1000ths, a value of zero is ignored.
Textbox Rescale and Scrolling
You can now have rescaling text boxes which will convert to scrolling if they exceed a given height, set using the RESCALEMAX tag. So an object can have the RESCALE and SCROLLING tags both set, and will rescale up to the height set by RESCALEMAX, and then stay at that size and use scrolling to allow access to the full text.
Force Selection Script Additions
Tile. Additional script commands to allow for custom force controls.
//set the selected state of a given unit on tile x,y on the deployment map. If select is 0 then the unit is unselected, otherwise selected. Note can fail if unit is fixed or not enough points. SetForceControlSelected(objectName, x, y, select) //returns 0 if the unit on x,y is unselected, 1 if selected, 2 if fixed, (-1 if no unit is on the tile) GetForceControlSelected(objectName, x, y) //set the zoom level for the camera in battle SetZoom(zoom)
There is now an additional tag for ForceSelection UI objects. HIDEBUTTONS will entirely hide the display of the normal force control buttons.
OBJ_UI_RENDER/HANDLE Change
The UI script callback functions UI_OBJ_RENDER and UI_OBJ_HANDLE now also has a name parameter containing the name of the rendering object.
FUNCTION UI_OBJ_RENDER(x,y,width,height,pass, name) FUNCTION UI_OBJ_HANDLE(data, event, id, name)
Water
1st pass water implemented. You can now add a SKYDOME <name> line to a lighting file. The name should not include the type extension. Note that only the skydome texture from the daytime lighting file is used by the system when loading the skydome. This texture should be in the DATA/BATTLE/TEXTURES folder (either main or campaign local). It is available in the shaders in sampler 7.
Flying Units
Tile. You now tag objects with FLYHEIGHT values. These are used to generate a per-tile max height. Then, if your squads file has a FlyingFollow attrib, then any unit with a non-zero value will remain above the ground by a value made up of the per-tile max height plus the value of the FlyingFollow attribute for the unit.
GetPositionDistance Script Command
Takes two positions (in 100ths) and returns the distance between them.
//return the distance in 100ths between two points that are also in 100ths GetPositionDistance(x1,y1,x2,y2)
Terrain Following Objects
You can use the TERRAINFOLLOW tag to allow objects to align themselves to the terrain.
New Script Functions
You can now use the Sort function to sort a generic array, and the FindStringInArray function to search for an array entry based on a string element.
//sort the array by the elementName entry (which must be an integer). If direction included, 0 is ascending (the default), 1 is descending. Sort(elementName, array, count, [direction]) //returns the index of the first array item containing and element called elementName which is the search string. elementName is a string entry, array is the variable array itself FindStringInArray(string, elementName, array)
An example would be
struct TTest { char name[32] ; int value ; } ... TTest array[2][32] ; Sort("value", array[1], 32) ;
AddVizUnitFormation Command
This command allows to you trigger and wait for a formation change.
//do a call to the unit placement function (potentially calling the FORMATION_CALLBACK) and wait until all the men are in position and facing the correct way. AddVizUnitFormation(id)
Formation Facing Control
Use the new command SetFormationFacing in the FORMATION_CALLBACK function to set the facing of the nth man in the unit. Use -1 to just have the man face in the default direction of the unit as a whole, as was the previous behaviour. Note that the facing is specified relative to the facing of the unit, not in terms of absolute facing. So to make a man face 45 degrees anticlockwise from the facing of the unit, the facing would be 45.
//set the facing of the nth man in the unit. Use -1 to just have the man face in the default direction of the unit as a whole. Only relevant in FORMATION_CALLBACK SetFormationFacing(n, facing)
Scrollable Text Controls
Text controls can now be made scrollable. Add
SCROLLING <control texture>
to the control definition and the control will (if the text is too large to fit in the control) add a scrollbar to allow for scrolling to view the ful text. Note that this will not work correctly when combined with rescaling text boxes. You can also use BARSIZE to control the size of the scrollbar.
String Manipulation and Creation
You can allow the user to create string entries (expected in the editor) via script. The new functions are:
//places the contents of the edit box into the first UI string. GetUIEditbox(objectName) //creates a string of the form IDS_<tagBody>_<number> finding the first empty slot in the string table, and fills it with the contents of the first UI string AddUserString(tagBody) //remove the denoted user string from the temporary store. Has no effect if the string has already been written out to the file. RemoveUserString(tag) //flush out any user strings to the TEXT9.TXT file. NOTE: this is done automatically at map save and editor exit. FlushUserStrings() //returns the highest N for which a string exists with the form IDS_<tagBody>_<N>, up to a max of 100000. Returns -1 if none exist. GetHighestStringIndex(tagBody) //return 1 if the string exists, 0 otherwise DoesStringExist(tag) //get the denoted string into the first UI string if it exists. Empty otherwise GetString(tag)
So users can type in strings which are then added to the list of strings available to use ingame.
Script Updates
1 - the break directive to trigger the debugger has changed to DebugBreak ; to prevent confusion with the C break statement.
2 - while loops are now supported. Note that the test cannot be an operation, so
while(i--)
will not work, as the scripting does not treat the left hand of an expression as a value in the same way as C.
Custom UI Object Rendering (inc Listbox Items)
Individual UI objects can now have their own scripts attached, including their own rendering callbacks. As before the rendering callback is of the form
FUNCTION UI_OBJ_RENDER(x,y,width,height,pass)
Where pass is 0/1 for pre/post normal control rendering.
Listboxes can also include
FUNCTION UI_OBJ_RENDER_ITEM(x,y,width,height,pass,flags, item, name)
which operates in the same way but for each listbox item. The flags param has bits set for selection (bit 0) and mouseover (bit 1), item is the index of the item in the listbox, name is the UI object name.
Listboxes: Multiple Selection
You can enable multiple selection for listboxes with the MULTISELECT tag in their UI definition. Then use
//return 1 if the specified item is selected, zero otherwise IsUIListboxItemSelected(object, index) //returns the number of items in a listbox GetUIListboxCount(object)
to interrogate the listbox.
Note: This means that it is possible to get UI script triggers from listboxes which are actually a CTRL+ event which unselects the item.
Scripting: GetWorkString
You can now use GetWorkString on the RHS of an assignment expression, e.g.
char myString[32] ;
myString = GetWorkString() ;
The contents will be safely truncated to the source string's size.
3DVIEW UI Control
Creates a 3D viewport into which you can load 3D models for viewing. The COLOUR tag for this control sets the background clear colour (use zero for a transparent background, FF000000 for black).
Script commands to control this are:
//if filename starts with # then defaults to standard unit loading paths. UIObject3DLoad(objectName, filename, [texturePath]) //automatically set the zoom and camera origin to the size of the currently loaded object UIObject3DAuto(objectName) //set the origin position and vertical angle of the camera. SetUIObject3DCamera(objectName, x,y,z,angle,[zoom]) //set the options for the view. 0 for off, nonzero for on. SetUIObject3DOptions(objectName, allowZoom, allowHorizontalRotate, allowVerticalRotate)