#define SWIMMING_SKILL "general.swimming"
#define SHADOW "/std/shadows/misc/water"
#define WET_EFFECT "/std/effects/object/wet"
#define WET_EFFECT_MATCH "object.wet"
#include <tasks.h>
#include <position.h>
int surface = 1;
string up_dir = "up", down_dir = "down", f_in_mess = "$N float$s in from $F.",
f_out_mess = "$N float$s $T.", s_in_mess = "$N sink$s in from $F.",
s_out_mess = "$N sink$s $T.",
c_in_mess = "$N get$s dragged in from $F.",
c_out_mess = "$N get$s dragged away $T.",
on_bottom = "lying on the bottom", non_float = "drifting nearby",
floating = "floating nearby";
int clarity = 100, salinity = 0;
int recheck_delay = -1;
mapping flows = ([ ]), delays = ([ ]);
int attempt_exit( string dir, object ob );
/**
* This method masks the standard one, to give messages more in-line
* with wet areas. See the general documentation for more details.
* @see query_default_position()
*/
mixed *query_default_position(object ob) {
return ({ SWIMMING, "You start to swim.\n",
capitalize(ob->the_short()) + " starts to swim.\n" });
} /* query_default_position() */
/**
* This method masks the standard one, to handle liquid-based positions.
* See the general documentation for more details.
* @see is_allowed_position()
*/
int is_allowed_position(string poss) {
switch (poss) {
case SWIMMING :
return 1;
default :
return 0;
}
} /* is_allowed_position() */
/**
* This method sets the delay before an object is swept downstream.
* @param dir the direction the object is swept
* @param delay the amount of time to wait
*/
void set_min_sweep_delay( string dir, int delay ) {
delays[ dir ] = delay;
return;
} /* set_min_sweep_delay() */
/**
* This method returns the sweep delay for the given direction.
* @param dir the exit direction
* @return the sweep delay for the given direction
*/
int query_min_sweep_delay( string dir ) { return delays[ dir ]; }
/**
* This method returns the sweep delays for all exits as a mapping.
* @return a mapping of all exits and their sweep delays
*/
mapping query_min_sweep_delays() { return delays; }
/**
* Documentation TBD
*/
void set_recheck_delay( int time_out ) {
recheck_delay = time_out;
INV( TO )->update_recheck( time_out );
return;
} /* set_recheck_delay() */
/**
* Documentation TBD
*/
int query_recheck_delay() { return recheck_delay; }
void set_bottom_mess( string mess ) {
on_bottom = mess;
return;
}
string query_bottom_mess() { return on_bottom; }
void set_nonfloat_mess( string mess ) {
non_float = mess;
return;
}
string query_nonfloat_mess() { return non_float; }
void set_float_mess( string mess ) {
floating = mess;
return;
}
string query_float_mess() { return floating; }
void set_sink_in_mess( string mess ) {
s_in_mess = mess;
return;
}
string query_sink_in_mess() { return s_in_mess; }
void set_sink_out_mess( string mess ) {
s_out_mess = mess;
return;
}
string query_sink_out_mess() { return s_out_mess; }
void set_float_in_mess( string mess ) {
f_in_mess = mess;
return;
}
string query_float_in_mess() { return f_in_mess; }
void set_float_out_mess( string mess ) {
f_out_mess = mess;
return;
}
string query_float_out_mess() { return f_out_mess; }
void set_sweep_in_mess( string mess ) {
c_in_mess = mess;
return;
}
string query_sweep_in_mess() { return c_in_mess; }
void set_sweep_out_mess( string mess ) {
c_out_mess = mess;
return;
}
string query_sweep_out_mess() { return c_out_mess; }
void set_surface( int on_top ) {
surface = on_top;
return;
} /* set_surface() */
int query_water() { return 1; }
int query_surface() { return surface; }
int query_bottom() {
return ( member_array( down_dir, (string *)TO->query_exits() ) == -1 );
}
void add_flow( string dir, mixed rate ) {
if ( intp( rate ) || functionp( rate ) ) {
flows[ dir ] = rate;
}
return;
} /* add_flow() */
void delete_flow( string dir ) {
map_delete( flows, dir );
return;
} /* delete_flow() */
int query_flow(string dir) { return evaluate( flows[dir] ); }
mapping query_flows() {
string dir;
mapping ret_flows;
ret_flows = ([ ]);
foreach ( dir in keys( flows ) ) {
ret_flows[ dir ] = evaluate( flows[ dir ] );
}
return ret_flows;
} /* query_flows() */
void set_clarity( int how_clear ) {
if ( how_clear < 0 ) clarity = 0;
else if ( how_clear > 100 ) clarity = 100;
else clarity = how_clear;
return;
} /* set_clarity() */
int query_clarity() { return clarity; }
void set_salinity( int how_salty ) {
if ( how_salty < 0 ) salinity = 0;
else if ( how_salty > 100 ) salinity = 100;
else salinity = how_salty;
return;
} /* set_salinity() */
int query_salinity() { return salinity; }
void set_up_dir( string dir ) {
up_dir = dir;
return; }
string query_up_dir() { return up_dir; }
void set_down_dir( string dir ) {
down_dir = dir;
return; }
string query_down_dir() { return down_dir; }
void event_enter( object ob, string, object from ) {
object *cntnrs, jar, h2o, *stuff;
if ( !ob->query_property( "dead" ) ) {
if ( !ob->find_water_shadow() )
clone_object( SHADOW )->setup_shadow(ob);
else if ( surface && from && !from->query_surface() &&
living( ob ) && !ob->query_property( "gills" ) ) {
tell_object( ob, "You break the surface and take a deep breath.\n" );
tell_room( TO, (string)ob->one_short() + " breaks the "
"surface and takes a deep breath.\n", ({ ob }) );
}
ob->test_float();
ob->test_sweep();
if ( living( ob ) ) {
ob->test_drown();
ob->do_soak();
}
if ( !ob->query_dry_cargo() ) {
cntnrs = filter_array( stuff = INV( ob ), "find_containers", TO );
foreach ( jar in cntnrs ) {
h2o = clone_object( WATER_OBJ );
h2o->set_amount( (int)jar->query_max_volume() -
(int)jar->query_volume() );
h2o->move( jar );
}
cntnrs = filter_array( stuff, "find_towels", TO );
foreach ( jar in cntnrs )
jar->add_effect( WET_EFFECT, 200 * (int)jar->query_weight() );
}
ob->update_recheck( recheck_delay );
}
return;
} /* event_enter() */
void event_exit( object ob, string mess, object to ) {
if ( to && !to->query_water() ) ob->dest_water_shadow();
else ob->cancel_sweep();
} /* event_exit() */
int attempt_exit( string dir, object ob ) {
int outcome, diff, flow_rate;
outcome = SUCCEED;
flow_rate = evaluate( flows[ dir ] );
if ( dir == up_dir &&
( diff = (int)ob->query_buoyancy() + flow_rate ) < 0 &&
!surface ) {
outcome = (int)TASKER->attempt_task( -diff, (int)ob->query_swim_bonus(),
100, -diff );
if ( outcome == FAIL ) {
tell_room( TO, (string)ob->query_short() + " struggles "
"to leave " + up_dir + ", but can't make any headway.\n",
ob );
tell_object( ob, "You struggle to leave " + up_dir + " but, with "
"load you're carrying, you can't make any headway.\n" );
return 0;
}
}
else if ( dir == down_dir &&
( diff = (int)ob->query_buoyancy() - flow_rate ) >
(int)ob->query_swim_bonus() ) {
outcome = (int)TASKER->attempt_task( diff, (int)ob->query_swim_bonus(),
100, diff );
if ( outcome == FAIL ) {
tell_room( TO, (string)ob->query_short() + " struggles "
"to leave " + down_dir + ", but can't make any "
"headway.\n", ob );
tell_object( ob, "You struggle to leave " + down_dir + " but, with "
"your buoyancy, you can't make any headway .\n" );
return 0;
}
}
else if ( flow_rate < 0 ) {
outcome = (int)TASKER->attempt_task( -flow_rate,
(int)ob->query_swim_bonus(), 100,
-flow_rate );
if ( outcome == FAIL ) {
tell_room( TO, (string)ob->query_short() + " struggles "
"against the " + dir + " current, but can't make any "
"headway.\n", ob );
tell_object( ob, "You can't make any headway against the "
"current.\n" );
return 0;
}
}
if ( outcome == AWARD && ob->add_skill_level( SWIMMING_SKILL, 1 )) {
tell_object( ob, ({ "%^YELLOW%^You move more surely as you glide "
"through the water.\n%^RESET%^",
"%^YELLOW%^You discover a more efficient "
"stroke.\n%^RESET%^",
"%^YELLOW%^You find a better way to streamline "
"your body.\n%^RESET%^",
"%^YELLOW%^You find a more efficient swimming "
"rhythm.\n%^RESET%^",
"%^YELLOW%^You begin to move more confidently "
"through the water.\n%^RESET%^"
})[ random(5) ] );
}
return 1;
} /* attempt_exit() */
int find_containers( object ob ) {
return (int)ob->query_max_volume() && !(int)ob->query_closed();
} /* find_containers() */
int find_towels( object ob ) {
int *effects;
effects = (int *)ob->effects_matching( WET_EFFECT_MATCH );
return (int)ob->id( "towel" ) && ( !sizeof( effects ) ||
(int)ob->arg_of( effects[ 0 ] ) < 200 * (int)ob->query_weight() );
} /* find_towels() */
string query_name() { return "drowning"; }
void init() {
if ( TP ) {
TP->add_command( "float", TO, "" );
TP->add_command( "swim", TO, "" );
}
}
int do_float() {
return TP->do_float();
}
int do_swim() {
return TP->do_swim();
}