/*****************************************************************************
* DikuMUD (C) 1990, 1991 by: *
* Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen, *
* and Katja Nyboe. *
*---------------------------------------------------------------------------*
* MERC 2.1 (C) 1992, 1993 by: *
* Michael Chastain, Michael Quan, and Mitchell Tse. *
*---------------------------------------------------------------------------*
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider. *
* Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, *
* gorog, Grishnakh, Nivek, Tricops, and Fireblade. *
*---------------------------------------------------------------------------*
* SMAUG 1.7 FUSS by: Samson and others of the SMAUG community. *
* Their contributions are greatly appreciated. *
*---------------------------------------------------------------------------*
* LoP (C) 2006, 2007 by: the LoP team. *
*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "h/mud.h"
/* Calculate roughly how much experience a character is worth */
double get_exp_worth( CHAR_DATA *ch )
{
double wexp;
wexp = ( ch->level * ch->level * UMAX( 1, ch->level / 2 ) );
return durange( MIN_EXP_WORTH, wexp, MAX_EXP_WORTH );
}
double exp_level( CHAR_DATA *ch, int level )
{
double lvl;
lvl = durange( 1, level, MAX_LEVEL );
return ( 20 + ( lvl * lvl * lvl ) );
}
double xp_compute( CHAR_DATA *gch, CHAR_DATA *victim )
{
double xp;
if( ( victim->level - gch->level ) > 10 )
return 0;
if( ( gch->level - victim->level ) > 10 )
return 0;
xp = get_exp_worth( victim );
if( !is_npc( gch ) && is_npc( victim ) )
{
int times = times_killed( gch, victim );
if( times >= 20 )
xp = 0;
else if( times )
{
xp = ( xp * ( 20 - times ) ) / 20;
if( times > 15 )
xp /= 3;
else if( times > 10 )
xp /= 1.5;
}
}
return durange( 0, xp, exp_level( gch, gch->level ) );
}
/* Advancement stuff. */
void advance_level( CHAR_DATA *ch )
{
if( !is_npc( ch ) )
{
set_char_color( AT_WHITE, ch );
if( ( ch->level % 2 ) == 1 )
{
send_to_char( "You have gained another practice session.\r\n", ch );
ch->practice += 1;
}
if( ch->level == MAX_LEVEL )
{
playing_printf( ch, "&[immortal]%s has just achieved Avatarhood!&[white]\r\n", ch->name );
do_help( ch, "M_ADVHERO_" );
ch->exp = 0.0;
}
}
}
void gain_exp( CHAR_DATA *ch, double gain )
{
double modgain, oldexp, gained;
if( is_npc( ch ) )
return;
if( ch->level >= MAX_LEVEL )
{
ch->exp = 0.0;
return;
}
modgain = gain;
/* No one goes below current exp for the level they are */
if( ( ch->exp + modgain ) < 0 )
modgain = ch->exp;
modgain = dumin( modgain, exp_level( ch, ch->level ) );
oldexp = ch->exp;
ch->exp = dumax( 0, ch->exp + ( int )modgain );
gained = ( ch->exp - oldexp );
if( not_authed( ch ) && ch->exp >= exp_level( ch, ch->level ) )
{
send_to_char( "You can't ascend to a higher level until you are authorized.\r\n", ch );
ch->exp = ( exp_level( ch, ch->level ) - 1 );
return;
}
if( gained != 0 )
ch_printf( ch, "You %s %s experience points.\r\n", gained > 0 ? "received" : "lost",
double_punct( fabs( gained ) ) );
while( ch->level < MAX_LEVEL && ch->exp >= exp_level( ch, ( ch->level + 1 ) ) )
{
set_char_color( AT_WHITE + AT_BLINK, ch );
ch->level += 1;
ch->exp -= exp_level( ch, ch->level );
ch_printf( ch, "You have obtained level %d!\r\n", ch->level );
advance_level( ch );
}
}
/* Display your current exp, level, and surrounding level exp requirements - Thoric */
CMDF( do_level )
{
int x, lowlvl, hilvl;
char arg[MIL], *s1, *s2;
s1 = color_str( AT_SCORE, ch );
s2 = color_str( AT_SCORE2, ch );
lowlvl = UMAX( 1, ch->level - 5 );
if( argument && argument[0] != '\0' )
{
argument = one_argument( argument, arg );
lowlvl = URANGE( 1, ( atoi( arg ) - 5 ), MAX_LEVEL );
}
hilvl = URANGE( lowlvl, ( lowlvl + 10 ), MAX_LEVEL );
ch_printf( ch, "\r\n%sExperience required from level %s%d %sto %s%d%s:\r\n", s1, s2, lowlvl, s1, s2, hilvl, s1 );
ch_printf( ch, "%s.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.\r\n", s1 );
for( x = lowlvl; x <= hilvl; x++ )
{
ch_printf( ch, "%s%s%s%5d%s> %s%12s %sexp", s1, x == ch->level ? "*" : " ", s2, x, s1, s2,
double_punct( exp_level( ch, x ) ), s1 );
if( x == ch->level )
ch_printf( ch, " %s(Current: %s%12s%s)", s1, s2, double_punct( ch->exp ), s1 );
else if( x == ( ch->level + 1 ) )
ch_printf( ch, " %s(Needed: %s%12s%s)", s1, s2, double_punct( exp_level( ch, ch->level + 1 ) - ch->exp ), s1 );
send_to_char( "\r\n", ch );
}
ch_printf( ch, "%s.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.~`~.\r\n", s1 );
}