src/hcode/btech/btechstats.c

Go to the documentation of this file.
00001 /*
00002  * Author: Markus Stenberg <fingon@iki.fi>
00003  *
00004  *  Copyright (c) 1996 Markus Stenberg
00005  *  Copyright (c) 1998-2002 Thomas Wouters
00006  *  Copyright (c) 2000-2002 Cord Awtry
00007  *  Copyright (c) 1999-2005 Kevin Stevens
00008  *       All rights reserved
00009  *
00010  */
00011 
00012 #include "config.h"
00013 #include <stdio.h>
00014 #include <math.h>
00015 #define BTECHSTATS
00016 #include "mech.h"
00017 #include "coolmenu.h"
00018 #include "mycool.h"
00019 #include "mech.events.h"
00020 #define BTECHSTATS_C
00021 #include "btmacros.h"
00022 #include "btechstats.h"
00023 #include "mux_tree.h"
00024 #include "htab.h"
00025 #include "create.h"
00026 #include "muxevent.h"
00027 #include "glue.h"
00028 #include "p.mechfile.h"
00029 #include "p.mech.utils.h"
00030 #include "p.mech.partnames.h"
00031 #include "p.mech.update.h"
00032 #include "p.bsuit.h"
00033 #include "p.map.obj.h"
00034 #include "p.mech.combat.h"
00035 #include "p.mech.combat.misc.h"
00036 #include "p.mech.pickup.h"
00037 #include "p.mech.tag.h"
00038 #include "p.functions.h"
00039 
00040 Tree skill_tree = NULL;
00041 extern dbref pilot_override;
00042 
00043 dbref cached_target_char = -1;
00044 int cached_skill;
00045 int cached_result;
00046 extern char *get_uptime_to_string(int);
00047 
00048 static int char_xp_bonus(PSTATS * s, int code);
00049 static int char_getstatvalue(PSTATS * s, char *name);
00050 static PSTATS *retrieve_stats(dbref player, int modes);
00051 static void clear_player(PSTATS * s);
00052 static void store_stats(dbref player, PSTATS * s, int modes);
00053 
00054 char *silly_get_uptime_to_string(int i)
00055 {
00056         static char buf[MBUF_SIZE];
00057         char *c;
00058 
00059         c = get_uptime_to_string(i);
00060         strcpy(buf, c);
00061         free_sbuf(c);
00062         return buf;
00063 }
00064 
00065 static int char_getskilltargetbycode_base(dbref player, PSTATS * s,
00066                                                                                   int code, int modifier, int use_xp);
00067 
00068 static int char_getskilltargetbycode_noxp(dbref player, int code,
00069                                                                                   int modifier);
00070 
00071 static int figure_xp_bonus(dbref player, PSTATS * s, int code)
00072 {
00073         int t = char_values[code].xpthreshold;
00074         int tx, bon, btar;
00075 
00076         if(t <= 0)
00077                 return 0;
00078         /* KLUDGE */
00079         s->xp[code] = s->xp[code] % XP_MAX;     /* reset exp modifier - this probably _was_ cached */
00080         btar = char_getskilltargetbycode_base(player, s, code, 0, 0);
00081         while (btar > 4) {
00082                 btar--;
00083                 t = t / 3;
00084         }
00085         while (btar < 4) {
00086                 btar++;
00087                 t = t * 3;
00088         }
00089         if(t < 1)
00090                 t = 1;
00091         tx = s->xp[code] % XP_MAX;
00092         bon = 0;
00093         while (tx > t) {
00094                 bon++;
00095                 tx -= t;
00096                 t = t * 3;
00097         }
00098         return bon;
00099 }
00100 
00101 static int figure_xp_to_next_level(dbref target, int code)
00102 {
00103         int xpthresh = char_values[code].xpthreshold;
00104         int start_skill, target_skill, counter, running_total = 1;
00105 
00106         if(xpthresh <= 0)
00107                 return -1;
00108         target_skill = char_getskilltargetbycode(target, code, 0);
00109         start_skill = char_getskilltargetbycode_noxp(target, code, 0);
00110         counter = start_skill;
00111         while (counter > 4) {
00112                 counter--;
00113                 xpthresh /= 3;
00114         }
00115         while (counter < 4) {
00116                 counter++;
00117                 xpthresh *= 3;
00118         }
00119         if(xpthresh < 1)
00120                 xpthresh = 1;
00121         while (target_skill <= start_skill) {
00122                 start_skill--;
00123                 running_total += xpthresh;
00124                 xpthresh *= 3;
00125         }
00126         return running_total;
00127 }
00128 
00129 /* Right now applies to only very few select skills */
00130 
00131 static int char_xp_bonus(PSTATS * s, int code)
00132 {
00133 #if 0
00134         int count = 1;
00135         int xp;
00136 
00137         if(t <= 0)
00138                 return 0;
00139         xp = s->xp[code];
00140         while (xp > (t * count)) {
00141                 xp -= t * count * (mudconf.btech_ic ? 1 : 4);
00142                 count++;
00143         }
00144         return count - 1;
00145 #endif
00146         return s->xp[code] / XP_MAX;
00147 }
00148 
00149 /*****************************/
00150 
00151 /*     list commands        */
00152 
00153 /*****************************/
00154 
00155 void list_charvaluestuff(dbref player, int flag)
00156 {
00157         int found = 0, ok, type;
00158         int i;
00159         char buf[80];
00160 
00161         if(flag == -1)
00162                 notify(player, "List of charvalues available:");
00163         if(flag >= 0) {
00164                 notify_printf(player, "List of %s available:",
00165                                           btech_charvaluetype_names[flag]);
00166         }
00167         buf[0] = 0;
00168         for(i = 0; i < NUM_CHARVALUES; i++) {
00169                 ok = 0;
00170                 type = char_values[i].type;
00171                 if(flag < 0)
00172                         ok = 1;
00173                 else if(type == flag)
00174                         ok = 1;
00175                 if(ok) {
00176                         sprintf(buf + strlen(buf), "%-23s ", char_values[i].name);
00177                         if(!((++found) % 3)) {
00178                                 notify(player, buf);
00179                                 strcpy(buf, " ");
00180                         }
00181                 }
00182         }
00183         if(found % 3) {
00184                 notify(player, buf);
00185         }
00186         notify(player, " ");
00187         notify_printf(player, "Total of %d things found.", found);
00188 }
00189 
00190 /*****************************/
00191 
00192 /*     get code commands    */
00193 
00194 /*****************************/
00195 
00196 HASHTAB playervaluehash, playervaluehash2;
00197 
00198 int char_getvaluecode(char *name)
00199 {
00200         int *ip;
00201         char *tmpbuf, *tmpc1, *tmpc2;
00202 
00203         tmpbuf = alloc_sbuf("getvaluecodefind");
00204         for(tmpc1 = name, tmpc2 = tmpbuf; *tmpc1 &&
00205                 ((tmpbuf - tmpc2) < (SBUF_SIZE - 1)); tmpc1++, tmpc2++)
00206                 *tmpc2 = ToLower(*tmpc1);
00207         *tmpc2 = 0;
00208         if((ip = hashfind(tmpbuf, &playervaluehash)) == NULL)
00209                 ip = hashfind(tmpbuf, &playervaluehash2);
00210         free_sbuf(tmpbuf);
00211         return ((int) ip) - 1;
00212 }
00213 
00214 /********************/
00215 
00216 /*   Roll the dice  */
00217 
00218 /********************/
00219 
00220 int char_rollsaving(void)
00221 {
00222         int r1, r2, r3;
00223         int r12, r13, r23;
00224 
00225         r1 = char_rolld6(1);
00226         r2 = char_rolld6(1);
00227         r3 = char_rolld6(1);
00228 
00229         r12 = r1 + r2;
00230         r13 = r1 + r3;
00231         r23 = r2 + r3;
00232 
00233         if(r12 > r13) {
00234                 if(r12 > r23)
00235                         return r12;
00236                 else
00237                         return r23;
00238         } else {
00239                 if(r13 > r23)
00240                         return r13;
00241                 else
00242                         return r23;
00243         }
00244 }
00245 
00246 int char_rollunskilled(void)
00247 {
00248         int r1, r2, r3;
00249         int r12, r13, r23;
00250 
00251         r1 = char_rolld6(1);
00252         r2 = char_rolld6(1);
00253         r3 = char_rolld6(1);
00254 
00255         r12 = r1 + r2;
00256         r13 = r1 + r3;
00257         r23 = r2 + r3;
00258 
00259         if(r12 < r13) {
00260                 if(r12 < r23)
00261                         return r12;
00262                 else
00263                         return r23;
00264         } else {
00265                 if(r13 < r23)
00266                         return r13;
00267                 else
00268                         return r23;
00269         }
00270 }
00271 
00272 int char_rollskilled(void)
00273 {
00274         return char_rolld6(2);
00275 }
00276 
00277 int char_rolld6(int num)
00278 {
00279         int i, total = 0;
00280 
00281         for(i = 0; i < num; i++)
00282                 total = total + (random() % 6) + 1;
00283         return (total);
00284 }
00285 
00286 /*****************************/
00287 
00288 /*     DB access commands   */
00289 
00290 /*****************************/
00291 
00292 static int char_getstatvalue(PSTATS * s, char *name)
00293 {
00294         return char_getstatvaluebycode(s, char_getvaluecode(name));
00295 }
00296 
00297 int char_getvalue(dbref player, char *name)
00298 {
00299         return char_getvaluebycode(player, char_getvaluecode(name));
00300 }
00301 
00302 static void char_setstatvalue(PSTATS * s, char *name, int value)
00303 {
00304         char_setstatvaluebycode(s, char_getvaluecode(name), value);
00305 }
00306 
00307 void char_setvalue(dbref player, char *name, int value)
00308 {
00309         char_setvaluebycode(player, char_getvaluecode(name), value);
00310 }
00311 
00312 static int char_getskilltargetbycode_base(dbref player, PSTATS * s,
00313                                                                                   int code, int modifier, int use_xp)
00314 {
00315         int val, skill;
00316 
00317         if(code == -1)
00318                 return 18;
00319         if(char_values[code].type != CHAR_SKILL)
00320                 return 18;
00321         if(use_xp && cached_target_char == player && cached_skill == code)
00322                 return cached_result + modifier;
00323         if(char_values[code].flag & CHAR_ATHLETIC)
00324                 val = char_gvalue(s, "build") + char_gvalue(s, "reflexes");
00325         else if(char_values[code].flag & CHAR_PHYSICAL)
00326                 val = char_gvalue(s, "reflexes") + char_gvalue(s, "intuition");
00327         else if(char_values[code].flag & CHAR_MENTAL)
00328                 val = char_gvalue(s, "intuition") + char_gvalue(s, "learn");
00329         else if(char_values[code].flag & CHAR_PHYSICAL)
00330                 val = char_gvalue(s, "reflexes") + char_gvalue(s, "intuition");
00331         else if(char_values[code].flag & CHAR_SOCIAL)
00332                 val = char_gvalue(s, "intuition") + char_gvalue(s, "charisma");
00333         else
00334                 return 18;
00335         if(use_xp) {
00336                 skill = char_getstatvaluebycode(s, code);
00337 
00338                 if(skill == -1)
00339                         return 18;
00340                 cached_target_char = player;
00341                 cached_skill = code;
00342                 cached_result = 18 - val - skill;
00343                 return cached_result + modifier;
00344         } else {
00345                 skill = s->values[code];
00346                 if(skill == -1)
00347                         return (18);
00348                 return 18 - val - skill;
00349         }
00350 }
00351 
00352 int char_getskilltargetbycode(dbref player, int code, int modifier)
00353 {
00354         PSTATS *s;
00355 
00356         s = retrieve_stats(player, VALUES_CO);
00357         return char_getskilltargetbycode_base(player, s, code, modifier, 1);
00358 }
00359 
00360 static int char_getskilltargetbycode_noxp(dbref player, int code,
00361                                                                                   int modifier)
00362 {
00363         PSTATS *s;
00364 
00365         s = retrieve_stats(player, VALUES_CO);
00366         return char_getskilltargetbycode_base(player, s, code, modifier, 0);
00367 }
00368 
00369 int char_getskilltarget(dbref player, char *name, int modifier)
00370 {
00371         return char_getskilltargetbycode(player, char_getvaluecode(name),
00372                                                                          modifier);
00373 }
00374 
00375 int char_getxpbycode(dbref player, int code)
00376 {
00377         PSTATS *s;
00378 
00379         if(code < 0)
00380                 return 0;
00381         s = retrieve_stats(player, VALUES_SKILLS);
00382         return s->xp[code] % XP_MAX;
00383 }
00384 
00385 int char_gainxpbycode(dbref player, int code, int amount)
00386 {
00387         PSTATS *s;
00388 
00389         if(code < 0)
00390                 return 0;
00391         s = retrieve_stats(player, VALUES_SKILLS | VALUES_ATTRS);
00392         if(!((mudstate.now > (s->last_use[code] + 30)) ||
00393                  (char_values[code].flag & SK_XP)))
00394                 return 0;
00395         s->last_use[code] = mudstate.now;
00396         s->xp[code] += amount;
00397         s->xp[code] =
00398                 s->xp[code] % XP_MAX + XP_MAX * figure_xp_bonus(player, s, code);
00399         store_stats(player, s, VALUES_SKILLS);
00400         return 1;
00401 }
00402 
00403 int char_gainxp(dbref player, char *skill, int amount)
00404 {
00405         return char_gainxpbycode(player, char_getvaluecode(skill), amount);
00406 }
00407 
00408 int char_getskillsuccess(dbref player, char *name, int modifier, int loud)
00409 {
00410         int roll, val;
00411         int code;
00412 
00413         code = char_getvaluecode(name);
00414 
00415         val = char_getskilltargetbycode(player, code, modifier);
00416 
00417         if(char_getvaluebycode(player, code) == 0)
00418                 roll = char_rollunskilled();
00419         else
00420                 roll = char_rollskilled();
00421         if(loud) {
00422                 notify_printf(player, "You make a %s skill roll!", name);
00423                 notify_printf(player, "Modified skill BTH : %d Roll : %d", val, roll);
00424         }
00425 
00426         if(roll >= val)
00427                 return (1);                             /* Success! */
00428         else
00429                 return (0);                             /* Failure */
00430 }
00431 
00432 int char_getskillmargsucc(dbref player, char *name, int modifier)
00433 {
00434         int roll, val;
00435         int code;
00436 
00437         code = char_getvaluecode(name);
00438 
00439         val = char_getskilltargetbycode(player, code, modifier);
00440 
00441         if(char_getvaluebycode(player, code) == 0)
00442                 roll = char_rollunskilled();
00443         else
00444                 roll = char_rollskilled();
00445 
00446         return (roll - val);
00447 }
00448 
00449 int char_getopposedskill(dbref first, char *skill1, dbref second,
00450                                                  char *skill2)
00451 {
00452         int per1, per2;
00453 
00454         per1 = char_getskillmargsucc(first, skill1, 0);
00455         per2 = char_getskillmargsucc(second, skill2, 0);
00456 
00457         if(per1 > per2)
00458                 return (first);
00459         else if(per2 == per1)
00460                 return (0);
00461         else
00462                 return (second);
00463 }
00464 
00465 int char_getattrsave(dbref player, char *name)
00466 {
00467         int val = char_getvalue(player, name);
00468 
00469         if(val == -1)
00470                 return (-1);
00471         else if(val > 9)
00472                 return 0;
00473         else
00474                 return (18 - 2 * val);
00475 }
00476 
00477 int char_getattrsavesucc(dbref player, char *name)
00478 {
00479         int roll, val = char_getattrsave(player, name);
00480 
00481         if(val == -1)
00482                 return (-1);
00483 
00484         roll = char_rollskilled();
00485 
00486         if(roll >= val)
00487                 return (1);
00488         else
00489                 return (0);
00490 }
00491 
00492 /************************/
00493 
00494 /*    Database Commands */
00495 
00496 /************************/
00497 
00498 void init_btechstats(void)
00499 {
00500         char *tmpbuf, *tmpc1, *tmpc2;
00501         int i, j;
00502 
00503         hashinit(&playervaluehash, 20 * HASH_FACTOR);
00504         hashinit(&playervaluehash2, 20 * HASH_FACTOR);
00505         tmpbuf = alloc_sbuf("getvaluecode");
00506         for(i = 0; i < NUM_CHARVALUES; i++) {
00507                 for(tmpc1 = char_values[i].name, tmpc2 = tmpbuf; *tmpc1;
00508                         tmpc1++, tmpc2++)
00509                         *tmpc2 = ToLower(*tmpc1);
00510                 *tmpc2 = '\0';
00511                 hashadd(tmpbuf, (int *) (i + 1), &playervaluehash);
00512                 tmpbuf[0] = '\0';
00513                 tmpc1 = tmpbuf;
00514                 for(j = 0; char_values[i].name[j]; j++) {
00515                         if(!isupper(char_values[i].name[j]))
00516                                 continue;
00517                         strncpy(tmpc1, &char_values[i].name[j], 3);
00518                         tmpc1 += 3;
00519                 }
00520                 *tmpc1 = '\0';
00521                 if(strlen(tmpbuf) <= 3) {
00522                         strncpy(tmpbuf, char_values[i].name, 5);
00523                         tmpbuf[5] = '\0';
00524                 }
00525                 char_values_short[i] = strdup(tmpbuf);
00526                 for(tmpc1 = tmpbuf; *tmpc1; tmpc1++)
00527                         *tmpc1 = ToLower(*tmpc1);
00528                 hashadd(tmpbuf, (int *) (i + 1), &playervaluehash2);
00529         }
00530         free_sbuf(tmpbuf);
00531 }
00532 
00533 static PSTATS *create_new_stats(void)
00534 {
00535         PSTATS *s;
00536 
00537         Create(s, PSTATS, 1);
00538         s->dbref = -1;
00539         clear_player(s);
00540         return s;
00541 }
00542 
00543 static void clear_player(PSTATS * s)
00544 {
00545         int i;
00546 
00547         for(i = 0; i < NUM_CHARVALUES; i++) {
00548                 s->values[i] = (char_values[i].type == CHAR_ATTRIBUTE ? 1 : 0);
00549                 s->xp[i] = 0;
00550         }
00551         char_slives(s, 1);
00552 }
00553 
00554 static void show_charstatus(dbref player, PSTATS * s, dbref thing)
00555 {
00556         char *p;
00557         int i, j;
00558         int notified;
00559         coolmenu *c = NULL;
00560 
00561         if(thing) {
00562                 addmenu(tprintf("%%cgName     %%c: %s (#%d)", Name(thing), thing));
00563                 if(*(p = silly_atr_get(thing, A_FACTION)))
00564                         addmenu(tprintf("%%cgFaction  %%c: %s", p));
00565 #if 0
00566                 if((p = get_rankname(thing)))
00567                         addmenu(tprintf("%%cgRank     %%c: %s", p));
00568                 if(*(p = silly_atr_get(thing, A_JOB)))
00569                         addmenu(tprintf("%%cgJob      %%c: %s", p));
00570 #endif
00571                 addline();
00572         }
00573         if(thing) {
00574                 addmenu(tprintf("%%cgBruise   %%c: %d of %d", char_gbruise(s),
00575                                                 char_gmaxbruise(s)));
00576                 addmenu(tprintf("%%cgLethal   %%c: %d of %d", char_glethal(s),
00577                                                 char_gmaxlethal(s)));
00578         }
00579         addmenu(tprintf("%%cgLives    %%c: %d", char_glives(s)));
00580         addempty();
00581         addmenu("%cgAttributes");
00582         addmenu("Characteristics");
00583         addline();
00584 
00585         addmenu(tprintf("  %-8s%1d (%d+)", "BLD", char_gvalue(s, "build"),
00586                                         18 - (char_gvalue(s, "build") * 2)));
00587         addmenu(tprintf("  %-15s%2d+", "Athletic", 18 - (char_gvalue(s,
00588                                                                                                                                  "build") +
00589                                                                                                          char_gvalue(s,
00590                                                                                                                                  "reflexes"))));
00591 
00592         addmenu(tprintf("  %-8s%1d (%d+)", "REF", char_gvalue(s, "reflexes"),
00593                                         18 - (char_gvalue(s, "reflexes") * 2)));
00594         addmenu(tprintf("  %-15s%2d+", "Physical", 18 - (char_gvalue(s,
00595                                                                                                                                  "reflexes") +
00596                                                                                                          char_gvalue(s,
00597                                                                                                                                  "intuition"))));
00598 
00599         addmenu(tprintf("  %-8s%1d (%d+)                              ", "INT",
00600                                         char_gvalue(s, "intuition"), 18 - (char_gvalue(s,
00601                                                                                                                                    "intuition")
00602                                                                                                            * 2)));
00603         addmenu(tprintf
00604                         ("  %-15s%2d+", "Mental",
00605                          18 - (char_gvalue(s, "learn") + char_gvalue(s, "intuition"))));
00606 
00607         addmenu(tprintf("  %-8s%1d (%d+)                              ", "LRN",
00608                                         char_gvalue(s, "learn"),
00609                                         18 - (char_gvalue(s, "learn") * 2)));
00610         addmenu(tprintf
00611                         ("  %-15s%2d+", "Social",
00612                          18 - (char_gvalue(s, "charisma") +
00613                                    char_gvalue(s, "intuition"))));
00614 
00615         addmenu(tprintf("  %-8s%1d (%d+)", "CHA", char_gvalue(s, "charisma"),
00616                                         18 - (char_gvalue(s, "charisma") * 2)));
00617         addempty();
00618         notified = 0;
00619         for(i = 0; i < NUM_CHARVALUES; i++) {
00620                 if(char_values[i].type != CHAR_ADVANTAGE)
00621                         continue;
00622                 if(!(j = s->values[i]))
00623                         continue;
00624                 notified = 1;
00625         }
00626         if(notified) {
00627                 addmenu("%cgAdvantages");
00628                 addline();
00629                 for(i = 0; i < NUM_CHARVALUES; i++) {
00630                         if(char_values[i].type != CHAR_ADVANTAGE)
00631                                 continue;
00632                         if(!(j = s->values[i]))
00633                                 continue;
00634                         switch (char_values[i].flag) {
00635                         case CHAR_ADV_BOOL:
00636                                 addmenu(tprintf("  %s", char_values[i].name));
00637                                 break;
00638                         case CHAR_ADV_VALUE:
00639                                 addmenu(tprintf("  %s: %d", char_values[i].name, j));
00640                                 break;
00641                         case CHAR_ADV_EXCEPT:
00642                                 if(j & CHAR_BLD)
00643                                         addmenu("  Exceptional Attribute: Build");
00644                                 if(j & CHAR_REF)
00645                                         addmenu("  Exceptional Attribute: Reflexes");
00646                                 if(j & CHAR_INT)
00647                                         addmenu("  Exceptional Attribute: Intuition");
00648                                 if(j & CHAR_LRN)
00649                                         addmenu("  Exceptional Attribute: Learn");
00650                                 if(j & CHAR_CHA)
00651                                         addmenu("  Exceptional Attribute: Charisma");
00652                         }
00653                         addempty();
00654                 }
00655         }
00656         addmenu("%cgSkills");
00657         addline();
00658 
00659         notified = 0;
00660         for(i = 0; i < NUM_CHARVALUES; i++) {
00661                 if(!s->values[i])
00662                         continue;
00663                 if(char_values[i].type != CHAR_SKILL)
00664                         continue;
00665                 addmenu(tprintf("  %-25.25s : %d (%d+)", char_values[i].name,
00666                                                 s->values[i], char_getskilltargetbycode(thing, i,
00667                                                                                                                                 0)));
00668                 notified = 1;
00669         }
00670         if(!notified)
00671                 addmenu("  None");
00672 
00673 /*   addempty(); */
00674         ShowCoolMenu(player, c);
00675         KillCoolMenu(c);
00676 }
00677 
00678 /************************/
00679 
00680 /*      MUSE COMMANDS   */
00681 
00682 /************************/
00683 
00684 void do_charstatus(dbref player, dbref cause, int key, char *arg1)
00685 {
00686         dbref thing;
00687         int dir = 0;
00688 
00689         PSTATS *s;
00690 
00691         if(WizR(player))
00692                 dir++;
00693 
00694         if(arg1 && *arg1) {
00695                 thing = char_lookupplayer(player, player, 0, arg1);
00696 
00697                 DOCHECK(thing == NOTHING, "I don't know who that is");
00698 
00699                 if(thing != player && !(WizR(player))) {
00700                         notify(player,
00701                                    "You do not have the authority to check that players stats");
00702                         return;
00703                 }
00704         } else
00705                 thing = player;
00706 
00707         s = retrieve_stats(thing, VALUES_ALL);
00708         show_charstatus(player, s, thing);
00709 }
00710 
00711 void do_charclear(dbref player, dbref cause, int key, char *arg1)
00712 {
00713         dbref thing;
00714 
00715         DOCHECK(!WizR(player),
00716                         "Sorry, only those with the real power may clear players stats");
00717         DOCHECK(!arg1 || !*arg1, "Who do you want to clear the stats from?");
00718         thing = char_lookupplayer(player, player, 0, arg1);
00719         DOCHECK(thing == NOTHING, "I don't know who that is");
00720         silly_atr_set(thing, A_ATTRS, "");
00721         silly_atr_set(thing, A_SKILLS, "");
00722         silly_atr_set(thing, A_ADVS, "");
00723         silly_atr_set(thing, A_HEALTH, "");
00724         notify_printf(player, "Player #%d stats cleared", thing);
00725 }
00726 
00727 #if 0
00728 /* Why, what the fuck? */
00729 dbref char_lookupplayer(dbref player, dbref cause, int key, char *arg1)
00730 {
00731         dbref which;
00732 
00733         if(!arg1 || !*arg1)
00734                 return NOTHING;
00735 
00736         if(!string_compare(arg1, "me") && (Typeof(player) == TYPE_PLAYER))
00737                 return player;
00738         if(arg1[0] == '#') {
00739                 if(sscanf(arg1, "#%d", &which) == 1)
00740                         if(which >= 0 && isPlayer(which))
00741                                 return which;
00742                 return NOTHING;
00743         }
00744         return lookup_player(NOTHING, arg1, 0);
00745 }
00746 #endif
00747 
00748 dbref char_lookupplayer(dbref player, dbref cause, int key, char *arg1)
00749 {
00750         return lookup_player(player, arg1, 0);
00751 }
00752 
00753 static int loc_mod(int loc)
00754 {
00755         switch (loc) {
00756         case HEAD:
00757                 return 15;
00758         case CTORSO:
00759                 return 50;
00760         case LTORSO:
00761         case RTORSO:
00762                 return 35;
00763         case LARM:
00764         case RARM:
00765                 return 30;
00766         case LLEG:
00767         case RLEG:
00768                 return 35;
00769         }
00770         return 0;
00771 }
00772 
00773 void initialize_pc(dbref player, MECH * mech)
00774 {
00775         PSTATS *s;
00776         int bruise, lethal, playerBLD;
00777         int dam, tot;
00778         char *c;
00779         int cnt;
00780         char buf1[MBUF_SIZE];
00781         char buf2[MBUF_SIZE];
00782         char buf3[MBUF_SIZE];
00783         char buf4[2];
00784         int ammo1;
00785         int ammo2;
00786         int i, id, brand;
00787         int pc_loc_to_mech_loc[] = { HEAD, CTORSO, RARM, RLEG };
00788 
00789         if(!(MechType(mech) == CLASS_MW &&
00790                  !(MechCritStatus(mech) & PC_INITIALIZED)))
00791                 return;
00792         buf4[1] = 0;
00793         s = retrieve_stats(player, VALUES_HEALTH | VALUES_ATTRS | VALUES_SKILLS);
00794         playerBLD = char_gvalue(s, "build");
00795         MechCritStatus(mech) |= PC_INITIALIZED;
00796         bruise = char_gbruise(s);
00797         lethal = char_glethal(s);
00798         tot = playerBLD * 20;
00799         dam = bruise + lethal;
00800         MechMaxSpeed(mech) =
00801                 (playerBLD + char_gvalue(s, "reflexes") + char_gvalue(s,
00802                                                                                                                           "running")) *
00803                 MP1 / 9.0;
00804 #define PC_LOCS 4
00805         for(i = 0; i < NUM_SECTIONS; i++) {
00806                 SetSectArmor(mech, i, 0);
00807                 SetSectOArmor(mech, i, 0);
00808                 SetSectInt(mech, i, (loc_mod(i) * (tot - dam)) / 100 + 1);
00809                 SetSectOInt(mech, i, (loc_mod(i) * (tot - dam)) / 100 + 1);
00810         }
00811         c = silly_atr_get(player, A_PCEQUIP);
00812         cnt = sscanf(c, "%s %s %s %d %d", buf1, buf2, buf3, &ammo1, &ammo2);
00813 
00814         switch (cnt) {
00815         case 5:
00816         case 4:
00817         case 3:
00818                 if(strcmp(buf3, "-")) {
00819                         if(!find_matching_vlong_part(buf3, NULL, &id, &brand)) {
00820                                 SendError(tprintf("Invalid PC weapon #1 for %s(#%d): %s",
00821                                                                   Name(player), player, buf3));
00822                                 return;
00823                         }
00824                         if(IsWeapon(id)) {
00825                                 SetPartType(mech, LARM, 0, id);
00826                                 SetPartData(mech, LARM, 0, 0);
00827                                 SetPartFireMode(mech, LARM, 0, 0);
00828                                 SetPartAmmoMode(mech, LARM, 0, 0);
00829                                 if((i = MechWeapons[Weapon2I(id)].ammoperton)) {
00830                                         SetPartType(mech, LARM, 1, I2Ammo(Weapon2I(id)));
00831                                         SetPartData(mech, LARM, 1, cnt >= 5 ? ammo2 : i);
00832                                         SetPartFireMode(mech, LARM, 1, 0);
00833                                         SetPartAmmoMode(mech, LARM, 1, 0);
00834                                 }
00835                         }
00836                 }
00837         case 2:
00838                 if(strcmp(buf2, "-")) {
00839                         if(!find_matching_vlong_part(buf2, NULL, &id, &brand)) {
00840                                 SendError(tprintf("Invalid PC weapon #1 for %s(#%d): %s",
00841                                                                   Name(player), player, buf2));
00842                                 return;
00843                         }
00844                         if(IsWeapon(id)) {
00845                                 SetPartType(mech, RARM, 0, id);
00846                                 SetPartData(mech, RARM, 0, 0);
00847                                 SetPartFireMode(mech, RARM, 0, 0);
00848                                 SetPartAmmoMode(mech, RARM, 0, 0);
00849                                 if((i = MechWeapons[Weapon2I(id)].ammoperton)) {
00850                                         SetPartType(mech, RARM, 1, I2Ammo(Weapon2I(id)));
00851                                         SetPartData(mech, RARM, 1, cnt >= 4 ? ammo1 : i);
00852                                         SetPartFireMode(mech, RARM, 1, 0);
00853                                         SetPartAmmoMode(mech, RARM, 1, 0);
00854                                 }
00855                         }
00856                 }
00857         case 1:
00858                 if(strlen(buf1) != PC_LOCS) {
00859                         SendError(tprintf("Invalid armor string for %s(#%d): %s",
00860                                                           Name(player), player, buf1));
00861                         return;
00862                 }
00863                 for(i = 0; buf1[i]; i++)
00864                         if(!isdigit(buf1[i])) {
00865                                 SendError(tprintf
00866                                                   ("Invalid armor char for %s(#%d) in %s (pos %d,%c)",
00867                                                    Name(player), player, buf1, i + 1, buf1[i]));
00868                                 return;
00869                         }
00870                 for(i = 0; buf1[i]; i++) {
00871                         buf4[0] = buf1[i];
00872                         SetSectArmor(mech, pc_loc_to_mech_loc[i], atoi(buf4));
00873                 }
00874         }
00875 }
00876 
00877 void fix_pilotdamage(MECH * mech, dbref player)
00878 {
00879         PSTATS *s;
00880         int bruise, lethal, playerBLD;
00881 
00882         s = retrieve_stats(player, VALUES_HEALTH | VALUES_ATTRS);
00883         bruise = char_gbruise(s);
00884         lethal = char_glethal(s);
00885         playerBLD = char_gvalue(s, "build") * 2;
00886         if(playerBLD < 1 || playerBLD > 100)
00887                 playerBLD = 10;
00888 
00889         MechPilotStatus(mech) = (bruise + lethal) / playerBLD;
00890 }
00891 
00892 int PilotStatusRollNeeded[] = { 0, 3, 5, 7, 10, 11 };
00893 
00894 #define CHDAM(val,ret) if (playerhits >= ((val))) return ret * mod;
00895 
00896 int mw_ic_bth(MECH * mech)
00897 {
00898         int playerBLD;
00899         int bruise, playerhits;
00900         PSTATS *s;
00901         int mod = 1;
00902 
00903         s = retrieve_stats(MechPilot(mech),
00904                                            VALUES_ATTRS | VALUES_ADVS | VALUES_HEALTH);
00905         playerBLD = char_gvalue(s, "build");
00906         bruise = char_gbruise(s);
00907         playerhits = 10 * playerBLD - bruise;
00908         if(char_gvalue(s, "toughness") == 1)
00909                 mod = -1;
00910         if(playerhits >= (8 * playerBLD))
00911                 return 3 * mod;
00912         else if(playerhits >= (6 * playerBLD))
00913                 return 5 * mod;
00914         else if(playerhits >= (4 * playerBLD))
00915                 return 7 * mod;
00916         else if(playerhits >= (2 * playerBLD))
00917                 return 9 * mod;
00918         else if(playerhits >= -1)
00919                 return 11 * mod;
00920         return 0;
00921 }
00922 
00923 int handlemwconc(MECH * mech, int initial)
00924 {
00925         int m, roll;
00926 
00927         if(In_Character(mech->mynum) && MechPilot(mech) > 0)
00928                 m = mw_ic_bth(mech);
00929         else {
00930                 if(initial)
00931                         if(MechPilotStatus(mech) > 5) {
00932                                 mech_notify(mech, MECHPILOT,
00933                                                         "You are killed from personal injuries!!");
00934                                 MechPilot(mech) = -1;
00935                                 Destroy(mech);
00936                                 ChannelEmitKill(mech, mech);
00937                                 MechSpeed(mech) = 0.;
00938                                 MechDesiredSpeed(mech) = 0.;
00939                                 return 0;
00940                         }
00941                 m = PilotStatusRollNeeded[BOUNDED(0, (int) MechPilotStatus(mech), 4)];
00942         }
00943         if(initial && Uncon(mech))
00944                 return 0;
00945         if(m < 0)
00946                 /*  Gets the saving roll for someone with toughness  */
00947                 roll = char_rollsaving();
00948         else
00949                 roll = char_rollskilled();
00950         if(MechPilot(mech) >= 0) {
00951                 if(initial) {
00952                         mech_notify(mech, MECHPILOT,
00953                                                 "You attempt to keep consciousness!");
00954                         mech_printf(mech, MECHPILOT,
00955                                                 "Retain Conciousness on: %d  \tRoll: %d", abs(m),
00956                                                 roll);
00957                 } else {
00958                         mech_notify(mech, MECHPILOT,
00959                                                 "You attempt to regain consciousness!");
00960                         mech_printf(mech, MECHPILOT,
00961                                                 "Regain Consciousness on: %d  \tRoll: %d", abs(m),
00962                                                 roll);
00963                 }
00964         }
00965         if(roll < (abs(m))) {
00966                 if(initial)
00967                         mech_notify(mech, MECHPILOT,
00968                                                 "Consciousness slips away from you as you enter a sea of darkness...");
00969                 ProlongUncon(mech, UNCONSCIOUS_TIME);
00970                 return 0;
00971         }
00972         return 1;
00973 }
00974 
00975 void headhitmwdamage(MECH * mech, MECH * attacker, int dam)
00976 {
00977         PSTATS *s;
00978         dbref player;
00979         int damage, bruise, lethaldam, playerBLD;
00980 
00981         if(mech->mynum < 0)
00982                 return;
00983         /* check to see if mech is IC */
00984         if(!In_Character(mech->mynum) || !GotPilot(mech)) {
00985                 MechPilotStatus(mech) += dam;
00986                 handlemwconc(mech, 1);
00987                 return;
00988         }
00989         player = MechPilot(mech);
00990 
00991         s = retrieve_stats(player, VALUES_ATTRS | VALUES_ADVS | VALUES_HEALTH);
00992         /* get the player_stats structure */
00993 
00994         bruise = char_gbruise(s);
00995         /* gets the players bruise damage */
00996 
00997         playerBLD = char_gvalue(s, "build");
00998         /* get the player's BLD value */
00999 
01000         damage = 2 * playerBLD * dam;
01001         /* the damage we are due */
01002 
01003         bruise += damage;
01004         /* this part subtracts 10 from players lethal damage */
01005 
01006         if(bruise > playerBLD * 10) {
01007                 lethaldam = char_glethal(s);
01008                 lethaldam += (bruise - playerBLD * 10);
01009                 bruise = playerBLD * 10;
01010 
01011                 if(lethaldam >= playerBLD * 10) {
01012                         lethaldam = playerBLD * 10;
01013                         char_slethal(s, playerBLD * 10 - 1);
01014                         char_sbruise(s, playerBLD * 10);
01015                         store_stats(player, s, VALUES_HEALTH);
01016                         if(!Destroyed(mech)) {
01017                                 DestroyMech(mech, attacker, 1);
01018                         }
01019                         KillMechContentsIfIC(mech->mynum);
01020                         return;
01021                 }
01022                 char_slethal(s, lethaldam);
01023         }
01024         char_sbruise(s, bruise);
01025         store_stats(player, s, VALUES_HEALTH);
01026         handlemwconc(mech, 1);
01027         MechPilotStatus(mech) += dam;
01028 }
01029 
01030 void mwlethaldam(MECH * mech, MECH * attacker, int dam)
01031 {
01032         PSTATS *s;
01033         dbref player;
01034         int bruise, lethaldam, playerBLD;
01035 
01036         if(mech->mynum < 0)
01037                 return;
01038         /* check to see if mech is IC */
01039         if(!In_Character(mech->mynum) || !GotPilot(mech)) {
01040                 MechPilotStatus(mech) += dam;
01041                 handlemwconc(mech, 1);
01042                 return;
01043         }
01044         player = MechPilot(mech);
01045 
01046         s = retrieve_stats(player, VALUES_ATTRS | VALUES_ADVS | VALUES_HEALTH);
01047         /* get the player_stats structure */
01048         bruise = char_gbruise(s);
01049         playerBLD = char_gvalue(s, "build");
01050         if(!playerBLD)
01051                 playerBLD++;
01052         lethaldam = char_glethal(s);
01053         lethaldam += BOUNDED(10, dam * playerBLD, 40);
01054         if(lethaldam >= playerBLD * 10) {
01055                 lethaldam = playerBLD * 10;
01056                 char_slethal(s, lethaldam - 1);
01057                 char_sbruise(s, lethaldam);
01058                 store_stats(player, s, VALUES_HEALTH);
01059                 if(!Destroyed(mech)) {
01060                         DestroyMech(mech, attacker, 1);
01061                 }
01062                 KillMechContentsIfIC(mech->mynum);
01063                 return;
01064         }
01065         char_sbruise(s, playerBLD * 10 - 5);
01066         char_slethal(s, lethaldam);
01067         store_stats(player, s, VALUES_HEALTH);
01068         handlemwconc(mech, 1);
01069         MechPilotStatus(mech) += dam;
01070 }
01071 
01072 void lower_xp(dbref player, int promillage)
01073 {
01074         PSTATS *s;
01075         int i;
01076 
01077         s = retrieve_stats(player, VALUES_ALL);
01078         for(i = 0; i < NUM_CHARVALUES; i++) {
01079                 if(!s->xp[i])
01080                         continue;
01081                 if(s->xp[i] < 0) {
01082                         s->xp[i] = 0;
01083                         continue;
01084                 }
01085                 s->xp[i] = (s->xp[i] % XP_MAX) * promillage / 1000;
01086                 s->xp[i] = s->xp[i] % XP_MAX + XP_MAX * figure_xp_bonus(player, s, i);
01087         }
01088         store_stats(player, s, VALUES_ALL);
01089 }
01090 
01091 void AccumulateTechXP(dbref pilot, MECH * mech, int reason)
01092 {
01093         char *skname;
01094         int xp;
01095         static char *techw = "technician-weapons";
01096 
01097         if(mech) {
01098                 if(!(skname = FindTechSkillName(mech)))
01099                         return;
01100         } else
01101                 skname = techw;
01102 
01103         xp = MAX(1, reason);
01104 
01105         // We emit all tech XP gains to the MechTechXP channel.
01106         if(char_gainxp(pilot, skname, xp))
01107                 SendTechXP(tprintf("%s gained %d %s XP (changing mech #%d)",
01108                                                    Name(pilot), xp, skname, mech ? mech->mynum : -1));
01109 }
01110 
01111 void AccumulateTechWeaponsXP(dbref pilot, MECH * mech, int reason)
01112 {
01113         char *skname;
01114         int xp;
01115         static char *techw = "technician-weapons";
01116 
01117         skname = techw;
01118         xp = MAX(1, reason);
01119 
01120         // We emit all tech xp gains to MechTechXP channel.
01121         if(char_gainxp(pilot, skname, xp))
01122                 SendTechXP(tprintf("%s gained %d %s XP (changing mech #%d)",
01123                                                    Name(pilot), xp, skname, mech ? mech->mynum : -1));
01124 }
01125 
01126 void AccumulateCommXP(dbref pilot, MECH * mech)
01127 {
01128         int xp;
01129 
01130         xp = 1;
01131         if(!RGotPilot(mech))
01132                 return;
01133         if(!In_Character(mech->mynum))
01134                 return;
01135         if(!Connected(pilot))
01136                 return;
01137         if(char_gainxp(pilot, "Comm-Conventional", xp))
01138                 SendXP(tprintf("%s gained %d %s XP (in #%d)", Name(pilot), xp,
01139                                            "Comm-Conventional", mech->mynum));
01140 }
01141 
01142 void AccumulatePilXP(dbref pilot, MECH * mech, int reason, int addanyway)
01143 {
01144         char *skname;
01145         int xp;
01146 
01147         if(!In_Character(mech->mynum))
01148                 return;
01149 
01150         if(!RGotPilot(mech))
01151                 return;
01152 
01153         if(!(skname = FindPilotingSkillName(mech)))
01154                 return;
01155 
01156         if(!addanyway) {
01157                 if(MechLX(mech) != MechX(mech) || MechLY(mech) != MechY(mech)) {
01158                         MechLX(mech) = MechX(mech);
01159                         MechLY(mech) = MechY(mech);
01160                 } else
01161                         return;
01162         }
01163         xp = MAX(1, reason);
01164 
01165         /* Switching to Exile method of tracking xp, where we split
01166          * Attacking and Piloting xp into two different channels
01167          */
01168         if(char_gainxp(pilot, skname, xp))
01169                 SendPilotXP(tprintf("%s gained %d %s XP", Name(pilot), xp, skname));
01170 /*
01171     if (char_gainxp(pilot, skname, xp))
01172             SendXP(tprintf("%s gained %d %s XP", Name(pilot), xp, skname));
01173 */
01174 }
01175 
01176 void AccumulateSpotXP(dbref pilot, MECH * attacker, MECH * wounded)
01177 {
01178         int xp = 1;
01179 
01180         if(!In_Character(attacker->mynum))
01181                 return;
01182         if(!RGotPilot(attacker))
01183                 return;
01184         if(MechPilot(attacker) != pilot)
01185                 return;
01186         if(attacker == wounded)
01187                 return;
01188         if(Destroyed(wounded))
01189                 return;
01190         if(MechTeam(wounded) == MechTeam(attacker))
01191                 return;
01192         if(!In_Character(wounded->mynum))
01193                 return;
01194         if(char_gainxp(pilot, "Gunnery-Spotting", xp))
01195                 SendXP(tprintf("%s gained spotting XP", Name(pilot)));
01196 }
01197 
01198 int MadePerceptionRoll(MECH * mech, int modifier)
01199 {
01200         int pilot;
01201 
01202         if(!In_Character(mech->mynum))
01203                 return 0;
01204         if(!RGotGPilot(mech))
01205                 return 0;
01206         pilot = MechPilot(mech);
01207         if(pilot <= 0)
01208                 return 0;
01209         if(!MechPer(mech))
01210                 MechPer(mech) = char_getskilltarget(pilot, "Perception", 2);
01211         if(Roll() < (MechPer(mech) + modifier))
01212                 return 0;
01213         char_gainxp(pilot, "Perception", 1);
01214         if(char_gainxp(pilot, "Perception", 1))
01215                 SendXP(tprintf("%s gained 1 perception XP", Name(pilot)));
01216         return 1;
01217 }
01218 
01219 void AccumulateArtyXP(dbref pilot, MECH * attacker, MECH * wounded)
01220 {
01221         int xp = 1;
01222 
01223         /* If not in character ie: like in simulator - no xp */
01224         if(!In_Character(attacker->mynum))
01225                 return;
01226 
01227         if(!RGotGPilot(attacker))
01228                 return;
01229 
01230         if(GunPilot(attacker) != pilot)
01231                 return;
01232 
01233         /* No xp for shooting yourself */
01234         if(attacker == wounded)
01235                 return;
01236 
01237         /* No xp for shooting destroyed units */
01238         if(Destroyed(wounded))
01239                 return;
01240 
01241         /* No xp if both on same team */
01242         if(MechTeam(wounded) == MechTeam(attacker))
01243                 return;
01244 
01245         /* If target not in character ie: in simulator - no xp */
01246         if(!In_Character(wounded->mynum))
01247                 return;
01248 
01249         /* Switching to Exile method of tracking xp, where we split
01250          * Attacking and Piloting xp into two different channels
01251          */
01252         if(char_gainxp(pilot, "Gunnery-Artillery", xp))
01253                 SendAttackXP(tprintf("%s gained %d artillery XP", Name(pilot), xp));
01254 }
01255 
01256 void AccumulateComputerXP(dbref pilot, MECH * mech, int reason)
01257 {
01258         int xp;
01259 
01260         if(!mech)
01261                 return;
01262 
01263         if(mech && In_Character(mech->mynum) && isPlayer(pilot))
01264                 if(char_gainxp(pilot, "computer", MAX(1, reason)))
01265                         SendXP(tprintf
01266                                    ("%s gained %d computer XP (mech #%d)", Name(pilot),
01267                                         reason, mech ? mech->mynum : -1));
01268 }
01269 
01270 int HasBoolAdvantage(dbref player, const char *name)
01271 {
01272         PSTATS *s;
01273         char buf[SBUF_SIZE];
01274 
01275         strcpy(buf, name);
01276         s = retrieve_stats(player, VALUES_ATTRS | VALUES_ADVS | VALUES_HEALTH);
01277         if(char_gvalue(s, buf) == 1)
01278                 return 1;
01279         else
01280                 return 0;
01281 }
01282 
01283 int bth_modifier[] =                    /* Starts from '3' , in 1/36's */
01284 {
01285         /*  3 4 5  6  7  8  9 10 11 12 */
01286         1, 3, 6, 10, 15, 21, 26, 30, 33, 35, 0, 0, 0, 0 /* pad, just in case */
01287 };
01288 
01289 #define TonValue(mech) \
01290 MAX(1, (MechTons(mech) / \
01291  ((MechType(mech) != CLASS_MECH) ? 2 : 1) / \
01292  ((MechMove(mech) == MOVE_NONE) ? 2 : 1)))
01293 
01294 static int t_mod(float sp)
01295 {
01296         if(sp <= MP2)
01297                 return 0;
01298         if(sp <= MP4)
01299                 return 1;
01300         if(sp <= MP6)
01301                 return 2;
01302         if(sp <= MP9)
01303                 return 3;
01304         return 4;                                       /* No extra mods */
01305 }
01306 
01307 #define MoveValue(mech) (t_mod(MMaxSpeed(mech)) + 2)
01308 #define NewMoveValue(mech) ((int) (MechMaxSpeed(mech)/MP1))
01309 
01310 float getPilotBVMod(MECH * mech, int weapindx)
01311 {
01312         /*
01313          * What we do is we get the mod as if we had a 0+ piloting (baseline)
01314          * for the gun skill we want. Each '+' above zero subtracts .05 from
01315          * the result. Obviously, each '+' below adds .05.
01316          *
01317          * The first number in the array below corresponds to a 0+ 0+ person
01318          * and the last number in the array below corresponds to a 7+ 0+ person
01319          * (that's <gun skill>+ <pilot skill>+)
01320          */
01321 
01322         int zeroPilotBaseSkills[] =
01323                 { 2.05, 1.85, 1.65, 1.45, 1.25, 1.15, 1.05, .95 };
01324 
01325         int myGSkill = FindPilotGunnery(mech, weapindx);
01326         int myPSkill = FindPilotPiloting(mech);
01327         float baseMod = 0.0;
01328 
01329         /* First we check if we have a totally off the wall GSkill, i.e., below
01330          * 0 or above 7.
01331          */
01332         if(myGSkill < 0) {
01333                 baseMod = zeroPilotBaseSkills[0] + (abs(myGSkill) * 0.20);
01334         } else if(myGSkill > 7) {
01335                 baseMod = zeroPilotBaseSkills[7] - (myGSkill * 0.10);
01336         } else {
01337                 baseMod = zeroPilotBaseSkills[myGSkill];
01338         }
01339 
01340         return (baseMod - ((0 + myPSkill) * 0.05));
01341 }
01342 
01343 /*
01344  * Routines and formula for XP gain.
01345  */
01346 void AccumulateGunXP(dbref pilot, MECH * attacker, MECH * wounded,
01347                                          int damage, float multiplier, int weapindx, int bth)
01348 {
01349         int omul, xp, my_BV, th_BV, my_speed, th_speed;
01350         float myPilotBVMod = 1.0, theirPilotBVMod = 1.0;
01351         float weapTypeMod;
01352         char *skname;
01353         char buf[MBUF_SIZE];
01354         int damagemod;
01355         float vrtmod;
01356         int i;
01357         int j = NUM_SECTIONS;
01358 
01359         weapTypeMod = 1;
01360 
01361         if(mudconf.btech_oldxpsystem) {
01362                 AccumulateGunXPold(pilot, attacker, wounded, damage,
01363                                                    multiplier, weapindx, bth);
01364                 return;
01365         }
01366 
01367         /* No XP for zero'd mechas */
01368         for(i = 0; i < NUM_SECTIONS; i++)
01369                 j -= SectIsDestroyed(wounded, i);
01370         
01371         if( j < 1)
01372                 return;
01373 
01374         /* Is attacker in character ie: not in simulator */
01375         if(!In_Character(attacker->mynum))
01376                 return;
01377 
01378         if(!RGotGPilot(attacker))
01379                 return;
01380 
01381         if(GunPilot(attacker) != pilot)
01382                 return;
01383 
01384         /* No xp for shooting yourself */
01385         if(attacker == wounded)
01386                 return;
01387 
01388         /* No xp for shooting destroyed mechs */
01389         if(Destroyed(wounded))
01390                 return;
01391 
01392         /* No xp for shooting a teammate */
01393         if(MechTeam(wounded) == MechTeam(attacker))
01394                 return;
01395 
01396         /* Is the target in character ie: in simulators */
01397         if(!In_Character(wounded->mynum))
01398                 return;
01399 
01400         /* No skill to match the weapon we're shooting with? */
01401         if(!(skname = FindGunnerySkillName(attacker, weapindx)))
01402                 return;
01403 
01404         /* No xp for shooting mechwarriors if you not a mechwarrior */
01405         if(MechType(wounded) == CLASS_MW && MechType(attacker) != CLASS_MW)
01406                 return;
01407 
01408         /* bth to high so no way to hit */
01409         if(!(bth <= 12))
01410                 return;
01411 
01412         multiplier = multiplier * mudconf.btech_xp_modifier;
01413 
01414         if(mudconf.btech_xp_bthmod) {
01415                 if(!(bth >= 3 && bth <= 12))
01416                         return;                         /* sure hits aren't interesting */
01417                 multiplier = 2 * multiplier * bth_modifier[bth - 3] / 36;
01418         }
01419 
01420         omul = multiplier;
01421 
01422         /* Need to do a BV mod between the mechs */
01423         my_BV = MechBV(attacker);
01424         th_BV = MechBV(wounded);
01425 
01426         if(mudconf.btech_xp_usePilotBVMod) {
01427                 myPilotBVMod = getPilotBVMod(attacker, weapindx);
01428                 theirPilotBVMod = getPilotBVMod(wounded, weapindx);
01429 
01430                 my_BV = my_BV * myPilotBVMod;
01431                 th_BV = th_BV * theirPilotBVMod;
01432 
01433 #ifdef XP_DEBUG
01434                 SendDebug(tprintf
01435                                   ("Using skill modified battle value for mechs %d and %d "
01436                                    "with skill mods of %2.2f and %2.2f", attacker->mynum,
01437                                    wounded->mynum, myPilotBVMod, theirPilotBVMod));
01438 #endif
01439         }
01440 
01441         my_speed = NewMoveValue(attacker) + 1;
01442         th_speed = NewMoveValue(wounded) + 1;
01443 
01444         if(MechWeapons[weapindx].type == TMISSILE)
01445                 weapTypeMod = mudconf.btech_xp_missilemod;
01446         else if(MechWeapons[weapindx].type == TAMMO)
01447                 weapTypeMod = mudconf.btech_xp_ammomod;
01448 
01449         if(mudconf.btech_defaultweapdam > 1)
01450                 damagemod = damage;
01451         else
01452                 damagemod = 1;
01453 
01454         if(mudconf.btech_xp_vrtmod)
01455                 vrtmod = (MechWeapons[weapindx].vrt <
01456                                   30 ? sqrt((double) MechWeapons[weapindx].vrt / 30.0) : 1);
01457         else
01458                 vrtmod = 1.0;
01459 
01460         multiplier =
01461                 (vrtmod * weapTypeMod * multiplier * sqrt((double) (th_BV +
01462                                                                                                                         1) * th_speed *
01463                                                                                                   mudconf.
01464                                                                                                   btech_defaultweapbv /
01465                                                                                                   mudconf.
01466                                                                                                   btech_defaultweapdam)) /
01467                 (sqrt
01468                  ((double) (my_BV + 1) * my_speed *
01469                   MechWeapons[weapindx].battlevalue / damagemod));
01470 
01471         if(mudconf.btech_perunit_xpmod)
01472                 multiplier = multiplier * MechXPMod(attacker); /* Per unit XP Mod. Defaults to 1 anyways */
01473         
01474         xp = BOUNDED(1, (int) (multiplier * damage / 100), 10);
01475 
01476         strcpy(buf, Name(wounded->mynum));
01477 
01478         // Emit XP gain over MechAttackXP
01479         if(char_gainxp(pilot, skname, (int) xp))
01480                 SendAttackXP(tprintf
01481                                          ("%s gained %d gun XP from feat of %f/100 difficulty "
01482                                           "(%d damage) against %s", Name(pilot), (int) xp, multiplier,
01483                                           damage, buf));
01484 }                                                               // end AccumulateGunXP()
01485 
01486 void AccumulateGunXPold(dbref pilot, MECH * attacker, MECH * wounded,
01487                                                 int numOccurences, float multiplier, int weapindx,
01488                                                 int bth)
01489 {
01490         int omul, xp;
01491         char *skname;
01492         char buf[MBUF_SIZE];
01493 
01494         /* Is the attacker in character ie: in simulators */
01495         if(!In_Character(attacker->mynum))
01496                 return;
01497 
01498         if(!RGotGPilot(attacker))
01499                 return;
01500 
01501         if(GunPilot(attacker) != pilot)
01502                 return;
01503 
01504         /* No xp for shooting yourself */
01505         if(attacker == wounded)
01506                 return;
01507 
01508         /* No xp for shooting destroyed units */
01509         if(Destroyed(wounded))
01510                 return;
01511 
01512         /* No xp for shooting teammate */
01513         if(MechTeam(wounded) == MechTeam(attacker))
01514                 return;
01515 
01516         /* if target is in character ie: in simulators or something */
01517         if(!In_Character(wounded->mynum))
01518                 return;
01519 
01520         if(!(skname = FindGunnerySkillName(attacker, weapindx)))
01521                 return;
01522 
01523         /* No xp for shooting a mechwarrior unless you a mechwarrior */
01524         if(MechType(wounded) == CLASS_MW && MechType(attacker) != CLASS_MW)
01525                 return;
01526 
01527         if(!(bth >= 3 && bth <= 12))
01528                 return;                                 /* sure hits aren't interesting */
01529 
01530         omul = multiplier;
01531         if(MechTons(attacker) > 0)
01532                 multiplier = multiplier * BOUNDED(50,
01533                                                                                   100 * TonValue(wounded) /
01534                                                                                   TonValue(attacker), 150);
01535         else {
01536                 /* Bring this to the attention of the admins */
01537                 SendError(tprintf
01538                                   ("AccumulateGunXP: Weird tonnage for IC mech #%d (%s): %d",
01539                                    attacker->mynum, Name(attacker->mynum),
01540                                    (short) MechTons(attacker)));
01541                 return;
01542         }
01543 
01544         /* Hmm.. we have to figure the speed differences as well */
01545         {
01546                 int my_speed = MoveValue(attacker);
01547                 int th_speed = MoveValue(wounded);
01548 
01549                 multiplier = multiplier * th_speed * th_speed / my_speed / my_speed;
01550         }
01551 
01552         multiplier = multiplier * bth_modifier[bth - 3] / 36;
01553         multiplier = multiplier * 2;    /* For average shot */
01554         if(mudconf.btech_perunit_xpmod)
01555                 multiplier = multiplier * MechXPMod(attacker); /* Per unit XP Modifier. Defaults to 1 */
01556 
01557         if(Number(1, 50) > (multiplier * numOccurences))
01558                 return;                                 /* Nothing for truly twinky stuff, occasionally */
01559 
01560         xp = BOUNDED(1, (int) (multiplier * numOccurences) / 100, 50);  /*Hardcoded limit */
01561         strcpy(buf, Name(wounded->mynum));
01562         /* Switching to Exile method of tracking xp, where we split
01563          * Attacking and Piloting xp into two different channels
01564          */
01565         if(char_gainxp(pilot, skname, (int) xp))
01566                 SendAttackXP(tprintf("%s gained %d gun XP from feat of %f %% "
01567                                                          "difficulty (%d occurences) against %s",
01568                                                          Name(pilot), (int) xp, multiplier, numOccurences,
01569                                                          buf));
01570 }
01571 
01572 void fun_btgetcharvalue(char *buff, char **bufc, dbref player, dbref cause,
01573                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
01574 {
01575         /* fargs[0] = char id (#222)
01576            fargs[1] = value name / value loc #
01577            fargs[2] = flaggo (?) */
01578         dbref target;
01579         int targetcode, flaggo;
01580 
01581         FUNCHECK((target =
01582                           char_lookupplayer(player, cause, 0, fargs[0])) == NOTHING,
01583                          "#-1 INVALID TARGET");
01584         FUNCHECK(!Wiz(player), "#-1 PERMISSION DENIED!");
01585         if(Readnum(targetcode, fargs[1]))
01586                 targetcode = char_getvaluecode(fargs[1]);
01587         FUNCHECK(targetcode < 0 ||
01588                          targetcode >= NUM_CHARVALUES, "#-1 INVALID VALUE");
01589         flaggo = atoi(fargs[2]);
01590         if(char_values[targetcode].type == CHAR_SKILL && flaggo == 4) {
01591                 safe_tprintf_str(buff, bufc, "%d",
01592                                                  figure_xp_to_next_level(target, targetcode));
01593                 return;
01594         }
01595         if(char_values[targetcode].type == CHAR_SKILL && flaggo == 3) {
01596                 safe_tprintf_str(buff, bufc, "%d",
01597                                                  retrieve_stats(target,
01598                                                                                 VALUES_SKILLS)->values[targetcode]);
01599                 return;
01600         }
01601         if(char_values[targetcode].type == CHAR_SKILL && flaggo == 2) {
01602                 safe_tprintf_str(buff, bufc, "%d", char_getxpbycode(target,
01603                                                                                                                         targetcode));
01604                 return;
01605         }
01606         if(char_values[targetcode].type == CHAR_SKILL && flaggo) {
01607                 safe_tprintf_str(buff, bufc, "%d",
01608                                                  char_getskilltargetbycode(target, targetcode, 0));
01609                 return;
01610         }
01611         safe_tprintf_str(buff, bufc, "%d", char_getvaluebycode(target,
01612                                                                                                                    targetcode));
01613 }
01614 
01615 void fun_btsetcharvalue(char *buff, char **bufc, dbref player, dbref cause,
01616                                                 char *fargs[], int nfargs, char *cargs[], int ncargs)
01617 {
01618         /* fargs[0] = char id (#222)
01619            fargs[1] = value name / value loc #
01620            fargs[2] = value to be set
01621            fargs[3] = flaggo (?)
01622          */
01623         dbref target;
01624         int targetcode, targetvalue, flaggo;
01625 
01626         FUNCHECK((target =
01627                           char_lookupplayer(player, cause, 0, fargs[0])) == NOTHING,
01628                          "#-1 INVALID TARGET");
01629         FUNCHECK(!Wiz(player), "#-1 PERMISSION DENIED!");
01630         if(Readnum(targetcode, fargs[1]))
01631                 targetcode = char_getvaluecode(fargs[1]);
01632         FUNCHECK(targetcode < 0 ||
01633                          targetcode >= NUM_CHARVALUES, "#-1 INVALID VALUE");
01634         targetvalue = atoi(fargs[2]);
01635         flaggo = atoi(fargs[3]);
01636 
01637         /* We supposedly have everything at hand.. */
01638         if(flaggo) {
01639                 FUNCHECK(char_values[targetcode].type != CHAR_SKILL,
01640                                  "#-1 ONLY SKILLS CAN HAVE FLAG");
01641                 if(flaggo == 1) {
01642                         /* Need to do some evil frobbage here */
01643                         char_setvaluebycode(target, targetcode, 0);
01644                         targetvalue =
01645                                 char_getskilltargetbycode(target, targetcode,
01646                                                                                   0) - targetvalue;
01647                 } else {
01648                         if(flaggo != 3) {
01649                                 /* Add exp */
01650                                 char_gainxpbycode(target, targetcode, targetvalue);
01651                                 SendXP(tprintf("#%d added %d more %s XP to #%d", player,
01652                                                            targetvalue, char_values[targetcode].name,
01653                                                            target));
01654                                 safe_tprintf_str(buff, bufc, "%s gained %d more %s XP.",
01655                                                                  Name(target), targetvalue,
01656                                                                  char_values[targetcode].name);
01657                         } else {
01658                                 /* Set the xp instead */
01659                                 char_gainxpbycode(target, targetcode,
01660                                                                   targetvalue - char_getxpbycode(target,
01661                                                                                                                                  targetcode));
01662                                 SendXP(tprintf
01663                                            ("#%d set #%d's %s XP to %d", player, target,
01664                                                 char_values[targetcode].name, targetvalue));
01665                                 safe_tprintf_str(buff, bufc, "%s's %s XP set to %d.",
01666                                                                  Name(target), char_values[targetcode].name,
01667                                                                  targetvalue);
01668                         }
01669                         return;
01670                 }
01671         }
01672         char_setvaluebycode(target, targetcode, targetvalue);
01673         safe_tprintf_str(buff, bufc, "%s's %s set to %d", Name(target),
01674                                          char_values[targetcode].name, char_getvaluebycode(target,
01675                                                                                                                                            targetcode));
01676 }
01677 
01678 /* ----------------------------------------------------------------------
01679 ** Syntax: btcharlist(skills|advantages|attributes[,targetplayer])
01680 **
01681 ** Given one of the three arguments above, btcharlist returns the
01682 ** listing of each in a space delimited list.  This is basically a
01683 ** function version of +show. If the second argument is provided, only
01684 ** the skills/advantages that are learned or possessed will
01685 ** appear. For attributes the full list will be returned of since
01686 ** characters need all of them.
01687 */
01688 void fun_btcharlist(char *buff, char **bufc, dbref player, dbref cause,
01689                                         char *fargs[], int nfargs, char *cargs[], int ncargs)
01690 {
01691         int i;
01692         int type = 0;
01693         int first = 1;
01694         dbref target = 0;
01695         enum {
01696                 CHSKI,
01697                 CHADV,
01698                 CHATT,
01699         };
01700         static char *cmds[] = {
01701                 "skills",
01702                 "advantages",
01703                 "attributes",
01704                 NULL
01705         };
01706 
01707         if(!fn_range_check("BTCHARLIST", nfargs, 1, 2, buff, bufc))
01708                 return;
01709 
01710         if(nfargs == 2) {
01711                 target = char_lookupplayer(player, cause, 0, fargs[1]);
01712                 if(target == NOTHING) {
01713                         safe_str("#-1 FUNCTION (BTCHARLIST) INVALID TARGET", buff, bufc);
01714                         return;
01715                 }
01716         }
01717 
01718         switch (listmatch(cmds, fargs[0])) {
01719         case CHSKI:
01720                 type = CHAR_SKILL;
01721                 break;
01722         case CHADV:
01723                 type = CHAR_ADVANTAGE;
01724                 break;
01725         case CHATT:
01726                 type = CHAR_ATTRIBUTE;
01727                 break;
01728         default:
01729                 safe_str("#-1 FUNCTION (BTCHARLIST) INVALID VALUE", buff, bufc);
01730                 return;
01731         }
01732 
01733         for(i = 0; i < NUM_CHARVALUES; ++i)
01734                 if(type == char_values[i].type) {
01735                         if(nfargs == 2 && type != CHAR_ATTRIBUTE) {
01736                                 int targetcode = char_getvaluecode(char_values[i].name);
01737                                 if(char_getvaluebycode(target, targetcode) == 0)
01738                                         continue;
01739                         }
01740                         if(first)
01741                                 first = 0;
01742                         else
01743                                 safe_str(" ", buff, bufc);
01744                         safe_str(char_values[i].name, buff, bufc);
01745                 }
01746         return;
01747 }
01748 
01749 #define MAX_PLAYERS_ON 10000
01750 
01751 void debug_xptop(dbref player, void *data, char *buffer)
01752 {
01753         int hm, i, j;
01754         dbref top[MAX_PLAYERS_ON];
01755         int topv[MAX_PLAYERS_ON];
01756         int count = 0, gt = 0;
01757         coolmenu *c = NULL;
01758         PSTATS *s;
01759 
01760 #if 0
01761         notify(player, "Support discontinued. Bother a wiz if this bothers you.");
01762         return;
01763 #endif
01764 
01765         bzero(top, sizeof(top));
01766         bzero(topv, sizeof(topv));
01767         skipws(buffer);
01768         DOCHECK(!*buffer, "Invalid argument!");
01769         DOCHECK((hm = char_getvaluecode(buffer)) < 0, "Invalid value name!");
01770         DOCHECK(char_values[hm].type != CHAR_SKILL,
01771                         "Only skills have XP (for now at least)");
01772         DO_WHOLE_DB(i) {
01773                 if(!isPlayer(i))
01774                         continue;
01775                 if(Wiz(i))
01776                         continue;
01777                 if(!(s = retrieve_stats(i, VALUES_SKILLS)))
01778                         continue;
01779                 if(!s->xp[hm])
01780                         continue;
01781                 top[count] = i;
01782                 topv[count] = (s->xp[hm] % XP_MAX);
01783                 gt += topv[count];
01784                 count++;
01785         }
01786         for(i = 0; i < (count - 1); i++)
01787                 for(j = i + 1; j < count; j++) {
01788                         if(topv[j] > topv[i]) {
01789                                 topv[count] = topv[j];
01790                                 topv[j] = topv[i];
01791                                 topv[i] = topv[count];
01792 
01793                                 top[count] = top[j];
01794                                 top[j] = top[i];
01795                                 top[i] = top[count];
01796                         }
01797                 }
01798         addline();
01799         for(i = 0; i < MIN(16, count); i++) {
01800                 addmenu(tprintf("%3d. %s", i + 1, Name(top[i])));
01801                 addmenu(tprintf("%d (%.3f %%)", topv[i], (100.0 * topv[i]) / gt));
01802         }
01803         addline();
01804         if(gt) {
01805                 addmenu(tprintf("Grand total: %d points", gt));
01806                 addline();
01807         }
01808         ShowCoolMenu(player, c);
01809         KillCoolMenu(c);
01810 }
01811 
01812 static void store_health(dbref player, PSTATS * s)
01813 {
01814         silly_atr_set(player, A_HEALTH, tprintf("%d,%d", char_gvalue(s,
01815                                                                                                                                  "Bruise"),
01816                                                                                         char_gvalue(s, "Lethal")));
01817 }
01818 
01819 static void retrieve_health(dbref player, PSTATS * s)
01820 {
01821         char *c = silly_atr_get(player, A_HEALTH);
01822         PSTATS *s1;
01823         int i1, i2;
01824 
01825         if(sscanf(c, "%d,%d", &i1, &i2) != 2) {
01826                 s1 = create_new_stats();
01827                 memcpy(s, s1, sizeof(PSTATS));
01828                 store_stats(player, s, VALUES_ALL);
01829                 free((void *) s1);
01830                 return;
01831         }
01832         char_svalue(s, "Bruise", i1);
01833         char_svalue(s, "Lethal", i2);
01834 }
01835 
01836 static void store_attrs(dbref player, PSTATS * s)
01837 {
01838         silly_atr_set(player, A_ATTRS, tprintf("%d,%d,%d,%d,%d", char_gvalue(s,
01839                                                                                                                                                  "Build"),
01840                                                                                    char_gvalue(s, "Reflexes"),
01841                                                                                    char_gvalue(s, "Intuition"),
01842                                                                                    char_gvalue(s, "Learn"),
01843                                                                                    char_gvalue(s, "Charisma")));
01844 }
01845 
01846 static void retrieve_attrs(dbref player, PSTATS * s)
01847 {
01848         char *c = silly_atr_get(player, A_ATTRS);
01849         PSTATS *s1;
01850         int i1, i2, i3, i4, i5;
01851 
01852         if(sscanf(c, "%d,%d,%d,%d,%d", &i1, &i2, &i3, &i4, &i5) != 5) {
01853                 s1 = create_new_stats();
01854                 memcpy(s, s1, sizeof(PSTATS));
01855                 store_stats(player, s, VALUES_ALL);
01856                 free((void *) s1);
01857                 return;
01858         }
01859         char_svalue(s, "Build", i1);
01860         char_svalue(s, "Reflexes", i2);
01861         char_svalue(s, "Intuition", i3);
01862         char_svalue(s, "Learn", i4);
01863         char_svalue(s, "Charisma", i5);
01864 }
01865 
01866 static void generic_retrieve_stuff(dbref player, PSTATS * s, int attr)
01867 {
01868         char *c = silly_atr_get(player, attr), *e;
01869         char buf[512];
01870         int i1, i2, i3, sn;
01871 
01872         if(!*c)
01873                 return;
01874         while (1) {
01875                 i2 = i3 = 0;
01876                 e = strchr(c, '/');
01877                 if(sscanf(c, "%[A-Za-z_-]:%d,%d,%d", buf, &i1, &i2, &i3) < 2)
01878                         return;
01879                 /* Do the magic ;) */
01880                 sn = char_getvaluecode(buf);
01881                 if(sn >= 0) {
01882                         s->values[sn] = i1;
01883                         if(i2)
01884                                 s->xp[sn] = i2;
01885                         if(i3)
01886                                 s->last_use[sn] = i3;
01887                 }
01888                 if(!(c = e))
01889                         return;
01890                 c++;
01891                 if(!(*c))
01892                         return;
01893         }
01894 }
01895 
01896 static void generic_store_stuff(dbref player, PSTATS * s, int attr, int flag)
01897 {
01898         char buf[LBUF_SIZE];
01899         int i;
01900         char *c;
01901 
01902         buf[0] = 0;
01903         c = buf;
01904         for(i = 0; i < NUM_CHARVALUES; i++) {
01905                 if(!s->values[i] && !s->xp[i])
01906                         continue;
01907                 if(flag) {
01908                         if(char_values[i].type != CHAR_SKILL)
01909                                 continue;
01910                 } else if(i != 5 && char_values[i].type != CHAR_ADVANTAGE)
01911                         continue;
01912                 if(s->xp[i])
01913                         sprintf(c, "%s:%d,%d,%d/", char_values_short[i], s->values[i],
01914                                         s->xp[i], (int) s->last_use[i]);
01915                 else
01916                         sprintf(c, "%s:%d/", char_values_short[i], s->values[i]);
01917                 while (*(++c));
01918         }
01919         if(*buf)
01920                 silly_atr_set(player, attr, buf);
01921         else
01922                 silly_atr_set(player, attr, "");
01923 }
01924 
01925 static void retrieve_skills(dbref player, PSTATS * s)
01926 {
01927         generic_retrieve_stuff(player, s, A_SKILLS);
01928 }
01929 
01930 static void retrieve_advs(dbref player, PSTATS * s)
01931 {
01932         generic_retrieve_stuff(player, s, A_ADVS);
01933 }
01934 
01935 static void store_skills(dbref player, PSTATS * s)
01936 {
01937         generic_store_stuff(player, s, A_SKILLS, 1);
01938 }
01939 
01940 static void store_advs(dbref player, PSTATS * s)
01941 {
01942         generic_store_stuff(player, s, A_ADVS, 0);
01943 }
01944 
01945 static void store_stats(dbref player, PSTATS * s, int modes)
01946 {
01947         if(!isPlayer(player))
01948                 return;
01949         if(modes & VALUES_HEALTH)
01950                 store_health(player, s);
01951         if(modes & VALUES_ATTRS)
01952                 store_attrs(player, s);
01953         if(modes & VALUES_ADVS) {
01954                 if(player == cached_target_char)
01955                         cached_target_char = -1;
01956                 store_advs(player, s);
01957         }
01958         if(modes & VALUES_SKILLS) {
01959                 if(player == cached_target_char)
01960                         cached_target_char = -1;
01961                 store_skills(player, s);
01962         }
01963 }
01964 
01965 static PSTATS *retrieve_stats(dbref player, int modes)
01966 {
01967         static PSTATS s;
01968 
01969         bzero(&s, sizeof(PSTATS));
01970         if(modes & VALUES_HEALTH)
01971                 retrieve_health(player, &s);
01972         if(modes & VALUES_ADVS)
01973                 retrieve_advs(player, &s);
01974         if(modes & VALUES_ATTRS)
01975                 retrieve_attrs(player, &s);
01976         if(modes & VALUES_SKILLS)
01977                 retrieve_skills(player, &s);
01978         return &s;
01979 }
01980 
01981 void debug_setxplevel(dbref player, void *data, char *buffer)
01982 {
01983         char *args[3];
01984         int xpt, code;
01985 
01986         DOCHECK(mech_parseattributes(buffer, args, 3) != 2, "Invalid arguments!");
01987         DOCHECK(Readnum(xpt, args[1]), "Invalid value!");
01988         DOCHECK(xpt < 0, "Threshold needs to be >=0 (0 = no gains possible)");
01989         DOCHECK((code =
01990                          char_getvaluecode(args[0])) < 0, "That isn't any charvalue!");
01991         DOCHECK(char_values[code].type != CHAR_SKILL, "That isn't any skill!");
01992         char_values[code].xpthreshold = xpt;
01993     log_error(LOG_WIZARD, "WIZ", "CHANGE", "Exp threshold for %s changed to %d by #%d", 
01994                                                  char_values[code].name, xpt, player);
01995 }
01996 
01997 int btthreshold_func(char *skillname)
01998 {
01999         int code;
02000 
02001         if(!skillname || !*skillname)
02002                 return -1;
02003         code = char_getvaluecode(skillname);
02004         if(code < 0)
02005                 return -1;
02006         if(char_values[code].type != CHAR_SKILL)
02007                 return -1;
02008         return char_values[code].xpthreshold;
02009 }

Generated on Mon May 28 04:25:20 2007 for BattletechMUX by  doxygen 1.4.7