/*
* This will generate a random item (5% container, 35% weapon / 65% armor) with randomized stats based on mob level.
* The item will be give a quality name based on the total stats it has, and further named based on slot
* and the highest stat on it. You can adjust how much level affects the stat bonuses by looking at a few
* of the loops used. There is also a modifier you can adjust based on mob flags or other criteria (I used
* elite and boss mobs). This should plug straight into probably any Dystopia with very minor modification,
* and was developed on Dystopia X-Mas Edition.
*
* Add the following to fight.c in hurt_person() directly above the call to raw_kill(victim).
* if( IS_NPC(victim) ) mob_rand_drop(victim,victim->level);
*
* In your object_data struct (mud.h, merc.h, or similar) add the following:
* bool has_aff;
*
* In your create_object() function make sure to initialize has_aff to FALSE, just to be safe.
*
* Also in your primary header (mud.h, merc.h, or similar) add the following:
* enum { QUALITY_NONE, QUALITY_POOR, QUALITY_COMMON, QUALITY_UNCOMMON, QUALITY_SUPERIOR, QUALITY_EPIC, QUALITY_LEGENDARY };
*
* If you want object quality to display like an item flag, add the folowing to the top of format_obj_to_char(),
* directly after the buffer declaration and clearing.
* switch( obj->quality )
* {
*  case QUALITY_NONE:        break;
*  case QUALITY_POOR:        strcat(buf, "#9(#0Poor#9)#n ");      break;
*  case QUALITY_COMMON:      strcat(buf, "#9(#7Common#9)#n ");    break;
*  case QUALITY_UNCOMMON:    strcat(buf, "#9(#GUncommon#9)#n ");  break;
*  case QUALITY_SUPERIOR:    strcat(buf, "#9(#LSuperior#9)#n ");  break;
*  case QUALITY_EPIC:        strcat(buf, "#9(#PEpic#9)#n ");      break;
*  case QUALITY_LEGENDARY:   strcat(buf, "#9(#RLegendary#9)#n "); break;
* }
*
* Feel free to modify this code to suit your needs, and if you have a great improvement I wouldn't mind if you
* shared it with me either, if you're so inclined :D. All I ask is to give me credit for the code if you do
* choose to use it.
*
* Updated to add random spell affects to items, too, and fixed a few minor bugs.
* One more fix to how spell affects save, after I realized how bastardized GodWars handles them.
*
* --Kline (Matt Goff)
*/

#define MAX_AFFECT_NAME 12
char *const affect_name[] = {
 "#9Invisibility#n", "#0Detect #9Invisibility#n", "#9Detect Hidden#n", "#LSanctuary#n", "#rNight Sight#n", "#gProtection #nfrom #REvil#n",
 "#oSneak#n", "#lFlying#n", "#pPass Door#n", "#gProtection #nfrom #CGood#n"
};

#define MAX_WEAPON_NAME 13
char *const weapon_name[] = {
 "", "Slicer", "Spear", "Blade", "Whip", "Claw", "Blaster", "Hammer", "Mace", "Grepper", "Biter", "Dagger", "Sucker"
};

#define MAX_QUALITY_NAME 6
char *const quality_name[] = {
 " Poor", " Common", " Uncommon", " Superior", " Epic", " Legendary"
};

#define MAX_CONTAINER_NAME 5
char *const container_name[] = {
 "Bag", "Satchel", "Sack", "Pouch", "Backpack"
};

#define MAX_FINGER_NAME 1
char *const finger_name[] = {
 "Ring"
};

#define MAX_NECK_NAME 4
char *const neck_name[] = {
 "Necklace", "Amulet", "Choker", "Gorget"
};

#define MAX_BODY_NAME 4
char *const body_name[] = {
 "Chest Guard", "Breastplate", "Robe", "Dress"
};

#define MAX_HEAD_NAME 5
char *const head_name[] = {
 "Helmet", "Skullcap", "Hat", "Hood", "Cowl"
};

