alRom/bin/
alRom/data/class/
alRom/data/command/
alRom/data/guild/
alRom/data/help/
alRom/data/lang/
alRom/data/race/
alRom/data/religion/
alRom/data/skill/
alRom/note/
/***************************************************************************
 *  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;
}