Game Development Community

Creating an in-game Journal using GuiMessageVectorCtrl

by Nick Zafiris · in Torque Game Engine · 01/05/2005 (4:40 am) · 25 replies

I'm trying to have all game messages and conversations get pushed into a Journal like in many RPGs.

My .gui file hierarchy is set-up like this:
GuiControl(journalDlg)
GuiWindowCntrl(journalWindow)
GuiScrollCtrl(journalScroll)
GuiMessageVectorCtrl(journal)

So far I've managed to get messages display on the GuiMessageVectorCtrl by attaching a messageVector and pushing lines i.e. pushBackLine("Journal Message", 0).

Problems I've encountered so far:

1. If you do a popDialog(journalDlg) and then a pushDialog(journalDlg) all text gets lost. Is there a way to have the text persist or at least dump it somewhere and re-insert it again when the gui is pushed?

2. It seems that the way the messageVector is designed, you can only use pushBackLine when the gui has been pushed. Anyone know of a way to override that? I guess you can set all controls to setVisible(false) but that gets messy and then you would also have to mess with the noCursor variable.

Any help would be appreciated. Also, anyone think I shouldn't use GuiMessageVectorCtrl for this but use GuiMLTextCtrl or something else instead?

Thanks,

Nick
Page «Previous 1 2
#1
01/05/2005 (5:32 am)
Haven't tried this myself, so just speculating (a very usefull feature though, one that I plan on implementing)... probably would just do an onSleep function that dumps the text to a file, then onWake that loads it, maybe want to parse the information for special formats for menus, subsections etc , course thats later...

not sure if vector is what you want to use, looking at this stuff now (I would like to do the same)


EDIT: going through source I find
Quote: /// Derived classes must keep this set of variables consistent if they
/// use this classes onRender. Note that this has the fairly large
/// disadvantage of requiring lots of ugly, tiny mem allocs. A rewrite
/// to a more memory friendly version might be a good idea...
So I might wonder if continually using such might cause memory issues in the long run, or slowdown ? maybe these "ugly, tiny mem allocs." happen for 'each' vector ctrl and not each time one is refreshed, etc
#2
01/05/2005 (5:45 am)
Found this in searching the forums

%filename = "userdata/user" @ %client.guid;
export('', %filename, False); //This is how I create and clean
new MessageVector(TempVector);
TempVector.dump(%filename);
TempVector.delete(); //Files so they can be written to fresh.
not sure if it helps, but interesting usage

from the source

ConsoleMethod( MessageVector, dump, void, 3, 4, "(string filename, string header=NULL)"
              "Dump the message vector to a file, optionally prefixing a header.")
#3
01/05/2005 (7:11 am)
Guess you could have something like

journal.txt

(or whatever you name it and whatever extension)...

then the onwake function of the gui could loop through and push it all to the messageVector to display...

then instead of pushing lines to it when a player talks with npcs, it could add these lines to journal.txt

not sure if this is the most efficient way though
#4
01/07/2005 (12:39 am)
Thanks Matthew for your helpful replies. I have already tried TempVector.dump(file.txt); but I can't seem to find the actual file on my hard drive afterwards. Don't know why. I do get the message "Dumping message vector TempVector to file.txt" on the console but file.txt does not exist.
I've also tried it this way TempVector.dump(file.txt, " ");

The onSleep and onWake seem like a good idea. Didn't think of that. It's actually isAwake though i think.

Nick
#5
01/07/2005 (8:54 am)
OnWake runs when the gui is pushed... isAwake checks if it pushed I beleive... know tetsGui::onWake(); works though, don't have much experience with isAwake...

running some tests to see if this will work
#6
01/07/2005 (10:07 am)
Filename should have at least one "/" in it

so TempVector.dump("./file.txt");

should work

though you can write to the root folder, you can't read from it in script


so do something along these lines

modpath/folder/filename

