Edit script files and functions during run-time
by Phillip O'Shea · 08/20/2008 (6:22 am) · 6 comments
Open up your "console/consoleFunctions.cc" file and locate the console function "exec". You'll need to add a callback for this function to notify us of a newly executed script file.
Next, open up your "console/fileSystemFunctions.cpp" file and paste this new function in there somewhere (I put mine after the "fileSize" function).
Finally, you need to add this package to your project. I placed mine in the root "main.cs" file (the first file to be called when the project is executed).
Bind the function to a key for ease of use.
That is it!
When you load your game, it will store all of the files that you execute and the last time they were modified. If you then call the function "updateScripts()" during the game, it will re-execute any files that have been modified.
This little idea was inspired by the Plastic Tweaker resource from Plastic Games. I strongly recommend that you check it out!
ConsoleFunction(exec, ... )
{
...
// ScriptUpdate Resource {
if (ret)
Con::executef(2, "onExec", scriptFileName);
// }
delete [] script;
execDepth--;
return ret;
}Next, open up your "console/fileSystemFunctions.cpp" file and paste this new function in there somewhere (I put mine after the "fileSize" function).
ConsoleFunction(fileTime, S32, 2, 2, "(fileName)\n"
"@param fileName The name of the file to check.\n"
"@return Returns the time of the last modification")
{
argc;
// Grab the full file address
Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
// Return the time
FileTime pModifyTime;
if (Platform::getFileTimes(scriptFilenameBuffer, NULL, &pModifyTime))
return (S32)pModifyTime.v1;
return 0;
}Finally, you need to add this package to your project. I placed mine in the root "main.cs" file (the first file to be called when the project is executed).
package ScriptUpdate
{
function onExec(%fileName)
{
for (%i = 0; %i < $ScriptUpdate::Count; %i++)
{
if (getField($ScriptUpdate::Info[%i], 0) $= %fileName)
{
$ScriptUpdate::Info[%i] = trim(%fileName TAB fileTime(%fileName));
return;
}
}
$ScriptUpdate::Info[$ScriptUpdate::Count] = trim(%fileName TAB fileTime(%fileName));
$ScriptUpdate::Count += 1;
}
function updateScripts(%val)
{
if (%val)
{
echo ("Updating Scripts...");
for (%i = 0; %i < $ScriptUpdate::Count; %i++)
{
%fileName = getField($ScriptUpdate::Info[%i], 0);
%fileTime = getField($ScriptUpdate::Info[%i], 1);
if (fileTime(%fileName) != %fileTime)
exec (%fileName);
}
}
}
};
//
activatePackage( ScriptUpdate );Bind the function to a key for ease of use.
moveMap.bind( "keyboard", "ctrl l", "updateScripts" );
That is it!
When you load your game, it will store all of the files that you execute and the last time they were modified. If you then call the function "updateScripts()" during the game, it will re-execute any files that have been modified.
This little idea was inspired by the Plastic Tweaker resource from Plastic Games. I strongly recommend that you check it out!
About the author
Head of Violent Tulip, a small independent software development company working in Wollongong, Australia. Go to http://www.violent-tulip.com/ to see our latest offerings.
#2
I am very curious about the Plastic Tweaker, but I'll only check it out once it's out of beta and selling. Until then, this resource will be a great aid. Thank you!
08/20/2008 (9:18 am)
Philip, this is a very neat inspiration! This resource would have fit perfectly all the other gems PG posted. I am very curious about the Plastic Tweaker, but I'll only check it out once it's out of beta and selling. Until then, this resource will be a great aid. Thank you!
#3
08/20/2008 (2:02 pm)
Sounds very cool, one thing though: Shouldn't updateScripts() be updateScripts(%val)?
#4
08/20/2008 (2:04 pm)
Thanks Nathan!
#5
08/20/2008 (2:35 pm)
Brilliant! Thanks a ton.
#6
1. First, all file changes were made in consoleFunctions.cc, there was no console/fileSystemFunctions.cpp for me?
2. The pModifyTime is only a struct for win32 it appears, so using the v1 field for that was an issue, I wrapped the return in an ifdef for that
3. The fileTime comparison wasn't working for me until I used !$= instead of != . Not sure if that's due to how Linux returns the values.
4. I had to actually make sure there was a fileName, or we end up trying to execute a nonexistent file
That was it, everything is working great now, will build a Windows build tomorrow to see if it messed anything.
08/21/2008 (1:57 am)
Thank you, a very helpful resource. I had a few issues I'm not sure are common and I've yet to test them on windows, but to get this working in Linux TGE 1.5.2 I had to make a couple changes:1. First, all file changes were made in consoleFunctions.cc, there was no console/fileSystemFunctions.cpp for me?
2. The pModifyTime is only a struct for win32 it appears, so using the v1 field for that was an issue, I wrapped the return in an ifdef for that
ConsoleFunction(fileTime, S32, 2, 2, "(fileName)\n"
"@param fileName The name of the file to check.\n"
"@return Returns the time of the last modification")
{
argc;
// Grab the full file address
Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), argv[1]);
// Return the time
FileTime pModifyTime;
if (Platform::getFileTimes(scriptFilenameBuffer, NULL, &pModifyTime))
{
#ifdef TORQUE_OS_WIN32
return (S32)pModifyTime.v1;
#else
return (S32)pModifyTime;
#endif
}
return 0;
}3. The fileTime comparison wasn't working for me until I used !$= instead of != . Not sure if that's due to how Linux returns the values.
4. I had to actually make sure there was a fileName, or we end up trying to execute a nonexistent file
if (%fileName !$= "")
{
if (fileTime(%fileName) !$= %fileTime)
{
exec (%fileName);
}
}That was it, everything is working great now, will build a Windows build tomorrow to see if it messed anything.

Sailendu Behera