/
roa/
roa/lib/boards/
roa/lib/config/
roa/lib/edits/
roa/lib/help/
roa/lib/misc/
roa/lib/plrobjs/
roa/lib/quests/
roa/lib/socials/
roa/lib/www/
roa/lib/www/LEDSign/
roa/lib/www/LEDSign/fonts/
roa/lib/www/LEDSign/scripts/
roa/src/s_inc/
roa/src/sclient/
roa/src/sclient/binary/
roa/src/sclient/text/
roa/src/util/
/************************************************************************
	Realms of Aurealis 		James Rhone aka Vall of RoA

guild.c				General procs for various guildmasters
				and guild procs.  Now just flag a mob with
				the guildmaster flag.

		*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
		        All rights reserved henceforth. 

    Please note that no guarantees are associated with any code from
Realms of Aurealis.  All code which has been released to the general
public has been done so with an 'as is' pretense.  RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license.   *** Read, Learn, Understand, Improve ***
*************************************************************************/
#include "conf.h"
#include "sysdep.h"

#include "structures.h"
#include "utils.h"
#include "comm.h"
#include "handler.h"
#include "db.h"
#include "magic.h"
#include "mudlimits.h"
#include "interpreter.h"
#include "acmd.h"
#include "lists.h"
#include "affect.h"
#include "global.h"

// external functions
extern int find_skill_num(char *name);
extern int find_gskill_num(char *name);

// return a measurement string for skill/spell proficiencies
char	*how_good(int percent)
{
  static char	buf[64];

  if (percent == 0)
     strcpy(buf, " (%4unknown%0)");
  else if (percent <= 10)
     strcpy(buf, " (%1awful%0)  ");
  else if (percent <= 20)
     strcpy(buf, " (%1bad%0)    ");
  else if (percent <= 40)
     strcpy(buf, " (%1poor%0)   ");
  else if (percent <= 55)
     strcpy(buf, " (%0average%0)");
  else if (percent <= 70)
     strcpy(buf, " (%0fair%0)   ");
  else if (percent <= 80)
     strcpy(buf, " (%6good%0)   ");
  else if (percent <= 85)
     strcpy(buf, " (%Bskilled%0)");
  else
    strcpy(buf, " (%BSuperb%0) ");

  return (buf);
}

// each class has a different learning curve per prac
int get_learned_percentage(chdata *ch, int spl)
{
  int perc;

  if (IS_NPC(ch)) 
    return 0;

  perc = (GET_INT(ch) * 2) - 6;

  switch(GET_CLASS(ch))
  {
    case CLASS_WARRIOR:
      return (GET_SKILL(ch, spl) + MIN(perc, 14));
    case CLASS_THIEF:
      return (GET_SKILL(ch, spl) + MIN(perc, 16));
    case CLASS_MONK: 
      return (GET_SKILL(ch, spl) + MIN(perc, 18));

    case CLASS_RANGER:
    case CLASS_BARD:
      return (GET_SKILL(ch, spl) + MIN(perc, 20));

    // primarily spell casters
    case CLASS_CLERIC:
    case CLASS_WARLOCK:
    case CLASS_MAGE:
    case CLASS_SHAMAN:
    case CLASS_MADEPT:
    case CLASS_DRUID:
      return (GET_SKILL(ch, spl) + MAX(14, perc));

    default:
      return 0;
   }
}

// each spell/skill has a min level when it can be practiced
// major update 7/8/98 -jtrhone

// pretty major MADEPT (and similar classed) bug in this function TO BE FIXED (soon) 8/12/98 -jtrhone
int get_spell_min_level(chdata *ch, int spl)
{
  int cls = GET_CLASS(ch);
  extern int num_remorts(chdata *ch);

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

  // if their current natural class has it available, return that num
  switch (cls) {
    case CLASS_MADEPT:
      // if they madept and their skill array says they know it, then return their level
      if (ch->skills[spl].learned)
        return ((int)GET_LEVEL(ch));
    break;

    default:
      if (clarray[cls].skills[spl].minlevel < LEV_IMM)
        return clarray[cls].skills[spl].minlevel;
    break;
  }

  // otherwise, they might be a remort...
  if (num_remorts(ch))
    for (cls=0; cls < NUM_CLASSES; cls++)
      if (PLR2_FLAGGED(ch, (1 << cls))) 
       {
         switch (cls+1) {
           case CLASS_MADEPT:
             // if they remort madept and their skill array says they know it, then return their level
             if (ch->skills[spl].learned)
               return ((int)GET_LEVEL(ch));
           break;

           default:
             if (clarray[cls+1].skills[spl].minlevel < LEV_IMM)
               return clarray[cls+1].skills[spl].minlevel;
           break;
         }
       }


  return LEV_IMM;
}

