/
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

remort.c			Code dealing with character ability to
				remort into other classes after attaining
				Lord/Legend status.

		******** 100% Completely Original Code ********
		*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
		******** 100% Completely Original Code ********
		        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 "interpreter.h"
#include "acmd.h"
#include "db.h"
#include "magic.h"
#include "mudlimits.h"
#include "roaolc.h"
#include "affect.h"
#include "lists.h"
#include "objsave.h"
#include "global.h"

// external vars
extern int exp_table[NUM_CLASSES][MAX_LEVELS]; 

// external functions
extern void extract_objects(obdata *obj);
extern void do_start(chdata *ch, BOOL remort);

// internal functions
ROA_MENU(remort_selection_menu);
ROA_MENU(remort_confirmation);

#define REMORT_PTS_NEEDED	100

int get_remort_points(chdata *ch)
{
  obdata *obj = ch->carrying;
  int bonus = 0;

  for ( ; obj; obj = obj->next_content)
    bonus += obj->min_level;

  return bonus;
}

// Changed to allow return of # of remorts. 08/05/98 -callahan
int num_remorts(chdata *ch)
{
  int i, j = 0;

  for (i = 0; i < NUM_CLASSES; i++)
    if (PLR2_FLAGGED(ch, (1 << i)))
      j++;

  return j;
}

ACMD(do_remort)
{
  int exp_to_imm;
  int i;

  if (IS_NPC(ch))
    return;

  if (IS_IMMORTAL(ch) && GET_LEVEL(ch) != LEV_IMPL)
  {
    send_to_char("Immortals no remort mon...not yet anyways..\n\r",ch);
    return;
  }

  exp_to_imm = exp_table[GET_CLASS(ch)-1][LEV_IMM];

  if (GET_LEVEL(ch) != LEV_IMPL)
  if (GET_LEVEL(ch) != LEV_LORD || GET_EXP(ch) < exp_to_imm-100) 
  {
    send_to_char("You lack the experience required to remort.\n\r",ch);
    return;
  }

  if (GET_LEVEL(ch) != LEV_IMPL)
  for (i = 0; i < MAX_WEAR; i++)
    if (EQ(ch, i))
    {
      send_to_char("You must place %Ball%0 of your EQ "
		   "in your inventory before you can remort.\n\r",ch);
      return;
    }

  // make sure they play by the rules... 2/12/98 -jtrhone
  if (inv_count(ch->carrying) > MAX_RENT_S)
  {
    sprintf(buf, "You may not have more than %%B%%6%d%%0 items when you remort.\n\r",
            MAX_RENT_S);
    S2C();
    return;
  }

  if (GET_LEVEL(ch) >= LEV_IMPL)
    i = 3500;
  else
  if ((i = get_remort_points(ch)) < REMORT_PTS_NEEDED)
  {
    send_to_char("You failed the remort point check.\n\r"
		 "You need more high level EQ to remort.\n\r",ch);
    return;
  }

  // must set the nogive before they go into menu... 2/12/98 -jtrhone
  SET_BIT(PRF2_FLAGS(ch), PRF2_NOGIVE);
  send_to_char("NoGive has been set.\n\r",ch);
 
  // store remort pts on character index for later use
  ch->pc_specials->index = i - REMORT_PTS_NEEDED;
 
  MENU_DEPTH(ch) = 0;
  SET_BIT(PLR_FLAGS(ch), PLR_BUILDING);
  menu_jump(ch, remort_confirmation);
}

// MAJOR remort bug dertected and fixed in stat distribution 4/17/98 -jtrhone
void apply_remort_bonus(chdata *ch, int bonus)
{
  int tmp = 0;

  if (bonus >= 1500) // apply to stats, max of 1500 applied to them
  {
    while (tmp < 1500)
    {
      switch (number(0, 5))
      {
	case 0:
	  if (ch->real_abils.str < 18)
	    ch->real_abils.str += 1;
	  else
	    ch->real_abils.str_add += 10;

	  ch->real_abils.str_add = MIN(100, ch->real_abils.str_add);
	  break;

	case 1:
	  ch->real_abils.intel += 1;
	  ch->real_abils.intel = MIN(18, ch->real_abils.intel);
	  break;

	case 2:
	  ch->real_abils.wis += 1;
	  ch->real_abils.wis = MIN(18, ch->real_abils.wis);
	  break;

	case 3:
	  ch->real_abils.dex += 1;
	  ch->real_abils.dex = MIN(18, ch->real_abils.dex);
	  break;

	case 4:
	  ch->real_abils.con += 1;
	  ch->real_abils.con = MIN(18, ch->real_abils.con);
	  break;

	default:
	  break;
      }
      tmp += 100;
    }
    bonus -= tmp;

    // make sure everything is set...
    ch->aff_abils = ch->real_abils;
  }

  while (bonus > 0)
  {
    tmp = number(1, bonus/2);
    switch (number(0, 3))
    {
      case 0:
    	GET_MAX_HIT(ch) += tmp;
    	bonus -= tmp;
	break;
      case 1:
    	GET_MAX_MANA(ch) += tmp;
    	bonus -= tmp;
	break;
      case 2:
    	GET_MAX_MOVE(ch) += tmp;
    	bonus -= tmp;
	break;
      default: break;
    }
  }
  GET_HIT(ch) = GET_MAX_HIT(ch);
  GET_MANA(ch) = GET_MAX_MANA(ch);
  GET_MOVE(ch) = GET_MAX_MOVE(ch);
}