#define MAX_LEGS_NAME 5
char *const legs_name[] = {
 "Leggings", "Leg Guards", "Pants", "Skirt", "Stockings"
};

#define MAX_FEET_NAME 4
char *const feet_name[] = {
 "Boots", "Shoes", "Sandals", "Slippers"
};

#define MAX_HANDS_NAME 4
char *const hands_name[] = {
 "Gloves", "Gauntlets", "Knuckles", "Mittens"
};

#define MAX_ARMS_NAME 2
char *const arms_name[] = {
 "Arm Guards", "Sleeves"
};

#define MAX_SHIELD_NAME 5
char *const shield_name[] = {
 "Buckler", "Tower Shield", "Shield", "Round Shield", "Skull Shield"
};

#define MAX_ABOUT_NAME 3
char *const about_name[] = {
 "Cloak", "Cape", "Shawl"
};

#define MAX_WAIST_NAME 3
char *const waist_name[] = {
 "Belt", "Cord", "Waistband"
};

#define MAX_WRIST_NAME 3
char *const wrist_name[] = {
 "Bracer", "Wrist Guard", "Bracelet"
};

#define MAX_FACE_NAME 6
char *const face_name[] = {
 "Mask", "Face Guard", "Goggles", "Glasses", "Visor", "Monacle"
};

#define MAX_SPECIAL_NAME 4
char *const special_name[] = {
 "Sigil", "Charm", "Rune", "Emblem"
};

#define MAX_BODYART_NAME 3
char *const bodyart_name[] = {
 "Tattoo", "Drawing", "Sketch"
};

#define MAX_MEDAL_NAME 2
char *const medal_name[] = {
 "Medal", "Commendation"
};

#define MAX_FLOAT_NAME 4
char *const float_name[] = {
 "Gem", "Spirit", "Orb", "Sprite"
};

