/**************************************************************************** * 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@spaceservices.net * 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 <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "merc.h" #include "const.h" DECLARE_DO_FUN( do_restore ); DECLARE_DO_FUN( do_transfer ); DECLARE_SPELL_FUN( spell_identify ); extern int mobile_count; void do_function args((CHAR_DATA *ch, DO_FUN *do_fun, char *argument)); struct quest_type { char *name; char *who_name; int vnum; int cost; }; #define QUEST_ARMS 46 #define QUEST_AURA 234 #define QUEST_LEGGINGS 233 #define QUEST_SWORD 213 #define QUEST_BPLATE 212 #define QUEST_BOOTS 44 #define QUEST_MASK 211 #define QUEST_GLOVES 224 #define QUEST_FLAME 232 #define QUEST_HELM 55 #define QUEST_WINGS 52 #define QUEST_BAG 230 #define QUEST_SHIELD 63 #define QUEST_REGEN 227 #define QUEST_INVIS 43 #define QUEST_DEED 216 #define QUEST_DAGGER 99 #define QUEST_DECANT 45 #define QUEST_TRIVIA OBJ_VNUM_TRIVIA_PILL #define OBJ_VNUM_TRIVIA_PILL 215 /* * Object vnums for Quest Rewards */ const struct quest_type quest_table[] = { {"nohunger", "{YNo Hunger/Thirst (quest buy nohunger){x", 0, 3000}, {"aura", "{YAura{W of {RSanctuary{x", QUEST_AURA, 2600}, {"leggings", "{YThe{W leggings of the {RGods{x", QUEST_LEGGINGS, 2600}, {"sword", "{YSword{W of the {RAncients{x", QUEST_SWORD, 2500}, {"breastplate", "{YBreastPlate{W of the {RAncients{x", QUEST_BPLATE, 2500}, {"boots", "{YBoots{W of {RHell{x", QUEST_BOOTS, 2500}, {"mask", "{YMask{W of the {RAncients{x", QUEST_MASK, 2500}, {"gloves", "{YGloves{W of {RProtection{x", QUEST_GLOVES, 2500}, {"flame", "{YFlame{W of the {RAncients{x", QUEST_FLAME, 2500}, {"helm", "{YHelm{W of {RCaptured Inferno{x", QUEST_HELM, 2300}, {"wings", "{YWings{W of the {RPegasus{x", QUEST_WINGS, 2000}, {"bag", "{YBag{W of the {RAncients{x", QUEST_BAG, 1000}, {"shield", "{YShield{W of {RThought{x", QUEST_SHIELD, 1500}, {"regeneration", "{YRing{W of {RRegeneration{x", QUEST_REGEN, 700}, {"invisibility", "{YCloak{W of {RInvisibility{x", QUEST_INVIS, 500}, {"dagger", "{GDagger of Acidx", QUEST_DAGGER, 1500}, {"deed", "{WAn {YOfficial {RDeed{x", QUEST_DEED, 500}, {"decanter", "{CDecanter of Endless Water{x", QUEST_DECANT, 500}, {"shoulder", "{CPads with diamond spiked tips{x", QUEST_ARMS, 2000}, {"trivia", "{YTrivia {RPill{x", QUEST_TRIVIA, 100}, {"frequent", "{YFrequent {RQuestor{x", 1, 1000 }, {"levelflux", "{YLevelflux{x", 2, 10000 }, {"train", "{Y100 {RTrains{x", 3, 2000 }, {"practice", "{Y1000 {RPractices{x", 4, 2000 }, {"dblquest", "{YDouble {RQuest{x", 5, 5000 }, {NULL, 0, 0} }; /* Quests to find objects */ #define QUEST_OBJQUEST1 71 #define QUEST_OBJQUEST2 78 #define QUEST_OBJQUEST3 82 #define QUEST_OBJQUEST4 92 /* * 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; } 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; } void add_apply(OBJ_DATA * obj, int loc, int mod, int where, int type, int dur,int vector, 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 = vector; pAf.level = level; affect_join_obj(obj, &pAf); return; } /* Updates a quest object. AFFECTS like sanctuary ect.. are done in game or on area file. (Anything not level based) */ 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 / 10); pbonus = UMAX(5, ch->level / 5); 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 (!IS_OBJ_STAT(obj, ITEM_NODROP)) SET_BIT(obj->extra_flags, ITEM_NODROP); /* Bonuses could get fun here */ if (obj->pIndexData->vnum == QUEST_BPLATE) { 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); } 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); } else if (obj->pIndexData->vnum == QUEST_LEGGINGS) { 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_WINGS) { 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_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->item_type == ITEM_CONTAINER) { /* weight modifiers */ 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) { /* weapon values of levelD5 */ obj->value[1] = UMAX(15, ( ch->level + 20 ) /5); obj->value[2] = ch->level < 80 ? 4 : 5; add_apply(obj, APPLY_DAMROLL, bonus, TO_OBJECT, 0, -1, 0, ch->level); add_apply(obj, APPLY_HITROLL, bonus, TO_OBJECT, 0, -1, 0, ch->level); } else if (obj->item_type == ITEM_ARMOR) { /* AC value of player level */ obj->value[0] = UMAX(20, ch->level); obj->value[1] = UMAX(20, ch->level); obj->value[2] = UMAX(20, ch->level); obj->value[3] = (5 * UMAX(20, ch->level)) / 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("{GQUEST commands: POINTS, INFO, TIME, REQUEST, COMPLETE, LIST,\n\r" " BUY, QUIT, SELL, REPLACE, IDENTIFY, CONVERT.\n\r" " CONVERTALL, REVERT, REVERTALL DBLQUEST{x\n\r",ch ); if(IS_IMMORTAL(ch)) send_to_char("{GQUEST RESET (player): resets players quest.{x\n\r", ch); send_to_char("{GFor 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() */ 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 */ void do_quest(CHAR_DATA * ch, char *argument) { CHAR_DATA *questman; OBJ_DATA *obj = NULL; OBJ_INDEX_DATA *questinfoobj; MOB_INDEX_DATA *questinfo; char buf[MSL]; char arg1[MIL]; char arg2[MIL]; int i = 0; 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 (!strcmp(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, 10); 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, 10); 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) { sprintf(buf, "{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)); send_to_char(buf, ch); 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 (!strcmp(arg1, "points")) { sprintf(buf, "You have %d quest points.\n\r", ch->pcdata->questpoints); send_to_char(buf, ch); return; } else if (!strcmp(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; } 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; } if (!strcmp(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++) { sprintf(buf, "\t%-5dqp ........ %s{x\n\r", quest_table[i].cost, quest_table[i].who_name); send_to_char(buf, ch); } 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 (!strcmp(arg1, "buy")) { if (arg2[0] == '\0') { send_to_char("To buy an item, type 'QUEST BUY <item>'.\n\r", ch); 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] = -1; ch->pcdata->condition[COND_THIRST] = -1; 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's mortal burdens.", ch, NULL, questman, TO_ROOM); return; } if (quest_table[i].vnum == 1) { ch->pcdata->questpoints -= quest_table[i].cost; SET_BIT( ch->act, PLR_FREQUENT ); send_to_char( "You are now a considered a frequent questor, you will have to wait less time between quests.\n\r", ch ); act("$N now recognizes $n as a frequent questor!", ch, NULL, questman, TO_ROOM ); return; } if ( ch->levelflux < 6 ) { if (quest_table[i].vnum == 2 ) { ch->pcdata->questpoints -= quest_table[i].cost; ch->levelflux++; printf_to_char( ch, "Your level flux has been raised to %d!\n\r", ch->levelflux ); return; } } if (quest_table[i].vnum == 3 ) { ch->pcdata->questpoints -= quest_table[i].cost; ch->train += 100; send_to_char( "The questmaster gives you 100 trains.\n\r", ch ); return; } if (quest_table[i].vnum == 4) { ch->pcdata->questpoints -= quest_table[i].cost; ch->practice += 1000; send_to_char( "The questmaster gives you 1000 practices.\n\r", ch ); return; } if (quest_table[i].vnum == 5) { ch->pcdata->questpoints -= quest_table[i].cost; ch->pcdata->dblq = 1; send_to_char( "The questmaster promises to give you double questpoints for every quest you complete from now on.\n\r", ch ); 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 a %s (%d) for %d questpoints.", quest_table[i].name, quest_table[i].vnum, quest_table[i].cost); append_file(ch, QUEST_FILE, buf); } } 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 (!strcmp(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, ch)) == 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 (!strcmp(arg1, "reset")) { CHAR_DATA *victim; if(!IS_IMMORTAL(ch)) { quest_usage(ch); return; } if (IS_NULLSTR(arg2)) { send_to_char("Syntax: quest reset <player>\n\r", ch); return; } if ((victim = get_char_world(ch, arg2)) == NULL) { send_to_char("They aren't here.\n\r", ch); return; } if (IS_NPC(victim)) { send_to_char("Mobs dont quest.\n\r", ch); return; } end_quest(victim, 0); if(victim != ch) send_to_char("You clear thier quest.\n\r", ch); sprintf(buf, "%s has cleared your quest.\n\r", PERS(ch, victim)); send_to_char(buf, ch); return; } else if (!strcmp(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, ch)) == 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 { 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 (!strcmp(arg1, "identify")) { if (IS_NULLSTR(arg2)) { printf_to_char(ch,"To identify an item, type 'QUEST IDENTIFY <item>'.\n\r"); return; } for (i = 0; quest_table[i].name != NULL; i++) { if (is_name(arg2, quest_table[i].name)) { if (quest_table[i].vnum == 0) { send_to_char("That isn't a quest item.\n\r", ch); 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 { 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); } obj_to_char(obj, ch); sprintf(buf, "%s costs %d questpoints.", obj->short_descr, quest_table[i].cost); send_to_char(buf, ch); spell_identify(0, ch->level, ch, obj, TAR_OBJ_INV); extract_obj(obj); return; } } } sprintf(buf, "I don't have that item, %s.", ch->name); do_mob_tell(ch, questman, buf); return; } else if (!strcmp(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) || ON_GQUEST(ch)) { 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 (!strcmp(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, points; int gold, quest, train, practice, silver; if (ch->pcdata->questmob == -1 && ch->pcdata->countdown > 0) { reward = number_range(125, 375); points = number_range(25, 70); 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 (chance(points/5)) { send_to_char("You gain an extra {YTrivia {RPoint{x!\n\r", ch); ch->pcdata->trivia += 1; } if ( ch->pcdata->countdown >= 8 ) { switch ( number_range( 0, 4 ) ) { default: quest = number_range( 10, 25 ); printf_to_char( ch, "{cAs a reward for completing your quest so fast i'm giving you {C%d {cquestpoints!\n\r", quest ); ch->pcdata->questpoints += quest; break; case 0: gold = number_range( 80, 200 ); printf_to_char( ch, "{yAs a reward for completing your quest so fast i'm giving {Y%d {ygold!{x\n\r", gold ); ch->gold += gold; break; case 1: quest = number_range( 10, 25 ); printf_to_char( ch, "{cAs a reward for completing your quest so fast i'm giving you {C%d {cquestpoints!\n\r", quest ); ch->pcdata->questpoints += quest; break; case 2: train = number_range( 2, 8 ); printf_to_char( ch, "{bAs a reward for completing your quest so fast i'm giving you {B%d {btrains!{x\n\r", train ); ch->train += train; break; case 3: practice = number_range( 5, 10 ); printf_to_char( ch, "{rAs a reward for completing your quest so fast i'm giving you {R%d {rpractices!{x\n\r", practice ); ch->practice += practice; break; case 4: silver = number_range( 250, 500 ); printf_to_char( ch, "{gAs a reward for completing your quest so fast i'm giving you {G%d {gsilver{x\n\r", silver ); ch->silver += silver; break; } } if ( IS_SET( ch->act, PLR_FREQUENT ) ) end_quest( ch, 5 ); else end_quest(ch, 10); if ( ch->pcdata->dblq == 1 ) reward *= 2; ch->gold += reward; if ( ch->pcdata->dblq == 1 || double_qp ) points *= 2; 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(125, 375); 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); 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 ( ch->pcdata->countdown >= 8 ) { switch ( number_range( 0, 4 ) ) { default: quest = number_range( 10, 25 ); printf_to_char( ch, "{cAs a reward for completing your quest so fast i'm giving you {C%d {cquestpoints!\n\r", quest ); ch->pcdata->questpoints += quest; break; case 0: gold = number_range( 80, 200 ); printf_to_char( ch, "{yAs a reward for completing your quest so fast i'm giving {Y%d {ygold!{x\n\r", gold ); ch->gold += gold; break; case 1: quest = number_range( 10, 25 ); printf_to_char( ch, "{cAs a reward for completing your quest so fast i'm giving you {C%d {cquestpoints!\n\r", quest ); ch->pcdata->questpoints += quest; break; case 2: train = number_range( 2, 8 ); printf_to_char( ch, "{bAs a reward for completing your quest so fast i'm giving you {B%d {btrains!{x\n\r", train ); ch->train += train; break; case 3: practice = number_range( 5, 10 ); printf_to_char( ch, "{rAs a reward for completing your quest so fast i'm giving you {R%d {rpractices!{x\n\r", practice ); ch->practice += practice; break; case 4: silver = number_range( 250, 500 ); printf_to_char( ch, "{gAs a reward for completing your quest so fast i'm giving you {G%d {gsilver{x\n\r", silver ); ch->silver += silver; break; } } if (chance(points/5)) { send_to_char("You gain an extra {YTrivia {RPoint{x!\n\r", ch); ch->pcdata->trivia += 1; } if ( IS_SET( ch->act, PLR_FREQUENT ) ) end_quest(ch, 5 ); else end_quest(ch, 10); if ( ch->pcdata->dblq == 1 ) reward *= 2; ch->gold += reward; if ( ch->pcdata->dblq == 1 || double_qp ) points *= 2; 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 (!strcmp(arg1, "quit") || !strcmp(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)) { if ( IS_SET( ch->act, PLR_FREQUENT ) ) end_quest(ch, 10); else end_quest(ch, 15); do_mob_tell(ch, questman, "Your quest is over, but for your cowardly behavior, you may not quest again for 15 minutes."); return; } else { send_to_char("You aren't on a quest!", ch); return; } } else if (!str_cmp(arg1, "convert")) { if(ch->pcdata->qps <= 0) { send_to_char("You don't have any iquest points to convert.\n\r",ch); return; } ch->pcdata->qps--; ch->pcdata->questpoints += 100; send_to_char("One immortal questpoint converted into 100 atomautic questpoints.\n\r",ch); return; } else if (!str_cmp(arg1, "convertall")) { if ( ch->pcdata->qps <= 0 ) { send_to_char( "I'm sorry you don't have enough immortal questpoints!\n\r", ch ); return; } if ( ch->pcdata->qps >= 500 ) { send_to_char( "I'm sorry you have to many questpoints to convert at once! 320 is the max!\n\r", ch ); return; } ch->pcdata->questpoints += ( 100 * ch->pcdata->qps ); ch->pcdata->qps = 0; send_to_char( "Ok all of your immortal questpoints have been converted to automatic questpoints!\n\r", ch ); return; } else if (!str_cmp(arg1,"revert")) { if(ch->pcdata->questpoints<100) { send_to_char("You don't have enough aquest points to revert.\n\r",ch); return; } ch->pcdata->qps++; ch->pcdata->questpoints -= 100; send_to_char("100 aquest points reverted into one iquest point.\n\r",ch); return; } else if (!str_cmp(arg1, "revertall")) { if ( ch->pcdata->questpoints < 100 ) { send_to_char("You don't have enough automatic questpoints to rever.\n\r", ch ); return; } ch->pcdata->qps += ( ch->pcdata->questpoints / 100 ); ch->pcdata->questpoints = 0; send_to_char("Reverting all your questpoints into immortal questpoints.\n\r", ch ); return; } quest_usage(ch); return; } #define MAX_QMOB_COUNT mobile_count 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 || victim->in_room->clan > 0 || IS_SET(victim->imm_flags, IMM_WEAPON | IMM_MAGIC) || IS_SET(victim->act, ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER | ACT_PET | ACT_PET | ACT_GAIN) || IS_SET(victim->affected_by, AFF_CHARM) || IS_SET(victim->in_room->room_flags, ROOM_PET_SHOP) || 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 >= (size_t)MAX_QMOB_COUNT) break; } if (mob_count == 0) /* not likely but just in case */ { 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."); if ( IS_SET( ch->act, PLR_FREQUENT ) ) end_quest(ch, 2); else end_quest(ch, 4); 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; /* countdown set here so we can use it for object timers */ ch->pcdata->countdown = number_range(12, 30); /* * 20% chance it will send the player on a 'recover item' quest. */ 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 Mayor of Midgaard 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 Arkham.", 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; 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; char buf [MSL]; 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) { if ( IS_SET( ch->act, PLR_FREQUENT ) ) end_quest(ch, 5); else end_quest(ch, 10 ); sprintf(buf, "You have run out of time for your quest!\n\rYou may quest again in %d minutes.\n\r", ch->pcdata->nextquest); send_to_char(buf, ch); } 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; } /* handy dandy, victim must be an NPC */ void do_mob_tell(CHAR_DATA * ch, CHAR_DATA * victim, char *argument) { char buf[MSL]; if (!victim) return; sprintf(buf, "{R%s tells you '{W%s{R'{x\n\r", victim->short_descr, argument); send_to_char(buf, ch); return; } void do_tpspend(CHAR_DATA * ch, char *argument) { CHAR_DATA *triviamob; char buf[MSL]; char arg1[MIL]; char arg2[MIL]; int sav_trust; argument = one_argument(argument, arg1); strcpy(arg2, argument); if(!ch || IS_NPC(ch)) return; if (arg1[0] == '\0') { send_to_char("Syntax: Tpspend <item>\n\r", ch); send_to_char(" Tpspend list\n\r", ch); return; } if (is_name(arg1, "list")) { send_to_char("{WTrivia Point Options{x\n\r", ch); send_to_char("{Ycorpse retrival{W......{R1tp\n\r", ch); send_to_char("{Ytransfer{W.............{R1tp\n\r", ch); send_to_char("{Yrestore{W..............{R1tp\n\r", ch); send_to_char("{Y5 trains{W.............{R1tp\n\r", ch); send_to_char("{Y40 practices{W.........{R1tp\n\r", ch); send_to_char("{Y75 questpoints{W.......{R1tp\n\r", ch); send_to_char("{Y1 Trivia Pill{W........{R1tp\n\r", ch); send_to_char("{WSee HELP TRIVIA for important info before buying.{X\n\r", ch); send_to_char("{WFor transfers and corpses, you do not have to be at a trivia shop.\n\r", ch); return; } else if (is_name(arg1, "corpse")) { if (ch->pcdata->trivia >= 1) { OBJ_DATA *obj; int count = 0; for (obj = ch->carrying ; obj != NULL ; obj = obj->next_content) { if (is_name(ch->name, obj->owner) && obj->item_type == ITEM_CORPSE_PC) { if(obj->in_room) obj_from_room(obj); else if(obj->carried_by) obj_from_char(obj); else if(obj->in_obj) obj_from_obj(obj->in_obj); obj->carried_by = ch; obj_to_room(obj, ch->in_room); count++; } } if (count == 0) send_to_char("You have no corpses in the game.\n\r", ch); else { ch->pcdata->trivia -= 1; if (count == 1) { send_to_char("Your corpse appears in the room.\n\r", ch); act("$n's corpse appears in the room.", ch, NULL, NULL, TO_ROOM); } else { send_to_char("All your corpses appear in the room.\n\r", ch); act("All of $n's corpses appear in the room.", ch, NULL, NULL, TO_ROOM); } } return; } else { send_to_char("You don't have enough trivia points for that.", ch); return; } } else if (is_name(arg1, "transfer")) { if (ch->pcdata->trivia >= 1) { ROOM_INDEX_DATA *oldroom; if (arg2[0] == '\0') { send_to_char("Transfer you where? [recall/room name/character name]\n\r", ch); return; } else if (!str_cmp(arg2, "recall")) sprintf(arg2, "%d", ROOM_VNUM_TEMPLE); oldroom = ch->in_room; sprintf(buf, "self '%s'", arg2); sav_trust = ch->trust; ch->trust = MAX_LEVEL; do_function(ch, &do_transfer, buf); ch->trust = sav_trust; if (oldroom != ch->in_room) ch->pcdata->trivia -= 1; else send_to_char("Whoops! You were not charged for that transfer.\n\r", ch); return; } else { send_to_char("You don't have enough trivia points for that.", ch); return; } } for (triviamob = ch->in_room->people; triviamob != NULL; triviamob = triviamob->next_in_room) { if (!IS_NPC(triviamob)) continue; if (triviamob->spec_fun == spec_lookup("spec_triviamob")) break; } if (triviamob == NULL || triviamob->spec_fun != spec_lookup("spec_triviamob")) { send_to_char("You can't do that here.\n\r", ch); return; } if (triviamob->fighting != NULL) { send_to_char("Wait until the fighting stops.\n\r", ch); return; } if (is_name(arg1, "practices pracs practice")) { if (ch->pcdata->trivia >= 1) { ch->pcdata->trivia -= 1; ch->practice += 40; act("$N gives 40 practices to $n.", ch, NULL, triviamob, TO_ROOM); act("$N gives you 40 practices.", ch, NULL, triviamob, TO_CHAR); return; } else { sprintf(buf, "Sorry, %s, but you don't have enough trivia points for that.", ch->name); do_mob_tell(ch, triviamob, buf); return; } } else if (is_name(arg1, "trains train")) { if (ch->pcdata->trivia >= 1) { ch->pcdata->trivia -= 1; ch->train += 5; act("$N gives 5 training sessions to $n.", ch, NULL, triviamob, TO_ROOM); act("$N gives you 5 training sessions.", ch, NULL, triviamob, TO_CHAR); return; } else { sprintf(buf, "Sorry, %s, but you don't have enough trivia points for that.", ch->name); do_mob_tell(ch, triviamob, buf); return; } } else if (is_name(arg1, "questpoints points")) { if (ch->pcdata->trivia >= 1) { ch->pcdata->trivia -= 1; ch->pcdata->questpoints += 75; /* a trivia point costs 100 quest points 25% conversion */ act("$N gives 75 questpoints to $n.", ch, NULL, triviamob, TO_ROOM); act("$N gives you 75 questpoints.", ch, NULL, triviamob, TO_CHAR); return; } else { sprintf(buf, "Sorry, %s, but you don't have enough trivia points for that.", ch->name); do_mob_tell(ch, triviamob, buf); return; } } else if (is_name(arg1, "pill")) { OBJ_DATA *obj = NULL; if (ch->pcdata->trivia >= 1) { obj = create_object(get_obj_index(OBJ_VNUM_TRIVIA_PILL), 1); if (obj != NULL) { act("$N gives $p to $n.", ch, obj, triviamob, TO_ROOM); act("$N gives you $p.", ch, obj, triviamob, TO_CHAR); obj_to_char(obj, ch); ch->pcdata->trivia -= 1; return; } else { sprintf(buf, "I don't any more trivia pills to give, %s.", ch->name); do_mob_tell(ch, triviamob, buf); } return; } else { sprintf(buf, "Sorry, %s, but you don't have enough trivia points for that.", ch->name); do_mob_tell(ch, triviamob, buf); return; } } else if (is_name(arg1, "restore")) { if (ch->pcdata->trivia >= 1) { sav_trust = ch->trust; ch->trust = MAX_LEVEL; do_function(ch, &do_restore, "all"); ch->trust = sav_trust; ch->pcdata->trivia -= 1; return; } else { sprintf(buf, "Sorry, %s, but you don't have enough trivia points for that.", ch->name); do_mob_tell(ch, triviamob, buf); return; } } else do_tpspend(ch, "list"); } void do_qpgive(CHAR_DATA * ch, char *argument) { 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, NULL, argument)) == NULL) { send_to_char("That person is not here.\n\r", ch); return; } if(IS_NPC(victim)) { send_to_char("NPC's don't need quest points.\n\r", ch); return; } if(victim == ch) { printf_to_char( ch, "You give yourself %d questpoints..... don't you feel better?\n\r", amount ); 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; } void do_tpgive(CHAR_DATA * ch, char *argument) { 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: tpgive [amount] [person]\n\r", ch); return; } if ((amount = atoi(arg)) <= 0) { send_to_char("Give how many trivia points?\n\r", ch); return; } if (amount > ch->pcdata->trivia) { send_to_char("You don't have that many trivia points to give!!\n\r", ch); return; } if ((victim = get_char_room(ch, NULL, argument)) == NULL) { send_to_char("That person is not here.\n\r", ch); return; } if(IS_NPC(victim)) { send_to_char("NPC's don't need trivia points.\n\r", ch); return; } if(victim == ch) { printf_to_char( ch, "You give yourself %d trivia points...... don't you feel better?\n\r", amount ); return; } ch->pcdata->trivia -= amount; victim->pcdata->trivia += amount; sprintf(buf, "%d", amount); act("$n gives you $t trivia points.", ch, buf, victim, TO_VICT); act("You give $N $t trivia points.", ch, buf, victim, TO_CHAR); act("$n gives $N $t trivia points.", ch, buf, victim, TO_ROOM); return; } void do_token ( CHAR_DATA *ch, char *argument ) { OBJ_DATA *obj=NULL; char buf[MAX_STRING_LENGTH]; char arg[MAX_STRING_LENGTH]; int value; one_argument( argument, arg ); if (IS_NPC(ch)) return; if (arg[0] == '\0') { send_to_char("How many qp should the token be worth?\n\r", ch); return; } if (ch->pcdata->questpoints <= 0 ) { send_to_char("You have no qp left to spend!\n\r", ch); return; } else { value = atoi(arg); if (value <= 0 ) { send_to_char("Tokens may only by made for positive amounts.\n\r", ch); return; } else if (value > ch->pcdata->questpoints ) { send_to_char("You don't have that many quest points.\n\r",ch); return; } else { obj = create_object(get_obj_index(OBJ_VNUM_TOKEN), 0); sprintf( buf, obj->short_descr, value ); free_string( obj->short_descr ); obj->short_descr = str_dup( buf ); sprintf( buf, obj->description, value ); free_string( obj->description ); obj->description = str_dup( buf ); obj->value[0] = value; ch->pcdata->questpoints -= value; obj_to_char(obj,ch); act( "You snap your fingers and produce a quest token!", ch, NULL, NULL,TO_CHAR); act( "$n snaps $s fingers and produces a quest token!", ch, NULL, NULL, TO_ROOM); return; } } return; } void unfinished_quest(CHAR_DATA *ch) { if (IS_QUESTOR(ch)) { bool found = FALSE; sprintf(log_buf, "Creating unfinished quest for %s.", ch->name); log_string(log_buf); wiznet(log_buf, NULL, NULL, 0, 0, 0); if (ch->pcdata->questobj > 0) { OBJ_DATA *obj = NULL; ROOM_INDEX_DATA *pRoom = NULL; for(obj = object_list; obj != NULL; obj = obj->next) if(obj->pIndexData->vnum == ch->pcdata->questobj && is_name(ch->name, obj->owner)) found = TRUE; if(!found) { if ((obj = create_object(get_obj_index(ch->pcdata->questobj), ch->level)) == NULL) end_quest(ch, 0); else { if ((pRoom = get_room_index(ch->pcdata->questloc)) == NULL) { pRoom = get_random_room(ch); ch->pcdata->questobj = pRoom->vnum; } obj_to_room(obj, pRoom); } do_quest(ch, "info"); send_to_char("\n\r", ch); } } else if (ch->pcdata->questmob > 0) { CHAR_DATA *mob; for(mob = char_list; mob != NULL; mob = mob->next) if(IS_NPC(mob) && mob->pIndexData->vnum == ch->pcdata->questmob) break; if (!mob) end_quest(ch, 5); else { ch->pcdata->questloc = mob->in_room->vnum; do_quest(ch, "info"); send_to_char("\n\r", ch); } } } } void update_all_qobjs(CHAR_DATA * ch) { OBJ_DATA *obj; AFFECT_DATA *o_paf; for (obj = ch->carrying; obj != NULL; obj = obj->next_content) { if (IS_OBJ_STAT(obj, ITEM_QUEST)) { update_questobjs(ch, obj); for (o_paf = obj->pIndexData->affected; o_paf != NULL; o_paf = o_paf->next) affect_join_obj(obj, o_paf); for (o_paf = obj->affected; o_paf != NULL; o_paf = o_paf->next) affect_check(ch, o_paf->where, o_paf->bitvector); } else { for (o_paf = obj->affected; o_paf != NULL; o_paf = o_paf->next) affect_check(ch, o_paf->where, o_paf->bitvector); if (!obj->enchanted) { for (o_paf = obj->pIndexData->affected; o_paf != NULL; o_paf = o_paf->next) affect_check(ch, o_paf->where, o_paf->bitvector); } } } } void do_levelflux( CHAR_DATA *ch, char *argument ) { CHAR_DATA *questman; ROOM_INDEX_DATA *in_room; int cost = 5000; in_room = ch->in_room; if ( IS_NPC( ch ) ) { send_to_char( "Sorry mobs don't have pets!\n\r", ch ); return; } if ( ch->pet == NULL ) { send_to_char( "You don't have a pet get one first!\n\r", ch ); return; } if ( ch->pet->in_room->vnum != ch->in_room->vnum ) { send_to_char( "Your pet has to be here with you!\n\r", ch ); return; } if ( ch->pet->level < 40 ) { send_to_char( "Your pet has to be at least level 40 to raise his levelflux!\n\r", ch ); return; } 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; } if ( ch->pet->levelflux >= 5 ) { send_to_char( "I'm sorry you can't train your levelflux past 5!\n\r", ch ); return; } if ( ch->pcdata->questpoints < cost ) { printf_to_char( ch, "I'm sorry it takes %d questpoints to buy a levelflux.\n\r", cost ); return; } ch->pet->levelflux++; ch->pcdata->questpoints -= cost; printf_to_char( ch, "Your pets levelflux is now %d.\n\r", ch->pet->levelflux ); printf_to_char( ch, "The questmaster relieves you of %d questpoints.\n\r", cost ); return; }