crodo_mud/cnf/
crodo_mud/lib/
crodo_mud/lib/house/
crodo_mud/lib/misc/
crodo_mud/lib/plralias/F-J/
crodo_mud/lib/plralias/U-Z/
crodo_mud/lib/plrobjs/
crodo_mud/lib/plrvars/A-E/
crodo_mud/lib/plrvars/F-J/
crodo_mud/lib/plrvars/K-O/
crodo_mud/lib/plrvars/P-T/
crodo_mud/lib/plrvars/U-Z/
crodo_mud/lib/text/
crodo_mud/lib/text/help/
crodo_mud/lib/world/
crodo_mud/src/
/* Proficiency list management
 * List Management Functions - Kevin Reid <kpreid@attglobal.net>
 * Everything else - Cris Jacobin (Muerte of CrodoMud)
 * Telnet://crodomud.crodo.com:4000
*/

#include "conf.h"
#include "sysdep.h"
#include "structs.h"

#include "utils.h"
#include "comm.h"
#include "db.h"
#include "interpreter.h"
#include "screen.h"
#include "constants.h"
#include "profs.h" 

/* External Functions */
char *how_good(int percent);

struct prof_data *prof_new_node(struct char_data *ch) {
  struct prof_data *new_node;

  if (ch == NULL)
   return NULL;

  new_node = malloc(sizeof(struct prof_data));

  if (new_node == NULL)
    return NULL;

  new_node->type = PROF_TYPE_NONE;
  new_node->key = 0;
  new_node->value = 0;

  new_node->next = PROFS(ch);
  PROFS(ch) = new_node;
  return new_node;
}

void prof_destroy_node(struct char_data *ch, struct prof_data *target) {
  struct prof_data *tnext;

  if (target == NULL)
    return;

  tnext = target->next;
  if (tnext) {
    *target = *tnext;
    free(tnext);
  } else if (PROFS(ch) == target) {
    free(target);
    PROFS(ch) = NULL;
  } else {
    struct prof_data *tprev;
    for (tprev = PROFS(ch); tprev != NULL; tprev = tprev->next) {
      if (tprev->next == target) {
        tprev->next = target->next;
        free(target);
      }
    }
  }
}

struct prof_data * prof_get_node(struct char_data *ch, int look_type, int look_key) {
  struct prof_data *i;
 
  for (i = PROFS(ch); i != NULL; i = i->next) {
    if (i->type != look_type) continue;
    if (i->key != look_key) continue;
    return i;
  }

  return NULL;
}

/*-------*/

PROF_VALUE_TYPE prof_get(struct char_data *ch, int look_type, int look_key) {
  struct prof_data *node;
 
  node = prof_get_node(ch, look_type, look_key);
  if (node == NULL) return -1;
  return node->value;
}
 
void prof_set(struct char_data *ch, int look_type, int look_key, PROF_VALUE_TYPE new_val) {

  struct prof_data *node;
 
  if (new_val > 100.00)
   new_val = 100.00;
 
  node = prof_get_node(ch, look_type, look_key);
  if (node == NULL) {

    /* If the node doesn't exist, and it's being set to <0, then don't bother
       allocating one */
    if (new_val < 0)
      return;

    node = prof_new_node(ch);

    if (node == NULL)
      return;
 
   node->type = look_type;
    node->key = look_key;
  }
  
  if (new_val < 0) {
    prof_destroy_node(ch, node);
  } else {
    node->value = new_val;
  }
}

void prof_destroy_all(struct char_data *ch) {
  while (PROFS(ch)) {
    prof_destroy_node(ch, PROFS(ch));
  }
}

    /* Load characters profs from disk*/
