inherit ARMOUR_OBJ; /** * This implements a breakable jewelley. The jewelley breaks into * two parts with an unreadable message on each, when you place the * two back together the message becomes clear. This allows you * to make up those cute breakuable bits of jewelery that only fit * together at one point :) * @started Thu May 14 23:37:14 CST 1998 * @author Pinkfish */ #include <language.h> #include <move_failures.h> string id_num; int broken; mixed *save_read_mess; void set_broken(int flag); int do_break_necklace(); int do_fit_together(object *obs); string query_broken_id(); int query_broken(); void create() { object *obs; save_read_mess = ({ }); do_setup++; ::create(); do_setup--; if ( !do_setup ) { this_object()->setup(); } /* Create a unique id for this thing. */ if (this_player()) { id_num = (string)this_player()->query_name() + time() + "-" + random(12); } else { obs = users(); id_num = (string)obs[random(sizeof(obs))]->query_name() + time() + "-" + random(12); } } /* create() */ /** @ignore yes */ void init() { add_command("break", "<direct:object> in two", (: do_break_necklace :) ); add_command("fit", "<direct:object> together with <indirect:object>", (: do_fit_together :) ); } /* init() */ /** @ignore yes */ string long(string word, int dark) { if (query_broken()) { return ::long(word, dark) + "It looks like half a piece of jewellery, " "you could \"fit\" it back together with " "the other half.\n"; } else { return ::long(word, dark) + "It looks like you could \"break\" the " "jewellery into two matching halves.\n"; } } /* long() */ /** * This method breaks the object into two. It creates an identical * second copy with the message set on, but set as unreadable. * @see query_broken() * @see set_broken() */ int do_break_necklace() { object new_copy; object ob; if (!broken) { /* First duplicate ourselves... */ new_copy = clone_object(base_name(this_object())); new_copy->set_player(player); new_copy->init_static_arg(query_static_auto_load(), player); new_copy->init_dynamic_arg(query_dynamic_auto_load(), player); /* Set the weight as half. */ new_copy->set_weight(query_weight() / 2); set_weight(query_weight() / 2); /* Set the value as half. */ new_copy->set_value(query_value() / 2); set_value(query_value() / 2); /* Set them both as broken. */ new_copy->set_broken(1); set_broken(1); ob = this_object(); while (environment(ob)) { if (new_copy->move(environment(ob)) == MOVE_OK) { break; } ob = environment(ob); } return 1; } return 0; } /* do_break_necklace() */ /** * This fits the two bits of the necklace back together. * @param obs the objects to get the fittable bit from */ int do_fit_together(object *obs) { object ob; if (query_broken()) { foreach (ob in obs) { if (ob != this_object() && ob->query_broken_id() == query_broken_id() && ob->query_broken()) { /* They are the same! */ /* Join them back together. */ set_weight(query_weight() + ob->query_weight()); set_value(query_value() + ob->query_value()); set_cond((query_cond() + ob->query_cond()) / 2); set_broken(0); ob->move("/room/rubbish"); ob->set_broken(0); add_succeeded_mess("$N fit$s $D and $I together.\n", ({ ob })); return 1; } } } add_failed_mess("You cannot fit $D and $I together.\n", obs); return 0; } /* do_fit_together() */ /** * This method sets the broken flag on the object. If the object is * not set as broken then the current set of read messages will * be stored away, so they can be properly mangled when seen * back. * @param flag the new broken flag * @see query_broken() * @see do_break() */ void set_broken(int flag) { if (!broken && flag) { save_read_mess = ::query_read_mess(); set_read_mess( ({ }) ); } else if (broken && !flag) { set_read_mess( save_read_mess + ::query_read_mess() ); save_read_mess = ({ }); } broken = flag; } /* set_broken() */ /** * This method returns the read message, it is overridden here to * do special things to the broken messages. * @return the standard read message array */ mixed *query_read_mess() { mixed *ret; mixed *stuff; int j; ret = ({ }); foreach (stuff in save_read_mess) { stuff = copy(stuff); for (j = 0; j < strlen(stuff[READ_MESS]); j++) { if (stuff[READ_MESS][j] != ' ') { stuff[READ_MESS][j] = '*'; } } ret += ({ stuff }); } /* Put the new messages last... */ ret += ::query_read_mess(); return ret; } /* query_read_mess() */ /** * This method returns the broken flag of the object. * @return the broken flag of the object * @see set_broken() * @see do_break() */ int query_broken() { return broken; } /* query_broken() */ /** * This method returns the id used for the broken object. * @return the unique id of the object */ string query_broken_id() { return id_num; } /* query_broken_id() */ /** @ignore yes */ mapping query_static_auto_load() { if ( base_name( this_object() ) != __FILE__[0..<3]) { return ([ ]); } return ([ "::" : ::int_query_static_auto_load(), ]); } /* query_static_auto_load() */ /** @ignore yes */ void init_static_arg(mapping map) { ::init_static_arg(map["::"]); } /* init_static_arg() */ /** @ignore yes */ mapping query_dynamic_auto_load() { return ([ "::" : ::query_dynamic_auto_load(), "broken" : broken, "saved" : save_read_mess, "id_num" : id_num ]); } /* query_dynamic_auto_load() */ /** @ignore yes */ void init_dynamic_arg(mapping arg) { ::init_dynamic_arg(arg["::"]); broken = arg["broken"]; save_read_mess = arg["saved"]; id_num = arg["id_num"]; } /* init_dynamic_arg() */ /** @ignore yes() */ mixed *stats() { return ::stats() + ({ ({ "broken", broken }), ({ "id", id_num }) }); } /* stats() */