/* this is how good player can learn a certain skill or spell */
// incorporated in clarray  7/8/98 -jtrhone
int get_max_percentage(chdata *ch)
{
  if (IS_NPC(ch)) 
    return 0;
  else
    return clarray[(int)GET_CLASS(ch)].max_perc;
}

// trade pracs for stats... 3/1/98 -jtrhone
ACMD(do_train)
{
  chdata *mob;
  char *argu = argument;
  sbyte *stat = NULL;
  BOOL sc = FALSE;

  if (IS_NPC(ch) || INVALID_ROOM(ch->in_room))
    return;

  skip_spaces(&argu);
  if (!*argu) 
  {
    send_to_char("Usage: train <str | int | wis | dex | con>.\n\r",ch);
    return;
  }

  /* else we have an argu, look for a guildie */
  for (mob = world[ch->in_room].people; mob; mob=mob->next_in_room)
    if (MOB2_FLAGGED(mob, MOB2_TRAINER))
      break;

  if (!mob)
  {
    send_to_char("There is nobody here to train you.\n\r",ch); 
    return;
  }

  // spellcasters use full train_pracs
  sc = (IS_NAT_WARLOCK(ch) || IS_NAT_MAGE(ch) || IS_NAT_CLERIC(ch) || IS_NAT_MADEPT(ch) || IS_NAT_DRUID(ch));

  // see if they have enough pracs...
  if ((sc && SPELLS_TO_LEARN(ch) < train_pracs) || SPELLS_TO_LEARN(ch) < (train_pracs*3)/4)
  {
    sprintf(buf, "You lack the required %d practices to train.\n\r", sc ? train_pracs : (train_pracs*3)/4);
    S2C();
    return;
  }

  if (is_abbrev(argu, "strength"))
    stat = &ch->real_abils.str;
  else
  if (is_abbrev(argu, "intelligence"))
    stat = &ch->real_abils.intel;
  else
  if (is_abbrev(argu, "wisdom"))
    stat = &ch->real_abils.wis;
  else
  if (is_abbrev(argu, "dexterity"))
    stat = &ch->real_abils.dex;
  else
  if (is_abbrev(argu, "constitution"))
    stat = &ch->real_abils.con;
  else
  {
    send_to_char("Unknown attribute.  <str | int | wis | dex | con>.\n\r",ch);
    return;
  }

  // see if they CAN train it...
  if (*stat >= 18)
  {
    send_to_char("You cannot train that stat any higher.\n\r",ch);
    return;
  }

  if (sc)
    SPELLS_TO_LEARN(ch) -= train_pracs;
  else
    SPELLS_TO_LEARN(ch) -= (train_pracs * 3) / 4;

  *stat += 1;
  affect_total(ch);

  act("You train for a while.",FALSE,ch,0,0,TO_CHAR);
  act("$n trains for a while.",FALSE,ch,0,0,TO_ROOM);
}

