|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00032 static sint64 pay_from_container(object *op, object *pouch, sint64 to_pay); 00033 00040 sint64 query_cost(object *tmp, object *who, int flag) 00041 { 00042 sint64 val; 00043 double diff; 00044 int number; 00045 int charisma = 11; 00046 00047 if ((number = tmp->nrof) == 0) 00048 { 00049 number = 1; 00050 } 00051 00052 /* Money is always identified */ 00053 if (tmp->type == MONEY) 00054 { 00055 return (number * tmp->value); 00056 } 00057 00058 /* Handle identified items */ 00059 if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) || !need_identify(tmp)) 00060 { 00061 if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) 00062 { 00063 return 0; 00064 } 00065 else 00066 { 00067 val = tmp->value * number; 00068 } 00069 } 00070 /* This area deals with objects that are not identified, but can be */ 00071 else 00072 { 00073 if (tmp->arch != NULL) 00074 { 00075 if (flag == COST_BUY) 00076 { 00077 LOG(llevBug, "query_cost(): Asking for buy-value of unidentified object %s.\n", query_name(tmp, NULL)); 00078 val = tmp->arch->clone.value * number; 00079 } 00080 /* Trying to sell something, or get true value */ 00081 else 00082 { 00083 /* Selling unidentified gems is *always* stupid */ 00084 if (tmp->type == GEM || tmp->type == JEWEL || tmp->type == NUGGET || tmp->type == PEARL) 00085 { 00086 val = number * 3; 00087 } 00088 /* Don't want to give anything away */ 00089 else if (tmp->type == POTION) 00090 { 00091 val = number * 50; 00092 } 00093 else 00094 { 00095 val = number * tmp->arch->clone.value; 00096 } 00097 } 00098 } 00099 else 00100 { 00101 /* No archetype with this object - we generate some dummy values to avoid server break */ 00102 LOG(llevBug, "query_cost(): Have object with no archetype: %s\n", query_name(tmp, NULL)); 00103 00104 if (flag == COST_BUY) 00105 { 00106 LOG(llevBug, "query_cost(): Asking for buy-value of unidentified object without arch.\n"); 00107 val = number * 100; 00108 } 00109 else 00110 { 00111 val = number * 80; 00112 } 00113 } 00114 } 00115 00116 /* Wands will count special. The base value is for a wand with one charge */ 00117 if (tmp->type == WAND) 00118 { 00119 val += (val * tmp->level) * tmp->stats.food; 00120 } 00121 else if (tmp->type == ROD || tmp->type == HORN || tmp->type == POTION || tmp->type == SCROLL) 00122 { 00123 val += val * tmp->level; 00124 } 00125 00126 /* We are done if we only want get the real value */ 00127 if (flag == COST_TRUE) 00128 { 00129 return val; 00130 } 00131 00132 /* First, we adjust charisma for players and count skills in */ 00133 if (who != NULL && who->type == PLAYER) 00134 { 00135 /* Used for SK_BARGAINING modification */ 00136 charisma = who->stats.Cha; 00137 00138 /* This skill will give us a charisma boost */ 00139 if (find_skill(who, SK_BARGAINING)) 00140 { 00141 charisma += 4; 00142 00143 if (charisma > MAX_STAT) 00144 { 00145 charisma = MAX_STAT; 00146 } 00147 } 00148 } 00149 00150 /* Now adjust for sell or buy multiplier */ 00151 if (flag == COST_BUY) 00152 { 00153 diff = (double) (1.0 - (double) cha_bonus[charisma]); 00154 } 00155 else 00156 { 00157 diff = (double) (0.20 + (double) cha_bonus[charisma]); 00158 } 00159 00160 val = (val * (long) (1000 * (diff))) / 1000; 00161 00162 /* We want to give at least 1 copper for items which have any 00163 * value. */ 00164 if (val < 1 && tmp->value > 0) 00165 { 00166 val = 1; 00167 } 00168 00169 return val; 00170 } 00171 00178 static archetype *find_next_coin(sint64 c, int *cointype) 00179 { 00180 archetype *coin; 00181 00182 do 00183 { 00184 if (coins[*cointype] == NULL) 00185 { 00186 return NULL; 00187 } 00188 00189 coin = find_archetype(coins[*cointype]); 00190 00191 if (coin == NULL) 00192 { 00193 return NULL; 00194 } 00195 00196 *cointype += 1; 00197 } 00198 while (coin->clone.value > c); 00199 00200 return coin; 00201 } 00202 00207 char *cost_string_from_value(sint64 cost) 00208 { 00209 static char buf[MAX_BUF]; 00210 archetype *coin, *next_coin; 00211 char *endbuf; 00212 sint64 num; 00213 int cointype = 0; 00214 00215 coin = find_next_coin(cost, &cointype); 00216 00217 if (coin == NULL) 00218 { 00219 return "nothing"; 00220 } 00221 00222 num = cost / coin->clone.value; 00223 cost -= num * coin->clone.value; 00224 00225 if (num == 1) 00226 { 00227 snprintf(buf, sizeof(buf), "1 %s%s", material_real[coin->clone.material_real].name, coin->clone.name); 00228 } 00229 else 00230 { 00231 snprintf(buf, sizeof(buf), "%"FMT64" %s%ss", num, material_real[coin->clone.material_real].name, coin->clone.name); 00232 } 00233 00234 next_coin = find_next_coin(cost, &cointype); 00235 00236 if (next_coin == NULL) 00237 { 00238 return buf; 00239 } 00240 00241 do 00242 { 00243 endbuf = buf + strlen(buf); 00244 00245 coin = next_coin; 00246 num = cost / coin->clone.value; 00247 cost -= num * coin->clone.value; 00248 00249 if (cost == 0.0) 00250 { 00251 next_coin = NULL; 00252 } 00253 else 00254 { 00255 next_coin = find_next_coin(cost, &cointype); 00256 } 00257 00258 if (next_coin) 00259 { 00260 /* There will be at least one more string to add to the list, 00261 * use a comma. */ 00262 strcat(endbuf, ", "); 00263 endbuf += 2; 00264 } 00265 else 00266 { 00267 strcat(endbuf, " and "); 00268 endbuf += 5; 00269 } 00270 00271 if (num == 1) 00272 { 00273 sprintf(endbuf, "1 %s%s", material_real[coin->clone.material_real].name, coin->clone.name); 00274 } 00275 else 00276 { 00277 sprintf(endbuf, "%"FMT64" %s%ss", num, material_real[coin->clone.material_real].name, coin->clone.name); 00278 } 00279 00280 } 00281 while (next_coin); 00282 00283 return buf; 00284 } 00285 00295 char *query_cost_string(object *tmp, object *who, int flag) 00296 { 00297 return cost_string_from_value(query_cost(tmp, who, flag)); 00298 } 00299 00305 sint64 query_money(object *op) 00306 { 00307 object *tmp; 00308 sint64 total = 0; 00309 00310 if (op->type != PLAYER && op->type != CONTAINER) 00311 { 00312 LOG(llevBug, "query_money(): Called with non player/container.\n"); 00313 return 0; 00314 } 00315 00316 for (tmp = op->inv; tmp; tmp = tmp->below) 00317 { 00318 if (tmp->type == MONEY) 00319 { 00320 total += tmp->nrof * tmp->value; 00321 } 00322 else if (tmp->type == CONTAINER && ((!tmp->race || strstr(tmp->race, "gold")) || QUERY_FLAG(tmp, FLAG_APPLIED))) 00323 { 00324 total += query_money(tmp); 00325 } 00326 else if (tmp->arch->name == shstr_cons.player_info && tmp->name == shstr_cons.BANK_GENERAL) 00327 { 00328 total += tmp->value; 00329 } 00330 } 00331 00332 return total; 00333 } 00334 00342 int pay_for_amount(sint64 to_pay, object *pl) 00343 { 00344 object *pouch; 00345 00346 if (to_pay == 0) 00347 { 00348 return 1; 00349 } 00350 00351 if (to_pay > query_money(pl)) 00352 { 00353 return 0; 00354 } 00355 00356 to_pay = pay_from_container(NULL, pl, to_pay); 00357 00358 for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) 00359 { 00360 if (pouch->type == CONTAINER && pouch->inv && (QUERY_FLAG(pouch, FLAG_APPLIED) || (!pouch->race || strstr(pouch->race, "gold")))) 00361 { 00362 to_pay = pay_from_container(NULL, pouch, to_pay); 00363 } 00364 } 00365 00366 #ifndef REAL_WIZ 00367 if (QUERY_FLAG(pl, FLAG_WAS_WIZ)) 00368 { 00369 SET_FLAG(op, FLAG_WAS_WIZ); 00370 } 00371 #endif 00372 00373 fix_player(pl); 00374 return 1; 00375 } 00376 00385 int pay_for_item(object *op, object *pl) 00386 { 00387 sint64 to_pay = query_cost(op, pl, COST_BUY); 00388 object *pouch; 00389 00390 if (to_pay == 0.0) 00391 { 00392 return 1; 00393 } 00394 00395 if (to_pay > query_money(pl)) 00396 { 00397 return 0; 00398 } 00399 00400 to_pay = pay_from_container(op, pl, to_pay); 00401 00402 for (pouch = pl->inv; (pouch != NULL) && (to_pay > 0); pouch = pouch->below) 00403 { 00404 if (pouch->type == CONTAINER && pouch->inv && (QUERY_FLAG(pouch, FLAG_APPLIED) || (!pouch->race || strstr(pouch->race, "gold")))) 00405 { 00406 to_pay = pay_from_container(op, pouch, to_pay); 00407 } 00408 } 00409 00410 #ifndef REAL_WIZ 00411 if (QUERY_FLAG(pl, FLAG_WAS_WIZ)) 00412 { 00413 SET_FLAG(op, FLAG_WAS_WIZ); 00414 } 00415 #endif 00416 00417 fix_player(pl); 00418 return 1; 00419 } 00420 00428 static sint64 pay_from_container(object *op, object *pouch, sint64 to_pay) 00429 { 00430 sint64 remain; 00431 int count, i; 00432 object *tmp, *coin_objs[NUM_COINS], *next, *bank_object = NULL; 00433 archetype *at; 00434 object *who; 00435 00436 (void) op; 00437 00438 if (pouch->type != PLAYER && pouch->type != CONTAINER) 00439 { 00440 return to_pay; 00441 } 00442 00443 remain = to_pay; 00444 00445 for (i = 0; i < NUM_COINS; i++) 00446 { 00447 coin_objs[i] = NULL; 00448 } 00449 00450 /* This hunk should remove all the money objects from the player/container */ 00451 for (tmp = pouch->inv; tmp; tmp = next) 00452 { 00453 next = tmp->below; 00454 00455 if (tmp->type == MONEY) 00456 { 00457 for (i = 0; i < NUM_COINS; i++) 00458 { 00459 if (!strcmp(coins[NUM_COINS - 1 - i], tmp->arch->name) && (tmp->value == tmp->arch->clone.value)) 00460 { 00461 /* This should not happen, but if it does, just merge 00462 * the two. */ 00463 if (coin_objs[i] != NULL) 00464 { 00465 LOG(llevBug, "pay_from_container(): %s has two money entries of (%s)\n", query_name(pouch, NULL), coins[NUM_COINS - 1 - i]); 00466 remove_ob(tmp); 00467 coin_objs[i]->nrof += tmp->nrof; 00468 esrv_del_item(CONTR(pouch), tmp->count, tmp->env); 00469 } 00470 else 00471 { 00472 remove_ob(tmp); 00473 00474 if (pouch->type == PLAYER) 00475 { 00476 esrv_del_item(CONTR(pouch), tmp->count,tmp->env); 00477 } 00478 00479 coin_objs[i] = tmp; 00480 } 00481 00482 break; 00483 } 00484 } 00485 00486 if (i == NUM_COINS) 00487 { 00488 LOG(llevBug, "pay_from_container(): Did not find string match for %s\n", tmp->arch->name); 00489 } 00490 } 00491 else if (tmp->arch->name == shstr_cons.player_info && tmp->name == shstr_cons.BANK_GENERAL) 00492 { 00493 bank_object = tmp; 00494 } 00495 } 00496 00497 /* Fill in any gaps in the coin_objs array - needed to make change. */ 00498 /* Note that the coin_objs array goes from least value to greatest value */ 00499 for (i = 0; i < NUM_COINS; i++) 00500 { 00501 if (coin_objs[i] == NULL) 00502 { 00503 at = find_archetype(coins[NUM_COINS - 1 - i]); 00504 00505 if (at == NULL) 00506 { 00507 LOG(llevBug, "pay_from_container(): Could not find %s archetype", coins[NUM_COINS - 1 - i]); 00508 } 00509 00510 coin_objs[i] = get_object(); 00511 copy_object(&at->clone, coin_objs[i], 0); 00512 coin_objs[i]->nrof = 0; 00513 } 00514 } 00515 00516 for (i = 0; i < NUM_COINS; i++) 00517 { 00518 sint64 num_coins; 00519 00520 if ((sint64) (coin_objs[i]->nrof * coin_objs[i]->value) > remain) 00521 { 00522 num_coins = remain / coin_objs[i]->value; 00523 00524 if ((num_coins * coin_objs[i]->value) < remain) 00525 { 00526 num_coins++; 00527 } 00528 } 00529 else 00530 { 00531 num_coins = coin_objs[i]->nrof; 00532 } 00533 00534 if (num_coins > SINT32_MAX) 00535 { 00536 LOG(llevDebug, "pay_from_container(): Money overflow value->nrof: number of coins > SINT32_MAX (type coin %d)\n", i); 00537 num_coins = SINT32_MAX; 00538 } 00539 00540 remain -= num_coins * coin_objs[i]->value; 00541 coin_objs[i]->nrof -= (uint32) num_coins; 00542 /* Now start making change. Start at the coin value 00543 * below the one we just did, and work down to 00544 * the lowest value. */ 00545 count = i - 1; 00546 00547 while (remain < 0 && count >= 0) 00548 { 00549 num_coins = -remain / coin_objs[count]->value; 00550 coin_objs[count]->nrof += (uint32) num_coins; 00551 remain += num_coins * coin_objs[count]->value; 00552 count--; 00553 } 00554 } 00555 00556 /* If there's still some remain, that means we could try to pay from 00557 * bank. */ 00558 if (bank_object && bank_object->value != 0 && remain != 0 && bank_object->value >= remain) 00559 { 00560 bank_object->value -= remain; 00561 remain = 0; 00562 } 00563 00564 for (i = 0; i < NUM_COINS; i++) 00565 { 00566 if (coin_objs[i]->nrof) 00567 { 00568 tmp = insert_ob_in_ob(coin_objs[i], pouch); 00569 00570 for (who = pouch; who && who->type != PLAYER && who->env != NULL; who = who->env) 00571 { 00572 } 00573 00574 esrv_send_item(who, tmp); 00575 esrv_send_item (who, pouch); 00576 esrv_update_item(UPD_WEIGHT, who, pouch); 00577 00578 if (pouch->type != PLAYER) 00579 { 00580 esrv_send_item(who, who); 00581 esrv_update_item(UPD_WEIGHT, who, who); 00582 } 00583 } 00584 } 00585 00586 return remain; 00587 } 00588 00596 int get_payment(object *pl, object *op) 00597 { 00598 char buf[MAX_BUF]; 00599 int ret = 1; 00600 00601 if (op != NULL && op->inv) 00602 { 00603 ret = get_payment(pl, op->inv); 00604 } 00605 00606 if (!ret) 00607 { 00608 return 0; 00609 } 00610 00611 if (op != NULL && op->below) 00612 { 00613 ret = get_payment(pl, op->below); 00614 } 00615 00616 if (!ret) 00617 { 00618 return 0; 00619 } 00620 00621 if (op != NULL && QUERY_FLAG(op, FLAG_UNPAID)) 00622 { 00623 strncpy(buf, query_cost_string(op, pl, COST_BUY), sizeof(buf)); 00624 00625 if (!pay_for_item(op, pl)) 00626 { 00627 sint64 i = query_cost(op, pl, COST_BUY) - query_money(pl); 00628 00629 CLEAR_FLAG(op, FLAG_UNPAID); 00630 new_draw_info_format(0, COLOR_WHITE, pl, "You lack %s to buy %s.", cost_string_from_value(i), query_name(op, NULL)); 00631 SET_FLAG(op, FLAG_UNPAID); 00632 return 0; 00633 } 00634 else 00635 { 00636 object *tmp, *c_cont = op->env; 00637 tag_t c = op->count; 00638 00639 CLEAR_FLAG(op, FLAG_UNPAID); 00640 CLEAR_FLAG(op, FLAG_STARTEQUIP); 00641 00642 if (pl->type == PLAYER) 00643 { 00644 new_draw_info_format(0, COLOR_WHITE, pl, "You paid %s for %s.", buf, query_name(op, NULL)); 00645 } 00646 00647 tmp = merge_ob(op, NULL); 00648 00649 if (pl->type == PLAYER) 00650 { 00651 /* It was merged */ 00652 if (tmp) 00653 { 00654 esrv_del_item(CONTR(pl), c, c_cont); 00655 op = tmp; 00656 } 00657 00658 esrv_send_item(pl, op); 00659 } 00660 } 00661 } 00662 00663 return 1; 00664 } 00665 00672 void sell_item(object *op, object *pl, sint64 value) 00673 { 00674 sint64 i; 00675 00676 if (pl == NULL || pl->type != PLAYER) 00677 { 00678 LOG(llevDebug, "sell_item(): Object other than player tried to sell something.\n"); 00679 return; 00680 } 00681 00682 if (op == NULL) 00683 { 00684 i = value; 00685 } 00686 else 00687 { 00688 i = query_cost(op, pl, COST_SELL); 00689 } 00690 00691 if (op && op->custom_name) 00692 { 00693 FREE_AND_CLEAR_HASH(op->custom_name); 00694 } 00695 00696 if (!i) 00697 { 00698 if (op) 00699 { 00700 new_draw_info_format(0, COLOR_WHITE, pl, "We're not interested in %s.", query_name(op, NULL)); 00701 } 00702 } 00703 00704 i = insert_coins(pl, i); 00705 00706 if (!op) 00707 { 00708 return; 00709 } 00710 00711 if (i != 0) 00712 { 00713 LOG(llevBug, "Warning - payment not zero: %"FMT64"\n", i); 00714 } 00715 00716 new_draw_info_format(0, COLOR_WHITE, pl, "You receive %s for %s.", query_cost_string(op, pl, 1), query_name(op, NULL)); 00717 SET_FLAG(op, FLAG_UNPAID); 00718 00719 /* Identify the item. Makes any unidentified item sold to unique shop appear identified. */ 00720 identify(op); 00721 } 00722 00728 int get_money_from_string(const char *text, struct _money_block *money) 00729 { 00730 int pos = 0; 00731 const char *word; 00732 00733 memset(money, 0, sizeof(struct _money_block)); 00734 00735 /* Kill all whitespace */ 00736 while (*text !='\0' && (isspace(*text) || !isprint(*text))) 00737 { 00738 text++; 00739 } 00740 00741 /* Easy, special case: all money */ 00742 if (!strncasecmp(text, "all", 3)) 00743 { 00744 money->mode = MONEYSTRING_ALL; 00745 return money->mode; 00746 } 00747 00748 money->mode = MONEYSTRING_NOTHING; 00749 00750 while ((word = get_word_from_string(text, &pos))) 00751 { 00752 int i = 0, flag = *word; 00753 00754 while (*(word + i) != '\0') 00755 { 00756 if (*(word + i) < '0' || *(word + i) > '9') 00757 { 00758 flag = 0; 00759 } 00760 00761 i++; 00762 } 00763 00764 /* If still set, we have a valid number in the word string */ 00765 if (flag) 00766 { 00767 int value = atoi(word); 00768 00769 /* A valid number - now lets look we have a valid money keyword */ 00770 if (value > 0 && value < 1000000) 00771 { 00772 if ((word = get_word_from_string(text, &pos)) && *word != '\0') 00773 { 00774 size_t len = strlen(word); 00775 00776 if (!strncasecmp("mithril", word, len)) 00777 { 00778 money->mode = MONEYSTRING_AMOUNT; 00779 money->mithril += value; 00780 } 00781 else if (!strncasecmp("gold", word, len)) 00782 { 00783 money->mode = MONEYSTRING_AMOUNT; 00784 money->gold += value; 00785 } 00786 else if (!strncasecmp("silver", word, len)) 00787 { 00788 money->mode = MONEYSTRING_AMOUNT; 00789 money->silver += value; 00790 } 00791 else if (!strncasecmp("copper", word, len)) 00792 { 00793 money->mode = MONEYSTRING_AMOUNT; 00794 money->copper += value; 00795 } 00796 } 00797 } 00798 } 00799 } 00800 00801 return money->mode; 00802 } 00803 00809 int query_money_type(object *op, int value) 00810 { 00811 object *tmp; 00812 sint64 total = 0; 00813 00814 for (tmp = op->inv; tmp; tmp = tmp->below) 00815 { 00816 if (tmp->type == MONEY && tmp->value == value) 00817 { 00818 total += tmp->nrof; 00819 } 00820 else if (tmp->type == CONTAINER && !tmp->slaying && ((!tmp->race || strstr(tmp->race, "gold")))) 00821 { 00822 total += query_money_type(tmp, value); 00823 } 00824 00825 if (total >= (sint64) value) 00826 { 00827 break; 00828 } 00829 } 00830 00831 return (int) total; 00832 } 00833 00841 sint64 remove_money_type(object *who, object *op, sint64 value, sint64 amount) 00842 { 00843 object *tmp, *tmp2; 00844 00845 for (tmp = op->inv; tmp; tmp = tmp2) 00846 { 00847 tmp2 = tmp->below; 00848 00849 if (!amount && value != -1) 00850 { 00851 return amount; 00852 } 00853 00854 if (tmp->type == MONEY && (tmp->value == value || value == -1)) 00855 { 00856 if ((sint64) tmp->nrof <= amount || value == -1) 00857 { 00858 object *env = tmp->env; 00859 00860 if (value == -1) 00861 { 00862 amount += (tmp->nrof * tmp->value); 00863 } 00864 else 00865 { 00866 amount -= tmp->nrof; 00867 } 00868 00869 remove_ob(tmp); 00870 00871 if (op->type == PLAYER) 00872 { 00873 esrv_del_item(CONTR(op), tmp->count, NULL); 00874 } 00875 else 00876 { 00877 esrv_del_item(NULL, tmp->count, env); 00878 } 00879 } 00880 else 00881 { 00882 tmp->nrof -= (uint32) amount; 00883 amount = 0; 00884 00885 esrv_send_item(who, tmp); 00886 esrv_send_item(who, op); 00887 esrv_update_item(UPD_WEIGHT, who, op); 00888 00889 if (op->type != PLAYER) 00890 { 00891 esrv_send_item(who, who); 00892 esrv_update_item(UPD_WEIGHT, who, who); 00893 } 00894 } 00895 } 00896 else if (tmp->type == CONTAINER && !tmp->slaying && ((!tmp->race || strstr(tmp->race, "gold")))) 00897 { 00898 amount = remove_money_type(who, tmp, value, amount); 00899 } 00900 } 00901 00902 return amount; 00903 } 00904 00910 void insert_money_in_player(object *pl, object *money, uint32 nrof) 00911 { 00912 object *tmp = get_object(); 00913 copy_object(money, tmp, 0); 00914 tmp->nrof = nrof; 00915 tmp = insert_ob_in_ob(tmp, pl); 00916 esrv_send_item(pl, tmp); 00917 esrv_send_item(pl, pl); 00918 esrv_update_item(UPD_WEIGHT, pl, pl); 00919 } 00920 00925 object *bank_get_info(object *op) 00926 { 00927 object *tmp; 00928 00929 for (tmp = op->inv; tmp; tmp = tmp->below) 00930 { 00931 if (tmp->arch->name == shstr_cons.player_info && tmp->name == shstr_cons.BANK_GENERAL) 00932 { 00933 return tmp; 00934 } 00935 } 00936 00937 return NULL; 00938 } 00939 00944 object *bank_create_info(object *op) 00945 { 00946 object *bank = get_archetype(shstr_cons.player_info); 00947 00948 FREE_AND_COPY_HASH(bank->name, shstr_cons.BANK_GENERAL); 00949 insert_ob_in_ob(bank, op); 00950 00951 return bank; 00952 } 00953 00959 object *bank_get_create_info(object *op) 00960 { 00961 object *bank = bank_get_info(op); 00962 00963 if (!bank) 00964 { 00965 bank = bank_create_info(op); 00966 } 00967 00968 return bank; 00969 } 00970 00975 sint64 bank_get_balance(object *op) 00976 { 00977 object *bank = bank_get_info(op); 00978 00979 if (!bank) 00980 { 00981 return 0; 00982 } 00983 00984 return bank->value; 00985 } 00986 00993 int bank_deposit(object *op, const char *text, sint64 *value) 00994 { 00995 int pos = 0; 00996 _money_block money; 00997 object *bank; 00998 00999 get_word_from_string(text, &pos); 01000 get_money_from_string(text + pos, &money); 01001 *value = 0; 01002 01003 if (!money.mode) 01004 { 01005 return BANK_SYNTAX_ERROR; 01006 } 01007 else if (money.mode == MONEYSTRING_ALL) 01008 { 01009 bank = bank_get_create_info(op); 01010 *value = remove_money_type(op, op, -1, 0); 01011 bank->value += *value; 01012 fix_player(op); 01013 } 01014 else 01015 { 01016 if (money.mithril) 01017 { 01018 if (query_money_type(op, coins_arch[0]->clone.value) < money.mithril) 01019 { 01020 return BANK_DEPOSIT_MITHRIL; 01021 } 01022 } 01023 01024 if (money.gold) 01025 { 01026 if (query_money_type(op, coins_arch[1]->clone.value) < money.gold) 01027 { 01028 return BANK_DEPOSIT_GOLD; 01029 } 01030 } 01031 01032 if (money.silver) 01033 { 01034 if (query_money_type(op, coins_arch[2]->clone.value) < money.silver) 01035 { 01036 return BANK_DEPOSIT_SILVER; 01037 } 01038 } 01039 01040 if (money.copper) 01041 { 01042 if (query_money_type(op, coins_arch[3]->clone.value) < money.copper) 01043 { 01044 return BANK_DEPOSIT_COPPER; 01045 } 01046 } 01047 01048 if (money.mithril) 01049 { 01050 remove_money_type(op, op, coins_arch[0]->clone.value, money.mithril); 01051 } 01052 01053 if (money.gold) 01054 { 01055 remove_money_type(op, op, coins_arch[1]->clone.value, money.gold); 01056 } 01057 01058 if (money.silver) 01059 { 01060 remove_money_type(op, op, coins_arch[2]->clone.value, money.silver); 01061 } 01062 01063 if (money.copper) 01064 { 01065 remove_money_type(op, op, coins_arch[3]->clone.value, money.copper); 01066 } 01067 01068 bank = bank_get_create_info(op); 01069 *value = money.mithril * coins_arch[0]->clone.value + money.gold * coins_arch[1]->clone.value + money.silver * coins_arch[2]->clone.value + money.copper * coins_arch[3]->clone.value; 01070 bank->value += *value; 01071 fix_player(op); 01072 } 01073 01074 return BANK_SUCCESS; 01075 } 01076 01084 int bank_withdraw(object *op, const char *text, sint64 *value) 01085 { 01086 int pos = 0; 01087 sint64 big_value; 01088 _money_block money; 01089 object *bank; 01090 01091 get_word_from_string(text, &pos); 01092 get_money_from_string(text + pos, &money); 01093 01094 bank = bank_get_info(op); 01095 *value = 0; 01096 01097 if (!bank || !bank->value) 01098 { 01099 return BANK_WITHDRAW_MISSING; 01100 } 01101 01102 if (!money.mode) 01103 { 01104 return BANK_SYNTAX_ERROR; 01105 } 01106 else if (money.mode == MONEYSTRING_ALL) 01107 { 01108 *value = bank->value; 01109 sell_item(NULL, op, bank->value); 01110 bank->value = 0; 01111 fix_player(op); 01112 } 01113 else 01114 { 01115 /* Just to set a border. */ 01116 if (money.mithril > 100000 || money.gold > 100000 || money.silver > 1000000 || money.copper > 1000000) 01117 { 01118 return BANK_WITHDRAW_HIGH; 01119 } 01120 01121 big_value = money.mithril * coins_arch[0]->clone.value + money.gold * coins_arch[1]->clone.value + money.silver * coins_arch[2]->clone.value + money.copper * coins_arch[3]->clone.value; 01122 01123 if (big_value > bank->value) 01124 { 01125 return BANK_WITHDRAW_MISSING; 01126 } 01127 01128 if (!player_can_carry(op, money.mithril * coins_arch[0]->clone.weight + money.gold * coins_arch[1]->clone.weight + money.silver * coins_arch[2]->clone.weight + money.copper * coins_arch[3]->clone.weight)) 01129 { 01130 return BANK_WITHDRAW_OVERWEIGHT; 01131 } 01132 01133 if (money.mithril) 01134 { 01135 insert_money_in_player(op, &coins_arch[0]->clone, money.mithril); 01136 } 01137 01138 if (money.gold) 01139 { 01140 insert_money_in_player(op, &coins_arch[1]->clone, money.gold); 01141 } 01142 01143 if (money.silver) 01144 { 01145 insert_money_in_player(op, &coins_arch[2]->clone, money.silver); 01146 } 01147 01148 if (money.copper) 01149 { 01150 insert_money_in_player(op, &coins_arch[3]->clone, money.copper); 01151 } 01152 01153 *value = big_value; 01154 bank->value -= big_value; 01155 fix_player(op); 01156 } 01157 01158 return BANK_SUCCESS; 01159 } 01160 01166 sint64 insert_coins(object *pl, sint64 value) 01167 { 01168 int count; 01169 object *tmp, *pouch; 01170 archetype *at; 01171 01172 for (count = 0; coins[count]; count++) 01173 { 01174 at = find_archetype(coins[count]); 01175 01176 if (at == NULL) 01177 { 01178 LOG(llevBug, "Could not find %s archetype", coins[count]); 01179 } 01180 else if ((value / at->clone.value) > 0) 01181 { 01182 for (pouch = pl->inv; pouch; pouch = pouch->below) 01183 { 01184 if (pouch->type == CONTAINER && QUERY_FLAG(pouch, FLAG_APPLIED) && pouch->race && strstr(pouch->race, "gold")) 01185 { 01186 int w = (int) ((float) at->clone.weight * pouch->weapon_speed); 01187 uint32 n = (uint32) (value / at->clone.value); 01188 01189 /* Prevent FPE */ 01190 if (w == 0) 01191 { 01192 w = 1; 01193 } 01194 01195 if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= (sint32) pouch->weight_limit)) 01196 { 01197 if (pouch->weight_limit && ((sint32)pouch->weight_limit-pouch->carrying) / w < (sint32) n) 01198 { 01199 n = (pouch->weight_limit-pouch->carrying) / w; 01200 } 01201 01202 tmp = get_object(); 01203 copy_object(&at->clone, tmp, 0); 01204 tmp->nrof = n; 01205 value -= tmp->nrof * tmp->value; 01206 tmp = insert_ob_in_ob(tmp, pouch); 01207 esrv_send_item(pl, tmp); 01208 esrv_send_item(pl, pouch); 01209 esrv_update_item(UPD_WEIGHT, pl, pouch); 01210 esrv_send_item(pl, pl); 01211 esrv_update_item(UPD_WEIGHT, pl, pl); 01212 } 01213 } 01214 } 01215 01216 if (value / at->clone.value > 0) 01217 { 01218 tmp = get_object(); 01219 copy_object(&at->clone, tmp, 0); 01220 tmp->nrof = (uint32) (value / tmp->value); 01221 value -= tmp->nrof * tmp->value; 01222 tmp = insert_ob_in_ob(tmp, pl); 01223 esrv_send_item(pl, tmp); 01224 esrv_send_item(pl, pl); 01225 esrv_update_item(UPD_WEIGHT, pl, pl); 01226 } 01227 } 01228 } 01229 01230 return value; 01231 }
1.7.4