Game Development Community

C++ code for linked list in script objects.

by David Schwanke · in Torque Game Engine · 06/16/2004 (8:14 pm) · 19 replies

Ok. So I succeedeed in creating my first C++ class for a TorqueScript object. In this case it was a RpgItem that extends class Item that let me make a Generic Item and insert into the game and have it retain rpg style properties. (name, desc, etc)

Well my next step is to make a linked list of objects WITHIN this rpg item so that each rpg item can be a specialized container.

I know how to do linked lists on the C++ source side, my question is, how do I make it in the C++ so that the torque script supports the lists and the C++ code can see them too?

As I understand it, the objects really are just pointers in the torque script so that a linked list in the torque script would really just be something like:

draw out unclean code:
%player.backpack = (some backpack RpgItem);
%player.backpack.FirstItem = (some item in backpack);
%player.backpack.FirstItem.nextItem = (next item in backpack);

Then of course I can iterate through the nextItems to go down the list of items in a backpack and even check each nextItem to see if it has a firstItem to see if it is also a container. Not the cleanest code, I know but it should do the job if i get the syntax right.

So now that youve listened to my drivel. The question:

How do I put the right hooks into the C++ class so that the C++ class can interact with the items via the PersistFields stuff?

I did a search on the entire code base for addField and noticed that ONLY specified field types get added through addField. TypeU32 TypeString etc.. So I know its not through addField unless no one has thought of this before which I just cant imagine myself being that inovative. :D

Did I miss something totally obvious again? Sometimes I get so set in one direction of thinking I get blind sided by the blatently simple. :D

#1
06/16/2004 (11:26 pm)
Why are you doing a linked list, again?
#2
06/17/2004 (11:31 am)
Its basically an inventory system with real objects as opposed to the way torque just has individual item counts. (In torque if you pick up a clip it just increases your bullets by 20, I want to be able to have actual clips, health kits, etc, that can be traded, stored, droped, etc.)

I also want to be able to have container items: Backpacks, ammo cases, that sort of thing.

So the idea is to have each item able to be a container.

FirstItem is what determines if the container is storing anything. (I will probably have some code somewhere that determines IF something can be a container. But that comes later.)

First Item is the first item in the linked list of items stored in that container.

Next item (within the first item) is the second item stored in the main container).

I know it seems convoluted the way it setup, but unless my brain just flipped a lizard I could have sworn from my college days that linked lists had the links inside the items being linked. So that conceptually it formed a chain between the items and the first item was stored inside the container that contained the list.

It may not make a whole big difference. In the end the field will be in both places. The question is which one gets used when in the code. I could probably just eas easily put nextItem next to firstItem instead of inside of it. But in my head it makes more sense to put it inside... That way you have tree like: (hope this comes out)

backpack
   |------------|----....
  FirstItem   NextItem
=
as opposed to 
=
backpack ------- NextItem
   |
 FirstItem

Gives me a sense of clarity though it does make the code look funky. Not sure which is considered cleaner by more profesional standards.
#3
06/17/2004 (11:41 am)
Be forewarned, I could be crazy. Ive been told I think 'really wierd'. In that sometimes my solutions are a little too far outside the box and there is something more simple an elegent that just escapes me until someone points it out.

I'm not even 100% sure why i want to be able to access the linked lists from inside the C++. I guess in a way I could probably do all the 'list' management from inside the scripts and use console methods to pass the objects that I want to work with back to the C++. I just figured it made more sense to code the C++ usage of the lists inside the C++ instead of relying on console methods. But again, I could be crazy.

I'm still haveing problems programming on three levels. C++ Code, Script definition, and then script instantiation. Ive only ever dealt with two before, html/(vb|java)script. All my C++ days were single level programs.
#4
06/17/2004 (11:50 am)
If I were doing this (and I am doing something distantly related), I would use SimGroups. Here's a quick tute:

new SimGroup(Backpack1);
%apple = createApple(red, 12 seeds, worm);
Backpack1.add(%apple);
%magazine = createBook(GG, newsletter, printed, limited edition);
Backpack1.add(%magazine);

for(%i = 0; %i < Backpack1.getCount(); %i++) {
   echo(Backpack1.getObject(%i));
}

if(%apple.eaten == true) {
   Backpack1.remove(%apple);
}