// mega update, new skill/dialect arrays, 6/20/98 -jtrhone
// split up dialg pracs into do_study
// even more 7/8/98 -jtrhone
ACMD(do_practice)
{
  chdata *mob;
  int i = 0;
  BOOL line;   
  int skl;
  char *argu = argument;
  static char buf[20000];

  if (IS_NPC(ch)) 
    return;

  *buf ='\0';

  skip_spaces(&argu);
  if (!*argu) 
  {
    sprintf(buf, "You have got %d practice sessions left.\n\r"
		 "You can practice the following:\n\r", SPELLS_TO_LEARN(ch));
    S2C();

    for (i = 1, line = TRUE, *buf = '\0'; i < MAX_SKILLS-1; i++)
      if (GET_LEVEL(ch) >= get_spell_min_level(ch, i) && *skill_names[i] && !SPELL_FLAGGED(i, S_NPCONLY)) 
      {
	sprintf(buf2, "%-23.23s %s    ", skill_names[i], how_good(GET_SKILL(ch, i)));
	if ((line = !line)) strcat(buf2, "\n\r");
	str_cat(buf, buf2, 20000, "do_practice");
      }

    str_cat(buf, "\n\r", 20000, "do_practice");
    page_string(ch->desc, buf, 1);
    return;
  }

  /* else we have an argu, look for a guildie */
  for (mob = world[ch->in_room].people; mob; mob=mob->next_in_room)
    if (SPC_FLAGGED(mob, SPC_GMASTER))
      break;

  if (!mob)
  {
    sprintf(buf,"You may only practice in the %s guild.\n\r", clarray[(int)GET_CLASS(ch)].class_name);
    S2C();
    return;
  }

  skl = find_skill_num(argu);

  // SPELL_ARMOR is the first, and it is # 1 (roa)
  if (skl < SPELL_ARMOR || skl >= MAX_SKILLS) 
  {
    act("$N looks at you with a confused expression.", TRUE,ch,0,mob,TO_CHAR);
    return;
  }

  if (GET_LEVEL(ch) < get_spell_min_level(ch, skl)) 
  {
    act("$N chuckles at you.", TRUE,ch,0,mob,TO_CHAR);
    return;
  }

  if (SPELLS_TO_LEARN(ch) <= 0) 
  {
    send_to_char("You are unable to practice now.\n\r", ch);
    return;
  }

  if (GET_SKILL(ch, skl) >= get_max_percentage(ch)) 
  {
    send_to_char("You are already learned in this area.\n\r", ch);
    return;
  }

  /* skill min level less than min level, updated 7/8/98 -jtrhone */
  i = get_spell_min_level(ch, skl);

  if (i < mob->npc_specials.min_train_level)
  {
    act("$N will not teach you something so basic, seek someone else.",FALSE, ch, 0, mob, TO_CHAR);
    return;
  }

  /* higher than max level */
  if (i > mob->npc_specials.max_train_level)
  {
    act("$N is unable to teach you such a skill, seek someone else.",FALSE, ch, 0, mob, TO_CHAR);
    return;
  }

  // else he will teach em...
  sprintf(buf, "$N teaches you a bit about %%6%s%%0.", skill_names[skl]);
  act(buf, FALSE, ch, 0, mob, TO_CHAR);
  act("You practice for a while...", FALSE, ch, 0, mob, TO_CHAR);
  act("$n practices for a while.",FALSE,ch,0,0,TO_ROOM);
  SPELLS_TO_LEARN(ch)--;

  SET_SKILL(ch, skl, MIN(get_max_percentage(ch), get_learned_percentage(ch, skl)));

  if (GET_SKILL(ch, skl) >= get_max_percentage(ch)) 
  {
    sprintf(buf, "You have mastered %%6%s%%0.", skill_names[skl]);
    act(buf, FALSE, ch, 0, mob, TO_CHAR);
  }
}

