/*****************************************************************************
 *  The Chronicles Experience System by Orion Elder.                         *
 *                                                                           *
 *  Updates to this snippet can be found at the SSWRA:                       *
 *  http://www.geocities.com/knytehawk/smaug/index.html                      *
 *                                                                           *
 *  Please send all bug reports, suggestions, or ideas to:                   *
 *  orion_elder@charter.net                                                  *
 *                                                                           *
 *  NOTE: If you downloaded this snippet from the SSWRA disregard. I will    *
 *        under no circumstances support versions of this snippet gleaned    *
 *        from other sources. If you're having problems download a fresh     *
 *        copy from the SSWRA and re-install.                                *
 *                                                                           *
 * If you're having problems with your copy of this snippet, please check to *
 * ensure that no updates have been posted before seeking help.              *
 *                                                                           *
 * Copyright 2001-2009 by Orion Elder                                        *
 *****************************************************************************/

[act_wiz.c]

In the do_advance function find:

        victim->exp      = exp_level(victim, 1);

Replace that with:

	victim->exp      = 0;

Then find:

    victim->exp   = exp_level( victim, victim->level );

Replace that with:

    victim->exp   = 0;

In the do_elevate function find:

       victim->exp   = exp_level( victim, victim->level );

Replace that with:

	victim->exp   = 0;

Then find:

       victim->exp   = exp_level( victim, victim->level );

Replace that with:

	victim->exp   = 0;

In the do_immortalize function find:

    victim->exp   = exp_level( victim, victim->level );

Replace that with:

    victim->exp   = 0;

In the do_mortalize function find:

        victim->exp      = exp_level(victim, LEVEL_DEMIGOD);

Replace that with:

	victim->exp      = 0;


[fight.c]

In the damage function find:

            /*
             * Dying penalty:
             * 1/2 way back to previous level.
             */
            if ( victim->exp > exp_level(victim, victim->level) )
                gain_exp( victim, (exp_level(victim, victim->level) - victim->exp)/2 );

            /*
             * New penalty... go back to the beginning of current level.
             victim->exp = exp_level( victim, victim->level );
             */

Replace that with:

	    /*
	     * Dying penalty:
	     * Loss of half your exp! :)
	     */
	    if ( victim->exp > 0 )
		gain_exp( victim, 0-(victim->exp/2) );

	    /*
	     * New penalty... go back to the beginning of current level.
	     victim->exp = 0;
	     */

In the xp_compute function find:

    return URANGE(0, xp, exp_level(gch, gchlev+1) - exp_level(gch, gchlev) );

Replace that with:

    return URANGE(0, xp, exp_level(gch, gchlev+1) );

In the do_flee function find:

             los = ( exp_level( ch, ch->level+1 ) - exp_level( ch, ch->level ) ) * 0.02;

Replace that with:

	    los = exp_level( ch, ch->level+1 ) * 0.02;

Then find:

    los = ( exp_level( ch, ch->level+1 ) - exp_level( ch, ch->level ) ) * 0.01;

Replace that with:

    los = exp_level( ch, ch->level+1 ) * 0.01;


[handler.c]

Find the exp_level function and replace it with:

/*
 * Updated exp_level function, to solve the pointless use of big numbers, and to
 * correct the old bad maths. -Orion
 */
int exp_level( CHAR_DATA *ch, sh_int level )
{
    int exp_level;

    level = UMAX( 0, level );
    exp_level = ( get_exp_base( ch ) * ( (3 * level * level) - (9 * level) + 7 ) );

    return exp_level;
}


[mud_comm.c]

In the simple_damage function find:

            /*
             * Dying penalty:
             * 1/2 way back to previous level.
             */
            if ( victim->exp > exp_level(victim, victim->level) )
                gain_exp( victim, (exp_level(victim, victim->level) - victim->exp)/2 );

            /*
             * New penalty... go back to the beginning of current level.
             victim->exp = exp_level( victim, victim->level );
             */

Replace that with:

	    /*
	     * Dying penalty:
	     * Loss of half your exp! :)
	     */
	    if ( victim->exp > 0 )
		gain_exp( victim, 0-(victim->exp/2) );

	    /*
	     * New penalty... go back to the beginning of current level.
	     victim->exp = 0;
	     */


[skills.c]

In the do_recall function find:

            lose = (exp_level(ch, ch->level+1) - exp_level(ch, ch->level)) * 0.1;

Replace that with:

	    lose = exp_level(ch, ch->level+1) * 0.1;

Then find:

        lose = (exp_level(ch, ch->level+1) - exp_level(ch, ch->level)) * 0.2;

Replace that with:

	lose = exp_level(ch, ch->level+1) * 0.2;


[update.c]

In the gain_exp function find:

    /* Deadly exp loss floor is exp floor of level */
    if(IS_PKILL(ch)&& modgain<0){
       if( ch->exp + modgain < exp_level(ch, ch->level)){
          modgain = exp_level(ch, ch->level) - ch->exp;
          sprintf(buf,"Gravoc's Pandect protects your insight.\n\r");
       }
    }

You can simply remove it, or replace it with:

    /*
     * Experience loss floor is zero (no one can have less than zero
     * experience... it just doesn't make sense). -Orion
     */
    if ( (ch->exp + modgain) < 0 )
    {
	modgain = 0;
	sprintf( buf, "%s %s seen fit to refrain from turning you into a babbling idiot.\n\r", "The Gods", "have" );
    }

Then find:

    modgain = UMIN(modgain,
        exp_level(ch, ch->level+2) - exp_level(ch, ch->level+1));

Replace that with:

    modgain = UMIN(modgain, (exp_level(ch, ch->level+2) - 1) );

Then find:

    while ( ch->level < LEVEL_AVATAR && ch->exp >= exp_level(ch, ch->level+1))
    {
        set_char_color( AT_WHITE + AT_BLINK, ch );
        ch_printf( ch, "You have now obtained experience level %d!\n\r", ++ch->level );
        advance_level( ch );
    }

Replace that with:

    while ( ch->level < LEVEL_AVATAR && ch->exp >= exp_level(ch, ch->level+1))
    {
	set_char_color( AT_WHITE + AT_BLINK, ch );
	ch_printf( ch, "You have now obtained experience level %d!\n\r", ++ch->level );

	ch->exp = ( ch->exp - exp_level( ch , ( ch->level ) ) );
	advance_level( ch );
    }


That SHOULD do it. Compile and go!

Now, I have NOT included a loading function to convert your new player files to this experience system. There are several solutions. You can set their exp to the amount needed to level minus one, and give them a free level. You can set their exp to zero. You can use the exp_level maths from the old system and figure out how much exp they'd have under the new system. There are a number of solutions... but I leave you to make this decision on your own.

I will not tell you how to do this part of the system. I have no objection to others submitting their solutions... it just simply isn't something I have any interest in writing.

NOTE: There is a very real possibility that I've missed something. I've made as
much an effort as possible to ensure that this snippet is as complete as I could
make it. If something DOES go wrong, just e-mail me. There is an e-mail link at
the SSWRA.