Difference between revisions of "Scenario Editing"

From MegaGlest
Jump to navigation Jump to search
(30 intermediate revisions by the same user not shown)
Line 7: Line 7:
 
*[http://www.lua.org/pil/ Programming in Lua]  
 
*[http://www.lua.org/pil/ Programming in Lua]  
 
*[http://lua-users.org/wiki/TutorialDirectory lua tutorials]  
 
*[http://lua-users.org/wiki/TutorialDirectory lua tutorials]  
*[http://lua-users.org/wiki Lua-Users.org Wiki]
+
*[http://lua-users.org/wiki Lua-Users.org Wiki]  
 +
== Lua/XML Intermixture Problem ==
 +
Due to XML's nature of using angle brackets for elements the parser will get confused and give an error if you try to use the left angle bracket in the scenario's XML file. 
 +
 
 +
A solution is to either swap the logic:
 +
 
 +
ie. if you wanted,<br />a &lt;= b <br />you would have to do,<br />b &gt;= a
 +
 
 +
Or use an external lua file as mentioned in the next section.
 +
 
 +
== Loading a Lua File ==
 +
To run Lua code in an external file you use the dofile function and provide the file path from the executable.
 +
 
 +
Example:
 +
 
 +
dofile("gae_scenarios/Tutorials/basic_tutorial/startup.lua")
  
 
== Language System ==
 
== Language System ==
Line 16: Line 31:
  
 
In advanced_tutorial_english.lng is :<br />MagicBrief=You are in command of the Magic faction, which uses mages and summoned creatures to fight.
 
In advanced_tutorial_english.lng is :<br />MagicBrief=You are in command of the Magic faction, which uses mages and summoned creatures to fight.
== Coordinate System ==
+
== Coordinates ==
The origin {0,0} is at the 'top left' (or north-west if you like) of the screen. A map's size defined in 'Tiles', each of which is a block of 2*2 Cells. For technical reasons the last row & column of Tiles are not valid.  So a 64 * 64 map is (64-1)*2 = 126 Cells wide and high.  The co-ordinates you supply in LUA are Cell coordinates, not Tile coordinates, and are 'zero indexed' (the first one is 0, the last is NumCells - 1).
+
Coordinates are specified as an array of two elements, the 'x' coordinate in the first element, and the 'y' coordinate in the second.
  
eg. A 128 x 128 Map has 254 x 254 Cells.
+
The origin {0,0} is at the 'top left' (or north-west if you like) of the screen. A map's size is defined in 'Tiles', each of which is a block of 2x2 Cells. For technical reasons the last row &amp; column of Tiles are not valid.  So a 64 * 64 map is (64-1)*2 = 126 Cells wide and high.  The co-ordinates you supply in LUA are Cell coordinates, not Tile coordinates, and are 'zero indexed' (the first one is 0, the last is NumCells - 1).
  
 +
eg. A 128 x 128 Map has 254 x 254 Cells. The northwest corner is {0,0} and the southeast corner is {253,253}.
 +
 +
When a function returns a 'Vec2i' you can access the individual co-ordinates by sub-scripting the array, 
 +
myPos = someFunction ()
 +
x = myPos[1]
 +
y = myPos[2]
 
When ever there is a parameter requiring positions of type Vec2i you can use the format '''{x,y}''' (where x and y are number values within the required range, as defined above) to select a position on the map.
 
When ever there is a parameter requiring positions of type Vec2i you can use the format '''{x,y}''' (where x and y are number values within the required range, as defined above) to select a position on the map.
 +
someFunction ( {x,y} )
 +
Here 'x' and 'y' could be numbers, variables, or 'expressions'.
 +
 +
You can also pass a 'pre created' array to these functions, which may be useful for scripting advanced scenarios.
  
 
== Faction Index and Players ==
 
== Faction Index and Players ==
Line 36: Line 61:
  
  
=== showMessage(string text, string header) ===
+
WARNING: All of these functions return type void and''' '''should''' not''' be used as arguments for other functions.
Display a message on the screen.
+
=== showMessage ( text, header ) ===
 +
Displays a message box on the screen, that will have to be dismissed by the player.
  
 
Parameters:<br />'''text''' - a string identifying the'' text'' from a language file<br />'''header''' - a string identifying the'' title bar text ''from a language file
 
Parameters:<br />'''text''' - a string identifying the'' text'' from a language file<br />'''header''' - a string identifying the'' title bar text ''from a language file
  
=== clearDisplayText() ===
+
=== setDisplayText ( text ) ===
Clears all message boxes from the screen, allowing space for the user to play, or for another message box to appear.
 
  
=== setDisplayText(string text) ===
 
  
 +
Displays a message at the top of the 'playing area'. Will remain until dismissed with clearDisplayText() or setDisplayText() is called again.
  
=== setCameraPosition(Vec2i pos) ===
+
Parameters:<br />'''text''' - a string identifying the'' text'' from a language file
 +
 
 +
=== clearDisplayText () ===
 +
Clears the message from the top of the playing area, previously set with setDisplayText().
 +
=== setCameraPosition ( pos ) ===
 
Move the camera to the coordinates of pos.
 
Move the camera to the coordinates of pos.
  
Parameters:<br />'''pos''' - an {x,y} position
+
Parameters:<br />'''pos''' - an array of two elements, specifying the co-ordinates {x,y}  
  
=== createUnit(string unitName, int factionIndex, Vec2i pos) ===
+
=== createUnit ( unit, faction, pos ) ===
Spawn a unit of unitName belonging to a faction.
+
Spawns a unit. If pos is occupied a nearby cell will be chosen.  The game attempts to keep a 2 cell 'border' between the new unit and other units or objects (ie. trees). '''Warning''':  If a position can not be found, the game crashes.
  
Parameters:<br />'''unitName''' - name of a unit in the loaded factions<br />'''factionIndex''' - a number identifier of the faction this unit will belong to<br />'''pos''' - an {x,y} position
+
Parameters:<br />'''unit''' - name of a unit in the loaded factions.<br />'''faction''' - the index of the faction this unit will belong to.<br />'''pos''' - an array of two elements, specifying the co-ordinates {x,y}
  
=== giveResource(string resourceName, int factionIndex, int amount) ===
+
=== giveResource ( resource, faction, amount ) ===
Give an amount of a specified resource to a player.<br />Parameters:<br />'''resourceName''' - a corresponding resource in the tech tree<br />'''factionIndex''' - the number identifier of the faction to give the resource<br />'''amount''' - the amount of resourceName the faction will receive
+
Give an amount of a specified resource to a player, negative values are valid and have the obvious effect.<br />Parameters:<br />'''resource''' - a corresponding resource in the tech tree<br />'''faction''' - the index of the faction to give the resource<br />'''amount''' - the amount of resource the faction will receive
  
=== givePositionCommand(int unitId, string commandName, Vec2i pos) ===
+
=== givePositionCommand ( unitId, command, pos ) ===
Instruct a unit to carry out a command.
+
Instruct a unit to carry out a command of type 'attack' or 'move'.
  
Parameters:<br />'''unitId''' - the id of a unit that is on the map<br />'''commandName''' - the type of command to carry out (eg 'attack', 'move')<br />'''pos''' - an {x,y} position
+
Parameters:<br />'''unitId''' - the id of a unit that has an attack and/or move command.<br />'''command''' - the type of command to carry out ('attack' or 'move')<br />'''pos''' - an array of two elements, specifying the co-ordinates {x,y}  
  
=== giveProductionCommand(int unitId, string producedName) ===
+
=== giveProductionCommand ( unitId, produced ) ===
  
=== giveUpgradeCommand(int unitId, string upgradeName) ===
+
Instruct a unit to carry out a command of type 'produce'.
  
=== disableAi(int factionIndex) ===
+
Parameters:<br />'''unitId''' - the id of a unit that is to produce the new unit.<br />'''produced''' - the type of unit to create. (ie. "worker")
Disables a factions AI. None of the faction's units will move without command.
+
=== giveUpgradeCommand ( unitId, upgrade ) ===
  
Parameters:<br />'''factionIndex''' - the number identifier of the faction
+
Instruct a unit to carry out a command of type 'upgrade'.
  
=== setPlayerAsWinner(int factionIndex) ===
+
Parameters:<br />'''unitId''' - the id of the unit to perform the upgrade.<br />'''upgrade '''- the type of upgrade to perform. (ie. "hell_gate")
  
=== endGame() ===
+
=== disableAi ( int faction ) ===
 +
Disables a factions AI. None of the faction's units will move without command.
  
== Queries ==
+
Parameters:<br />'''faction '''- the index of the faction [0-3, Player1=0]
These function return useful information that can be used in command functions.
 
  
=== Vec2i getStartLocation(int factionIndex) ===
+
=== setPlayerAsWinner ( faction ) ===
  
 +
Sets the player with index 'faction' as the winner, would typically be followed by endGame().
  
=== Vec2i getUnitPosition(int unitId) ===
+
Parameters:<br />'''faction '''- the index of the faction [0-3, Player1=0]
 +
=== endGame () ===
  
 +
End the scenario, usually would be called after setPlayerAsWinner() when victory conditions have been met.
 +
== Queries ==
 +
These function return useful information that can be used in command functions.
  
=== int getUnitFaction(int unitId) ===
+
=== Vec2i startLocation ( faction ) ===
 +
Returns the start location for a given faction.
  
 +
Parameters:<br />'''faction '''- the index of the faction [0-3, Player1=0]
  
=== int getResourceAmount(string resourceName, int factionIndex) ===
+
Example:
 +
createUnit ( "someunit", 0, {startLocation(0)[1] + 5, startLocation(0)[2]} )
 +
This would create a  unit 5 cells east of startLocation 0.
  
 +
=== Vec2i unitPosition ( unitId ) ===
  
=== string getLastCreatedUnitName() ===
+
Returns the current location of a given unit.
  
 +
Parameters:
  
=== int getLastCreatedUnitId() ===
+
'''unitId - '''the unitId of the unit whose position you wish to know.
  
 +
Example:
 +
if ( unitPosition(myUnit)[1] &gt; 47 and 75 &gt; unitPosition(myUnit)[1]
 +
 +
and  unitPostion(myUnit)[2] &gt; 95 ) then
 +
 +
  -- The unit's x co-ord is between 47 and 75, and its y cord is larger than 95.
 +
 +
  -- trigger some action here ?
 +
 +
end
  
=== string getLastDeadUnitName() ===
+
=== int unitFaction ( unitId )===
 +
Returns the faction '''index''' of the unit with unitId.
  
 +
=== int resourceAmount ( resource, faction ) ===
  
=== int getLastDeadUnitId() ===
+
Returns the amount of a given resource is possessed by a faction.
  
 +
=== string lastCreatedUnitName () ===
  
=== int getUnitCount(int factionIndex) ===
+
Returns the unit type of the last created unit.
 +
=== int lastCreatedUnit () ===
  
 +
Returns the unit ID of the last created unit.
 +
=== string lastDeadUnitName () ===
  
=== int getUnitCountOfType(int factionIndex, string typeName) ===
+
Returns the type of the last unit to die.
 +
=== int lastDeadUnit ()===
  
 +
Returns the ID of the last unit to die.
 +
=== int unitCount ( faction ) ===
  
 +
Returns the number of units a given faction has.
 +
=== int unitCountOfType ( faction, type ) ===
  
 +
Returns the number of units of a specific type a given faction has.
 
== Events ==
 
== Events ==
These are xml tags used to execute lua code on its specified event. Variables can be used across different events. (TODO: see if events can be nested)
+
These are xml tags used to execute lua code on its specified event. Variables can be used across different events. (TODO: see if events can be nested [Ed: This wont end well&nbsp;;) -silnarm])
  
 
&lt;startup&gt;<br />[insert code]
 
&lt;startup&gt;<br />[insert code]
 +
 
&lt;startup&gt;
 
&lt;startup&gt;
  
Line 123: Line 186:
  
 
&lt;resourceHarvested&gt;<br />[insert code] <br />&lt;/resourceHarvested&gt;
 
&lt;resourceHarvested&gt;<br />[insert code] <br />&lt;/resourceHarvested&gt;
== The available functions ==
 
'''As there is no list of the possible commands now, here a copy of some things from script_manager.h (from the glest sourcecode) which should contain/show all possible Glest lua-commands.'''
 
 
 
=== Message Box Functions ===
 
 
 
bool getMessageBoxEnabled() const {return !messageQueue.empty();}
 
 
GraphicMessageBox* getMessageBox() {return &messageBox;}
 
 
string getDisplayText() const {return displayText;}
 
 
bool getGameOver() const {return gameOver;}
 
 
const PlayerModifiers *getPlayerModifiers(int factionIndex) const {return &playerModifiers[factionIndex];}
 
 
 
 
 
=== Events ===
 
 
 
void onMessageBoxOk();
 
 
void onResourceHarvested();
 
 
void onUnitCreated(const Unit* unit);
 
 
void onUnitDied(const Unit* unit);
 
 
 
 
private:
 
 
 
 
string wrapString(const string &str, int wrapCount);
 
 
 
 
 
=== Wrappers, Commands ===
 
 
 
void showMessage(const string &text, const string &header);
 
 
void clearDisplayText();
 
 
void setDisplayText(const string &text);
 
 
void setCameraPosition(const Vec2i &pos);
 
 
void createUnit(const string &unitName, int factionIndex, Vec2i pos);
 
 
void giveResource(const string &resourceName, int factionIndex, int amount);
 
 
void givePositionCommand(int unitId, const string &producedName, const Vec2i &pos);
 
 
void giveProductionCommand(int unitId, const string &producedName);
 
 
void giveUpgradeCommand(int unitId, const string &upgradeName);
 
 
void disableAi(int factionIndex);
 
 
void setPlayerAsWinner(int factionIndex);
 
 
void endGame();
 
 
 
 
 
=== Wrappers, Queries ===
 
 
 
Vec2i getStartLocation(int factionIndex);
 
 
Vec2i getUnitPosition(int unitId);
 
 
int getUnitFaction(int unitId);
 
 
int getResourceAmount(const string &resourceName, int factionIndex);
 
 
const string &getLastCreatedUnitName();
 
 
int getLastCreatedUnitId();
 
 
const string &getLastDeadUnitName();
 
 
int getLastDeadUnitId();
 
 
int getUnitCount(int factionIndex);
 
 
int getUnitCountOfType(int factionIndex, const string &typeName);
 
 
 
 
 
=== Callbacks, Commands ===
 
 
 
static int showMessage(LuaHandle* luaHandle);
 
 
static int setDisplayText(LuaHandle* luaHandle);
 
 
static int clearDisplayText(LuaHandle* luaHandle);
 
 
static int setCameraPosition(LuaHandle* luaHandle);
 
 
static int createUnit(LuaHandle* luaHandle);
 
 
static int giveResource(LuaHandle* luaHandle);
 
 
static int givePositionCommand(LuaHandle* luaHandle);
 
 
static int giveProductionCommand(LuaHandle* luaHandle);
 
 
static int giveUpgradeCommand(LuaHandle* luaHandle);
 
 
static int disableAi(LuaHandle* luaHandle);
 
 
static int setPlayerAsWinner(LuaHandle* luaHandle);
 
 
static int endGame(LuaHandle* luaHandle);
 
 
 
 
 
=== Callbacks, Queries ===
 
 
 
static int getStartLocation(LuaHandle* luaHandle);
 
 
static int getUnitPosition(LuaHandle* luaHandle);
 
 
static int getUnitFaction(LuaHandle* luaHandle);
 
 
static int getResourceAmount(LuaHandle* luaHandle);
 
 
static int getLastCreatedUnitName(LuaHandle* luaHandle);
 
 
static int getLastCreatedUnitId(LuaHandle* luaHandle);
 
 
static int getLastDeadUnitName(LuaHandle* luaHandle);
 
 
static int getLastDeadUnitId(LuaHandle* luaHandle);
 
 
static int getUnitCount(LuaHandle* luaHandle);
 
 
static int getUnitCountOfType(LuaHandle* luaHandle);
 

Revision as of 02:00, 12 November 2009

In newer Glest versions (3.2.0 beta and newer) lua scripting gives opens a new possibility of scripted scenarios.

The game includes 2 tutorial scenarios and one scripted normal scenario(storming) now. These demo scenarios show a bit what's possible now. Have a look at them if you want to learn it.

Useful Links

Lua/XML Intermixture Problem

Due to XML's nature of using angle brackets for elements the parser will get confused and give an error if you try to use the left angle bracket in the scenario's XML file.

A solution is to either swap the logic:

ie. if you wanted,
a <= b
you would have to do,
b >= a

Or use an external lua file as mentioned in the next section.

Loading a Lua File

To run Lua code in an external file you use the dofile function and provide the file path from the executable.

Example:

dofile("gae_scenarios/Tutorials/basic_tutorial/startup.lua")

Language System

Each scenario is stored in its own folder. In this folder should be an xml file of the same name as the folder with xml as the extension. Glest also looks for a lng file (scenario_name_english.lng as default) to allow for translations of text.

Example

In advanced_tutorial.xml is :
showMessage('MagicBrief', 'GlestAdvancedTutorial')

In advanced_tutorial_english.lng is :
MagicBrief=You are in command of the Magic faction, which uses mages and summoned creatures to fight.

Coordinates

Coordinates are specified as an array of two elements, the 'x' coordinate in the first element, and the 'y' coordinate in the second.

The origin {0,0} is at the 'top left' (or north-west if you like) of the screen. A map's size is defined in 'Tiles', each of which is a block of 2x2 Cells. For technical reasons the last row & column of Tiles are not valid. So a 64 * 64 map is (64-1)*2 = 126 Cells wide and high. The co-ordinates you supply in LUA are Cell coordinates, not Tile coordinates, and are 'zero indexed' (the first one is 0, the last is NumCells - 1).

eg. A 128 x 128 Map has 254 x 254 Cells. The northwest corner is {0,0} and the southeast corner is {253,253}.

When a function returns a 'Vec2i' you can access the individual co-ordinates by sub-scripting the array,

myPos = someFunction () 
x = myPos[1]
y = myPos[2]

When ever there is a parameter requiring positions of type Vec2i you can use the format {x,y} (where x and y are number values within the required range, as defined above) to select a position on the map.

someFunction ( {x,y} )

Here 'x' and 'y' could be numbers, variables, or 'expressions'.

You can also pass a 'pre created' array to these functions, which may be useful for scripting advanced scenarios.

Faction Index and Players

You need to specify the players like:

<players>
	<player control="human" faction="tech" team="1"/>
	<player control="cpu" faction="magic" team="2"/>
	<player control="closed"/>
	<player control="closed"/>		
</players>

The first player's factionIndex is 0. The second player's factionIndex is 1 and so on. There must be exactly 4 player tags.

Commands

WARNING: All of these functions return type void and should not be used as arguments for other functions.

showMessage ( text, header )

Displays a message box on the screen, that will have to be dismissed by the player.

Parameters:
text - a string identifying the text from a language file
header - a string identifying the title bar text from a language file

setDisplayText ( text )

Displays a message at the top of the 'playing area'. Will remain until dismissed with clearDisplayText() or setDisplayText() is called again.

Parameters:
text - a string identifying the text from a language file

clearDisplayText ()

Clears the message from the top of the playing area, previously set with setDisplayText().

setCameraPosition ( pos )

Move the camera to the coordinates of pos.

Parameters:
pos - an array of two elements, specifying the co-ordinates {x,y}

createUnit ( unit, faction, pos )

Spawns a unit. If pos is occupied a nearby cell will be chosen. The game attempts to keep a 2 cell 'border' between the new unit and other units or objects (ie. trees). Warning: If a position can not be found, the game crashes.

Parameters:
unit - name of a unit in the loaded factions.
faction - the index of the faction this unit will belong to.
pos - an array of two elements, specifying the co-ordinates {x,y}

giveResource ( resource, faction, amount )

Give an amount of a specified resource to a player, negative values are valid and have the obvious effect.
Parameters:
resource - a corresponding resource in the tech tree
faction - the index of the faction to give the resource
amount - the amount of resource the faction will receive

givePositionCommand ( unitId, command, pos )

Instruct a unit to carry out a command of type 'attack' or 'move'.

Parameters:
unitId - the id of a unit that has an attack and/or move command.
command - the type of command to carry out ('attack' or 'move')
pos - an array of two elements, specifying the co-ordinates {x,y}

giveProductionCommand ( unitId, produced )

Instruct a unit to carry out a command of type 'produce'.

Parameters:
unitId - the id of a unit that is to produce the new unit.
produced - the type of unit to create. (ie. "worker")

giveUpgradeCommand ( unitId, upgrade )

Instruct a unit to carry out a command of type 'upgrade'.

Parameters:
unitId - the id of the unit to perform the upgrade.
upgrade - the type of upgrade to perform. (ie. "hell_gate")

disableAi ( int faction )

Disables a factions AI. None of the faction's units will move without command.

Parameters:
faction - the index of the faction [0-3, Player1=0]

setPlayerAsWinner ( faction )

Sets the player with index 'faction' as the winner, would typically be followed by endGame().

Parameters:
faction - the index of the faction [0-3, Player1=0]

endGame ()

End the scenario, usually would be called after setPlayerAsWinner() when victory conditions have been met.

Queries

These function return useful information that can be used in command functions.

Vec2i startLocation ( faction )

Returns the start location for a given faction.

Parameters:
faction - the index of the faction [0-3, Player1=0]

Example:

createUnit ( "someunit", 0, {startLocation(0)[1] + 5, startLocation(0)[2]} )

This would create a unit 5 cells east of startLocation 0.

Vec2i unitPosition ( unitId )

Returns the current location of a given unit.

Parameters:

unitId - the unitId of the unit whose position you wish to know.

Example:

if ( unitPosition(myUnit)[1] > 47 and 75 > unitPosition(myUnit)[1]

and  unitPostion(myUnit)[2] > 95 ) then

  -- The unit's x co-ord is between 47 and 75, and its y cord is larger than 95.

  -- trigger some action here ?

end

int unitFaction ( unitId )

Returns the faction index of the unit with unitId.

int resourceAmount ( resource, faction )

Returns the amount of a given resource is possessed by a faction.

string lastCreatedUnitName ()

Returns the unit type of the last created unit.

int lastCreatedUnit ()

Returns the unit ID of the last created unit.

string lastDeadUnitName ()

Returns the type of the last unit to die.

int lastDeadUnit ()

Returns the ID of the last unit to die.

int unitCount ( faction )

Returns the number of units a given faction has.

int unitCountOfType ( faction, type )

Returns the number of units of a specific type a given faction has.

Events

These are xml tags used to execute lua code on its specified event. Variables can be used across different events. (TODO: see if events can be nested [Ed: This wont end well ;) -silnarm])

<startup>
[insert code]

<startup>

<unitCreatedOfType type="unitname">
[insert code]
</unitCreatedOfType>

<unitDied>
[insert code]
</unitDied>

<resourceHarvested>
[insert code]
</resourceHarvested>