/*- * Copyright (c) 1998 fjoe <fjoe@iclub.nsu.ru> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: quest.c,v 1.103 1999/04/16 15:52:20 fjoe Exp $ */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <time.h> #include "merc.h" #include "quest.h" #ifdef SUNOS # include <stdarg.h> # include "compat/compat.h" #endif /* * quest items */ #define QUEST_VNUM_GIRTH 94 #define QUEST_VNUM_RING 95 #define QUEST_VNUM_RUG 50 #define QUEST_VNUM_SONG 40 #define QUEST_VNUM_CANTEEN 34402 #define TROUBLE_MAX 3 static void quest_tell(CHAR_DATA *ch, CHAR_DATA *questor, const char *fmt, ...); static CHAR_DATA *questor_lookup(CHAR_DATA *ch); qtrouble_t *qtrouble_lookup(CHAR_DATA *ch, int vnum); static void quest_points(CHAR_DATA *ch, char *arg); static void quest_info(CHAR_DATA *ch, char *arg); static void quest_time(CHAR_DATA *ch, char *arg); static void quest_list(CHAR_DATA *ch, char *arg); static void quest_buy(CHAR_DATA *ch, char *arg); static void quest_request(CHAR_DATA *ch, char *arg); static void quest_complete(CHAR_DATA *ch, char *arg); static void quest_trouble(CHAR_DATA *ch, char *arg); static bool quest_give_item(CHAR_DATA *ch, CHAR_DATA *questor, int item_vnum, int count_max); static bool buy_gold(CHAR_DATA *ch, CHAR_DATA *questor); static bool buy_prac(CHAR_DATA *ch, CHAR_DATA *questor); static bool buy_tattoo(CHAR_DATA *ch, CHAR_DATA *questor); static bool buy_death(CHAR_DATA *ch, CHAR_DATA *questor); static bool buy_katana(CHAR_DATA *ch, CHAR_DATA *questor); static bool buy_vampire(CHAR_DATA *ch, CHAR_DATA *questor); enum qitem_type { TYPE_ITEM, TYPE_OTHER }; typedef struct qitem_data QITEM_DATA; struct qitem_data { char *name; int price; const char *restrict_class; int vnum; bool (*do_buy)(CHAR_DATA *ch, CHAR_DATA *questor); }; struct qitem_data qitem_table[] = { { "small magic rug", 750, NULL, QUEST_VNUM_RUG, NULL }, { "50,000 gold pieces", 500, NULL, 0, buy_gold }, { "60 practices", 500, NULL, 0, buy_prac }, { "tattoo of your religion", 200, NULL, 0, buy_tattoo }, { "Decrease number of deaths", 50, "samurai", 0, buy_death }, { "Katana quest", 100, "samurai", 0, buy_katana }, { "Vampire skill", 50, "vampire", 0, buy_vampire }, { "Bottomless canteen with cranberry juice", 350, NULL, QUEST_VNUM_CANTEEN, NULL }, { NULL } }; struct qcmd_data { char *name; void (*do_fn)(CHAR_DATA *ch, char* arg); int min_position; int extra; }; typedef struct qcmd_data Qcmd_t; Qcmd_t qcmd_table[] = { { "points", quest_points, POS_DEAD, CMD_KEEP_HIDE}, { "info", quest_info, POS_DEAD, CMD_KEEP_HIDE}, { "time", quest_time, POS_DEAD, CMD_KEEP_HIDE}, { "list", quest_list, POS_RESTING, 0}, { "buy", quest_buy, POS_RESTING, 0}, { "request", quest_request, POS_RESTING, 0}, { "complete", quest_complete, POS_RESTING, 0}, { "trouble", quest_trouble, POS_RESTING, 0}, { NULL} }; /* * The main quest function */ void do_quest(CHAR_DATA *ch, const char *argument) { char cmd[MAX_INPUT_LENGTH]; char arg[MAX_INPUT_LENGTH]; Qcmd_t *qcmd; argument = one_argument(argument, cmd, sizeof(cmd)); argument = one_argument(argument, arg, sizeof(arg)); if (IS_NPC(ch)) return; for (qcmd = qcmd_table; qcmd->name != NULL; qcmd++) if (str_prefix(cmd, qcmd->name) == 0) { if (ch->position < qcmd->min_position) { char_puts("In your dreams, or what?\n", ch); return; } if (!IS_SET(qcmd->extra, CMD_KEEP_HIDE) && IS_SET(ch->affected_by, AFF_HIDE | AFF_FADE)) { REMOVE_BIT(ch->affected_by, AFF_HIDE | AFF_FADE); act_puts("You step out of shadows.", ch, NULL, NULL, TO_CHAR, POS_DEAD); act("$n steps out of shadows.", ch, NULL, NULL, TO_ROOM); } qcmd->do_fn(ch, arg); return; } char_puts("QUEST COMMANDS: points info time request complete list buy trouble.\n", ch); char_puts("For more information, type: help quests.\n", ch); } void quest_handle_death(CHAR_DATA *ch, CHAR_DATA *victim) { if (IS_NPC(ch) && IS_SET(ch->pIndexData->act, ACT_SUMMONED) && ch->master != NULL) ch = ch->master; if (victim->hunter) if (victim->hunter == ch) { act_puts("You have almost completed your QUEST!\n" "Return to questmaster before your time " "runs out!", ch, NULL, NULL, TO_CHAR, POS_DEAD); ch->pcdata->questmob = -1; } else { act_puts("You have completed someone's quest.", ch, NULL, NULL, TO_CHAR, POS_DEAD); ch = victim->hunter; act_puts("Someone has completed you quest.", ch, NULL, NULL, TO_CHAR, POS_DEAD); quest_cancel(ch); ch->pcdata->questtime = -number_range(5, 10); } } void quest_cancel(CHAR_DATA *ch) { CHAR_DATA *fch; if (IS_NPC(ch)) { bug("quest_cancel: called for NPC", 0); return; } /* * remove mob->hunter */ for (fch = npc_list; fch; fch = fch->next) if (fch->hunter == ch) { fch->hunter = NULL; break; } ch->pcdata->questtime = 0; ch->pcdata->questgiver = 0; ch->pcdata->questmob = 0; ch->pcdata->questobj = 0; ch->pcdata->questroom = NULL; } /* * Called from update_handler() by pulse_area */ void quest_update(void) { CHAR_DATA *ch, *ch_next; for (ch = char_list; ch && !IS_NPC(ch); ch = ch_next) { ch_next = ch->next; if (ch->pcdata->questtime < 0) { if (++ch->pcdata->questtime == 0) { char_puts("{*You may now quest again.\n", ch); return; } } else if (IS_ON_QUEST(ch)) { if (--ch->pcdata->questtime == 0) { char_puts("You have run out of time for your quest!\n", ch); quest_cancel(ch); ch->pcdata->questtime = -number_range(5, 10); } else if (ch->pcdata->questtime < 6) { char_puts("Better hurry, you're almost out of time for your quest!\n", ch); return; } } } } void qtrouble_set(CHAR_DATA *ch, int vnum, int count) { qtrouble_t *qt; if ((qt = qtrouble_lookup(ch, vnum)) != NULL) qt->count = count; else { qt = malloc(sizeof(*qt)); qt->vnum = vnum; qt->count = count; qt->next = ch->pcdata->qtrouble; ch->pcdata->qtrouble = qt; } } /* * local functions */ static void quest_tell(CHAR_DATA *ch, CHAR_DATA *questor, const char *fmt, ...) { va_list ap; char buf[MAX_STRING_LENGTH]; va_start(ap, fmt); vsnprintf(buf, sizeof(buf), GETMSG(fmt, ch->lang), ap); va_end(ap); do_tell_raw(questor, ch, buf); } static CHAR_DATA* questor_lookup(CHAR_DATA *ch) { CHAR_DATA *vch; CHAR_DATA *questor = NULL; for (vch = ch->in_room->people; vch != NULL; vch = vch->next_in_room) { if (!IS_NPC(vch)) continue; if (IS_SET(vch->pIndexData->act, ACT_QUESTOR)) { questor = vch; break; } } if (questor == NULL) { char_puts("You can't do that here.\n", ch); return NULL; } if (questor->fighting != NULL) { char_puts("Wait until the fighting stops.\n", ch); return NULL; } return questor; } qtrouble_t *qtrouble_lookup(CHAR_DATA *ch, int vnum) { qtrouble_t *qt; for (qt = ch->pcdata->qtrouble; qt != NULL; qt = qt->next) if (qt->vnum == vnum) return qt; return NULL; } /* * quest do functions */ static void quest_points(CHAR_DATA *ch, char* arg) { char_printf(ch, "You have {W%d{x quest points.\n", ch->pcdata->questpoints); } static void quest_info(CHAR_DATA *ch, char* arg) { if (!IS_ON_QUEST(ch)) { char_puts("You aren't currently on a quest.\n", ch); return; } if (ch->pcdata->questmob == -1) { char_puts("Your quest is ALMOST complete!\nGet back to questor before your time runs out!\n", ch); return; } if (ch->pcdata->questobj > 0) { OBJ_INDEX_DATA *qinfoobj; qinfoobj = get_obj_index(ch->pcdata->questobj); if (qinfoobj != NULL) { char_printf(ch, "You are on a quest to recover the fabled {W%s{x!\n", qinfoobj->name); if (ch->pcdata->questroom) char_printf(ch, "That location is in general area of {W%s{x for {W%s{x.\n", ch->pcdata->questroom->area->name, mlstr_mval(ch->pcdata->questroom->name)); } else char_puts("You aren't currently on a quest.\n", ch); return; } if (ch->pcdata->questmob > 0) { MOB_INDEX_DATA *questinfo; questinfo = get_mob_index(ch->pcdata->questmob); if (questinfo != NULL) { char_printf(ch, "You are on a quest to slay the dreaded {W%s{x!\n", mlstr_mval(questinfo->short_descr)); if (ch->pcdata->questroom) char_printf(ch, "That location is in general area of {W%s{x for {W%s{x.\n", ch->pcdata->questroom->area->name, mlstr_mval(ch->pcdata->questroom->name)); } else char_puts("You aren't currently on a quest.\n", ch); return; } } static void quest_time(CHAR_DATA *ch, char* arg) { if (!IS_ON_QUEST(ch)) { char_puts("You aren't currently on a quest.\n", ch); if (ch->pcdata->questtime < -1) char_printf(ch, "There are {W%d{x minutes remaining until you can go on another quest.\n", -ch->pcdata->questtime); else if (ch->pcdata->questtime == -1) char_puts("There is less than a minute remaining until you can go on another quest.\n", ch); } else char_printf(ch, "Time left for current quest: {W%d{x.\n", ch->pcdata->questtime); } static void quest_list(CHAR_DATA *ch, char *arg) { CHAR_DATA *questor; QITEM_DATA *qitem; class_t *cl; if ((questor = questor_lookup(ch)) == NULL || (cl = class_lookup(ch->class)) == NULL) return; act("$n asks $N for list of quest items.", ch, NULL, questor, TO_ROOM); act_puts("You ask $N for list of quest items.", ch, NULL, questor, TO_CHAR, POS_DEAD); char_puts("Current Quest Items available for Purchase:\n", ch); for (qitem = qitem_table; qitem->name; qitem++) { if (qitem->restrict_class != NULL && !is_name(cl->name, qitem->restrict_class)) continue; if (arg[0] != '\0' && !is_name(arg, qitem->name)) continue; char_printf(ch, "%5dqp...........%s\n", qitem->price, qitem->name); } char_puts("To buy an item, type 'QUEST BUY <item>'.\n", ch); } static void quest_buy(CHAR_DATA *ch, char *arg) { CHAR_DATA *questor; QITEM_DATA *qitem; class_t *cl; if ((questor = questor_lookup(ch)) == NULL || (cl = class_lookup(ch->class)) == NULL) return; if (arg[0] == '\0') { char_puts("To buy an item, type 'QUEST BUY <item>'.\n", ch); return; } for (qitem = qitem_table; qitem->name; qitem++) if (is_name(arg, qitem->name)) { bool buy_ok = FALSE; if (qitem->restrict_class != NULL && !is_name(cl->name, qitem->restrict_class)) continue; if (ch->pcdata->questpoints < qitem->price) { quest_tell(ch, questor, "Sorry, {W%s{z, but you don't have " "enough quest points for that.", ch->name); return; } if (qitem->vnum == 0) buy_ok = qitem->do_buy(ch, questor); else buy_ok = quest_give_item(ch, questor, qitem->vnum, 0); if (buy_ok) ch->pcdata->questpoints -= qitem->price; return; } quest_tell(ch, questor, "I do not have that item, %s.", ch->name); } #define MAX_QMOB_COUNT 512 static void quest_request(CHAR_DATA *ch, char *arg) { int i; CHAR_DATA *mobs[MAX_QMOB_COUNT]; size_t mob_count; CHAR_DATA *victim = NULL; CHAR_DATA *questor; if ((questor = questor_lookup(ch)) == NULL) return; act("$n asks $N for a quest.", ch, NULL, questor, TO_ROOM); act_puts("You ask $N for a quest.", ch, NULL, questor, TO_CHAR, POS_DEAD); if (IS_ON_QUEST(ch)) { quest_tell(ch, questor, "But you are already on a quest!"); return; } if (ch->pcdata->questtime < 0) { quest_tell(ch, questor, "You're very brave, {W%s{z, but let someone else " "have a chance.", ch->name); quest_tell(ch, questor, "Come back later."); return; } quest_tell(ch, questor, "Thank you, brave {W%s{z!", ch->name); /* * find MAX_QMOB_COUNT quest mobs and store their vnums in mob_buf */ mob_count = 0; for (victim = npc_list; victim; victim = victim->next) { int diff = victim->level - ch->level; if (!IS_NPC(victim) || (ch->level < 51 && (diff > 4 || diff < -1)) || (ch->level > 50 && (diff > 6 || diff < 0)) || victim->pIndexData->pShop || victim->race == ch->race || victim->invis_level || (IS_EVIL(victim) && IS_EVIL(ch)) || (IS_GOOD(victim) && IS_GOOD(ch)) || victim->pIndexData->vnum < 100 || IS_SET(victim->pIndexData->act, ACT_TRAIN | ACT_PRACTICE | ACT_HEALER | ACT_NOTRACK | ACT_PET) || IS_SET(victim->pIndexData->imm_flags, IMM_SUMMON) || questor->pIndexData == victim->pIndexData || victim->in_room == NULL || (IS_SET(victim->pIndexData->act, ACT_SENTINEL) && IS_SET(victim->in_room->room_flags, ROOM_PRIVATE | ROOM_SOLITARY)) || !str_cmp(victim->in_room->area->name, hometown_name(ch->hometown)) || IS_SET(victim->in_room->area->flags, AREA_CLOSED | AREA_NOQUEST)) continue; mobs[mob_count++] = victim; if (mob_count >= MAX_QMOB_COUNT) break; } if (mob_count == 0) { quest_tell(ch, questor, "I'm sorry, but i don't have any quests for you at this time."); quest_tell(ch, questor, "Try again later."); ch->pcdata->questtime = -5; return; } victim = mobs[number_range(0, mob_count-1)]; ch->pcdata->questroom = victim->in_room; if (chance(40)) { /* Quest to find an obj */ OBJ_DATA *eyed; int obj_vnum; if (IS_GOOD(ch)) i = 0; else if (IS_EVIL(ch)) i = 2; else i = 1; obj_vnum = number_range(QUEST_OBJ_FIRST, QUEST_OBJ_LAST); eyed = create_obj(get_obj_index(obj_vnum), 0); eyed->level = ch->level; eyed->owner = mlstr_dup(ch->short_descr); eyed->ed = ed_new2(eyed->pIndexData->ed, ch->name); eyed->cost = 0; eyed->timer = 30; obj_to_room(eyed, victim->in_room); ch->pcdata->questobj = eyed->pIndexData->vnum; quest_tell(ch, questor, "Vile pilferers have stolen {W%s{z " "from the royal treasury!", mlstr_mval(eyed->short_descr)); quest_tell(ch, questor, "My court wizardess, with her magic mirror, " "has pinpointed its location."); quest_tell(ch, questor, "Look in the general area of {W%s{z for {W%s{z!", victim->in_room->area->name, mlstr_mval(victim->in_room->name)); } else { /* Quest to kill a mob */ if (IS_GOOD(ch)) { quest_tell(ch, questor, "Rune's most heinous criminal, {W%s{z, " "has escaped from the dungeon.", mlstr_mval(victim->short_descr)); quest_tell(ch, questor, "Since the escape, {W%s{z has murdered {W%d{z civilians!", mlstr_mval(victim->short_descr), number_range(2, 20)); quest_tell(ch, questor, "The penalty for this crime is death, and you are to deliver the sentence!"); } else { quest_tell(ch, questor, "An enemy of mine, {W%s{z, " "is making vile threats against the crown.", mlstr_mval(victim->short_descr)); quest_tell(ch, questor, "This threat must be eliminated!"); } quest_tell(ch, questor, "Seek {W%s{z out in the vicinity of {W%s{z!", mlstr_mval(victim->short_descr), mlstr_mval(victim->in_room->name)); quest_tell(ch, questor, "That location is in general area of {W%s{z.", victim->in_room->area->name); ch->pcdata->questmob = victim->pIndexData->vnum; victim->hunter = ch; } ch->pcdata->questgiver = questor->pIndexData->vnum; ch->pcdata->questtime = number_range(10, 20) + ch->level/10; quest_tell(ch, questor, "You have {W%d{z minutes to complete this quest.", ch->pcdata->questtime); quest_tell(ch, questor, "May the gods go with you!"); } static void quest_complete(CHAR_DATA *ch, char *arg) { bool complete = FALSE; CHAR_DATA *questor; OBJ_DATA *obj; OBJ_DATA *obj_next; int gold_reward = 0; int qp_reward = 0; int prac_reward = 0; if ((questor = questor_lookup(ch)) == NULL) return; act("$n informs $N $e has completed $s quest.", ch, NULL, questor, TO_ROOM); act_puts("You inform $N you have completed your quest.", ch, NULL, questor, TO_CHAR, POS_DEAD); if (!IS_ON_QUEST(ch)) { quest_tell(ch, questor, "You have to REQUEST a quest first, {W%s{z.", ch->name); return; } if (ch->pcdata->questgiver != questor->pIndexData->vnum) { quest_tell(ch, questor, "I never sent you on a quest! Perhaps you're " "thinking of someone else."); return; } if (ch->pcdata->questobj > 0) for (obj = ch->carrying; obj; obj = obj_next) { obj_next = obj->next_content; if (obj->pIndexData->vnum == ch->pcdata->questobj && IS_OWNER(ch, obj)) { act_puts("You hand {W$p{x to $N.", ch, obj, questor, TO_CHAR, POS_DEAD); act("$n hands {W$p{x to $N.", ch, obj, questor, TO_ROOM); extract_obj(obj, 0); if (chance(15)) prac_reward = number_range(1, 6); qp_reward = number_range(20, 40); gold_reward = 35 + number_range(ch->level, 2*ch->level); complete = TRUE; break; } } else if (ch->pcdata->questmob == -1) { if (chance(2)) prac_reward = number_range(1, 6); qp_reward = number_range(15, 35); gold_reward = dice(ch->level/10 + 1, 30); gold_reward = URANGE(0, gold_reward, 20*ch->level); complete = TRUE; } if (!complete) { quest_tell(ch, questor, "You haven't completed the quest yet, but there is " "still time!"); return; } ch->gold += gold_reward; ch->pcdata->questpoints += qp_reward; quest_tell(ch, questor, "Congratulations on completing your quest!"); quest_tell(ch, questor, "As a reward, I am giving you %d quest points, " "and %d gold.", qp_reward, gold_reward); if (prac_reward) { ch->practice += prac_reward; quest_tell(ch, questor, "You gain %d practices!\n", prac_reward); } quest_cancel(ch); ch->pcdata->questtime = -number_range(8, 12); } static void quest_trouble(CHAR_DATA *ch, char *arg) { CHAR_DATA *questor; QITEM_DATA *qitem; class_t *cl; if ((questor = questor_lookup(ch)) == NULL || (cl = class_lookup(ch->class)) == NULL) return; if (arg[0] == '\0') { char_puts("To correct a quest award's trouble, type: 'quest trouble <award>'.\n", ch); return; } for (qitem = qitem_table; qitem->name; qitem++) { if (qitem->restrict_class != NULL && !is_name(cl->name, qitem->restrict_class)) continue; if (qitem->vnum && is_name(arg, qitem->name)) { quest_give_item(ch, questor, qitem->vnum, TROUBLE_MAX); return; } } quest_tell(ch, questor, "Sorry, {W%s{z, but you haven't bought " "that quest award, yet.\n", ch->name); } /* * quest buy functions */ static bool quest_give_item(CHAR_DATA *ch, CHAR_DATA *questor, int item_vnum, int count_max) { OBJ_DATA *reward; qtrouble_t *qt; OBJ_INDEX_DATA *pObjIndex = get_obj_index(item_vnum); /* * check quest trouble data */ qt = qtrouble_lookup(ch, item_vnum); if (count_max) { /* * 'quest trouble' */ if ((qt && qt->count > count_max) || !IS_SET(pObjIndex->extra_flags, ITEM_QUEST)) { /* ch requested this item too many times * * or the item is not quest */ quest_tell(ch, questor, "This item is beyond the trouble option."); return FALSE; } else if (!qt) { /* ch has never bought this item, but requested it */ quest_tell(ch, questor, "Sorry, {W%s{z, but you haven't bought " "that quest award, yet.\n", ch->name); return FALSE; } } else { /* * 'quest buy' */ if (qt && qt->count <= TROUBLE_MAX) { quest_tell(ch, questor, "You have already bought this item."); return FALSE; } } reward = create_obj(pObjIndex, 0); if (get_wear_level(ch, reward) < reward->level) { quest_tell(ch, questor, "This item is too powerful for you.\n"); extract_obj(reward, 0); return FALSE; } /* update quest trouble data */ if (qt && count_max) { OBJ_DATA *obj; OBJ_DATA *obj_next; /* `quest trouble' */ for (obj = object_list; obj != NULL; obj = obj_next) { obj_next = obj->next; if (obj->pIndexData->vnum == item_vnum && IS_OWNER(ch, obj)) { extract_obj(obj, 0); break; } } quest_tell(ch, questor, "This is the %i time that I am giving " "that award back.", qt->count); if (qt->count > count_max) quest_tell(ch, questor, "And I won't give you that again, " "with trouble option.\n"); } if (!qt && IS_SET(pObjIndex->extra_flags, ITEM_QUEST)) { qt = malloc(sizeof(*qt)); qt->vnum = item_vnum; qt->count = 0; qt->next = ch->pcdata->qtrouble; ch->pcdata->qtrouble = qt; } if (qt) { if (count_max) qt->count++; else qt->count = 1; } /* ok, give him requested item */ if (IS_SET(pObjIndex->extra_flags, ITEM_QUEST)) { reward->owner = mlstr_dup(ch->short_descr); mlstr_free(reward->short_descr); reward->short_descr = mlstr_printf(reward->pIndexData->short_descr, IS_GOOD(ch) ? "holy" : IS_NEUTRAL(ch) ? "blue-green" : "evil", ch->name); } obj_to_char(reward, ch); act("$N gives {W$p{x to $n.", ch, reward, questor, TO_ROOM); act_puts("$N gives you {W$p{x.", ch, reward, questor, TO_CHAR, POS_DEAD); return TRUE; } static bool buy_gold(CHAR_DATA *ch, CHAR_DATA *questor) { ch->pcdata->bank_g += 50000; act("$N gives 50,000 gold pieces to $n.", ch, NULL, questor, TO_ROOM); act("$N transfers 50,000 gold pieces to your bank account.\n",ch, NULL, questor, TO_CHAR); return TRUE; } static bool buy_prac(CHAR_DATA *ch, CHAR_DATA *questor) { ch->practice += 60; act("$N gives 60 practices to $n.", ch, NULL, questor, TO_ROOM); act_puts("$N gives you 60 practices.", ch, NULL, questor, TO_CHAR, POS_DEAD); return TRUE; } static bool buy_tattoo(CHAR_DATA *ch, CHAR_DATA *questor) { OBJ_DATA *tattoo; if (!ch->religion) { char_puts("You don't have a religion to have a tattoo.\n", ch); return FALSE; } tattoo = get_eq_char(ch, WEAR_TATTOO); if (tattoo != NULL) { char_puts("But you have already your tattoo!\n", ch); return FALSE; } tattoo = create_obj(get_obj_index(religion_table[ch->religion].vnum), 0); obj_to_char(tattoo, ch); equip_char(ch, tattoo, WEAR_TATTOO); act("$N tattoos $n with {W$p{x!", ch, tattoo, questor, TO_ROOM); act_puts("$N tattoos you with {W$p{x!", ch, tattoo, questor, TO_CHAR, POS_DEAD); return TRUE; } static bool buy_death(CHAR_DATA *ch, CHAR_DATA *questor) { if (ch->pcdata->death < 1) { quest_tell(ch, questor, "Sorry, {W%s{z, but you haven't got any deaths yet.", ch->name); return FALSE; } ch->pcdata->death -= 1; return TRUE; } static bool buy_katana(CHAR_DATA *ch, CHAR_DATA *questor) { AFFECT_DATA af; OBJ_DATA *katana; if ((katana = get_obj_list(ch, "katana", ch->carrying)) == NULL) { quest_tell(ch, questor, "Sorry, {W%s{z, but you don't have your katana with you.", ch->name); return FALSE; } af.where = TO_WEAPON; af.type = gsn_katana; af.level = 100; af.duration = -1; af.modifier = 0; af.bitvector = WEAPON_KATANA; af.location = APPLY_NONE; affect_to_obj(katana, &af); quest_tell(ch, questor, "As you wield it, you will feel that its power will increase continuosly."); return TRUE; } static bool buy_vampire(CHAR_DATA *ch, CHAR_DATA *questor) { set_skill(ch, gsn_vampire, 100); act("$N gives secret of undead to $n.", ch, NULL, questor, TO_ROOM); act_puts("$N gives you SECRET of undead.", ch, NULL, questor, TO_CHAR, POS_DEAD); act("Lightning flashes in the sky.", ch, NULL, NULL, TO_ALL); return TRUE; }