I'm not positive on all the syntax... that just came from my head. If you get stuck, just open up the mission editor, look at MissionGroup's id, and type 1234.dump(); in the console (replace 1234 with MissionGroup id). That tells you all the methods you can call on MissionGroups (or any object, for that matter). If you can't figure out the parameters, search for it in the source, or write a test function that calls it, and when you run the game, put trace(true); in the console and check the console.log after you quit.
#5
06/17/2004 (11:54 am)
So SimGroup's are in the scripts? I couldnt figure out how to tell if you could use SimGroups in scripts. I saw them in the C++ code though. But thought they only workedk there since I couldnt find any in any of the script code.

Ill look into this. Thanks.
#6
06/17/2004 (12:11 pm)
This may be usefull but i have another issue that the linked lists was going to solve. Stacking.

This may seem complicated but it does make sense (atleast to me, but im also used to thinking on multiple abstraction levels at once, when i can get my head around them :) ):

Each item would have actual two list links within it that would be used by the inventory system: nextSameItem and nextDiffItem.

nextSameItem would be a list of all the items that were the same. All the ammo boxes for example.
nextDiffItem would be the lists of the first items of each other type of item the container had.

This would be setup such that if you were say looking for an ammo box. Instead of going through a list of 100 items. You could go through a list of 20 different items, and find a single ammobox then go through the ammo boxes until you find the ammo box you were looking for.

This would also let us easily stack the items by iterating down each list of same items and counting them and stacking them and then going down the next list and so on.

Now what I couldnt determine from SimSet or SimGroup was if there was any way to iterate through items of the same class within the set vsus different classes.

** EDIT **
This is where my talk of torque code gets flaky because of my loose handle on the 3 different types of code. When I say different class I mean in the way that if you have class Item and then you have CrossBow and AmmoBox. CrossBow and AmmoBox are two different 'classes'. (But thats probably the wrong term.)
** END **

If not when when I wanted to create the inventory and stack it I would have to create a linked list anyway of everything or atleast an array and keep adding things to the end of the array.

Keep in mind the original torque system just has a array variable for each type of possible item in the game in the player definition class and a max item. In an rpg setting there are literally thousands of possible items and half of them the player will never interact with (because they are unique or whatever).

Also, I dont remember there being a way in SimSets to extract a single random class item from the set. I would have to iterate through the set until I found the item that matched my class. Where as in a linked list I could just iterate through those nextDifItems until I found the right class then use the top one or use a specfic one depending on need.

Its a very specialized solution and it may still need linked lists. We're doing an mmorpg and torque wasnt designed for that so a lot of the functionality has to be invented from the ground up.

I will still look into simsets again if i can.
#7
06/17/2004 (1:07 pm)
Why not nest the SimSets/groups? Have a Backpack group, then an Ammo group inside that, with all ammo boxes. You can get a random entry in the group if you really want...
%item = group.getObject(getRandom(group.getCount()-1));
I don't see why you would need this...
If you setup a nice hierarchy it could work different. Example:
Top Level
  Containers
    Backpack
    Bucket
    Tupperware(tm)
  Weapons
    Melee
      Longsword
      Spiked Club
    Ranged
      Elvish radioactive glow-bow
      throwing daggers
  Items
    Healing
      Snake oil
      Pizza
    Magic
      Mana replenishing potion
      Town portal mushroom
Just create a group for each category, and work your way down the hierarchy. This may be a teeny bit cumbersome, but your code will be 100% readable when you look at it 2 years from now, and it's already made for you. You can create SimGroups from a string, so they can be uniquely named at runtime.
%id = getNextWeaponID();
%mystring = "Weapon" @ %id;
new SimGroup(%mystring);

You can also get the name of a group from its ID. So you get 2145 from MainGroup.getObject(%i), then use getName (I forgot the actual function name) to find out what the name is, and you can use string parsing technique to match things up. You could even use delimiters in your naming, such as underscores... i.e. OrcCimeter_241 to facilitate scanning and tokenizing.

Using linked lists may be a better bet for you, I don't know. I also don't know off the top of my head how to use linked lists in script. Somehow I remember someone mentioning how to use variable references in script, which would allow you to use linked lists purely in script. Maybe someone else will be able to elaborate on that.
#8
06/17/2004 (1:31 pm)
Hmm.. I kind of like this solution but I think it may be a bit too cumbersom as you said.

