/**
* This is a wall object. It is added to rooms when you use the set_wall()
* function to add a climable wall exit to a room. If you wish to have
* players climb somewhere this is the preferred method to use.
*
* @author Deutha
* @see climb
* @see /std/room.c
* @see /std/rooftop.c
*/
string *belows;
mixed *bottom, *moves;
object room;
void create() {
belows = ({ });
bottom = 0;
moves = ({ });
} /* create() */
void setup_shadow( object thing ) {
shadow( thing, 1 );
room = thing;
} /* setup_shadow() */
void destruct_shadow( object thing ) {
if ( thing == TO )
destruct( TO );
else
thing->destruct_shadow( thing );
} /* destruct_shadow() */
string *query_belows() { return copy( belows ); }
mixed *query_bottom() { return copy( bottom ); }
mixed *query_moves() { return copy( moves ); }
int query_at_bottom() { return !bottom; }
mixed *query_move( string word ) {
int i;
i = member_array( word, moves );
if ( i == -1 )
return 0;
return moves[ i + 1 .. i + 3 ];
} /* query_move() */
void calc_co_ord() {
int i, delta, *co_ord;
string word, other;
room->calc_co_ord();
if ( co_ord )
return;
foreach ( word in ({ "down", "up" }) ) {
i = member_array( word, moves );
if ( i == -1 )
continue;
other = moves[ i + 2 ];
if ( !find_object( other ) )
continue;
co_ord = copy( (int *)other->query_co_ord() );
if ( !co_ord )
continue;
delta = (int)room->query_room_size() + (int)other->query_room_size();
if ( word == "down" )
co_ord[ 2 ] += delta;
else
co_ord[ 2 ] -= delta;
room->set_co_ord( co_ord );
return;
}
} /* calc_co_ord() */
void set_wall( mixed *args ) {
int i, j;
mixed arg;
for ( i = sizeof( args ) - 2; i > -1; i -= 2 ) {
arg = args[ i + 1 ];
switch ( args[ i ] ) {
case "bottom" :
bottom = arg;
room->add_property( "here", "falling past you" );
break;
case "below" :
belows += arg;
break;
case "move" :
j = member_array( arg[ 0 ], moves );
if ( j == -1 )
moves += arg;
else
moves[ j + 1 .. j + 3 ] = arg[ 1 .. 3 ];
break;
}
}
} /* set_wall() */
void event_enter( object thing, string mess, object from ) {
room->event_enter( thing, mess, from );
if ( !living( thing ) && bottom )
call_out( "fall_down", 0, thing );
} /* event_enter() */
void fall_down( object thing ) {
int damage;
string word;
if ( !thing )
return;
if ( environment( thing ) != room )
return;
damage = (int)room->query_room_size();
if ( sizeof( belows ) )
foreach ( word in belows ) {
tell_room( find_object( word ), (string)thing->a_short() +
" $V$0=falls,fall$V$ past you and $V$0=is,are$V$ gone.\n" );
damage += 2 * (int)word->query_room_size();
}
if ( stringp( bottom ) ) {
if ( living( thing ) )
thing->move_with_look( bottom,
"$N fall$s from above with a loud thump.",
"$N drop$s downwards out of sight." );
else
thing->move( bottom,
"$N fall$s from above with a loud thump.",
"$N drop$s downwards out of sight." );
return;
}
word = bottom[ 0 ];
damage += (int)word->query_room_size();
if ( stringp( bottom[ 1 ] ) )
if ( living( thing ) )
thing->move_with_look( word, call_other( word, bottom[ 1 ], thing,
room ), "$N drop$s downwards out of sight." );
else
thing->move( word, call_other( word, bottom[ 1 ], thing, room ),
"$N drop$s downwards out of sight." );
else
if ( living( thing ) ) {
thing->move_with_look( word,
"$N fall$s from above with a loud crunch.",
"$N drop$s downwards out of sight." );
damage *= bottom[ 1 ] * (int)thing->query_complete_weight();
damage /= 10000;
damage -= (int)thing->query_ac( "blunt", damage );
if ( damage > 0 )
if ( (int)thing->adjust_hp( -damage ) < 0 )
thing->attack_by( room );
else
tell_object( thing, "Ouch, that hurt!\n" );
} else
thing->move( word,
"$N fall$s from above with a loud thump.",
"$N drop$s downwards out of sight." );
} /* fall_down() */