/* Inheritable for melting food by Carmine, August 2001 */ /** * * <BR> * This is an inheritable for frozen food which melts, * based on the temperature of the room environment in * which it finds itself. * <P> * It performs just as normal food, apart from the following: * <P> * - It cannot be cured or dried * <P> * - It does not decay * <P> * - It cannot be forced to behave as a liquid * <P> * - When applied or eaten, it will cause a brief decrease * in temperature of the user. * <P> * It will melt into a liquid, which can be set using * set_melt_result(). This is default at water, and can be * queried using query_melt_result(). * <P> * It's melt level can be checked by query_melt_level(). This * starts at a value of ten times the original weight of the * meltable food. * <P> * It's rate of melting adjusts itself regularly, based on the * temperature. This can be checked with query_melt_rate(), and * set temporarily with set_melt_rate. * <P> * The level of melting is shown in the long and short of the object. * These are created using query_short_rotten_adjective and * query_long_decay_level, and are based on the percentage of * object left. * * @author Carmine * */ #include <bits_controller.h> #include <weather.h> inherit "/obj/food"; #define CHILL -5 /* By how much eating or applying this will cool you */ #define CHILL_TIME 10 /* For how long eating or applying this will cool you */ #define MELT_RATE_DEFAULT 6 /* The default melt rate, initially corresponding to 60 seconds for something of weight 1 to melt away to nothing in a 20 deg. C environment */ #define WATER "/obj/food/beverages/water.food" /* default melt liquid */ /* This is a lookup table which holds the melt rates dependent on the environment's temperature. It has values for 1 to 50 C, after which the melt rate is 1 (fast). Below 1, no melt takes place */ #define _LOOKUP_RATE ({ 60, 57, 54, 51, 48, 42, 36, 30, 27, 24, \ 20, 18, 16, 14, 12, 10, 9, 8, 7, 6, \ 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, \ 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, \ 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 }) /* GLOBAL VARIABLES */ private int _melt_level; /* this represents the amount left to melt */ private int _original_melt_level; /* this stores the original melt level at setup */ private int _melt_rate; /* this is the number of seconds between the melt counter counting up by 1 - it is the number of seconds between liquid being produced by the melting object */ private int _melt_counter; /* this counts up to 10, and decreases the weight of this object by 1 every time it reaches 10, whereupon it resets to 0 */ private int _callout_id; /* the id of the melting call out */ private string _melt_result; /* the path of the liquid result of melting */ /* FUNCTION PROTOTYPES */ void create(); void set_melt_result( string result ); string query_melt_result(); void set_melt_rate( int rate ); int query_melt_rate(); int query_melt_level(); private void setup_callout(); protected void do_melt(); /** * @ignore yes */ void create() { do_setup++; ::create(); do_setup--; _melt_rate = MELT_RATE_DEFAULT; _melt_counter = 0; set_melt_result( WATER ); set_decay_speed( 1 ); setup_callout(); if ( !do_setup ) { this_object()->setup(); } _melt_level = ( this_object()->query_weight() ) * 10; _original_melt_level = _melt_level; }/* create() */ /** * This function sets the liquid that the melting food melts into. * The default value for this is water. * * @param result The path of the liquid generated when this food melts * * @see query_melt_result() */ void set_melt_result( string result ) { _melt_result = result; } /* set_melt_result */ /** * This function returns the liquid that the melting food melts into. * The default value for this is water. * * @return The path of the liquid generated when this food melts. * * @see set_melt_result() */ string query_melt_result() { return _melt_result; } /* query_melt_result */ /** * This function sets the current melt rate for the liquid. This will * have no ostensible affect on the melting of the liquid, as the * melt rate is recalculated regularly. * * @param rate The new rate of melting * * @see query_melt_rate() * */ void set_melt_rate( int rate ) { _melt_rate = rate; } /* set_melt_rate */ /** * This function returns the current rate of melting of the frozen food. * * @return The current melt rate of the food. * * @see set_melt_rate() * */ int query_melt_rate() { return _melt_rate; } /* query_melt_rate */ /** * This function returns the current melt level of the food. This value * starts at ten times the original weight of the object, and decreases * in time, as the food melts. * * @return The current melt level of the food. */ int query_melt_level() { return _melt_level; } /* query_melt_level */ /** * @ignore yes */ private void setup_callout() { if( _callout_id ) { remove_call_out( _callout_id ); } _callout_id = call_out( "do_melt", _melt_rate ); } /* setup_callout */ /** * @ignore yes */ protected void do_melt() { object liquid; object room, ob; int environment_temp, current_weight; /* finds the final container of this object - ie the room that the object is within, whether it's nested in many containers or not */ ob = environment( this_object() ); if( !ob ) { return; } room = ob; while( ob = environment( ob ) ) { room = ob; } /* sets environment_temp to the temperature of the room, in degrees centigrade */ if( room->query_property( "location" ) == "outside" ) { environment_temp = WEATHER->query_temperature( room ); } else if( room->query_name() == "clone_on_demand-store" ) { environment_temp = 0; // Don't melt if you're in a shop's inventory } else { environment_temp = 20 + room->query_property( "warmth" ); } /* if temperature is less than 0, no melt. */ if( environment_temp > 1 ) { /* setup the melt rate dependent on environment temp: hotter environment means faster melting call out */ if( environment_temp > 50 ) { _melt_rate = 1; } else { _melt_rate = _LOOKUP_RATE[ environment_temp ]; } /* decrease melt level counter and increase melt counter */ _melt_level = _melt_level - 1; _melt_counter = _melt_counter + 1; /* if the counter has reached 10 yet, make some liquid and remove some weight */ if ( _melt_counter >= 10 ) { liquid = clone_object( _melt_result ); liquid->set_amount( 20 ); liquid->move( environment( this_object() ) ); current_weight = this_object()->query_weight(); if( current_weight <= 1 ) { this_object()->move( "/room/rubbish" ); } else { this_object()->set_weight( current_weight - 1 ); } _melt_counter = 0; } } _callout_id = call_out( "do_melt", _melt_rate ); } /* do_melt */ /** * This function returns the adjective appended to the food's * short description, describing how melted it is. * * @return The adjectives added to the food's short describing its * melt status. * @see query_long_decay_level() */ string query_short_rotten_adjective() { string ret; int bing; bing = 100 - ( ( 100 * _melt_level ) / _original_melt_level ); ret = ""; switch ( bing ) { case 0..1: break; case 2..20: ret = "slightly melted " + ret; break; case 21..45: ret = "partially melted " + ret; break; case 46..55: ret = "half melted " + ret; break; case 56..80: ret = "mostly melted " + ret; break; case 81..100: ret = "almost completely melted " + ret; break; } return ret; } /* query_short_rotten_adjective */ /** * This function provides words for the food's long description, * showing how melted the object is. * * @return The words appended to the food's long, showing its melt status. * * @see query_short_rotten_adjective() */ string query_long_decay_level() { string ret; int bing; bing = 100 - ( ( 100 * _melt_level ) / _original_melt_level ); ret = ""; switch ( bing ) { case 0..1: if( query_collective() && query_amount() > 1 ) ret += "They have not yet begun to melt.\n"; else ret += "It has not yet begun to melt.\n"; break; case 2..20: if( query_collective() && query_amount() > 1 ) ret += "They have melted slightly.\n"; else ret += "It has melted slightly.\n"; break; case 21..45: if( query_collective() && query_amount() > 1 ) ret += "They have partially melted away.\n"; else ret += "It has partially melted away.\n"; break; case 46..55: if( query_collective() && query_amount() > 1 ) ret += "They are half melted away.\n"; else ret += "It is half melted away.\n"; break; case 56..80: if( query_collective() && query_amount() > 1 ) ret += "They have mostly melted away.\n"; else ret += "It has mostly melted away.\n"; break; case 81..100: if( query_collective() && query_amount() > 1 ) ret += "They have almost complete melted away.\n"; else ret += "It has almost completely melted away.\n"; break; } return ret; } /* query_long_decay_level */ /* Make the person chilly for a while when they eat the food. Then inherits normal eat stuff. */ /** * @ignore yes */ varargs int do_eat( int no_mess ) { this_player()->add_property( "warmth", CHILL, CHILL_TIME ); return( ::do_eat( no_mess ) ); } /* do_eat() */ /* Make the victim chilly for a while when they apply the food. Then inherits normal apply stuff. */ /** * @ignore yes */ int do_apply( object * things ) { int i; if( i = ::do_apply( things ) ) { things[ 0 ]->add_property( "warmth", CHILL, CHILL_TIME ); } return i; } /* do_apply() */ /** * @ignore yes */ int do_rub( object * things ) { int i; if( i = ::do_rub( things ) ) { things[ 0 ]->add_property( "warmth", CHILL, CHILL_TIME ); } return i; } /* do_rub() */ /** * @ignore yes */ mixed *stats() { mixed *args; args =::stats() + ({ ({ "melt level", _melt_level }), ({ "melt result", _melt_result }), ({ "original melt level", _original_melt_level }), ({ "melt rate", _melt_rate }), ({ "melt counter", _melt_counter }), ({ "callout id", _callout_id }) }); return args; } /* stats() */ /* This section covers all the loading of global variables */ /** * @ignore yes */ mapping int_query_static_auto_load() { return ([ "::" : ::int_query_static_auto_load(), "melt_level" : _melt_level, "melt_result" : _melt_result, "original melt level" : _original_melt_level, "melt rate" : _melt_rate, "melt counter" : _melt_counter, "callout id" : _callout_id ]); } /* int_query_static_auto_load() */ /** * @ignore yes */ mapping query_static_auto_load() { if ( ( base_name( this_object() ) != "/obj/food" ) && !query_continuous() ) { return 0; } return int_query_static_auto_load(); } /* query_static_auto_load() */ /** * @ignore yes */ void init_static_arg( mapping map ) { if ( !mapp( map ) ) { return; } if ( map[ "::" ] ) { ::init_static_arg( map[ "::" ] ); } _melt_level = map[ "melt_level" ]; _melt_result = map[ "melt_result" ]; _original_melt_level = map[ "original melt level" ]; _melt_rate = map[ "melt rate" ]; _melt_counter = map[ "melt counter" ]; _callout_id = map[ "callout id" ]; } /* init_static_arg() */ /** * @ignore yes */ mapping query_dynamic_auto_load() { return ([ "::" : ::query_dynamic_auto_load(), "melt_level" : _melt_level, "melt_result" : _melt_result, "original melt level" : _original_melt_level, "melt rate" : _melt_rate, "melt counter" : _melt_counter, "callout id" : _callout_id ]); } /* query_dynamic_auto_load() */ /** * @ignore yes */ void init_dynamic_arg( mapping map, object ) { if ( !mapp( map ) ) { return; } if ( map[ "::" ] ) { ::init_dynamic_arg( map[ "::" ] ); } _melt_level = map[ "melt_level" ]; _melt_result = map[ "melt_result" ]; _original_melt_level = map[ "original melt level" ]; _melt_rate = map[ "melt rate" ]; _melt_counter = map[ "melt counter" ]; _callout_id = map[ "callout id" ]; } /* init_dynamic_arg() */ /* This is all masked stuff from /obj/food.c which stops frozen foods being liquids, from being dried, from decaying, from being splashed. */ /* Frozen things are not liquids */ /** * @ignore yes */ int query_liquid() { return 0; } /* query_liquid() */ /** * @ignore yes */ void set_liquid() { } /* set_liquid() */ /* do_decay is called by the bits_controller, and, as the frozen item won't decay, does nothing. */ /** * @ignore yes */ void do_decay() { return; } /* do_decay */ /* This frozen food doesn't decay - it melts */ /** * @ignore yes */ int query_decays() { return 0; } /* query_decays() */ /** * @ignore yes */ int query_decay_speed() { return 0; } /* query_decay_speed() */ /** * @ignore yes */ int query_decay_level() { return 0; } /* query_decay_level() */ /** * @ignore yes */ void set_decay_speed( int decay ) { return( ::set_decay_speed( 1 ) ); } /* set_decay_speed() */ /* You cannot cure frozen food. */ /** * @ignore yes */ int do_cure() { return 0; } /** * @ignore yes */ int query_cured() { return 0; } /** * @ignore yes */ int do_dry() { return 0; } /** * @ignore yes */ int query_dried() { return 0; } /* The frozen food won't be rotten. */ /** * @ignore yes */ int query_rotten() { return 0; } /* Can't splash it. */ /** * @ignore yes */ void set_splashable() { return; }