I took this opportunity to document how to
search for related functions and events in
the lib. Hopefully this is helpful to folks
beyond just getting rid of the $N name token.
The first thing I did was look in the verb
code for what seems like it actually sets
the description:
this_player()->SetLong(str);
Fair enough, let's see what happens when we try
to just call that function:
call me->SetLong("foo")
OBJ(cratylus /secure/save/creators/c/cratylus) -> SetLong( "foo" ) = "$N looks a bit rumpled and tired."
Ok...not that it will work, but let's try with
an eval:
eval return this_player()->SetLong("bar")
Result = "$N looks a bit rumpled and tired."
Right...it was pretty sure not to work, but
it's worth trying a thing a few different ways
sometimes. Unexpected results are a gift from
the fates.
Let's see what happens if we do it with an $N.
eval return this_player()->SetLong("foo $N bar")
Result = "foo $N bar"
Dead Souls Zayin /domains/campus/obj >
exa me
Optimus Cratylus Maximus
foo Cratylus bar
The male human is in top condition.
Cratylus is carrying:
Wire-rimmed glasses (worn)
A small black box
A robe (worn)
A .357 magnum revolver
Sure enough. Looks like SetLong wants a $N.
Let's find where this SetLong is defined for
me and why it's being finicky.
findfun SetLong
/lib/events/look
/lib/interactive
/lib/door
/lib/std/room
/lib/die
Ok, it looks like there are several files that define
SetLong. We're looking for a file that is inherited by
me...since the describe verb calls
this_player()->SetLong(str);
It's not terribly likely that I inherit door, room,
or die code (that's die as in dice you roll), so the
most likely candidates for inspection are /lib/events/look
and /lib/interactive.
To see if I inherit those, I can use the showtree command.
Since I am a creator, my top lib file is LIB_CREATOR,
aka /lib/creator.c
showtree /lib/creator.c
/lib/creator
/lib/player
/lib/interactive
/lib/events/describe
/lib/comp/container
/lib/events/look_in
/lib/props/addstuff
/lib/comp/object
/lib/shadow_hook
/lib/props/clean
/lib/props/description
/lib/events/search
/lib/events/disarm
/lib/props/id
/lib/events/listen
/lib/events/look
/lib/props/properties
/lib/props/radiance
/lib/events/smell
/lib/events/touch
/lib/events/shoot
/lib/user/autosave
/lib/files
/lib/props/move
/lib/pager
/lib/messages
/lib/interface
/lib/chat
(1-28 44%) pr
ess enter:
/lib/command
/lib/editor
/lib/nmsh
/lib/history
/lib/living
/lib/props/carry
/lib/combat
/lib/race
/lib/body
/lib/lvs/position
/lib/events/fall
/lib/events/sink
/lib/undead
/lib/events/crawl
/lib/events/fly
/lib/events/swim
/lib/mount
/lib/props/body_mass
/lib/persist
/lib/genetics
/lib/language
/lib/talk
/lib/classes
/lib/lvs/abilities
/lib/lvs/level
/lib/combatmsg
/lib/currency
/lib/follow
(29-56 90%) press enter:
/lib/magic
/lib/lead
/lib/teach
/lib/learn
/lib/quest
/lib/events/stop
Dead Souls Zayin /domains/campus/obj >
Ug, what a lot of inherits. Rather than wade
through all that, how about using the
inherits command:
help inherits
Syntax: inherits THING -f FILE
Tries to match FILE with the list of inherited files for THING.
See also: showtree, findobj
Dead Souls Zayin /domains/campus/obj >
inherits me -f /lib/interactive
Checking OBJ(cratylus /secure/save/creators/c/cratylus) for inheritance of
/lib/interactive , just a moment...
Optimus Cratylus Maximus inherits /lib/interactive.
Dead Souls Zayin /domains/campus/obj >
inherits me -f /lib/events/look
Checking OBJ(cratylus /secure/save/creators/c/cratylus) for inheritance of
/lib/events/look , just a moment...
Optimus Cratylus Maximus inherits /lib/events/look.
Sho nuff. Let's start with SetLong() in /lib/events/look.c
string SetLong(string str){
return SetExternalDesc(str);
}
Hrm. Nothing about $N's there. But it seems to call
SetExternalDesc(), so let's investigate that function:
string SetExternalDesc(string desc){
return (ExternalDesc = desc);
}
No dice. SetLong() in /lib/events/look.c only calls
a local function and doesn't seem interested in
string tokens. Let's leave this file alone for now
and investigate the other likely candidate, /lib/interactive.c
string SetLong(string str){
if(strsrch(str, "$N") == -1) return object::GetLong();
else return object::SetLong(str);
}
AHA! A check for $N. It looks like if "$N" does not
exist in the passed variable 'str', SetLong() in LIB_INTERACTIVE
is supposed to just return your current GetLong()...which
is consistent with the results from our eval and call tests.
Well, let's change it by commenting out the $N check,
and just return the inherited SetLong():
string SetLong(string str){
//if(strsrch(str, "$N") == -1) return object::GetLong();
//else return object::SetLong(str);
return object::SetLong(str);
}
You might be wondering what those :'s are. '::' is the
"scope resolution operator", it means "don't call this
function in this current inheritable, call it in the
file in inherit called 'object'."
Since SetLong() is defined in the current inheritable,
LIB_INTERACTIVE, then just having that line read
return SetLong(str);
Would cause a recursing call to itself that
would eventually fail and not do anything at all.
Instead, with the scope resolution operator, we
call SetLong() where it is defined in an object
we inherit, in this case, LIB_OBJECT.
Confused? Don't worry, it's not super important to
grok that for our task. And that's kind of a nice
thing about lib stuff. You don't have to fully
understand every last thing...just keep tinkering
and eventually things will make more sense as you
play with them.
Anyway, so now we removed the check, let's make sure
LIB_INTERACTIVE still works:
update /lib/interactive
/lib/interactive: Ok
Good. Now remember, this is a file we inherit...so
my player object still has the old code. I have to
somehow update my own player object in order to
take advantage of the new LIB_INTERACTIVE code:
userload me
Done.
Done.
/domains/default/room/arena
The Arena
You are in a large room with blank cement walls. This room was built so
Creators may test their armor, weapons and NPC's in combat. A large steel door
is here, which can be used to prevent wimpy creatures from escaping.
Obvious exit: south
A weapons rack, a recycling bin, an ammo box, and a tall metal locker are here.
A fighter is standing here.
A training dummy is standing here.
Done.
You wear a robe.
You wear wire-rimmed glasses.
Whee! Looks like it works ok.
Protip: I'm showing off here. Normally you should avoid
userloading yourself. Test on a test creator first.
Now, let's see about changing my description without the
name token:
describe Code! Until your fingers break!
Your description must include a minimum of one '$N' to specify your name.
What?? Oh right. We changed the SetLong(), but we
never changed the verb, which *also* checks. Let's try
a direct call before we monkey with the verb:
call me->SetLong("Code! Until your eyes bleed!")
OBJ(cratylus /secure/save/creators/c/cratylus) -> SetLong( "Code! Until your
eyes bleed!" ) = "Code! Until your eyes bleed!"
Dead Souls Zayin /domains/campus/obj >
exa me
Optimus Cratylus Maximus
Cratylus is nondescript.
The male human is in top condition.
Cratylus is carrying:
Wire-rimmed glasses (worn)
A small black box
A robe (worn)
A .357 magnum revolver
Uh...Hrm. So apparently we succeeded in changing the
description but now my long is "nondescript"? Let's
check to see what my actual Long is:
call me->GetLong()
OBJ(cratylus /secure/save/creators/c/cratylus) -> GetLong() = "Optimus Cratylus
Maximus\nCratylus is nondescript.\nThe male human is in top
condition.\nCratylus is carrying:\nWire-rimmed glasses (worn)\nA small black
box\nA robe (worn)\nA .357 magnum revolver\n\n"
I'm suspicious, though. Take another look at what the return
was from my call:
"Code! Until your eyes bleed!"
Why would my call return that, but now GetLong() doesn't show it?
After all, the return is supposed to be what the
ExternalDesc is set to in LIB_LOOK (remember we examined
that file first?). Something tells me that the ExternalDesc
is indeed correctly set, but GetLong() *also* wants a $N. Let's
see if that's correct.
findfun GetLong
/lib/lamp
/lib/events/look
/lib/cigar
/lib/player
/lib/pipe
/lib/bot
/lib/fuel
/lib/interactive
/lib/door
/lib/torch
/lib/std/room
/lib/creator
/lib/npc
/lib/body
/lib/donate
Ok, let's look at GetLong() in LIB_INTERACTIVE:
varargs string GetLong(){
string str;
str = object::GetLong(str);
if(!str || strsrch(str, "$N") == -1) str = "$N is nondescript.";
str = replace_string(str, "$N", GetName());
return str;
}
Bingo! Ok, Let's fiddle with that check too...
varargs string GetLong(){
string str;
str = object::GetLong(str);
//if(!str || strsrch(str, "$N") == -1) str = "$N is nondescript.";
str = replace_string(str, "$N", GetName());
return str;
}
I commented out the check, but left the line that replaces
$N with a name. After all, maybe there is some usefulness
to replacing a token with a name.
Allrighty, let's test...
update /lib/interactive
/lib/interactive: Ok
Dead Souls Zayin /domains/campus/obj >
userload me
Done.
Done.
/domains/default/room/arena
The Arena
You are in a large room with blank cement walls. This room was built so
Creators may test their armor, weapons and NPC's in combat. A large steel door
is here, which can be used to prevent wimpy creatures from escaping.
Obvious exit: south
A weapons rack, a recycling bin, an ammo box, and a tall metal locker are here.
A fighter is standing here.
A training dummy is standing here.
Done.
You wear wire-rimmed glasses.
You wear a robe.
call me->SetLong("Code! Though the heavens fall!")
OBJ(cratylus /secure/save/creators/c/cratylus) -> SetLong( "Code! Though the
heavens fall!" ) = "Code! Though the heavens fall!"
Dead Souls Zayin /domains/campus/obj >
exa me
Optimus Cratylus Maximus
Code! Though the heavens fall!
The male human is in top condition.
Cratylus is carrying:
Wire-rimmed glasses (worn)
A .357 magnum revolver
A robe (worn)
A small black box
Tadaaa!
With this example I've demonstrated both how to
do what you want, but also the steps you'll want
to take when faced with another such challenge.
Good luck, and happy coding.
-Crat