Anyway, let's talk about some of these kinds of changes. For starters, I replaced the female_character class. In the standard library, that class gets its own type ('female_character"), so if you have a game where you are checking if objects are NPCs, you have to check for both "character" and "female_character". I changed it so female_character objects are of type "character", as you can always check for the female attribute if you are truly looking for a female NPC.
More recently, I was writing some code that assumed the player_character object was of type "player_character". Funnily enough, this was not the case (it is actually of type "character")! Now, maybe people won't agree with me on this one, but I feel the player_character should get its own type, so in roodylib, it currently does so.
Much further back, I changed up some of the vehicle class code so it'd be (hopefully) easier to change which directions can exit a vehicle:
replace vehicle(DoGo also has some slightly different code, I believe)
{
type vehicle
vehicle_verb "drive" ! default verb
prep "in", "out" ! " prepositions
vehicle_move true ! by default, always ready to move
#ifclear NO_VERBS
before
{
parent(player) DoGo
{
if word[2] = "out" and object = self
{
object = out_obj
return false
}
if (object ~= u_obj, out_obj) and object.type = direction
{
! "To walk, you'll have to get out..."
OMessage(vehicle, 1, self)
return true
}
else
return object
}
}
#endif
is enterable, static
}
Lately, I also was looking at something whose design I disagree with but will do nothing about. I was taking a look at GetInput, which is a short and simple routine:
routine GetInput(p)Personally, I'd think that you'd only call GetInput when you want to also provide a prompt, so it should be something like this:
{
print p;
input
}
routine GetInput(p)My logic is, hey, only call GetInput when you want a prompt of some point. Otherwise, why not just call input directly? Thing is, the standard library (and other existing code) call GetInput without a prompt argument a lot. I could either change all of those library routines (breaking lots of game source, too, in the process, probably) or just ignore it. I'll just do the latter. I could add a slightly-similar-sounding routine to roodylib that behaves like I feel GetInput should, but hey, I admit this isn't an important problem...
{
if p
print p;
else
print prompt;
input
}
So yeah, that.
In other news, I updated Activate, the routine for starting daemons, so it complains if it is called before the player global has been set (I've run into that problem once or twice):
replace Activate(a, set) ! <set> is for fuses onlySo yeah, that's all some stuff.
{
local err
if not player
{
Font(BOLD_ON)
print "[WARNING: The player global must be set before
daemon (object "; number a;") can be activated.]"
err = true
}
a.in_scope = player
a is active
if a.type = fuse and not err
{
if set
a.timer = set
run a.activate_event
}
elseif a.type = daemon and not err
{
if set and not a.#timer
{
Font(BOLD_ON)
print "[WARNING: Attempt to set nonexistent timer
property on daemon (object "; number a; ")]"
err = true
}
else
a.timer = set
run a.activate_event
}
elseif not err
{
Font(BOLD_ON)
print "[WARNING: Attempt to activate non-fuse/\
daemon (object "; number a; ")]"
err = true
}
#ifset DEBUG
if debug_flags & D_FUSES and not err
{
print "[Activating "; a.name; " "; number a;
if a.type = fuse
print " (timer = "; number a.timer; ")";
print "]"
}
#endif
if err
{
Font(BOLD_OFF)
"\npress a key to continue..."
HiddenPause
}
return (not err)
}
Why can't a daemon be activated before the player global is set? Granted, intentionally doing so wouldn't seem to make much sense.
ReplyDeleteDaemons are a type of local event, but instead of being attached to a location or object (where they would execute every time that location or object is within scope), Activate(a) has the line: a.in_scope = player
DeleteIf the "player" global hasn't been set, Activate just put the daemon in the scope of the nothing object, not the player_character (which explains why you don't see the daemon occurring for the rest of the game).