"starter.fps/data/journal/journal.txt"
#7
01/07/2005 (11:23 am)
Ok set up a basic way to do this... not sure if this is the best, but works


function JournalDemo::onWake()
{

	%c = new MessageVector(journalText){};
	gmvText.attach(journalText);

	JournalDemo.readJournal("starter.fps/data/journal/journal.txt");

}

function JournalDemo::dumpFile(%this, %filename)
{

	echo("attempting to dump file from" SPC %this SPC "to" SPC %filename);//for debug
	journalText.dump(%filename);
	
}

function JournalDemo::readJournal(%this, %filename) { 

	%file = new FileObject(); 
	
	echo("attempting to open file for reading:" SPC %filename);	//for debug

	if(%file.openForRead(%filename)) 
	{ 
		echo("file opened for reading");
		while(!%file.isEOF()) 
		{ 
			%input = %file.readLine(); 
			echo(%input); //for debug
			journalText.pushFrontLine(%input,0);
		}
 	} else
	{
		echo("file NOT opened for reading");//for debug
	}
	
	%file.close();
 	%file.delete(); 
} 

function JournalDemo::writeToJournal(%this, %textToWrite)
{

	%file = new FileObject(); 

	%lineCount = 0;

	if(%file.openForRead("starter.fps/data/journal/journal.txt")) 
	{ 
		echo("scanning file to find end");//for debug
		while(!%file.isEOF()) 
		{ 
			%journalContents[%lineCount] = %file.readLine();
			%lineCount++;
			echo(%lineCount);//for debug
		}
 	} else
	{
		echo("file scan failed"); //for debug
	}
	
	%file.close();

	if(%file.openForWrite("starter.fps/data/journal/journal.txt"))
	{
		echo("file opened for writing"); //for debug
	} else
	{
		echo("file did not open for writing");//for debug
	}
	
	for(%i=0;%i<%lineCount;%i++)
	{

		%file.writeLine(%journalContents[%i]);

	}

	%file.writeLine(%textToWrite);

      %file.close(); 
      %file.delete();


}


you use this
function JournalDemo::writeToJournal(%this, %textToWrite)
write to the journal ... say

JournalDemo.writeToJournal("Sir Hughes told me to go to the pub and collect some ale for him and his friends");

basically I set up a manual append for file writing... it loops through, counts the lines of the file and loads them in an array, then it opens it for writing and writes your new line to the end
#8
01/07/2005 (11:24 am)
Note:

I'm using the following gui

if you use this be sure to change the background image, or the main control
//--- OBJECT WRITE BEGIN ---
new GuiChunkedBitmapCtrl(JournalDemo) {
   profile = "GuiDefaultProfile";
   bitmap = "./journalBack.JPG";
   tile = "1";

   new GuiScrollCtrl(JournalWindow) {
     profile = "ChatScrollProfile";
     horizSizing = "right";
     vertSizing = "bottom";
     position = "26 32";
     extent = "324 300";
     minExtent = "8 2";
     visible = "1";
     willFirstRespond = "1";
     hScrollBar = "alwaysOff";
     vScrollBar = "alwaysOff";
     constantThumbHeight = "0";
     childMargin = "0 0";

     new GuiMessageVectorCtrl(gmvText) {
       profile = "ChatMessageProfile";
       horizSizing = "right";
       vertSizing = "bottom";
       position = "2 2";
       extent = "320 300";
       minExtent = "8 8";
       visible = "1";
       setFirstResponder = "0";
       lineSpacing = "0";
       lineContinuedIndex = "10";
       matchColor = "0 0 255 255";
       maxColorIndex = 9;
    };
  };
};

//--- OBJECT WRITE END ---
#9
01/07/2005 (11:27 am)
The best way to do a complete journal system would be to parse it... and add correct tags... at least this seems like it would be the way to me. I might do that later and submit it as a resource.
#10
01/10/2005 (1:53 am)
Tried your code and works flawlessly!
I see you don't need an onSleep function this way. I also noticed that the JournalDemo::dumpFile() function never gets called.

