version 1.27 | | version 1.28 |
---|
| | |
/* | | /* |
* static char *rcsid_shop_c = | | * static char *rcsid_shop_c = |
* "$Id: shop.c,v 1.27 2004/04/16 16:28:22 akirschbaum Exp $"; | | * "$Id: shop.c,v 1.28 2004/04/25 07:17:40 mwedel Exp $"; |
*/ | | */ |
| | |
/* | | /* |
| | |
* | | * |
* Mark Wedel (mwedel@pyramid.com) | | * Mark Wedel (mwedel@pyramid.com) |
*/ | | */ |
int query_cost(object *tmp, object *who, int flag) { | | uint64 query_cost(object *tmp, object *who, int flag) { |
int val; | | uint64 val; |
int number; /* used to better calculate value */ | | int number; /* used to better calculate value */ |
int no_bargain; | | int no_bargain; |
float diff; | | float diff; |
| | |
/* Limit amount of money you can get for really great items. */ | | /* Limit amount of money you can get for really great items. */ |
if (flag==F_TRUE || flag==F_SELL) { | | if (flag==F_TRUE || flag==F_SELL) { |
if (val/number>10000) { | | if (val/number>10000) { |
val=8000+isqrt((int)val/number)*20; | | val=8000+isqrt(val/number)*20; |
val *= number; | | val *= number; |
} | | } |
} | | } |
| | |
if(flag==F_SELL && !QUERY_FLAG(tmp, FLAG_IDENTIFIED) && need_identify(tmp)) { | | if(flag==F_SELL && !QUERY_FLAG(tmp, FLAG_IDENTIFIED) && need_identify(tmp)) { |
val = (val > 600)? 600:val; | | val = (val > 600)? 600:val; |
} | | } |
return (int)val; | | return val; |
} | | } |
| | |
/* Find the coin type that is worth more the 'c'. Starts at the | | /* Find the coin type that is worth more the 'c'. Starts at the |
* cointype placement. | | * cointype placement. |
*/ | | */ |
| | |
static archetype *find_next_coin(int c, int *cointype) { | | static archetype *find_next_coin(uint64 c, int *cointype) { |
archetype *coin; | | archetype *coin; |
| | |
do { | | do { |
| | |
return coin; | | return coin; |
} | | } |
| | |
/* This returns a string of how much somethign is worth based on | | /* This returns a string of how much something is worth based on |
* an integer being passed. | | * an integer being passed. |
| | * cost is the cost we need to represent. |
| | * While cost is 64 bit, the number of any coin is still really |
| | * limited to 32 bit (size of nrof field). If it turns out players |
| | * have so much money that they have more than 2 billion platinum |
| | * coins, there are certainly issues - the easiest fix at that |
| | * time is to add a higher denomination (mithril piece with |
| | * 10,000 silver or something) |
*/ | | */ |
char *cost_string_from_value(int cost) | | char *cost_string_from_value(uint64 cost) |
{ | | { |
static char buf[MAX_BUF]; | | static char buf[MAX_BUF]; |
archetype *coin, *next_coin; | | archetype *coin, *next_coin; |
| | |
return "nothing"; | | return "nothing"; |
| | |
num = cost / coin->clone.value; | | num = cost / coin->clone.value; |
cost -= num * coin->clone.value; | | /* so long as nrof is 32 bit, this is true. |
| | * If it takes more coins than a person can possibly carry, this |
| | * is basically true. |
| | */ |
| | if ( (cost / coin->clone.value) > UINT32_MAX) { |
| | strcpy(buf,"an unimaginable sum of money."); |
| | return buf; |
| | } |
| | |
| | cost -= (uint64)num * (uint64)coin->clone.value; |
if (num == 1) | | if (num == 1) |
sprintf(buf, "1 %s", coin->clone.name); | | sprintf(buf, "1 %s", coin->clone.name); |
else | | else |
| | |
| | |
coin = next_coin; | | coin = next_coin; |
num = cost / coin->clone.value; | | num = cost / coin->clone.value; |
cost -= num * coin->clone.value; | | cost -= (uint64)num * (uint64)coin->clone.value; |
| | |
if (cost == 0) | | if (cost == 0) |
next_coin = NULL; | | next_coin = NULL; |
| | |
return cost_string_from_value(query_cost(tmp,who,flag)); | | return cost_string_from_value(query_cost(tmp,who,flag)); |
} | | } |
| | |
/* This function finds out how much money the player is carrying, * | | /* This function finds out how much money the player is carrying, |
* and returns that value */ | | * including what is in containers. |
/* Now includes any coins in active containers -- DAMN */ | | */ |
int query_money(object *op) { | | uint64 query_money(object *op) { |
object *tmp; | | object *tmp; |
int total=0; | | uint64 total=0; |
| | |
if (op->type!=PLAYER && op->type!=CONTAINER) { | | if (op->type!=PLAYER && op->type!=CONTAINER) { |
LOG(llevError, "Query money called with non player/container"); | | LOG(llevError, "Query money called with non player/container"); |
| | |
} | | } |
for (tmp = op->inv; tmp; tmp= tmp->below) { | | for (tmp = op->inv; tmp; tmp= tmp->below) { |
if (tmp->type==MONEY) { | | if (tmp->type==MONEY) { |
total += tmp->nrof * tmp->value; | | total += (uint64)tmp->nrof * (uint64)tmp->value; |
} else if (tmp->type==CONTAINER && | | } else if (tmp->type==CONTAINER && |
QUERY_FLAG(tmp,FLAG_APPLIED) && | | QUERY_FLAG(tmp,FLAG_APPLIED) && |
(tmp->race==NULL || strstr(tmp->race,"gold"))) { | | (tmp->race==NULL || strstr(tmp->race,"gold"))) { |
| | |
} | | } |
return total; | | return total; |
} | | } |
/* TCHIZE: This function takes the amount of money from the * | | /* TCHIZE: This function takes the amount of money from the |
* the player inventory and from it's various pouches using the * | | * the player inventory and from it's various pouches using the |
* pay_from_container function. * | | * pay_from_container function. |
* returns 0 if not possible. 1 if success */ | | * returns 0 if not possible. 1 if success |
| | */ |
int pay_for_amount(int to_pay,object *pl) { | | int pay_for_amount(int to_pay,object *pl) { |
object *pouch; | | object *pouch; |
| | |
| | |
return 1; | | return 1; |
} | | } |
| | |
/* DAMN: This is now a wrapper for pay_from_container, which is * | | /* DAMN: This is now a wrapper for pay_from_container, which is |
* called for the player, then for each active container that can hold * | | * called for the player, then for each active container that can hold |
* money until op is paid for. Change will be left wherever the last * | | * money until op is paid for. Change will be left wherever the last |
* of the price was paid from. */ | | * of the price was paid from. |
| | */ |
int pay_for_item(object *op,object *pl) { | | int pay_for_item(object *op,object *pl) { |
int to_pay = query_cost(op,pl,F_BUY); | | uint64 to_pay = query_cost(op,pl,F_BUY); |
object *pouch; | | object *pouch; |
int saved_money; | | uint64 saved_money; |
| | |
if (to_pay==0) return 1; | | if (to_pay==0) return 1; |
if(to_pay>query_money(pl)) return 0; | | if(to_pay>query_money(pl)) return 0; |
| | |
* with weight not be subtracted properly. We now remove and | | * with weight not be subtracted properly. We now remove and |
* insert the coin objects - this should update the weight | | * insert the coin objects - this should update the weight |
* appropriately | | * appropriately |
| | * |
| | * DAMN: This function is used for the player, then for any active |
| | * containers that can hold money, until the op is paid for. |
*/ | | */ |
/* DAMN: This function is used for the player, then for any active * | | uint64 pay_from_container(object *op, object *pouch, int to_pay) { |
* containers that can hold money, until the op is paid for. */ | | int count, i; |
int pay_from_container(object *op, object *pouch, int to_pay) { | | uint64 remain; |
int count, i, remain; | | |
object *tmp, *coin_objs[NUM_COINS], *next; | | object *tmp, *coin_objs[NUM_COINS], *next; |
archetype *at; | | archetype *at; |
object *who; | | object *who; |
| | |
| | |
if (coin_objs[i]->nrof*coin_objs[i]->value> remain) { | | if (coin_objs[i]->nrof*coin_objs[i]->value> remain) { |
num_coins = remain / coin_objs[i]->value; | | num_coins = remain / coin_objs[i]->value; |
if (num_coins*coin_objs[i]->value< remain) num_coins++; | | if ((uint64)num_coins*(uint64)coin_objs[i]->value < remain) num_coins++; |
} else { | | } else { |
num_coins = coin_objs[i]->nrof; | | num_coins = coin_objs[i]->nrof; |
} | | } |
| | |
remain -= num_coins * coin_objs[i]->value; | | remain -= (uint64)num_coins * (uint64)coin_objs[i]->value; |
coin_objs[i]->nrof -= num_coins; | | coin_objs[i]->nrof -= num_coins; |
/* Now start making change. Start at the coin value | | /* Now start making change. Start at the coin value |
* below the one we just did, and work down to | | * below the one we just did, and work down to |
| | |
for (i=0; i<NUM_COINS; i++) { | | for (i=0; i<NUM_COINS; i++) { |
if (coin_objs[i]->nrof) { | | if (coin_objs[i]->nrof) { |
object *tmp = insert_ob_in_ob(coin_objs[i], pouch); | | object *tmp = insert_ob_in_ob(coin_objs[i], pouch); |
for (who = pouch; who && who->type!=PLAYER && who->env!=NULL; who=who->env) {} | | for (who = pouch; who && who->type!=PLAYER && who->env!=NULL; who=who->env) ; |
esrv_send_item(who, tmp); | | esrv_send_item(who, tmp); |
esrv_send_item (who, pouch); | | esrv_send_item (who, pouch); |
esrv_update_item (UPD_WEIGHT, who, pouch); | | esrv_update_item (UPD_WEIGHT, who, pouch); |
| | |
return(remain); | | return(remain); |
} | | } |
| | |
/* Eneq(@csd.uu.se): Better get_payment, descends containers looking for | | /* Better get_payment, descends containers looking for |
unpaid items. get_payment is now used as a link. To make it simple | | * unpaid items, and pays for them. |
we need the player-object here. */ | | * returns 0 if the player still has unpaid items. |
| | * returns 1 if the player has paid for everything. |
int get_payment2 (object *pl, object *op) { | | * pl is the player buying the stuff. |
| | * op is the object we are examining. If op has |
| | * and inventory, we examine that. IF there are objects |
| | * below op, we descend down. |
| | */ |
| | int get_payment(object *pl, object *op) { |
char buf[MAX_BUF]; | | char buf[MAX_BUF]; |
int ret=1; | | int ret=1; |
| | |
if (op!=NULL&&op->inv) | | if (op!=NULL&&op->inv) |
ret = get_payment2(pl, op->inv); | | ret = get_payment(pl, op->inv); |
| | |
if (!ret) | | if (!ret) |
return 0; | | return 0; |
| | |
if (op!=NULL&&op->below) | | if (op!=NULL&&op->below) |
ret = get_payment2 (pl, op->below); | | ret = get_payment (pl, op->below); |
| | |
if (!ret) | | if (!ret) |
return 0; | | return 0; |
| | |
if(op!=NULL&&QUERY_FLAG(op,FLAG_UNPAID)) { | | if(op!=NULL&&QUERY_FLAG(op,FLAG_UNPAID)) { |
strncpy(buf,query_cost_string(op,pl,F_BUY),MAX_BUF); | | strncpy(buf,query_cost_string(op,pl,F_BUY),MAX_BUF); |
if(!pay_for_item(op,pl)) { | | if(!pay_for_item(op,pl)) { |
int i=query_cost(op,pl,F_BUY) - query_money(pl); | | uint64 i=query_cost(op,pl,F_BUY) - query_money(pl); |
CLEAR_FLAG(op, FLAG_UNPAID); | | CLEAR_FLAG(op, FLAG_UNPAID); |
new_draw_info_format(NDI_UNIQUE, 0, pl, | | new_draw_info_format(NDI_UNIQUE, 0, pl, |
"You lack %s to buy %s.", cost_string_from_value(i), | | "You lack %s to buy %s.", cost_string_from_value(i), |
| | |
return 1; | | return 1; |
} | | } |
| | |
int get_payment(object *pl) { | | |
int ret; | | |
| | |
ret = get_payment2 (pl, pl->inv); | | /* Modified function to give out platinum coins. This function uses |
| | * the coins[] array to know what coins are available, just like |
return ret; | | * buy item. |
} | | * |
| | * Modified to fill available race: gold containers before dumping |
/* Modified function to give out platinum coins. This function is * | | * remaining coins in character's inventory. |
* not as general as pay_for_item in finding money types - each * | | */ |
* new money type needs to be explicity code in here. */ | | |
/* Modified to fill available race: gold containers before dumping * | | |
* remaining coins in character's inventory. -- DAMN */ | | |
void sell_item(object *op, object *pl) { | | void sell_item(object *op, object *pl) { |
int i=query_cost(op,pl,F_SELL), count; | | uint64 i=query_cost(op,pl,F_SELL), extra_gain; |
object *tmp; | | int count; |
object *pouch; | | object *tmp, *pouch; |
archetype *at; | | archetype *at; |
int extra_gain; | | |
| | |
if(pl==NULL||pl->type!=PLAYER) { | | if(pl==NULL||pl->type!=PLAYER) { |
LOG(llevDebug,"Object other than player tried to sell something.\n"); | | LOG(llevDebug,"Object other than player tried to sell something.\n"); |
| | |
identify(op); | | identify(op); |
return; | | return; |
} | | } |
| | |
/* We compare the price with the one for a player | | /* We compare the price with the one for a player |
* without bargaining skill. | | * without bargaining skill. |
* This determins the amount of exp (if any) gained for bargaining. | | * This determins the amount of exp (if any) gained for bargaining. |
| | |
| | |
if (w==0) w=1; /* Prevent divide by zero */ | | if (w==0) w=1; /* Prevent divide by zero */ |
if ( n>0 && (!pouch->weight_limit || pouch->carrying+w<=pouch->weight_limit)) { | | if ( n>0 && (!pouch->weight_limit || pouch->carrying+w<=pouch->weight_limit)) { |
if (pouch->weight_limit && (pouch->weight_limit-pouch->carrying)/w<n) { | | if (pouch->weight_limit && (pouch->weight_limit-pouch->carrying)/w<n) |
n = (pouch->weight_limit-pouch->carrying)/w; | | n = (pouch->weight_limit-pouch->carrying)/w; |
} | | |
tmp = get_object(); | | tmp = get_object(); |
copy_object(&at->clone, tmp); | | copy_object(&at->clone, tmp); |
tmp->nrof = n; | | tmp->nrof = n; |
i -= tmp->nrof * tmp->value; | | i -= (uint64)tmp->nrof * (uint64)tmp->value; |
tmp = insert_ob_in_ob(tmp, pouch); | | tmp = insert_ob_in_ob(tmp, pouch); |
esrv_send_item (pl, tmp); | | esrv_send_item (pl, tmp); |
esrv_send_item (pl, pouch); | | esrv_send_item (pl, pouch); |
| | |
tmp = get_object(); | | tmp = get_object(); |
copy_object(&at->clone, tmp); | | copy_object(&at->clone, tmp); |
tmp->nrof = i/tmp->value; | | tmp->nrof = i/tmp->value; |
i -= tmp->nrof * tmp->value; | | i -= (uint64)tmp->nrof * (uint64)tmp->value; |
tmp = insert_ob_in_ob(tmp, pl); | | tmp = insert_ob_in_ob(tmp, pl); |
esrv_send_item (pl, tmp); | | esrv_send_item (pl, tmp); |
esrv_send_item (pl, pl); | | esrv_send_item (pl, pl); |