void mob_rand_drop( CHAR_DATA *mob, int level )
{
 char output[MSL], slot[MSL], best_stat[MSL], quality[MSL], aff_name[MSL];
 OBJ_DATA *obj;
 AFFECT_DATA *paf;
 float mod = 1.0;
 int value = 0, affect = 0, i = 0, num_aff = 0, seed = 0, chance = 0, bitvector = 0;
 int add_str = 0, add_dex = 0, add_int = 0, add_wis = 0, add_con = 0,
     add_mana = 0, add_hit = 0, add_move = 0, add_ac = 0, add_hr = 0,
     add_dr = 0, add_save = 0, add_best = 0, add_tot = 0;

 output[0] = '\0'; slot[0] = '\0'; best_stat[0] = '\0'; quality[0] = '\0'; aff_name[0] = '\0';
 seed = number_percent();
 chance = 5;

 if( IS_SET(mob->act,ACT_ELITE) )
  chance += 25;
 if( IS_SET(mob->act,ACT_BOSS) )
  chance += 100;

 if( number_percent() >= chance )
  return;

 if( IS_SET(mob->act,ACT_ELITE) )
 {
  mod += 0.10;
  num_aff -= 1;
 }
 if( IS_SET(mob->act,ACT_BOSS) )
 {
  mod += 0.20;
  num_aff -= 2;
 }

 obj = create_object(get_obj_index(OBJ_VNUM_PROTOPLASM),0);
 obj->weight = number_range((level * 0.02),(level * 0.04));
 SET_BIT(obj->wear_flags,ITEM_TAKE);

 if( seed <= 5 )
  obj->item_type = ITEM_CONTAINER;
 else if( seed > 5 && seed <= 40 )
  obj->item_type = ITEM_WEAPON;
 else
  obj->item_type = ITEM_ARMOR;

 if( obj->item_type == ITEM_CONTAINER )
 {
  obj->value[0] = (number_range((level * 0.10),(level * 0.20)) * 5);
  obj->value[0] *= mod;
  add_tot = obj->value[0];
  sprintf(slot,"%s",container_name[number_range(0,MAX_CONTAINER_NAME-1)]);
 }
 else if( obj->item_type == ITEM_WEAPON )
 {
  SET_BIT(obj->wear_flags,ITEM_WIELD);
  obj->value[1] = number_range((level * 0.06),(level * 0.08));
  if( obj->value[1] < 1 )
   obj->value[1] = 1;
  obj->value[1] *= mod;
  obj->value[2] = number_range((level * 0.08),(level * 0.12));
  if( obj->value[2] < 1 )
   obj->value[2] = 1;
  obj->value[2] *= mod;
  obj->value[3] = number_range(1,12);
  sprintf(slot,"%s",weapon_name[obj->value[3]]);
 }
 else
 {
  switch( number_range(1,21) )
  {
   default: extract_obj(obj); return;
   case 1:  SET_BIT(obj->wear_flags,ITEM_WEAR_FINGER);  sprintf(slot,"%s",finger_name[number_range(0,MAX_FINGER_NAME-1)]);   break;
   case 2:  SET_BIT(obj->wear_flags,ITEM_WEAR_FINGER);  sprintf(slot,"%s",finger_name[number_range(0,MAX_FINGER_NAME-1)]);   break;
   case 3:  SET_BIT(obj->wear_flags,ITEM_WEAR_NECK);    sprintf(slot,"%s",neck_name[number_range(0,MAX_NECK_NAME-1)]);       break;
   case 4:  SET_BIT(obj->wear_flags,ITEM_WEAR_NECK);    sprintf(slot,"%s",neck_name[number_range(0,MAX_NECK_NAME-1)]);       break;
   case 5:  SET_BIT(obj->wear_flags,ITEM_WEAR_BODY);    sprintf(slot,"%s",body_name[number_range(0,MAX_BODY_NAME-1)]);       break;
   case 6:  SET_BIT(obj->wear_flags,ITEM_WEAR_HEAD);    sprintf(slot,"%s",head_name[number_range(0,MAX_HEAD_NAME-1)]);       break;
   case 7:  SET_BIT(obj->wear_flags,ITEM_WEAR_LEGS);    sprintf(slot,"%s",legs_name[number_range(0,MAX_LEGS_NAME-1)]);       break;
   case 8:  SET_BIT(obj->wear_flags,ITEM_WEAR_FEET);    sprintf(slot,"%s",feet_name[number_range(0,MAX_FEET_NAME-1)]);       break;
   case 9:  SET_BIT(obj->wear_flags,ITEM_WEAR_HANDS);   sprintf(slot,"%s",hands_name[number_range(0,MAX_HANDS_NAME-1)]);     break;
   case 10: SET_BIT(obj->wear_flags,ITEM_WEAR_ARMS);    sprintf(slot,"%s",arms_name[number_range(0,MAX_ARMS_NAME-1)]);       break;
   case 11: SET_BIT(obj->wear_flags,ITEM_WEAR_SHIELD);  sprintf(slot,"%s",shield_name[number_range(0,MAX_SHIELD_NAME-1)]);   break;
   case 12: SET_BIT(obj->wear_flags,ITEM_WEAR_ABOUT);   sprintf(slot,"%s",about_name[number_range(0,MAX_ABOUT_NAME-1)]);     break;
   case 13: SET_BIT(obj->wear_flags,ITEM_WEAR_WAIST);   sprintf(slot,"%s",waist_name[number_range(0,MAX_WAIST_NAME-1)]);     break;
   case 14: SET_BIT(obj->wear_flags,ITEM_WEAR_WRIST);   sprintf(slot,"%s",wrist_name[number_range(0,MAX_WRIST_NAME-1)]);     break;
   case 15: SET_BIT(obj->wear_flags,ITEM_WEAR_WRIST);   sprintf(slot,"%s",wrist_name[number_range(0,MAX_WRIST_NAME-1)]);     break;
   case 16: SET_BIT(obj->wear_flags,ITEM_WEAR_FACE);    sprintf(slot,"%s",face_name[number_range(0,MAX_FACE_NAME-1)]);       break;
   case 17: SET_BIT(obj->wear_flags,ITEM_WEAR_SPECIAL); sprintf(slot,"%s",special_name[number_range(0,MAX_SPECIAL_NAME-1)]); break;
   case 19: SET_BIT(obj->wear_flags,ITEM_WEAR_BODYART); sprintf(slot,"%s",bodyart_name[number_range(0,MAX_BODYART_NAME-1)]); break;
   case 20: SET_BIT(obj->wear_flags,ITEM_WEAR_MEDAL);   sprintf(slot,"%s",medal_name[number_range(0,MAX_MEDAL_NAME-1)]);     break;
   case 21: SET_BIT(obj->wear_flags,ITEM_WEAR_FLOAT);   sprintf(slot,"%s",float_name[number_range(0,MAX_FLOAT_NAME-1)]);     break;
  }
  obj->value[0] = number_range((level * 0.13),(level * 0.23));
  if( obj->value[0] < 1 )
   obj->value[0] = 1;
  obj->value[0] *= mod;
 }

 if( obj->item_type != ITEM_CONTAINER )
 {
  for( i = 0; i < 6; i++ )
  {
   if( number_percent() >= (num_aff * 10) )
   {
    num_aff++;
    value = number_range((level * 0.08),(level * 0.13));
    if( value < 1 )
     value = 1;
    value *= mod;

    add_tot += value;

    switch( number_range(1,12) )
    {
     default: extract_obj(obj); return; //Number_range seems to return out of range at random; handle it.
     case 1:  add_str += value;         break;
     case 2:  add_dex += value;         break;
     case 3:  add_int += value;         break;
     case 4:  add_wis += value;         break;
     case 5:  add_con += value;         break;
     case 6:  add_mana += value;        break;
     case 7:  add_hit += value;         break;
     case 8:  add_move += value;        break;
     case 9:  add_ac += (value * -1);   break;
     case 10: add_hr += value;          break;
     case 11: add_dr += value;          break;
     case 12: add_save += (value * -1); break;
    }
   }
  }

  for( i = 0; i < 12; i++ )
  {
   affect = APPLY_NONE;
   switch( i )
   {
    case 1: 
     if( add_str > 0 )
     {
      affect = APPLY_STR;
      value = add_str;
      add_best = add_str;
      sprintf(best_stat,"#oStrength#n");
     }
     break;
    case 2:
     if( add_dex > 0 )
     {
      affect = APPLY_DEX;
      value = add_dex;
      if( add_dex > add_best )
      {
       add_best = add_dex;
       sprintf(best_stat,"#gDexterity#n");
      }
     }
     break;
    case 3:
     if( add_int > 0 )
     {
      affect = APPLY_INT;
      value = add_int;
      if( add_int > add_best )
      {
       add_best = add_int;
       sprintf(best_stat,"#cIntellect#n");
      }
     }
     break;
    case 4:
     if( add_wis > 0 )
     {
      affect = APPLY_WIS;
      value = add_wis;
      if( add_wis > add_best )
      {
       add_best = add_wis;
       sprintf(best_stat,"#lWisdom#n");
      }
     }
     break;
    case 5:
     if( add_con > 0 )
     {
      affect = APPLY_CON;
      value = add_con;
      if( add_con > add_best )
      {
       add_best = add_con;
       sprintf(best_stat,"#rConstitution#n");
      }
     }
     break;
    case 6:
     if( add_mana > 0 )
     {
      affect = APPLY_MANA;
      value = add_mana;
      if( add_mana > add_best )
      {
       add_best = add_mana;
       sprintf(best_stat,"#CMana#n");
      }
     }
     break;
    case 7:
     if( add_hit > 0 )
     {
      affect = APPLY_HIT;
      value = add_hit;
      if( add_hit > add_best )
      {
       add_best = add_hit;
       sprintf(best_stat,"#RHealth#n");
      }
     }
     break;
    case 8:
     if( add_move > 0 )
     {
      affect = APPLY_MOVE;
      value = add_move;
      if( add_move > add_best )
      {
       add_best = add_move;
       sprintf(best_stat,"#GMovement#n");
      }
     }
     break;
    case 9:
     if( add_ac < 0 )
     {
      affect = APPLY_AC;
      value = add_ac;
      if( (add_ac * -1) > add_best )
      {
       add_best = (add_ac * -1);
       sprintf(best_stat,"#yProtection#n");
      }
     }
     break;
    case 10:
     if( add_hr > 0 )
     {
      affect = APPLY_HITROLL;
      value = add_hr;
      if( add_hr > add_best )
      {
       add_best = add_hr;
       sprintf(best_stat,"#9Striking#n");
      }
     }
     break;
    case 11:
     if( add_dr > 0 )
     {
      affect = APPLY_DAMROLL;
      value = add_dr;
      if( add_dr > add_best )
      {
       add_best = add_dr;
       sprintf(best_stat,"#0Damage#n");
      }
     }
     break;
    case 12:
     if( add_save < 0 )
     {
      affect = APPLY_SAVING_SPELL;
      value = add_save;
      if( (add_save * -1) > add_best )
      {
       add_best = (add_save * -1);
       sprintf(best_stat,"#PResistance#n");
      }
     }
     break;
   }
   if( affect )
   {
    if( affect_free == NULL )
     paf = alloc_perm(sizeof(*paf));
    else
    {
     paf = affect_free;
     affect_free = affect_free->next;
    }
    if( obj->item_type == ITEM_ARMOR && number_percent() <= 10 && !obj->has_aff )
    {
     seed = number_range(1,10);
     switch( seed )
     {
      case 1:  bitvector = 5;  break; /* Invisible          */
      case 2:  bitvector = 2;  break; /* Detect Invis       */
      case 3:  bitvector = 10; break; /* Detect Hidden      */
      case 4:  bitvector = 9;  break; /* Sanctuary          */
      case 5:  bitvector = 4;  break; /* Infrared           */
      case 6:  bitvector = 7;  break; /* Protection vs Evil */
      case 7:  bitvector = 11; break; /* Sneak              */
      case 8:  bitvector = 3;  break; /* Flying             */
      case 9:  bitvector = 6;  break; /* Pass Door          */
      case 10: bitvector = 8;  break; /* Protection vs Good */
     }
     sprintf(aff_name,"%s",affect_name[seed-1]);
     obj->has_aff = TRUE;
     obj->value[3] = bitvector;
    }
    paf->type = 0;
    paf->duration = -1;
    paf->location = affect;
    paf->modifier = value;
    paf->bitvector = 0;
    paf->next = obj->affected;
    obj->affected = paf;
   }
  }
 }

 if( add_tot < 100 )
  obj->quality = QUALITY_POOR;
 else if( add_tot >= 100 && add_tot < 200 )
  obj->quality = QUALITY_COMMON;
 else if( add_tot >= 200 && add_tot < 300 )
  obj->quality = QUALITY_UNCOMMON;
 else if( add_tot >= 300 && add_tot < 400 )
  obj->quality = QUALITY_SUPERIOR;
 else if( add_tot >= 400 && add_tot < 500 )
  obj->quality = QUALITY_EPIC;
 else if( add_tot >= 500 )
  obj->quality = QUALITY_LEGENDARY;

 sprintf(quality,"%s",quality_name[obj->quality]);
 free_string(obj->name);
 free_string(obj->short_descr);
 free_string(obj->description);

 if( obj->item_type != ITEM_CONTAINER )
  sprintf(output,"%s of %s",slot,best_stat);
 else
  sprintf(output,"%s",slot);

 if( bitvector > 0 )
 {
  strcat(output," and ");
  strcat(output,aff_name);
 }

 obj->short_descr = str_dup(output);
 obj->description = str_dup(output);

 strcat(output,quality);
 obj->name = str_dup(strip_ansi(output));

 obj_to_char(obj,mob);

 return;
}