First we would have to know the structure of items in advance or atleast develop some way of knowing what to look for.

The idea of the containers was to have them containable too.

So for example a backpack might contain a sack which could contain a pouch which could contain a potion. Your system seems a bit too rigid to work in that kind of environment though that isnt to say that it couldnt be adapted. Thank you still, its giving me food for thought.

I'm more for the flowing data style of coding. Leave it in as raw an organization as possible and let the functions do the organizing. I only choze the one level of organizing (nextDiff/nextSame) because I know from experience that stacking code can reek havoc on the client refresh rate in inventory situations with lots of randomly spread stacked items. (Ive been in games where you went to your inventory and watched the stacks of items slowly increase by 1 as the inventory code 'dealt' with you 200 small items. :D)

I think I am going to go back to linked lists but only do them as the simple %player.whatever version. And not worry about dealing with them in the C++ code. If I have to ill pass them back to the C++ through console commands. (be interesting to see if you can pass back an entire 'backpack' full of RpgItems and see if they still retain the script changed information. :D)
#9
06/17/2004 (3:56 pm)
You can make stacks work very easily with SimGroups.

Just make a SimGroup for each stack! (Gasp!)

SimGroups are ideal for representing directed acycle graphs of any sort, including your inventory problem.

FYI, all scriptable objects are represented by a SimObject or subclass thereof. You should really take the time to get familiar with SimObject and Torque's scripting system in general before going any further in this endeavour. You have too many unknowns and you're making the problem too complex for yourself.

SimSets and SimGroups are the basis for all set and group operations in Torque, so you don't need to worry about performance. The object hierarchy stores on average several thousand objects, using nested SimSets and SimGroups - so a few hundred here and there just doesn't matter.

If you have a truly vast set of inventory objects, you may want to get a copy of SQLite or another relational database application and work with that.
#10
06/17/2004 (5:15 pm)
PLEASE, PLEASE, PLEASE give me some good links on learning about SimObjects and the scripting language.

Ive done nothing with this project but hear people tell me to go check out something else first. Obviosly, this is the lowest link on the chain so maybe I can finally learn something.

I have been beating myself senseless trying to twist my way through this maze of code snippets, resource files, half documented source code, forums, broken links, plan files, google searches.

I really wish I had a clue as to how to actually get decent amounts of usefull information out of this system for any given topic. I am sure its possible, because I can tell that everyone but me has figured out how, but I'm just lost.
#11
06/17/2004 (5:37 pm)
While I'm putting in my plea of desperation request:

Do you have any good links on how to know which SDK classes are available in the scripting language and how to use them?

That was my biggest problem in this case. I was told to go use SimSets and there was no documentation that I could find that said whether or not SimSets were supported well in the scripting langauge. So I assumed that I had to use them in the C++ and then translate that somehow into scripting. When I finally tracked them down in the sdk none of the console methods are documented and I couldnt really make much sense of the actual code except by inference and suggestion.

I guess my biggest problem is with all these what 10 different ways to figure stuff out I dont have nor know how to develop a system of checking all these locations methoidically to get good information.

It takes forever just to trace the functions in the source. Then you have the SDK docs, then you have the non-existant script docs (Finally found a list of console functions but no list of classes. WOuldnt it make sense to have both and have them in the same place?) Then you have the searching on the forums, searching on the resources, searching on the plans. Then there is google. I know I have said this all before but it drives me nuts.