int load_profs(struct char_data *ch) {

  FILE *fl;
  char fname[MAX_STRING_LENGTH];
  struct prof_file_elem prof;

   /* Build the filename (/lib/plrprofs) */

   if (!get_filename(GET_NAME(ch), fname, PROFS_FILE)) {
    send_to_char("Filename error in load_profs!\r\n", ch);
    return (1); }

   /* Cannot open the file! */

   if (!(fl = fopen(fname, "r+b"))) { 
    if (errno != ENOENT) {      /* if it fails, NOT because of no file */
      log("SYSERR: READING PROFS FILE %s : %s", fname, strerror(errno));
      send_to_char("\r\n********************* NOTICE *********************\r\n"
                   "There was a problem loading your profs from disk.\r\n"
                   "Contact a God for assistance.\r\n", ch);
    }

    return (1);
  }

    /* Make sure we're at the beginning */

  rewind(fl);

   /* Begin adding profs */

  while (!feof(fl)) {

   fread(&prof, sizeof(struct prof_file_elem), 1, fl);
   prof_set(ch, prof.type, prof.key, prof.value); }

   /* Profs loaded and ready to go */
   return (0);
}


   /* Save character's profs to disk */
int save_profs(struct char_data *ch) {

struct prof_data *prof;
struct prof_file_elem prof_data;

FILE *fl;
char filename[MAX_INPUT_LENGTH];
int ferr = 0;

  /* No profs, no reason to save (logging into game?) */

  if (PROFS(ch) == NULL)
    return (0);

  if (IS_NPC(ch))
    return (0);

  if (!get_filename(GET_NAME(ch), filename, PROFS_FILE)) {
    send_to_char("Filename Error in save profs\r\n", ch);
    return (1); }

   if (!(fl = fopen(filename, "wb"))) {
      log("SYSERR: WRITING PROFS FILE %s : %s", filename, strerror(errno));
      send_to_char("\r\n********************* NOTICE *********************\r\n"
                   "There was a problem writing your profs to disk.\r\n"
                   "Contact a God for assistance.\r\n", ch);       }

	rewind(fl);
    	prof = PROFS(ch);

  /* Write profs to disk */

  while (prof != NULL) {

    prof_data.type  = prof->type;
    prof_data.key   = prof->key;
    prof_data.value = prof->value;

    ferr = fwrite(&prof_data, sizeof(struct prof_file_elem), 1, fl);
    
    if (ferr < 1) {
    perror("SYSERR: error writing to file in save_profs");
    return (1);   }

    prof = prof->next;
    }

    fclose(fl);
    return (0);
}

ACMD(do_profs) {

 struct prof_data *prof;
 char buffer[MAX_STRING_LENGTH];
 extern struct obj_data *obj_proto;
 int int_value;

  prof = PROFS(ch);

  if (!GET_PROF_SLOTS(ch))
    sprintf(buffer, "You have no proficiency slots remaining.\r\n");
  else
    sprintf(buffer, "You have %d proficiency slot%s remaining.\r\n\r\n",
            GET_PROF_SLOTS(ch), (GET_PROF_SLOTS(ch) == 1 ? "" : "s"));

   send_to_char(buffer, ch);
  if (prof == NULL) {
   send_to_char("You are not proficient in ANYTHING.  You suck!\r\n", ch);
   return; }

  if (prof != NULL) 
   send_to_char("You are proficient in the following weapons.\r\n", ch);

  while (prof != NULL) {
  int_value = prof->value;
  sprintf(buffer, "%s.  Proficiency: %s\r\n",
	  obj_proto[real_object(prof->key)].short_description, 
	  how_good(int_value));
   send_to_char(buffer, ch);
   prof = prof->next;
		       }
   send_to_char("\r\n", ch);
 }

float prof_adjust(struct char_data *ch) {

  float value;

    value = PROF_WEAP_ADJ;

   /* Class based modifiers */

     if (IS_WARRIOR(ch))
      value *= 2; 
     else
     if (IS_THIEF(ch))
      value *= 1.5;

   /* Add to the current prof */
    value += GET_CUR_PROF(ch)->value;

   return (value);
}

