Game Development Community

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);

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();
}

#1
09/06/2008 (8:30 pm)
Update:

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...
#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.