/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, David * * Love, Guilherme 'Willie' Arnold, and Mitchell Tse. * * * * In order to use any part of this Envy Diku Msud, you must comply with * * the original Diku license in 'license.doc', the Merc license in * * 'license.txt', as well as the Envy license in 'license.nvy'. * * In particular, you may not remove either of these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * ***************************************************************************/ /*$Id: crafting.c,v 1.23 2005/04/10 16:29:00 tyrion Exp $*/ #if defined( macintosh ) #include <types.h> #else #include <sys/types.h> #endif #include <stdio.h> #include <time.h> #include <string.h> #include <math.h> #include "merc.h" char* target_name; /* local functions */ char* set_skin_quality(OBJ_DATA* skin); char* name_tanned_armor(OBJ_DATA* armor); /* Use this file for all ranger skills */ extern char* target_name; void spell_imprint( int sn, int level, CHAR_DATA *ch, void *vo ); // skin corpses for hides int skill_skin( int sn, int level, CHAR_DATA *ch, void *vo ) { char buf[MAX_STRING_LENGTH]; char buf2[MAX_STRING_LENGTH]; OBJ_DATA* obj = (OBJ_DATA*) vo; OBJ_DATA* skin = NULL; if (IS_NPC(ch)) return SKPELL_BOTCHED; if (obj->item_type == ITEM_CORPSE_NPC) { if (obj->value[0] == TAN_NONE || (obj->value[0] == TAN_PC && !IS_IMMORTAL(ch))) { send_to_char(AT_RED, "You cannot skin that!\n\r", ch); return SKPELL_BOTCHED; } } else if ( obj->item_type == ITEM_ARMOR ) { if (!IS_SET(obj->extra_flags2, ITEM_CRAFTED)) { send_to_char(AT_RED, "You can't scrape leather from non-leather armor!\n\r", ch); return SKPELL_BOTCHED; } } else if (obj->item_type == ITEM_SKIN) { OBJ_DATA* obj2; char arg [MAX_INPUT_LENGTH]=""; target_name = one_argument(target_name, arg); one_argument(target_name, arg); if (!obj->carried_by) { send_to_char(AT_RED, "You do not have that in your inventory! Pick it up!\n\r", ch); return SKPELL_BOTCHED; } if (arg[0]=='\0') { send_to_char(AT_RED, "You need two rolls of leather to combine!\n\r", ch); return SKPELL_BOTCHED; } obj2 = get_obj_carry(ch, arg); if (!obj2 || (obj2 && obj2->item_type != ITEM_SKIN)) { send_to_char(AT_RED, "You need two rolls of leather to combine!\n\r", ch); return SKPELL_BOTCHED; } if (obj==obj2) { send_to_char(AT_RED, "You cannot combine a roll of leather with itself!\n\r", ch); return SKPELL_BOTCHED; } if (number_percent() - 20 < ( ch->pcdata->learned[sn] / 10 ) ) { int waste = 0; skin = create_object( get_obj_index( OBJ_VNUM_LEATHER ), obj->level ); waste = URANGE(1, UMIN( obj->value[1], obj->value[2]), 10); /* waste -= waste * ch->pcdata->learned[sn] / 1000; */ if( number_percent( ) + 10 <= ch->pcdata->learned[sn] / 10 && waste > 0 ) { waste -= 1; } skin->item_type = ITEM_SKIN; skin->level = (obj->level + obj2->level) / 2; skin->value[1] = UMAX(1, obj->value[1] + obj2->value[1] - waste); skin->value[0] = (obj->value[0] + obj2->value[0]) / 2; skin->weight = obj->weight + obj2->weight; strcpy(buf2, set_skin_quality( skin )); send_to_char(AT_WHITE, "You skilfully combine:\n\r", ch); send_to_char(AT_BLUE, obj->short_descr, ch); send_to_char(AT_BLUE, "\n\r", ch); send_to_char(AT_BLUE, obj2->short_descr, ch); send_to_char(AT_BLUE, "\n\r", ch); if (waste) { sprintf(buf, "You waste %d yards of leather.\n\r", waste); send_to_char(AT_BLUE, buf, ch); } sprintf(buf, "Creating %d yards of %s leather!\n\r", skin->value[1], buf2); send_to_char(AT_RED, buf, ch); act(AT_RED, "$n combines two rolls of leather." , ch, NULL, NULL, TO_ROOM); extract_obj(obj); extract_obj(obj2); obj_to_char(skin, ch); return SKPELL_NO_DAMAGE; } else { send_to_char(AT_RED, "You fail to combine the two rolls of leather, destroying both of them!\n\r", ch); act(AT_RED, "$n attempts to combine two rolls of leather, but fails!", ch, NULL, NULL, TO_ROOM); extract_obj(obj); extract_obj(obj2); return SKPELL_BOTCHED; } } else { send_to_char(AT_RED, "You can only skin corpses. What are you thinking?\n\r", ch); return SKPELL_BOTCHED; } if (number_percent() - 20 < ( ch->pcdata->learned[sn] / 10 ) ) { int learned = ch->pcdata->learned[sn]; skin = create_object( get_obj_index( OBJ_VNUM_LEATHER ), obj->level ); skin->item_type = ITEM_SKIN; if (obj->item_type == ITEM_ARMOR) { skin->level = obj->level; skin->value[1] = 1 + obj->level * number_range(1, learned / 10) / 100; } else { skin->level = UMIN( 105, (get_mob_index( obj->value[1] ))->level); skin->value[1] = (get_mob_index( obj->value[1] ))->size /* mob size */ * number_range(1, learned / 40) /* x (multi by) 1 to 25 */ / 10 /* / (divide by) 10 */ + UMAX(1, ( skin->level / 25 ) ); /* + (plus) 1 to 4 */ } skin->weight = number_range( skin->value[1]/2, skin->value[1] ); if (learned == 1000) { skin->value[0]=number_range(SKIN_GOOD, SKIN_PERFECT); } else if (learned > 750) { if (number_percent() < 25) skin->value[0]=number_range(SKIN_GOOD, SKIN_PERFECT); else skin->value[0]=number_range(SKIN_DECENT, SKIN_EXCELLENT); } else if (learned > 500) { if(number_percent() < 10) skin->value[0]=number_range(SKIN_GOOD, SKIN_PERFECT); else if (number_percent() < 30) skin->value[0]=number_range(SKIN_DECENT, SKIN_EXCELLENT); else skin->value[0]=number_range(SKIN_LOUSY, SKIN_DECENT); } else { if(number_percent() < 5) skin->value[0]=number_range(SKIN_GOOD, SKIN_PERFECT); else if (number_percent() < 15) skin->value[0]=number_range(SKIN_DECENT, SKIN_EXCELLENT); else if (number_percent() < 30) skin->value[0]=number_range(SKIN_LOUSY, SKIN_DECENT); else skin->value[0]=number_range(SKIN_DESTROYED, SKIN_PASSABLE); } strcpy(buf2, set_skin_quality(skin) ); obj_to_char(skin, ch ); sprintf(buf, "You skillfully scrape the leather creating %d yards of %s leather!\n\r", skin->value[1], buf2); send_to_char(AT_RED, buf, ch); sprintf(buf, "$n scrapes the %s for its leather.", obj->short_descr); act(AT_RED, buf, ch, NULL, NULL, TO_ROOM); } else { send_to_char(AT_RED, "You mangle the skin. You've destroyed it!\n\r", ch); act(AT_RED, "$n thoroughly dices a corpse, but it yields no leather!", ch, NULL, NULL, TO_ROOM); } extract_obj(obj); return SKPELL_ZERO_DAMAGE; } // tan hides for armor int skill_tan( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA* skin = (OBJ_DATA*) vo; OBJ_DATA* needle = get_obj_carry(ch, "needle"); OBJ_DATA* armor = NULL; char buf [MAX_STRING_LENGTH]; char arg1[MAX_STRING_LENGTH]; char arg2[MAX_STRING_LENGTH]; int yards = 0; int loc = 0; int lvl = 0; int bonus = 0; if (IS_NPC(ch)) return SKPELL_BOTCHED; if (skin->item_type != ITEM_SKIN) { send_to_char(AT_ORANGE, "You need to use leather to tan!\n\r", ch); return SKPELL_BOTCHED; } if (!needle || needle->item_type != ITEM_NEEDLE) { send_to_char(AT_ORANGE, "You need a needle to tan leather!\n\r", ch); return SKPELL_BOTCHED; } if (!IS_SET(ch->in_room->room_flags, ROOM_TANNERY)) { send_to_char(AT_ORANGE, "You need to be in a tannery to tan leather!\n\r", ch); return SKPELL_BOTCHED; } target_name = one_argument(target_name, arg1); target_name = one_argument(target_name, arg1); /* Repeat to throw away first arg */ target_name = one_argument(target_name, arg2); if (arg1[0]=='\0' || !is_number(arg1)) { send_to_char(AT_ORANGE, "You need to choose how many yards of leather you will use!\n\r", ch); return SKPELL_BOTCHED; } yards = atoi( arg1 ); if (!yards) { send_to_char(AT_ORANGE, "You need to choose how many yards of leather you will use!\n\r", ch); return SKPELL_BOTCHED; } if ( yards > skin->value[1] ) { sprintf(buf, "Your %s doesn't contain enough leather.\n\rChoose another roll or combine two rolls.\n\r", skin->short_descr); send_to_char(AT_ORANGE, buf, ch ); return SKPELL_BOTCHED; } else if ( yards <= 0) { send_to_char(AT_ORANGE, "How many yards of leather do you plan on using?\n\r", ch); return SKPELL_BOTCHED; } if (arg2[0]=='\0' || !is_number(arg2)) { lvl = ch->level; } else { lvl = atoi( arg2 ); if (lvl <= 0) lvl = ch->level; if (lvl > ch->level) { send_to_char(AT_ORANGE, "You can't try to make an item high level than you are!\n\r", ch); return SKPELL_BOTCHED; } lvl = UMIN( lvl, ch->level ); } if ( lvl > yards ) { send_to_char(AT_ORANGE, "You need at least 1 yard per level of item you are creating!\n\r", ch); return SKPELL_BOTCHED; } /* extra leather supplied */ bonus = yards - lvl; /* difficulty for levelv */ bonus += skin->value[0] - (lvl/5); bonus = UMAX( bonus, 25 ); /* cap the bonus. not sure on value yet */ do { loc = (int) pow(2,number_range(2, 20)) + ITEM_TAKE; /* generate a valid wear loc */ } while (loc == ITEM_WIELD + ITEM_TAKE || loc == ITEM_PROTOTYPE + ITEM_TAKE || loc == ITEM_WEAR_CONTACT + ITEM_TAKE ); skin->value[1] -= yards; if (skin->value[1] <= 0) { extract_obj( skin ); send_to_char( AT_ORANGE, "You use all of your leather roll.\n\r", ch ); } else { set_skin_quality(skin); } if (number_percent() < (((ch->pcdata->learned[sn]/10)+bonus))) { int max_extra = 0; int cur_extra = 0; int bv = 2; int rescount = 0; int statcount = 0; send_to_char(AT_ORANGE, "You skillfully tan and sew the leather!\n\r", ch); armor = create_object( get_obj_index(OBJ_VNUM_TANNED), lvl); armor->weight = number_range(5, 15); armor->level = lvl; armor->wear_flags = loc; armor->cost = lvl; armor->durability_max = number_fuzzy(skin->value[0]) * number_fuzzy(lvl/10); armor->durability_cur = number_range(armor->durability_max/4, armor->durability_max); max_extra = lvl / 17 + 1; /* 2->7 affects plus 2 possible spells */ cur_extra = 0; while (bv <= ITEM_ACID && cur_extra < max_extra ) { if (number_percent() < 10 && bv != ITEM_INVENTORY && bv != ITEM_PATCHED && bv != ITEM_LOCK) { cur_extra++; armor->extra_flags += bv; } bv *= 2; } bv = 0; while (bv <= ITEM_DISPEL && cur_extra < max_extra ) { if (number_percent() < 10 ) { cur_extra++; armor->extra_flags2 += bv; } bv *= 2; } SET_BIT(armor->extra_flags2, ITEM_CRAFTED); /* ac */ armor->value[0] = number_fuzzy( level / 4 + 2 ); /* applies */ for (cur_extra = 0; cur_extra < max_extra; cur_extra++) { int apply = 0; int amt = 0; int pct = 0; AFFECT_DATA* pAf; pct = number_percent(); if (pct<5) { if (rescount >= 2) continue; rescount++; apply = number_range(APPLY_DAM_ACID, APPLY_DAM_WATER ); if (loc == WEAR_BODY || loc == WEAR_HOLD || loc == WEAR_SHIELD) amt = number_range( - lvl / 10, lvl / 4 ); else if (loc == ITEM_WEAR_FINGER || loc == ITEM_WEAR_NECK || loc == ITEM_WEAR_ORBIT || loc == ITEM_WEAR_ANKLE || loc == ITEM_WEAR_WRIST || loc == ITEM_WEAR_WAIST ) amt = number_range( 1, lvl / 20 ); else amt = number_range( -1, lvl / 10); } else if (pct < 20) { apply = APPLY_SAVING_SPELL; amt = 0 - number_range(lvl / 20 , lvl / 5 ); if (lvl > 100) amt -= number_range(0, 20); } else if (pct < 50) { if (statcount >= 2) continue; statcount++; apply = number_range(APPLY_STR,APPLY_CON); amt = number_range(1, (lvl / 30) + 1 ); } else if (pct < 75 ) { apply = number_range(APPLY_SEX, APPLY_ANTI_DIS); switch(apply) { default: cur_extra--; continue; break; /* you got hosed */ case APPLY_MANA: amt = number_range(lvl / 5, lvl ); amt = number_range(lvl / 5, lvl ); if (lvl > LEVEL_HERO) amt += number_range(0, (lvl - LEVEL_HERO) / 4); break; case APPLY_BP: amt = number_range(lvl / 10 , lvl / 3); amt = number_range(lvl / 5, lvl ); if (lvl > LEVEL_HERO) amt += number_range(0, (lvl - LEVEL_HERO) * 20); break; case APPLY_HIT: amt = number_range(lvl / 5, lvl ); if (lvl > LEVEL_HERO) amt += number_range(0, (lvl - LEVEL_HERO) * 20); break; case APPLY_MOVE: amt = number_range(lvl, lvl * 2 ); break; case APPLY_AC: amt = 0 - number_range(lvl / 5, lvl + 50 ); if (lvl > LEVEL_HERO) amt -= number_range(0, (lvl - LEVEL_HERO) * 10); break; case APPLY_HITROLL: case APPLY_DAMROLL: if (loc==ITEM_WEAR_BODY) amt = number_range( lvl / 5, lvl / 2 ); else amt = number_range( level / 10, level / 3 ); break; case APPLY_ANTI_DIS: amt = number_range( lvl / 5, lvl ); break; } } if (apply) { bool found = FALSE; for (pAf = armor->affected; pAf; pAf=pAf->next) { if (pAf->location == apply) { found = TRUE; break; } } if (found) { cur_extra--; continue; } pAf = new_affect(); pAf->location = apply; if (amt < 0) pAf->modifier = -number_fuzzy( -amt ); else pAf->modifier = number_fuzzy(amt); pAf->type = 0; pAf->duration = -1; pAf->bitvector = 0; pAf->next = armor->affected; pAf->type = 0; armor->affected = pAf; /* if you got hitroll, you got damroll */ if (apply == APPLY_HITROLL || apply == APPLY_DAMROLL) { if (apply == APPLY_HITROLL) apply = APPLY_DAMROLL; else apply = APPLY_HITROLL; pAf = new_affect(); pAf->location = apply; pAf->modifier = number_fuzzy(amt); pAf->type = 0; pAf->duration = -1; pAf->bitvector = 0; pAf->next = armor->affected; armor->affected = pAf; } } } /* perm spells */ if (lvl > 30 && number_percent() < 10) { AFFECT_DATA* pAf = new_affect(); pAf = new_affect(); do { pAf->location = number_range(PERM_SPELL_BEGIN, PERM_SPELL_END); } while ( !valid_aff_loc(pAf->location) ); pAf->type = skill_lookup(affect_loc_name(pAf->location)); if (pAf->type < 0) { pAf->type = 0; sprintf(buf, "skill_tanning: affect name for: %s does not match sn for skill_lookup", affect_loc_name(pAf->location) ); bug(buf, 0); } pAf->modifier = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->next = armor->affected; armor->affected = pAf; } if (number_percent() < 3 && lvl > LEVEL_HERO) { AFFECT_DATA* pAf = new_affect(); pAf = new_affect(); do { pAf->location = number_range(PERM_SPELL_BEGIN, PERM_SPELL_END ); } while (!valid_aff_loc(pAf->location) ); pAf->type = skill_lookup(affect_loc_name(pAf->location)); if (pAf->type < 0) { pAf->type = 0; sprintf(buf, "skill_tanning: affect name for: %s does not match sn for skill_lookup", affect_loc_name(pAf->location) ); bug(buf, 0); } pAf->modifier = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->next = armor->affected; armor->affected = pAf; } send_to_char(AT_ORANGE, "You manage to create:\n\r", ch); sprintf(buf, "%s\n\r", name_tanned_armor(armor)); send_to_char(AT_WHITE, buf, ch); obj_to_char(armor, ch); if (number_percent() < 10) { send_to_char(AT_CYAN, "Your needle breaks!\n\r", ch); extract_obj(needle); } act(AT_ORANGE, "$n skillfully tans and stitches together some new armor!", ch, NULL, NULL, TO_ROOM); } else { if (number_percent() < 25) { send_to_char(AT_CYAN, "You break your needle in the attempt!\n\r", ch); extract_obj( needle ); } send_to_char(AT_ORANGE, "Your attempt at tanning fails miserably!\n\r", ch); return SKPELL_BOTCHED; } return SKPELL_ZERO_DAMAGE; } /* Helper function to avoid repetitive code */ char* set_skin_quality(OBJ_DATA* skin) { static char buf [MAX_STRING_LENGTH]; static char quality[MAX_STRING_LENGTH]; if (skin->item_type != ITEM_SKIN) { bug("set_skin_quality: object is not a skin!", 0); return NULL; } strcpy(quality, flag_string(quality_flags, skin->value[0])); sprintf(buf, (get_obj_index( OBJ_VNUM_LEATHER ))->short_descr, skin->value[1], quality); free_string(skin->short_descr); skin->short_descr = str_dup(buf); sprintf(buf, (get_obj_index( OBJ_VNUM_LEATHER ))->description, quality); free_string(skin->description); skin->description = str_dup(buf); return quality; } char* name_tanned_armor(OBJ_DATA* armor) { char prefix1 [MAX_STRING_LENGTH] = ""; char prefix2 [MAX_STRING_LENGTH] = ""; char location [MAX_STRING_LENGTH] = ""; char suffix1 [MAX_STRING_LENGTH] = ""; char suffix2 [MAX_STRING_LENGTH] = ""; char format [MAX_STRING_LENGTH] = "%s%s%s of %s%s"; static char final[MAX_STRING_LENGTH] = ""; char first = 0; char last = 0; int e1 = armor->extra_flags; int e2 = armor->extra_flags2; AFFECT_DATA* paf = NULL; switch (armor->wear_flags - ITEM_TAKE) { case ITEM_WEAR_FINGER: strcpy(location, "ring"); break; case ITEM_WEAR_NECK: { int pct = number_percent(); if (pct < 20) strcpy(location, "Scarf"); else if (pct < 40) strcpy(location, "Chain"); else if (pct < 60) strcpy(location, "Choker"); else strcpy(location, "Necklace"); } break; case ITEM_WEAR_BODY: { int pct = number_percent(); if (pct < 10) strcpy(location, "Breastplate"); else if (pct < 20) strcpy(location, "Leather"); else if (pct < 30) strcpy(location, "Studded Leather"); else if (pct < 40) strcpy(location, "Padded Leather"); else if (pct < 50) strcpy(location, "Banded Leather"); else if (pct < 75) strcpy(location, "Cured Leather"); else strcpy(location, "Hide"); } break; case ITEM_WEAR_HEAD: { int pct = number_percent(); if (pct < 30) strcpy(location, "Headdress"); else if (pct < 60) strcpy(location, "Helm"); else strcpy(location, "Helmet"); } break; case ITEM_WEAR_LEGS: strcpy(location, "Leggings"); break; case ITEM_WEAR_FEET: { int pct = number_percent(); if (pct < 25) strcpy(location, "Sandals"); else if (pct < 50) strcpy(location, "Shoes"); else strcpy(location, "Boots"); } break; case ITEM_WEAR_HANDS: if (number_percent() < 50) strcpy(location, "Gloves"); else strcpy(location, "Gauntlets"); break; case ITEM_WEAR_ARMS: if (number_percent() < 50) strcpy(location, "Sleeves"); else strcpy(location, "Vambraces"); break; case ITEM_WEAR_SHIELD: strcpy(location, "Shield"); break; case ITEM_WEAR_ABOUT: strcpy(location, "Cloak"); break; case ITEM_WEAR_WAIST: strcpy(location, "Belt"); break; case ITEM_WEAR_WRIST: strcpy(location, "Bracelet"); break; case ITEM_HOLD: strcpy(location, "Orb"); break; case ITEM_WEAR_ORBIT: strcpy(location, "Ball"); break; case ITEM_WEAR_FACE: strcpy(location, "Mask"); break; case ITEM_WEAR_EARS: strcpy(location, "Earrings"); break; case ITEM_WEAR_ANKLE: strcpy(location, "Ankle Bracelet"); break; } /* Checked in reverse order. extra2 high->low, extra1 high->low * since low bits are more likely due to the algorithm, this gives * high order bits precedence for naming. (Otherwise you see a lot * of glowing and humming stuff) */ if (IS_SET(e2, ITEM_DISPEL)) { strcpy(prefix2, "Vortex "); } else if (IS_SET(e2, ITEM_SPARKING )) { strcpy(prefix2, "Lightning "); } else if (IS_SET(e2, ITEM_HIDDEN)) { strcpy(prefix2, "Shadey "); } else if (IS_SET(e1, ITEM_ACID)) { strcpy(prefix2, "Corrosive "); } else if (IS_SET(e1, ITEM_ICY)) { strcpy(prefix2, "Freezing "); } else if (IS_SET(e1, ITEM_FLAME)) { strcpy(prefix2, "Flaming "); } else if (IS_SET(e1, ITEM_POISONED)) { strcpy(prefix2, "Virulent "); } else if (IS_SET(e1, ITEM_BLESS) || IS_SET(e2, ITEM_HOLY)) { strcpy(prefix2, "Blessed "); } else if (IS_SET(e1, ITEM_NODROP) || IS_SET(e1, ITEM_NOREMOVE)) { strcpy(prefix2, "Cursed "); } else if (IS_SET(e1, ITEM_MAGIC)) { strcpy(prefix2, "Magic "); } else if (IS_SET(e1, ITEM_INVIS)) { strcpy(prefix2, "Translucent "); } else if (IS_SET(e1, ITEM_EVIL)) { strcpy(prefix2, "Wicked "); } else if (IS_SET(e1, ITEM_DARK)) { strcpy(prefix2, "Dark "); } else if (IS_SET(e1, ITEM_HUM)) { strcpy(prefix2, "Vibrating "); } else if (IS_SET(e1, ITEM_GLOW)) { strcpy(prefix2, "Bright "); } else { if (number_percent() < 50 ) strcpy(prefix2, "Strange "); else strcpy(prefix2, "Queer "); } first = prefix2[0]; last = location[strlen(location)-1]; if (last == 's') strcpy(prefix1, ""); else if (first == 'A' || first == 'E' || first == 'I' || first == 'O' || first =='U') strcpy(prefix1, "an "); else strcpy(prefix1, "a "); for (paf = armor->affected ; paf; paf = paf->next) { if (strcmp(suffix1, "") && strcmp(suffix2, "")) break; switch (paf->location) { case APPLY_STR: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Steel "); }; break; case APPLY_DEX: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Quicksilver "); }; break; case APPLY_INT: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Mentats"); }; break; case APPLY_WIS: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Owls"); }; break; case APPLY_CON: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Dragonkind"); }; break; case APPLY_MANA: if (!strcmp(suffix2, "")) { strcpy(suffix2, "BattleMages"); }; break; case APPLY_BP: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Vampires"); }; break; case APPLY_ANTI_DIS: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Iron "); }; break; case APPLY_HIT: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Healthiness"); }; break; case APPLY_MOVE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Swift "); }; break; case APPLY_AC: if (!strcmp(suffix2, "")) { strcpy(suffix2, "BlackSmiths"); }; break; case APPLY_HITROLL: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Aiming"); }; break; case APPLY_DAMROLL: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Bloodmetal "); }; break; case APPLY_AGE_SPELL: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Old "); }; break; case APPLY_ANGELIC_AURA: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Angelic "); }; break; case APPLY_ANTI_FLEE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Spiders"); }; break; case APPLY_AURA_ANTI_MAGIC: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Dispelling "); }; break; case APPLY_BEND_LIGHT: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Prismatic "); }; break; case APPLY_BIOFEEDBACK: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Controlled "); }; break; case APPLY_BLADE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Blades"); }; break; case APPLY_BLESS: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Blessed "); }; break; case APPLY_BLIND: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Justice"); }; break; case APPLY_BLOODSHIELD: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Bloodrayne"); }; break; case APPLY_CHANGE_SEX: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Homaphradite "); }; break; case APPLY_CHAOS: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Insanity"); }; break; case APPLY_CLOAKING: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Thieves"); }; break; case APPLY_CLOUD_OF_HEALING: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Druidic "); }; break; case APPLY_COFIRE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Fire "); }; break; case APPLY_COMBAT_MIND: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Monks"); }; break; case APPLY_CONFUSED: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Dimwitted "); }; break; case APPLY_CURSE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Caring"); }; break; case APPLY_CURSE_NATURE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Nature's "); }; break; case APPLY_DANCING: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Twinkling"); }; break; case APPLY_DETECT_EVIL: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Inquisition"); }; break; case APPLY_DETECT_GOOD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Slayers "); }; break; case APPLY_DETECT_HIDDEN: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Eagle-Eyed "); }; break; case APPLY_DETECT_INVIS: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Astral-Eyed "); }; break; case APPLY_DETECT_MAGIC: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Magic-Eyed "); }; break; case APPLY_EARTHSHIELD: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Gaia"); }; break; case APPLY_ESSENCE_OF_GAIA: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Mother Earth"); }; break; case APPLY_ETHEREAL_SNAKE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Serpent "); }; break; case APPLY_ETHEREAL_WOLF: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Wolf "); }; break; case APPLY_FAERIE_FIRE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Visibility"); }; break; case APPLY_FIRESHIELD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Fire Elemental "); }; break; case APPLY_FLAMING: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Everflaming "); }; break; case APPLY_FLYING: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Winged "); }; break; case APPLY_FORCE_OF_NATURE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Nature Warriors"); }; break; case APPLY_FORESTWALK: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Rangers"); }; break; case APPLY_FUMBLE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Butterfingers"); }; break; case APPLY_GHOST_SHIELD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Dead "); }; break; case APPLY_GIANT_STRENGTH:if (!strcmp(suffix2, "")) { strcpy(suffix2, "Cloud Giants"); }; break; case APPLY_GOLDEN_ARMOR: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Shiny "); }; break; case APPLY_GOLDEN_SANCTUARY: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Rightousness"); }; break; case APPLY_HASTE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Hare "); }; break; case APPLY_HEIGHTEN_SENSES: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Hound "); }; break; case APPLY_HIDE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Stealth"); }; break; case APPLY_HOLY_PROTECTION: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Gods Hand"); }; break; case APPLY_ICESHIELD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Arctic "); }; break; case APPLY_IMPROVED_HIDE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Thieves "); }; break; case APPLY_IMPROVED_INVIS: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Forgotten"); }; break; case APPLY_INERTIAL: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Wall"); }; break; case APPLY_INFRARED: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Dwarf "); }; break; case APPLY_INVISIBLE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Unseen"); }; break; case APPLY_LEAF_SHIELD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Forest "); }; break; case APPLY_LIQUID_SKIN: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Fish "); }; break; case APPLY_MALIGNIFY: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Weakness "); }; break; case APPLY_MIST: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Fog "); }; break; case APPLY_MOUNTAINWALK: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Cherpa "); }; break; case APPLY_NAGAROMS_CURSE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "NAGAROM'S UNHOLY WRATH!!!111oneone!1"); }; break; case APPLY_OCCULUTUS_VISUM: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Visage"); }; break; case APPLY_PASS_DOOR: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Phantom Formed "); }; break; case APPLY_PEACE: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Mediation"); }; break; case APPLY_PESTILENCE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Plague "); }; break; case APPLY_PLAINSWALK: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Foal "); }; break; case APPLY_POWER_LEAK: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Fatigue"); }; break; case APPLY_PRAYER: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Holiness"); }; break; case APPLY_PROTECT: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Darks Bane "); }; break; case APPLY_PROTECTION_GOOD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Gods Bane "); }; break; case APPLY_QUICKNESS: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Speed "); }; break; case APPLY_RANDOMSHIELD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "the Unknown "); }; break; case APPLY_SANCTUARY: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Safety"); }; break; case APPLY_SATANIC_INFERNO: if (!strcmp(suffix2, "")) { strcpy(suffix2, "HellFury"); }; break; case APPLY_SCRY: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Farseeing "); }; break; case APPLY_SHADOW_IMAGE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Ever-Ecplipsing "); }; break; case APPLY_SHOCKSHIELD: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Shocking "); }; break; case APPLY_SLIT: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Gagging "); }; break; case APPLY_SNEAK: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Silence "); }; break; case APPLY_SWAMPWALK: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Moors"); }; break; case APPLY_TALE_OF_TERROR: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Fear"); }; break; case APPLY_TITAN_STRENGTH: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Titan "); }; break; case APPLY_TONGUES: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Babel"); }; break; case APPLY_TORTURE: if (!strcmp(suffix1, "")) { strcpy(suffix1, "Soul "); }; break; case APPLY_TRUESIGHT: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Visions"); }; break; case APPLY_UNHOLY_STRENGTH: if (!strcmp(suffix2, "")) { strcpy(suffix2, "Demon Strength"); }; break; } } if (!strcmp(suffix1,"") && !strcmp(suffix2, "")) { strcpy(suffix1, "Insignificance"); } sprintf(final, format, prefix1, prefix2, location, suffix1, suffix2); free_string(armor->short_descr); armor->short_descr = str_dup(final); sprintf(format, "A %s lies here upon the groud, discarded.", location); free_string(armor->description); armor->description = str_dup(format); sprintf(format, "%s %s %s%s", prefix2, location, suffix1, suffix2); free_string(armor->name); armor->name = str_dup(format); return final; } int skill_forestry( int sn, int level, CHAR_DATA *ch, void *vo ) { int i; int forest_count; ROOM_INDEX_DATA* room = ch->in_room; char buf[MAX_STRING_LENGTH]; if (IS_NPC(ch)) { return SKPELL_MISSED; } if (!IS_OUTSIDE(ch) || !IS_FOREST(ch)) { send_to_char(AT_DGREEN, "You have to be outside in a forest to chop wood!\n\r", ch); return SKPELL_BOTCHED; } if (IS_SET(room->timed_room_flags, ROOM_TIMED_DEFORESTED)) { send_to_char(AT_DGREEN, "This forest has already been harvested!\n\r", ch); return SKPELL_BOTCHED; } forest_count = 1; for (i = 0; i < MAX_DIR; i++) { if (room->exit[i] && IS_OUTSIDE(ch) && IS_FOREST(ch)) forest_count++; } sprintf(buf, "%d forest rooms found!\n\r", forest_count); bug(buf, 0); set_timed_room_flags( ch->in_room, ROOM_TIMED_DEFORESTED, 600 ); send_to_char(AT_GREEN, "Forestry isn't completed yet!\n\r", ch); return SKPELL_NO_DAMAGE; } int skill_fletching( int sn, int level, CHAR_DATA *ch, void *vo ) { send_to_char(AT_YELLOW, "Fletching isn't completed yet!\n\r", ch); return SKPELL_NO_DAMAGE; } int skill_mining( int sn, int level, CHAR_DATA *ch, void *vo ) { send_to_char(AT_DGREY, "Mining isn't completed yet!\n\r", ch); return SKPELL_NO_DAMAGE; } int skill_forging( int sn, int level, CHAR_DATA *ch, void *vo ) { send_to_char(AT_DGREY, "Forging isn't completed yet!\n\r", ch); return SKPELL_NO_DAMAGE; } void destroy_craft( CHAR_DATA* ch, bool failed ) { char buf[MAX_STRING_LENGTH]; char* name; PC_DATA* pc; if (IS_NPC(ch)) return; pc = ch->pcdata; name = item_type_name(pc->craft_target); if (failed) { char verb[MAX_STRING_LENGTH]; if (pc->craft_type == CRAFT_SCROLL) strcpy(verb, "burst into flames"); else strcpy(verb, "explodes into pieces"); sprintf(buf, "Your %s %s and disappears!\n\r", name, verb); send_to_char(AT_RED, buf, ch); send_to_char(AT_RED, "You must have made a mistake somewhere!\n\r\n\r", ch); } else { sprintf(buf, "The momentary distraction makes you ruin the %s!\n\r\n\r", name); send_to_char(AT_RED, "Your attempt at crafting is interrupted!\n\r", ch); send_to_char(AT_RED, buf, ch); } if (number_percent() < 25) { OBJ_DATA* o; int type = 0; if (pc->craft_type == CRAFT_SCROLL) type = ITEM_QUILL; else if (pc->craft_type == CRAFT_POTION) type = ITEM_PESTLE; if (type) { for (o = ch->carrying; o; o = o->next_content) { if ( o->item_type == type) break; } sprintf(buf, "Your %s breaks!\n\r", item_type_name(o) ); send_to_char(AT_WHITE, buf, ch); extract_obj(o); } } pc->craft_timer = 0; pc->craft_type = 0; pc->spell1 = 0; pc->spell2 = 0; pc->spell3 = 0; extract_obj(pc->craft_target); } void finish_craft( CHAR_DATA* ch ) { PC_DATA* pc; char buf[MAX_STRING_LENGTH]; if (IS_NPC(ch)) return; pc = ch->pcdata; /* take care of stuff like having sleep cast on you */ if (ch->position != POS_STANDING) destroy_craft(ch, FALSE); switch (pc->craft_type) { default: send_to_char(AT_RED, "You finished something...\n\r", ch); break; case CRAFT_POTION: { int lvl1, lvl2, lvl3; int pct1, pct2, pct3; int pct_scribe = pc->learned[skill_lookup("alchemy")]/10; if (pc->spell3) { int target = 0; lvl1 = UMIN( skill_table[pc->spell1].skill_level[ch->class], skill_table[pc->spell1].skill_level[ch->multied] ); lvl2 = UMIN( skill_table[pc->spell2].skill_level[ch->class], skill_table[pc->spell2].skill_level[ch->multied] ); lvl3 = UMIN( skill_table[pc->spell3].skill_level[ch->class], skill_table[pc->spell3].skill_level[ch->multied] ); pct1 = pc->learned[pc->spell1]/10; pct2 = pc->learned[pc->spell2]/10; pct3 = pc->learned[pc->spell3]/10; target = (pct_scribe + ( (120-lvl1) + pct1) + ( (120-lvl2) + pct2/2) + ( (120-lvl3) + pct3/4) ) / 7; if (number_percent() < target ) { spell_imprint(pc->spell1, ch->level, ch, pc->craft_target); spell_imprint(pc->spell2, ch->level, ch, pc->craft_target); spell_imprint(pc->spell3, ch->level, ch, pc->craft_target); act(AT_WHITE, "$n finishes brewing a potion.", ch, NULL, NULL, TO_ROOM ); } else { destroy_craft( ch, TRUE ); act(AT_WHITE, "$n failed to brew a potion.", ch, NULL, NULL, TO_ROOM ); return; } } else if (pc->spell2) { int target = 0; lvl1 = UMIN( skill_table[pc->spell1].skill_level[ch->class], skill_table[pc->spell1].skill_level[ch->multied] ); lvl2 = UMIN( skill_table[pc->spell2].skill_level[ch->class], skill_table[pc->spell2].skill_level[ch->multied] ); pct1 = pc->learned[pc->spell1]/10; pct2 = pc->learned[pc->spell2]/10; target = (pct_scribe + ( (120-lvl1) + pct1) + ( (120-lvl2) + pct2/2) ) / 5; if (number_percent() < target ) { spell_imprint(pc->spell1, ch->level, ch, pc->craft_target); spell_imprint(pc->spell2, ch->level, ch, pc->craft_target); act(AT_WHITE, "$n finishes brewing a potion.", ch, NULL, NULL, TO_ROOM ); } else { destroy_craft( ch, TRUE ); act(AT_WHITE, "$n failed to brew a potion.", ch, NULL, NULL, TO_ROOM ); return; } } else { int target = 0; lvl1 = UMIN( skill_table[pc->spell1].skill_level[ch->class], skill_table[pc->spell1].skill_level[ch->multied] ); pct1 = pc->learned[pc->spell1]/10; target = (pct_scribe + ( (120-lvl1) + pct1) ) / 3; if (number_percent() < target ) { spell_imprint(pc->spell1, ch->level, ch, pc->craft_target); act(AT_WHITE, "$n finishes brewing a potion.", ch, NULL, NULL, TO_ROOM ); } else { destroy_craft( ch, TRUE ); act(AT_WHITE, "$n failed to brew a potion.", ch, NULL, NULL, TO_ROOM ); return; } } } break; case CRAFT_SCROLL: { int lvl1, lvl2, lvl3; int pct1, pct2, pct3; int pct_scribe = pc->learned[skill_lookup("inscription")]/10; if (pc->spell3) { int target = 0; lvl1 = UMIN( skill_table[pc->spell1].skill_level[ch->class], skill_table[pc->spell1].skill_level[ch->multied] ); lvl2 = UMIN( skill_table[pc->spell2].skill_level[ch->class], skill_table[pc->spell2].skill_level[ch->multied] ); lvl3 = UMIN( skill_table[pc->spell3].skill_level[ch->class], skill_table[pc->spell3].skill_level[ch->multied] ); pct1 = pc->learned[pc->spell1]/10; pct2 = pc->learned[pc->spell2]/10; pct3 = pc->learned[pc->spell3]/10; target = (pct_scribe + ( (120-lvl1) + pct1) + ( (120-lvl2) + pct2/2) + ( (120-lvl3) + pct3/4) ) / 7; if (number_percent() < target ) { spell_imprint(pc->spell1, ch->level, ch, pc->craft_target); spell_imprint(pc->spell2, ch->level, ch, pc->craft_target); spell_imprint(pc->spell3, ch->level, ch, pc->craft_target); act(AT_WHITE, "$n finishes writing a scroll.", ch, NULL, NULL, TO_ROOM ); } else { destroy_craft( ch, TRUE ); act(AT_WHITE, "$n failed to write a scroll.", ch, NULL, NULL, TO_ROOM ); return; } } else if (pc->spell2) { int target = 0; lvl1 = UMIN( skill_table[pc->spell1].skill_level[ch->class], skill_table[pc->spell1].skill_level[ch->multied] ); lvl2 = UMIN( skill_table[pc->spell2].skill_level[ch->class], skill_table[pc->spell2].skill_level[ch->multied] ); pct1 = pc->learned[pc->spell1]/10; pct2 = pc->learned[pc->spell2]/10; target = (pct_scribe + ( (120-lvl1) + pct1) + ( (120-lvl2) + pct2/2) ) / 5; if (number_percent() < target ) { spell_imprint(pc->spell1, ch->level, ch, pc->craft_target); spell_imprint(pc->spell2, ch->level, ch, pc->craft_target); act(AT_WHITE, "$n finishes writing a scroll.", ch, NULL, NULL, TO_ROOM ); } else { destroy_craft( ch, TRUE ); act(AT_WHITE, "$n failed to write a scroll.", ch, NULL, NULL, TO_ROOM ); return; } } else { int target = 0; lvl1 = UMIN( skill_table[pc->spell1].skill_level[ch->class], skill_table[pc->spell1].skill_level[ch->multied] ); pct1 = pc->learned[pc->spell1]/10; target = (pct_scribe + ( (120-lvl1) + pct1) ) / 3; if (number_percent() < target ) { spell_imprint(pc->spell1, ch->level, ch, pc->craft_target); act(AT_WHITE, "$n finishes writing a scroll.", ch, NULL, NULL, TO_ROOM ); } else { destroy_craft( ch, TRUE ); act(AT_WHITE, "$n failed to write a scroll.", ch, NULL, NULL, TO_ROOM ); return; } } } break; } if ( number_percent() < 10 ) { OBJ_DATA* o; int type = 0; if (pc->craft_type == CRAFT_SCROLL) type = ITEM_QUILL; else if (pc->craft_type == CRAFT_POTION) type = ITEM_PESTLE; if (type) { for (o = ch->carrying; o; o = o->next_content) { if ( o->item_type == type) break; } sprintf(buf, "Your %s breaks!\n\r", item_type_name(o) ); send_to_char(AT_WHITE, buf, ch); extract_obj(o); } } pc->craft_target->level = ch->level; pc->craft_target->value[0] = ch->level; SET_BIT(pc->craft_target->extra_flags2, ITEM_CRAFTED); pc->craft_target = NULL; pc->craft_timer = 0; pc->craft_type = 0; pc->spell1 = 0; pc->spell2 = 0; pc->spell3 = 0; } int skill_brew ( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA* pestle; OBJ_DATA* vial; char buf [MAX_STRING_LENGTH]; char spell1[MAX_INPUT_LENGTH]; char spell2[MAX_INPUT_LENGTH]; char spell3[MAX_INPUT_LENGTH]; int sn1; int sn2; int sn3; target_name = one_argument( target_name, spell1 ); target_name = one_argument( target_name, spell2 ); target_name = one_argument( target_name, spell3 ); if ( spell1[0] == '\0' ) { send_to_char(AT_WHITE, "Use alchemy on what spell?\n\r", ch ); return SKPELL_BOTCHED; } if ( (vial = get_obj_carry(ch, spell1)) ) { if (vial->item_type != ITEM_POTION) { send_to_char(AT_WHITE, "You can't empty an item that isn't a potion!\n\r", ch); return SKPELL_BOTCHED; } extract_obj(vial); if (number_percent() > ( ( ch->pcdata->learned[skill_lookup("alchemy")]/10 + (120-vial->level) + (120-vial->value[0]) ) /2 ) ) { send_to_char(AT_WHITE, "Oh no! You crack the vial. It's ruined!\n\r", ch); act( AT_WHITE, "$n cracks a vial while trying to empty it.\n\r", ch, NULL, NULL, TO_ROOM); return SKPELL_BOTCHED; } act( AT_WHITE, "$n empties a vial..\n\r", ch, NULL, NULL, TO_ROOM); send_to_char(AT_WHITE, "You empty the vial.\n\r", ch); vial = create_object( get_obj_index( OBJ_VNUM_FLASK ), ch->level); obj_to_char(vial, ch); return SKPELL_NO_DAMAGE; } if ( (sn1 = skill_lookup(spell1)) < 0 || !ch->pcdata->learned[sn1] || !can_use_skspell(ch, sn1) ) { sprintf(buf, "You don't know '%s'! How can you brew it?\n\r", spell1); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!skill_table[sn1].is_spell) { sprintf(buf, "'%s' is not a spell!\n\r", spell1); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!IS_SET(skill_table[sn1].craftable, CRAFT_POTION)) { sprintf( buf, "You are unable to brew the spell '%s'\n\r", spell1); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } if (spell2[0]) { if ( (sn2 = skill_lookup(spell2) ) < 0 || !ch->pcdata->learned[sn2] || !can_use_skspell(ch, sn2) ) { sprintf(buf, "You don't know '%s'! How can you brew it?\n\r", spell2); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!skill_table[sn2].is_spell) { sprintf(buf, "'%s' is not a spell!\n\r", spell2); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!IS_SET(skill_table[sn2].craftable, CRAFT_POTION)) { sprintf( buf, "You are unable to brew the spell '%s'\n\r", spell2); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } } else { sn2 = 0; } if (spell3[0]) { if ( (sn3 = skill_lookup(spell3) ) < 0 || !ch->pcdata->learned[sn3] || !can_use_skspell(ch, sn3) ) { sprintf(buf, "You don't know '%s'! How can you brew it?\n\r", spell3); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!skill_table[sn3].is_spell) { sprintf(buf, "'%s' is not a spell!\n\r", spell3); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!IS_SET(skill_table[sn3].craftable, CRAFT_POTION)) { sprintf( buf, "You are unable to brew the spell '%s'\n\r", spell3); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } } else { sn3 = 0; } /* Do we have a parchment to scribe spells? */ for ( vial = ch->carrying; vial; vial = vial->next_content ) { if ( vial->item_type == ITEM_POTION && !(vial->value[0] || vial->value[1] || vial->value[2] || vial->value[3]) ) break; } if ( !vial ) { send_to_char(AT_WHITE, "You do not have an empty vial.\n\r", ch ); return SKPELL_BOTCHED; } for ( pestle = ch->carrying; pestle; pestle = pestle->next_content ) { if ( pestle->item_type == ITEM_PESTLE ) break; } if ( !pestle ) { send_to_char(AT_WHITE, "You do not have a pestle and mortar.\n\r", ch ); return SKPELL_BOTCHED; } act(AT_WHITE, "$n begins brewing a potion.", ch, vial, NULL, TO_ROOM ); send_to_char(AT_WHITE, "You begin to carefully brew the potion.\n\r", ch); ch->pcdata->spell1 = sn1; ch->pcdata->spell2 = sn2; ch->pcdata->spell3 = sn3; ch->pcdata->craft_target = vial; ch->pcdata->craft_type = CRAFT_POTION; ch->pcdata->craft_timer = ( MANA_COST( ch, sn1) + (sn2 ? MANA_COST(ch, sn2) : 0 ) + (sn3 ? MANA_COST(ch, sn3) : 0 ) ); return SKPELL_NO_DAMAGE; } int skill_inscription ( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA* quill; OBJ_DATA* parch; char buf [MAX_STRING_LENGTH]; char spell1[MAX_INPUT_LENGTH]; char spell2[MAX_INPUT_LENGTH]; char spell3[MAX_INPUT_LENGTH]; int sn1; int sn2; int sn3; target_name = one_argument( target_name, spell1 ); target_name = one_argument( target_name, spell2 ); target_name = one_argument( target_name, spell3 ); if ( spell1[0] == '\0' ) { send_to_char(AT_WHITE, "Use inscription what spell?\n\r", ch ); return SKPELL_BOTCHED; } if ( (parch = get_obj_carry(ch, spell1)) ) { if (parch->item_type != ITEM_SCROLL) { send_to_char(AT_WHITE, "You can't scrape an item that isn't a scroll!\n\r", ch); return SKPELL_BOTCHED; } extract_obj(parch); if (number_percent() > ( ( ch->pcdata->learned[skill_lookup("inscription")]/10 + (120-parch->level) + (120-parch->value[0]) ) /2 ) ) { send_to_char(AT_WHITE, "Oh no! You made a mistake. The scroll is ruined!\n\r", ch); act( AT_WHITE, "$n tears a scroll while trying to clear it.\n\r", ch, NULL, NULL, TO_ROOM); return SKPELL_BOTCHED; } act( AT_WHITE, "$n scrapes the words from a scroll.\n\r", ch, NULL, NULL, TO_ROOM); send_to_char(AT_WHITE, "You scrape the text from the scroll.\n\r", ch); parch = create_object( get_obj_index( OBJ_VNUM_PARCHMENT ), ch->level); obj_to_char(parch, ch); return SKPELL_NO_DAMAGE; } if ( (sn1 = skill_lookup(spell1)) < 0 || !ch->pcdata->learned[sn1] || !can_use_skspell(ch, sn1) ) { sprintf(buf, "You don't know '%s'! How can you scribe it?\n\r", spell1); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!skill_table[sn1].is_spell) { sprintf(buf, "'%s' is not a spell!\n\r", spell1); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!IS_SET(skill_table[sn1].craftable, CRAFT_SCROLL)) { sprintf( buf, "You are unable to scribe the spell '%s'\n\r", spell1); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } if (spell2[0]) { if ( (sn2 = skill_lookup(spell2) ) < 0 || !ch->pcdata->learned[sn2] || !can_use_skspell(ch, sn2) ) { sprintf(buf, "You don't know '%s'! How can you scribe it?\n\r", spell2); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!skill_table[sn2].is_spell) { sprintf(buf, "'%s' is not a spell!\n\r", spell2); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!IS_SET(skill_table[sn2].craftable, CRAFT_SCROLL)) { sprintf( buf, "You are unable to scribe the spell '%s'\n\r", spell2); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } } else { sn2 = 0; } if (spell3[0]) { if ( (sn3 = skill_lookup(spell3) ) < 0 || !ch->pcdata->learned[sn3] || !can_use_skspell(ch, sn3) ) { sprintf(buf, "You don't know '%s'! How can you scribe it?\n\r", spell3); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!skill_table[sn3].is_spell) { sprintf(buf, "'%s' is not a spell!\n\r", spell3); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } else if (!IS_SET(skill_table[sn3].craftable, CRAFT_SCROLL)) { sprintf( buf, "You are unable to scribe the spell '%s'\n\r", spell3); send_to_char(AT_WHITE, buf, ch); return SKPELL_BOTCHED; } } else { sn3 = 0; } /* Do we have a parchment to scribe spells? */ for ( parch = ch->carrying; parch; parch = parch->next_content ) { if ( parch->item_type == ITEM_SCROLL && !(parch->value[0] || parch->value[1] || parch->value[2] || parch->value[3] )) break; } if ( !parch ) { send_to_char(AT_WHITE, "You do not have a parchment.\n\r", ch ); return SKPELL_BOTCHED; } for ( quill = ch->carrying; quill; quill = quill->next_content ) { if ( quill->item_type == ITEM_QUILL ) break; } if ( !quill ) { send_to_char(AT_WHITE, "You do not have a quill.\n\r", ch ); return SKPELL_BOTCHED; } act(AT_WHITE, "$n begins writing a scroll.", ch, parch, NULL, TO_ROOM ); send_to_char(AT_WHITE, "You begin to carefully write the scroll.\n\r", ch); ch->pcdata->spell1 = sn1; ch->pcdata->spell2 = sn2; ch->pcdata->spell3 = sn3; ch->pcdata->craft_target = parch; ch->pcdata->craft_type = CRAFT_SCROLL; ch->pcdata->craft_timer = ( MANA_COST( ch, sn1) + (sn2 ? MANA_COST(ch, sn2) : 0 ) + (sn3 ? MANA_COST(ch, sn3) : 0 ) ); return SKPELL_NO_DAMAGE; } void spell_imprint( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *obj = (OBJ_DATA *) vo; int sp_slot, i, mana; char buf[ MAX_STRING_LENGTH ]; if (obj->deleted) { return; }; if (skill_table[sn].spell_fun == spell_null ) { send_to_char(AT_WHITE,"That is not a spell.\n\r",ch); return; } /* counting the number of spells contained within */ for (sp_slot = i = 1; i < 4; i++) if (obj->value[i] != skill_lookup("reserved")) sp_slot++; if (sp_slot > 3) { act (AT_WHITE,"$p cannot contain any more spells.", ch, obj, NULL, TO_CHAR); return; } /* scribe/brew costs 4 times the normal mana required to cast the spell */ mana = 4 * MANA_COST(ch, sn); if ( !IS_NPC(ch) && ch->mana < mana ) { send_to_char(AT_WHITE, "You don't have enough mana.\n\r", ch ); return; } if ( IS_NPC( ch ) || ( number_percent() > ( ch->pcdata->learned[sn] / 10 ) && ch->level < L_SEN ) ) { send_to_char(AT_WHITE, "You lost your concentration.\n\r", ch ); ch->mana -= mana / 2; return; } /* executing the imprinting process */ ch->mana -= mana; obj->value[sp_slot] = sn; /* Making it successively harder to pack more spells into potions or scrolls - JH */ if (ch->level < L_SEN ) { switch( sp_slot ) { default: bug( "sp_slot has more than %d spells.", sp_slot ); return; case 1: break; case 2: if ( number_percent() > 80 ) { sprintf(buf, "The magic enchantment has failed --- the %s vanishes.\n\r", item_type_name(obj) ); send_to_char(AT_WHITE, buf, ch ); extract_obj( obj ); return; } break; case 3: if ( number_percent() > 60 ) { sprintf(buf, "The magic enchantment has failed --- the %s vanishes.\n\r", item_type_name(obj) ); send_to_char(AT_WHITE, buf, ch ); extract_obj( obj ); return; } break; } } /* If level < L_SEN */ /* labeling the item */ free_string (obj->short_descr); sprintf ( buf, "a %s of ", item_type_name(obj) ); for (i = 1; i <= sp_slot ; i++) if (obj->value[i] != -1) { strcat (buf, skill_table[obj->value[i]].name); (i != sp_slot ) ? strcat (buf, ", ") : strcat (buf, "") ; } obj->short_descr = str_dup(buf); free_string( obj->name ); sprintf( buf, "%s ", item_type_name( obj ) ); for( i = 1; i <= sp_slot; i++ ) if( obj->value[i] != -1 ) { strcat( buf, skill_table[obj->value[i]].name); (i != sp_slot ) ? strcat( buf, " ") : strcat( buf, "" ); } obj->name = strdup( buf ); free_string( obj->description ); sprintf( buf, "A %s is here. (", item_type_name( obj ) ); for( i = 1; i <= sp_slot; i++ ) if( obj->value[i] != -1 ) { strcat( buf, skill_table[obj->value[i]].name); (i != sp_slot ) ? strcat( buf, ", ") : strcat( buf, "" ); } sprintf( buf, "%s).", buf ); obj->description = strdup( buf ); sprintf(buf, "You have imbued a new spell to the %s.\n\r", item_type_name(obj) ); send_to_char(AT_WHITE, buf, ch ); return; } /* Study skill... converted from Rom by Maniac */ int skill_study( int sn, int level, CHAR_DATA *ch, void *vo ) { OBJ_DATA *scroll; return SKPELL_MISSED; if (( scroll = get_obj_carry(ch,target_name)) == NULL) { send_to_char(AT_WHITE,"You don't have that scroll.\n\r",ch); return SKPELL_BOTCHED; } if ( scroll->item_type != ITEM_SCROLL ) { send_to_char(AT_WHITE,"You can only study scrolls.\n\r",ch); return SKPELL_BOTCHED; } if ( ch->level < scroll->level ) { send_to_char(AT_WHITE,"You are not a high enough level to use this scroll.\n\r", ch ); return SKPELL_MISSED; } if (( skill_table[scroll->value[1]].skill_level[ch->class] >= 72 ) && ( !IS_IMMORTAL(ch) )) { send_to_char(AT_WHITE,"Your class may not learn that spell.\n\r",ch); return SKPELL_MISSED; } if ( skill_table[scroll->value[1]].skill_level[ch->class] > ch->level ) { send_to_char(AT_WHITE,"This spell is beyond your grasp. Perhaps in a few levels...\n\r", ch ); return SKPELL_MISSED; } if ( ch->pcdata->learned[scroll->value[1]] > 0 ) { send_to_char(AT_WHITE,"You know that spell already!\n\r",ch); return SKPELL_MISSED; } act(AT_WHITE,"$n studies $p.",ch,scroll,NULL,TO_ROOM); act(AT_WHITE,"You study $p.",ch,scroll,NULL,TO_CHAR); if (number_percent() >= (20 + ( ch->pcdata->learned[skill_lookup("scrolls")] / 10 ) ) * 4/5) { send_to_char(AT_WHITE,"You mess up and the scroll vanishes!\n\r",ch); act(AT_WHITE,"$n screams in anger.",ch,NULL,NULL,TO_ROOM); } else { act(AT_WHITE,"You learn the spell!",ch,NULL,NULL,TO_CHAR); act(AT_WHITE,"$n learned the spell!",ch,NULL,NULL,TO_ROOM); ch->pcdata->learned[scroll->value[1]] = 50; } extract_obj(scroll); return SKPELL_NO_DAMAGE; } void strip_timed_room_flags( ROOM_INDEX_DATA* room) { char buf[MAX_STRING_LENGTH]; sprintf(buf, "Resetting flags for room: %d", room->vnum); log_string( buf, CHANNEL_LOG, L_APP); room->timed_room_flags = 0; } void set_timed_room_flags( ROOM_INDEX_DATA* room, int flag, int timer ) { if (!room) return; SET_BIT(room->timed_room_flags, flag); room->flag_timer = UMAX( room->flag_timer, timer); room->next_timed_room = timed_room_list; timed_room_list = room; switch (flag) { case ROOM_TIMED_DEFORESTED: case ROOM_TIMED_MINED: case ROOM_TIMED_CAMP: default: /* do something. like... load a camp fire */ break; } }