As you develop your Crafted Map or Game Mode mod, it is recommended that you test it in-game frequently and debug your script to resolve any errors.
This is particularly important before publishing your mod for other players to experience! A number of tools designed to help you locate bugs in your scripted mod are outlined below.
The Script Debugging Tool
The Age of Empires IV Content Editor includes a script debugging tool that allows you to connect the Content Editor to the game client and surface information that will help you debug and develop your script.
This section covers the basic workflows involving the debugging tool.
Preparing the Content Editor for Debugging
To prepare the Content Editor for debugging, perform the following steps:
- The debugging tool relies on a series of functions available via the Script drop-down in the Content Editor toolbar.
- Open the Locals pane by selecting Script > Debugging > Locals. This window will display local variables when a breakpoint is reached in your script.
- Open the Globals pane by selecting Script > Debugging > Globals. This window will display global variables when a breakpoint is reached in your script.
- Select Tools > Customize Toolbars...
- Check ScriptEditor.Debugging and close the window. This will add a number of useful shortcut buttons below the Content Editor toolbar and will save you time during debugging.
Connecting the Content Editor to the Game
To connect the content editor to the Age of Empires IV game client, perform the following steps:
- When you are ready to debug your script, right-click on Age of Empires IV in Steam and select Properties...
- In the Launch Options field, enter -dev.
When you launch Age of Empires IV with this argument you will not be able to play with anyone who did not also launch with -dev.
However, it will enable a number of features that are useful for debugging like the ability to connect to the Content Editor and developer game cheats.
- Launch Age of Empires IV from Steam.
- In the Age of Empires IV Content Editor, select the Attach button. This will connect the Content Editor to the game client for debugging.
- With your script open, navigate to the line of your code that you would like to debug and click in the column to the left of line number. This will create a breakpoint.
- Start a Skirmish or Custom match with your mod selected.
- When the game is about to run this line of code and is attached to the editor, it will pause the simulation at the breakpoint and populate the Global and Local panes. This is useful for identifying the variables you have access and validating that they are behaving as you would expect.
After you encounter a breakpoint, you can control how you step through the script using the following debugging functions.
These functions are detailed below:
The Run button unfreezes the game and lets it run normally again.
This function will not go back into the debugger until the game hits another breakpoint (or, the same breakpoint again).
Step Into / Step Out
The Step Into and Step Out commands follow the execution after the breakpoint and moves onto the next line that will be executed in that function.
If any lines call other SCAR functions, you may wish to step into those functions instead, following the path inside those functions in a step by step fashion as well. This is what the Step Into button does.
The Step Out button does the opposite, and is usually used when you have stepped into a function. It completes the execution of that inner function, and freezes the game again once the function has returned and you are back in the original function.
This runs one line of code, indicated by a yellow arrow.
The arrow will then move down to the next line of code it’s going to run, following your script’s structure, and stop there. You can then step over again to run that line. This way, you can step through your script one line at a time. You’ll be able to see the path it takes along the way, doing things like skipping blocks inside if statements, or returning back to the top of a loop.
When you are finished debugging, you can detach the debugger and the game will carry on normally while ignoring any future breakpoints in might hit.
Those breakpoints only freeze the game when the debugger is attached.
After launching the Age of Empires IV game client with the -dev argument, the scar console can be opened while in a match and serves two primary functions:
- The console displays a log scar print statements and scar errors. If you encounter a scar error in your script, this is the first place you should look to identify what line of code it occurred on.
- The console is a direct input into the Lua instance that runs your scripts. This means that you can type a function directly into the console and it will run immediately (e.g. typing Mod_FindTownCenter() and pressing enter will run the Mod_FindTownCenter() function while playing the Template with Examples game mode mod.
To open the console while in a match, press Alt + Shift + ~.
All of the information that is written to the SCAR console is also written out to a log file.
You can find these log files in your My Documents\My Games\[Project]\Logfiles\ directory.
Each time you run the game, a new folder is create in the Logfiles directory (and this new folder will have the time you launched the game, so you can find the right one). Inside are all of the log files generated in the game session, and the one you’re interested in is the scarlog.txt file.
Fatal Scar Errors
When something goes wrong and the game tried to execute some script that it just can't execute, you will get a Fatal SCAR Error. The game will freeze, and the error will be shown in your SCAR console.
As the error is in the SCAR console, it is also written to the scarlog.txt file in your Logfiles directory.
If someone who plays your mod encounters an error, they can send you that log file.
Anatomy of a SCAR Error
When a Fatal SCAR Error occurs, you’ll see some information about the error in your SCAR console and in your scarlog.
By following the stacktrace, you can see the path of execution your script took before it encountered the error.
Your script might be that topmost line of the stacktrace. It might also be that the crash occurred in some of the SCAR libraries. This is normal - after all, often when you call a function it will call other functions, which can then call other functions, and so on. If an FSE occurs inside a library, it could be:
a) a bug in the library, or
b) you called a function with some invalid parameters, but it wasn’t until deep inside that function that those parameters caused an error.
The latter is more common when you’re developing a script, so it’s worth looking down the stacktrace and finding the last point at which it was executing your script, and making sure that makes sense.
Continuing from a SCAR Error
You can try to continue the game by pressing the Pause key on your keyboard to unpause and continue. Sometimes this will let you continue, and sometimes it won't.
If the error was in a rule, then it might be executed again right after.
You can try fixing the rule in the script, reburning the file, and hot-reloading the script.
There are a few common errors you may encounter while debugging. These errors are detailed below.
- Tried to call global ???? (a nil value)
This means you tried to call a function that doesn’t exist. Usually this is because you spelled the function wrong. Alternatively, you might not be importing the file with the function definition - either you forgot to import the main project scar file, or you forgot to import another one of your files if your mission script spans several files.
- Invalid parameter ??? (type expected = ???, received = ???)
You will only get this error on a call to a C++ function,, but this means that the function received a parameter that was the wrong variable type. It will tell you which parameter was incorrect (the first "???") as well as what variable type that parameter should have been, and what it actually was (the second and third "???").
- Invalid SGroup* in ParmTraits<>:Pop
This slightly cryptic error message means that you tried to pass a function something like a SGroupID/EGroupID which is no longer valid. i.e. you destroyed the group, which might very well be because you used SGroup_Destroy(sg_myGroup) instead of SGroup_DestroyAllSquads(sg_myGroup)