Problem with dynamic fields on simobject
by Jaimi McEntire · in Torque Game Engine Advanced · 09/06/2008 (7:59 pm) · 3 replies
I've written a save file system using the XML class in script. I create a simobject, assign some values on it, and pass that to a function to dump the dynamic fields to the XML. This works great, except in one case - if I add the value of $Sim::Time to SaveFileInfo.GameTime, then I can no longer retrieve the GameTime field - iterating through the dynamic fields no longer finds GameTime - but it does find a field named "CrossbowReloadSound" (obviously not from this object...)
Has anyone seen this kind of behavior before? It's like the dynamic fields have gotten corrupted. I am able to evaluate SaveFileInfo.GameTime + $Sim::Time in the debugger without a problem, and it gives the correct values.
*edit - it's getDynamicField that is returning the wrong field name (see function code below). Typing echo(SaveFileInfo.GameTime); returns the correct value for the GameTime field.
%fldname = %object.getDynamicField(%i);
The XML with the bad field:
If I don't assign it, then I still get GameTime...
The correct XML is output if I do not reassign GameTime.
Function that writes out a simobject to an already open XML doc:
Has anyone seen this kind of behavior before? It's like the dynamic fields have gotten corrupted. I am able to evaluate SaveFileInfo.GameTime + $Sim::Time in the debugger without a problem, and it gives the correct values.
*edit - it's getDynamicField that is returning the wrong field name (see function code below). Typing echo(SaveFileInfo.GameTime); returns the correct value for the GameTime field.
%fldname = %object.getDynamicField(%i);
new SimObject(SaveFileInfo)
{
GameTime = 0;
};
function UpdateSaveFileInfo(%Comment,%Screenshot)
{
SaveFileInfo.Location = MissionInfo.name;
SaveFileInfo.Comment = %Comment;
SaveFileInfo.Screenshot = %Screenshot;
SaveFileInfo.GameTime = SaveFileInfo.GameTime + $Sim::Time;
SaveFileInfo.MissionFile = $Server::MissionFile;
SaveFileInfo.Game = $Server::GameType;
SaveFileInfo.Type = $Server::MissionType;
SaveFileInfo.Player = $pref::Player::Name;
SaveFileInfo.ServerType = $Server::ServerType;
}The XML with the bad field:
- <SaveFileInfo> <ServerType>SinglePlayer</ServerType> <Location>Sorcerors Isle</Location> <Comment>comment</Comment> <screenShot>scriptsAndAssets/Screenshots/Save1.jpg</screenShot> <MissionFile>scriptsAndAssets/data/missions/wm_SorcerorsIsle.mis</MissionFile> <type>RPG</type> <Game>Trail of stars</Game> <Player>Otto Jax</Player> <CrossbowReloadSound /> </SaveFileInfo>
If I don't assign it, then I still get GameTime...
new SimObject(SaveFileInfo)
{
GameTime = 0;
};
function UpdateSaveFileInfo(%Comment,%Screenshot)
{
SaveFileInfo.Location = MissionInfo.name;
SaveFileInfo.Comment = %Comment;
SaveFileInfo.Screenshot = %Screenshot;
SaveFileInfo.GameTime = 0; // able to get the field if I don't add $Sim::Time
SaveFileInfo.MissionFile = $Server::MissionFile;
SaveFileInfo.Game = $Server::GameType;
SaveFileInfo.Type = $Server::MissionType;
SaveFileInfo.Player = $pref::Player::Name;
SaveFileInfo.ServerType = $Server::ServerType;
}The correct XML is output if I do not reassign GameTime.
- <SaveFileInfo> <MissionFile>scriptsAndAssets/data/missions/wm_SorcerorsIsle.mis</MissionFile> <type>RPG</type> <Game>Trail of stars</Game> <GameTime>0</GameTime> <Player>Otto Jax</Player> <ServerType>SinglePlayer</ServerType> <Location>Sorcerors Isle</Location> <Comment>comment</Comment> <screenShot>scriptsAndAssets/Screenshots/Save1.jpg</screenShot> </SaveFileInfo>
Function that writes out a simobject to an already open XML doc:
function WriteSimObject(%Xml, %object)
{
%ClassName = %object.getName();
%Xml.writeClassBegin(%ClassName);
// write dynamic fields
%fldcnt = %object.getDynamicFieldCount();
for (%i=0;%i<%fldcnt;%i++)
{
%fldname = %object.getDynamicField(%i);
%fldvalue = %object.getFieldValue(%fldname);
if (isObject(%fldvalue))
{
WriteSimObject(%Xml,%fldvalue);
}
else
{
%Xml.writeField(%fldname,%fldvalue);
}
}
%Xml.writeClassEnd();
}
#2
09/06/2008 (9:56 pm)
Strangely enough, the problem only manifests itself if I use $Sim::Time. I've changed the code to use getSimTime() instead, and now everything works. (except Sim::Time is in seconds, and getSimTime is in milliseconds, but I can adjust for that...)
#3
09/06/2008 (10:03 pm)
It is probably best to use a ScriptObject rather than using a SimObject. It might have something to do with it.
Associate Jaimi McEntire
King of Flapjacks
The C++ getDynamicField ConsoleMethod is finding the correct value:
char* buffer = Con::getReturnBuffer(256); if (*itr) { SimFieldDictionary::Entry* entry = *itr; dSprintf(buffer, 256, "%s", entry->slotName); return buffer; }At this point, the buffer contains "GameTime" like expected. But this is never actually returned to the script correctly. At this point, it appears like Stack Corruption, but I'm not sure how to proceed. The WriteSimObject function is recursive, but this is a top level object - it hasn't recursed...