/**
* This is the clothing file. Contains everything you need to
* make some nice clothing.
*/
#include <move_failures.h>
// defines for scabbards, reusing pocket variables.
#define SHEATH pocket_mess
#define TYPES pockets
#define SCABBARD biggest
inherit "/std/container";
inherit "/std/basic/wearable";
inherit "/std/basic/close_lock";
string pocket_mess;
mixed pockets;
int biggest;
/** @ignore yes */
private void make_scabbard();
void create() {
do_setup++;
container::create();
wearable::create();
close_lock::create();
set_stuck(1);
set_can_export_inventory();
add_alias("clothing");
add_plural("clothes");
add_immune_to("blunt");
set_opaque();
if( !query_property("shop type") )
add_property("shop type", "haberdashery");
do_setup--;
if( !do_setup )
TO->setup();
} /* create() */
/**
* This method makes the clothing object a clothing-scabbard,
* which means it will be fixable by 'mend' etc.
* It will allow to have sheathes for daggers inside bras etc.
* @see query_scabbard()
* @see query_clothing()
* @see set_types()
* @see query_types()
* @see set_no_weapons_allowed()
* @see query_no_weapons_allowed()
* @see test_type_ok()
*/
void set_clothing_scabbard() {
SCABBARD = -2;
add_property("shop type", "haberdashery");
add_immune_to("blunt");
add_alias("clothing");
add_plural("clothes");
} /* set_clothing_scabbard() */
/**
* This method determines if the object is a scabbard or not.
* @return returns 1 for a scabbard
* @see query_clothing()
* @see set_types()
* @see query_types()
* @see set_no_weapons_allowed()
* @see query_no_weapons_allowed()
* @see set_clothing_scabbard()
* @see test_type_ok()
*/
int query_scabbard() { return SCABBARD < 0 && sizeof(TYPES); }
/**
* This method will return true if the item is an item of clothing.
* @return returns true if it's a clothing item
* @see /obj/clothing->query_clothing()
* @see query_scabbard()
* @see set_types()
* @see query_types()
* @see set_no_weapons_allowed()
* @see query_no_weapons_allowed()
* @see set_clothing_scabbard()
* @see test_type_ok()
*/
int query_clothing() { return SCABBARD != -1; }
/**
* This method sets the number of weapons allowed into the scabbard.
* @param i the number of weapons allowed into the scabbard
* @see query_scabbard()
* @see query_clothing()
* @see set_types()
* @see query_types()
* @see query_no_weapons_allowed()
* @see set_clothing_scabbard()
* @see test_type_ok()
*/
void set_no_weapons_allowed( int i ) {
if( i == 1 )
remove_property("_NWA_");
else if( i > 0 )
add_property("_NWA_", i );
else
return;
call_out( (: make_scabbard :), 0 );
} /* set_no_weapons_allowed() */
/**
* This method returns the number of weapons allowed into the scabbard.
* @return the number of weapons allowed into the scabbard.
* @see query_scabbard()
* @see query_clothing()
* @see set_types()
* @see query_types()
* @see set_no_weapons_allowed()
* @see set_clothing_scabbard()
* @see test_type_ok()
*/
int query_no_weapons_allowed() { return query_property("_NWA_"); }
/**
* This method returns the types of weapons that can be
* sheathed in the scabbard.
* @return the types that can be sheathed
* @see query_scabbard()
* @see query_clothing()
* @see set_types()
* @see set_no_weapons_allowed()
* @see query_no_weapons_allowed()
* @see set_clothing_scabbard()
* @see test_type_ok()
*/
string *query_types() { return ( query_scabbard() ? TYPES : ({ }) ); }
/**
* This method returns the message associated with the scabbard.
* @param flag if the flag is set then the message will be
* constructed without the "It could sheath" bit.
* @return the message associated with the scabbard
* @see query_scabbard()
*/
varargs string query_scabbard_mess( int flag ) {
if( query_scabbard() ) {
int num;
string mess;
if( !num = query_no_weapons_allowed() )
num = 1;
mess = "";
if( !flag )
mess += ({"It", "They"})[query_group(TO)]+" could sheath ";
switch( sizeof(TYPES) ) {
case 0 :
return "";
case 1 :
return mess + ( num > 1 ? query_num(num)+" "+pluralize(TYPES[0]) :
add_a(TYPES[0]) )+( !flag ? ".\n" : "");
case 2 :
return mess + ( num > 1 ? query_num(num)+" "+pluralize(TYPES[0]) :
add_a(TYPES[0]) )+" or "+( num > 1 ? pluralize(TYPES[1]) :
add_a(TYPES[1]) )+( !flag ? ".\n" : "");
default :
return mess + ( num > 1 ? query_num(num)+" "+
implode( map( TYPES[1..], (: pluralize($1) :) ), ", ") :
implode( map( TYPES[1..], (: add_a($1) :) ), ", ") )+" or "+
( num > 1 ? pluralize( TYPES[0] ) : add_a(TYPES[0]) )+
( !flag ? ".\n" : "");
}
}
return "";
} /* query_scabbard_mess() */
/** @ignore yes */
private void make_scabbard() {
add_alias("scabbard");
add_plural("scabbards");
if( SCABBARD == -1 ) {
add_property("shop type", "armoury");
remove_immune_to("blunt");
remove_alias("clothing");
remove_plural("clothes");
}
SHEATH = query_scabbard_mess();
} /* make_scabbard() */
/**
* This method sets the types of weapons that can be
* sheathed in the scabbard.
* @param words the array of types that can be sheathed
* @see query_scabbard()
* @see query_clothing()
* @see query_types()
* @see set_no_weapons_allowed()
* @see query_no_weapons_allowed()
* @see set_clothing_scabbard()
* @see test_type_ok()
*/
void set_types( string *words ) {
TYPES = words;
if( SCABBARD > -1 )
SCABBARD = -1;
call_out( (: make_scabbard :), 0 );
} /* set_types() */
/** @ignore yes */
string long( string word, int dark ) {
int i;
string ret, *sizes;
mapping types;
ret = container::long( word, dark );
if( dark == 2 || dark == -2 )
return container::long( word, dark );
if( query_scabbard() ) {
i = query_group(TO);
return container::long( word, dark ) + SHEATH +
query_contents( ( !i ? "It" : "They" )+" contain"+
( i ? "" : "s" )+": " ) + wearable::long( word, dark );
}
if( sizeof( pockets ) && !dark ) {
types = ([ ]);
for( i = 0; i < sizeof( pockets ); i += 2 )
types[ pockets[ i ] ]++;
sizes = keys( types );
sizes = map( sizes, (: query_num($2[$1]) + " " + $1 + " pocket"+
( $2[$1] > 1 ? "s" : "" ) :), types );
i = query_group(TO);
ret += "$C$"+the_short()+" has "+query_multiple_short( sizes )+".\n"+
query_contents( ( !i ? "It" : "They" )+" contain"+
( i ? "" : "s" )+": " );
ret += close_lock::long_status();
}
return ret + wearable::long( word, dark );
} /* long() */
/** @ignore yes */
varargs string pretty_short( object thing ) {
return close_lock::short_status() + ::pretty_short( thing );
} /* pretty_short() */
/** @ignore yes */
varargs string pretty_plural( object thing ) {
return close_lock::short_status() + ::pretty_plural( thing );
} /* pretty_plural() */
/**
* This method returns the message associated with the pocket.
* @return the message associated with the pocket
* @see set_pocket_mess()
* @see query_pockets()
* @see add_pocket()
*/
string query_pocket_mess() {
return ( !query_scabbard() ? pocket_mess : "" );
} /* query_pocket_mess() */
/**
* This method sets the message associated with the pocket.
* @param words the message associated with the pocket
* @see query_pocket_mess()
* @see add_pocket()
*/
void set_pocket_mess( string words ) {
if( !query_scabbard() )
pocket_mess = words;
} /* set_pocket_mess() */
/**
* This method returns all the pockets on the object.
* @return all the pockets on the object
* @see add_pocket()
*/
mixed query_pockets() {
return ( !query_scabbard() && sizeof(pockets) ? pockets : ({ }) );
} /* query_pockets() */
/**
* This method adds a pocket onto the clothing.
* @param type the type of pocket
* @param amount the amount the pocket can hold
* @see query_pockets()
* @see set_pocket_mess()
* @see query_pocket_mess()
*/
void add_pocket( string type, int amount ) {
if( !type || type == "" || amount < 1 || query_scabbard() )
return;
if( !pocket_mess )
pocket_mess = "a pocket in $ob_short$";
if( !pointerp( pockets ) )
pockets = ({ });
pockets += ({ type, amount });
max_weight += amount;
if( amount > biggest )
biggest = amount;
} /* add_pocket() */
/**
* This method queries whether or not this weapon
* can be sheathed in the scabbard.
* @param thing the weapon to test
* @param flag the move flag (see test_add)
* @return 1 if the weapon can be sheathed in the scabbard, 0 if not
* @see query_scabbard()
* @see query_clothing()
* @see set_types()
* @see query_types()
* @see set_no_weapons_allowed()
* @see query_no_weapons_allowed()
* @see set_clothing_scabbard()
*/
int test_type_ok( object thing, int flag, int test ) {
string word;
int i;
if( !ENV( thing ) || !query_scabbard() )
return ::test_add( thing, flag );
foreach( word in TYPES )
if( sizeof( match_object_in_array( word, ({ thing }) )->objects ) ) {
if( !test ) {
if( !i = query_no_weapons_allowed() )
i = 1;
if( sizeof( INV(TO) ) >= i ) {
write( the_short()+" already holds "+
query_multiple_short( INV(TO) )+".\n");
return 0;
}
if( TO->can_not_sheathe( thing ) )
return 0;
}
return ::test_add( thing, flag );
}
if( !test )
write( thing->the_short()+" doesn't fit very well in "+
the_short()+". "+SHEATH );
return 0;
} /* test_type_ok() */
/** @ignore yes */
int test_add( object thing, int flag ) {
int i;
// no pockets nor scabbard types.
if( !sizeof( pockets ) || flag )
return 0;
if( query_scabbard() )
return test_type_ok( thing, flag, 0 );
if( !ENV( thing ) )
return 1;
if( !biggest ) {
for( i = 0; i < sizeof( pockets ); i+= 2 ) {
if( pockets[ i + 1 ] > biggest )
biggest = pockets[ i + 1 ];
}
}
if( (int)thing->query_complete_weight() > biggest )
return write( (string)thing->the_short() +" is too big "+
"to fit in any of "+the_short()+"'s pockets.\n" );
return 1;
} /* test_add() */
/** @ignore yes */
int query_ac( string type, int amount ) {
do_damage( type, amount );
return 0;
} /* query_ac() */
/**
* This method sets up the condition for the clothing.
* @param number the maximum condition for the clothing
*/
void setup_clothing( int number ) {
set_max_cond( number );
set_cond( number );
set_lowest_cond( number );
} /* setup_clothing() */
/** @ignore yes */
int query_value() { return modify_value( container::query_value() ); }
/** @ignore yes */
int query_full_value() { return container::query_value(); }
/** @ignore yes */
int drop( mixed stuff ) {
if( worn_by && living( worn_by ) )
return 1;
return container::drop(stuff);
} /* drop() */
/** @ignore yes */
varargs int move( mixed dest, string messin, string messout ) {
int flag;
object from;
from = ENV(TO);
flag = container::move( dest, messin, messout );
if( !flag && worn_by ) {
set_worn_by( 0 );
if( from )
from->remove_inventory_container(TO);
if( ENV(TO) )
ENV(TO)->add_inventory_container(TO);
}
return flag;
} /* move() */
/** @ignore yes */
void dest_me() {
set_worn_by( 0 );
container::dest_me();
} /* dest_me() */
/**
* This method causes the object to be broken.
*/
void break_me() {
if( worn_by )
INV(TO)->move( ENV( worn_by ), "$N fall$s from "+a_short()+".");
else
INV(TO)->move( ENV(TO), "$N fall$s out of "+a_short()+".");
::break_me();
} /* break_me() */
/** @ignore yes */
mixed stats() {
mixed i, ret;
ret = container::stats() + wearable::stats();
if( query_scabbard() && sizeof(TYPES) ) {
foreach( i in TYPES )
ret += ({ ({ "scabbard type", i }) });
} else if( sizeof(pockets) )
for( i = 0; i < sizeof( pockets ); i += 2 )
ret += ({ ({ pockets[ i ] +" pocket", pockets[ i + 1 ] }) });
return ret;
} /* stats() */
/** @ignore yes */
mapping int_query_static_auto_load() {
mapping map;
map = ([
"::" : container::int_query_static_auto_load(),
"wear" : wearable::query_static_auto_load(),
]);
if( sizeof(pockets) )
map["pockets"] = pockets;
if( pocket_mess )
map["pocket mess"] = pocket_mess;
if( query_transparent() )
map["trans"] = query_transparent();
map["stuck"] = query_stuck();
if( query_difficulty() )
map["difficulty"] = query_difficulty();
if( query_key() )
map["key"] = query_key();
if( query_open_trap_func() )
map["trap open func"] = query_open_trap_func();
if( query_lock_trap_func() )
map["trap lock func"] = query_lock_trap_func();
if( query_open_trap_ob() )
map["trap open ob"] = query_open_trap_ob();
if( query_lock_trap_ob() )
map["trap lock ob"] = query_lock_trap_ob();
if( biggest < 0 )
map["biggest"] = biggest;
return map;
} /* int_query_static_auto_load() */
/** @ignore yes */
mapping query_static_auto_load() {
if( base_name(TO) != __FILE__[0..<3] )
return ([ ]);
return int_query_static_auto_load();
} /* query_static_auto_load() */
/** @ignore yes */
mapping query_dynamic_auto_load() {
mapping map;
map = ([
"::" : container::query_dynamic_auto_load(),
"wear" : wearable::query_dynamic_auto_load(),
]);
if( query_locked() )
map["locked"] = query_locked();
if( query_closed() )
map["closed"] = query_closed();
return map;
} /* query_dynamic_auto_load() */
/** @ignore yes */
void init_static_arg( mapping map ) {
if( !mapp( map ) )
return;
if( map[ "::" ] )
container::init_static_arg( map[ "::" ] );
if( map[ "wear" ] )
wearable::init_static_arg( map[ "wear" ] );
if( map[ "pocket mess" ] )
pocket_mess = map[ "pocket mess" ];
if( map[ "pockets" ] )
pockets = map[ "pockets" ];
if( map["trans"] )
set_transparent();
else
set_opaque();
if( map["difficulty"] )
set_difficulty( map["difficulty"] );
if( map["key"] )
set_key( map["key"] );
if( map["trap open func"] )
set_open_trap( map["trap open ob"], map["trap open func"] );
if( map["trap lock func"] )
set_lock_trap( map["trap lock ob"], map["trap lock func"] );
if( !undefinedp( map["stuck"] ) )
set_stuck( map["stuck"] );
if( map["biggest"] )
biggest = map["biggest"];
if( SCABBARD == -2 )
add_immune_to("blunt");
// call out because of the properties.
if( query_scabbard() )
call_out( (: make_scabbard :), 0 );
} /* init_static_arg() */
/** @ignore yes */
void init_dynamic_arg( mapping map ) {
if( map[ "::" ] )
container::init_dynamic_arg( map["::"] );
if( map[ "wear" ] )
wearable::init_dynamic_arg( map["wear"] );
if( map[ "locked" ] )
set_locked();
else
set_unlocked();
if( map["closed" ] )
set_closed();
else
set_open();
} /* init_dynamic_arg() */