/* ******************************************************************** */
/* coded by castillo. email: castillo7@hotmail.com                      */
/* RELEASE : 8 jan 1999                                                 */
/*----------------------------------------------------------------------*/
/* (ver 1.01, 10 Jan 99) - little bug fixed that could mix up player's  */
/* order                                                                */ 
/* ******************************************************************** */
#include "conf.h" 
#include "sysdep.h" 
#include "structs.h" 
#include "utils.h" 
#include "comm.h" 
#include "interpreter.h" 
#include "handler.h" 
#include "db.h" 
#include "spells.h" 
#include "olc.h"

/* extern variables */
extern char *pc_class_types[]; 
extern char *apply_types[]; 
extern char *wear_bits[]; 
extern struct attack_hit_type attack_hit_text[]; 
 
/* extern functions */
ACMD(do_olc);
void oedit_save_internally (struct descriptor_data *d); 
int real_zone (int number); 
/* ----------------------------------------------------------------------- */

#define ARMORER_MODE   0
#define WEAPONIST_MODE 1

/* ----------------------------------------------------------------------- */
/* This filed give a list a zone number (vnum) the program will use to 
   store all armors and weapons created. 
   WARNING: the list must end with -1                                      */
/* ----------------------------------------------------------------------- */
int zones_system [] = {177, 178, 179, -1};
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/* These fields define what is allowed to choose...                        
   FALSE(0): not allowed.                                                       
   TRUE(1) : allowed.                                                           
   TRUE(2) : allowed but the rest isn't. NOTE: must be used in need, to keep 
             good text alignement. but using only 0 and 1 won't hurt.      */
/* ----------------------------------------------------------------------- */
short allow_wear [NUM_ITEM_WEARS] = 
      {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}; 
short allow_stat [NUM_APPLIES] = 
      {0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
       1, 1, 1}; 
short allow_attack [NUM_ATTACK_TYPES] = 
      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
/* check in: structs.h for the list of "APPLY_xxxx"
   check in: structs.h for the list of "ITEM_WEAR_xxxx"
   check in: fight.c for "struct attack_hit_type attack_hit_text[]" 
   it's gonna help you to identify the entries of these fields....         */
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/* TRUE(1) or FALSE(0). this field identify which applies are better to
   have under 0. right now, there's: ARMOR, and all SAVING_ set to 1. 
   That's needed to "calculate" the price for an armor or weapon...
   eg: hitroll by 1, or armor by 1... armor must be known as a negative
   stat, because it's better to have armor by (under 0)                    */
/* ----------------------------------------------------------------------- */
short neg_stat [NUM_APPLIES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1};
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
signed int stat_limits [NUM_APPLIES][2] = 
      {{0,0}, {-4,4}, {-4,4}, {-4,4}, {-4,4}, {-4,4}, {-4,4}, {0,0},
       {0,0}, {-10,10}, {-99,99}, {-99,99}, {0,100}, {0,100}, {0,100},
       {0,0}, {0,0}, {-30,30}, {-4,4}, {-4,4}, {-10,10}, {-10,10}, 
       {-10,10}, {-10,10}, {-10,10}};

/* index (0-2)... 0=HITROLL_MODIFIER, 1=NUMBER_DAMAGE, 2=SIZE_DAMAGE */
short weapon_limits  [3][2]  = {{0, 10}, {0, 10}, {0, 20}};
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
/* basic price for an armor is based on the price of the slot choosen */
short wear_price [NUM_ITEM_WEARS] = 
      {0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5};
short stat_price [NUM_APPLIES] = 
      {0, 8, 10, 10, 10, 10, 10, 0, 0, 5, 2, 2, 5, 5, 5, 0, 0, 7, 15, 15,
       2, 2, 2, 2, 2};
/* basic price for a weapon is based on his attack type */
short attack_price [NUM_ATTACK_TYPES] = 
      {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20};
/* ----------------------------------------------------------------------- */

/* ----------------------------------------------------------------------- */
char weapon_affname [3][20] = 
     {"HITROLL_MODIFIER", "NUMBER_DAMAGE",  "SIZE_DAMAGE"};
char name_mob_mode [2][20] = {"Armorer", "Weaponist"};
char name_obj_mode [2][20] = {"armor", "weapon"};
struct armory_olcs {
   char *name;
   struct olc_data *olc;
   struct armory_olcs *next;
  } *armory_list = NULL;
struct armory_olcs *weaponist_list = NULL;
struct obj_data item;
/* ********************************************************************** */

