Inventory listing in sidebar

Hi,

I’m trying to create a sidebar in the webUI which gives the player a little extra information beyond what’s in the status bar. I’d like to add an inventory listing, but going round in circles trying to get it to work, when it seems it should be simple. Maybe I missed something?

My latest attempt is to include the line

    "<p>You are carrying: \n<<me.showInventory(tall)>>";

in showStatusHtml(), but it results in nil object reference in:

buildSynthParam(typeString, obj)
{
return ‘{’ + typeString + ’ ’ + gSynthMessageParam(obj) + ‘}’;
}

I guess this is the part which creates the extra part of the message in reply to player’s ‘Inventory’ command (‘You are carrying…’), which I don’t want anyway, but I can’t figure out how to get rid of it.

Thanks

Otto

I don’t know what is “tall” in your code, but that shouldn’t be a problem. But I can’t figure out what to suggest because I really don’t know what is happening in your code given such a small excerpt. If you don’t resolve the problem in reasonable time please extract complete minimal working game source code (say one room one object game with whole webui sidebar as you have coded it) and post it to the forum.

You can get rid of “you are carrying” by changing inventory lister by your own. Instead of calling showInventory you can call showInventoryWith and supplying your own lister. Search “inventorylister” in msg_neu.t library code for sample.

Thanks Tomas -

I tried looking through the msg_neu.t library code as you suggested, but still just can’t seem to get the inventory listing to work in the sidebar. Here is some working code:

gameMain: GameMainDef
initialPlayerChar = me
;

  • me: Actor
    location = entranceHall
    virusCount = 0
    ;

entranceHall: Room ‘Entrance Hall’
"You are in the entrance hall. There is a coffee machine in the corner. A window looks out over
the countryside. "

east = lounge

;

modify statusLine
showStatusHtml()
{
// shows the room the player is currently in
showStatusLeft();
// shows the players ‘IQ’ score and health

Health: <<100 - me.virusCount>><.statusscore>
IQ Score: <>
\n (<<getDescriptor()>>)<./statusscore>

”;
// show the player’s inventory
// “

You are carrying: \n<<me.showInventory(ListTall)>>”;
// add the status-line exit list, if desired
if (gPlayerChar.location != nil)
{
gPlayerChar.location.showStatuslineExits();
“<<statusHTML(0)>><<aHref(gLibMessages.commandLookAround, nil, nil, AHREF_Plain)>>

”;
}
}

    getDescriptor()
{   
        if (scoreIQ>=100 && scoreIQ<110)
        {return 'average';}
        else if (scoreIQ>=110 && scoreIQ<120)
        {return 'above average';}
        else if (scoreIQ>=120 && scoreIQ<130)
        {return 'superior';}
        else if (scoreIQ>=130 && scoreIQ<140)
        {return 'near genius';}
        else return 'genius';
}

    

scoreIQ = 100 + libGlobal.scoreObj.totalScore

;

modify initDisplay()
{
webMainWin.createFrame(commandWin, ‘command’,‘0, 0, 80%, 80%’);
webMainWin.createFrame(statuslineBanner, ‘statusline’, ‘80%, 0, 100%, 100%’);
statuslineBanner.init();
statusLine.statusDispMode = StatusModeBrowser;
}

;

the line

You are carrying: \n<<me.showInventory(ListTall)>> is supposed to show the player’s inventory
in the sidebar between the score and the exit list - however, when I remove the //, it always results in an error

nil object reference

in

buildSynthParam(typeString, obj)
{
return ‘{’ + typeString + ’ ’ + gSynthMessageParam(obj) + ‘}’;
}

First of all you should call <<me.showInventory(true)>> for tall listing, actually it doesn’t matter, but ListTall is a bit mask used in Lister interface deeper in the call stack.

Second, your code actually works and is correct with one little catch. Runtime bug occurs in the first execution of the showStatusHtml() method only because apparently it is executed too early before me object is fully initialized so the library don’t know yet how to call player character. Sorry I’m quite vague here because I didn’t go into detail and I don’t know what’s the precise initialization order of the library, but I was successful setting a flag from the initial look around description in the first room and testing this flag to not call showInventory too early:

"You are in the entrance hall. There is a coffee machine in the corner. A window looks out over the countryside.<.reveal initialized> "

if(gRevealed('initialized')) "<p>You are carrying: \n<<me.showInventory(true)>>";

1 Like

Fantastic!
Works perfectly. Although I have no idea how you figured it out - I spent hours going round in circles looking at the library files.

The question is surely rather rhetorical, but I’ll answer anyway. I’ve looked what happened by examining stack trace:

connectWebUI:http://localhost:38601/?TADS_session=d979d36a-51aa-9331-1cc7f26f4a9e-351f Runtime error: nil object reference -->/usr/share/games/frobtads/tads3/lib/adv3/en_us/msg_neu.t, line 68 /usr/share/games/frobtads/tads3/lib/adv3/en_us/msg_neu.t, line 4654 /usr/share/games/frobtads/tads3/lib/adv3/lister.t, line 546 /usr/share/games/frobtads/tads3/lib/adv3/lister.t, line 131 /usr/share/games/frobtads/tads3/lib/adv3/lister.t, line 1621 /usr/share/games/frobtads/tads3/lib/adv3/actor.t, line 8880 /usr/share/games/frobtads/tads3/lib/adv3/actor.t, line 8858 main.t, line 37 /usr/share/games/frobtads/tads3/lib/adv3/status.t, line 220 /usr/share/games/frobtads/tads3/lib/adv3/misc.t, line 112 /usr/share/games/frobtads/tads3/lib/adv3/misc.t, line 659 /usr/share/games/frobtads/tads3/lib/adv3/misc.t, line 603 /usr/share/games/frobtads/tads3/lib/_main.t, line 209 /usr/share/games/frobtads/tads3/lib/_main.t, line 122 /usr/share/games/frobtads/tads3/lib/_main.t, line 31
The msg_neu.t, line 68 is the place where nil object reference happened, but more interesting is the way through code to this place. On the line 4654 is following code:

showListEmpty(pov, parent) { "<<buildSynthParam('The/he', parent)>> {is} empty-handed. "; }
There you will see, that parent variable is what is passed to the buildSynthParam and this is the variable holding nil value. So backsteping through the call stack over lister.t, line 546, then 131 and 1621 I’ve seen that the variable is only passed along the way without any alteration and came to the actor.t, line 8880, where is “self” passed:

inventoryLister.showList(self, self, contents, ListRecurse | (tall ? ListTall : 0), 0, infoTab, nil);
That’s part of the Actor class and when you are in a method, and you see that self (which should be value of me variable) is in fact nil value, than it is quite weird and I realized the error is printed right at start before any client is connected to the game. That lead me to try suppress first occurrence and wait until me has a value.

Thanks again Tomas -

It wasn’t entirely a rhetorical question, as I seem to have hit a bit of a ‘wall’ in TADS 3 recently, being quite able to do some basic things like add verbs and so on, but not, for example, more advanced things like change the format of the web interface, which is not really covered in depth in the manuals. Looking through the library is helpful sometimes, but often sends me round in circles. Not coming from a programming background at all, just having learned BASIC on old Sinclair machines 30+ years ago, some things are just not obvious.

So it is actually really useful to see how some more professional people have figured out where the problems are.