/**
* This method keeps track of all the messages on the object for
* reading etc. Keeps track of the language, the text and the
* size.
* @author Pinkfish
*/
#include <language.h>
inherit "/std/basic/desc";
private nosave mixed _read_mess = ({ });
private nosave int _max_size = 100;
private nosave int _cur_size;
nosave mapping describe;
/**
* This method sets the maximum amount of writing that can be
* placed onto the object.
* @param siz the maximum size
* @see query_max_size()
* @see add_read_mess()
*/
void set_max_size(int siz) { _max_size = siz; }
/**
* This method returns the current maximum text size of the object.
* @return the current maximum text size
* @see set_max_size()
* @see add_read_mess()
*/
int query_max_size() { return _max_size; }
/** @ignore yes */
private int internal_text_size( string lang, string str, int size ) {
return size * ( sizeof(str) *
(int)LANGUAGE_H->query_language_size( lang ) / 10 );
} /* internal_text_size() */
/**
* This method sets the size of the current amount of writing
* on the object.
* @see set_max_size()
* @see add_read_mess()
* @see query_cur_size()
* @param siz the new current size
*/
void set_cur_size(int siz) { _cur_size = siz; }
/**
* This method returns the size of the current amount of writing
* on the object.
* @see set_max_size()
* @see add_read_mess()
* @see set_cur_size()
* @return the current amount of writing on the object
*/
int query_cur_size() {
int i, j;
if( _cur_size < 1 && ( j = sizeof( _read_mess ) ) ) {
for( i = 0, _cur_size = 0; i < j; i++ )
_cur_size += internal_text_size( _read_mess[i][READ_LANG],
_read_mess[i][READ_MESS], _read_mess[i][READ_SIZE] );
}
return _cur_size;
} /* query_cur_size() */
/**
* Calling this is very rude unless you are creating the object as it
* erases all of the writing off it!
*/
varargs void set_read_mess( mixed str, string lang, int size ) {
_cur_size = 0;
if( pointerp( str ) ) {
_read_mess = str;
} else {
if( !lang )
lang = "common";
if( !size )
size = 1;
_read_mess = ( str ? ({ ({ str, 0, lang, size }) }) : ({ }) );
}
} /* set_read_mess() */
/**
* This method returns the current read messae array on the object.
* The returned array consists of an array of arrays. The internal
* array has 4 elements, the first is the text of the message
* the second is the type of the message, the third is the language
* and the last element is the size of the writing.
*<p>
* The defines in the file /include/language.h should be used
* for the indexes into this array.
* @return the read message array
* @see add_read_mess()
* @see set_max_size()
* @see /include/language.h
*/
mixed query_read_mess() { return copy( _read_mess ); }
/**
* This method queries whether or not the specified text
* fits on this object. The arguments to this function are
* identical to those of add_read_mess().
* @return 1 if the text fits on the object, 0 if not
*/
int test_add_read_mess( string str, string type, string lang, int size ) {
// Use query_cur_size() so that _cur_size will be accurate,
// as it is not saved - Sandoz.
if( query_cur_size() >= _max_size )
return 0;
if( !sizeof(str) )
return 1;
if( !size )
size = 1;
if( !lang )
lang = "common";
return ( _cur_size + internal_text_size( lang, str, size ) <= _max_size );
} /* test_add_read_mess() */
/**
* This method adds a new read message onto the object.
* <p>
* The str bit is the actual string to add, it is the message which
* will get printed. The type is the type of the writing, like "spidery
* writing" or "charcoal based letters". The language is the
* language in which it is written and the size is the size of the
* letters (standard handwriting should be of size 1).
* The size is used to see if the writing can fit on the page.
* <p>
* If no language is given, the default is "common". If no type is
* given, then no type bit is printed and if no size is specified then
* a size of 1 is the default.
* <p>
* This also adjusts the size of stuff on the object. If too much
* is attempted to be written on the object, the remainder will be
* cut off.
* @param str the text of the message
* @param type the type of the message
* @param lang the language the message is in
* @param size the size of the message
* @return the text that was successfully written onto the object
* @see query_read_mess()
* @see set_max_size()
* @see /handlers/language->query_language_size()
* @see /handlers/language->squidge_text()
*/
varargs string add_read_mess( string str, string type, string lang, int size ) {
int i;
// Use query_cur_size() so that _cur_size will be accurate,
// as it is not saved - Sandoz.
if( query_cur_size() >= _max_size || !sizeof(str) )
return "";
if( !size )
size = 1;
if( !lang )
lang = "common";
i = internal_text_size( lang, str, size );
if( _cur_size + i > _max_size ) {
str = (string)LANGUAGE_H->squidge_text( lang, str,
( _max_size - _cur_size - size ) * 10 / size );
if( !i = strlen(str) )
return "";
_cur_size += internal_text_size( lang, str, size );
} else {
_cur_size += i;
}
_read_mess += ({ ({ str, type, lang, size }) });
return str;
} /* add_read_mess() */
/**
* This method removes a piece of writing off the object.
* <p>
* If you know the actual message or the language or the type you can remove
* that message.
*<p>
* Using the type and or language is a very dodgy way of doing this. Using
* a combination is much better.
* <p>
* Any of the parameters set to a non-zero value will be used for the search.
* @param str the text string
* @see /handlers/language->query_language_size()
* @see add_read_mess()
* @see query_read_mess()
* @param type the type of the text
* @param lang the language it is written in
* @return 0 if the text was not found, 1 if it was
*/
int remove_read_mess( string str, string type, string lang ) {
int i;
for( i = 0; i < sizeof(_read_mess); i++ ) {
if( str && _read_mess[i][READ_MESS] != str )
continue;
if( type && _read_mess[i][READ_TYPE] != type )
continue;
if( lang && _read_mess[i][READ_LANG] != lang )
continue;
// Use query_cur_size() so that _cur_size will be accurate,
// as it is not saved - Sandoz.
_cur_size = query_cur_size() - internal_text_size(
_read_mess[i][READ_LANG], _read_mess[i][READ_MESS],
_read_mess[i][READ_SIZE] );
_read_mess = delete( _read_mess, i, 1 );
return 1;
}
return 0;
} /* remove_read_mess() */
/**
* This method returns the read message for the object. This is what should
* be displayed to the player if they attempt to read this object.
* @return the read message, 0 if there is none
*/
string query_readable_message( object player, int dummy ) {
string message, type, lang, *sigs;
mixed mess, bit, read_mess;
if( !sizeof( read_mess = query_read_mess() ) )
return 0;
message = "";
sigs = ({ });
foreach( bit in read_mess ) {
mess = bit[ READ_MESS ];
type = bit[ READ_TYPE ];
lang = bit[ READ_LANG ];
if( functionp( mess ) )
mess = evaluate( mess );
if( stringp( mess ) && sscanf( mess, "$$%s$$", mess ) ) {
if( !mess = unguarded( (: read_file, mess+".txt" :) ) )
mess = "Warning: text file cannot be read!";
}
if( type == "signature") {
sigs += ({ mess });
continue;
}
mess = LANGUAGES->garble_text( lang, mess, TO, TP );
if( !LANGUAGES->query_language_magic( lang ) ) {
mess = "Text "+( type == "printing" ? "printed" : "written")+
( type && type != "printing" ? " in "+type : "")+
( lang ? " in "+lang : "")+":\n"+
indent( mess, 3, TP->query_cols() )+"\n";
}
message += mess;
}
if( sizeof(sigs) )
message += "\n"+( query_group(TO) ? "They bear ": "It bears ")+
query_multiple_short(sigs)+".\n";
return message;
} /* query_readable_mesage() */
/**
* This method returns the short description to use with the reading.
* It will go: You read <read short>:
* <p>
* It will automaticly add a $name$ onto the end of the string for you.
* This will be replaced with the correct a/the short for the message
* which is printed.
* @param player the player reading the message
*/
string query_read_short( object player, int dummy ) {
string id, *read_mess;
if( !sizeof( read_mess = query_read_mess() ) )
return 0;
if( id = TO->query_property("read id") )
id += " $name$";
else
id = "$name$";
return id;
} /* query_read_short() */
/**
* This method adds details for an item.
* @param d_name the name(s) of the detail
* @param mess the descripton of the item
*/
void add_detail( mixed d_name, string mess ) {
if( pointerp(d_name) ) {
foreach( string detail in d_name )
add_detail( detail, mess );
return;
}
if( !describe )
describe = ([ ]);
describe += ([ d_name: mess ]);
} /* add_detail() */
/**
* This method returns the current value of the detail for an item.
* @param str the detail to get
* @return the detail for an item
*/
string query_detail( string str ) {
string key, name, *bits, *adjs;
if( !mapp(describe) )
return 0;
if( describe[str] )
return describe[str];
bits = explode( str, " ");
adjs = bits[0..<2];
str = bits[<1];
foreach( key in keys(describe) ) {
bits = explode( key, " ");
name = bits[<1];
if( str == name || str == pluralize(name) ) {
if( !sizeof(adjs) )
return describe[key];
if( !sizeof( bits = bits[0..<2] ) )
continue;
if( !sizeof( filter( adjs, (: member_array( $1, $2 ) == -1 :),
bits ) ) )
return describe[key];
}
}
return 0;
} /* query_detail() */