/* validate a description, name, etc.
   We don't allow ~ or $, because it's marks in database file... 
   otherwise after a crash or reboot, your mud won't boot up.
   I don't allow color either for aliases */
void val_desc (char *s, int color) 
{
 int i;
 for (i=0; i<strlen(s); i++)
   if ((s[i] == '~') || (s[i] == '$') || ((s[i] == '&') && !color))
     s[i] = ' ';
} 

void list_stat (struct char_data *ch) 
{
 int i, cpt=0;
 char buf [80] = "";
 char ind [4][10] = {"\r\n", " * ", "\r\n", "\r\n"};

 send_to_char ("There is the list of availables stats:\r\n"
               "(choose one or more with: want <name> <value>)\r\n\r\n"
               "&b&3Name          Price    Limits       "
               "Name          Price    Limits.&0\r\n", ch);      
 for (i=0; i<NUM_APPLIES; i++)
   if ((allow_stat [i] < 0) || (allow_stat [i] > 2)) /* sanity check */ 
     send_to_char ("\r\n**** ERROR: allow_stat[] is corrupted.\r\n", ch);
   else
     if (allow_stat [i] != 0) {
       sprintf (buf, "&1%-13s &m: &2%2d&rM    &6[&2%3d&6, &2%3d&6]&0%s",
                     apply_types [i], stat_price [i], stat_limits [i][0],
                     stat_limits [i][1], (i < NUM_APPLIES - 1) ?
                     ind [allow_stat [i] * 2 + (++cpt % 2) - 2] : "\r\n");
       send_to_char (buf, ch);
     } 
}

void list_wear (struct char_data *ch)
{
 int i, cpt=0;
 char buf [80] = "";
 char ind [4][10] = {"\r\n", "   *   ", "\r\n", "\r\n"};

 send_to_char ("What kind of body armor do you want?\r\n"
               "(choose a kind with: want wear <name>)\r\n\r\n"
               "&b&3Name          Price       Name          Price.&0\r\n", ch);
 for (i=0; i<NUM_ITEM_WEARS; i++)
   if ((allow_wear [i] < 0) || (allow_wear [i] > 2)) /* sanity check */ 
     send_to_char ("\r\n**** ERROR: allow_wear [] is corrupted.\r\n", ch);
   else
     if (allow_wear [i] != 0) {
       sprintf (buf, "&1%-13s &5:&2%3d&1M&0%s", wear_bits [i], 
                wear_price [i], (i < NUM_ITEM_WEARS - 1) ? 
                ind [allow_wear [i] * 2 + (++cpt % 2) - 2] : "\r\n");
       send_to_char (buf, ch);
     } 
}
 
void list_attack (struct char_data *ch)
{
 int i, cpt=0;
 char buf [80] = "";
 char ind [4][10] = {"\r\n", "   *   ", "\r\n", "\r\n"};

 send_to_char ("What kind of weapon do you want?\r\n"
               "(choose a kind with: want attack <name>)\r\n\r\n"
               "&b&3Attack name     Price       Attack name     Price.&0\r\n", ch);
 for (i=0; i<NUM_ATTACK_TYPES; i++) 
   if ((allow_attack [i] < 0) || (allow_attack [i] > 2)) /* sanity check */ 
     send_to_char ("\r\n**** ERROR: allow_attack [] is corrupted.\r\n", ch);
   else
     if (allow_attack [i] != 0) {
       sprintf (buf, "&1%-12s &5:&2%6d&1M&0%s", attack_hit_text[i].singular,
                attack_price[i], (i < NUM_ATTACK_TYPES - 1) ?
                ind [allow_attack [i] * 2 + (++cpt % 2) - 2] : "\r\n");
       send_to_char (buf, ch);
     } 
}

