/**************************************************************************** * Automated Quest code written by Vassago of MOONGATE, moongate.ams.com * * 4000. Copyright (c) 1996 Ryan Addams, All Rights Reserved. Use of this * * code is allowed provided you add a credit line to the effect of: * * "Quest Code (c) 1996 Ryan Addams" to your logon screen with the rest * * of the standard diku/rom credits. If you use this or a modified version * * of this code, let me know via email: moongate@moongate.ams.com. Further * * updates will be posted to the rom mailing list. If you'd like to get * * the latest version of quest.c, please send a request to the above add- * * ress. Quest Code v2.03. Please do not remove this notice from this file. * ****************************************************************************/ /******************************************************************************** * Updated Quest Code copyright 1999-2001 * * Markanth : markanth@hotpop.com or rjenn78@home.com * * Devil's Lament : spaceservices.net port 3778 * * Web Page : http://spaceservices.net/~markanth/ * * * * Quest objects are now updated by owner's level, code is more dynamic. * * * * All I ask in return is that you give me credit on your mud somewhere * * or email me if you use it. * ********************************************************************************/ #include <ctype.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include "merc.h" #include "recycle.h" struct quest_type { char *name; char *who_name; long vnum; int cost; }; /* Quest Prizes */ #define QUEST_BLADE 501 /* Blade */ #define QUEST_ARMOR 502 /* Armor */ #define QUEST_LEGGING 505 /* Leggings */ #define QUEST_GAUNTLET 503 /* Gauntlets */ #define QUEST_BOOT 512 /* Boots */ #define QUEST_HELM 514 /* Helm */ #define QUEST_RING 506 /* Ring */ #define QUEST_ORB 516 /* Orb */ #define QUEST_NECKLACE 517 /* Necklace */ #define QUEST_MASK 508 /* Mask */ #define QUEST_BELT 511 /* Belt */ #define QUEST_CLOAK 507 /* Cloak */ #define QUEST_BRACER 509 /* Bracelet */ #define QUEST_EARRING 518 /* Earring */ #define QUEST_ANKLET 513 /* Anklet */ #define QUEST_SHIELD 510 /* Shield */ #define QUEST_AURA 515 /* Aura */ #define QUEST_TATTOO 504 /* Tattoo */ #define QUEST_SLEEVE 519 /* Sleeves */ #define QUEST_FLAME 520 /* Flame */ #define QUEST_STRINGTICK 548 /* Restring Ticket */ #define QUEST_WHOTICK 549 /* Whostring Ticket */ /*#define QUEST_TRIVIA OBJ_VNUM_TRIVIA_PILL*/ /* * Quest Reward Table. */ const struct quest_type quest_table[] = { {"blade", "{BB{blad{Be{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_BLADE, 20000}, {"protection", "{RP{rrotectio{Rn {xof the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_ARMOR, 15000}, {"gauntlets", "{GG{gauntlet{Gs{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's", QUEST_GAUNTLET, 9000}, {"tattoo", "{RT{ratto{Ro{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_TATTOO, 5000}, {"leggings", "{WL{Degging{Ws{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_LEGGING, 5000}, {"boots", "{DB{moot{Ds {xof the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_BOOT, 5000}, {"mask", "{CM{cas{Ck{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_MASK, 5000}, {"helm", "{YH{yel{Ym{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_HELM, 5000}, {"belt", "{BB{gel{Bt{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_BELT, 5000}, {"orb", "{CO{Br{Cb{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_ORB, 5000}, {"earring", "{ME{Darrin{Mg{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_EARRING, 5000}, {"shield", "{DS{Ghiel{Dd{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_SHIELD, 5000}, {"ring", "{MR{min{Mg{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_RING, 5000}, {"cloak", "{DC{gloa{Dk {xof the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_CLOAK, 5000}, {"neckguard", "{WN{Deckguar{Wd {xof the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_NECKLACE, 5000}, {"anklet", "{gA{cnkle{gt{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_ANKLET, 5000}, {"bracer", "{BB{Drace{Br{x of the {YA{yn{Yc{yi{Ye{yn{Yt{y's{x", QUEST_BRACER, 5000}, {"aura", "{CA{Wu{Cr{Wa{x of the {YA{yn{Yc{yi{Ye{yn{Yt{ys{x", QUEST_AURA, 5000}, {"sleeves", "{RS{cl{Re{ce{Rv{ce{Rs{x of the {YA{yn{Yc{yi{Ye{yn{Yt{ys{x", QUEST_SLEEVE, 5000}, {"flame", "{RF{Yl{Ra{Ym{Re{x of the {YA{yn{Yc{yi{Ye{yn{Yt{ys{x", QUEST_FLAME, 5000}, {"wticket", "{wA {WW{ghostrin{Wg{G Ticket (Quest Buy WTicket){x", QUEST_WHOTICK, 3000}, {"sticket", "{wA {WR{gestrin{Wg {GTicket (Quest Buy STicket){x", QUEST_STRINGTICK, 2000}, {NULL, 0, 0} }; /* Quests to find objects */ #define QUEST_OBJQUEST1 3315 #define QUEST_OBJQUEST2 3316 #define QUEST_OBJQUEST3 3317 #define QUEST_OBJQUEST4 3318 /* * CHANCE function. I use this everywhere in my code, very handy :> */ bool chance ( int num ) { if ( number_range ( 1, 100 ) <= num ) return TRUE; else return FALSE; } /* is object in quest table? */ int is_qobj ( OBJ_DATA * obj ) { int i; if ( !obj || !obj->pIndexData ) return -1; for ( i = 0; quest_table[i].name != NULL; i++ ) { if ( obj->pIndexData->vnum == quest_table[i].vnum ) return i; } return -1; } /* get the cost of an object in questpoints */ int qobj_cost ( OBJ_DATA * obj ) { int i; if ( !obj || !obj->pIndexData ) return 0; for ( i = 0; quest_table[i].name != NULL; i++ ) { if ( obj->pIndexData->vnum == quest_table[i].vnum ) return quest_table[i].cost; } return 0; } /* * * Add or enhance an obj affect. */ void affect_join_obj ( OBJ_DATA * obj, AFFECT_DATA * paf ) { AFFECT_DATA *paf_old; bool found; found = FALSE; for ( paf_old = obj->affected; paf_old != NULL; paf_old = paf_old->next ) { if ( paf_old->location == paf->location ) { paf_old->level = paf->level; paf_old->modifier = paf->modifier; found = TRUE; } } if ( !found ) affect_to_obj ( obj, paf ); return; } /* Nice little addapply function */ void add_apply ( OBJ_DATA * obj, int loc, int mod, int where, int type, int dur, long bit, int level ) { AFFECT_DATA pAf; if ( obj == NULL ) return; if ( !obj->enchanted ) affect_enchant ( obj ); pAf.location = loc; pAf.modifier = mod; pAf.where = where; pAf.type = type; pAf.duration = dur; pAf.bitvector = bit; pAf.level = level; affect_join_obj ( obj, &pAf ); return; } /* Update a questobject */ void update_questobjs ( CHAR_DATA * ch, OBJ_DATA * obj ) { int bonus, pbonus, cost; if ( obj == NULL || obj->pIndexData == NULL ) { bug ( "update_questobjs: NULL obj", 0 ); return; } if ( ch == NULL ) { bug ( "update_questobjs: NULL ch", 0 ); return; } if ( !IS_OBJ_STAT ( obj, ITEM_QUEST ) && is_qobj ( obj ) == -1 ) return; bonus = UMAX ( 5, ch->level / 2 ); pbonus = UMAX ( 5, ch->level / 2 ); cost = qobj_cost ( obj ); if ( obj->level != ch->level ) obj->level = ch->level; if ( obj->condition != -1 ) obj->condition = -1; if ( obj->cost != cost ) obj->cost = cost; if ( !CAN_WEAR ( obj, ITEM_NO_SAC ) ) SET_BIT ( obj->wear_flags, ITEM_NO_SAC ); if ( !IS_OBJ_STAT ( obj, ITEM_BURN_PROOF ) ) SET_BIT ( obj->extra_flags, ITEM_BURN_PROOF ); if ( obj->pIndexData->vnum == QUEST_ARMOR ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level * 7 ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level * 7 ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level * 7 ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_SHIELD ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_TATTOO ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_MASK ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_EARRING ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_AURA ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_BRACER ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_NECKLACE ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_ORB ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_ANKLET ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_BELT ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_CLOAK ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_RING ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_HELM ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_GAUNTLET ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_BOOT ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_LEGGING ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_SLEEVE ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->pIndexData->vnum == QUEST_FLAME ) { add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level / 2 ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level / 2 ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level * 2 ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level * 2 ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level ), TO_OBJECT, 0, -1, 0, ch->level * 2 ); } else if ( obj->item_type == ITEM_CONTAINER ) { obj->weight = -1 * ( 50 + ( ch->level * 1.5 ) ); obj->value[0] = 1000 + ( 20 * ch->level ); obj->value[3] = 1000 + ( 20 * ch->level ); } if ( obj->item_type == ITEM_WEAPON ) { obj->value[1] = UMAX ( 15, ch->level ); obj->value[2] = ch->level < 80 ? 6 : 8; add_apply ( obj, APPLY_DAMROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HITROLL, pbonus, TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_HIT, UMAX ( 50, ch->level * 4 ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MANA, UMAX ( 50, ch->level * 4 ), TO_OBJECT, 0, -1, 0, ch->level ); add_apply ( obj, APPLY_MOVE, UMAX ( 50, ch->level * 4 ), TO_OBJECT, 0, -1, 0, ch->level ); } else if ( obj->item_type == ITEM_ARMOR ) { obj->value[0] = UMAX ( 20, ch->level * 4 / 3 ); obj->value[1] = UMAX ( 20, ch->level * 4 / 3 ); obj->value[2] = UMAX ( 20, ch->level * 4 / 3 ); obj->value[3] = ( 5 * UMAX ( 20, ch->level * 4 / 3 ) ) / 6; } else if ( obj->item_type == ITEM_STAFF ) obj->value[0] = UMAX ( 40, ch->level / 3 ); return; } /* Usage info on the QUEST commands*/ /* Keep this in line with the do_quest function's keywords */ void quest_usage ( CHAR_DATA * ch ) { send_to_char ( "{YQUEST commands: POINTS INFO TIME REQUEST COMPLETE LIST BUY QUIT SELL REPLACE.{x\n\r", ch ); send_to_char ( "{YFor more information, type 'HELP QUEST'.{x\n\r", ch ); return; } /* Obtain additional location information about sought item/mob */ void quest_where ( CHAR_DATA * ch, char *what ) { char buf[MAX_INPUT_LENGTH]; ROOM_INDEX_DATA *room; if ( !ch || IS_NPC ( ch ) ) return; if ( ch->pcdata->questloc <= 0 ) { bug ( "QUEST INFO: ch->questloc = %ld", ch->pcdata->questloc ); return; } if ( ch->in_room == NULL ) return; room = get_room_index ( ch->pcdata->questloc ); if ( room->area == NULL ) { bug ( "QUEST INFO: room(%ld)->area == NULL", ch->pcdata->questloc ); return; } if ( room->area->name == NULL ) { bug ( "QUEST INFO: area->name == NULL", 0 ); return; } sprintf ( buf, "{RRumor has it this %s was last seen in the area known as %s,{x\n\r", what, room->area->name ); send_to_char ( buf, ch ); if ( room->name == NULL ) { bug ( "QUEST INFO: room(%ld)->name == NULL", ch->pcdata->questloc ); return; } sprintf ( buf, "{Rnear %s.{x\n\r", room->name ); send_to_char ( buf, ch ); } /* end quest_where() */ /* Does player have thier target object? */ OBJ_DATA *has_questobj ( CHAR_DATA * ch ) { OBJ_DATA *obj; OBJ_INDEX_DATA *pObj; if ( !ch || IS_NPC ( ch ) || ch->pcdata->questobj <= 0 ) return NULL; if ( ( pObj = get_obj_index ( ch->pcdata->questobj ) ) == NULL ) return NULL; for ( obj = ch->carrying; obj != NULL; obj = obj->next_content ) if ( obj != NULL && obj->pIndexData == pObj ) return obj; return NULL; } /* * The main quest function */ CH_CMD ( do_quest ) { CHAR_DATA *questman; OBJ_DATA *obj = NULL; // EXTRA_DESCR_DATA *ed; OBJ_INDEX_DATA *questinfoobj; MOB_INDEX_DATA *questinfo; char buf[MSL]; char arg1[MIL]; char arg2[MIL]; int i = 0; if ( !ch ) return; if ( IS_NPC ( ch ) ) { send_to_char ( "I'm sorry, you can't quest.\n\r", ch ); return; } argument = one_argument ( argument, arg1 ); argument = one_argument ( argument, arg2 ); if ( arg1[0] == '\0' ) { quest_usage ( ch ); return; } if ( !str_cmp ( arg1, "info" ) ) { MOB_INDEX_DATA *qm_mobindex; if ( !IS_QUESTOR ( ch ) ) { send_to_char ( "You aren't currently on a quest.\n\r", ch ); return; } send_to_char ( "\n\r", ch ); if ( ch->pcdata->questgiver <= 0 ) { bug ( "QUEST INFO: quest giver = %d", ch->pcdata->questgiver ); send_to_char ( "{RIt seems your quest master died of old age waiting for you.{x\n\r", ch ); end_quest ( ch, 5 ); return; } qm_mobindex = get_mob_index ( ch->pcdata->questgiver ); if ( qm_mobindex == NULL ) { bug ( "QUEST INFO: quest giver %d has no MOB_INDEX_DATA!", ch->pcdata->questgiver ); send_to_char ( "{RYour quest master has fallen very ill. Please contact an imm!{x\n\r", ch ); end_quest ( ch, 5 ); return; } if ( ch->pcdata->questmob == -1 || has_questobj ( ch ) ) /* killed target mob */ { send_to_char ( "{RYour quest is {fALMOST{x{R complete!{x\n\r", ch ); sprintf ( buf, "{RGet back to %s{R before your time runs out!{x\n\r", ( qm_mobindex->short_descr == NULL ? "your quest master" : qm_mobindex-> short_descr ) ); send_to_char ( buf, ch ); return; } else if ( ch->pcdata->questobj > 0 ) /* questing for an object */ { questinfoobj = get_obj_index ( ch->pcdata->questobj ); if ( questinfoobj != NULL ) { printf_to_char ( ch, "{RYou recall the quest which the %s{R gave you.{x\n\r", ( qm_mobindex->short_descr == NULL ? "your quest master" : qm_mobindex-> short_descr ) ); sprintf ( buf, "{RYou are on a quest to recover the fabled %s{R!{x\n\r", questinfoobj->name ); send_to_char ( buf, ch ); quest_where ( ch, "treasure" ); return; } /* quest object not found! */ bug ( "No info for quest object %d", ch->pcdata->questobj ); ch->pcdata->questobj = 0; REMOVE_BIT ( ch->act, PLR_QUESTOR ); /* no RETURN -- fall thru to 'no quest', below */ } else if ( ch->pcdata->questmob > 0 ) /* questing for a mob */ { questinfo = get_mob_index ( ch->pcdata->questmob ); if ( questinfo != NULL ) { sprintf ( buf, "{RYou are on a quest to slay the dreaded %s{R!{x\n\r", questinfo->short_descr ); send_to_char ( buf, ch ); quest_where ( ch, "fiend" ); return; } /* quest mob not found! */ bug ( "No info for quest mob %d", ch->pcdata->questmob ); ch->pcdata->questmob = 0; /* Changed to mob instead of obj - Lotus */ REMOVE_BIT ( ch->act, PLR_QUESTOR ); /* no RETURN -- fall thru to 'no quest', below */ } /* we shouldn't be here */ bug ( "QUEST INFO: Questor with no kill, mob or obj", 0 ); return; } if ( !str_cmp ( arg1, "points" ) ) { sprintf ( buf, "{WYou have {r%-8ld{W AQP{x\n\r{WYou have {r%-8d {WIQP{x\n\r", ch->pcdata->questpoints, ch->qps ); send_to_char ( buf, ch ); return; } else if ( !str_cmp ( arg1, "time" ) ) { if ( !IS_SET ( ch->act, PLR_QUESTOR ) ) { send_to_char ( "You aren't currently on a quest.\n\r", ch ); if ( ch->pcdata->nextquest > 1 ) { sprintf ( buf, "There are %d minutes remaining until you can go on another quest.\n\r", ch->pcdata->nextquest ); send_to_char ( buf, ch ); } else if ( ch->pcdata->nextquest == 1 ) { sprintf ( buf, "There is less than a minute remaining until you can go on another quest.\n\r" ); send_to_char ( buf, ch ); } } else if ( ch->pcdata->countdown > 0 ) { sprintf ( buf, "Time left for current quest: %d\n\r", ch->pcdata->countdown ); send_to_char ( buf, ch ); } return; } /* * Checks for a character in the room with spec_questmaster set. This * special procedure must be defined in special.c. You could instead use * an ACT_QUESTMASTER flag instead of a special procedure. */ for ( questman = ch->in_room->people; questman != NULL; questman = questman->next_in_room ) { if ( !IS_NPC ( questman ) ) continue; if ( questman->spec_fun == spec_lookup ( "spec_questmaster" ) ) break; } if ( questman == NULL || questman->spec_fun != spec_lookup ( "spec_questmaster" ) ) { send_to_char ( "You can't do that here.\n\r", ch ); return; } if ( questman->fighting != NULL ) { send_to_char ( "Wait until the fighting stops.\n\r", ch ); return; } /* * And, of course, you will need to change the following lines for YOUR * quest item information. Quest items on Moongate are unbalanced, very * very nice items, and no one has one yet, because it takes awhile to * build up quest points :> Make the item worth their while. */ if ( !str_cmp ( arg1, "list" ) ) { act ( "$n asks $N for a list of quest items.", ch, NULL, questman, TO_ROOM ); send_to_char ( "\t{YCurrent Quest Items available for Purchase:{x\n\r", ch ); for ( i = 0; quest_table[i].who_name != NULL; i++ ) printf_to_char ( ch, "\t%-5dqp ........ %s{x\n\r", quest_table[i].cost, quest_table[i].who_name ); // printf_to_char(ch," 500 qp ........ {R25 {WI{wqp ({Wquest buy iqp{x){x\n\r"); send_to_char ( "\tTo buy an item, type 'QUEST BUY <item>'.\n\r", ch ); send_to_char ( "\tFor more info on quest items type 'help questitems'\n\r", ch ); return; } else if ( !str_cmp ( arg1, "buy" ) ) { if ( arg2[0] == '\0' ) { send_to_char ( "To buy an item, type 'QUEST BUY <item>'.\n\r", ch ); return; } if ( !str_cmp ( arg1, "iqp" ) ) { if ( ch->pcdata->questpoints >= 500 ) { ch->pcdata->questpoints -= 500; ch->qps += 25; } else { sprintf ( buf, "Sorry, %s, but you don't have enough quest points for that.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } } for ( i = 0; quest_table[i].name != NULL; i++ ) { if ( is_name ( arg2, quest_table[i].name ) ) { if ( ch->pcdata->questpoints >= quest_table[i].cost ) { if ( quest_table[i].vnum == 0 ) { ch->pcdata->questpoints -= quest_table[i].cost; ch->pcdata->condition[COND_FULL] = -51; ch->pcdata->condition[COND_THIRST] = -51; act ( "$N calls upon the power of the gods to relieve your mortal burdens.", ch, NULL, questman, TO_CHAR ); act ( "$N calls upon the power of the gods to relieve $n' mortal burdens.", ch, NULL, questman, TO_ROOM ); return; } else if ( ( obj = create_object ( get_obj_index ( quest_table[i].vnum ), ch->level ) ) == NULL ) { send_to_char ( "That object could not be found, contact an immortal.\n\r", ch ); return; } else { ch->pcdata->questpoints -= quest_table[i].cost; if ( !IS_IMMORTAL ( ch ) ) { sprintf ( buf, "Bought %s for %d questpoints.", quest_table[i].name, quest_table[i].cost ); append_file ( ch, QUEST_FILE, buf ); } } /* this is my object owner code ed = new_extra_descr(); ed->keyword = str_dup(KEYWD_OWNER); ed->description = str_dup(ch->name); ed->next = obj->extra_descr; obj->extra_descr = ed; */ if ( !IS_SET ( obj->pIndexData->extra_flags, ITEM_QUEST ) ) { SET_BIT ( obj->pIndexData->extra_flags, ITEM_QUEST ); SET_BIT ( obj->extra_flags, ITEM_QUEST ); SET_BIT ( obj->pIndexData->area->area_flags, AREA_CHANGED ); } act ( "$N gives $p to $n.", ch, obj, questman, TO_ROOM ); act ( "$N gives you $p.", ch, obj, questman, TO_CHAR ); obj_to_char ( obj, ch ); save_char_obj ( ch ); return; } else { sprintf ( buf, "Sorry, %s, but you need %d quest points for that.", ch->name, quest_table[i].cost ); do_mob_tell ( ch, questman, buf ); return; } } } sprintf ( buf, "I don't have that item, %s.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } else if ( !str_cmp ( arg1, "sell" ) ) { if ( arg2[0] == '\0' ) { send_to_char ( "To sell an item, type 'QUEST SELL <item>'.\n\r", ch ); return; } if ( ( obj = get_obj_carry ( ch, arg2 ) ) == NULL ) { send_to_char ( "Which item is that?\n\r", ch ); return; } if ( !IS_OBJ_STAT ( obj, ITEM_QUEST ) ) { sprintf ( buf, "That is not a quest item, %s.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } for ( i = 0; quest_table[i].name != NULL; i++ ) { if ( quest_table[i].vnum <= 0 ) continue; if ( quest_table[i].vnum == obj->pIndexData->vnum ) { ch->pcdata->questpoints += quest_table[i].cost / 3; act ( "$N takes $p from $n.", ch, obj, questman, TO_ROOM ); sprintf ( buf, "$N takes $p from you for %d quest points.", quest_table[i].cost / 3 ); act ( buf, ch, obj, questman, TO_CHAR ); extract_obj ( obj ); save_char_obj ( ch ); return; } } sprintf ( buf, "I only take items I sell, %s.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } else if ( !str_cmp ( arg1, "replace" ) ) { if ( arg2[0] == '\0' ) { send_to_char ( "To replace an item, type 'QUEST REPLACE <item>'.\n\r", ch ); return; } if ( ( obj = get_obj_carry ( ch, arg2 ) ) == NULL ) { send_to_char ( "Which item is that?\n\r", ch ); return; } if ( !IS_OBJ_STAT ( obj, ITEM_QUEST ) ) { sprintf ( buf, "That is not a quest item, %s.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } if ( ch->pcdata->questpoints < 75 ) { do_mob_tell ( ch, questman, "It costs 75 questpoints to replace an item." ); return; } for ( i = 0; quest_table[i].name != NULL; i++ ) { if ( quest_table[i].vnum <= 0 ) continue; if ( quest_table[i].vnum == obj->pIndexData->vnum ) { OBJ_DATA *newobj; if ( ( newobj = create_object ( get_obj_index ( quest_table[i].vnum ), ch->level ) ) == NULL ) { sprintf ( buf, "I could not find a new quest item for you %s.", ch->name ); do_mob_tell ( ch, questman, buf ); } else { /* this is my object owner code ed = new_extra_descr(); ed->keyword = str_dup(KEYWD_OWNER); ed->description = str_dup(ch->name); ed->next = obj->extra_descr; obj->extra_descr = ed; */ obj_to_char ( newobj, ch ); extract_obj ( obj ); ch->pcdata->questpoints -= 75; act ( "$N takes $p from $n and gives $m a new one.", ch, obj, questman, TO_ROOM ); act ( "$N replaces $p with a new one for 75 quest points.", ch, obj, questman, TO_CHAR ); save_char_obj ( ch ); } return; } } sprintf ( buf, "I only replace items I sell, %s.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } else if ( !str_cmp ( arg1, "request" ) ) { act ( "$n asks $N for a quest.", ch, NULL, questman, TO_ROOM ); act ( "You ask $N for a quest.", ch, NULL, questman, TO_CHAR ); if ( IS_SET ( ch->act, PLR_QUESTOR ) ) { do_mob_tell ( ch, questman, "But you're already on a quest!" ); return; } if ( ch->pcdata->nextquest > 0 ) { sprintf ( buf, "You're very brave, %s, but let someone else have a chance.", ch->name ); do_mob_tell ( ch, questman, buf ); do_mob_tell ( ch, questman, "Come back later." ); return; } sprintf ( buf, "Thank you, brave %s!", ch->name ); do_mob_tell ( ch, questman, buf ); ch->pcdata->questmob = 0; ch->pcdata->questobj = 0; generate_quest ( ch, questman ); return; } else if ( !str_cmp ( arg1, "complete" ) ) { if ( ch->pcdata->questgiver != questman->pIndexData->vnum ) { do_mob_tell ( ch, questman, "I never sent you on a quest! Perhaps you're thinking of someone else." ); return; } if ( IS_SET ( ch->act, PLR_QUESTOR ) ) { int reward, pracreward, points; if ( ch->pcdata->questmob == -1 && ch->pcdata->countdown > 0 ) { reward = number_range ( 100, 800 ); points = number_range ( 25, 75 ); act ( "$n informs $N $e has completed $s quest.", ch, NULL, questman, TO_ROOM ); act ( "You inform $N you have completed $s quest.", ch, NULL, questman, TO_CHAR ); do_mob_tell ( ch, questman, "Congratulations on completing your quest!" ); sprintf ( buf, "As a reward, I am giving you %d quest points, and %d gold.", points, reward ); do_mob_tell ( ch, questman, buf ); if ( double_qp ) { sprintf ( buf, "You recive an extra %d quest points due to doubleqp!!", points ); do_mob_tell ( ch, questman, buf ); } if ( chance ( 15 ) ) { pracreward = number_range ( 1, 6 ); sprintf ( buf, "You gain %d practices!\n\r", pracreward ); send_to_char ( buf, ch ); ch->practice += pracreward; } end_quest ( ch, 8 ); add_cost ( ch, reward, VALUE_GOLD ); ch->pcdata->questpoints += points; if ( double_qp ) { ch->pcdata->questpoints += points; } save_char_obj ( ch ); return; } else if ( ch->pcdata->questobj > 0 && ch->pcdata->countdown > 0 ) { if ( ( obj = has_questobj ( ch ) ) != NULL ) { reward = number_range ( 150, 1250 ); points = number_range ( 50, 100 ); act ( "$n informs $N $e has completed $s quest.", ch, NULL, questman, TO_ROOM ); act ( "You inform $N you have completed $s quest.", ch, NULL, questman, TO_CHAR ); act ( "You hand $p to $N.", ch, obj, questman, TO_CHAR ); act ( "$n hands $p to $N.", ch, obj, questman, TO_ROOM ); do_mob_tell ( ch, questman, "Congratulations on completing your quest!" ); sprintf ( buf, "As a reward, I am giving you %d quest points, and %d gold.", points, reward ); do_mob_tell ( ch, questman, buf ); if ( double_qp ) { sprintf ( buf, "You recive an extra %d quest points due to doubleqp!!", points ); do_mob_tell ( ch, questman, buf ); } if ( chance ( 15 ) ) { pracreward = number_range ( 1, 6 ); sprintf ( buf, "You gain %d practices!\n\r", pracreward ); send_to_char ( buf, ch ); ch->practice += pracreward; } end_quest ( ch, 8 ); add_cost ( ch, reward, VALUE_GOLD ); ch->pcdata->questpoints += points; if ( double_qp ) { ch->pcdata->questpoints += points; } extract_obj ( obj ); save_char_obj ( ch ); return; } else { do_mob_tell ( ch, questman, "You haven't completed the quest yet, but there is still time!" ); return; } return; } else if ( ( ch->pcdata->questmob > 0 || ch->pcdata->questobj > 0 ) && ch->pcdata->countdown > 0 ) { do_mob_tell ( ch, questman, "You haven't completed the quest yet, but there is still time!" ); return; } } if ( ch->pcdata->nextquest > 0 ) sprintf ( buf, "But you didn't complete your quest in time!" ); else sprintf ( buf, "You have to REQUEST a quest first, %s.", ch->name ); do_mob_tell ( ch, questman, buf ); return; } else if ( !str_cmp ( arg1, "quit" ) || !str_cmp ( arg1, "fail" ) ) { act ( "$n informs $N $e wishes to quit $s quest.", ch, NULL, questman, TO_ROOM ); act ( "You inform $N you wish to quit $s quest.", ch, NULL, questman, TO_CHAR ); if ( ch->pcdata->questgiver != questman->pIndexData->vnum ) { do_mob_tell ( ch, questman, "I never sent you on a quest! Perhaps you're thinking of someone else." ); return; } if ( IS_SET ( ch->act, PLR_QUESTOR ) ) { end_quest ( ch, 30 ); do_mob_tell ( ch, questman, "Your quest is over, but for your cowardly behavior, you may not quest again for 30 minutes." ); return; } else { send_to_char ( "You aren't on a quest!", ch ); return; } } send_to_char ( "Quest commands: Info, Time, Request, Complete, Quit, List, Sell and Buy.\n\r", ch ); send_to_char ( "For more information, type 'Help Quest'.\n\r", ch ); return; } #define MAX_QMOB_COUNT mobile_count /* do all mobs what the heck */ void generate_quest ( CHAR_DATA * ch, CHAR_DATA * questman ) { CHAR_DATA *victim = NULL; ROOM_INDEX_DATA *room = NULL; CHAR_DATA *mobs[MAX_QMOB_COUNT]; size_t mob_count; OBJ_DATA *questitem = NULL; char buf[MSL]; int mrange; /* * * find MAX_QMOB_COUNT quest mobs and store their vnums in mob_buf */ mob_count = 0; for ( victim = char_list; victim; victim = victim->next ) { if ( !IS_NPC ( victim ) || !quest_level_diff ( ch, victim ) || ( victim->pIndexData == NULL || victim->in_room == NULL || victim->pIndexData->pShop != NULL ) || ( IS_EVIL ( victim ) && IS_EVIL ( ch ) && chance ( 50 ) ) || ( IS_GOOD ( victim ) && IS_GOOD ( ch ) && chance ( 50 ) ) || victim->pIndexData->vnum < 100 || IS_SET ( victim->imm_flags, IMM_WEAPON | IMM_MAGIC ) || IS_SET ( victim->act, ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER | ACT_PET | ACT_IS_PRIEST | ACT_PET | ACT_GAIN ) || IS_SET ( victim->affected_by, AFF_CHARM ) || questman->pIndexData == victim->pIndexData || ( ( IS_SET ( victim->act, ACT_SENTINEL ) ) && IS_SET ( victim->in_room->room_flags, ROOM_PRIVATE | ROOM_SOLITARY | ROOM_SAFE ) ) ) continue; mobs[mob_count++] = victim; if ( mob_count >= MAX_QMOB_COUNT ) break; } if ( mob_count == 0 ) { do_mob_tell ( ch, questman, "I'm sorry, but I don't have any quests for you at this time." ); do_mob_tell ( ch, questman, "Try again later." ); end_quest ( ch, 2 ); return; } /* * at this point the player is sure to get a quest */ ch->pcdata->questgiver = questman->pIndexData->vnum; mrange = number_range ( 0, mob_count - 1 ); while ( ( victim = mobs[mrange] ) == NULL ) mrange = number_range ( 0, mob_count - 1 ); room = victim->in_room; ch->pcdata->questloc = room->vnum; ch->pcdata->countdown = number_range ( 12, 30 ); /* * 20% chance it will send the player on a 'recover item' quest. Changed * to 15 by Markanth */ if ( chance ( 20 ) ) { long objvnum = 0; switch ( number_range ( 0, 3 ) ) { case 0: objvnum = QUEST_OBJQUEST1; break; case 1: objvnum = QUEST_OBJQUEST2; break; case 2: objvnum = QUEST_OBJQUEST3; break; case 3: objvnum = QUEST_OBJQUEST4; break; } questitem = create_object ( get_obj_index ( objvnum ), ch->level ); obj_to_room ( questitem, room ); REMOVE_BIT ( ch->act, PLR_CANLOOT ); free_string ( questitem->owner ); questitem->owner = str_dup ( ch->name ); questitem->cost = 0; questitem->timer = ( 4 * ch->pcdata->countdown + 10 ) / 3; ch->pcdata->questobj = questitem->pIndexData->vnum; switch ( number_range ( 0, 1 ) ) { default: case 0: sprintf ( buf, "Vile pilferers have stolen %s from the royal treasury!", questitem->short_descr ); do_mob_tell ( ch, questman, buf ); do_mob_tell ( ch, questman, "My court wizardess, with her magic mirror, has pinpointed its location." ); break; case 1: sprintf ( buf, "A powerful wizard has stolen %s for his personal power!", questitem->short_descr ); do_mob_tell ( ch, questman, buf ); break; } if ( room->name != NULL ) { sprintf ( buf, "Look for %s somewhere in the vicinity of %s!", questitem->short_descr, room->name ); do_mob_tell ( ch, questman, buf ); sprintf ( buf, "That location is in the general area of %s.", room->area->name ); do_mob_tell ( ch, questman, buf ); } } /* * Quest to kill a mob */ else { switch ( number_range ( 0, 3 ) ) { default: case 0: sprintf ( buf, "An enemy of mine, %s, is making vile threats against the crown.", victim->short_descr ); do_mob_tell ( ch, questman, buf ); do_mob_tell ( ch, questman, "This threat must be eliminated!" ); break; case 1: sprintf ( buf, "Thera's most heinous criminal, %s, has escaped from the dungeon!", victim->short_descr ); do_mob_tell ( ch, questman, buf ); sprintf ( buf, "Since the escape, %s has murdered %d civillians!", victim->short_descr, number_range ( 2, 20 ) ); do_mob_tell ( ch, questman, buf ); do_mob_tell ( ch, questman, "The penalty for this crime is death, and you are to deliver the sentence!" ); break; case 2: sprintf ( buf, "The King of Gaalstrom has recently been attacked by %s. This is an act of war!", victim->short_descr ); do_mob_tell ( ch, questman, buf ); sprintf ( buf, "%s must be severly dealt with for this injustice.", victim->short_descr ); do_mob_tell ( ch, questman, buf ); break; case 3: sprintf ( buf, "%s has been stealing valuables from the citizens of Gaalstrom.", victim->short_descr ); do_mob_tell ( ch, questman, buf ); sprintf ( buf, "Make sure that %s never has the chance to steal again.", victim->short_descr ); do_mob_tell ( ch, questman, buf ); break; } if ( room->name != NULL ) { sprintf ( buf, "Seek %s out somewhere in the vicinity of %s!", victim->short_descr, room->name ); do_mob_tell ( ch, questman, buf ); sprintf ( buf, "That location is in the general area of %s.", room->area->name ); do_mob_tell ( ch, questman, buf ); } ch->pcdata->questmob = victim->pIndexData->vnum; } if ( ch->pcdata->questmob > 0 || ch->pcdata->questobj > 0 ) { SET_BIT ( ch->act, PLR_QUESTOR ); sprintf ( buf, "You have %d minutes to complete this quest.", ch->pcdata->countdown ); do_mob_tell ( ch, questman, buf ); do_mob_tell ( ch, questman, "May the gods go with you!" ); } else end_quest ( ch, 2 ); return; } bool quest_level_diff ( CHAR_DATA * ch, CHAR_DATA * mob ) { int bonus = 20 + ch->level; if ( IS_IMMORTAL ( ch ) ) return TRUE; else if ( ch->level > ( mob->level + bonus ) || ch->level < ( mob->level - bonus ) ) return FALSE; else return TRUE; } void quest_update ( void ) { DESCRIPTOR_DATA *d; CHAR_DATA *ch; for ( d = descriptor_list; d != NULL; d = d->next ) { if ( d->connected == CON_PLAYING && ( ch = ( d->original ? d->original : d->character ) ) != NULL ) { if ( ch->pcdata->nextquest > 0 ) { ch->pcdata->nextquest--; if ( ch->pcdata->nextquest == 0 ) { send_to_char ( "You may now quest again.\n\r", ch ); return; } } else if ( IS_SET ( ch->act, PLR_QUESTOR ) ) { if ( --ch->pcdata->countdown <= 0 ) { printf_to_char ( ch, "You have run out of time for your quest!\n\rYou may quest again in %d minutes.\n\r", ch->pcdata->nextquest ); end_quest ( ch, 18 ); } if ( ch->pcdata->countdown > 0 && ch->pcdata->countdown < 6 ) { send_to_char ( "Better hurry, you're almost out of time for your quest!\n\r", ch ); return; } } } } return; } void end_quest ( CHAR_DATA * ch, int time ) { REMOVE_BIT ( ch->act, PLR_QUESTOR ); ch->pcdata->questgiver = 0; ch->pcdata->countdown = 0; ch->pcdata->questmob = 0; ch->pcdata->questobj = 0; ch->pcdata->questloc = 0; ch->pcdata->nextquest = time; } void do_mob_tell ( CHAR_DATA * ch, CHAR_DATA * victim, char *argument ) { char buf[MSL]; sprintf ( buf, "{R%s{R tells you '{W%s{R'{x\n\r", victim->short_descr, argument ); send_to_char ( buf, ch ); // ch->reply = victim; return; } CH_CMD ( do_qpgive ) { CHAR_DATA *victim; char arg[MIL], buf[MIL]; int amount; if ( !ch || IS_NPC ( ch ) ) return; argument = one_argument ( argument, arg ); if ( argument[0] == '\0' || !is_number ( arg ) ) { send_to_char ( "Syntax: qpgive [amount] [person]\n\r", ch ); return; } if ( ( amount = atoi ( arg ) ) <= 0 ) { send_to_char ( "Give how many questpoints?\n\r", ch ); return; } if ( amount > ch->pcdata->questpoints ) { send_to_char ( "You don't have that many questpoints to give.\n\r", ch ); return; } if ( ( victim = get_char_room ( ch, argument ) ) == NULL ) { send_to_char ( "That person is not here.\n\r", ch ); return; } ch->pcdata->questpoints -= amount; victim->pcdata->questpoints += amount; sprintf ( buf, "%d", amount ); act ( "$n gives you $t questpoints.", ch, buf, victim, TO_VICT ); act ( "You give $N $t questpoints.", ch, buf, victim, TO_CHAR ); act ( "$n gives $N $t questpoints.", ch, buf, victim, TO_ROOM ); return; }