/* -*- LPC -*- */
/*
* $Locker: $
* $Id: quest_handler.c,v 1.9 2000/07/29 14:49:21 taffyd Exp $
* $Log: quest_handler.c,v $
* Revision 1.9 2000/07/29 14:49:21 taffyd
* Actually did what I said I did in 1.7 ;)
*
* Revision 1.8 2000/07/29 14:40:33 taffyd
* Changed logging so that if there is no this_player() it uses
previous_object(). So that the web interface to the quests command works.
*
* Revision 1.7 2000/07/29 14:34:29 presto
* Forcibly unlocked by taffyd
*
* Revision 1.6 2000/07/29 02:18:20 pinkfish
* Forcibly unlocked by presto
*
* Revision 1.5 2000/03/17 20:55:07 ceres
* Removed references to the old team handler
*
* Revision 1.4 1999/09/27 21:19:29 wodan
* fixed ancient bug in query_fame_str and removed line that did nothing.
*
* Revision 1.3 1999/09/27 21:13:25 terano
* Got it working.
*
* Revision 1.2 1999/05/20 01:02:27 ceres
* Added status for quests
*
* Revision 1.1 1998/01/06 05:03:33 ceres
* Initial revision
*
*/
/**
* This class keeps track of the current set of quests availabe in the
* game.
* @author Furball
*/
#include <player_handler.h>
#define LIBRARY "/obj/handlers/nlibrary"
#define QUEST_LOG "QUESTS"
#define SAVE_FILE "/save/quests"
#define BACKUP_FILE "/save/quests/quests"
inherit "/std/object";
private int *quest_level;
private int *num_times_done;
private int *quest_status;
private string *quest_name;
private string *quest_title;
private string *quest_story;
private string *last_done_by;
private nosave int total_qp;
/**
* This method reloads the quests from the save file.
* @see save_quests()
*/
void load_quests() { unguarded( (: restore_object, SAVE_FILE :) ); }
/**
* This method saves the current set of quests to the save file.
* @see load_quests()
*/
void save_quests() { unguarded( (: save_object, SAVE_FILE :) ); }
void create() {
int i;
::create();
load_quests();
if ( !quest_name ) {
quest_name = ({ });
}
if ( !quest_level ) {
quest_level = ({ });
}
if ( !quest_title ) {
quest_title = ({ });
}
if ( !quest_story ) {
quest_story = ({ });
}
if ( !last_done_by ) {
last_done_by = ({ });
}
if ( !num_times_done ) {
num_times_done = ({ });
}
if ( !quest_status ) {
if(sizeof(quest_name)) {
quest_status = allocate(sizeof(quest_name));
for(i=0; i<sizeof(quest_name); i++) {
quest_status[i] = 1;
}
} else {
quest_status = ({ });
}
}
for(i = 0; i<sizeof(quest_level); i++) {
if(quest_status[i]) {
total_qp += quest_level[i];
}
}
} /* create() */
/**
* This returns the current total gp for all of the current quests.
* @return the total gp
*/
int query_total_qp() { return total_qp; }
/**
* This method adds a new quest into the system. You only need to call
* this ONCE. The name of the quest must be unique. The story is
* what can be seen in the players books about the player.
* @param name the name of the quest
* @param level the level of the quest 0-100
* @param title the title for finishing the quest, 0 for none
* @param story the story about the quest
* @return 1 if successful, 0 if not
* @see delete_quest()
* @see query_quest_level()
* @see query_quest_title()
* @see query_quest_story()
*/
int add_quest( string name, int level, string title, string story ) {
string log_name;
if ( member_array( name, quest_name ) != -1 )
return 0;
quest_name += ({ name });
quest_level += ({ level });
quest_title += ({ title });
quest_story += ({ story });
last_done_by += ({ "nobody" });
num_times_done += ({ 0 });
quest_status += ({ 1 }); //Make it active!
if ( this_player() ) {
log_name = this_player()->query_name();
}
else {
log_name = file_name( previous_object() );
}
log_file( QUEST_LOG, log_name +
" added: "+ name +", "+ level +", "+ title +", "+ story +"\n" );
save_quests();
unguarded( (: cp, SAVE_FILE +".o", BACKUP_FILE +"."+ time() :) );
total_qp += level;
return 1;
} /* add_quest() */
/**
* Change the status of a quest from active to inactive
* and vice versa.
* @param the name of a quest.
*/
int change_quest_status(string name) {
int temp;
temp = member_array(name, quest_name);
if(temp == -1) {
return -1;
}
quest_status[temp] = !quest_status[temp];
return quest_status[temp];
}
/**
* This method returns the status of a quest.
* @param the name of a quest
* @return 1 for active, 0 for inactive.
*/
int query_quest_status(string name) {
int temp;
temp = member_array(name, quest_name);
if(temp == -1) {
return -1;
}
return quest_status[temp];
}
/**
* This method returns the level of the quest.
* @param name the name of the quest
* @return the level of the quest, -1 on failure
* @see add_quest()
* @see set_quest_level()
*/
int query_quest_level(string name) {
int temp;
temp = member_array(name, quest_name);
if(temp == -1) {
return -1;
}
return quest_level[temp];
} /* query_quest_level() */
/**
* This method sets the level of the quest.
* @param name the name of the quest
* @param level the level of the quest
* @return 0 on failure, 1 on success
* @see add_quest()
* @see query_quest_level()
*/
int set_quest_level(string name, int level) {
int temp;
string log_name;
temp = member_array(name, quest_name);
if(temp == -1) {
return 0;
}
if ( this_player() ) {
log_name = this_player()->query_name();
}
else {
log_name = file_name( previous_object() );
}
log_file(QUEST_LOG, "%s : level set for %s to %d\n\n",
log_name, name, level);
quest_level[ temp ] = level;
save_quests();
return 1;
} /* set_quest_level() */
/**
* This method returns the story associated with the quest.
* @param name of the quest
* @return the story of the quest
* @see add_quest()
* @see set_quest_story()
*/
string query_quest_story(string name) {
int temp;
temp = member_array(name, quest_name);
if(temp == -1) {
return "did nothing";
}
return quest_story[temp];
} /* query_quest_story() */
/**
* This method sets the story associated with the quest.
* @param name of the quest
* @param story the new story of the quest
* @see add_quest()
* @see query_quest_story()
*/
int set_quest_story(string name, string story) {
int temp;
string log_name;
temp = member_array(name, quest_name);
if(temp == -1) {
return 0;
}
if ( this_player() ) {
log_name = this_player()->query_name();
}
else {
log_name = file_name( previous_object() );
}
log_file(QUEST_LOG, "%s : story set for %s to %s\n\n",
log_name, name, story);
quest_story[ temp ] = story;
save_quests();
return 1;
} /* set_quest_story() */
/**
* This method returns the title associated with the quest.
* @param name of the quest
* @return the title of the quest
* @see add_quest()
* @see set_quest_title()
*/
string query_quest_title(string name) {
int temp;
temp = member_array(name, quest_name);
if(temp == -1 || quest_title[temp] == "") {
return "Unknown Quester";
}
return quest_title[temp];
} /* query_quest_title() */
/**
* This method sets the title associated with the quest.
* @param name of the quest
* @param title the new title of the quest
* @see add_quest()
* @see query_quest_title()
*/
int set_quest_title(string name, string title) {
int temp;
string log_name;
temp = member_array(name, quest_name);
if(temp == -1) {
return 0;
}
if ( this_player() ) {
log_name = this_player()->query_name();
}
else {
log_name = file_name( previous_object() );
}
log_file(QUEST_LOG, "%s : title set for %s to %s\n\n",
log_name, name, title);
quest_title[ temp ] = title;
save_quests();
return 1;
} /* set_quest_title() */
/**
* This method returns the number of times the quest has been
* completed.
* @param name thre name of the quest
* @return the number of times completed
* @see quest_completed()
* @see add_quest()
* @see query_quest_done()
*/
int query_quest_times( string name ) {
int i;
i = member_array( name, quest_name );
if ( i == -1 )
return -1;
return num_times_done[ i ];
} /* query_quest_times() */
/**
* This method returns the name of the last person to complete the
* quest.
* @param name thre name of the quest
* @return the last person to complete the quest
* @see quest_completed()
* @see add_quest()
* @see query_quest_times()
*/
mixed query_quest_done( string name ) {
int i;
i = member_array( name, quest_name );
if ( i == -1 )
return -1;
return last_done_by[ i ];
} /* query_quest_done() */
/**
* This method removes the given quest from the system.
* @see name the name of the quest to remove
* @return 0 on failure, 1 on success
* @see add_quest()
*/
int delete_quest(string name) {
int temp;
string log_name;
if ( this_player() ) {
log_name = this_player()->query_name();
}
else {
log_name = file_name( previous_object() );
}
log_file(QUEST_LOG, log_name + " removed : " +
name + "\n\n");
temp = member_array(name, quest_name);
if(temp == -1) {
return 0;
}
total_qp -= quest_level[temp];
quest_name = delete(quest_name, temp, 1);
quest_level = delete(quest_level, temp, 1);
quest_title = delete(quest_title, temp, 1);
quest_story = delete(quest_story, temp, 1);
last_done_by = delete( last_done_by, temp, 1 );
num_times_done = delete( num_times_done, temp, 1 );
save_quests();
return 1;
} /* delete_quest() */
/**
* This method returns the names of all the quests.
* @return the names of all the quests
* @see add_quest()
* @see delete_quest()
*/
string *query_quest_names() {
return quest_name + ({ });
} /* query_quest_names() */
/**
* This method returns the levels of all the quests.
* @return the levels of all the quests
* @see add_quest()
* @see delete_quest()
*/
int *query_quest_levels() {
return quest_level + ({ });
} /* query_quest_levels() */
/**
* This method returns the titles of all the quests.
* @return the titles of all the quests
* @see add_quest()
* @see delete_quest()
*/
string *query_quest_titles() {
return quest_title + ({ });
} /* query_quest_titles() */
/**
* This method returns the stories of all the quests.
* @return the stories of all the quests
* @see add_quest()
* @see delete_quest()
*/
string *query_quest_stories() {
return quest_story + ({ });
} /* query_quest_stories() */
/**
* This method should be called in the code when a quest is complete.
* @param name name of the player
* @param quest the quest completed
* @param prev_ob the object which completed the quest
* @see add_quest()
* @see delete_quest()
*/
void quest_completed( string name, string quest, object prev_ob ) {
int i;
string word;
log_file( QUEST_LOG, ctime( time() ) +" "+ name +" completed "+
quest +"\n" );
user_event( "inform", name +" completes "+ quest, "quest" );
if ( file_name( previous_object() ) != LIBRARY ) {
prev_ob = previous_object();
}
word = (string)prev_ob->query_name();
if ( !word ) {
word = file_name( prev_ob );
} else {
word += " ("+ file_name( prev_ob ) +")";
}
log_file( QUEST_LOG, "given by "+ word +"\n" );
i = member_array( quest, quest_name );
if ( i == -1 ) {
log_file( QUEST_LOG, "non existent quest\n" );
return;
}
last_done_by[ i ] = name;
num_times_done[ i ]++;
save_quests();
} /* query_completed() */
/* Fame functions - for use in halls of fame / libraries etc. */
/* Piecemaker 25/3/93 */
/**
* This method returns the fame of the player.
* Gets the fame percentage of the player. Quest points / total quest points
* @param name the name of the player
* @return the fame as a percentage (0-100)
* @see query_player_story()
* @see query_fame_string()
* @see query_total_qp()
*/
int query_player_fame(string name){
int playerqp, rank;
/* do checking on the names */
if (!name){
return 0;
}
/* expand the nicknames if there are any */
if (this_player()){
name = (string)this_player()->expand_nickname(name);
}
/* are they a valid player ? */
if (!PLAYER_HANDLER->test_user(name)){
return 0;
}
/* do the calculations */
playerqp = (int)LIBRARY->query_quest_points(name);
rank = ( playerqp * 125 ) / query_total_qp();
return rank;
} /* query_player_fame() */
/**
* This method returns a string associated with the fame level of the
* player.
* @param name the name of the player
* @return the fame string
* @see query_player_fame()
* @see query_player_story()
*/
string query_fame_str( string name ) {
switch ( query_player_fame( name ) ) {
case 0 .. 4 :
return "completely unknown";
case 5 .. 14 :
return "unknown";
case 15 .. 24 :
return "unknown";
case 25 .. 34 :
return "moderately well known";
case 35 .. 44 :
return "well known";
case 45 .. 54 :
return "very well known";
case 55 .. 64 :
return "known throughout the region";
case 65 .. 74 :
return "famous";
case 75 .. 84 :
return "renowned";
case 85 .. 94 :
return "Disc renowned";
default :
return "so renowned that no introduction is needed";
}
} /* query_fame_str() */
/**
* This method lists the stories for the quests the player has done.
* @param name the name of the player
* @return the story of the player
* @see query_fame_string()
* @see query_player_fame()
*/
string *query_player_story(string name){
string *quests;
string *story;
int i;
story = ({ });
/* do checking on the names */
if (!name){
return ({ });
}
/* expand the nicknames if there are any */
if (this_player()){
name = (string)this_player()->expand_nickname(name);
}
/* are they a valid player ? */
if (!PLAYER_HANDLER->test_user(name)){
return 0;
}
/* right, we checked everything now. Lets do some real work. */
quests = query_quest_names();
if (sizeof(quests) == 1){
story = ({"Is an under achiever."});
}
else{
for(i=0;i<sizeof(quests);i++){
if (LIBRARY->query_quest_done(name, quests[i])){
story = ({ query_quest_story( quests[ i ] ) }) + story;
}
}
}
return story;
} /* query_player_story() */
/**
* This method prints out a lot of quest stats. For debugging purpsoes
* only.
*/
void print_some_stats() {
int i;
for (i = 0; i < sizeof(quest_name); i++)
printf("%s: %6d, %3d\n", quest_name[i], num_times_done[i], quest_level[i]);
} /* print_some_stats() */