A link with patch notes: https://www.ageofempires.com/news/aoe2de-update-42848/
So we have 2 options to create functions that we can call. In-game using the Script Call effect and outside of the game in an .xs file that is imported to the scenario.
Let's start with in-game scripting. This is very limited due to the in game message box being small and does not support some common commands such as CTRL+Z.
1. Create a trigger that defines a function using the new Script Call effect. This trigger creates the function xsTest2, and when called it will send a chat saying "test2". The trigger has its starting state set to OFF so it will not fire, but the script will still be visible to the other triggers.
2. Add a new trigger with starting state ON with a Script Call effect that calls the defined function. This will call the function from the first trigger. Even though the first trigger never "fires", the script in the message box is saved for other scripts to call.
3. Test it! As soon as the scenario starts you should see the chat saying test2!
Triggers with Script Call effects will fire when the trigger conditions are met. If your trigger has starting state ON and no conditions the Script Call effect will call the function immediately, which is why my examples has the function in a trigger with starting state OFF.
Now that we know how to define and use functions defined in game, let's look at external functions. These are stored in a script file in your game directory, \resources\_common\xs\.
1. In the xs folder, create a new text document and open it with notepad. Write this function in there: It should look like this.
2. Go to the scenario editor in game and open your scenario. In the "Map" tab, there is a new box where you write your script filename.
3. Create a new trigger with starting state ON. Add a Script Call effect and write the function from your script file in there. (After I took this screenshot I noticed it's not required to have the paranthesis "()" after the function name)
4. When you test your scenario, it should now send a chat with the text "test" as soon as the game starts.
You can still create functions in game, even if you use an external script.Here I have created a trigger with starting state OFF with a Script Call effect that defines the function xsTest2 that sets Player 1's food to 100. The scenario still has the xsTest.xs file in the "Map" tab, meaning the function defined in there can also be called. A new trigger effect with Script Call is created which calls for the xsTest function from the external script and another Script Call effect is added that calls for the xsTest2 function defined in the first trigger. When I test the scenario now, Player 1 should have 100 food and a chat is sent that says "test", and that is exactly what happens!
I have not figured out how to call several functions from the same Script Call without creating a new function which in turn calls several functions yet. A workaround is to create a new effect for each function, but it will probably get annoying to keep track of which effect calls which function. I hope this is
The arguments are not very clear for me yet. The first argument for xsChatData is the string to be displayed, which can use variables that seems to be defined by the second argument. An example of this is a function to show Player 1's exact food count:
I have not figured out how to use input arguments for custom functions yet. For example, this function does not parse:
The functions available so far and what they do:
xsTriggerVariable(int var)
Returns the value of variable "var". xsTriggerVariable(5) would return the value of variable 5. The return value is an integer and can be used by other functions. Not sure how this works with variables with custom names, but I assume they just go by variable ID.
xsSetTriggerVariable(int var, int val)
Sets a trigger variable "var" to value "val". xsSetTriggerVariable(5,100) would set variable 5 to value 100.
xsPlayerAttribute(int p, int res)
Returns an attribute "res" of player "p". xsPlayerAttribute(5,0) would return the amount of food player 5 has. The returned value is an integer and can be used by other functions.
xsSetPlayerAttribute(int p, int res, int val)
Sets player "p"s attribute "res" to value "val". xsSetPlayerAttribute(2,0,100) would set player 2's food supply to 100.
xsChatData(string s, int var)
Sends a chat message "s" (not sure to what player it sends the message, possibly to all players) with value "var" as a variable input for the message. xsChatData("Hello!", 0) simply sends a chat message with "Hello!", while xsChatData("Player 2's food count is %d", xsPlayerAttribute(2,0)) would send a chat message with Player 2's exact food supply.
Someone on aoe3 forum has made a nice guide for xs-scripting:https://eso-community.net/viewtopic.php?p=436182
Although the functions are not the same for aoe2, the principle is the same!
CheeseOnToast on the AokH discord said that documentation is "to-do", so let's hope that comes out pretty soon!
I won't go into detail about what the potential of this implementation has for scenario design, but instead I'll give a quick guide to get started with xs-scripting.Scenario Editor
A new.xs scripting functionality has been added to the scenario editor!
Players can now add an .xs script to their scenario, which can communicate with triggers and other areas of the game to allow for a more complex flow-control than that offered by regular triggers.
All available constants for the new .xs scripting can be found in Constants.xs in \resources_common\xs
Here are a few examples of the functions which can be called:xsTriggerVariable: Returns the value of the desired Trigger Variable. xsSetTriggerVariable: Sets a trigger variable to the desired value. xsPlayerAttribute: Returns the value of the desired player attribute. xsSetPlayerAttribute: Sets the desired player attribute to the value specified. xsChatData: Sends a chat with the desired message/variable. This is useful for testing.
So we have 2 options to create functions that we can call. In-game using the Script Call effect and outside of the game in an .xs file that is imported to the scenario.
Let's start with in-game scripting. This is very limited due to the in game message box being small and does not support some common commands such as CTRL+Z.
Triggers with Script Call effects will fire when the trigger conditions are met. If your trigger has starting state ON and no conditions the Script Call effect will call the function immediately, which is why my examples has the function in a trigger with starting state OFF.
Now that we know how to define and use functions defined in game, let's look at external functions. These are stored in a script file in your game directory, \resources\_common\xs\.
and save as xsTest.xs.
void xsTest()
{
xsChatData("test", 0);
}
You can still create functions in game, even if you use an external script.
I have not figured out how to call several functions from the same Script Call without creating a new function which in turn calls several functions yet. A workaround is to create a new effect for each function, but it will probably get annoying to keep track of which effect calls which function. I hope this is
The arguments are not very clear for me yet. The first argument for xsChatData is the string to be displayed, which can use variables that seems to be defined by the second argument. An example of this is a function to show Player 1's exact food count:
void chatPlayer1Food()
{
xsChatData("Player 1's food supply: %d", xsPlayerAttribute(1,0));
}
I have not figured out how to use input arguments for custom functions yet. For example, this function does not parse:
void chatPlayerFood(int p) {
xsChatData("Player food: %d",xsPlayerAttribute(p,0));
}
The functions available so far and what they do:
Returns the value of variable "var". xsTriggerVariable(5) would return the value of variable 5. The return value is an integer and can be used by other functions. Not sure how this works with variables with custom names, but I assume they just go by variable ID.
Sets a trigger variable "var" to value "val". xsSetTriggerVariable(5,100) would set variable 5 to value 100.
Returns an attribute "res" of player "p". xsPlayerAttribute(5,0) would return the amount of food player 5 has. The returned value is an integer and can be used by other functions.
Sets player "p"s attribute "res" to value "val". xsSetPlayerAttribute(2,0,100) would set player 2's food supply to 100.
Sends a chat message "s" (not sure to what player it sends the message, possibly to all players) with value "var" as a variable input for the message. xsChatData("Hello!", 0) simply sends a chat message with "Hello!", while xsChatData("Player 2's food count is %d", xsPlayerAttribute(2,0)) would send a chat message with Player 2's exact food supply.
Someone on aoe3 forum has made a nice guide for xs-scripting:
Although the functions are not the same for aoe2, the principle is the same!
CheeseOnToast on the AokH discord said that documentation is "to-do", so let's hope that comes out pretty soon!
[This message has been edited by Basse (edited 11-22-2020 @ 02:00 PM).]