Maybe I'm simple, maybe I expect too much? I dunno. Its been 7 years since coded and that was in the confines of college, maybe I just got lucky and spent 5 years coding only in places where people had all their information in one place. All I know is its driving me insane. By the end of the night my head is spinning and I have only a vague concept of having actually acomplished anything. What am I doing wrong?
#12
06/17/2004 (6:18 pm)
What I've done when I can't find documentation on something is just jump into coding and make a simple test.
I'd recommend not even thinking about making your game right now. Just make little tiny technology demos. First you could try the "backpack and apples" example I gave. Just create a SimGroup, add some objects, and remove them. Then start building onto it... but only once you've tested it and understand how it works up to that point.
As far as understanding scripting... some things that really really have helped me are: Tribal IDE. Create a new project... don't just open a file... and have it load all the .cs files in your entire game dir (starter.fps, for one). Then you can highlight a function name, right-click it, and it'll take you right to where it's defined. You can also use find-in-files (even within tribal) to find usages of that same function. Just reading the scripts will help a lot. Remember... your game isn't already written for you in code snipits... you'll have to create _some_ new stuff.
Also, the %obj.dump() command is very useful, combined with trace(true);
The Torque docs have a scripting section that is very well put together. I have been through most, if not all of it. But most of what I've learned came from just trying (and failing) to code something up, and tweaking my attempts until I got it right.
I've been through the same thing... just a few months ago. I have my dream game concept, and it's pretty complex. After starting and getting stuck with technical stuff, I decided to think up a simpler game that is based more closely on Torque's default fps setup. It's not a fps, you're just a guy running around filling up containers with fluid.
Only once I decided to go simpler did I start learning about Torque. I wasn't overwhelmed with what I couldn't do. Another thing I decided was to stay in script. That essentially means I'm modding the demo, but I've learned a lot of Torque. When my game is coming along nicely, I _might_ think about modifying the c++ source to add something the demo can't support. I realize you might think... "I don't have time to make more than one game." I thought that too... but as I'm developing this one game, I'm coming up with a better idea of how to make my masterpiece.
If you'd like a simple game idea (that fits well with torque), I can try to think of one... I love doing that :)
#13
06/17/2004 (8:15 pm)
Still no links. :(

Exactly what torque docs are you refering to that have a nice scripting section?

I dont mean to sound whiney but I am trying to debug my own learning process because something is obviosly wrong. You may think that the "Torque docs scripting section" is great, but either:

A) Ive never seen it. (Something is wrong with my search techniques.)
B) I didnt understand it and didnt think it was relevent enough to pursue. (Something is wrong with my basic learning/assesing.)
C) I already know it all and consider it pat information. (My problem is elsewhere and I am just not connecting what I know with what people are suggesting.)

But without an actual link to what you think the Torque Docs scripting section refers to, I have no idea how to tell what the problem is with what I am doing. We could be talking about two totally different scripting sections and the one your refering to would make all the difference for me.

The only section that I know of is this. And to me thats fairly basic. Keep in mind I already have written a C++ class extension of the Item class AND written a basic item in taht new class in script. I understand the bare basics of script.

What I dont understand is precisely "What is it that I dont understand?" I feel like I know the basics yet I keep getting told to go back to the basics. Then when I ask 'where are the basics' I dont get any links to any basics, to which I can say "AH HAH! There are the basics that I dont have yet." :) Understand why I'm going nuts yet? :D

Thanks for your help and especially for you guys baby stepping me through this. I never worked on a psuedo open source project before but I do hope someday to get to the point of being able to return the favor to someone else.
#14
06/17/2004 (8:50 pm)
Yes, those are the scripting docs I am talking about... but also check the appendices with the datablock reference (I'm sure you've looked at those too).

Another thing you can try is avoiding the forums and searching, so you can concentrate on a whole day of programming. I did this a couple times, and I surprised myself with the progress I made. Searching for things is addicting... there's always the hope that someone else already did what you want to, though usually you get it done faster if you do it yourself (unless it's huge), and it's the way you want it. I've found myself doing that lots.

I really really recommend doing the prototyping thing, though. Don't try to write the whole thing all at once. Slow down a little. Relax. Take a deep breath. Wax on, wax off. (uh huh... :) How about this... I'll give you homework :) This will hopefully improve your scripting ability.

1. Create a new script class based on the item datablock (now this is a lot simpler than you may take it... if you want me to expound, let me know). Say it's a backpack.

2. Create another class... maybe an apple (gee I'm boring).

3. Write an onPickup method for each of them. This onPickup method should create SimGroups to contain them... for now just hardcode their names as "apple" and "backpack".

4. When you pickup the apple, it should check to see if there is a backpack group. If so, then it should add the apple simgroup to the inside of the backpack group, and add the apple item to the apple simgroup. (Completely confused yet? Good.)

You don't need any graphical feedback for any of this... just use the console to verify that these actions are taking place. Use dts shapes that already exist (like a healthkit and crossbowammo) If your changes don't seem to be updating, you may have an error in the script, so scroll through the console output and watch for red text near where your script is loaded and executed.

The benefit to this is that I'm pretty sure I know how to do it... and I have a sort of similar script (except I use onCollision and I don't put anything in groups... my groups are already made). So try this, and when you're looking for the car keys to drive yourself to the insane asylum (which means you've put enough work in to get frustrated and start pulling hair), take a minute to post your question, and I'll give a hint or solution. I may just even do this all myself as an exercise to help my understanding, even though I don't need it for my game coming up.

