/**
* The library is a sort of information center.
* Currently it supports only the recording on stories about players and
* recording the quests that they have done.
* @author Furball
* @see /include/library.h
*/
#include <quest_handler.h>
#define SHARED 10
#define UNSHARED 90
#define RESTORE_PATH "save/library/"
inherit "/std/object";
int *times;
string player_name, *quests, text_file;
mapping player_quest_info;
nosave mapping qps;
int new_top_quest();
/** @ignore yes */
private void init_data(string pl_name) {
player_name = pl_name;
quests = ({ });
times = ({ });
text_file = "";
player_quest_info = ([ ]);
} /* init_data() */
/** @ignore yes */
private int get_data_file( string name ) {
int success;
if( player_name != name ) {
success = unguarded( (: restore_object, RESTORE_PATH+name[0..0]+"/"+name :) );
if( !success ) {
init_data( name );
}
return success;
}
return 1;
} /* get_data_file() */
/** @ignore yes */
private void save_data_file( string name ) {
unguarded( (: save_object, RESTORE_PATH+name[0..0]+"/"+name :) );
return ;
} /* save_data_file() */
/**
* This method returns the players current title.
* @param name the name of the player
* @return their current title, 0 if no title
* @see /handlers/quest_handler.c
*/
string query_title( string name ) {
get_data_file( name );
if( !quests || !sizeof( quests ) )
return 0;
return (string)QUEST_HANDLER->query_quest_title( choice( quests ) );
} /* query_title() */
/**
* This method returns the set of currently completed quests by the
* player.
* @param name the name of the player
* @return the array of completed quests
*/
string *query_quests( string name ) {
get_data_file(name);
if( !quests )
return ({ });
return quests + ({ });
} /* query_quests() */
/**
* This method returns the most recently completed quest by the player.
* @param name the player name
* @return the most recently completed quest
*/
string get_most_recent_quest( string name ) {
int loop, highest;
string quest_name;
if( !get_data_file(name) )
return "Sorry";
if( !sizeof(quests) )
return "None";
for( highest = loop = 0; loop < sizeof(quests); loop++ ) {
if( times[loop] > highest ) {
highest = times[loop];
quest_name = quests[loop];
}
}
return quest_name;
} /* get_most_recent_quest() */
/**
* This method gets the most recent time a quest was complete by the
* player.
* @param name the name of the player
* @return the time of the most recently completed quest
*/
int get_most_recent_time( string name ) {
int *t;
if( !get_data_file(name) )
return -1;
if( !sizeof(quests) )
return 0;
if( !sizeof( t = sort_array( times, -1 ) ) )
return 0;
return t[0];
} /* get_most_recent_time() */
/**
* This method sets the player as having done the quest and if we
* should give them xp for it
* This function should be called when a quest is finished. It will then
* call the quest_completed function on the quest handler and do all
* assorted modifications to the player object etc. The name should be the
* players name and the quest should be the name of the quest that is
* stored in the quest handler.
* <p>
* The include file <library.h> should be used for calls to this
* handler.
* @return 0 if the quest is already completed
* @see /handlers/quest_handler->quest_completed()
* @param pl_name name of the player
* @param qu_name name of the quest
* @param no_xp do not give out xp
* @example
* // Set the player as completing the womble friend quest, they get
* // xp for it.
* LIBRARAY->set_quest(this_player()->query_name(), "womble friend", 0);
*/
int set_quest(string pl_name, string qu_name, int no_xp) {
int qu_level, qu_xp;
object ob;
// guests can't do quests.
if( find_player(pl_name)->query_property("guest") )
return 0;
// Inactive quests automatically fail.
if( !QUEST_HANDLER->query_quest_status(qu_name) )
return 0;
// clean out the qps cache so that we don't get invalid data.
if( qps && qps[pl_name] )
map_delete( qps, pl_name );
get_data_file( pl_name );
/* Already done the quest? */
if( member_array( qu_name, quests ) != -1 )
return 0;
quests += ({ qu_name });
times += ({ time() });
/* Make sure the quest exists */
qu_level = (int)QUEST_HANDLER->query_quest_level( qu_name );
if( qu_level < 1 )
return 0;
qu_xp = (int)QUEST_HANDLER->query_quest_xp( qu_name );
if( qu_xp < 1 )
qu_xp = qu_level * 10000;
QUEST_HANDLER->quest_completed( pl_name, qu_name, PO );
save_data_file( pl_name );
ob = find_player( pl_name );
if( objectp( ob ) ) {
if( !no_xp ) {
ob->adjust_xp( (qu_xp*UNSHARED/100));
/* The 1 indicates that this xp should be */
/* shared with other team members. */
ob->adjust_xp( qu_xp*SHARED/100, 1 );
}
call_out("save_them", 1, ob );
ob->set_title( "quest",
(string)QUEST_HANDLER->query_quest_title( qu_name ) );
}
return 1;
} /* set_quest() */
/**
* This method removes a quest from the players list of completed quests.
* @param pl_name the player name
* @param qu_name the quest name
* @return 0 if they have not done the quest, 1 if they habe
* @see /handlers/quest_handler.c
*/
int unset_quest( string pl_name, string qu_name ) {
int qu_level, i;
get_data_file( pl_name );
/* haven't done the quest? */
if( ( i = member_array( qu_name, quests ) ) == -1 )
return 0;
/* make sure the quest exists */
qu_level = (int)QUEST_HANDLER->query_quest_level( qu_name );
if( qu_level < 1 )
return 0;
quests -= ({ qu_name });
times -= ({ times[i] });
save_data_file( pl_name );
return 1;
} /* unset_quest() */
/**
* This method causes the player to be saved.
* @param thing the player to save
*/
void save_them( object thing ) {
if( thing )
thing->save();
} /* save_them() */
/**
* This method sets the information related to the players quest.
* This information is used for quests which have several parts to them
* and information needs to be stored about the player as they attempt
* to complete it.
* @param pl_name the name of the player
* @param qu_info the quest name
* @param details the information associated with the quest.
*/
void set_player_quest_info( string pl_name, string qu_info, mixed *details ) {
get_data_file( pl_name );
if( !player_quest_info )
player_quest_info = ([ ]);
player_quest_info[qu_info] = details;
save_data_file(pl_name);
} /* set_player_quest_info() */
/**
* This method returns all the quest information for a player.
* This information is used for quests which have several parts to them
* and information needs to be stored about the player as they attempt
* to complete it. The keys of the mapping are the quest names and the
* values are the information associated with the quest.
* @param pl_name the name of the player
* @return the mapping containing all the quest info
*/
mapping query_all_player_quest_info( string pl_name ) {
get_data_file( pl_name );
if( !player_quest_info )
return 0;
return copy(player_quest_info);
} /* query_all_player_quest_info() */
/**
* This method returns the quest info for a specific quest.
* This information is used for quests which have several parts to them
* and information needs to be stored about the player as they attempt
* to complete it.
* @param pl_name the player name
* @param qu_info the quest name
* @return the information associated with the quest
*/
mixed *query_player_quest_info( string pl_name, string qu_info ) {
get_data_file( pl_name );
if( !player_quest_info )
return 0;
player_quest_info = player_quest_info + ([ ]);
return player_quest_info[qu_info];
} /* query_player_quest_info() */
/**
* This method returns the time at which a quest is completed.
* @param name the name of the player to get the time for
* @param qu_name the name of the quest
* @return the time at which it is completed
*/
int query_quest_time( string name, string qu_name ) {
int time;
if( !get_data_file(name) )
return 0;
time = member_array( qu_name, quests );
if( time < 0 )
return 0;
return times[time];
} /* query_quest_time() */
/**
* This method returns the story associated with the player. This is
* created from all the information about the quests they have done
* joined together into a neato story.
* @param name the player name
* @return the story of the player
* @see /handlers/quest_handler->query_quest_story()
*/
string query_story( string name ) {
string story, quest;
if( !get_data_file(name) )
return "You can find nothing in the library on " + CAP(name) + "\n";
if( text_file != "" )
return unguarded( (: read_file, text_file :) );
if( !sizeof(quests) )
return CAP( player_name )+" has lead a most unadventureous life.\n";
story = "";
foreach( quest in quests )
story += QUEST_HANDLER->query_quest_story( quest )+",\n";
return story;
} /* query_story() */
/**
* This method tells us if the player has completed the quest.
* @param player the name of the player
* @param quest the quest name
* @return 1 if the quest has been done, 0 if it has not
*/
int query_quest_done( string player, string quest ) {
get_data_file(player);
return member_array( quest, quests ) != -1;
} /* query_quest_done() */
/**
* This method returns the current number of quest points gathered
* by the player.
* @param name the player
* @return the current number of quest pointds
* @see /handlers/query_handler->query_quest_level()
*/
int query_quest_points( string name ) {
int points;
string word;
// qps is used to cache the count of quest points since it's expensive and
// queried a lot.
// the reason for storing points+1 is so that someone with 0 points still
// comes up true under the test if(qps[name])
if( !qps )
qps = ([ ]);
if( qps[name] )
return qps[name]-1;
get_data_file( name );
if( !quests || !sizeof( quests ) )
points = 0;
else {
foreach( word in quests )
points += (int)QUEST_HANDLER->query_quest_level( word );
}
qps[name] = points+1;
return points;
} /* query_quest_points() */
/**
* This method is called when a player refreshes totally or gets deleted.
* @param name the player name
* @return 0 if they do not exists, 1 if they do
*/
int restart( string name ) {
if( TP != this_player(1) && PO != find_object("/handlers/refresh") )
return 0;
// clean out the qps cache so that we don't get invalid data.
if( !qps )
qps = ([ ]);
if( !undefinedp( qps[name] ) )
map_delete( qps, name );
player_name = 0;
unguarded( (: rm, RESTORE_PATH+name[0..0]+"/"+name+".o" :) );
return 1;
} /* restart() */