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
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
#2
from the source
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 usagefrom 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
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
01/05/2005 (7:11 am)
Guess you could have something likejournal.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
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
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
running some tests to see if this will work
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
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"
01/07/2005 (10:07 am)
Filename should have at least one "/" in itso 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
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
01/07/2005 (11:23 am)
Ok set up a basic way to do this... not sure if this is the best, but worksfunction 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
I'm using the following gui
if you use this be sure to change the background image, or the main control
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
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
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
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.
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
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
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
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
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
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
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
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
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

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
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 entrycheck 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
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
01/23/2005 (5:50 pm)
Have a detailed list of all the functions for the system in my latest planOnly 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
Torque 3D Owner Matthew Langley
Torque
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
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