This assignment is due tomorrow evening, and there will be a 10% deduction per day late :)
#15
06/17/2004 (9:23 pm)
David,

Some links:

www.garagegames.com/docs/torque.sdk/engine/index.php - the engine overview.
www.garagegames.com/docs/torque.sdk/engine/classSimObject.php - SimObject, foundation of all scripting.
www.garagegames.com/docs/torque.sdk/engine/classSimSet.php - SimSet.
www.garagegames.com/docs/torque.sdk/engine/classSimGroup.php - SimGroup.

Have you been here before? Seen this? How about this?

Have you tried doing a forum search on stuff like ConsoleMethod, ConsoleFunction, console.h, or SimObject?

You've been asking a lot of questions but not doing much research.
#16
06/18/2004 (10:46 am)
**** EDIT ****
If you read this in email, reread it, I rewrote it. I got a little bitchy in the original My apologies if you read that.

First Ben I wanna take the time to thank you for your help in this. The following is going to sound a little harsh but its because I also care about other people that might end up in the same situation that I just did. Please dont take it personally.

And yes it sounds like I'm biting the hand that just fed me but that one line gets real old when people keep saying it and its not the problem.
**** END ****

Dont take this personally, but as a word of caution:

Please dont try to tell me that i havnt been doing much research. Read what John posted just before you. He just got done telling me I have been doing TOO much. And he is right. I have all this knowledge bouncing around in my head, but none of it is tied together.

If I took the time I could make you a list twice as long as what you gave me on the stuff we talked about but it wouldnt be as 'connected' as your list. In fact it would be mostly fragments from the forums. The 'Seen This' and 'How About This' I didnt find. But I probably found about 10 or more others like it just not as complete.

I specifically asked for links NOT because I was lazy but because I wanted to CHECK my links to make sure that I wasnt missing stuff and to see if there was something ELSE wrong with the way I was aproaching this.

I had the first 5 links, obviosly I did not read them as carefully as everyone else seems to have read them so I will go read them again. I already know about ConsoleMethods and ConsoleFunctions. I have already used them to create my RpgItem class. But I will read the links for due diligence.

Ill dig in deeper to the forum posts and see whats in them.

But please dont assume that I havnt done much research, there isnt anyway for you to know that unless your sitting here next to me or I tell you.

Sorry if I sound pissy but research is not my problem. I know the guts of research and I do it. It seems based on the links that I came up with and how I read them and the list of links that you gave me, that my problem isnt in finding the links its knowing which links to pay attention to and figuring out how to tie them together.

Thank you for your help, both of you, even you Ben, I'm not mad, just please dont always make the assumption that someone hasnt done enough research. That isnt always the case. I did more then enough, I just didn't know how to properly use what I found.
#17
06/18/2004 (10:53 am)
And John I thank you for your assignment but I cant get it back to you on any specific time frame. My time at this project is spurradic at best due to my life situation. (Part of it is a mental condition that limits how long I can spend on the computer doing any one thing.)

I already have an RpgItem class that I wrote. I think I a may try to do your project with that. First though Ill take the time to really study Ben's links and thats going to take me a day or two atleast. (To really make sure I got them this time.)
#18
06/18/2004 (3:14 pm)
I'm very glad that you rewrote your post. You've decided to learn. Excellent choice, and one few people make... Thanks for turning this into a productive conversation, instead of one that spirals downhill.

Anyway, once you've reviewed that stuff, you should have a better idea about what's going on... if you still have questions, please feel free to ask. :)
#19
06/18/2004 (3:17 pm)
No worries... I was just trying to bring back school memories :) I just find it helpful when I have very detailed goals in attacking a project. Small ones, too. I can almost promise you that doing the assignment will help, though, so remember to do it sometime :)