/***************************************************************************
* _/_/_/_/ _/ _/ _/_/_/_/ _/_/_/_/ AckFUSS is modified ACK!MUD 4.3.1 *
* _/ _/ _/ _/ _/ copyright Matt Goff (Kline) 2008 *
* _/_/ _/ _/ _/_/_/_/ _/_/_/_/ *
* _/ _/ _/ _/ _/ Support for this code is provided *
* _/ _/_/_/_/ _/_/_/_/ _/_/_/_/ at www.ackmud.net -- check it out!*
***************************************************************************/
/*
* Original mquest code kindly donated by Abel@StormHunters. Thanks!
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "globals.h"
#ifndef DEC_ACT_COMM_H
#include "h/act_comm.h"
#endif
#ifndef DEC_COMM_H
#include "h/comm.h"
#endif
#ifndef DEC_DB_H
#include "h/db.h"
#endif
#ifndef DEC_HANDLER_H
#include "h/handler.h"
#endif
#ifndef DEC_MONEY_H
#include "h/money.h"
#endif
void do_mquest( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *mob = NULL;
OBJ_DATA *obj;
OBJ_DATA *obj_next;
char buf[MSL];
char arg1[MIL]; /* command */
char arg2[MIL]; /* for hint */
argument = one_argument(argument,arg1);
argument = one_argument(argument,arg2);
if( IS_NPC(ch) )
return;
if( get_psuedo_level(ch) < 20 )
{
send_to_char("You must be level 20 to request quests from the questmaster.\r\n",ch);
return;
}
if( arg1[0] == '\0' )
{
send_to_char("Mquest what? Syntax: mquest <giveup|request|info|complete|hint>\r\n",ch);
return;
}
if( !str_prefix(arg1,"request") )
{
for( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
if( IS_NPC(mob) && mob->npcdata->pIndexData->act.test(ACT_QUESTMASTER) )
break;
if( mob == NULL || !can_see(ch,mob) )
{
send_to_char("You have to be at a questmaster!\r\n",ch);
return;
}
if( ch->pcdata->quest_info->is_questing )
{
send_to_char("You are already on a quest! Give up on it first if you'd like a new one.\r\n",ch);
return;
}
if( ch->pcdata->quest_info->wait_time > 0 )
{
snprintf(buf,MSL,"You must wait %d more minute%s before taking another quest.\r\n",ch->pcdata->quest_info->wait_time,ch->pcdata->quest_info->wait_time > 1 ? "s" : "");
send_to_char(buf,ch);
return;
}
if( number_percent() < 51 )
{
send_to_char("Your next available quest is an @@eitem retrieval quest@@N!\r\n",ch);
if( number_percent() < 70 )
ch->pcdata->quest_info->quest_type = QUEST_MULTI_RETRIEVE;
else
ch->pcdata->quest_info->quest_type = QUEST_RETRIEVAL;
generate_retrieval_quest(ch);
ch->pcdata->quest_info->is_questing = TRUE;
}
else
{
send_to_char("Your next available quest is a @@ecreature killing@@N quest!\r\n",ch);
if( number_percent() <= 25 )
ch->pcdata->quest_info->quest_type = QUEST_MULTI_KILL;
else if( number_percent() <= 50 )
ch->pcdata->quest_info->quest_type = QUEST_KILLING;
else if( number_percent() <= 75 )
ch->pcdata->quest_info->quest_type = QUEST_KILLING_R;
else
ch->pcdata->quest_info->quest_type = QUEST_MULTI_KILL_R;
generate_killing_quest(ch);
ch->pcdata->quest_info->is_questing = TRUE;
}
mquest_calc_rewards(ch);
mquest_info(ch);
do_save(ch,"auto");
return;
}
else if( !str_prefix(arg1,"giveup") )
{
int pqp = 0, pgold = 0, pexp = 0, mn = 0;
char *cost;
char change[MSL], mbuf[MSL];
change[0] = '\0';
mbuf[0] = '\0';
for( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
if( IS_NPC(mob) && mob->npcdata->pIndexData->act.test(ACT_QUESTMASTER) )
break;
if( mob == NULL || !can_see(ch,mob) )
{
send_to_char("You have to be at a questmaster!\r\n",ch);
return;
}
if( !ch->pcdata->quest_info->is_questing )
{
send_to_char("You are not currently on a quest!\r\n",ch);
return;
}
pqp = UMAX(1,ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP]/3);
pgold = UMAX(1,ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD]/4);
pexp = UMAX(1,ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP]/4);
if( (ch->pcdata->quest_points - pqp) < 0 )
{
send_to_char("You do not have enough quest points to give up on this quest!\r\n",ch);
return;
}
if( (money_value(ch->money) - pgold) < 0 )
{
send_to_char("You do not have enough gold to give up on this quest!\r\n",ch);
return;
}
if( (ch->exp - pexp) < 0 )
{
send_to_char("You do not have enough experience to give up on this quest!\r\n",ch);
return;
}
ch->pcdata->quest_points -= pqp;
cost = take_best_coins(ch->money,pgold); /* Gives a string of the coins we need to steal. */
cost = one_argument(cost,change); /* First arg is change, skip it. Rest is what we take. */
for( mn = 0; mn < MAX_CURRENCY; mn++ )
{
char m_number[MSL], m_name[MSL];
cost = one_argument(cost,m_number);
if( m_number[0] == '\0' )
break;
cost = one_argument(cost,m_name);
if( m_name[0] == '\0' )
break;
if( m_number > 0 )
snprintf(mbuf,MSL,"%s %s",m_number,m_name);
}
ch->exp -= pexp;
snprintf(buf,MSL,"Giving up on this quest has cost you %d qp, %d exp, %s.\r\n",pqp,pexp,cost_to_money(money_to_value(ch,mbuf)));
send_to_char(buf,ch);
ch->pcdata->records->mquest_f++;
ch->pcdata->quest_info->wait_time = number_range(10,15); /* higher wait time on giveup */
snprintf(buf,MSL,"You must wait %d minutes before your next quest.\r\n",ch->pcdata->quest_info->wait_time);
send_to_char(buf,ch);
mquest_clear(ch,FALSE);
do_save(ch,"auto");
return;
}
else if( !str_prefix(arg1,"hint") )
{
short hint = 0;
if( !ch->pcdata->quest_info->is_questing )
{
send_to_char("You are not currently on a quest!\r\n",ch);
return;
}
if( ch->pcdata->quest_info->quest_type == QUEST_KILLING || ch->pcdata->quest_info->quest_type == QUEST_KILLING_R )
snprintf(arg2,MIL,"1");
hint = atoi(arg2);
if( !is_number(arg2) )
{
send_to_char("You must select a task number for which you want a hint.\r\n",ch);
return;
}
if( hint < 1 || hint > 5 )
{
send_to_char("You must choose the number of a task that you currently have!\r\n",ch);
return;
}
if( ch->pcdata->quest_info->amount[hint-1] == -1 )
{
send_to_char("You do not currently have a task with that number.\r\n",ch);
return;
}
if( ch->pcdata->quest_info->amount[hint-1] == 0 )
{
send_to_char("You have already completed that task!\r\n",ch);
return;
}
if( ch->pcdata->quest_info->quest_hint[hint-1] )
{
send_to_char("You've already got your hint for that task!\r\n",ch);
return;
}
if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL || ch->pcdata->quest_info->quest_type == QUEST_KILLING )
{
MOB_INDEX_DATA *imob = get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[hint-1]);
snprintf(buf,MSL,"%s can be found somewhere in %s.\r\n",imob->short_descr,imob->area->name);
send_to_char(buf,ch);
}
else if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL_R || ch->pcdata->quest_info->quest_type == QUEST_KILLING_R )
{
std::list<CHAR_DATA *>::iterator li;
for( li = char_list.begin(); li != char_list.end(); li++ )
{
mob = *li;
if( !IS_NPC(mob) )
continue;
if( mob->in_room == NULL )
continue;
if( mob->race == ch->pcdata->quest_info->quest_mob_vnum[hint-1] )
break;
}
snprintf(buf,MSL,"%ss can be found somewhere in %s.\r\n",race_table[mob->race].race_title,mob->in_room->area->name);
send_to_char(buf,ch);
}
else if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_RETRIEVE || ch->pcdata->quest_info->quest_type == QUEST_RETRIEVAL )
{
OBJ_INDEX_DATA *ob = get_obj_index(ch->pcdata->quest_info->quest_item_vnum[hint-1]);
snprintf(buf,MSL,"%s can be found somewhere in %s.\r\n",ob->short_descr,ob->area->name);
send_to_char(buf,ch);
}
ch->pcdata->quest_info->quest_hint[hint-1] = TRUE;
send_to_char("Your quest rewards have been reduced for using a hint.\r\n",ch);
do_save(ch,"auto");
return;
}
else if( !str_prefix(arg1,"info") )
{
if( !ch->pcdata->quest_info->is_questing )
{
send_to_char("You are not currently on a quest!\r\n",ch);
if( ch->pcdata->quest_info->wait_time > 0 )
{
snprintf(buf,MSL,"You must wait %d more minute%s before taking another quest.\r\n",ch->pcdata->quest_info->wait_time,ch->pcdata->quest_info->wait_time > 1 ? "s" : "");
send_to_char(buf,ch);
}
return;
}
if( ch->pcdata->quest_info->quest_type != 0 )
{
mquest_info(ch);
return;
}
}
else if( !str_prefix(arg1,"complete") )
{
short i = 0, x = 0;
for( mob = ch->in_room->first_person; mob; mob = mob->next_in_room )
if( IS_NPC(mob) && mob->npcdata->pIndexData->act.test(ACT_QUESTMASTER) )
break;
if( mob == NULL )
{
send_to_char("You have to be at a questmaster!\r\n",ch);
return;
}
if( !ch->pcdata->quest_info->is_questing )
{
send_to_char("You aren't even on a quest! Request one first.\r\n",ch);
return;
}
switch( ch->pcdata->quest_info->quest_type )
{
default:
send_to_char("Invalid quest type. Notifity an immortal.\r\n",ch);
return;
case QUEST_RETRIEVAL:
case QUEST_MULTI_RETRIEVE:
for( i = 0; i < QUEST_MAX_DATA; i++) /* take objects */
{
if( ch->pcdata->quest_info->quest_item_vnum[i] > -1 )
{
x = 0;
for( obj = ch->first_carry; obj != NULL && ch->pcdata->quest_info->amount[i] > 0; obj = obj_next )
{
obj_next = obj->next_in_carry_list;
if( ch->pcdata->quest_info->quest_item_vnum[i] == obj->pIndexData->vnum && obj->wear_loc == WEAR_NONE && !IS_OBJ_STAT(obj,ITEM_EXTRA_UNIQUE) )
{
extract_obj(obj);
x++;
ch->pcdata->quest_info->amount[i]--;
if( ch->pcdata->quest_info->amount[i] == 0 )
{
snprintf(buf,MSL,"You have now handed in all the %s you needed for your quest.\r\n",get_obj_index(ch->pcdata->quest_info->quest_item_vnum[i])->short_descr);
send_to_char(buf,ch);
}
}
}
if( x > 0 && ch->pcdata->quest_info->amount[i] != 0 )
{
snprintf(buf,MSL,"%s (%d) was handed into the questmaster.\r\n",get_obj_index(ch->pcdata->quest_info->quest_item_vnum[i])->short_descr,x);
send_to_char(buf,ch);
}
}
}
x = 0;
for( i = 0; i < QUEST_MAX_DATA; i++ )
if( ch->pcdata->quest_info->quest_item_vnum[i] > -1 && ch->pcdata->quest_info->amount[i] > 0 )
x += ch->pcdata->quest_info->amount[i];
if( x > 0 )
{
mquest_info(ch);
return;
}
ch->pcdata->quest_info->quest_complete = TRUE;
mquest_complete_message(ch);
do_save(ch,"auto");
return;
case QUEST_KILLING:
case QUEST_MULTI_KILL:
case QUEST_KILLING_R:
case QUEST_MULTI_KILL_R:
x = 0;
for( i = 0; i < QUEST_MAX_DATA; i++ )
if( ch->pcdata->quest_info->quest_mob_vnum[i] > -1 && ch->pcdata->quest_info->amount[i] > 0 )
x += ch->pcdata->quest_info->amount[i];
if( x > 0 )
{
mquest_info(ch);
return;
}
ch->pcdata->quest_info->quest_complete = TRUE;
mquest_complete_message(ch);
do_save(ch,"auto");
return;
}
}
do_mquest(ch,"");
return;
}
void do_qstat( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *victim;
char buf[MSL];
short i = 0;
if( argument[0] == '\0' )
{
send_to_char("Qstat whom?\r\n",ch);
return;
}
if( (victim = get_char_world(ch,argument)) == NULL )
{
send_to_char("They aren't here.\r\n",ch);
return;
}
if( IS_NPC(victim) )
{
send_to_char("Not on mobiles.\r\n",ch);
return;
}
snprintf(buf,MSL,"@@y%s@@b's current quest status:@@N\r\n",victim->name);
send_to_char(buf,ch);
switch( victim->pcdata->quest_info->quest_type )
{
default:
send_to_char("No active quest.\r\n",ch);
return;
case QUEST_RETRIEVAL:
if( victim->pcdata->quest_info->quest_item_vnum[0] > -1 )
{
snprintf(buf,MSL,"%s is seeking item %d-%s...\r\n",PERS(victim,ch),victim->pcdata->quest_info->quest_item_vnum[0],get_obj_index(victim->pcdata->quest_info->quest_item_vnum[0])->short_descr);
send_to_char(buf,ch);
if( victim->pcdata->quest_info->amount[0] > 0 )
{
snprintf(buf,MSL,"...and must retrieve %d more of them.\r\n",victim->pcdata->quest_info->amount[0]);
send_to_char(buf,ch);
}
}
else
send_to_char("Invalid quest item.\r\n",ch);
break;
case QUEST_KILLING:
if( victim->pcdata->quest_info->quest_mob_vnum[0] > -1 )
{
snprintf(buf,MSL,"%s is seeking mob %d-%s...\r\n",PERS(victim,ch),victim->pcdata->quest_info->quest_mob_vnum[0],get_mob_index(victim->pcdata->quest_info->quest_mob_vnum[0])->short_descr);
send_to_char(buf,ch);
if( victim->pcdata->quest_info->amount[0] > 0 )
{
snprintf(buf,MSL,"...and must slay %d more of them.\r\n",victim->pcdata->quest_info->amount[0]);
send_to_char(buf,ch);
}
}
else
send_to_char("Invalid quest mob.\r\n",ch);
break;
case QUEST_MULTI_KILL:
send_to_char("Kill the following creatures (# of times).\r\n",ch);
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( victim->pcdata->quest_info->quest_mob_vnum[i] > -1 )
{
snprintf(buf,MSL,"Target #%d: %5d-%s (%d)\r\n",i+1,victim->pcdata->quest_info->quest_mob_vnum[i],get_mob_index(victim->pcdata->quest_info->quest_mob_vnum[i])->short_descr,victim->pcdata->quest_info->amount[i]);
send_to_char(buf,ch);
}
}
break;
case QUEST_MULTI_RETRIEVE:
send_to_char("Retrieve the following items (# of times).\r\n",ch);
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( victim->pcdata->quest_info->quest_item_vnum[i] > -1 )
{
snprintf(buf,MSL,"Item #%d: %5d-%s (%d)\r\n",i+1,victim->pcdata->quest_info->quest_item_vnum[i],get_obj_index(victim->pcdata->quest_info->quest_item_vnum[i])->short_descr,victim->pcdata->quest_info->amount[i]);
send_to_char(buf,ch);
}
}
break;
case QUEST_KILLING_R:
if( victim->pcdata->quest_info->quest_mob_vnum[0] > -1 )
{
snprintf(buf,MSL,"%s is seeking %s mobs...\r\n",PERS(victim,ch),race_table[victim->pcdata->quest_info->quest_mob_vnum[0]].race_title);
send_to_char(buf,ch);
if( victim->pcdata->quest_info->amount[0] > 0 )
{
snprintf(buf,MSL,"...and must slay %d more of them.\r\n",victim->pcdata->quest_info->amount[0]);
send_to_char(buf,ch);
}
}
else
send_to_char("Invalid quest race.\r\n",ch);
break;
case QUEST_MULTI_KILL_R:
send_to_char("Kill mobs of the following races (# of times).\r\n",ch);
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( victim->pcdata->quest_info->quest_mob_vnum[i] > -1 )
{
snprintf(buf,MSL,"Target #%d: %s (%d)\r\n",i+1,race_table[victim->pcdata->quest_info->quest_mob_vnum[i]].race_title,victim->pcdata->quest_info->amount[i]);
send_to_char(buf,ch);
}
}
break;
}
snprintf(buf,MSL,"QP: %d\r\nGold: %s\r\nExp: %d\r\n",victim->pcdata->quest_info->quest_reward[QUEST_REWARD_QP],cost_to_money(victim->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD]),victim->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP]);
send_to_char(buf,ch);
return;
}
void mquest_info( CHAR_DATA *ch )
{
char buf[MSL];
short i =0 ;
switch( ch->pcdata->quest_info->quest_type )
{
default:
snprintf(buf,MSL,"quest_type is a value of %d, how'd that happen? Tell an imm, thanks!\r\n",ch->pcdata->quest_info->quest_type);
send_to_char(buf,ch);
break;
case QUEST_RETRIEVAL:
if( ch->pcdata->quest_info->quest_item_vnum[0] > -1 )
{
snprintf(buf,MSL,"You are seeking the item known as %s@@N.\r\n",get_obj_index(ch->pcdata->quest_info->quest_item_vnum[0])->short_descr);
send_to_char(buf,ch);
if( ch->pcdata->quest_info->amount[0] > 0 )
{
snprintf(buf,MSL,"Your quest contract states that you must retrieve %d more of them.\r\n",ch->pcdata->quest_info->amount[0]);
send_to_char(buf,ch);
snprintf(buf,MSL,"@@eHint:@@N They can be found in %s@@N!\r\n",get_obj_index(ch->pcdata->quest_info->quest_item_vnum[i])->area->name);
if( ch->pcdata->quest_info->quest_hint[0] )
send_to_char(buf,ch);
}
}
else
send_to_char("Invalid quest item.\r\n",ch);
break;
case QUEST_KILLING:
if( ch->pcdata->quest_info->quest_mob_vnum[0] > -1 )
{
snprintf(buf,MSL,"You are seeking out the creature known as %s@@N.\r\n",get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[0])->short_descr);
send_to_char(buf,ch);
if( ch->pcdata->quest_info->amount[0] > 0 )
{
snprintf(buf,MSL,"Your quest contract states that you must slay %d more of them.\r\n",ch->pcdata->quest_info->amount[0]);
send_to_char(buf,ch);
snprintf(buf,MSL,"@@eHint:@@N They can be found in %s@@N!\r\n",get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->area->name);
if( ch->pcdata->quest_info->quest_hint[0] )
send_to_char(buf,ch);
}
else
send_to_char("You have fulfilled the kill requirements outlined in your contract.\r\n",ch);
}
else
send_to_char("Invalid quest mob.\r\n",ch);
break;
case QUEST_MULTI_KILL:
send_to_char("You must hunt down and destroy the following creatures (# of times).\r\n",ch);
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( ch->pcdata->quest_info->quest_mob_vnum[i] > -1 )
{
snprintf(buf,MSL,"Target #%d: %s (%d)",i+1,get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->short_descr,ch->pcdata->quest_info->amount[i]);
send_to_char(buf,ch);
if( ch->pcdata->quest_info->quest_hint[i] )
snprintf(buf,MSL," [%s]\r\n",get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->area->name);
else
snprintf(buf,MSL,"\r\n");
send_to_char(buf,ch);
}
}
break;
case QUEST_MULTI_RETRIEVE:
send_to_char("You must retrieve the following items from across the land (# of times).\r\n",ch);
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( ch->pcdata->quest_info->quest_item_vnum[i] > -1 )
{
snprintf(buf,MSL,"Item #%d: %s (%d)",i+1,get_obj_index(ch->pcdata->quest_info->quest_item_vnum[i])->short_descr,ch->pcdata->quest_info->amount[i]);
send_to_char(buf,ch);
if( ch->pcdata->quest_info->quest_hint[i] )
snprintf(buf,MSL," [%s]\r\n",get_obj_index(ch->pcdata->quest_info->quest_item_vnum[i])->area->name);
else
snprintf(buf,MSL,"\r\n");
send_to_char(buf,ch);
}
}
break;
case QUEST_KILLING_R:
if( ch->pcdata->quest_info->quest_mob_vnum[0] > -1 )
{
snprintf(buf,MSL,"You are seeking out %s creatures.\r\n",race_table[ch->pcdata->quest_info->quest_mob_vnum[0]].race_title);
send_to_char(buf,ch);
if( ch->pcdata->quest_info->amount[0] > 0 )
{
CHAR_DATA *mob = NULL;
std::list<CHAR_DATA *>::iterator li;
snprintf(buf,MSL,"Your quest contract states that you must slay %d more of them.\r\n",ch->pcdata->quest_info->amount[0]);
send_to_char(buf,ch);
for( li = char_list.begin(); li != char_list.end(); li++ )
{
mob = *li;
if( !IS_NPC(mob) )
continue;
if( mob->in_room == NULL )
continue;
if( mob->race == ch->pcdata->quest_info->quest_mob_vnum[0] )
break;
}
if( mob != NULL )
{
snprintf(buf,MSL,"@@eHint:@@N They can be found in %s@@N!\r\n",mob->in_room->area->name);
if( ch->pcdata->quest_info->quest_hint[0] )
send_to_char(buf,ch);
}
}
else
send_to_char("You have fulfilled the kill requirements outlined in your contract.\r\n",ch);
}
else
send_to_char("Invalid quest mob race.\r\n",ch);
break;
case QUEST_MULTI_KILL_R:
send_to_char("You must hunt down and destroy the following types of creatures (# of times).\r\n",ch);
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( ch->pcdata->quest_info->quest_mob_vnum[i] > -1 )
{
CHAR_DATA *mob = NULL;
std::list<CHAR_DATA *>::iterator li;
for( li = char_list.begin(); li != char_list.end(); li++ )
{
mob = *li;
if( !IS_NPC(mob) )
continue;
if( mob->in_room == NULL )
continue;
if( mob->race == ch->pcdata->quest_info->quest_mob_vnum[i] )
break;
}
snprintf(buf,MSL,"Target #%d: %s (%d)",i+1,race_table[ch->pcdata->quest_info->quest_mob_vnum[i]].race_title,ch->pcdata->quest_info->amount[i]);
send_to_char(buf,ch);
if( ch->pcdata->quest_info->quest_hint[i] && mob != NULL )
snprintf(buf,MSL," [%s]\r\n",mob->in_room->area->name);
else
snprintf(buf,MSL,"\r\n");
send_to_char(buf,ch);
}
else
send_to_char("Invalid quest mob race.\r\n",ch);
}
break;
}
return;
}
void mquest_complete_message( CHAR_DATA *ch )
{
char buf[MSL];
short hint = 0, i = 0;
float tmp = 0;
if( IS_NPC(ch) )
return;
if( ch->pcdata->quest_info->quest_complete )
{
for( i = 0; i < QUEST_MAX_DATA; i++ )
if( ch->pcdata->quest_info->quest_hint[i] )
hint++;
if( hint > 0 )
{
snprintf(buf,MSL,"Quest reward reduced for the use of %d hint%s.\r\n",hint,hint > 1 ? "s" : "");
send_to_char(buf,ch);
}
while( hint > 0 )
{
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP];
tmp *= 0.90;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] = static_cast<int>(tmp);
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD];
tmp *= 0.90;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] = static_cast<int>(tmp);
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP];
tmp *= 0.90;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = static_cast<int>(tmp);
hint--;
}
snprintf(buf,MSL,"Quest Complete. You have earned %d qp, %d experience, %s!\r\n",ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP],ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP],cost_to_money(ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD]));
send_to_char(buf,ch);
ch->pcdata->quest_points += ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP];
join_money(round_money(ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD],TRUE),ch->money);
ch->exp += ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP];
ch->pcdata->records->mquest_c++;
ch->pcdata->records->qp_tot += ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP];
if( ch->pcdata->records->mquest_c % 50 == 0 ) /* every time a person completes 50 quests */
{
send_to_char("@@eCongratulations! You've succesfully completed 50 questmaster quests!\r\n",ch);
send_to_char("@@eYou have been rewarded a bonus 25 practices and 40 quest points!\r\n",ch);
ch->practice += 25;
ch->pcdata->quest_points += 40;
ch->pcdata->records->qp_tot += 40;
}
if( ch->pcdata->quest_points > ch->pcdata->records->qp )
{
send_to_char("@@yYou've broken your quest point record!@@N\r\n",ch);
ch->pcdata->records->qp = ch->pcdata->quest_points;
}
mquest_clear(ch,FALSE);
}
else
send_to_char("You haven't completed the quest's requirements yet.\r\n",ch);
return;
}
void mquest_calc_rewards( CHAR_DATA *ch )
{
short clev, tot_amt, tot_tsk;
int exp;
float mod = 1.00, tmp = 0;
if( IS_NPC(ch) )
return;
tot_amt = 0;
tot_tsk = 0;
clev = get_psuedo_level(ch);
exp = (exp_mob_base(clev) * sysdata.killperlev);
exp = number_range(static_cast<int>(exp * 0.04),static_cast<int>(exp * 0.08));
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] = number_range(static_cast<int>(clev / 40),static_cast<int>(clev / 20));
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] = number_range(static_cast<int>(clev * 15),static_cast<int>(clev * 30));
if( is_adept(ch) )
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = number_range(static_cast<int>(exp_to_level_adept(ch) * 0.04),static_cast<int>(exp_to_level_adept(ch) * 0.08));
else
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = exp;
/* Add some randomness */
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] += number_range(-1,1);
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] = number_range(static_cast<int>(ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] * 0.9),static_cast<int>(ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] * 1.1));
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = number_range(static_cast<int>(ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] * 0.9),static_cast<int>(ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] * 1.1));
for( tot_tsk = 0; tot_tsk < QUEST_MAX_DATA; tot_tsk++ )
{
if( ch->pcdata->quest_info->amount[tot_tsk] == -1 )
break;
else
tot_amt += ch->pcdata->quest_info->amount[tot_tsk];
}
if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_RETRIEVE )
{
if( tot_tsk >= 3 )
mod += ((tot_tsk - 3) * 0.1);
else
mod -= 0.2;
}
else if( ch->pcdata->quest_info->quest_type == QUEST_RETRIEVAL )
{
if( tot_amt >= 3 )
mod += ((tot_amt - 3) * 0.1);
else
mod -= 0.2;
}
else if( ch->pcdata->quest_info->quest_type == QUEST_KILLING || ch->pcdata->quest_info->quest_type == QUEST_KILLING_R )
{
if( tot_amt >= 3 )
mod += ((tot_amt - 4) * 0.1);
else
mod -= 0.2;
}
else if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL || ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL_R )
{
if( tot_tsk >= 3 )
mod += ((tot_tsk - 3 ) * 0.1);
else
mod -= 0.2;
mod += ((tot_amt - 10) * 0.02);
}
else
{
send_to_char("An error has occured calculating rewards. This should not happen.\r\n",ch);
ch->pcdata->quest_info->wait_time = 0;
mquest_clear(ch,TRUE);
return;
}
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP];
tmp *= mod;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] = static_cast<int>(tmp);
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD];
tmp *= mod;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] = static_cast<int>(tmp);
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP];
tmp *= mod;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = static_cast<int>(tmp);
/* Bonus! */
if( number_percent() < 5 )
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] += 2;
if( number_percent() < 5 )
{
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD];
tmp *= 1.5;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] = static_cast<int>(tmp);
}
if( number_percent() < 5 )
{
tmp = ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP];
tmp *= 1.5;
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = static_cast<int>(tmp);
}
/* No negative rewards */
if( ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] < 0 )
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_QP] = 0;
if( ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] < 0 )
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_GOLD] = 0;
if( ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] < 0 )
ch->pcdata->quest_info->quest_reward[QUEST_REWARD_EXP] = 0;
return;
}
void mquest_clear( CHAR_DATA *ch, bool error )
{
int i = 0;
char buf[MSL];
if( IS_NPC(ch) )
return;
for( i = 0; i < QUEST_MAX_DATA; i++ )
ch->pcdata->quest_info->amount[i] = -1;
ch->pcdata->quest_info->is_questing = FALSE;
ch->pcdata->quest_info->quest_complete = FALSE;
for( i = 0; i < QUEST_MAX_DATA; i++ )
ch->pcdata->quest_info->quest_hint[i] = FALSE;
for( i = 0; i < QUEST_MAX_DATA; i++ )
ch->pcdata->quest_info->quest_item_vnum[i] = -1;
for( i = 0; i < QUEST_MAX_DATA; i++ )
ch->pcdata->quest_info->quest_mob_vnum[i] = -1;
for( i = 0; i < QUEST_MAX_REWARD; i++ )
ch->pcdata->quest_info->quest_reward[i] = 0;
ch->pcdata->quest_info->quest_type = 0;
ch->pcdata->quest_info->time_left = 0;
if( ch->pcdata->quest_info->wait_time == 0 && !error )
{
ch->pcdata->quest_info->wait_time = 5;
snprintf(buf,MSL,"You must wait %d minutes before your next quest.\r\n",ch->pcdata->quest_info->wait_time);
send_to_char(buf,ch);
}
do_save(ch,"auto");
return;
}
void generate_killing_quest( CHAR_DATA *ch )
{
CHAR_DATA *mob;
short max, i, x;
bool redo = FALSE, race = FALSE;
short min_lev, max_lev;
short clev;
if( IS_NPC(ch) )
return;
if( ch->pcdata->quest_info->quest_type == QUEST_KILLING_R || ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL_R )
race = TRUE;
clev = get_psuedo_level(ch);
min_lev = static_cast<int>(clev * 0.7);
max_lev = static_cast<int>(clev * 1.1);
if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL || ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL_R )
max = number_range(3,5);
else
max = 1;
if( clev <= 80 && max_lev > 80 )
max_lev = 80;
else if( clev < 110 && max_lev > 110 )
max_lev = 110;
else if( clev == 120 && min_lev <110 )
min_lev = 110;
min_lev = UMAX(0,min_lev);
max_lev = UMIN(140,max_lev);
for( i = 0; i < max; i++ )
{
mob = NULL;
mob = get_quest_kill(min_lev,max_lev,ch);
if( !mob && !race )
{
min_lev -= 10;
max_lev -= 10;
i--;
if( min_lev < 1 || max_lev < 1 )
{
send_to_char("Mquest error. Unable to find suitible mobs. Aborting.\r\n",ch);
ch->pcdata->quest_info->wait_time = 0;
mquest_clear(ch,TRUE);
return;
}
continue;
}
x = 0;
if( !race )
ch->pcdata->quest_info->quest_mob_vnum[i] = mob->npcdata->pIndexData->vnum;
else
{
ch->pcdata->quest_info->quest_mob_vnum[i] = number_range(0,MAX_RACE-1);
if( number_percent() < 30 )
ch->pcdata->quest_info->amount[i] = 1;
else
ch->pcdata->quest_info->amount[i] = (2 + number_range(0,4));
}
if( !race )
{
if( redo ) /* If it just failed the same-area check, don't check again, check vnums. */
{
redo = FALSE; /* Prevent crashing due to infinite loop. */
for( x = 0; x < i; x++ )
if( (ch->pcdata->quest_info->quest_mob_vnum[i] == ch->pcdata->quest_info->quest_mob_vnum[x]) && (x != i) )
redo = TRUE; /* Same vnum, don't allow it. Don't redo same-area check though. */
}
else
{
for( x = 0; x < i; x++ )
if( !str_cmp(get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->area->name,get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[x])->area->name) && (x != i) )
redo = TRUE;
}
if( !redo )
{
if( number_percent() < 30 )
ch->pcdata->quest_info->amount[i] = 1;
else
{
if( get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->act.test(ACT_SENTINEL) )
ch->pcdata->quest_info->amount[i] = 1;
else
ch->pcdata->quest_info->amount[i] = (2 + number_range(0,4));
}
}
else
{ /* Same area detected. Run it again. */
ch->pcdata->quest_info->quest_mob_vnum[i] = -1;
ch->pcdata->quest_info->amount[i] = -1;
i--;
}
}
}
if( ch->pcdata->quest_info->quest_type == QUEST_KILLING || ch->pcdata->quest_info->quest_type == QUEST_KILLING_R )
for( i = 1; i < QUEST_MAX_DATA; i++ )
{
ch->pcdata->quest_info->quest_mob_vnum[i] = -1;
ch->pcdata->quest_info->amount[i] = -1;
}
return;
}
CHAR_DATA *get_quest_kill( int min_lev, int max_lev, CHAR_DATA *ch )
{
CHAR_DATA *mob = NULL;
std::list<CHAR_DATA *>::iterator li;
int i = number_range(0,mob_index_list.size()-1);
for( li = char_list.begin(); li != char_list.end(); li++ )
{
mob = *li;
i--;
if( i > 0 ) /* Add some variety to where we start in the ch_list */
continue;
if( !IS_NPC(mob) )
continue;
if( (get_psuedo_level(mob) < min_lev || get_psuedo_level(mob) > max_lev)
|| (mob->in_room->area->min_level > get_psuedo_level(ch) || mob->in_room->area->max_level < get_psuedo_level(ch))
|| (mob->in_room->area->flags.test(AFLAG_NOSHOW) || mob->in_room->area->flags.test(AFLAG_NO_QUEST))
|| (!str_cmp(rev_spec_lookup(mob->npcdata->spec_fun),"spec_cast_adept"))
|| (!str_cmp(rev_spec_lookup(mob->npcdata->spec_fun),"spec_executioner"))
|| (mob->npcdata->pIndexData->vnum > mob->in_room->area->max_vnum || mob->npcdata->pIndexData->vnum < mob->in_room->area->min_vnum)
|| (mob->in_room->room_flags.test(RFLAG_SAFE))
|| (IS_AFFECTED(mob,AFF_CHARM))
|| (mob->act.test(ACT_PET))
|| (mob->act.test(ACT_NO_QUEST)))
continue;
if( number_percent() < 5 ) /* Add variety to actually selecting the first ch we find in the ch_list */
return mob;
}
return mob;
}
void generate_retrieval_quest( CHAR_DATA *ch )
{
OBJ_DATA *obj;
short max, i, x;
bool redo=FALSE;
short min_lev, max_lev;
short clev;
if( IS_NPC(ch) )
return;
clev = get_psuedo_level(ch);
min_lev = static_cast<int>(clev * 0.7);
max_lev = static_cast<int>(clev * 1.1);
if(ch->pcdata->quest_info->quest_type == QUEST_MULTI_RETRIEVE )
max = number_range(3,5);
else
max = 1;
if( clev <= 80 && max_lev > 80 )
max_lev = 80;
else if( clev < 110 && max_lev > 110 )
max_lev = 110;
else if( clev == 120 && min_lev <110 )
min_lev = 110;
min_lev = UMAX(0,min_lev);
max_lev = UMIN(140,max_lev);
for( i = 0; i < max; i++ )
{
obj = NULL;
obj = get_quest_item(min_lev,max_lev,ch);
if( !obj )
{
min_lev -= 10;
max_lev -= 10;
i--;
if( min_lev < 1 || max_lev < 1 )
{
send_to_char("Mquest error. Unable to find suitible objs. Aborting.\r\n",ch);
ch->pcdata->quest_info->wait_time = 0;
mquest_clear(ch,TRUE);
return;
}
continue;
}
ch->pcdata->quest_info->quest_item_vnum[i] = obj->pIndexData->vnum;
if( redo ) /* If it just failed the same-area check, don't check again, check vnums. */
{
redo = FALSE; /* Prevent crashing due to infinite loop. */
for( x = 0; x < i; x++ )
if( (ch->pcdata->quest_info->quest_item_vnum[i] == ch->pcdata->quest_info->quest_item_vnum[x]) && (x != i) )
redo = TRUE; /* Same vnum, don't allow it. Don't redo same-area check though. */
}
else
{
for( x = 0; x < i; x++ )
if( !str_cmp(get_obj_index(ch->pcdata->quest_info->quest_item_vnum[i])->area->name,get_obj_index(ch->pcdata->quest_info->quest_item_vnum[x])->area->name) && (x != i) )
redo = TRUE;
}
if( !redo )
{
if( ch->pcdata->quest_info->quest_type == QUEST_MULTI_RETRIEVE )
ch->pcdata->quest_info->amount[i] = 1;
else
ch->pcdata->quest_info->amount[i] = (2 + number_range(0,4));
}
else
{ /* Same area detected. Run it again. */
ch->pcdata->quest_info->quest_item_vnum[i] = -1;
ch->pcdata->quest_info->amount[i] = -1;
i--;
}
}
return;
}
OBJ_DATA *get_quest_item( int min_lev, int max_lev, CHAR_DATA *ch )
{
OBJ_DATA *obj = NULL;
int i = number_range(0,obj_index_list.size()-1);
std::list<OBJ_DATA *>::iterator li;
for( li = obj_list.begin(); li != obj_list.end(); li++ )
{
obj = *li;
i--;
if( i > 0 ) /* Add some variety to where we start in the obj_list */
continue;
if( obj->in_room )
{
if( (obj->in_room->area->flags.test(AFLAG_NO_QUEST) || obj->in_room->area->flags.test(AFLAG_NOSHOW)) /* Hide places we don't want to use. */
|| (obj->in_room->area->min_level > get_psuedo_level(ch) || obj->in_room->area->max_level < get_psuedo_level(ch))
|| (obj->pIndexData->vnum > obj->in_room->area->max_vnum || obj->pIndexData->vnum < obj->in_room->area->min_vnum) /* outside obj's own area */
|| (!CAN_WEAR(obj,ITEM_TAKE)) /* ensure we can pick it up */
|| (IS_OBJ_STAT(obj,ITEM_EXTRA_RARE)) /* don't waste rares */
|| (obj->item_type == ITEM_QUEST) /* no autoquest items */
|| (obj->item_type == ITEM_MONEY)
|| (IS_OBJ_STAT(obj,ITEM_EXTRA_NO_QUEST))
|| (obj->item_type == ITEM_PIECE)
|| (IS_OBJ_STAT(obj,ITEM_EXTRA_UNIQUE))
|| (obj->carried_by != NULL && (!IS_NPC(obj->carried_by)
|| (IS_NPC(obj->carried_by) && obj->carried_by->npcdata->pIndexData->pShop != NULL))) /* held by PC or held by NPC that is a shopkeeper */
|| (obj->weight > 15)
|| (obj->level > max_lev)
|| (obj->level < min_lev))
continue;
if( number_percent() < 5 ) /* Add variety to actually selecting the first obj we find in the obj_list */
return obj;
}
else if( obj->carried_by && obj->carried_by->in_room )
{
if( (obj->carried_by->in_room->area->flags.test(AFLAG_NO_QUEST) || obj->carried_by->in_room->area->flags.test(AFLAG_NOSHOW)) /* Hide places we don't want to use. */
|| (obj->carried_by->in_room->area->min_level > get_psuedo_level(ch) || obj->carried_by->in_room->area->max_level < get_psuedo_level(ch))
|| (obj->pIndexData->vnum > obj->carried_by->in_room->area->max_vnum || obj->pIndexData->vnum < obj->carried_by->in_room->area->min_vnum) /* outside obj's own area */
|| (!CAN_WEAR(obj,ITEM_TAKE)) /* ensure we can pick it up */
|| (IS_OBJ_STAT(obj,ITEM_EXTRA_RARE)) /* don't waste rares */
|| (obj->item_type == ITEM_QUEST) /* no autoquest items */
|| (obj->item_type == ITEM_MONEY)
|| (IS_OBJ_STAT(obj,ITEM_EXTRA_NO_QUEST))
|| (obj->item_type == ITEM_PIECE)
|| (IS_OBJ_STAT(obj,ITEM_EXTRA_UNIQUE))
|| (obj->carried_by != NULL && (!IS_NPC(obj->carried_by)
|| (IS_NPC(obj->carried_by) && obj->carried_by->npcdata->pIndexData->pShop != NULL))) /* held by PC or held by NPC that is a shopkeeper */
|| (obj->weight > 15)
|| (obj->level > max_lev)
|| (obj->level < min_lev))
continue;
if( number_percent() < 5 ) /* Add variety to actually selecting the first obj we find in the obj_list */
return obj;
}
}
return obj;
}
char *display_mob_target( CHAR_DATA *ch, CHAR_DATA *victim )
{
if( IS_NPC(ch) || !IS_NPC(victim) )
return "";
if( ch->pcdata->quest_info->is_questing && (ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL || ch->pcdata->quest_info->quest_type == QUEST_KILLING) )
{
short i = 0;
/* Ugly to workaround same-descr mobs with different vnums for repop purposes */
for( i = 0; i < QUEST_MAX_DATA; i++ )
if( ch->pcdata->quest_info->quest_mob_vnum[i] > -1
&& ch->pcdata->quest_info->amount[i] > 0
&& (ch->pcdata->quest_info->quest_mob_vnum[i] == victim->npcdata->pIndexData->vnum
|| (!str_cmp(get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->short_descr,victim->npcdata->short_descr)
&& get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->area == victim->in_room->area)) )
return "@@e[@@yTARGET@@e] @@N";
}
if( ch->pcdata->quest_info->is_questing && (ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL_R || ch->pcdata->quest_info->quest_type == QUEST_KILLING_R) )
{
short i = 0;
for( i = 0; i < QUEST_MAX_DATA; i++ )
if( ch->pcdata->quest_info->quest_mob_vnum[i] > -1
&& ch->pcdata->quest_info->amount[i] > 0
&& ch->pcdata->quest_info->quest_mob_vnum[i] == victim->race
&& (get_psuedo_level(ch) < get_psuedo_level(victim) || (get_psuedo_level(victim) - get_psuedo_level(ch)) >= -10) )
return "@@e[@@yTARGET@@e] @@N";
}
return "";
}
char *display_obj_target( CHAR_DATA *ch, OBJ_DATA *obj )
{
if( IS_NPC(ch) )
return "";
if( ch->pcdata->quest_info->is_questing && (ch->pcdata->quest_info->quest_type == QUEST_MULTI_RETRIEVE || ch->pcdata->quest_info->quest_type == QUEST_RETRIEVAL) )
{
short i = 0;
for( i = 0; i < QUEST_MAX_DATA; i++ )
if( ch->pcdata->quest_info->quest_item_vnum[i] > -1
&& ch->pcdata->quest_info->quest_item_vnum[i] == obj->pIndexData->vnum
&& ch->pcdata->quest_info->amount[i] > 0 )
return "@@e[@@yTARGET@@e] @@N";
}
return "";
}
void update_mquest_wait_time( CHAR_DATA *ch )
{
if( IS_NPC(ch) )
return;
if( !ch->pcdata->quest_info->is_questing && ch->pcdata->quest_info->wait_time > 0 && ch->desc != NULL )
{
ch->pcdata->quest_info->wait_time--;
if( ch->pcdata->quest_info->wait_time == 0 )
send_to_char("You can now get another quest from the questmaster!\r\n",ch);
}
return;
}
void update_mquest_kill( CHAR_DATA *ch, CHAR_DATA *victim )
{
short i, tot = 0;
if( IS_NPC(ch) || !IS_NPC(victim) )
return;
if( ch->pcdata->quest_info->is_questing && (ch->pcdata->quest_info->quest_type == QUEST_KILLING || ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL) && !ch->pcdata->quest_info->quest_complete )
{
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( ch->pcdata->quest_info->quest_mob_vnum[i] < 0 )
continue;
if( ch->pcdata->quest_info->amount[i] > 0
&& (ch->pcdata->quest_info->quest_mob_vnum[i] == victim->npcdata->pIndexData->vnum
|| (!str_cmp(get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->short_descr,victim->npcdata->short_descr)
&& get_mob_index(ch->pcdata->quest_info->quest_mob_vnum[i])->area == victim->in_room->area)) )
{
ch->pcdata->quest_info->amount[i]--;
send_to_char("You have completed a quest kill!\r\n",ch);
if( ch->pcdata->quest_info->amount[i] == 0 )
send_to_char("You have completed the kill requirement for this creature!\r\n",ch);
}
if( ch->pcdata->quest_info->amount[i] > -1 )
tot += ch->pcdata->quest_info->amount[i];
}
if( tot == 0 ) /* If the total is 0 after checking through the whole loop, then they've completed their quest. */
{
ch->pcdata->quest_info->quest_complete = TRUE;
send_to_char("You have completed your quest! Return to the quest master.\r\n",ch);
}
}
if( ch->pcdata->quest_info->is_questing && (ch->pcdata->quest_info->quest_type == QUEST_KILLING_R || ch->pcdata->quest_info->quest_type == QUEST_MULTI_KILL_R) && !ch->pcdata->quest_info->quest_complete )
{
for( i = 0; i < QUEST_MAX_DATA; i++ )
{
if( ch->pcdata->quest_info->quest_mob_vnum[i] < 0 )
continue;
if( ch->pcdata->quest_info->amount[i] > 0 && (ch->pcdata->quest_info->quest_mob_vnum[i] == victim->race) && (get_psuedo_level(ch) < get_psuedo_level(victim) || (get_psuedo_level(victim) - get_psuedo_level(ch)) >= -10) )
{
ch->pcdata->quest_info->amount[i]--;
send_to_char("You have completed a quest kill!\r\n",ch);
if( ch->pcdata->quest_info->amount[i] == 0 )
send_to_char("You have completed the kill requirement for this race!\r\n",ch);
}
if( ch->pcdata->quest_info->amount[i] > -1 )
tot += ch->pcdata->quest_info->amount[i];
}
if( tot == 0 ) /* If the total is 0 after checking through the whole loop, then they've completed their quest. */
{
ch->pcdata->quest_info->quest_complete = TRUE;
send_to_char("You have completed your quest! Return to the quest master.\r\n",ch);
}
}
return;
}