Atrinik Server 2.5
server/exp.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00037 uint64 new_levels[MAXLEVEL + 2] =
00038 {
00039     0,          0,          1500,       4000,       8000,
00040     16000,      32000,      64000,      125000,     250000,
00041     500000,     1100000,    2300000,    3600000,    5000000,
00042     6500000,    8100000,    9800000,    11600000,   13500000,
00043     15500000,   17600000,   19800000,   22100000,   24500000,
00044     27000000,   29600000,   32300000,   35100000,   38000000,
00045     41000000,   44100000,   47300000,   50600000,   54000000,
00046     57500000,   61100000,   64800000,   68600000,   72500000,
00047     76500000,   80600000,   84800000,   89100000,   93500000,
00048     98000000,   102600000,  107300000,  112100000,  117000000,
00049     122000000,  127100000,  132300000,  137600000,  143000000,
00050     148500000,  154100000,  159800000,  165600000,  171500000,
00051     177500000,  183600000,  189800000,  196100000,  202500000,
00052     209000000,  215600000,  222300000,  229100000,  236000000,
00053     243000000,  250100000,  257300000,  264600000,  272000000,
00054     280200000,  294800000,  310200000,  326300000,  343200000,
00055     361000000,  379700000,  399300000,  419900000,  441500000,
00056     464200000,  488100000,  513100000,  539400000,  567000000,
00057     596000000,  626400000,  658300000,  691900000,  727100000,
00058     764100000,  802900000,  843700000,  886500000,  931500000,
00059     978700000,  1028200000, 1080300000, 1134900000, 1192300000,
00060     1252500000, 1315800000, 1382200000, 1451900000, 1525100000,
00061     2100000000ULL, 4200000000ULL, 8400000000ULL, 16800000000ULL, 33600000000ULL,
00062     67200000000ULL, 134400000000ULL
00063 };
00064 
00067 _level_color level_color[201] =
00068 {
00069     {-2, -1, 0, 1, 2, 3},
00070     {-1, 0, 1, 2, 3, 4},
00071     {0, 1, 2, 3, 4, 5},
00072     {1, 2, 3, 4, 5, 6},
00073     {2, 3, 4, 5, 6, 7},
00074     {3, 4, 5, 6, 7, 8},
00075     {4, 5, 6, 7, 8, 9},
00076     {5, 6, 7, 8, 9, 10},
00077     {6, 7, 8, 9, 10, 11},
00078     {7, 8, 9, 10, 11, 12},
00079     {7, 9, 10, 11, 12, 14},
00080     {8, 9, 11, 12, 13, 15},
00081     {9, 10, 12, 13, 14, 16},
00082     {9, 11, 13, 14, 15, 17},
00083     {10, 11, 14, 15, 16, 18},
00084     {11, 12, 15, 16, 17, 19},
00085     {11, 13, 16, 17, 18, 20},
00086     {12, 14, 17, 18, 19, 21},
00087     {13, 15, 18, 19, 20, 22},
00088     {14, 16, 19, 20, 21, 23},
00089     {14, 17, 20, 21, 22, 24},
00090     {15, 17, 21, 22, 24, 26},
00091     {16, 18, 22, 23, 25, 27},
00092     {16, 19, 23, 24, 26, 28},
00093     {17, 19, 24, 25, 27, 30},
00094     {18, 20, 25, 26, 28, 31},
00095     {19, 21, 26, 27, 29, 32},
00096     {19, 22, 27, 28, 30, 33},
00097     {20, 23, 28, 29, 31, 35},
00098     {21, 24, 29, 30, 32, 36},
00099     {22, 25, 30, 31, 33, 37},
00100     {22, 25, 31, 32, 34, 38},
00101     {23, 26, 32, 33, 35, 39},
00102     {24, 27, 32, 35, 37, 41},
00103     {25, 28, 33, 36, 38, 42},
00104     {25, 28, 34, 37, 39, 43},
00105     {26, 29, 35, 38, 40, 44},
00106     {27, 30, 36, 39, 41, 45},
00107     {28, 31, 37, 40, 42, 46},
00108     {28, 32, 38, 41, 44, 48},
00109     {29, 33, 39, 42, 45, 49},
00110     {30, 34, 40, 43, 46, 50},
00111     {30, 34, 41, 44, 47, 52},
00112     {31, 35, 42, 45, 48, 53},
00113     {32, 36, 43, 46, 49, 54},
00114     {33, 37, 44, 47, 50, 55},
00115     {33, 37, 45, 48, 51, 57},
00116     {34, 38, 46, 49, 52, 58},
00117     {35, 39, 47, 50, 53, 59},
00118     {36, 40, 48, 51, 54, 60},
00119     {36, 41, 49, 52, 55, 61},
00120     {37, 42, 50, 53, 56, 62},
00121     {38, 43, 51, 54, 57, 63},
00122     {38, 43, 52, 55, 58, 65},
00123     {39, 44, 53, 56, 59, 66},
00124     {40, 45, 54, 57, 60, 67},
00125     {41, 46, 55, 58, 61, 68},
00126     {41, 47, 56, 59, 63, 70},
00127     {42, 48, 57, 60, 64, 71},
00128     {43, 49, 58, 61, 65, 72},
00129     {44, 50, 59, 62, 66, 73},
00130     {44, 50, 60, 63, 67, 75},
00131     {45, 51, 61, 64, 68, 76},
00132     {46, 52, 62, 65, 69, 77},
00133     {47, 53, 63, 66, 70, 78},
00134     {47, 53, 64, 67, 71, 79},
00135     {48, 54, 64, 69, 73, 81},
00136     {49, 55, 65, 70, 74, 82},
00137     {50, 56, 66, 71, 75, 83},
00138     {50, 56, 67, 72, 76, 84},
00139     {51, 57, 68, 73, 77, 85},
00140     {52, 58, 69, 74, 78, 86},
00141     {53, 59, 70, 75, 79, 87},
00142     {53, 60, 71, 76, 80, 89},
00143     {54, 61, 72, 77, 81, 90},
00144     {55, 62, 73, 78, 82, 91},
00145     {56, 63, 74, 79, 83, 92},
00146     {56, 63, 75, 80, 85, 94},
00147     {57, 64, 76, 81, 86, 95},
00148     {58, 65, 77, 82, 87, 96},
00149     {59, 66, 78, 83, 88, 97},
00150     {59, 67, 79, 84, 89, 99},
00151     {60, 68, 80, 85, 90, 100},
00152     {61, 69, 81, 86, 91, 101},
00153     {62, 70, 82, 87, 92, 102},
00154     {62, 70, 83, 88, 93, 103},
00155     {63, 71, 84, 89, 94, 104},
00156     {64, 72, 85, 90, 95, 105},
00157     {65, 73, 86, 91, 96, 106},
00158     {65, 73, 87, 92, 97, 108},
00159     {66, 74, 88, 93, 98, 109},
00160     {67, 75, 89, 94, 99, 110},
00161     {68, 76, 90, 95, 100, 111},
00162     {69, 77, 91, 96, 101, 112},
00163     {69, 78, 92, 97, 103, 114},
00164     {70, 79, 93, 98, 104, 115},
00165     {71, 80, 94, 99, 105, 116},
00166     {72, 81, 95, 100, 106, 117},
00167     {72, 81, 96, 101, 107, 119},
00168     {73, 82, 96, 103, 109, 120},
00169     {74, 83, 97, 104, 110, 121},
00170     {75, 84, 98, 105, 111, 122},
00171     {75, 84, 99, 106, 112, 124},
00172     {76, 85, 100, 107, 113, 125},
00173     {77, 86, 101, 108, 114, 126},
00174     {78, 87, 102, 109, 115, 127},
00175     {79, 88, 103, 110, 116, 128},
00176     {79, 89, 104, 111, 117, 129},
00177     {80, 90, 105, 112, 118, 130},
00178     {81, 91, 106, 113, 119, 131},
00179     {82, 92, 107, 114, 120, 132},
00180     {82, 92, 108, 115, 121, 134},
00181     {83, 93, 109, 116, 122, 135},
00182     {84, 94, 110, 117, 123, 136},
00183     {85, 95, 111, 118, 124, 137},
00184     {86, 96, 112, 119, 125, 138},
00185     {86, 96, 113, 120, 126, 140},
00186     {87, 97, 114, 121, 127, 141},
00187     {88, 98, 115, 122, 128, 142},
00188     {89, 99, 116, 123, 129, 143},
00189     {90, 100, 117, 124, 130, 144},
00190     {90, 101, 118, 125, 132, 146},
00191     {91, 102, 119, 126, 133, 147},
00192     {92, 103, 120, 127, 134, 148},
00193     {93, 104, 121, 128, 135, 149},
00194     {94, 105, 122, 129, 136, 150},
00195     {94, 105, 123, 130, 137, 151},
00196     {95, 106, 124, 131, 138, 152},
00197     {96, 107, 125, 132, 139, 153},
00198     {97, 108, 126, 133, 140, 154},
00199     {97, 109, 127, 134, 141, 156},
00200     {98, 110, 128, 135, 142, 157},
00201     {99, 110, 128, 137, 144, 158},
00202     {100, 111, 129, 138, 145, 159},
00203     {101, 112, 130, 139, 146, 160},
00204     {101, 113, 131, 140, 147, 162},
00205     {102, 114, 132, 141, 148, 163},
00206     {103, 115, 133, 142, 149, 164},
00207     {104, 116, 134, 143, 150, 165},
00208     {105, 117, 135, 144, 151, 166},
00209     {106, 118, 136, 145, 152, 167},
00210     {106, 118, 137, 146, 153, 169},
00211     {107, 119, 138, 147, 154, 170},
00212     {108, 120, 139, 148, 155, 171},
00213     {109, 121, 140, 149, 156, 172},
00214     {110, 122, 141, 150, 157, 173},
00215     {110, 122, 142, 151, 159, 175},
00216     {111, 123, 143, 152, 160, 176},
00217     {112, 124, 144, 153, 161, 177},
00218     {113, 125, 145, 154, 162, 178},
00219     {114, 126, 146, 155, 163, 179},
00220     {114, 127, 147, 156, 164, 180},
00221     {115, 128, 148, 157, 165, 181},
00222     {116, 129, 149, 158, 166, 182},
00223     {117, 130, 150, 159, 167, 183},
00224     {118, 131, 151, 160, 168, 184},
00225     {119, 132, 152, 161, 169, 185},
00226     {119, 132, 153, 162, 170, 187},
00227     {120, 133, 154, 163, 171, 188},
00228     {121, 134, 155, 164, 172, 189},
00229     {122, 135, 156, 165, 173, 190},
00230     {123, 136, 157, 166, 174, 191},
00231     {123, 137, 158, 167, 175, 193},
00232     {124, 138, 159, 168, 176, 194},
00233     {125, 139, 160, 169, 177, 195},
00234     {126, 139, 160, 171, 179, 196},
00235     {127, 140, 161, 172, 180, 197},
00236     {128, 141, 162, 173, 181, 198},
00237     {128, 142, 163, 174, 182, 200},
00238     {129, 143, 164, 175, 183, 201},
00239     {130, 144, 165, 176, 184, 202},
00240     {131, 145, 166, 177, 185, 203},
00241     {132, 146, 167, 178, 186, 204},
00242     {133, 147, 168, 179, 187, 205},
00243     {133, 147, 169, 180, 189, 207},
00244     {134, 148, 170, 181, 190, 208},
00245     {135, 149, 171, 182, 191, 209},
00246     {136, 150, 172, 183, 192, 210},
00247     {137, 151, 173, 184, 193, 211},
00248     {138, 152, 174, 185, 194, 212},
00249     {139, 153, 175, 186, 195, 213},
00250     {139, 153, 176, 187, 196, 214},
00251     {140, 154, 177, 188, 197, 215},
00252     {141, 155, 178, 189, 198, 216},
00253     {142, 156, 179, 190, 199, 217},
00254     {143, 157, 180, 191, 200, 218},
00255     {144, 158, 181, 192, 201, 219},
00256     {144, 159, 182, 193, 202, 221},
00257     {145, 160, 183, 194, 203, 222},
00258     {146, 161, 184, 195, 204, 223},
00259     {147, 162, 185, 196, 205, 224},
00260     {148, 163, 186, 197, 206, 225},
00261     {149, 164, 187, 198, 207, 226},
00262     {150, 165, 188, 199, 208, 227},
00263     {150, 165, 189, 200, 209, 229},
00264     {151, 166, 190, 201, 210, 230},
00265     {152, 167, 191, 202, 211, 231},
00266     {153, 168, 192, 203, 212, 232},
00267     {154, 169, 192, 205, 214, 233},
00268     {155, 170, 193, 206, 215, 234},
00269     {156, 171, 194, 207, 216, 235}
00270 };
00271 
00273 #define MAX_EXPERIENCE new_levels[MAXLEVEL]
00274 
00275 #define MAX_EXP_IN_OBJ new_levels[MAXLEVEL] / (MAX_EXP_CAT - 1)
00276 
00285 uint64 level_exp(int level, double expmul)
00286 {
00287     return (uint64) (expmul * (double) new_levels[level]);
00288 }
00289 
00298 sint64 add_exp(object *op, sint64 exp, int skill_nr, int exact)
00299 {
00300     object *exp_ob = NULL, *exp_skill = NULL;
00301 
00302     /* Sanity check */
00303     if (!op)
00304     {
00305         LOG(llevBug, "add_exp(): Called for NULL object.\n");
00306         return 0;
00307     }
00308 
00309     /* No exp gain for monsters */
00310     if (op->type != PLAYER)
00311     {
00312         return 0;
00313     }
00314 
00315     if (skill_nr == CHOSEN_SKILL_NO)
00316     {
00317         LOG(llevDebug, "TODO: add_exp(): called for %s with exp %"FMT64". CHOSEN_SKILL_NO set. TODO: select skill.\n", query_name(op, NULL), exp);
00318         return 0;
00319     }
00320 
00321     /* Now we grab the skill experience object from the player's shortcut
00322      * pointer array. */
00323     exp_skill = CONTR(op)->skill_ptr[skill_nr];
00324 
00325     /* Sanity */
00326     if (!exp_skill)
00327     {
00328         LOG(llevDebug, "add_exp(): called for %s with skill nr %d / %"FMT64" exp - object has not this skill.\n", query_name(op, NULL), skill_nr, exp);
00329         return 0;
00330     }
00331 
00332     /* If we are full in this skill, there nothing is to do. */
00333     if (exp_skill->level >= MAXLEVEL)
00334     {
00335         return 0;
00336     }
00337 
00338     /* Mark the skills for update */
00339     CONTR(op)->update_skills = 1;
00340     exp_ob = exp_skill->exp_obj;
00341 
00342     if (!exp_ob)
00343     {
00344         LOG(llevBug, "add_exp() skill: %s - no exp_ob found!!\n", query_name(exp_skill, NULL));
00345         return 0;
00346     }
00347 
00348     /* General adjustments for playbalance */
00349     if (!exact)
00350     {
00351         sint64 limit = (new_levels[exp_skill->level + 1] - new_levels[exp_skill->level]) / 4;
00352 
00353         if (exp > limit)
00354         {
00355             exp = limit;
00356         }
00357     }
00358 
00359     /* First we see what we can add to our skill */
00360     exp = adjust_exp(op, exp_skill, exp);
00361 
00362     /* Notify the player of the exp gain */
00363     new_draw_info_format(0, COLOR_WHITE, op, "You got %"FMT64" exp in skill %s.", exp, skills[skill_nr].name);
00364     CONTR(op)->stat_exp_gained += exp;
00365 
00366     /* adjust_exp() has adjusted the skill and all exp_obj and player
00367      * experience. Now let's check for level up in all categories. */
00368     player_lvl_adj(op, exp_skill);
00369     player_lvl_adj(op, exp_ob);
00370     player_lvl_adj(op, NULL);
00371 
00372     if (op->exp_obj)
00373     {
00374         op->exp_obj = NULL;
00375     }
00376 
00377     /* The real experience we have added to our skill */
00378     return exp;
00379 }
00380 
00388 void player_lvl_adj(object *who, object *op)
00389 {
00390     char buf[MAX_BUF];
00391 
00392     /* When rolling stats */
00393     if (!op)
00394     {
00395         op = who;
00396     }
00397 
00398     /* No exp gain for indirect skills */
00399     if (op->type == SKILL && !op->last_eat)
00400     {
00401         LOG(llevBug,"player_lvl_adj() called for indirect skill %s (who: %s)\n", query_name(op, NULL), who == NULL ? "<null>" : query_name(who, NULL));
00402         return;
00403     }
00404 
00405     if (op->level < MAXLEVEL && op->stats.exp >= (sint64) level_exp(op->level + 1, 1.0))
00406     {
00407         op->level++;
00408 
00409         /* Show the player some effects. */
00410         if (op->type == SKILL && who && who->type == PLAYER && who->map)
00411         {
00412             object *effect_ob;
00413 
00414             play_sound_player_only(CONTR(who), CMD_SOUND_EFFECT, "event01.ogg", 0, 0, 0, 0);
00415 
00416             if (level_up_arch)
00417             {
00418                 /* Prepare effect */
00419                 effect_ob = arch_to_object(level_up_arch);
00420                 effect_ob->map = who->map;
00421                 effect_ob->x = who->x;
00422                 effect_ob->y = who->y;
00423 
00424                 if (!insert_ob_in_map(effect_ob, effect_ob->map, NULL, INS_NO_MERGE | INS_NO_WALK_ON))
00425                 {
00426                     /* Something is wrong - remove object */
00427                     if (!QUERY_FLAG(effect_ob, FLAG_REMOVED))
00428                     {
00429                         remove_ob(effect_ob);
00430                     }
00431                 }
00432             }
00433         }
00434 
00435         if (who && who->type == PLAYER && op->type != EXPERIENCE && op->type != SKILL && who->level > 1)
00436         {
00437             if (who->level > 4)
00438             {
00439                 CONTR(who)->levhp[who->level] = (char) rndm(1, who->arch->clone.stats.maxhp);
00440             }
00441             else if (who->level > 2)
00442             {
00443                 CONTR(who)->levhp[who->level] = (char) rndm(1, who->arch->clone.stats.maxhp / 2) + (who->arch->clone.stats.maxhp / 2);
00444             }
00445             else
00446             {
00447                 CONTR(who)->levhp[who->level] = (char) who->arch->clone.stats.maxhp;
00448             }
00449         }
00450 
00451         if (op->level > 1 && op->type == EXPERIENCE)
00452         {
00453             if (who && who->type == PLAYER)
00454             {
00455                 /* Mana */
00456                 if (op->stats.Pow)
00457                 {
00458                     if (op->level > 4)
00459                     {
00460                         CONTR(who)->levsp[op->level] = (char) rndm(1, who->arch->clone.stats.maxsp);
00461                     }
00462                     else
00463                     {
00464                         CONTR(who)->levsp[op->level] = (char) who->arch->clone.stats.maxsp;
00465                     }
00466                 }
00467                 /* Grace */
00468                 else if (op->stats.Wis)
00469                 {
00470                     if (op->level > 4)
00471                     {
00472                         CONTR(who)->levgrace[op->level] = (char) rndm(1, who->arch->clone.stats.maxgrace);
00473                     }
00474                     else
00475                     {
00476                         CONTR(who)->levgrace[op->level] = (char) who->arch->clone.stats.maxgrace;
00477                     }
00478                 }
00479             }
00480 
00481             if (who)
00482             {
00483                 snprintf(buf, sizeof(buf), "You are now level %d in %s based skills.", op->level, op->name);
00484                 new_draw_info(0, COLOR_RED, who, buf);
00485             }
00486         }
00487         else if (op->level > 1 && op->type == SKILL)
00488         {
00489             if (who)
00490             {
00491                 /* If we leveled up praying or wizardry, we need to send a spell list update */
00492                 if (op->stats.sp == SK_PRAYING || op->stats.sp == SK_SPELL_CASTING)
00493                 {
00494                     send_spelllist_cmd(who, NULL, SPLIST_MODE_UPDATE);
00495                 }
00496 
00497                 snprintf(buf, sizeof(buf), "You are now level %d in the skill %s.", op->level, op->name);
00498                 new_draw_info(0, COLOR_RED, who, buf);
00499             }
00500         }
00501         else
00502         {
00503             if (who)
00504             {
00505                 snprintf(buf, sizeof(buf), "You are now level %d.", op->level);
00506                 new_draw_info(0, COLOR_RED, who, buf);
00507             }
00508         }
00509 
00510         if (who)
00511         {
00512             fix_player(who);
00513         }
00514 
00515         /* To increase more levels. */
00516         player_lvl_adj(who, op);
00517     }
00518     else if (op->level > 1 && op->stats.exp < (sint64) level_exp(op->level, 1.0))
00519     {
00520         op->level--;
00521 
00522         if (who)
00523         {
00524             fix_player(who);
00525         }
00526 
00527         if (op->type == EXPERIENCE)
00528         {
00529             if (who)
00530             {
00531                 snprintf(buf, sizeof(buf), "-You are now level %d in %s based skills.", op->level, op->name);
00532                 new_draw_info(0, COLOR_RED, who, buf);
00533             }
00534         }
00535         else if (op->type == SKILL)
00536         {
00537             if (who)
00538             {
00539                 snprintf(buf, sizeof(buf), "-You are now level %d in the skill %s.", op->level, op->name);
00540                 new_draw_info(0, COLOR_RED, who, buf);
00541             }
00542         }
00543         else
00544         {
00545             if (who)
00546             {
00547                 snprintf(buf, sizeof(buf), "-You are now level %d.", op->level);
00548                 new_draw_info(0, COLOR_RED, who, buf);
00549             }
00550         }
00551 
00552         /* To decrease more levels. */
00553         player_lvl_adj(who, op);
00554     }
00555 }
00556 
00567 sint64 adjust_exp(object *pl, object *op, sint64 exp)
00568 {
00569     object *tmp;
00570     int i, sk_nr;
00571     sint64 sk_exp, pl_exp;
00572 
00573     /* Be sure this is a skill object from a player. */
00574     if (op->type != SKILL || !pl || pl->type != PLAYER)
00575     {
00576         LOG(llevBug, "adjust_exp() - called for non player or non skill: skill: %s -> player: %s\n", query_name(op, NULL), query_name(pl, NULL));
00577         return 0;
00578     }
00579 
00580     /* Add or sub the exp and cap it. Must be >= 0 and <= MAX_EXPERIENCE */
00581     op->stats.exp += exp;
00582 
00583     if (op->stats.exp < 0)
00584     {
00585         exp -= op->stats.exp;
00586         op->stats.exp = 0;
00587     }
00588 
00589     if (op->stats.exp > (sint64) MAX_EXPERIENCE)
00590     {
00591         exp = exp - (op->stats.exp - MAX_EXPERIENCE);
00592         op->stats.exp = MAX_EXPERIENCE;
00593     }
00594 
00595     /* Now we collect the experience of all skills which are in the same
00596      * experience object category. */
00597     sk_nr = skills[op->stats.sp].category;
00598     sk_exp = 0;
00599 
00600     for (tmp = pl->inv; tmp; tmp = tmp->below)
00601     {
00602         if (tmp->type == SKILL && skills[tmp->stats.sp].category == sk_nr && !QUERY_FLAG(tmp, FLAG_STAND_STILL))
00603         {
00604             if (tmp->stats.exp > sk_exp)
00605             {
00606                 sk_exp = tmp->stats.exp;
00607             }
00608         }
00609     }
00610 
00611     /* Set the experience of the experience object to our best skill of
00612      * this group. */
00613     op->exp_obj->stats.exp = sk_exp;
00614 
00615     pl_exp = 0;
00616 
00617     for (i = 0; i < MAX_EXP_CAT - 1; i++)
00618     {
00619         if (CONTR(pl)->last_skill_ob[i]->stats.exp > pl_exp && !QUERY_FLAG(CONTR(pl)->last_skill_ob[i], FLAG_STAND_STILL))
00620         {
00621             pl_exp = CONTR(pl)->last_skill_ob[i]->stats.exp;
00622         }
00623     }
00624 
00625     /* Set our player exp to highest category experience. */
00626     pl->stats.exp = pl_exp;
00627 
00628     return exp;
00629 }
00630 
00637 void apply_death_exp_penalty(object *op)
00638 {
00639     object *tmp;
00640     float loss_p;
00641     sint64 lev_exp, loss_exp;
00642 
00643     /* Mark the skills for update */
00644     CONTR(op)->update_skills = 1;
00645 
00646     for (tmp = op->inv; tmp; tmp = tmp->below)
00647     {
00648         /* Only adjust skills with level and a positive exp value,
00649          * negative exp has special meaning. */
00650         if (tmp->type == SKILL && tmp->level && tmp->last_eat == 1)
00651         {
00652             /* Check there is experience we can drain. */
00653             lev_exp = tmp->stats.exp - new_levels[tmp->level];
00654 
00655             /* Sanity check */
00656             if (lev_exp < 0)
00657             {
00658                 LOG(llevBug, "apply_death_exp_penalty(): Skill %s (%d %"FMT64") for player %s -> less exp as level need!\n", query_name(tmp, NULL), tmp->level, tmp->stats.exp, query_name(op, NULL));
00659             }
00660 
00661             if (!lev_exp)
00662             {
00663                 continue;
00664             }
00665 
00666             if (tmp->level < 2)
00667             {
00668                 loss_exp = lev_exp - (int) ((float) lev_exp * 0.9);
00669             }
00670             else if (tmp->level < 3)
00671             {
00672                 loss_exp = lev_exp - (int) ((float) lev_exp * 0.85);
00673             }
00674             else
00675             {
00676                 loss_p = 0.927f - (((float) tmp->level / 5.0f) * 0.00337f);
00677                 loss_exp = (new_levels[tmp->level + 1] - new_levels[tmp->level]) - (int) ((float) (new_levels[tmp->level + 1] - new_levels[tmp->level]) * loss_p);
00678             }
00679 
00680             if (loss_exp < 0)
00681             {
00682                 loss_exp = 0;
00683             }
00684 
00685             if (loss_exp > lev_exp)
00686             {
00687                 loss_exp = lev_exp;
00688             }
00689 
00690             if (loss_exp > 0)
00691             {
00692                 adjust_exp(op, tmp, -loss_exp);
00693                 player_lvl_adj(op, tmp);
00694             }
00695         }
00696     }
00697 
00698     for (tmp = op->inv; tmp; tmp = tmp->below)
00699     {
00700         /* Adjust experience object levels. */
00701         if (tmp->type == EXPERIENCE && tmp->stats.exp)
00702         {
00703             player_lvl_adj(op, tmp);
00704         }
00705     }
00706 
00707     /* Adjust the player level. */
00708     player_lvl_adj(op, NULL);
00709 }
00710 
00733 float calc_level_difference(int who_lvl, int op_lvl)
00734 {
00735     int r;
00736     float v, tmp = 1.0f;
00737 
00738     /* Sanity checks */
00739     if (who_lvl < 0 || who_lvl > 200 || op_lvl < 0 || op_lvl > 200)
00740     {
00741         LOG(llevBug, "calc_level_difference(): Level out of range! (%d - %d)\n", who_lvl, op_lvl);
00742         return 0.0f;
00743     }
00744 
00745     /* Grey, no experience */
00746     if (op_lvl < level_color[who_lvl].green)
00747     {
00748         return 0.0f;
00749     }
00750 
00751     /* Yellow, blue or green */
00752     if (who_lvl > op_lvl)
00753     {
00754         if (op_lvl >= level_color[who_lvl].yellow)
00755         {
00756             r = who_lvl - level_color[who_lvl].yellow;
00757 
00758             if (r < 1)
00759             {
00760                 r = 1;
00761             }
00762 
00763             v = 0.2f / (float) r;
00764             tmp = 1.0f - (v * (float) (who_lvl - op_lvl));
00765         }
00766         else if (op_lvl >= level_color[who_lvl].blue)
00767         {
00768             r = level_color[who_lvl].yellow - level_color[who_lvl].blue;
00769 
00770             if (r < 1)
00771             {
00772                 r = 1;
00773             }
00774 
00775             v = 0.3f / (float) r;
00776             tmp = 0.4f + (v * (float) (op_lvl - level_color[who_lvl].blue + 1));
00777         }
00778         /* Green */
00779         else
00780         {
00781             r = level_color[who_lvl].blue - level_color[who_lvl].green;
00782 
00783             if (r < 1)
00784             {
00785                 r = 1;
00786             }
00787 
00788             v = 0.05f / (float) r;
00789             tmp = 0.25f + (v * (float) (op_lvl - level_color[who_lvl].green + 1));
00790         }
00791     }
00792     /* Yellow, orange, red, purple */
00793     else if (who_lvl < op_lvl)
00794     {
00795         /* Still yellow */
00796         if (op_lvl < level_color[who_lvl].orange)
00797         {
00798             r = level_color[who_lvl].orange - who_lvl - 1;
00799 
00800             if (r < 1)
00801             {
00802                 r = 1;
00803             }
00804 
00805             v = 0.1f / (float) r;
00806             tmp = 1.0f + (v * (float) (op_lvl - who_lvl));
00807 
00808         }
00809         /* Orange */
00810         else if (op_lvl < level_color[who_lvl].red)
00811         {
00812             r = level_color[who_lvl].red - who_lvl - 1;
00813 
00814             if (r < 1)
00815             {
00816                 r = 1;
00817             }
00818 
00819             v = 0.2f / (float) r;
00820             tmp = 1.2f + (v * (float) (op_lvl - who_lvl));
00821         }
00822         /* Red or purple */
00823         else
00824         {
00825             r = (op_lvl + 1) - level_color[who_lvl].red;
00826             v = 0.1f * (float) r;
00827             tmp = 1.4f + v;
00828         }
00829     }
00830 
00831     return tmp;
00832 }
00833 
00838 uint64 calculate_total_exp(object *op)
00839 {
00840     uint64 exp = 0;
00841     int i;
00842 
00843     for (i = 0; i < NROFSKILLS; i++)
00844     {
00845         if (CONTR(op)->skill_ptr[i])
00846         {
00847             exp += CONTR(op)->skill_ptr[i]->stats.exp;
00848         }
00849     }
00850 
00851     return exp;
00852 }