So far I haven't noticed any performance issues. I also tested it when picking up items and you can't tell it's opening and closing a file each time.

Oh and sorry about the late replies. Couldn't get online most of last week.

Thanks!
Nick
#11
01/10/2005 (7:18 am)
Great! glad it works for you, glad the perfomance doesn't take a hit either, haven't got a chance to test that.

yeah decided agianst the dump function (though it does work); however, it writes that obnoxious tag to the front of each line, so figured why parse it out when not needed.

Also that system mike take a performance hit once your journal gets large enough, due to it rewriting the file each time you add something (don't know if thats anything to worry about considering its just text); however, a way to completely aleviate this is to load all the journal entries into an array that the game holds and references (rather than the file)... then when a person saves their game (or you can link it to exiting the game) the journal is written. Right now this system works well for debuging, since a save game system might not be implemented already, if the game crashes your journal is already written, etc... but later you might want to consider those, would take little modification.
#12
01/10/2005 (7:31 am)
Using an array sounds like a great idea. I'll test it again though with a LOT of text to see if it slows down.

I do have a somewhat funcional save-game feature implemented using SQLite. It shouldn't be a problem making the journal to work with it. I can just store the filename where the journal resides in a variable.

Nick
#13
01/11/2005 (8:20 am)
Hey... Um... Why not make the journal control live elsewhere so you're not constantly saving/loading?
#14
01/11/2005 (8:45 am)
Maybe have a global array that holds all the entires then on gui wake just display that... then save the journal with the save game function. Pretty much what I was proposing towards the end, though haven't got a chance to do it, I still would like to set up a complete journal system and submit it as a resource, with parsed files, different ways to load entries... guess its all pretty basic, just time consuming... but again time seems to elude me.
#15
01/12/2005 (5:46 am)
You know, now that you guys triggered my thinking, using a global array instead of saving and loading the journal each time is an absolute must. At least for single player.

That's because in case the player exits the game without saving it while having new journal entries, then the next time the player loads the game, it will show journal entries on events that have not yet technically happened! That would also produce duplicate entries!

So I'll just have the above code get called only upon game saving/loading, and simply use an array for temporary storage/viewing of the journal during gameplay.

Nick
#16
01/12/2005 (7:58 am)
Yeah, was running into the same thoughts myself...

I'm going to be making a full journal system like I mentioned, that will write tagged info, then parse it and allow you to look it up in different ways (at least as far as I plan right now)... so I'll submit it as a resource, though considering many people probably don't have a save game function implemented yet might suggest they put it in the leave function of game.cs... until they have a save system
#17
01/19/2005 (9:39 am)
Well nearly have a fairly in-depth in game journal system using a couple script object style arrays (including one three dimensional array) and message vector, with navigating by click...

check it out in my current plan
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7015
hopefully will have it out as a resource soon
#18
01/20/2005 (4:26 pm)
Here is a sample pic of what I've gotten so far, i have an image loaded to the right pane if you specify one for each entry
razedskyz.com/games/torque/plan/journalpic1.JPG
check out the above plan link to see more details


I've added some fairly advanced features... all sorts of searching... the beef of it is a three dimensional array that can be used for much more than just a journal, an inventory system, really any sort of data... its more like a database with a modified message vector that I have set up as a journal presently
#19
01/20/2005 (11:18 pm)
Cool! :)
#20
01/23/2005 (5:50 pm)
Have a detailed list of all the functions for the system in my latest plan

Only have a couple more functions to write and it will be completely finished (very easy ones too)... then I will create a couple more examples of using the data system, have the Journal example completely fleshed out... think i will do an inventory example (so might try and create some in game guis for that)... as well as a mission loading example, this should be efficient for using more complex zone systems with a couple game.cs modifications... really can be used for anything so if anyone interested in using this has any use for some sort of data system other than what I've mentioned I'd be happy to develop an example
Page «Previous 1 2