// new, just practice in dialect/gskill array... 6/20/98 -jtrhone
ACMD(do_study)
{
  chdata *mob;
  int i = 0;
  BOOL line;   
  int skl;
  char *argu = argument;
  static char buf[20000];

  if (IS_NPC(ch)) 
    return;

  *buf ='\0';

  skip_spaces(&argu);
  if (!*argu) 
  {
    sprintf(buf, "You have got %d practice sessions left.\n\r"
		 "You can study the following:\n\r", SPELLS_TO_LEARN(ch));
    S2C();

    strcpy(buf,"%6-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%0 "
               "%BDialects%0" 
               "%6 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%0\n\r");
    // first, show them dialects...
    for (i = 0, line = TRUE; i < MAX_GSKILLS; i++)
      if (*gskill_names[i] && GSKILL_FLAGGED(i, G_DIALECT) && ch->gskills[i].learned) 
      {
	sprintf(buf2, "%-23.23s %s    ", gskill_names[i], how_good(ch->gskills[i].perc));
	if ((line = !line)) strcat(buf2, "\n\r");
	str_cat(buf, buf2, 20000, "do_study");
      }

    strcat(buf, "\n\r");

    strcat(buf,"%6-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%0 "
               "%BMisc%0" 
               "%6 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-%0\n\r");
    // now for general skills...
    for (i = 0, line = TRUE; i < MAX_GSKILLS; i++)
      if (*gskill_names[i] && !GSKILL_FLAGGED(i, G_DIALECT) && ch->gskills[i].learned) 
      {
	sprintf(buf2, "%-23.23s %s    ", gskill_names[i], how_good(ch->gskills[i].perc));
	if ((line = !line)) strcat(buf2, "\n\r");
	str_cat(buf, buf2, 20000, "do_study");
      }

    str_cat(buf, "\n\r", 20000, "do_study");
    page_string(ch->desc, buf, 1);
    return;
  }

  /* else we have an argu, look for a guildie */
  for (mob = world[ch->in_room].people; mob; mob=mob->next_in_room)
    if (SPC_FLAGGED(mob, SPC_GMASTER))
      break;

  if (!mob)
  {
    sprintf(buf, "You may only study in the %s guild.\n\r", clarray[(int)GET_CLASS(ch)].class_name);
    S2C();
    return;
  }

  skl = find_gskill_num(argu);
  if (skl < 0 || skl >= MAX_GSKILLS) 
  {
    act("$N looks at you with a confused expression.", TRUE,ch,0,mob,TO_CHAR);
    return;
  }

  if (SPELLS_TO_LEARN(ch) <= 0) 
  {
    send_to_char("You are unable to study now.\n\r", ch);
    return;
  }

  if (ch->gskills[skl].perc >= 95) 
  {
    send_to_char("You have already mastered this area.\n\r", ch);
    return;
  }

  // else he will teach em...
  sprintf(buf, "$N teaches you a bit about %%6%s%%0.", gskill_names[skl]);
  act(buf, FALSE, ch, 0, mob, TO_CHAR);
  act("You study for a while...", FALSE, ch, 0, mob, TO_CHAR);
  act("$n studies for a while.",FALSE,ch,0,0,TO_ROOM);
  SPELLS_TO_LEARN(ch)--;

  ch->gskills[skl].perc += (GET_INT(ch) * 2) - 6;
  ch->gskills[skl].perc = MIN(95, ch->gskills[skl].perc);

  if (ch->gskills[skl].perc >= 95) 
  {
    sprintf(buf, "You have mastered %%6%s%%0.", gskill_names[skl]);
    act(buf, FALSE, ch, 0, mob, TO_CHAR);
  }
}

ACMD(do_wpractice)
{
  chdata *mob;

  if (IS_NPC(ch)) 
    return;

  if (!IS_WARLOCK(ch))
  {
    send_to_char("You know not of such magic.\n\r",ch);
    return;
  }

  for (mob = world[ch->in_room].people; mob; mob=mob->next_in_room)
    if (SPC_FLAGGED(mob, SPC_GMASTER))
      break;

  if (!mob)
  {
    send_to_char("You may only improve your casting ability in your guild.\n\r",ch);
    return;
  }

  if (SPELLS_TO_LEARN(ch) <= 0)
  {
    send_to_char("You cannot practice now.\n\r",ch);
    return;
  }

  if ((int)GET_WLEVEL(ch) >= GET_LEVEL(ch))
  {
    send_to_char("You cannot improve your casting ability above your current level!\n\r",ch);
    return;
  }

  SPELLS_TO_LEARN(ch)--;
  GET_WLEVEL(ch)++;

  if (GET_INT(ch) >= 18) 
    GET_WLEVEL(ch)++;

  GET_WLEVEL(ch) = MIN(GET_LEVEL(ch), GET_WLEVEL(ch));

  sprintf(buf, "You have improved your casting ability to level %%6%d%%0.\n\r", GET_WLEVEL(ch));
  S2C();
}