/*
 * This will generate a random item (30% weapon / 70% 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);
 *
 * 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.
 *
 * --Kline (Matt Goff)
 */

#define MAX_WEAPON_NAME 13
char *const weapon_name[] = {
 "", "slicer", "dagger", "blade", "whip", "claw", "blaster", "mace", "mace", "grepper", "biter", "dagger", "sucker"
};

#define MAX_QUALITY_NAME 6
char *const quality_name[] = {
 "#0poor#n", "#7common#n", "#Guncommon#n", "#Lexceptional#n", "#Pepic#n", "#Rlegendary#n"
};

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

#define MAX_NECK_NAME 3
char *const neck_name[] = {
 "necklace", "amulet", "choker"
};

#define MAX_BODY_NAME 2
char *const body_name[] = {
 "chest guard", "breastplate"
};

#define MAX_HEAD_NAME 3
char *const head_name[] = {
 "helmet", "skullcap", "hat"
};

#define MAX_LEGS_NAME 3
char *const legs_name[] = {
 "leggings", "leg guards", "pants"
};

#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 5
char *const face_name[] = {
 "mask", "face guard", "goggles", "glasses", "visor"
};

#define MAX_SPECIAL_NAME 3
char *const special_name[] = {
 "sigil", "charm", "rune"
};

#define MAX_BODYART_NAME 3
char *const bodyart_name[] = {
 "tattoo", "drawing", "sketch"
};

#define MAX_MEDAL_NAME 1
char *const medal_name[] = {
 "medal"
};

#define MAX_FLOAT_NAME 3
char *const float_name[] = {
 "gem", "spirit", "deity"
};

void mob_rand_drop( CHAR_DATA *mob, int level )
{
 char output[MSL], slot[MSL], best_stat[MSL], quality[MSL];
 OBJ_DATA *obj;
 AFFECT_DATA *paf;
 bool go = FALSE;
 float mod = 1.0;
 int value = 0, affect = 0, i = 0, num_aff = 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';

 if( (IS_SET(mob->act,ACT_ELITE) || IS_SET(mob->act,ACT_BOSS)) || number_percent() <= 3 )
  go = TRUE;

 if( !go )
  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.05),(level * 0.15));
 SET_BIT(obj->wear_flags,ITEM_TAKE);

 switch( number_range(1,10) )
 {
  default: extract_obj(obj); return; //Number_range seems to return out of range at random; handle it.
  case 1:
  case 2:
  case 3:  obj->item_type = ITEM_WEAPON; break;
  case 4:
  case 5:
  case 6:
  case 7:
  case 8:
  case 9:
  case 10: obj->item_type = ITEM_ARMOR;  break;
 }

 if( obj->item_type == ITEM_WEAPON )
 {
  SET_BIT(obj->wear_flags,ITEM_WIELD);
  obj->value[1] = number_range((level * 0.02),(level * 0.04));
  if( obj->value[1] < 1 )
   obj->value[1] = 1;
  obj->value[1] *= mod;
  obj->value[2] = number_range((level * 0.04),(level * 0.08));
  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; //Number_range seems to return out of range at random; handle it.
   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.10),(level * 0.20));
  if( obj->value[0] < 1 )
   obj->value[0] = 1;
  obj->value[0] *= mod;
 }

 for( i = 0; i < 6; i++ )
 {
  if( number_percent() >= (num_aff * 10) )
  {
   num_aff++;
   value = number_range((level * 0.05),(level * 0.10));
   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,"#yarmor#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,"#7striking#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;
   }
   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 )
  sprintf(quality,"%s",quality_name[0]);
 else if( add_tot >= 100 && add_tot < 200 )
  sprintf(quality,"%s",quality_name[1]);
 else if( add_tot >= 200 && add_tot < 300 )
  sprintf(quality,"%s",quality_name[2]);
 else if( add_tot >= 300 && add_tot < 400 )
  sprintf(quality,"%s",quality_name[3]);
 else if( add_tot >= 400 && add_tot < 500 )
  sprintf(quality,"%s",quality_name[4]);
 else if( add_tot >= 500 )
  sprintf(quality,"%s",quality_name[5]);

 free_string(obj->name);
 sprintf(output,"%s %s of %s",quality,slot,best_stat);
 obj->name = str_dup(strip_ansi(output));
 free_string(obj->short_descr);
 obj->short_descr = str_dup(output);
 free_string(obj->description);
 obj->description = str_dup(output);

 obj_to_char(obj,mob);

 return;
}