void prof_slot_gain(struct char_data *ch) {

 int class;

 if (IS_MULTI(ch))
  class = GET_SECOND_CLASS(ch);
 else
  class = GET_FIRST_CLASS(ch);

 switch (class) {

  case CLASS_WARRIOR:
    if ((GET_LEVEL(ch) == 3) || (GET_LEVEL(ch) == 6) ||
        (GET_LEVEL(ch) == 9) || (GET_LEVEL(ch) == 12) ||
        (GET_LEVEL(ch) == 15) || (GET_LEVEL(ch) == 18) ||
        (GET_LEVEL(ch) == 21) || (GET_LEVEL(ch) == 24) ||
        (GET_LEVEL(ch) == 27) || (GET_LEVEL(ch) == 30))       
    GET_PROF_SLOTS(ch)++;
  break;
  case CLASS_THIEF:
    if ((GET_LEVEL(ch) == 4) || (GET_LEVEL(ch) == 8) ||
        (GET_LEVEL(ch) == 12) || (GET_LEVEL(ch) == 16) ||
        (GET_LEVEL(ch) == 20) || (GET_LEVEL(ch) == 24) ||
        (GET_LEVEL(ch) == 28) || (GET_LEVEL(ch) == 24))
    GET_PROF_SLOTS(ch)++;
  break;
  case CLASS_NECROMANCER:  
    if ((GET_LEVEL(ch) == 4) || (GET_LEVEL(ch) == 8) || 
        (GET_LEVEL(ch) == 12) || (GET_LEVEL(ch) == 16) ||
        (GET_LEVEL(ch) == 20) || (GET_LEVEL(ch) == 24) ||
        (GET_LEVEL(ch) == 28) || (GET_LEVEL(ch) == 24))  
    GET_PROF_SLOTS(ch)++;
  break;
  case CLASS_SORCERER:  
    if ((GET_LEVEL(ch) == 6) || (GET_LEVEL(ch) == 12) || 
        (GET_LEVEL(ch) == 18) || (GET_LEVEL(ch) == 24) ||
        (GET_LEVEL(ch) == 30) || (GET_LEVEL(ch) == 24))
    GET_PROF_SLOTS(ch)++;
  break;
  }
}

int prof_apply_thac0(struct char_data *ch) {
  
 int class;
    
  if (IS_MULTI(ch))
   class = GET_SECOND_CLASS(ch);
  else
   class = GET_FIRST_CLASS(ch);
  
  if (IS_NPC(ch))
   class = CLASS_THIEF;  
        
  /* Not proficient in the current weapon */
  if ((GET_CUR_PROF(ch) == NULL) ||
      (GET_CUR_PROF(ch)->value <= 40)) {
   
        switch (class) {

        case CLASS_WARRIOR:
         return (-2);
        break;
        case CLASS_THIEF:
         return (-3);
        break;
        case CLASS_NECROMANCER:
         return (-3);
        break;
        case CLASS_SORCERER:
         return (-4);
        break;
}
	}

      /* Char is specialized in this weapon */
      if (GET_CUR_PROF(ch)->value >= 81)
       return (1);

      /* No bonus for just being proficient.
        Chars assumed to be average with their 
        weapon of choice */

	return (0);
}

int profs_delete_file(struct char_data *ch)
{
  char filename[50];
  FILE *fl; 
          
  if (!get_filename(GET_NAME(ch), filename, PROFS_FILE))
    return (0);
  if (!(fl = fopen(filename, "rb"))) {
    if (errno != ENOENT)        /* if it fails but NOT because of no file */
      log("SYSERR: deleting profs file %s (1): %s", filename, strerror(errno));
    return (0);
  }  
  fclose(fl);
  
  /* if it fails, NOT because of no file */
  if (remove(filename) < 0 && errno != ENOENT)
    log("SYSERR: deleting profs file %s (2): %s", filename, strerror(errno));
  
  return (1);
}