void list_help (struct char_data *ch, int mode) 
{
  sprintf (buf, "&1Commands are&5:&0\r\n"
                "List stat   - Show you the list of add on.\r\n"
                "%s"
                "Want        - ac <value>.\r\n"
                "            - long <desc>.  (that's the description you see\r\n"
                "                             if your %s is lying on the floor)\r\n"
                "            - name <name>.  (that's the words to handle your %s)\r\n"
                "            - short <desc>. (that's the normal description)\r\n"
                "            - stat <value>. (see: 'list stat')\r\n"
                "%s" 
                "Buy         - buy the %s you just setted up.\r\n"
                "Reset       - Will reset the %s to the default one.\r\n"
                "&1Note: &5- there is a limits of &1%d&5 stats per item.\r\n" 
                "      - You get a pay back of half the value for a negative stat.\n\r" 
                "      - There is a minimum fee per %s that is: the price of %s",

                (mode == ARMORER_MODE) ? "List wear   - Get a look to my armorer's skills.\r\n"
                                       : "List attack - Get a look to my weaponist's skills.\r\n",
                name_obj_mode [mode], name_obj_mode [mode],
                (mode == ARMORER_MODE) ? "            - wear <item_wear>.\r\n"
                                       : "            - HITROLL_MODIFIER <number>.\r\n"
                                         "            - NUMBER_DAMAGE <number>.\r\n"
                                         "            - SIZE_DAMAGE <number>.\r\n",
                name_obj_mode [mode], name_obj_mode [mode],
                MAX_OBJ_AFFECT, name_obj_mode [mode],
                (mode == ARMORER_MODE) ? "item wear.\r\n" : 
                "attack type.&b&3          - ADD TO THE BASIC PRICE:"
                "(NUMBER_DAMAGE * SIZE_DAMAGE * 2M)&0\r\n");
  send_to_char (buf, ch);
  send_to_char("&6-----------------------------------------------------------------&0\r\n",ch);
}

void do_want (struct char_data *ch, char *argument, struct armory_olcs *d,
              int mode) 
{
  int i, i2, found = -1, number;
  argument = one_argument(argument, buf);
  skip_spaces (&argument);

  number = atoi (argument);
  for (i=0; i<NUM_APPLIES; i++) 
    if (allow_stat[i] && isname(buf, apply_types[i]))
      if ((number < stat_limits[i][0]) || (number > stat_limits[i][1])) {
        sprintf (buf, "&2Your value is out of range. the limits for &5%s"
                      " &2is &6[&1%d&2, &1%d&6].&0\r\n", 
                 apply_types[i], stat_limits[i][0], stat_limits[i][1]);
        send_to_char (buf, ch);
        return;    
      } else {
          for (i2=0; i2<MAX_OBJ_AFFECT; i2++) 
            if (OLC_OBJ(d)->affected [i2].location == i) {
              found = i2;
              i2 = MAX_OBJ_AFFECT;
            } else if ( (found == -1) && 
                         ((OLC_OBJ(d)->affected[i2].location == 0) ||
                          (i2 == MAX_OBJ_AFFECT - 1)) )
                     found = i2; 
          if (number != 0) {
            OLC_OBJ(d)->affected[found].location = i;
            sprintf (buf, "&2You set &5%s &2to &5: &1%d.\r\n&0",
                    apply_types[i], number);     
          } else {
              OLC_OBJ(d)->affected[found].location = 0;
              sprintf (buf, "&2You unset &5%s.&0\r\n", apply_types[i]);
            } 
          OLC_OBJ(d)->affected[found].modifier = number;
          send_to_char (buf, ch);
          return;                      
        }   
  if (isname(buf, "name")) {
    if (OLC_OBJ(d)->name)
      free (OLC_OBJ(d)->name);
    val_desc (argument, 0);
    OLC_OBJ(d)->name = str_dup(argument);
    sprintf (buf, "&2You set &5NAME&2 to &5: &1%s&0\r\n", argument);
    send_to_char (buf, ch);
    return;
  }
  if (isname(buf, "long description")) {
    if (OLC_OBJ(d)->description)
      free (OLC_OBJ(d)->description);
    val_desc(argument, 1);
    OLC_OBJ(d)->description = str_dup(argument);
    sprintf (buf, "&5You set &2LONG DESCRIPTION&5 to &2: &1%s&0\r\n", argument);
    send_to_char (buf, ch); 
    return;
  }
  if (isname(buf, "short description")) {
    if (OLC_OBJ(d)->short_description)
      free (OLC_OBJ(d)->short_description);
    val_desc(argument, 1);
    OLC_OBJ(d)->short_description = str_dup (argument);
    sprintf (buf, "&5You set &2SHORT DESCRIPTION&5 to &2: &1%s&0\r\n", 
             argument);
    send_to_char (buf, ch);
    return;
  }
  if (mode == ARMORER_MODE) {
    if (isname(buf, "ac")) {
      if ( (number < stat_limits[APPLY_AC][0]) ||
           (number > stat_limits[APPLY_AC][1]) ) {
        sprintf (buf, "&2Your value is out of range. the limits for &5%s"
                      " &2is &6[&1%d&2, &1%d&6].&0\r\n", 
                 apply_types[APPLY_AC], stat_limits[APPLY_AC][0],
                 stat_limits[APPLY_AC][1]);
        send_to_char (buf, ch);
        return;
      }
      GET_OBJ_VAL(OLC_OBJ(d), 0) = number;
      sprintf (buf, "&2You set &5AC&2 to &5: &1%d&0\r\n", number);
      send_to_char (buf, ch);
      return;
    }
    if (isname(buf, "wear")) {
      for (i=0; i<NUM_ITEM_WEARS; i++)
        if (allow_wear [i] && isname(argument, wear_bits[i])) {
          GET_OBJ_WEAR(OLC_OBJ(d)) = i;
          sprintf (buf, "&2You set &5WEAR_ITEM&2 to &5: &1%s&0\r\n", 
                   wear_bits[i]);
          send_to_char (buf, ch);
          return;
        }
    }
  } else {          /* mode=weaponist */
      if (isname(buf, "attack")) 
        for (i=0; i<NUM_ATTACK_TYPES; i++)
           if (allow_attack[i] && isname(argument,
               attack_hit_text[i].singular)) {
             GET_OBJ_VAL(OLC_OBJ(d), 3) = i;
             sprintf (buf, "&2You set &5ATTACK TYPE&2 to &5: &1%s&0\r\n",
                      attack_hit_text[i].singular);
             send_to_char (buf, ch);
             return;
           }    
      for (i=0; i<3; i++)
        if (isname(buf, weapon_affname [i])) 
           if ((number < weapon_limits [i][0]) || 
               (number > weapon_limits [i][1])) {
             sprintf (buf, "&2Your value is out of range. the limits for "
                           "&5%s &2is &6[&1%d&2, &1%d&6].&0\r\n", 
                            weapon_affname [i], weapon_limits[i][0],
                            weapon_limits[i][1]);
             send_to_char (buf, ch);
             return;     
           } else {
               GET_OBJ_VAL(OLC_OBJ(d), i) = number;
               sprintf (buf, "&2You set &5%s &2to &5: &1%d&0\r\n",
                        weapon_affname [i], number);
               send_to_char (buf, ch);
               return;
             }         
    }
 send_to_char ("&5Sorry, &2but i don't understand what you want.&0\r\n", ch);
}

