https://archonwiki.slitherine.com/api.php?action=feedcontributions&user=Richards&feedformat=atomArchon Wiki - User contributions [en]2024-03-28T21:47:50ZUser contributionsMediaWiki 1.38.2https://archonwiki.slitherine.com/index.php?title=Modding&diff=434Modding2017-10-26T08:48:31Z<p>Richards: /* File Layout Guide */</p>
<hr />
<div>= Modding Guide =<br />
NOTE: This documentation is ongoing. For additional information and tips see our forums, as well as the older STUB wikis [http://www.slitherinebravo.net/GameWiki/doku.php?id=stub_engine Here] or [https://sites.google.com/site/battleacademy2 Here].<br />
== The Basics ==<br />
You will create all your mods inside their own 'campaign', a folder which holds all your maps, scripts, or other custom files - or alternatively as a global mod in the MODS folder. <b>At no point should you alter the main game files.</b> This will likely cause you to either not be able to play multiplayer, or cause multiplayer games to behave incorrectly. It is also likely to cause problems when the game updates.<br />
<br />
== Creating a Mod ==<br />
Globals mods currently support skinning, and a custom squads file. To use mods, you must first create a MODS folder in your local folder (e.g. My Documents/My Games/Sanctus). Then create a named folder for each mod (no spaces!). You can place a modded SQUADS.CSV in the root of your mod folder, this will always replace the in-game version, so generally you should copy the main game file and then edit it as desired. You may have as many mods installed as desired, but only one (or, of course, none) can be active at any time.<br />
<nowiki>.../MODS/MYMOD/SQUADS.CSV</nowiki><br />
To apply skins to units you would create a UNITTEXTURES folder to mirror the one in the main game data<br />
<nowiki>.../MODS/MYMOD/DATA/BATTLE/UNITTEXTURES</nowiki><br />
You can then place modded unit textures into this folder and they will be used ingame. Note that the code will attempt to load these textures even for saved games, to allow you to switch skins.<br />
<br />
Note that some other textures are skinnable, if their folder paths are duplicated. The skinability of other textures depends on a variety of internal code factors, including how the code searches for an uses the textures. But it can never hurt to try!<br />
<br />
== Creating a Campaign ==<br />
The simplest way to start modding is to select the Editor from the main menu, enter names for your campaign, and then use the editor to build a map. You will then be able to select your campaign from the Campaign Screen, and then choose which of your maps to play.<br />
<br />
<b>TIP:</b>Select the Plugins list in the editor, and choose the Random Map Plugin. This will create random maps for you in the editor, which you can then populate with units. It's a quick way to get started!<br />
<br />
Once you have a campaign, you can then begin to add other functionality, up to and including your own mission scripts, AI logic, UI screens, or even new 3D objects.<br />
<br />
In a simple Campaign, the order in which scenarios appear on the scenario selection screen is not defined.<br />
<br />
== Advanced Campaigns ==<br />
<br />
If you want to control the order in which scenarios are listed, set up custom text for scenarios, or customise any other aspects of the game when playing your scenarios, you will need to edit additional files. Editing these files is easy, and their contents are explained below.<br />
<br />
===CAMPAIGN.TXT===<br />
This file denotes the order of any campaigns that are included on the scenario selection screen. Note that if this file does not exist, then the game will attempt to use all the scenarios in the SCENARIOS directory.<br />
<br />
The form of the file is simply:<br />
<br />
<nowiki>[Scenario1]<br />
[Scenario2]</nowiki><br />
Where the scenario names are the filenames of your user scenarios. So in this case you would have Scenario1 and Scenario2 BAM files from the editor.<br />
<br />
===Custom Text===<br />
You can have multiple text files inside the campaign directory. They must all be named TEXT<N>.TXT where N can be any number from 0 to 63. For example text0.txt or text12.txt.<br />
<br />
These text files must be UNICODE files, and so support non-ASCII characters [Note: you may need to use applicable fonts to allow the display of non-ASCII characters].<br />
<br />
Notepad++ easily allows you to save UNICODE files, as do most standard text editors.<br />
<br />
The format of these (and all) strings files is:<br />
<nowiki><stringTag>, “<string>”,</nowiki><br />
The commas are important! Note that to insert a newline into a string, you need to use the ~ character.<br />
<br />
Strings used by the game are:<br />
<br />
<nowiki>IDS_CAMPAIGN_NAME, “The campaign name shown on the campaign selection screen”,<br />
IDS_SCENARIO_DESC_<scenarioName>, “one string per scenario, shown over the scenario selection display if there is no custom UI for the scenario (see below)”, <br />
IDS_CAMPAIGN_TEXT, “Text describing the campaign, shown on the campaign selection screen if there is no custom UI”,</nowiki><br />
Some of these strings are set up for you when you create the campaign, others you can add if you want to have more customised text shown when people play your campaign.<br />
<br />
===Campaign Graphics===<br />
There are two files you can create to customise the look of your campaign. These files can be in either TGA or DDS (recommended) format. If either of these files are not defined, then the game uses some default images. 1024×1024 or 512×512 are usual sizes for these two images.<br />
<br />
BACKDROP.DDS (or TGA) This file is used as the backdrop behind your scenarios after you select your campaign to play.<br />
<br />
ICON.DDS (or TGA) Shown on the campaign selection screen.<br />
<br />
===Campaign Scripts===<br />
If you create a CAMPAIGN.BSF script file, then it will enable you to have campaign-level logic which you can then deal with within your battles.<br />
<br />
Campaign scripts make use of campaign variables, which are special global variables defined in the CAMPAIGN.TXT file. To define a campaign variable, you need to add a line of the form:<br />
<nowiki>VAR <name></nowiki><br />
for example<br />
<nowiki>VAR TotalKills</nowiki><br />
You can then use the SetCampaignVar and GetCampaignVar commands any scripts that you use, including any campaign script. You are limited to 64 campaign variables, although each one can be accessed as an array of 8 entries (see the documentation for Get/SetCampaignVar for more details).<br />
<b>NOTE: This has now been superceded by the use of global singleton variables in the script - that is, any globals defined in the campaign script will be saved and loaded during the campaign playthrough, and so are a simpler way to save campaign logic data.</b><br />
<br />
===Campaign Script Callbacks===<br />
Many times we want to be able to respond to events from within the game. The game uses callback function to do this. These are specifically named functions which are passed information by the game.<br />
<br />
You can define certain campaign functions which will be called when specific actions happen in the game. They are:<br />
<nowiki>// Called whenever a unit is destroyed.<br />
FUNCTION KILL_CALLBACK(side, id)<br />
<br />
// called every time a campaign is loaded up. <br />
// Note: Not just when a new campaign is started.<br />
FUNCTION INIT_CAMPAIGN()</nowiki><br />
===Summary===<br />
You can create your own campaigns entirely from within the game, but you can also create custom text and images to change the look of your campaign.<br />
You can also create custom UI, animated briefings, custom units, and even give units entirely different behaviors!<br />
<br />
==Scenarios==<br />
Without a special script, a scenario will end once all of the enemy's units are destroyed. But a scenario script allows you to have much finer control of the course of a battle.<br />
===The Scenario Script===<br />
The scenario script interacts with the mission through a number of callback functions.<br />
====Tick====<br />
<nowiki>// Called every tick<br />
FUNCTION TICK( side )</nowiki><br />
This callback is called every tick of the model (30 times a second). The side is the side currently having its turn. Use this function to track ongoing events, like the death of units, or movement of the enemy.<br />
<br />
====StartTurn====<br />
<nowiki>// Called at the beginning of each turn<br />
FUNCTION STARTTURN( side, mode )</nowiki><br />
At the start of each new turn, this function is called. The mode parameter describes the type of game in progress (e.g. single player, PBEM, etc), and is generally not needed. Use this function to trigger events based on the turn.<br />
<br />
Note that this function is called once per turn, and the sequence of turns is as follows:<br />
<br />
<nowiki>-1 : This is a pre-turn called when a scenario is first begun<br />
0 : First turn for side 0<br />
1 : First turn for side 1<br />
2 : Second turn for side 0<br />
3 : Second turn for side 1<br />
4 : etc</nowiki><br />
<br />
====StartTurnPost====<br />
<nowiki>// Called after all the default start turn logic has been done<br />
FUNCTION STARTTURNPOST( side, mode )</nowiki><br />
After the StartTurn function is called, there is other internal logic which occurs (for example, updating the APs for each unit, and calling any unit script functions). This function can be used optionally to make changes once all the normal logic and value resets are done. And example is altering the default sight ranges, or number of APs a unit has.<br />
<br />
====Win_Scenario_Callback====<br />
<nowiki>// Called each tick. Can determine whether there is a winner for the scenario.<br />
FUNCTION WIN_SCENARIO_CALLBACK( winner )<//nowiki><br />
This callback if called every tick provided no winner has been selected. The code passes in the side it thinks is the winner (-1 for no winner yet). It returns a new winner value. 0 or 1 for a winning side, and -1 for no winner. Thus it can prevent the default game logic from ending a battle should it need to.<br />
<br />
Note that this function is no longer called once a winner is set in any way (e.g. through the EndBattle command).<br />
<br />
====DrawScenarioUI====<br />
<nowiki>// Called every frame to render out any scenario specific UI<br />
FUNCTION DRAWSCENARIOUI()</nowiki><br />
You can use this function to render any custom UI which your scenario might desire. Examples would be tracking achievements, showing a turn countdown if there is a limit in the mission. But it could be anything you like using the UI script commands (see the list of script commands in the autodocs).<br />
<br />
Note that this display can be disabled by the user using the toggle which appears just below the Exit Battle button whenever this function is defined in the scenario.<br />
<br />
== File Layout Guide ==<br />
<nowiki>MYCAMPAIGN<br />
│ backdrop.dds<br />
│ Campaign.txt<br />
│ icon.dds<br />
│ sides.txt<br />
│ Squads.csv<br />
| ArmyList.txt<br />
│ Terrain.txt<br />
│ text1.txt<br />
│ uniticons.dds<br />
│<br />
├───AI<br />
│ AI.bsf<br />
│<br />
├───ANIM<br />
│ MyAnim.s3f<br />
│<br />
├───BONUS<br />
│ MyBonus.BSF<br />
│<br />
├───DATA<br />
│ │ music.txt<br />
│ │ sfx0.txt<br />
│ │<br />
│ ├───BATTLE<br />
│ │ ├───SCRIPTS<br />
│ │ ├───UNITS<br />
│ │ │ MyUnit.txt<br />
│ │ │ MyUnit_0.s3f<br />
│ │ │<br />
│ │ └───UNITTEXTURES<br />
│ ├───MUSIC<br />
│ ├───SOUNDS<br />
│ └───UI<br />
│ │ Campaign_Overlay.txt<br />
│ │ EndCamp.txt<br />
│ │ SCENUI_MyScenario.txt<br />
│ │<br />
│ └───TEXTURES<br />
│ │ CampaignListIcon.dds<br />
│ │<br />
│ └───ICONS<br />
│ MyUnit.dds<br />
│ MyUnit_SLOT.dds<br />
│<br />
├───OBJECTS<br />
├───TILES<br />
├───SCENARIOS<br />
│ MyScenario.bam<br />
│ MyScenario.bsf<br />
│ MyScenario.dds</nowiki></div>Richardshttps://archonwiki.slitherine.com/index.php?title=QuickStart&diff=155QuickStart2016-06-18T07:26:13Z<p>Richards: /* Iteration */</p>
<hr />
<div>= Iteration =<br />
Archon is designed to support rapid iteration, as such you can dynamically reload the following types of assets.<br />
<br />
;Shaders (SHIFT+F1)<br />
:Reloads all the currently loaded shaders. Edit and continue supported for shader errors.<br />
<br />
;Scripts (SHIFT+F4)<br />
:Reloads all currently loaded scripts. Edit and continue supported.<br />
<br />
;Textures (CONTROL+HOME)<br />
:Reloads any textures which have changed since loading.<br />
<br />
;Strings and UI files (CTRL+END)<br />
: Reloads strings and UI files.</div>Richardshttps://archonwiki.slitherine.com/index.php?title=Scripting&diff=127Scripting2016-05-12T12:36:27Z<p>Richards: /* Control */</p>
<hr />
<div>Archon scripting is a much expanded iteration on the original STUB scripting. The original documentation is included/updated below.<br />
<br />
== Script Syntax ==<br />
<br />
CScript is a simple scripting language, based on the basic C syntax. It provides a simple framework to hook it up to an application, effectively the function call handling.<br />
<br />
Even if you have not had experience with scripting languages before, you can begin to add or alter your custom scripts using just a simple text editor (see the Tools section for details on how to help make editing better with syntax highlighting and other useful features).<br />
<br />
The team recommend taking a look at the existing scripts to begin to see the way the scripting works. Beginning by tweaking existing scripts is a great way to see something onscreen quickly.<br />
<br />
All scripting must be part of a function. A function has the form:<br />
<br />
<code>FUNCTION <name>( [<param>], [<param>], ...)<br />
{<br />
<function body><br />
}</code><br />
<br />
For example<br />
<br />
<code>FUNCTION Tick( side ) <br />
{<br />
}</code><br />
<br />
or<br />
<br />
<code>FUNCTION Process( TType data )<br />
{<br />
}</code><br />
<br />
There is a limit of 12 parameters that can be passed to a given function.<br />
<br />
All functions return a value, although you do not have to use it, nor use the return should you decide not to. To return a value use:<br />
<br />
<code>return <value> ;</code><br />
<br />
Note that a call to return will skip any further processing in the function and exit with the value immediately.<br />
<br />
=== Macros ===<br />
<br />
You can define macros - textual substitutions - in the same way as for C. Note that #/## notations are not supported. E.g.<br />
<br />
<code>#define MAX_UNITS 256</code><br />
<br />
==== Predefined Macros ====<br />
<br />
Some macros may be predefined based on other data files. The names of these predefined macros will always begin with a $ character and all characters will be in uppercase.<br />
* Macros will be predefined for all colours specified in the COLOURDICTIONARY chunk of DATA/UISETTINGS.TXT that are appropriate for use where script commands expect colours as parameters.<br />
* Macros will be predefined for all fonts specified in SYSTEM/FONT.TXT that are appropriate for use where script commands expect fonts as parameters.<br />
<br />
For example, <code>DrawMapString(x, y, $SMALLFONT, $ALERTCOLOUR)</code><br />
<br />
=== Structures ===<br />
<br />
You can define structures in a similar way to C. The format is:<br />
<br />
<code>struct <typename><br />
{ <br />
<contents><br />
}</code><br />
<br />
For example<br />
<br />
<code>struct TPos<br />
{<br />
int x ;<br />
int y ;<br />
}<br />
<br />
struct TObject<br />
{ <br />
int type ;<br />
TPos position ;<br />
int orders[4] ;<br />
}</code><br />
<br />
Access is as per standard C syntax:<br />
<br />
<code>TObject obj ;<br />
<br />
obj.type = 5 ;<br />
obj.orders[0] = 0 ;<br />
obj.position.x = 9 ;</code><br />
<br />
=== Control ===<br />
<br />
You have 2 ways to control the flow of a function. The IF statement, and the FOR statement. All code executed by an IF or FOR statement must be enclosed in a block (within a { } pair).<br />
<br />
An IF statement has the form:<br />
<br />
<code>if( <condition> )<br />
{<br />
<execute if condition true><br />
}<br />
else if( <condition 2> )<br />
{<br />
<execute if condition 2 true><br />
}<br />
else<br />
{<br />
<execute if neither condition false><br />
}</code><br />
<br />
Note that the else keyword and following code is optional. Where the condition can be made up of various logical operators such as && (and) and || (or). So an example statement would be:<br />
<br />
<code>if( ( a == 10) || ( b == 5 ) )<br />
{<br />
}</code><br />
<br />
A FOR statement has the form:<br />
<br />
<code>for(<start>; <condition>; <delta>)<br />
{<br />
}</code><br />
<br />
<start> is a statement initialising the loop variable, <condition> is a check where the loop will continue so long as it is true, and the <delta> statement is a simple expression incrementing (or decrementing) the loop variable. So the statement:<br />
<br />
<code>for( i=0; i<10; i++ )<br />
{<br />
}</code><br />
<br />
would repeat the code inside the block with i having values of 0 to 9 inclusive, before moving onto any following code.<br />
<br />
Key Differences with C<br />
<br />
+ There is no operator priority. Brackets are supported and their use recommended.<br />
<br />
+ IF statements can can use only a single && or || statement pair when expressions are not contained in brackets. That is:<br />
<br />
<code>if( a == 0 && b == 0 && c == 0 ) is invalid<br />
<br />
if( (a == 0) && (b == 0) && (c == 0) ) is valid</code><br />
<br />
+ All atomic variables are signed integers.<br />
<br />
+ Single line IF and FOR result expressions are not allowed:<br />
<br />
<code>if(a == 0) is invalid<br />
a = 10 ;<br />
<br />
if(a == 0) is valid<br />
{<br />
a = 10 ;<br />
}</code> <br />
<br />
+ All structures are passed by reference to functions (e.g. any changes to a passed in struct in a function will affect the passed in variable in the calling function). <br />
<br />
<br />
Including Files<br />
<br />
You can include other files in your scripts. These can contain useful utility functions, either of your own, or from the game. The syntax for including a file is:<br />
<br />
<code>include "filename.bsf"</code><br />
<br />
(note that #include will work also)<br />
<br />
The script system will look for the file in the following places in the following order:<br />
<br />
same folder as the initial file<br />
<campaign folder>/DATA/BATTLE/SCRIPTS<br />
<campaign folder>/DATA/SCRIPTS<br />
DATA/BATTLE/SCRIPTS<br />
DATA/SCRIPTS<br />
filename as provided<br />
<br />
=== Singletons ===<br />
<br />
Any variables defined outside a function are considered to be global, singleton variables. These variables are a single instance across all scripts that access them. You can also initialise singletons (but not local variables) this initialiser lists. These should exactly match the number of entries, and do not support sub-lists. E.g.<br />
<br />
<code>int gArray[3][2]={0,1,2,3,4,5} ;</code><br />
<br />
=== The char Type ===<br />
<br />
You can define and use arrays of chars as strings. Versions of the sprintf and strcpy functions exist. These functions are safe, in that they cannot exceed the bounds of their output strings.<br />
<br />
<code>char name[32] ;<br />
char work[32] ;<br />
int someValue ;<br />
<br />
someValue = 99 ;<br />
name[0] = 'A' ;<br />
PrintStringLiteral( name ) ;<br />
sprintf( work, "%d", someValue ) ;<br />
strcpy( name, work ) ;</code><br />
<br />
Limitations to note:<br />
<br />
char arrays must be multiples of 4 in size, multidimensional arrays are supported.<br />
<br />
== The Debugger ==<br />
There is an integrated script debugger which can be activated with <b>CTRL+F3</b>. This allows you to check variable values, flow, etc. Note that the debugger is still work in progress. You can insert a breakpoint into your code using the <br />
<br />
<code>DebugBreak;</code><br />
<br />
intrinsic, as well as dynamic breakpoints you set yourself in the code.</div>Richardshttps://archonwiki.slitherine.com/index.php?title=Latest_Additions&diff=126Latest Additions2016-05-05T09:47:40Z<p>Richards: /* Force Selection Script Additions */</p>
<hr />
<div>= Force Selection Script Additions =<br />
Tile. Additional script commands to allow for custom force controls.<br />
<nowiki>//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.<br />
SetForceControlSelected(objectName, x, y, select)<br />
<br />
//returns 0 if the unit on x,y is unselected, 1 if selected, 2 if fixed, (-1 if no unit is on the tile)<br />
GetForceControlSelected(objectName, x, y)<br />
<br />
//set the zoom level for the camera in battle<br />
SetZoom(zoom)</nowiki><br />
There is now an additional tag for ForceSelection UI objects. HIDEBUTTONS will entirely hide the display of the normal force control buttons.<br />
<br />
= OBJ_UI_RENDER/HANDLE Change =<br />
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.<br />
<nowiki>FUNCTION UI_OBJ_RENDER(x,y,width,height,pass, name)<br />
FUNCTION UI_OBJ_HANDLE(data, event, id, name)</nowiki><br />
<br />
= Water =<br />
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.<br />
<br />
= Flying Units =<br />
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.<br />
<br />
= GetPositionDistance Script Command =<br />
Takes two positions (in 100ths) and returns the distance between them.<br />
<nowiki>//return the distance in 100ths between two points that are also in 100ths<br />
GetPositionDistance(x1,y1,x2,y2)</nowiki><br />
<br />
= Terrain Following Objects =<br />
You can use the TERRAINFOLLOW tag to allow objects to align themselves to the terrain.<br />
<br />
= New Script Functions =<br />
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.<br />
<nowiki>//sort the array by the elementName entry (which must be an integer). If direction included, 0 is ascending (the default), 1 is descending.<br />
Sort(elementName, array, count, [direction])<br />
<br />
//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<br />
FindStringInArray(string, elementName, array)</nowiki><br />
<br />
An example would be<br />
<nowiki>struct TTest<br />
{<br />
char name[32] ;<br />
int value ;<br />
}<br />
...<br />
TTest array[2][32] ;<br />
<br />
Sort("value", array[1], 32) ;</nowiki><br />
<br />
= AddVizUnitFormation Command =<br />
This command allows to you trigger and wait for a formation change.<br />
<br />
<nowiki>//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.<br />
AddVizUnitFormation(id)</nowiki><br />
<br />
=Formation Facing Control =<br />
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.<br />
<br />
<nowiki>//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<br />
SetFormationFacing(n, facing)</nowiki><br />
<br />
= Scrollable Text Controls =<br />
Text controls can now be made scrollable. Add<br />
<br />
<nowiki>SCROLLING <control texture> </nowiki><br />
<br />
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.<br />
<br />
= String Manipulation and Creation =<br />
You can allow the user to create string entries (expected in the editor) via script. The new functions are:<br />
<br />
<nowiki>//places the contents of the edit box into the first UI string.<br />
GetUIEditbox(objectName)<br />
<br />
//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<br />
AddUserString(tagBody)<br />
<br />
//remove the denoted user string from the temporary store. Has no effect if the string has already been written out to the file.<br />
RemoveUserString(tag)<br />
<br />
//flush out any user strings to the TEXT9.TXT file. NOTE: this is done automatically at map save and editor exit.<br />
FlushUserStrings()<br />
<br />
//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.<br />
GetHighestStringIndex(tagBody)<br />
<br />
//return 1 if the string exists, 0 otherwise<br />
DoesStringExist(tag)<br />
<br />
//get the denoted string into the first UI string if it exists. Empty otherwise<br />
GetString(tag)</nowiki><br />
<br />
So users can type in strings which are then added to the list of strings available to use ingame.<br />
<br />
= Script Updates =<br />
1 - the break directive to trigger the debugger has changed to DebugBreak ; to prevent confusion with the C break statement.<br />
<br />
2 - while loops are now supported. Note that the test cannot be an operation, so<br />
<code>while(i--)</code><br />
will not work, as the scripting does not treat the left hand of an expression as a value in the same way as C.<br />
<br />
= Custom UI Object Rendering (inc Listbox Items) =<br />
Individual UI objects can now have their own scripts attached, including their own rendering callbacks. As before the rendering callback is of the form<br />
<br />
<code>FUNCTION UI_OBJ_RENDER(x,y,width,height,pass)</code><br />
<br />
Where pass is 0/1 for pre/post normal control rendering.<br />
<br />
Listboxes can also include<br />
<br />
<code>FUNCTION UI_OBJ_RENDER_ITEM(x,y,width,height,pass,flags, item, name)</code><br />
<br />
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.<br />
<br />
= Listboxes: Multiple Selection =<br />
You can enable multiple selection for listboxes with the MULTISELECT tag in their UI definition. Then use <br />
<br />
<nowiki>//return 1 if the specified item is selected, zero otherwise<br />
IsUIListboxItemSelected(object, index)<br />
<br />
//returns the number of items in a listbox<br />
GetUIListboxCount(object)</nowiki><br />
<br />
to interrogate the listbox. <br />
<br />
<i>Note: This means that it is possible to get UI script triggers from listboxes which are actually a CTRL+ event which unselects the item.</i><br />
<br />
= Scripting: GetWorkString =<br />
You can now use GetWorkString on the RHS of an assignment expression, e.g.<br />
<code>char myString[32] ;<br />
myString = GetWorkString() ;</code><br />
The contents will be safely truncated to the source string's size.<br />
<br />
= 3DVIEW UI Control =<br />
<br />
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).<br />
<br />
Script commands to control this are:<br />
<br />
<nowiki><br />
//if filename starts with # then defaults to standard unit loading paths.<br />
UIObject3DLoad(objectName, filename, [texturePath])<br />
<br />
//automatically set the zoom and camera origin to the size of the currently loaded object<br />
UIObject3DAuto(objectName)<br />
<br />
//set the origin position and vertical angle of the camera.<br />
SetUIObject3DCamera(objectName, x,y,z,angle,[zoom])<br />
<br />
//set the options for the view. 0 for off, nonzero for on.<br />
SetUIObject3DOptions(objectName, allowZoom, allowHorizontalRotate, allowVerticalRotate)<br />
</nowiki></div>Richardshttps://archonwiki.slitherine.com/index.php?title=Units&diff=123Units2016-04-26T18:12:39Z<p>Richards: /* Custom Formations */</p>
<hr />
<div>= Custom Formations =<br />
Custom formations work using a callback function which sets up the formation data for a given unit's men. The callback function has the form:<br />
<br />
<code>FUNCTION FORMATION_CALLBACK(me)</code><br />
<br />
this function will make use of the SetFormationRow function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile. offset is [0, 32], angle is [0, 359]. Only relevant in FORMATION_CALLBACK<br />
SetFormationRow(n, offset, angle)</code><br />
<br />
or, alternatively, the SetFormationRowXY function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile, using offsets when facing 0. offset is [0, 32]. Only relevant in FORMATION_CALLBACK<br />
<br />
SetFormationRowXY(n, x, y)</code><br />
<br />
NOTE: What both these functions set is the points making up the formation. They do not assign a particular man to a particular formation point. A scoring algorithm determines which man moves to which formation point when the formation changes.<br />
<br />
= Unit Order Scripting =<br />
The ability to alter the behaviour of the units is one of the most powerful areas of the game scripting. Each unit type can have its own set of scripts and behaviour (although you don't have to do this). As you will see, you can get units to do almost anything with a well written script.<br />
<br />
A unit will look for a script which is called <name>.BSF in the DATA\BATTLE\SCRIPTS directory, where <name> is the unit name as denoted by the Name entry in the squads.csv file. <b>If the code cannot find a unique BSF file, it will load up a script called $DEFAULT.BSF to handle all the unit's behaviours.</b><br />
<br />
The approach that the game itself uses is to have all units use a single set of scripts, but to use the unit attributes (as defined in the squads file) to determine what a unit can or cannot do. This has the advantage that abilities can be added or removed from a unit simply by altering data.<br />
<br />
On the other hand, you might have units with very disparate abilities, in which case you might be best using individual scripts for each unit, bearing in mind you can always INCLUDE any shared functionality.<br />
<br />
== Unit Callback Functions ==<br />
<br />
There are a variety of functions which a unit can have which are called at times by the code.<br />
<br />
=== StartTurn ===<br />
<br />
<code>FUNCTION STARTTURN( me )</code><br />
This function is called at the start of a unit's side's turn. This would be used to reset any per-turn counters or limits. Examples would be a unit's shots, or tick up its morale. STARTTURN is a required function for every unit.<br />
<br />
=== CustomTrigger ===<br />
<br />
<code>FUNCTION CUSTOM_TRIGGER( me, a, b, c, d )</code><br />
The custom trigger is a low level function used to trigger scripting from the unit animation files. It passes through any of the 4 parameters allowed in the animation file for a unit.<br />
<br />
=== Init Functions ===<br />
<br />
<code>FUNCTION INIT_*( me )</code><br />
Any function which is named with INIT_ as the first 5 characters will be called on unit creation. You can use this to set up attributes, initialised starting values, etc. Note that if there is more than one INIT_ function then the order they will be called in cannot be guaranteed.<br />
<br />
=== Unit Ability Functions ===<br />
To actually allow a unit to do anything, it needs to have scripted behaviours.<br />
<br />
There are 3 types of ability, depending upon the contents of the tile you are attempting to action. These are TILE_, ALL_, and UNIT_. TILE_ can operate only on empty tiles, ALL_ will attempt to work on all tiles, and UNIT_ will only operate on a tile with a unit present on it.<br />
<br />
The key functions which will allow you to begin creating unit behaviours are described below. Note we will show all examples using the ALL_ tag, but this can be replaced with the TILE_ or UNIT_ tag to simplify the scripting as desired.<br />
<br />
Note that for all the functions described here, you can omit any of the parameters you don't use, and that the code will correctly assign them no matter where in the param list they are. Indeed, you can have extra parameters in a function header and they will be set to zero if they are called by the code rather than by you.<br />
<br />
=== Checking ===<br />
<code>FUNCTION CHECK_ALL_<name>( me, unit, tilex, tiley [, reaction] )</code><br />
This function is used to determine whether a unit can perform a task. The return value can be either the cost of the action in AP, or -2 if you with the task icon not to be shown, or -1 if you wish to show the icon in a disabled state. See below for details on the optional reaction parameter.<br />
<br />
=== Executing ===<br />
<code>FUNCTION ALL_<name>(me, unit, tilex, tiley)</code><br />
This is the function which is called when the user selects the action for the unit. Note this cannot happen if the check function returns -1 or -2 as the icon will not be selectable.<br />
<br />
=== Reacting ===<br />
<code>FUNCTION REACT_ALL_<name>(me, unit, tilex, tiley)</code><br />
If you want a unit to be able to react to other units, then you make use of the reaction function. This works in concert with the CHECK_ function for a given command. The system first calls the CHECK_ function to determine whether an action is possible against the reacted-against unit. Note that when CHECK_ is called in this case, the optional reaction parameter is set to 1, rather than 0 as it normally is.<br />
<br />
If the check function returns >=0 then this is taken as the AP cost of the action, and the system then calls the REACT_ function. The react function should return a 'score' for this unit using this action to react to the threat. Examples of how to calculate this score we be based on things like chance of success, range to target, etc - as dependent upon the game model. The system will go through all units on the reacting side and then sort the reactions by their scores, and execute them in the 'best' order. Note that returning -1 from a REACT_ function means that you do not want the unit to attempt to react with this action.<br />
<br />
== Other Unit Callbacks ==<br />
=== Moving from Tile ===<br />
<code>FUNCTION MOVE_FROM_TILE_CALLBACK(me)</code><br />
This callback is called whenever a unit is about to move off from a tile during a movement (e.g. it is called once for each tile on the route). Returning -1 or -2 will cancel the movement (e.g. the whole route), the difference being that -1 does not refund any APs used for movement, while -2 does. Return zero for normal movement.<br />
<br />
=== Deployment ===<br />
<code>FUNCTION DEPLOYCHECK_ALL_MOVE(me, unit, tilex, tiley)</code><br />
This works in the same way as the normal CHECK_ function, but is only called during a deployment phase - if it exists then it is called rather than the normal CHECK_ function during deployment.<br />
<br />
=== Icon Setup ===<br />
<code>FUNCTION UISETUP_ALL_<name>( x, y, width, height, me, tilex, tiley )</code><br />
This optional function can be used to setup and draw the order icon. The x,y,width,height parameters are the onscreen positions of the button. Functions such as SetUITexture are used within this function, and any button tooltip is also set up here.<br />
<br />
=== Custom Button Rendering ===<br />
<code>FUNCTION UIBUTTON_ALL_MOVE(me, x,y,width, height, tilex, tiley)</code><br />
This function allows for custom rendering of the order button.</div>Richardshttps://archonwiki.slitherine.com/index.php?title=Latest_Additions&diff=117Latest Additions2016-04-04T10:06:33Z<p>Richards: /* Formation Facing Control */</p>
<hr />
<div>= GetPositionDistance Script Command =<br />
Takes two positions (in 100ths) and returns the distance between them.<br />
<nowiki>//return the distance in 100ths between two points that are also in 100ths<br />
GetPositionDistance(x1,y1,x2,y2)</nowiki><br />
<br />
= Terrain Following Objects =<br />
You can use the TERRAINFOLLOW tag to allow objects to align themselves to the terrain.<br />
<br />
= New Script Functions =<br />
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.<br />
<nowiki>//sort the array by the elementName entry (which must be an integer). If direction included, 0 is ascending (the default), 1 is descending.<br />
Sort(elementName, array, count, [direction])<br />
<br />
//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<br />
FindStringInArray(string, elementName, array)</nowiki><br />
<br />
An example would be<br />
<nowiki>struct TTest<br />
{<br />
char name[32] ;<br />
int value ;<br />
}<br />
...<br />
TTest array[2][32] ;<br />
<br />
Sort("value", array[1], 32) ;</nowiki><br />
<br />
= AddVizUnitFormation Command =<br />
This command allows to you trigger and wait for a formation change.<br />
<br />
<nowiki>//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.<br />
AddVizUnitFormation(id)</nowiki><br />
<br />
=Formation Facing Control =<br />
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.<br />
<br />
<nowiki>//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<br />
SetFormationFacing(n, facing)</nowiki><br />
<br />
= Scrollable Text Controls =<br />
Text controls can now be made scrollable. Add<br />
<br />
<nowiki>SCROLLING <control texture> </nowiki><br />
<br />
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.<br />
<br />
= String Manipulation and Creation =<br />
You can allow the user to create string entries (expected in the editor) via script. The new functions are:<br />
<br />
<nowiki>//places the contents of the edit box into the first UI string.<br />
GetUIEditbox(objectName)<br />
<br />
//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<br />
AddUserString(tagBody)<br />
<br />
//remove the denoted user string from the temporary store. Has no effect if the string has already been written out to the file.<br />
RemoveUserString(tag)<br />
<br />
//flush out any user strings to the TEXT9.TXT file. NOTE: this is done automatically at map save and editor exit.<br />
FlushUserStrings()<br />
<br />
//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.<br />
GetHighestStringIndex(tagBody)<br />
<br />
//return 1 if the string exists, 0 otherwise<br />
DoesStringExist(tag)<br />
<br />
//get the denoted string into the first UI string if it exists. Empty otherwise<br />
GetString(tag)</nowiki><br />
<br />
So users can type in strings which are then added to the list of strings available to use ingame.<br />
<br />
= Script Updates =<br />
1 - the break directive to trigger the debugger has changed to DebugBreak ; to prevent confusion with the C break statement.<br />
<br />
2 - while loops are now supported. Note that the test cannot be an operation, so<br />
<code>while(i--)</code><br />
will not work, as the scripting does not treat the left hand of an expression as a value in the same way as C.<br />
<br />
= Custom UI Object Rendering (inc Listbox Items) =<br />
Individual UI objects can now have their own scripts attached, including their own rendering callbacks. As before the rendering callback is of the form<br />
<br />
<code>FUNCTION UI_OBJ_RENDER(x,y,width,height,pass)</code><br />
<br />
Where pass is 0/1 for pre/post normal control rendering.<br />
<br />
Listboxes can also include<br />
<br />
<code>FUNCTION UI_OBJ_RENDER_ITEM(x,y,width,height,pass,flags, item, name)</code><br />
<br />
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.<br />
<br />
= Listboxes: Multiple Selection =<br />
You can enable multiple selection for listboxes with the MULTISELECT tag in their UI definition. Then use <br />
<br />
<nowiki>//return 1 if the specified item is selected, zero otherwise<br />
IsUIListboxItemSelected(object, index)<br />
<br />
//returns the number of items in a listbox<br />
GetUIListboxCount(object)</nowiki><br />
<br />
to interrogate the listbox. <br />
<br />
<i>Note: This means that it is possible to get UI script triggers from listboxes which are actually a CTRL+ event which unselects the item.</i><br />
<br />
= Scripting: GetWorkString =<br />
You can now use GetWorkString on the RHS of an assignment expression, e.g.<br />
<code>char myString[32] ;<br />
myString = GetWorkString() ;</code><br />
The contents will be safely truncated to the source string's size.<br />
<br />
= 3DVIEW UI Control =<br />
<br />
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).<br />
<br />
Script commands to control this are:<br />
<br />
<nowiki><br />
//if filename starts with # then defaults to standard unit loading paths.<br />
UIObject3DLoad(objectName, filename, [texturePath])<br />
<br />
//automatically set the zoom and camera origin to the size of the currently loaded object<br />
UIObject3DAuto(objectName)<br />
<br />
//set the origin position and vertical angle of the camera.<br />
SetUIObject3DCamera(objectName, x,y,z,angle,[zoom])<br />
<br />
//set the options for the view. 0 for off, nonzero for on.<br />
SetUIObject3DOptions(objectName, allowZoom, allowHorizontalRotate, allowVerticalRotate)<br />
</nowiki></div>Richardshttps://archonwiki.slitherine.com/index.php?title=Units&diff=103Units2016-03-15T18:01:42Z<p>Richards: </p>
<hr />
<div>= Custom Formations =<br />
Custom formations work using a callback function which sets up the formation data for a given unit's men. The callback function has the form:<br />
<br />
<code>FUNCTION FORMATION_CALLBACK(me)</code><br />
<br />
this function will make use of the SetFormationRow function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile. offset is [0, 32], angle is [0, 359]. Only relevant in FORMATION_CALLBACK<br />
SetFormationRow(n, offset, angle)</code><br />
<br />
or, alternatively, the SetFormationRowXY function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile, using offsets when facing 0. offset is [0, 32]. Only relevant in FORMATION_CALLBACK<br />
<br />
SetFormationRowXY(n, x, y)</code><br />
<br />
<br />
= Unit Order Scripting =<br />
The ability to alter the behaviour of the units is one of the most powerful areas of the game scripting. Each unit type can have its own set of scripts and behaviour (although you don't have to do this). As you will see, you can get units to do almost anything with a well written script.<br />
<br />
A unit will look for a script which is called <name>.BSF in the DATA\BATTLE\SCRIPTS directory, where <name> is the unit name as denoted by the Name entry in the squads.csv file. <b>If the code cannot find a unique BSF file, it will load up a script called $DEFAULT.BSF to handle all the unit's behaviours.</b><br />
<br />
The approach that the game itself uses is to have all units use a single set of scripts, but to use the unit attributes (as defined in the squads file) to determine what a unit can or cannot do. This has the advantage that abilities can be added or removed from a unit simply by altering data.<br />
<br />
On the other hand, you might have units with very disparate abilities, in which case you might be best using individual scripts for each unit, bearing in mind you can always INCLUDE any shared functionality.<br />
<br />
== Unit Callback Functions ==<br />
<br />
There are a variety of functions which a unit can have which are called at times by the code.<br />
<br />
=== StartTurn ===<br />
<br />
<code>FUNCTION STARTTURN( me )</code><br />
This function is called at the start of a unit's side's turn. This would be used to reset any per-turn counters or limits. Examples would be a unit's shots, or tick up its morale. STARTTURN is a required function for every unit.<br />
<br />
=== CustomTrigger ===<br />
<br />
<code>FUNCTION CUSTOM_TRIGGER( me, a, b, c, d )</code><br />
The custom trigger is a low level function used to trigger scripting from the unit animation files. It passes through any of the 4 parameters allowed in the animation file for a unit.<br />
<br />
=== Init Functions ===<br />
<br />
<code>FUNCTION INIT_*( me )</code><br />
Any function which is named with INIT_ as the first 5 characters will be called on unit creation. You can use this to set up attributes, initialised starting values, etc. Note that if there is more than one INIT_ function then the order they will be called in cannot be guaranteed.<br />
<br />
=== Unit Ability Functions ===<br />
To actually allow a unit to do anything, it needs to have scripted behaviours.<br />
<br />
There are 3 types of ability, depending upon the contents of the tile you are attempting to action. These are TILE_, ALL_, and UNIT_. TILE_ can operate only on empty tiles, ALL_ will attempt to work on all tiles, and UNIT_ will only operate on a tile with a unit present on it.<br />
<br />
The key functions which will allow you to begin creating unit behaviours are described below. Note we will show all examples using the ALL_ tag, but this can be replaced with the TILE_ or UNIT_ tag to simplify the scripting as desired.<br />
<br />
Note that for all the functions described here, you can omit any of the parameters you don't use, and that the code will correctly assign them no matter where in the param list they are. Indeed, you can have extra parameters in a function header and they will be set to zero if they are called by the code rather than by you.<br />
<br />
=== Checking ===<br />
<code>FUNCTION CHECK_ALL_<name>( me, unit, tilex, tiley [, reaction] )</code><br />
This function is used to determine whether a unit can perform a task. The return value can be either the cost of the action in AP, or -2 if you with the task icon not to be shown, or -1 if you wish to show the icon in a disabled state. See below for details on the optional reaction parameter.<br />
<br />
=== Executing ===<br />
<code>FUNCTION ALL_<name>(me, unit, tilex, tiley)</code><br />
This is the function which is called when the user selects the action for the unit. Note this cannot happen if the check function returns -1 or -2 as the icon will not be selectable.<br />
<br />
=== Reacting ===<br />
<code>FUNCTION REACT_ALL_<name>(me, unit, tilex, tiley)</code><br />
If you want a unit to be able to react to other units, then you make use of the reaction function. This works in concert with the CHECK_ function for a given command. The system first calls the CHECK_ function to determine whether an action is possible against the reacted-against unit. Note that when CHECK_ is called in this case, the optional reaction parameter is set to 1, rather than 0 as it normally is.<br />
<br />
If the check function returns >=0 then this is taken as the AP cost of the action, and the system then calls the REACT_ function. The react function should return a 'score' for this unit using this action to react to the threat. Examples of how to calculate this score we be based on things like chance of success, range to target, etc - as dependent upon the game model. The system will go through all units on the reacting side and then sort the reactions by their scores, and execute them in the 'best' order. Note that returning -1 from a REACT_ function means that you do not want the unit to attempt to react with this action.<br />
<br />
== Other Unit Callbacks ==<br />
=== Moving from Tile ===<br />
<code>FUNCTION MOVE_FROM_TILE_CALLBACK(me)</code><br />
This callback is called whenever a unit is about to move off from a tile during a movement (e.g. it is called once for each tile on the route). Returning -1 or -2 will cancel the movement (e.g. the whole route), the difference being that -1 does not refund any APs used for movement, while -2 does. Return zero for normal movement.<br />
<br />
=== Deployment ===<br />
<code>FUNCTION DEPLOYCHECK_ALL_MOVE(me, unit, tilex, tiley)</code><br />
This works in the same way as the normal CHECK_ function, but is only called during a deployment phase - if it exists then it is called rather than the normal CHECK_ function during deployment.<br />
<br />
=== Icon Setup ===<br />
<code>FUNCTION UISETUP_ALL_<name>( x, y, width, height, me, tilex, tiley )</code><br />
This optional function can be used to setup and draw the order icon. The x,y,width,height parameters are the onscreen positions of the button. Functions such as SetUITexture are used within this function, and any button tooltip is also set up here.<br />
<br />
=== Custom Button Rendering ===<br />
<code>FUNCTION UIBUTTON_ALL_MOVE(me, x,y,width, height, tilex, tiley)</code><br />
This function allows for custom rendering of the order button.</div>Richardshttps://archonwiki.slitherine.com/index.php?title=Units&diff=102Units2016-03-15T17:59:47Z<p>Richards: </p>
<hr />
<div>= Custom Formations =<br />
Custom formations work using a callback function which sets up the formation data for a given unit's men. The callback function has the form:<br />
<br />
<code>FUNCTION FORMATION_CALLBACK(me)</code><br />
<br />
this function will make use of the SetFormationRow function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile. offset is [0, 32], angle is [0, 359]. Only relevant in FORMATION_CALLBACK<br />
SetFormationRow(n, offset, angle)</code><br />
<br />
or, alternatively, the SetFormationRowXY function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile, using offsets when facing 0. Only relevant in FORMATION_CALLBACK<br />
<br />
SetFormationRowXY(n, x, y)</code><br />
<br />
<br />
= Unit Order Scripting =<br />
The ability to alter the behaviour of the units is one of the most powerful areas of the game scripting. Each unit type can have its own set of scripts and behaviour (although you don't have to do this). As you will see, you can get units to do almost anything with a well written script.<br />
<br />
A unit will look for a script which is called <name>.BSF in the DATA\BATTLE\SCRIPTS directory, where <name> is the unit name as denoted by the Name entry in the squads.csv file. <b>If the code cannot find a unique BSF file, it will load up a script called $DEFAULT.BSF to handle all the unit's behaviours.</b><br />
<br />
The approach that the game itself uses is to have all units use a single set of scripts, but to use the unit attributes (as defined in the squads file) to determine what a unit can or cannot do. This has the advantage that abilities can be added or removed from a unit simply by altering data.<br />
<br />
On the other hand, you might have units with very disparate abilities, in which case you might be best using individual scripts for each unit, bearing in mind you can always INCLUDE any shared functionality.<br />
<br />
== Unit Callback Functions ==<br />
<br />
There are a variety of functions which a unit can have which are called at times by the code.<br />
<br />
=== StartTurn ===<br />
<br />
<code>FUNCTION STARTTURN( me )</code><br />
This function is called at the start of a unit's side's turn. This would be used to reset any per-turn counters or limits. Examples would be a unit's shots, or tick up its morale. STARTTURN is a required function for every unit.<br />
<br />
=== CustomTrigger ===<br />
<br />
<code>FUNCTION CUSTOM_TRIGGER( me, a, b, c, d )</code><br />
The custom trigger is a low level function used to trigger scripting from the unit animation files. It passes through any of the 4 parameters allowed in the animation file for a unit.<br />
<br />
=== Init Functions ===<br />
<br />
<code>FUNCTION INIT_*( me )</code><br />
Any function which is named with INIT_ as the first 5 characters will be called on unit creation. You can use this to set up attributes, initialised starting values, etc. Note that if there is more than one INIT_ function then the order they will be called in cannot be guaranteed.<br />
<br />
=== Unit Ability Functions ===<br />
To actually allow a unit to do anything, it needs to have scripted behaviours.<br />
<br />
There are 3 types of ability, depending upon the contents of the tile you are attempting to action. These are TILE_, ALL_, and UNIT_. TILE_ can operate only on empty tiles, ALL_ will attempt to work on all tiles, and UNIT_ will only operate on a tile with a unit present on it.<br />
<br />
The key functions which will allow you to begin creating unit behaviours are described below. Note we will show all examples using the ALL_ tag, but this can be replaced with the TILE_ or UNIT_ tag to simplify the scripting as desired.<br />
<br />
Note that for all the functions described here, you can omit any of the parameters you don't use, and that the code will correctly assign them no matter where in the param list they are. Indeed, you can have extra parameters in a function header and they will be set to zero if they are called by the code rather than by you.<br />
<br />
=== Checking ===<br />
<code>FUNCTION CHECK_ALL_<name>( me, unit, tilex, tiley [, reaction] )</code><br />
This function is used to determine whether a unit can perform a task. The return value can be either the cost of the action in AP, or -2 if you with the task icon not to be shown, or -1 if you wish to show the icon in a disabled state. See below for details on the optional reaction parameter.<br />
<br />
=== Executing ===<br />
<code>FUNCTION ALL_<name>(me, unit, tilex, tiley)</code><br />
This is the function which is called when the user selects the action for the unit. Note this cannot happen if the check function returns -1 or -2 as the icon will not be selectable.<br />
<br />
=== Reacting ===<br />
<code>FUNCTION REACT_ALL_<name>(me, unit, tilex, tiley)</code><br />
If you want a unit to be able to react to other units, then you make use of the reaction function. This works in concert with the CHECK_ function for a given command. The system first calls the CHECK_ function to determine whether an action is possible against the reacted-against unit. Note that when CHECK_ is called in this case, the optional reaction parameter is set to 1, rather than 0 as it normally is.<br />
<br />
If the check function returns >=0 then this is taken as the AP cost of the action, and the system then calls the REACT_ function. The react function should return a 'score' for this unit using this action to react to the threat. Examples of how to calculate this score we be based on things like chance of success, range to target, etc - as dependent upon the game model. The system will go through all units on the reacting side and then sort the reactions by their scores, and execute them in the 'best' order. Note that returning -1 from a REACT_ function means that you do not want the unit to attempt to react with this action.<br />
<br />
== Other Unit Callbacks ==<br />
=== Moving from Tile ===<br />
<code>FUNCTION MOVE_FROM_TILE_CALLBACK(me)</code><br />
This callback is called whenever a unit is about to move off from a tile during a movement (e.g. it is called once for each tile on the route). Returning -1 or -2 will cancel the movement (e.g. the whole route), the difference being that -1 does not refund any APs used for movement, while -2 does. Return zero for normal movement.<br />
<br />
=== Deployment ===<br />
<code>FUNCTION DEPLOYCHECK_ALL_MOVE(me, unit, tilex, tiley)</code><br />
This works in the same way as the normal CHECK_ function, but is only called during a deployment phase - if it exists then it is called rather than the normal CHECK_ function during deployment.<br />
<br />
=== Icon Setup ===<br />
<code>FUNCTION UISETUP_ALL_<name>( x, y, width, height, me, tilex, tiley )</code><br />
This optional function can be used to setup and draw the order icon. The x,y,width,height parameters are the onscreen positions of the button. Functions such as SetUITexture are used within this function, and any button tooltip is also set up here.<br />
<br />
=== Custom Button Rendering ===<br />
<code>FUNCTION UIBUTTON_ALL_MOVE(me, x,y,width, height, tilex, tiley)</code><br />
This function allows for custom rendering of the order button.</div>Richardshttps://archonwiki.slitherine.com/index.php?title=Units&diff=101Units2016-03-15T17:59:25Z<p>Richards: </p>
<hr />
<div>= Custom Formations =<br />
Custom formations work using a callback function which sets up the formation data for a given unit's men. The callback function has the form:<br />
<br />
<code>FUNCTION FORMATION_CALLBACK(me)</code><br />
<br />
this function will make use of the SetFormationRow function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile. offset is [0, 32], angle is [0, 359]. Only relevant in FORMATION_CALLBACK<br />
SetFormationRow(n, offset, angle)</code><br />
<br />
or, alternatively, the SetFormationRowXY function:<br />
<br />
<code>//Set the location of the nth man in the unit relative to the center of the tile, using offsets when facing 0. Only relevant in FORMATION_CALLBACK<br />
SetFormationRowXY(n, x, y)</code><br />
<br />
<br />
= Unit Order Scripting =<br />
The ability to alter the behaviour of the units is one of the most powerful areas of the game scripting. Each unit type can have its own set of scripts and behaviour (although you don't have to do this). As you will see, you can get units to do almost anything with a well written script.<br />
<br />
A unit will look for a script which is called <name>.BSF in the DATA\BATTLE\SCRIPTS directory, where <name> is the unit name as denoted by the Name entry in the squads.csv file. <b>If the code cannot find a unique BSF file, it will load up a script called $DEFAULT.BSF to handle all the unit's behaviours.</b><br />
<br />
The approach that the game itself uses is to have all units use a single set of scripts, but to use the unit attributes (as defined in the squads file) to determine what a unit can or cannot do. This has the advantage that abilities can be added or removed from a unit simply by altering data.<br />
<br />
On the other hand, you might have units with very disparate abilities, in which case you might be best using individual scripts for each unit, bearing in mind you can always INCLUDE any shared functionality.<br />
<br />
== Unit Callback Functions ==<br />
<br />
There are a variety of functions which a unit can have which are called at times by the code.<br />
<br />
=== StartTurn ===<br />
<br />
<code>FUNCTION STARTTURN( me )</code><br />
This function is called at the start of a unit's side's turn. This would be used to reset any per-turn counters or limits. Examples would be a unit's shots, or tick up its morale. STARTTURN is a required function for every unit.<br />
<br />
=== CustomTrigger ===<br />
<br />
<code>FUNCTION CUSTOM_TRIGGER( me, a, b, c, d )</code><br />
The custom trigger is a low level function used to trigger scripting from the unit animation files. It passes through any of the 4 parameters allowed in the animation file for a unit.<br />
<br />
=== Init Functions ===<br />
<br />
<code>FUNCTION INIT_*( me )</code><br />
Any function which is named with INIT_ as the first 5 characters will be called on unit creation. You can use this to set up attributes, initialised starting values, etc. Note that if there is more than one INIT_ function then the order they will be called in cannot be guaranteed.<br />
<br />
=== Unit Ability Functions ===<br />
To actually allow a unit to do anything, it needs to have scripted behaviours.<br />
<br />
There are 3 types of ability, depending upon the contents of the tile you are attempting to action. These are TILE_, ALL_, and UNIT_. TILE_ can operate only on empty tiles, ALL_ will attempt to work on all tiles, and UNIT_ will only operate on a tile with a unit present on it.<br />
<br />
The key functions which will allow you to begin creating unit behaviours are described below. Note we will show all examples using the ALL_ tag, but this can be replaced with the TILE_ or UNIT_ tag to simplify the scripting as desired.<br />
<br />
Note that for all the functions described here, you can omit any of the parameters you don't use, and that the code will correctly assign them no matter where in the param list they are. Indeed, you can have extra parameters in a function header and they will be set to zero if they are called by the code rather than by you.<br />
<br />
=== Checking ===<br />
<code>FUNCTION CHECK_ALL_<name>( me, unit, tilex, tiley [, reaction] )</code><br />
This function is used to determine whether a unit can perform a task. The return value can be either the cost of the action in AP, or -2 if you with the task icon not to be shown, or -1 if you wish to show the icon in a disabled state. See below for details on the optional reaction parameter.<br />
<br />
=== Executing ===<br />
<code>FUNCTION ALL_<name>(me, unit, tilex, tiley)</code><br />
This is the function which is called when the user selects the action for the unit. Note this cannot happen if the check function returns -1 or -2 as the icon will not be selectable.<br />
<br />
=== Reacting ===<br />
<code>FUNCTION REACT_ALL_<name>(me, unit, tilex, tiley)</code><br />
If you want a unit to be able to react to other units, then you make use of the reaction function. This works in concert with the CHECK_ function for a given command. The system first calls the CHECK_ function to determine whether an action is possible against the reacted-against unit. Note that when CHECK_ is called in this case, the optional reaction parameter is set to 1, rather than 0 as it normally is.<br />
<br />
If the check function returns >=0 then this is taken as the AP cost of the action, and the system then calls the REACT_ function. The react function should return a 'score' for this unit using this action to react to the threat. Examples of how to calculate this score we be based on things like chance of success, range to target, etc - as dependent upon the game model. The system will go through all units on the reacting side and then sort the reactions by their scores, and execute them in the 'best' order. Note that returning -1 from a REACT_ function means that you do not want the unit to attempt to react with this action.<br />
<br />
== Other Unit Callbacks ==<br />
=== Moving from Tile ===<br />
<code>FUNCTION MOVE_FROM_TILE_CALLBACK(me)</code><br />
This callback is called whenever a unit is about to move off from a tile during a movement (e.g. it is called once for each tile on the route). Returning -1 or -2 will cancel the movement (e.g. the whole route), the difference being that -1 does not refund any APs used for movement, while -2 does. Return zero for normal movement.<br />
<br />
=== Deployment ===<br />
<code>FUNCTION DEPLOYCHECK_ALL_MOVE(me, unit, tilex, tiley)</code><br />
This works in the same way as the normal CHECK_ function, but is only called during a deployment phase - if it exists then it is called rather than the normal CHECK_ function during deployment.<br />
<br />
=== Icon Setup ===<br />
<code>FUNCTION UISETUP_ALL_<name>( x, y, width, height, me, tilex, tiley )</code><br />
This optional function can be used to setup and draw the order icon. The x,y,width,height parameters are the onscreen positions of the button. Functions such as SetUITexture are used within this function, and any button tooltip is also set up here.<br />
<br />
=== Custom Button Rendering ===<br />
<code>FUNCTION UIBUTTON_ALL_MOVE(me, x,y,width, height, tilex, tiley)</code><br />
This function allows for custom rendering of the order button.</div>Richardshttps://archonwiki.slitherine.com/index.php?title=Test_Page&diff=100Test Page2016-03-15T17:16:35Z<p>Richards: </p>
<hr />
<div>This is a test 4</div>Richards