In my game, gPlayerChar is candidate until a test period is over at which time gPlayerChar morphs into saturnExplorer. Both are actor objects.
This is achieved by these lines of code…
setPlayer(saturnExplorer);
candidate.moveInto(nil);
saturnExplorer.moveInto(hibernationChamber);
All is well. The game works, I can play the entire game to a successful conclusion.
However, a tester has encountered a nil obj ref during game play when he enters the command close eyes immediately after the player char switch. Actually, any command that takes a direct object—whether it’s a valid command or not (take drink even though there is no drink in scope), will achieve the same results, as will a non-implemented action whether it takes an object or not, such, as awaken for which there is no implementation in my game.
If I enter a valid command without an object (look or wait, I can then enter the close eyes—as well as the take drink and awaken commands—without encountering the nil obj ref.
I’ve found where the problem occurs, just not how to avoid or correct it.
The nil obj ref error is produced by line 960 in query.t…
addSelfIlluminatingWithin(obj)
{
addAll(obj.intContents.subset({x: x.visibleInDark}));
}
…which is fed by line 183…
local c = actor.outermostVisibleParent();
The local c is used in a subsequent call to addSelfIlluminatingWithin, where it becomes the the obj of line 960.
When I run my game and set a breakpoint at 183, actor is candidate, not saturnExplorer as expected (since it’s after the player char switch). Since candidate is by now located in nil, c is nil, and line 960 generates a nil obj ref.
I’ve been able to reproduce the error in a test bed environment. Initially, the player char is me.
When you push the magic button, me is moved into nil and otherPerson becomes the player char.
If you then enter any command that takes an object—take drink for example—the nil obj ref error occurs.
If you enter the command wait first, then take drink, it does not.
Here’s the test bed code…
#charset "us-ascii"
#include <tads.h>
#include "advlite.h"
versionInfo: GameID
IFID = '445C38A3-AD1B-4729-957A-F584600DE5C1'
name = 'test'
byline = 'by Jerry Ford'
htmlByline = 'by <a href="mailto:jerry.o.ford@gmail.com">
Jerry Ford</a>'
version = '1'
authorEmail = 'Jerry Ford <jerry.o.ford@gmail.com>'
desc = 'Testing scene.'
htmlDesc = 'Testing scene.'
;
gameMain: GameMainDef
initialPlayerChar = me
paraBrksBtwnSubcontents = nil
;
me: Actor 'me' @room
"The main man.<.p>"
isHim = true
person = 2
;
+ eyes: Thing, Fixture 'eyes'
"Eyes."
isOpenable = true
;
otherPerson: Actor 'other person'
"The other person. <.p>"
isHim = true
;
room: Room 'room'
"In the room. \b
A magic button mounted on the wall is currently in the <i><<magicButton.status>></i> position. <.p>"
;
+ magicButton: Button 'magic button'
"The magic button. <.p>"
status = 'off'
dobjFor(Push)
{
action()
{
status = (status == 'on' ? 'off' : 'on');
"The button's status changes to <<status>>. <.p>";
}
}
;
otherRoom: Room 'other room'
"The other room. <.p>"
;
showTime: Scene
startsWhen = magicButton.status == 'on'
whenStarting()
{
otherPerson.moveInto(otherRoom);
setPlayer(otherPerson, 2);
me.moveInto(nil);
otherRoom.desc;
}
;