void reset_armweap (struct char_data *ch, struct armory_olcs *q, int aff,
                    int mode)
{
 clear_object(OLC_OBJ(q));  
 if (OLC_OBJ(q)->name)
   free(OLC_OBJ(q)->name);
 if (OLC_OBJ(q)->description)
   free(OLC_OBJ(q)->description);
 if (OLC_OBJ(q)->short_description)
   free(OLC_OBJ(q)->short_description); 
 OLC_OBJ(q)->name = str_dup("Undefined object");
 OLC_OBJ(q)->description = str_dup ("An unfinished object is lying here.");
 OLC_OBJ(q)->short_description = str_dup("An unfinished object");
 GET_OBJ_WEAR(OLC_OBJ(q)) = 1;
 if (mode == ARMORER_MODE) 
   GET_OBJ_TYPE(OLC_OBJ(q)) = ITEM_ARMOR;
 else 
   GET_OBJ_TYPE(OLC_OBJ(q)) = ITEM_WEAPON; 
 OLC_VAL(q) = 0;
 if (aff) {
   sprintf (buf, "&2Stat for %s has been reset.&0\r\n", name_obj_mode [mode]);
   send_to_char (buf, ch);
 }
}

long int armory_cost ( struct armory_olcs *q, int mode )
{
 long int cost;
 long int min_price;
 int i, s, ind;
 float d; 

/* add the base price coming from where to wear + ac */
 if (mode == ARMORER_MODE) {
   cost = wear_price [GET_OBJ_WEAR(OLC_OBJ(q))] * 1000000;
   if (GET_OBJ_VAL(OLC_OBJ(q), 0) < 0) 
     cost += (stat_price [APPLY_AC] / 2.0) * 
             (GET_OBJ_VAL(OLC_OBJ(q), 0) * 1000000);
   else
     cost += stat_price [APPLY_AC] * (GET_OBJ_VAL(OLC_OBJ(q), 0)) *
             1000000;
 } else
     cost = (attack_price [GET_OBJ_VAL(OLC_OBJ(q), 3)] * 1000000) +
          (GET_OBJ_VAL(OLC_OBJ(q), 1) * GET_OBJ_VAL(OLC_OBJ(q), 2) * 2000000) + 
          (GET_OBJ_VAL(OLC_OBJ(q), 0) * stat_price[APPLY_HITROLL] * 1000000);

/* add the price of each stats (modifier) */
 for (i=0; i < MAX_OBJ_AFFECT; i++) {
    ind = neg_stat [(int)OLC_OBJ(q)->affected[i].location] * 2 +
                   (OLC_OBJ(q)->affected[i].modifier < 0); 
    switch (ind) {  
        case 0 : d = 1;
                 s = 1;
                 break;
        case 1 : d = 2.0; 
                 s = 1;
                 break;
        case 2 : d = 2.0; 
                 s = -1;
                 break;
        case 3 : d = 1;
                 s = -1;
                 break;
        default : d = 1;
                  s = 1; /* just in case ;-) */
    }  
    cost += (stat_price [(int)OLC_OBJ(q)->affected[i].location] / d) *
            (s * OLC_OBJ(q)->affected[i].modifier) * 1000000;
    }

/* let's make sure the eq cost somethings. so no cheat like using
   lot of negative affects.. then you get money.. because it's cost -x, of
   course we can change the code and instead of giving -price/2 for
   negative stats. just ignore them */ 
 if (mode == ARMORER_MODE)
   min_price = wear_price [GET_OBJ_WEAR(OLC_OBJ(q))] * 1000000;
 else
   min_price = attack_price [GET_OBJ_VAL(OLC_OBJ(q), 3)] * 1000000;
 if (cost < min_price)
   cost = min_price;
 return (cost);
}