// the actual remorting function, waxes objects, remort character
// apply any saved bonuses from EQ, send messages to world -roa
void remort_character(chdata *ch, int cls)
{
  dsdata *jt;
  int bonus = ch->pc_specials->index;	// saved here remember? :)

  // set a remort bit based on current class
  SET_BIT(PLR2_FLAGS(ch), (1 << ((int)GET_CLASS(ch)-1))); 
  GET_CLASS(ch) = cls;

  if (!IS_IMMORTAL(ch))
  {
    extract_objects(ch->carrying);
    REMOVE_BIT(PLR_FLAGS(ch), PLR_CRASH | PLR_FORCED);
  }
  send_to_char("Objects sacrificed...\n\r",ch);

  while (ch->affected)
    affect_remove(ch, ch->affected);
  affect_total(ch);
  send_to_char("Affects removed...\n\r", ch);
 
  if (!IS_IMMORTAL(ch))
  {
    do_start(ch, TRUE);
    affect_total(ch);
  }
  send_to_char("Rerolled...\n\r", ch);

  apply_remort_bonus(ch, bonus);
  send_to_char("Remort bonus applied...\n\r",ch);

  save_char(ch, NOWHERE);
  send_to_char("%B%6Remort abilities%0:\n\r",ch);
  sprintf(buf, "Str:%d/%d Int:%d Wis:%d Dex:%d Con:%d.\n\r",
          GET_STR(ch), GET_ADD(ch), GET_INT(ch), GET_WIS(ch), GET_DEX(ch), GET_CON(ch));
  S2C();

  sprintf(buf, "%s has remorted!", GET_NAME(ch));
  for (jt = descriptor_list; jt; jt = jt->next)
    if (D_CHECK(jt) && jt->character != ch &&
        PRF_FLAGGED(jt->character, PRF_MORTLOG) && SEND_OK(jt->character))
      send_to_char(buf, jt->character);

  sprintf(buf, "PLRUPD: %s remorted with %d remort pts.", GET_NAME(ch), bonus);
  mudlog(buf, BRF, MAX(LEV_IMM, GET_INVIS_LEV(ch)), TRUE);
}

// confirm that user wants to remort 
ROA_MENU(remort_confirmation)
{
  char buf[MAX_STRING_LENGTH];
  char *p;

  if (!input_str)
  {
    MENU_PROMPT(ch) = "Are you sure you want to remort (yes/NO)? ";
    return;
  }

  strcpy(buf, input_str);
  p = strtok(buf, "   \n\r");
  if (p && strncasecmp("yes", p, strlen(p)) == 0)
    menu_jump(ch, remort_selection_menu);
  else
  {
    MENU_PROMPT(ch)  = NULL;
    MENU_HANDLER(ch) = NULL;
    MENU_DEPTH(ch)   = 0;
    REMOVE_BIT(PLR_FLAGS(ch), PLR_BUILDING);
    send_to_char("Remort not confirmed.\n\r",ch);
  }
}


ROA_MENU(remort_selection_menu)
{
  char *p;
  int field, i;
  char buf[MAX_STRING_LENGTH];

  if (!input_str)
  {
    menu_title_send("Remort Selection Menu", ch);
    for (i=1; i <= NUM_CLASSES; i++)
      if (rcarray[GET_RACE(ch)].race_allow[i] && i != GET_CLASS(ch) && !PLR2_FLAGGED(ch, (1 << (i - 1))))
      {
	sprintf(buf, "%2d.) %%6%s%%0\n\r",i, clarray[i].class_name);
	S2C();
      }

    send_to_char("\n\r", ch);
    MENU_PROMPT(ch) = "Enter class number to select or 0 to abort: ";
    return;
  }

  strcpy(buf, input_str);
  p = strtok(buf, "   \n\r");
  if (p)
    field = atoi(p);
  else
    field = 0;

  if (!field)
  {
    send_to_char("Remort aborted.\n\r",ch);
    MENU_PROMPT(ch)  = NULL;
    MENU_HANDLER(ch) = NULL;
    MENU_DEPTH(ch)   = 0;
    REMOVE_BIT(PLR_FLAGS(ch), PLR_BUILDING);
    return;
  }

  if ( field < 1 || field > NUM_CLASSES || !rcarray[GET_RACE(ch)].race_allow[field])
  {
    send_to_char("Invalid class selection.\n\r", ch);
    menu_jump(ch, remort_selection_menu);
    return;
  }

  if (GET_CLASS(ch) == field || PLR2_FLAGGED(ch, (1 << (field - 1))))
  {
    send_to_char("Cannot remort into a class you have been.\n\r", ch);
    menu_jump(ch, remort_selection_menu);
    return;
  }
  
  // ok, they chose a valid one
  MENU_PROMPT(ch)  = NULL;
  MENU_HANDLER(ch) = NULL;
  MENU_DEPTH(ch)   = 0;
  REMOVE_BIT(PLR_FLAGS(ch), PLR_BUILDING);
  remort_character(ch, field);   // remort points saved on char as index
}