/*************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik Stfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. 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. * ***************************************************************************/ /*************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * ***************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "tables.h" #include "lookup.h" #include "olc.h" #include "const.h" #define MAX_ARMOR_SUFFIX 25 #define MAX_WEAPON_SUFFIX 15 #define MAX_PREFIX 6 CHAR_DATA *random_mob args( (void) ); void format_obj args( (OBJ_DATA *obj) ); void format_obj_weapon args( (OBJ_DATA *obj) ); void format_obj_armor args( (OBJ_DATA *obj) ); int wear_bit args( (int loc) ); void name_obj args( (CHAR_DATA *mob,OBJ_DATA *obj, int i, int x, int y) ); char *weapon_type_name args( (OBJ_DATA *obj) ); char *armor_type_name args( (OBJ_DATA *obj) ); int which_location args( (void) ); void apply_good_affect args( (OBJ_DATA *obj,bool positive) ); void unique_obj_set args((OBJ_DATA *pObj, int stat_type, int add_stat )); extern struct fix_type fix_table[]; DECLARE_DO_FUN(do_wear ); struct unique_prefix_type { char *descriptive; int stat_style; }; struct unique_attrib_table unique_table_armor_suffix[MAX_ARMOR_SUFFIX] = { { "" }, { "taste" }, { "protection" }, { "value" }, { "power" }, { "dark power" }, { "holiness" }, { "desecration" }, { "hope" }, { "hopelessness" }, { "care" }, { "invunlerability" }, { "Ferric" }, { "Dagda" }, { "Chele" }, { "Khain" }, { "Keogh" }, { "Svartalfar" }, { "Makaruda" }, { "Moirai" }, { "Diku" }, { "the fallen" }, { "the gods" }, { "the Shrike" }, { "mystery" }, }; struct unique_attrib_table unique_table_weapon_suffix[MAX_WEAPON_SUFFIX] = { { "" }, { "destruction" }, { "sharpness" }, { "power" }, { "maiming" }, { "killing" }, { "slaying" }, { "havok" }, { "crushing" }, { "cutting" }, { "fear" }, { "pillage" }, { "slashing"}, { "annoyance" }, { "striking" }, }; struct unique_prefix_type unique_table_prefix[MAX_PREFIX] = { { "", -1 }, { "Angel", STAT_INT }, { "Drake", STAT_STR }, { "Elder", STAT_WIS }, { "Lord", STAT_CON }, { "Monk", STAT_DEX } }; int match_bit_to_int(int bit) { int i; for( i = 0; fix_table[i].bit != -1 ; i++) { if( IS_SET(bit, fix_table[i].bit ) ) return fix_table[i].wear; } return -1; } void create_unique(void) { OBJ_DATA *obj; char buf[MSL]; CHAR_DATA *mob; int iWear; int prefx = number_range(1,MAX_PREFIX-1); int wSfx = number_range(1,MAX_WEAPON_SUFFIX-1); int aSfx = number_range(1,MAX_ARMOR_SUFFIX-1); if( ( mob = random_mob() ) == NULL ) { logf2("Random mod generation failed. Not creating unique."); return; } if ( (obj = create_object( get_obj_index( OBJ_UNIQUE_DUMMY), 0) ) == NULL) { log_string( "Bug with OBJ_UNIQUE_DUMMY"); return; } free_string(obj->short_descr); free_string(obj->description); if ( IS_SET( mob->in_room->area->area_flags , NO_UNIQUE ) ) return; SET_BIT(obj->wear_flags,ITEM_TAKE); obj->level = mob->level; format_obj(obj); name_obj(mob,obj, prefx, wSfx, aSfx); unique_obj_set(obj, unique_table_prefix[prefx].stat_style, aSfx); SET_BIT( obj->extra2_flags, ITEM_UNIQUE ); SET_BIT( obj->extra2_flags, ITEM_RELIC ); obj->xp_tolevel = MIN_XP; if( ( iWear = match_bit_to_int(obj->wear_flags) ) == -1 ) { logf2("BUG: create_unique- Match_bit_to_int == -1"); return; } obj_to_char(obj,mob); equip_char(mob,obj,iWear); sprintf(buf,"The unique object, %s, loaded to %s in room %d", obj->short_descr,mob->name,mob->in_room->vnum); log_string( buf ); sprintf(buf,"%s (On: %d)[In: %d]", obj->name, mob->pIndexData->vnum, mob->in_room->vnum ); wiznet(buf, NULL, NULL, WIZ_UNIQUE, 0 ,106); } void do_tally(CHAR_DATA *ch, char *argument) { OBJ_DATA *obj; int tally = 0; bool show = FALSE; if(!str_cmp(argument, "show" ) ) show = TRUE; for(obj = object_list; obj != NULL; obj = obj->next ) { CHAR_DATA *vch; if( (vch = obj->carried_by) == NULL) continue; if(!IS_NPC(vch)) continue; if(IS_SET(obj->extra2_flags,ITEM_UNIQUE) ) { tally++; if(show) printf_to_char(ch, "%d) %s (On: %d)[In: %d]\n\r",tally, obj->name, obj->carried_by && obj->carried_by->pIndexData ? obj->carried_by->pIndexData->vnum : 0, obj->carried_by ? obj->carried_by->in_room->vnum : 0 ); } } printf_to_char( ch, "Their are currently %d unique items in the wilderness.\n\r", tally ); return; } int which_location() { int i; int location = 0; i = number_range(1,11); switch(i) { case 1: location = APPLY_STR; break; case 2: location = APPLY_DEX; break; case 3: location = APPLY_INT; break; case 4: location = APPLY_WIS; break; case 5: location = APPLY_CON; break; case 6: location = APPLY_MANA; break; case 7: location = APPLY_HIT; break; case 8: location = APPLY_MOVE; break; case 9: location = APPLY_HITROLL; break; case 10: location = APPLY_DAMROLL; break; case 11: location = APPLY_SAVES; break; } return location; } /*Lets apply some nice affects.*/ void apply_good_affect(OBJ_DATA *obj,bool positive) { int location; AFFECT_DATA *af; int mult; int value; int max,min; location = which_location(); switch(location) { default: mult = 10; break; case(APPLY_HIT): mult = 20; break; case(APPLY_MOVE): mult = 20; break; case(APPLY_MANA): mult = 20; break; } value = (1+(obj->level/10)) * mult; max = value*2; min = value/2; if(min == 0) min++; /*apply a negative affect*/ if(!positive) { value = value*-1; max = value/2; min = value*2; } af = new_affect(); af->location = location; af->modifier = number_range(min,max); af->where = 0; af->type = -1; af->duration = -1; af->bitvector = 0; af->level = obj->level; af->next = obj->affected; obj->affected = af; } /*the fido's armor of taste*/ void name_obj(CHAR_DATA *mob,OBJ_DATA *obj, int i, int x, int y) { char buf[MSL]; char buf2[MSL]; char buf3[MSL]; sprintf(buf,"the %s's %s of %s", unique_table_prefix[i].descriptive, get_obj_use(obj, UTYPE_WEAPON) ? weapon_type_name(obj) : armor_type_name(obj), get_obj_use(obj, UTYPE_WEAPON) ? unique_table_weapon_suffix[x].descriptive : unique_table_armor_suffix[y].descriptive); sprintf(buf2,"%s is laying here on the ground.",buf); sprintf(buf3,"%s",buf); free_string(obj->name); free_string(obj->short_descr); free_string(obj->description); obj->name = str_dup(buf3); obj->short_descr = str_dup(buf); obj->description = str_dup(buf2); } void format_obj_weapon(OBJ_DATA *obj) { int i; USE *use; use = get_obj_use(obj, UTYPE_WEAPON); /*What type of weapon?*/ i = number_range(0,8); use->value[0] = i; /*Set it to wield*/ SET_BIT(obj->wear_flags,ITEM_WIELD); } char *weapon_type_name(OBJ_DATA *obj) { USE *use; static char buf[MSL]; buf[0] = '\0'; use = get_obj_use(obj, UTYPE_WEAPON); switch(use->value[0]) { case(WEAPON_EXOTIC) : sprintf(buf, "exotic weapon"); break; case(WEAPON_SWORD): sprintf(buf, "sword"); break; case(WEAPON_DAGGER): sprintf(buf, "dagger"); break; case(WEAPON_SPEAR): sprintf(buf, "spear"); break; case(WEAPON_MACE): sprintf(buf, "mace"); break; case(WEAPON_AXE): sprintf(buf, "axe"); break; case(WEAPON_FLAIL): sprintf(buf, "flail"); break; case(WEAPON_WHIP): sprintf(buf, "whip"); break; case(WEAPON_POLEARM): sprintf(buf, "polearm"); break; case(WEAPON_STAFF): sprintf(buf, "staff"); break; } return buf; } char *armor_type_name(OBJ_DATA *obj) { int i; static char buf[MSL]; buf[0] = '\0'; switch(obj->wear_loc) { case 0: sprintf(buf, "light"); break; case 1: case 2: sprintf(buf, "ring"); break; case 3: case 4: i = number_range(1,3); if(i == 1) sprintf(buf, "necklace"); else if(i == 2) sprintf(buf, "pendant"); else sprintf(buf, "neck guard"); break; case 5: i = number_range(1,3); if(i == 1) sprintf(buf, "armor"); else if(i == 2) sprintf(buf, "breastplate"); else sprintf(buf, "chain mail"); break; case 6: i = number_range(1,3); if(i == 1) sprintf(buf, "skullcap"); else if(i == 2) sprintf(buf, "helmet"); else sprintf(buf, "helm"); break; case 7: i = number_range(1,3); if(i == 1) sprintf(buf, "leggings"); else if(i == 2) sprintf(buf, "leg plates"); else sprintf(buf, "pants"); break; case 8: i = number_range(1,3); if(i == 1) sprintf(buf, "sandals"); else if(i == 2) sprintf(buf, "boots"); else sprintf(buf, "clogs"); break; case 9: i = number_range(1,3); if(i == 1) sprintf(buf, "gloves"); else if(i == 2) sprintf(buf, "gauntlets"); else sprintf(buf, "sap gloves"); break; case 10: sprintf(buf, "arm plates"); break; case 11: sprintf(buf, "shield"); break; case 12: i = number_range(1,3); if(i == 1) sprintf(buf, "cloak"); else if(i == 2) sprintf(buf, "cape"); else sprintf(buf, "coat"); break; case 13: i = number_range(1,3); if( i == 1) sprintf(buf, "belt"); else if(i == 2) sprintf(buf, "girdle"); else sprintf(buf, "chain"); break; case 14: case 15: i = number_range(1,3); if( i == 1) sprintf(buf, "bracelet"); else if(i == 2) sprintf(buf, "wrist band"); else sprintf(buf, "band"); break; } return buf; } void format_obj_armor(OBJ_DATA *obj) { USE *use; /*Objects of ARMOR type can be ring, boots, shield, etc. Lets assign a random wear location to decide what this will be.*/ obj->wear_loc = number_range(0,15); /*Ok, we have a type now. Lets go through and set a wear bit.*/ switch(obj->wear_loc) { case 0: use = new_use(); use->use_type = UTYPE_LIGHT; use_to_obj( obj, use ); break; case 1: case 2: SET_BIT(obj->wear_flags,ITEM_WEAR_FINGER); break; case 3: case 4: SET_BIT(obj->wear_flags,ITEM_WEAR_NECK); break; case 5: SET_BIT(obj->wear_flags,ITEM_WEAR_BODY); break; case 6: SET_BIT(obj->wear_flags,ITEM_WEAR_HEAD); break; case 7: SET_BIT(obj->wear_flags,ITEM_WEAR_LEGS); break; case 8: SET_BIT(obj->wear_flags,ITEM_WEAR_FEET); break; case 9: SET_BIT(obj->wear_flags,ITEM_WEAR_HANDS); break; case 10: SET_BIT(obj->wear_flags,ITEM_WEAR_ARMS); break; case 11: SET_BIT(obj->wear_flags,ITEM_WEAR_SHIELD); break; case 12: SET_BIT(obj->wear_flags,ITEM_WEAR_ABOUT); break; case 13: SET_BIT(obj->wear_flags,ITEM_WEAR_WAIST); break; case 14: case 15: SET_BIT(obj->wear_flags,ITEM_WEAR_WRIST); break; } } void format_obj(OBJ_DATA *obj) { USE *use; int i; /* Weapon, Armor? */ i = number_range(0,1); switch(i) { case 0: use = new_use(); use->use_type = UTYPE_WEAPON; use_to_obj( obj, use ); format_obj_weapon(obj); break; case 1: use = new_use(); use->use_type = UTYPE_ARMOR; use_to_obj( obj, use ); format_obj_armor(obj); break; } } CHAR_DATA *random_mob() { CHAR_DATA *mob; CHAR_DATA *vch; CHAR_DATA *vch_next; char buf[MSL]; int i,x; mob = NULL; i = (number_range(1,top_mob_index)); x = 0; for(vch = char_list; vch != NULL; vch = vch_next) { vch_next = vch->next; if(!IS_NPC(vch) || (vch->pIndexData == NULL || vch->name == NULL || vch->short_descr == NULL || vch->in_room == NULL ) || vch->pIndexData->vnum < 100 || vch->in_room->clan > 0 || IS_SET( vch->act, ACT_TRAIN | ACT_PRACTICE | ACT_IS_HEALER | ACT_PET | ACT_GAIN | ACT_BOUNTY | ACT_MOUNT | ACT_FORGER | ACT_IS_CHANGER ) || IS_SET( vch->in_room->room_flags, ROOM_PET_SHOP) ) continue; x++; if ( i == 0 || x == 0 || vch == NULL ) { sprintf(buf,"RANDOM_MOB: Null mob, i is 0, or x is 0. I: %d, X: %d, Vch: %s", i, x, vch->name ); log_string(buf); } if(x == i) mob = vch; if(x >= top_mob_index) break; } return mob; } void unique_obj_set(OBJ_DATA *pObj, int stat_type, int add_stat ) { int dice, size, bonus; double avg; AFFECT_DATA *pAf; USE *use; bonus = UMAX(0, pObj->level/5 - 1); /* adjust this next line to change the avg dmg your weapons will get! */ avg = (pObj->level * .90); dice = (pObj->level/8 + 1); size = dice/2; for (size=dice/2 ; dice * (size +2)/2 < avg ; size++ ); dice = UMAX(1, dice); size = UMAX(2, size); if( ( use = get_obj_use(pObj, UTYPE_ARMOR ) ) ) { size = (int)(UMAX(1, pObj->level/2.8 + 1)); pObj->weight = pObj->level + 1; pObj->cost = pObj->level^2 * 2; use->value[0] = size; use->value[1] = size; use->value[2] = size; use->value[3] = (size - 1); } else if( ( use = get_obj_use(pObj, UTYPE_WEAPON ) ) ) { switch (use->value[0]) { default: case WEAPON_EXOTIC: case WEAPON_BOW: case WEAPON_SWORD: break; case WEAPON_DAGGER: dice = UMAX(1, dice - 1); size = UMAX(2, size - 1); break; case WEAPON_SPEAR: case WEAPON_POLEARM: size++; break; case WEAPON_MACE: case WEAPON_AXE: size = UMAX(2,size - 1); break; case WEAPON_FLAIL: case WEAPON_WHIP: dice = UMAX(1, dice - 1); break; } dice = UMAX(1, dice); size = UMAX(2, size); } pObj->cost = 25 * (size * (dice + 1)) + 20 * bonus + 20 * pObj->level; pObj->weight = pObj->level + 1; use->value[1] = dice; use->value[2] = size; if(bonus > 0 ) switch(stat_type) { case STAT_STR: pAf = new_affect(); pAf->location = APPLY_DAMROLL; pAf->modifier = (int)(bonus*1.5); pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; pAf = new_affect(); pAf->location = APPLY_STR; pAf->modifier = bonus; pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; break; case STAT_DEX: pAf = new_affect(); pAf->location = APPLY_HITROLL; pAf->modifier = (int)(bonus * 1.5); pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; pAf = new_affect(); pAf->location = APPLY_DEX; pAf->modifier = bonus; pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; break; case STAT_CON: pAf = new_affect(); pAf->location = APPLY_HIT; pAf->modifier = (int)(bonus * 1.5); pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; pAf = new_affect(); pAf->location = APPLY_CON; pAf->modifier = bonus; pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; break; case STAT_INT: pAf = new_affect(); pAf->location = APPLY_MANA; pAf->modifier = (int)(bonus * 1.5); pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; pAf = new_affect(); pAf->location = APPLY_INT; pAf->modifier = bonus; pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; break; case STAT_WIS: pAf = new_affect(); pAf->location = APPLY_WIS; pAf->modifier = (int)(bonus * 1.5); pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; pAf = new_affect(); pAf->location = APPLY_SAVES; pAf->modifier = bonus - (bonus*2); // Saves gotta be a negitive, and Ionno how else to do it. pAf->where = TO_OBJECT; pAf->type = -1; pAf->duration = -1; pAf->bitvector = 0; pAf->level = pObj->level; pAf->next = pObj->affected; pObj->affected = pAf; break; } return; }