00001
00002
00003
00004
00005
00006
00007
00008
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
00079 s->xp[code] = s->xp[code] % XP_MAX;
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
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
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
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
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
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);
00428 else
00429 return (0);
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
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
00674 ShowCoolMenu(player, c);
00675 KillCoolMenu(c);
00676 }
00677
00678
00679
00680
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
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
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
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
00993
00994 bruise = char_gbruise(s);
00995
00996
00997 playerBLD = char_gvalue(s, "build");
00998
00999
01000 damage = 2 * playerBLD * dam;
01001
01002
01003 bruise += damage;
01004
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
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
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
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
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
01166
01167
01168 if(char_gainxp(pilot, skname, xp))
01169 SendPilotXP(tprintf("%s gained %d %s XP", Name(pilot), xp, skname));
01170
01171
01172
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
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
01234 if(attacker == wounded)
01235 return;
01236
01237
01238 if(Destroyed(wounded))
01239 return;
01240
01241
01242 if(MechTeam(wounded) == MechTeam(attacker))
01243 return;
01244
01245
01246 if(!In_Character(wounded->mynum))
01247 return;
01248
01249
01250
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[] =
01284 {
01285
01286 1, 3, 6, 10, 15, 21, 26, 30, 33, 35, 0, 0, 0, 0
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;
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
01314
01315
01316
01317
01318
01319
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
01330
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
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
01368 for(i = 0; i < NUM_SECTIONS; i++)
01369 j -= SectIsDestroyed(wounded, i);
01370
01371 if( j < 1)
01372 return;
01373
01374
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
01385 if(attacker == wounded)
01386 return;
01387
01388
01389 if(Destroyed(wounded))
01390 return;
01391
01392
01393 if(MechTeam(wounded) == MechTeam(attacker))
01394 return;
01395
01396
01397 if(!In_Character(wounded->mynum))
01398 return;
01399
01400
01401 if(!(skname = FindGunnerySkillName(attacker, weapindx)))
01402 return;
01403
01404
01405 if(MechType(wounded) == CLASS_MW && MechType(attacker) != CLASS_MW)
01406 return;
01407
01408
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;
01417 multiplier = 2 * multiplier * bth_modifier[bth - 3] / 36;
01418 }
01419
01420 omul = multiplier;
01421
01422
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);
01473
01474 xp = BOUNDED(1, (int) (multiplier * damage / 100), 10);
01475
01476 strcpy(buf, Name(wounded->mynum));
01477
01478
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 }
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
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
01505 if(attacker == wounded)
01506 return;
01507
01508
01509 if(Destroyed(wounded))
01510 return;
01511
01512
01513 if(MechTeam(wounded) == MechTeam(attacker))
01514 return;
01515
01516
01517 if(!In_Character(wounded->mynum))
01518 return;
01519
01520 if(!(skname = FindGunnerySkillName(attacker, weapindx)))
01521 return;
01522
01523
01524 if(MechType(wounded) == CLASS_MW && MechType(attacker) != CLASS_MW)
01525 return;
01526
01527 if(!(bth >= 3 && bth <= 12))
01528 return;
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
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
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;
01554 if(mudconf.btech_perunit_xpmod)
01555 multiplier = multiplier * MechXPMod(attacker);
01556
01557 if(Number(1, 50) > (multiplier * numOccurences))
01558 return;
01559
01560 xp = BOUNDED(1, (int) (multiplier * numOccurences) / 100, 50);
01561 strcpy(buf, Name(wounded->mynum));
01562
01563
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
01576
01577
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
01619
01620
01621
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
01638 if(flaggo) {
01639 FUNCHECK(char_values[targetcode].type != CHAR_SKILL,
01640 "#-1 ONLY SKILLS CAN HAVE FLAG");
01641 if(flaggo == 1) {
01642
01643 char_setvaluebycode(target, targetcode, 0);
01644 targetvalue =
01645 char_getskilltargetbycode(target, targetcode,
01646 0) - targetvalue;
01647 } else {
01648 if(flaggo != 3) {
01649
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
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
01680
01681
01682
01683
01684
01685
01686
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
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 }