void armweap_buy (struct char_data *ch, struct armory_olcs *q, int mode)
{
 long int cost;
 struct obj_data *obj;
 int i, x = -1;

 cost = armory_cost (q, mode);
 if (GET_GOLD(ch) < cost) {
   send_to_char ("&2Sorry, you don't have enough coins!&0\r\n", ch);
   return;
 }

 OLC_NUM(q) = -1;
 while (OLC_NUM(q) == -1) {
   while ( (zones_system[++x] != -1) &&
           ((OLC_ZNUM(q) = real_zone(zones_system[x] * 100)) == -1));
   if (zones_system[x] == -1) {
     send_to_char ("Sorry, there's no zone to create armor."
                   " notify an admin.\r\n", ch);
     log ("SYSERR: There's no zone allowed to created new objs.");
     return;
   }
   for (i=0; i<100; i++)
      if (real_object (zones_system[x] * 100 + i) == -1) {
        OLC_NUM(q) = (zones_system[x] * 100 + i);
        break;
      }
 }

 (ch->desc)->olc = q->olc;
 if (mode == WEAPONIST_MODE)
   GET_OBJ_WEAR(OLC_OBJ(q)) = ITEM_WEAR_WIELD + 1;
 else
   GET_OBJ_WEAR(OLC_OBJ(q)) = (1 << GET_OBJ_WEAR(OLC_OBJ(q))) + 1;
 oedit_save_internally(ch->desc);
 sprintf (buf, "save %d", (int)(OLC_NUM(q)/100));
 do_olc (ch, buf, LVL_IMPL, SCMD_OLC_OEDIT);
 (ch->desc)->olc = NULL;
 obj = read_object (real_object(OLC_NUM(q)), REAL);
 obj_to_char (obj, ch);
 GET_GOLD(ch) -= cost;
 sprintf (buf, "&2You bought &5%s &2for &1%lu &5coins!&0\r\n", 
          OLC_OBJ(q)->short_description, cost);
 send_to_char (buf, ch); 
 sprintf (buf, "NOTIFY: %s created %s at the armorer.\n\r", GET_NAME(ch), 
               OLC_OBJ(q)->short_description);
 log (buf);
 reset_armweap (ch, q, FALSE, mode); 
}

