#include <position.h>
#include <soul.h>
#include <talker.h>
/* Current time for broom flight is 12 seconds */
#define TIME_LIMIT 15
#define BROOMSTICK "/d/guilds/witches/items/broomstick"
#define GRANNY "/d/guilds/witches/chars/granny_weatherwax"
inherit "/std/outside";
int screen_command( string cmd );
string *people;
string *allowed_commands = ({ "l", "look", "glance", /* "eat", "drink",
"taste", "t", "tell", "say", "lsay", "shout", "emote", "hedgehog",
"i", "inventory", "sing", "croon", */ });
void setup() {
set_light( 100 );
set_short( "high above the Disc" );
add_property( "determinate", "" );
set_day_long( "You are high above the Disc, flying through the "
"air.\n" );
set_night_long( "You are high above the Disc, flying through the "
"night sky.\n" );
add_item( ({ "down", "disc", }), "The Disc spreads out below "
"you, much too far away to make out anything distinctly." );
people = ({ });
}
int query_flying( string who ) {
if( member_array( who, people ) > -1 )
return 1;
else
return 0;
}
void drop_non_living( object ob ) {
object broom = load_object( BROOMSTICK );
object player;
object dest;
if( ob->query_corpse() ) {
string name = ob->query_owner();
name = lower_case( explode( name, " " )[0] );
player = find_player( name );
}
if( !player )
player = load_object( GRANNY );
if( !broom || !player )
return; // bugger. Let it hover.
dest = broom->random_dest( player );
ob->move( dest, "$N streaks down from above and crashes into the ground "
"with a thud, narrowly missing you.",
"$N disappear$s from view far below." );
}
/* Damn, they're still here. Put them down somewhere. */
void down_they_go( object witch, object *riding ) {
object broom; // the broom she's riding
object *brooms; // all the brooms in her inventory
object *held; // all the brooms she's *holding*
string path; // the path of the place she's headed
object dest; // the place she's headed
// Maybe she's not even here!
if( !witch )
return;
people -= ({ witch->query_name() });
if( environment( witch ) != this_object() )
return;
// Did she enter the air room by flying? (As opposed to eg restarting
// here, being here when the room was updated, or some other rare event)
// If so, use the broom she flew in on to land her.
// NB: Fireflies, fruitbats etc. don't have a broom in this list.
if( sizeof( riding ) && riding[0] != 0 ) {
broom = riding[0];
tell_creator( "tannah", "broom: %O\n", broom );
} else {
// We've lost track of which broom she flew in on. Let's try to find
// another one to use. This might drop her into a destination from a
// previous flight, but at least it'll drop her somewhere.
brooms = match_objects_for_existence( "witches' broomstick",
({ witch }), 0 );
// does she have any?
if( !sizeof( brooms ) ) {
// if she's not holding any brooms, check to see if she's still
// autoloading
if( witch->query_auto_loading() ) {
call_out( (: down_they_go :), TIME_LIMIT, witch, riding );
tell_object( witch, "Your thighs twitch reflexively and your "
"hands scrabble at the air, searching "
"for your broom.\n" );
return;
} else { // she isn't autoloading and she hasn't got one. SUX0R!
broom = load_object( BROOMSTICK );
}
} else if( sizeof( brooms ) > 1 ) {
// if she's got more than one, pick the one she's holding. If
// she isn't holding any, pick any of them (she'll crash when she
// lands)
held = filter( brooms, (: $1->query_holder() == $(witch) :) );
if( sizeof( held ) )
broom = held[0];
else
broom = brooms[0];
} else {
// she's only got the one. Use it.
broom = brooms[0];
}
}
// if it's got a destination, use it. If not, pick a new one.
path = broom->query_destination();
if( path )
dest = load_object( path );
else
dest = broom->random_dest(witch);
tell_creator( "tannah", "Broom: %O\nLanding in: %O\n", broom, dest );
broom->land( witch, dest );
}
void event_enter( object ob, string message, object from ) {
if( !living( ob ) ) { // objects fall straight away
ob->set_position( "dropping towards the ground" );
call_out( (: drop_non_living :), 2, ob );
return;
}
/* Block all actions they might take up here and screen out those that
* aren't allowed */
ob->command_override( (: screen_command :) );
/* Sometimes the call_out in the broom gets lost. This shouldn't be
* needed too often, but still... */
people += ({ ob->query_name() });
call_out( (: down_they_go :), TIME_LIMIT, ob,
filter( previous_object(-1), (: $1->id( "broomstick" ) :) ) );
}
mixed query_default_position() {
return ({ "flying through the air" });
}
void event_exit(object ob, string message, object to) {
tell_object( ob, "You plummet towards the ground.\n" );
tell_room( this_object(), ob->the_short()
+" plummets towards the ground.\n", ob );
STANDING_CMD->position( ob, 1 );
}
int screen_command( string cmd ) {
string garbage; /* the part of the command string we don't need */
sscanf( cmd, "%s %s", cmd, garbage );
/* We'll completely ignore aliases unless they're broken down. */
if( cmd == "END_ALIAS" ||
(function_exists("query_aliases",this_player()) &&
member_array( cmd, keys( this_player()->query_aliases() ) ) != -1 ))
return notify_fail( "" );
/* We'll check cmd against the list of allowed commands. If it's in the
* list, returning 0 allows it to execute normally. We're not allowing
* souls for now. */
if( member_array( cmd, allowed_commands ) != -1 /* ||
SOUL_OBJECT->query_soul_command( cmd ) */ )
return 0;
/* Let cres do things players can't, but warn them. */
if( this_player()->query_creator() ) {
write( "You attempt aerial feats mere mortals dare not.\n" );
return 0;
}
/* A nice little array of messages, so they don't get bored with the
* same warning every time. */
write( ({
"You don't dare do that while flying so high above the ground.\n",
"Your broom lurches alarmingly, nearly tossing you to the ground "
"below.\n",
"Your concentration wanes and your broom suddenly loses "
"altitude.\n",
})[ random( 3 ) ] );
return 1;
/* The rest of the function isn't ever used because of the above return,
* but I left it here in case we want to expand the list of allowed
* commands later. */
/* if the first character is ', then it's a say and allowed. */
if( cmd[0] == 39 ) return 0;
/* if the first character is ", then it's a say and allowed. */
if( cmd[0] == 34 ) return 0;
} /* screen_command() */
string *query_people() { return people; }