/* -*- LPC -*- */ /* * $Locker: $ * $Id: misc.c,v 1.16 2003/03/07 01:10:01 ceres Exp $ * */ /** * This class contains information relating to the value and the weight * of the object. * @author Pinkfish */ #include <money.h> #include <move_failures.h> #define WATCH_DEFINE "fluff'n'stuff" #define PRICE_INDEX "/obj/handlers/cpi_handler" inherit "/std/basic/light"; inherit "/std/basic/consecrate"; inherit "/std/basic/move"; /* this will also handle value... */ nosave int weight; // People have to ask explicitly for weightlessness nosave int length = 1; nosave int width = 1; nosave int value; nosave mapping value_info; void check_log_status( object *parray ); void create() { weight = 1; light::create(); if(this_object()->query_property(WATCH_DEFINE)) call_out( "check_log_status", 1, previous_object(-1) ); value_info = ([ ]); } /** * This method sets the width to the given amount. * @param w the amount to set the width to * @see query_width() */ void set_width(int w) { width = w; } /** * This method queries the width of an object. The width should be the shorter * side of an object and the length its longer one. Sadly someone chose inches * as the size units. :( * * @param w the amount to set the width to * @see set_width() */ int query_width() { return width; } /** * This method sets the length to the given amount. The length should be the * long side of an object, the width its shorter one. Sadly someone chose * inches as the size units. :( * * @param w the amount to set the length to. * @see query_length() */ void set_length(int l) { length = l; } /** * This method queries the length of an object. * @param w the amount to set the length to * @see set_length() */ int query_length() { return length; } /** * This method adjusts the weight by the given amount. * @param w the amount to change the weight by * @see set_weight() * @see query_weight() */ void adjust_weight(int w) { if (environment()) { environment()->add_weight(w); } weight += w; } /* adjust_weight() */ /** * This method sets the weight of the object. One weight unit * is 50 grams. * <p> * When setting the weights of weapons use the following guide: * <pre> * o===================o=====================o================o * | Weapon | Approx. Weight (kg) | Weight Units | * o===================o=====================o================o * | Dagger | 0.5 | 10 | * | War Hammer | 1.1 | 22 | * | Mace | 1.3 | 26 | * | Flail | 1.5 | 30 | * | Pole Axe | 2.3 | 46 | * | Short Sword | 0.8 | 16 | * | Broad Sword | 1.1 | 22 | * | Long Sword | 1.4 | 28 | * | Bastard Sword | 1.9 | 38 | * | Two-handed Sword | 2.7 | 42 | * o===================o=====================o================o * </pre> * @param w the amount to change the weight by * @see adjust_weight() * @see query_weight() */ void set_weight(int w) { if (environment()) environment()->add_weight(w-weight); weight = w; } /* set_weight() */ /** * This method returns the current weight of the object. * @return the current weight of the object * @see set_weight() * @see adjust_weight() */ int query_weight() { return weight; } /** * This method returns the current weight of the object. It does basicly * the same thing as the previous call. NB: this_object()->query_weight() * is pretty much the same as query_weight(), except it takes shadows into * account. * @return the current weight of the object * @see set_weight() * @see adjust_weight() * @see query_weight() */ int query_complete_weight() { return (int)this_object()->query_weight(); } /** * This method changes the value of the object by a certain number of * coins. The coins can be any type. * @see /obj/handlers/money_handler->query_total_value() * @see adjust_value() * @see query_money_array() * @see set_value() * @return the new value */ varargs int adjust_money(mixed amt, string coin) { if (pointerp(amt)) { value += (int)MONEY_HAND->query_total_value(amt); if (value < 0) { value = 0; } return value; } amt = (int)MONEY_HAND->query_total_value( ({ coin, amt }) ); value += amt; if (value < 0) { value = 0; } return value; } /* adjust_money() */ /** * This method changes the current value of the object. * @param i the amount to change the value by * @return the new value of the object */ int adjust_value(int i) { value += i; return value; } /* adjust_value() */ /** * This method returns the value of the object as a money array. The * money array is a list oif coinages followed by a number of coins. * Eg: <code>({ "copper", 10, "silver", 12 }).</code> * @see /obj/handlers/money_handlers->create_money_array() * @see set_value() * @see adjust_value() * @see adjust_money() * @see query_value() */ mixed *query_money_array() { return (mixed *)MONEY_HAND->create_money_array(value); } /* query_money_array() */ /** * This method returns the number of coins of a certain * type that are in the value of the object. This is not * a good estimate of value or anything, no idea why it is * here really. I am sure I had a good reason * at the time :) * @param type the type of coin to look for * @return the number of coins of that type * @see /obj/handlers/money_handlers->create_money_array() * @see set_value() * @see adjust_value() * @see adjust money() * @see query_money_array() * @see query_value() */ int query_money(string type) { int i; mixed *m_a; m_a = (mixed *)MONEY_HAND->create_money_array(value); i = member_array(type, m_a); if (i == -1) { return 0; } return m_a[i+1]; } /* query_money() */ /** * This method sets the value of the object. The actual value in * coins and so forth is worked out by the money handler based on the * value. * @param number the new value of the object * @see query_value() * @see adjust_value() * @see query_money_array() */ void set_value( int number ) { value = number; } /** * This method sets the value information for a type of * special object. This is the extra value information associated * with the "artifact", "enchantment" or "material" of the object. * @param word the type of value information * @param number the amount to set it to * @see query_value_at() * @see remove_value_info() * @see set_value() */ void set_value_info( string word, int number ) { value_info[ word ] = number; } /* set_value_info */ /** * This method removes the value information for a type of * special object. This is the extra value information associated * with the "artifact", "enchantment" or "material" of the object. * @param word the type of value information to remove * @see query_value_at() * @see set_value_info() * @see set_value() */ void remove_value_info( string word ) { if ( undefinedp( value_info[ word ] ) ) return; value_info = m_delete( value_info, word ); } /* remove_value_info() */ /** * This method returns the current value of the object. * @return the current value of the object */ int query_value() { return value; } /** * This method returns the vase value of the object. This is before * any scaling from things like condition occurs. * @return the base value */ int query_base_value() { return value; } /* query_base_value() */ /** * This method returns the information associated for all the special * bits of the object. The value infor maping ihas keys which are * the type of value info and the value is the value of it. * @return the value info mapping * @see set_value_info() * @see query_value_at() * @see remove_value_info() */ mapping query_value_info() { return value_info; } /** * This method figures out how much an object will cost in a certain * place. For instance at a shop that does not handle artifcacts an * artifact will be bought and sold cheaply. The current types * of "artifact", "enchantment" and "material" are recognised. * A property in the shop of the type "artifact valued" will * cause the values of that type to be taken into account. * @param place the object to find the value at * @return the value in the shop * @see query_value() * @see set_value_info() * @see adjust_value() */ int query_value_at( object place ) { int i, total; string *info; mixed how; if ( !value_info ) { value_info = ([ ]); } total = (int)this_object()->query_value(); info = m_indices( value_info ); for ( i = 0; i < sizeof( info ); i++ ) { how = (mixed)place->query_property( info[ i ] +" valued" ); if ( how ) { switch ( info[ i ] ) { case "artifact" : total += ( value_info[ "artifact" ] * ( how[ 0 ] + how[ 1 ] * (int)this_object()->query_charges() ) ) / how[ 2 ]; break; case "enchantment" : if ( this_object()->query_max_enchant() ) total += ( value_info[ "enchantment" ] * how * (int)this_object()->query_enchant() ) / (int)this_object()->query_max_enchant(); break; case "material" : total += (int)this_object()->query_weight() * (int)PRICE_INDEX->query_price( (string)this_object()-> query_material(), how ); break; default : total += value_info[ info[ i ] ]; } } } return total; } /* query_value_at() */ /** * This method always returns the most expensive value of an item. * This should be used for things like theif quotas and anything which * requires the real actual value of an item. * @param place the place to find the values in */ int query_value_real(string place) { int i; int total; string *info; if ( !value_info ) { value_info = ([ ]); } total = (int)this_object()->query_value(); info = m_indices( value_info ); for ( i = 0; i < sizeof( info ); i++ ) { switch ( info[ i ] ) { case "artifact" : total += ( value_info[ "artifact" ] * ( 3 + 1 * (int)this_object()->query_charges() ) ) / 1; break; case "enchantment" : if ( this_object()->query_max_enchant() ) total += ( value_info[ "enchantment" ] * 10 * (int)this_object()->query_enchant() ) / (int)this_object()->query_max_enchant(); break; case "material" : total += (int)this_object()->query_weight() * (int)PRICE_INDEX->query_price( (string)this_object()-> query_material(), place ); break; default : total += value_info[ info[ i ] ]; break; } } return total; } /* query_value_real() */ /** @ignore yes */ varargs int move( mixed dest, string messin, string messout ) { int i, w; object from; if( stringp(dest) ) { if ( strsrch( dest , "#") != -1 ) dest = find_object(dest); else dest = load_object(dest); } if(!dest) return MOVE_INVALID_DEST; w = (int)this_object()->query_complete_weight(); if(!(dest->add_weight(w))) return MOVE_TOO_HEAVY; from = environment(); i = ::move(dest, messin, messout); if(i != MOVE_OK) { dest->add_weight(-w); return i; } if(from) from->add_weight(-w); if(query_light_needs_inform()) { if(from) inform_of_light_level_change(from); inform_of_light_level_change(dest); } return i; } /** @ignore yes */ void dest_me() { if ( environment() ) { environment()->add_weight( -(int)this_object()->query_complete_weight() ); if ( query_my_light() ) adjust_light( -query_my_light() ); } ::dest_me(); } /* dest_me() */ /** @ignore yes */ mixed *stats() { int i; string *info; mixed *guff; guff = ({ ({ "value", value }) }); if ( !value_info ) value_info = ([ ]); info = m_indices( value_info ); for ( i = 0; i < sizeof( info ); i++ ) guff += ({ ({ "(info) "+ info[ i ], value_info[ info[ i ] ] }) }); return light::stats() + consecrate::stats() + guff; } /* stats() */ /** @ignore yes */ // Monitor for people passing around items that they shouldn't be. void check_log_status( object *parray ) { if ( this_object()->query_property( WATCH_DEFINE ) && clonep( this_object() ) && arrayp( parray ) && member_array(load_object("/secure/cmds/creator/cl_one"), parray) != -1){ log_file( "WATCH", "%s TO: %s. TP: %s.\n", ctime(time()), base_name( this_object() ), parray[2]->query_name() ); this_object()->add_property( "CT", time() ); user_event( "inform", sprintf( "[Restricted] %s cloned %s.", parray[2]->query_cap_name(), base_name( this_object() ) ), "cheat" ); } }