int main_armweap (struct char_data *ch, int cmd, char *argument, int mode)
{
 int i;
 struct descriptor_data *d;
 struct armory_olcs *q = NULL, *prev = NULL; 

 if (!(d=ch->desc)) 
   return 1;

 skip_spaces(&argument);

 if (CMD_IS("want") || CMD_IS("reset") || CMD_IS("list") ||
     CMD_IS("buy")) {
   if (IS_NPC(ch)) {
     send_to_char ("Little pet, Go Away!\r\n", ch);
     return 1;
   }
   for (q = (mode == ARMORER_MODE) ? armory_list : weaponist_list; q;
        prev=q, q=q->next)
      if (isname (q->name, GET_NAME(ch))) break;
   if (q == NULL) {
     CREATE(q, struct armory_olcs, 1);
     if ((mode == ARMORER_MODE) && (armory_list == NULL))
       armory_list = q;
     else if ((mode == WEAPONIST_MODE) && (weaponist_list == NULL))
            weaponist_list = q;
          else
            prev->next=q;
     q->name = str_dup(GET_NAME(ch));
     q->next=NULL;
     CREATE(q->olc, struct olc_data, 1);
     CREATE(OLC_OBJ(q), struct obj_data, 1);
     reset_armweap(ch, q, FALSE, mode);
   }
 }
 if (CMD_IS("buy")) {
   armweap_buy (ch, q, mode);
   return 1;
 }
 if (CMD_IS("want")) {
   do_want (ch, argument, q, mode);
   return 1;
 }
 if (CMD_IS("reset")) {
   reset_armweap (ch, q, TRUE, mode);
   return 1;
 } 
 if (CMD_IS("list")) {
   sprintf (buf, "&2Welcome to the %s of &8%s&2.&0\r\n", 
            name_mob_mode [mode], pc_class_types[(int)GET_CLASS(ch)]);
   send_to_char (buf, ch);
   send_to_char("&8-----------------------------------------------------------------&0\r\n",ch);
   if (isname(argument, "stat")) {
     list_stat(ch);
     return 1;
   }
   if (mode == ARMORER_MODE)
     if (isname(argument, "wear")) {
       list_wear(ch);
       return 1;
     } else;
   else if (isname(argument, "attack")) {
          list_attack(ch);
          return 1;
        }
   if (isname(argument, "help")) {
     list_help (ch, mode);
     return 1;
   }
   send_to_char ("&1Note&5: 'list help' to get a list of help.\r\n\r\n"
                 "There is your current order&m:&n\r\n"
                 "&6-----------------------------------------------------------------&0\r\n", ch);
   sprintf (buf, "&b&3Name list&0&5          :&6 %s&0\r\n" 
                 "&b&3Short description&0&5  :&6 %s&0\r\n"
                 "&b&3Long description&0&5   :&6 %s&0\r\n", 
            OLC_OBJ(q)->name, OLC_OBJ(q)->short_description,
            OLC_OBJ(q)->description);
   send_to_char (buf, ch);
   if (mode == ARMORER_MODE) 
     sprintf (buf, "&b&3Wear&0&5               : &6%s\r\n"
                   "&b&3AC&0&5                 :&6 %d\r\n",
              wear_bits[GET_OBJ_WEAR(OLC_OBJ(q))], 
              GET_OBJ_VAL(OLC_OBJ(q), 0));
   else 
     sprintf (buf, "&b&3Attack type        &0&5: &6%s\r\n" 
                   "&b&3%-19s&0&5:&6 &6%d\r\n" 
                   "&b&3%-19s&0&5: &6%d\r\n"
                   "&b&3%-19s&0&5: &6%d\r\n",
              attack_hit_text [GET_OBJ_VAL(OLC_OBJ(q), 3)].singular,
              weapon_affname [0], GET_OBJ_VAL(OLC_OBJ(q), 0), 
              weapon_affname [1], GET_OBJ_VAL(OLC_OBJ(q), 1),
              weapon_affname [2], GET_OBJ_VAL(OLC_OBJ(q), 2));
   send_to_char (buf, ch);

   for (i=0; i<MAX_OBJ_AFFECT; i++) 
     if (OLC_OBJ(q)->affected[i].location) {
       sprintf (buf, "&0&3Modifier           &5: &6%s &5by &6%d\r\n", 
                      apply_types [(int)OLC_OBJ(q)->affected[i].location],
                      OLC_OBJ(q)->affected[i].modifier);
       send_to_char (buf, ch);
     }  
   sprintf (buf, "\r\n&2This nice %s should cost you a little &5: &1%lu"
                 " &2coins.&0\r\n", 
            name_obj_mode [mode], armory_cost (q, mode));
   send_to_char (buf, ch);
   return 1;
 }
 return 0;
}

SPECIAL(armorer)
{
 return (main_armweap (ch, cmd, argument, ARMORER_MODE));
}

SPECIAL(weaponist)
{
 return (main_armweap (ch, cmd, argument, WEAPONIST_MODE));
}
/* ******************************************************************** */
