ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/shop.c
(Generate patch)

Comparing deliantra/server/server/shop.c (file contents):
Revision 1.17 by root, Tue Jul 11 10:35:20 2006 UTC vs.
Revision 1.19 by elmex, Tue Jul 11 18:00:46 2006 UTC

1/* 1/*
2 * static char *rcsid_shop_c = 2 * static char *rcsid_shop_c =
3 * "$Id: shop.c,v 1.17 2006/07/11 10:35:20 root Exp $"; 3 * "$Id: shop.c,v 1.19 2006/07/11 18:00:46 elmex Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
335 /* so long as nrof is 32 bit, this is true. 335 /* so long as nrof is 32 bit, this is true.
336 * If it takes more coins than a person can possibly carry, this 336 * If it takes more coins than a person can possibly carry, this
337 * is basically true. 337 * is basically true.
338 */ 338 */
339 if ( (cost / coin->clone.value) > UINT32_MAX) { 339 if ( (cost / coin->clone.value) > UINT32_MAX) {
340 strcpy(buf,"an unimaginable sum of money."); 340 strcpy(buf,"an unimaginable sum of money");
341 return buf; 341 return buf;
342 } 342 }
343 343
344 cost -= (uint64)num * (uint64)coin->clone.value; 344 cost -= (uint64)num * (uint64)coin->clone.value;
345 sprintf(buf, "%d %s", num, num > 1 ? coin->clone.name_pl : coin->clone.name); 345 sprintf(buf, "%d %s", num, num > 1 ? coin->clone.name_pl : coin->clone.name);
719 } 719 }
720 } 720 }
721 return 1; 721 return 1;
722} 722}
723 723
724/* written by elmex:
725 * moved this code from sell_item () here to have a function
726 * that pays the player an amount. Mainly put the code here to
727 * be able to call it from a plugin.
728 *
729 * If the player can't carry all the money that is paid, it gets inserted
730 * in his inventory anyway. This is the best alternative to not pay any money
731 * or put it on the ground under the player. This way the player can still
732 * go somewhere and unload the money at a safe place.
733 *
734 */
735void pay_player (object *pl, uint64 amount) {
736 int count = 0;
737 archetype *at = 0;
738 object *pouch = 0, *tmp = 0;
739
740 for (count = 0; coins[count] != NULL; count++)
741 {
742 at = find_archetype (coins[count]);
743
744 if (at == NULL)
745 LOG(llevError, "Could not find %s archetype\n", coins[count]);
746 else if ((amount / at->clone.value) > 0)
747 {
748 for (pouch=pl->inv; pouch; pouch=pouch->below)
749 {
750 if (pouch->type == CONTAINER
751 && QUERY_FLAG (pouch, FLAG_APPLIED)
752 && pouch->race
753 && strstr (pouch->race, "gold"))
754 {
755 int w = at->clone.weight * (100 - pouch->stats.Str) / 100;
756 int n = amount / at->clone.value;
757
758 if (w == 0)
759 w = 1; /* Prevent divide by zero */
760
761 if (n > 0 && (!pouch->weight_limit || pouch->carrying + w <= pouch->weight_limit))
762 {
763 if (pouch->weight_limit && (pouch->weight_limit - pouch->carrying) / w < n)
764 n = (pouch->weight_limit - pouch->carrying) / w;
765
766 tmp = get_object ();
767 copy_object (&at->clone, tmp);
768 tmp->nrof = n;
769 amount -= (uint64)tmp->nrof * (uint64)tmp->value;
770 tmp = insert_ob_in_ob (tmp, pouch);
771 esrv_send_item (pl, tmp);
772 esrv_send_item (pl, pouch);
773 esrv_update_item (UPD_WEIGHT, pl, pouch);
774 esrv_send_item (pl, pl);
775 }
776 }
777 }
778
779 if (amount / at->clone.value > 0)
780 {
781 tmp = get_object ();
782 copy_object (&at->clone, tmp);
783 tmp->nrof = amount / tmp->value;
784 amount -= (uint64)tmp->nrof * (uint64)tmp->value;
785 tmp = insert_ob_in_ob (tmp, pl);
786 esrv_send_item (pl, tmp);
787 esrv_send_item (pl, pl);
788 }
789 }
790 }
791
792 if (amount != 0)
793#ifndef WIN32
794 LOG (llevError,"Warning - payment in pay_player () not zero: %llu\n", amount);
795#else
796 LOG (llevError,"Warning - payment in pay_player () not zero: %I64u\n", amount);
797#endif
798}
799
800/* elmex: this is for the bank plugin :( */
801uint64 pay_player_arch (object *pl, const char *arch, uint64 amount) {
802 archetype *at = find_archetype (arch);
803 object *tmp = NULL;
804
805 if (at == NULL)
806 return 0;
807
808 if (amount > 0)
809 {
810 tmp = get_object ();
811 copy_object (&at->clone, tmp);
812 tmp->nrof = amount;
813 tmp = insert_ob_in_ob (tmp, pl);
814 esrv_send_item (pl, tmp);
815 esrv_send_item (pl, pl);
816 }
817
818 return 1;
819}
724 820
725/* Modified function to give out platinum coins. This function uses 821/* Modified function to give out platinum coins. This function uses
726 * the coins[] array to know what coins are available, just like 822 * the coins[] array to know what coins are available, just like
727 * buy item. 823 * buy item.
728 * 824 *
729 * Modified to fill available race: gold containers before dumping 825 * Modified to fill available race: gold containers before dumping
730 * remaining coins in character's inventory. 826 * remaining coins in character's inventory.
731 */ 827 */
732void sell_item(object *op, object *pl) { 828void sell_item(object *op, object *pl) {
733 uint64 i=query_cost(op,pl,F_SELL | F_SHOP), extra_gain; 829 uint64 amount = query_cost (op,pl,F_SELL | F_SHOP), extra_gain;
734 int count;
735 object *tmp, *pouch;
736 archetype *at;
737 830
738 if(pl==NULL||pl->type!=PLAYER) { 831 if(pl==NULL || pl->type != PLAYER)
832 {
739 LOG(llevDebug,"Object other than player tried to sell something.\n"); 833 LOG(llevDebug,"Object other than player tried to sell something.\n");
740 return; 834 return;
835 }
836
837 if(op->custom_name)
838 FREE_AND_CLEAR_STR (op->custom_name);
839
840 if(!amount)
741 } 841 {
742
743 if(op->custom_name) FREE_AND_CLEAR_STR(op->custom_name);
744
745 if(!i) {
746 new_draw_info_format(NDI_UNIQUE, 0, pl, 842 new_draw_info_format (NDI_UNIQUE, 0, pl,
747 "We're not interested in %s.",query_name(op)); 843 "We're not interested in %s.", query_name (op));
748 844
749 /* Even if the character doesn't get anything for it, it may still be 845 /* Even if the character doesn't get anything for it, it may still be
750 * worth something. If so, make it unpaid 846 * worth something. If so, make it unpaid
751 */ 847 */
752 if (op->value) { 848 if (op->value)
849 {
753 SET_FLAG(op, FLAG_UNPAID); 850 SET_FLAG(op, FLAG_UNPAID);
754 SET_FLAG(op, FLAG_PLAYER_SOLD); 851 SET_FLAG(op, FLAG_PLAYER_SOLD);
755 } 852 }
853
756 identify(op); 854 identify (op);
757 return; 855 return;
758 } 856 }
759 857
760 /* We compare the price with the one for a player 858 /* We compare the price with the one for a player
761 * without bargaining skill. 859 * without bargaining skill.
762 * This determins the amount of exp (if any) gained for bargaining. 860 * This determins the amount of exp (if any) gained for bargaining.
763 * exp/10 -> 1 for each gold coin 861 * exp/10 -> 1 for each gold coin
764 */ 862 */
765 extra_gain = i - query_cost(op,pl,F_SELL | F_NO_BARGAIN | F_SHOP); 863 extra_gain = amount - query_cost (op, pl, F_SELL | F_NO_BARGAIN | F_SHOP);
766 864
767 if (extra_gain > 0) 865 if (extra_gain > 0)
768 change_exp(pl,extra_gain/10,"bargaining",SK_EXP_NONE); 866 change_exp(pl, extra_gain / 10, "bargaining", SK_EXP_NONE);
769
770 for (count=0; coins[count]!=NULL; count++) {
771 at = find_archetype(coins[count]);
772 if (at==NULL) LOG(llevError, "Could not find %s archetype\n", coins[count]);
773 else if ((i/at->clone.value) > 0) {
774 for ( pouch=pl->inv ; pouch ; pouch=pouch->below ) {
775 if ( pouch->type==CONTAINER && QUERY_FLAG(pouch, FLAG_APPLIED) && pouch->race && strstr(pouch->race, "gold") ) {
776 int w = at->clone.weight * (100-pouch->stats.Str)/100;
777 int n = i/at->clone.value;
778 867
779 if (w==0) w=1; /* Prevent divide by zero */ 868 pay_player (pl, amount);
780 if ( n>0 && (!pouch->weight_limit || pouch->carrying+w<=pouch->weight_limit)) {
781 if (pouch->weight_limit && (pouch->weight_limit-pouch->carrying)/w<n)
782 n = (pouch->weight_limit-pouch->carrying)/w;
783 869
784 tmp = get_object();
785 copy_object(&at->clone, tmp);
786 tmp->nrof = n;
787 i -= (uint64)tmp->nrof * (uint64)tmp->value;
788 tmp = insert_ob_in_ob(tmp, pouch);
789 esrv_send_item (pl, tmp);
790 esrv_send_item (pl, pouch);
791 esrv_update_item (UPD_WEIGHT, pl, pouch);
792 esrv_send_item (pl, pl);
793 }
794 }
795 }
796 if (i/at->clone.value > 0) {
797 tmp = get_object();
798 copy_object(&at->clone, tmp);
799 tmp->nrof = i/tmp->value;
800 i -= (uint64)tmp->nrof * (uint64)tmp->value;
801 tmp = insert_ob_in_ob(tmp, pl);
802 esrv_send_item (pl, tmp);
803 esrv_send_item (pl, pl);
804 }
805 }
806 }
807
808 if (i!=0)
809#ifndef WIN32
810 LOG(llevError,"Warning - payment not zero: %llu\n", i);
811#else
812 LOG(llevError,"Warning - payment not zero: %I64u\n", i);
813#endif
814
815 new_draw_info_format(NDI_UNIQUE, 0, pl, 870 new_draw_info_format (NDI_UNIQUE, 0, pl,
816 "You receive %s for %s.",query_cost_string(op,pl,F_SELL | F_SHOP), 871 "You receive %s for %s.", query_cost_string (op, pl, F_SELL | F_SHOP),
817 query_name(op)); 872 query_name (op));
873
818 SET_FLAG(op, FLAG_UNPAID); 874 SET_FLAG (op, FLAG_UNPAID);
819 identify(op); 875 identify (op);
820} 876}
877
821 878
822/* returns a double that is the ratio of the price that a shop will offer for 879/* returns a double that is the ratio of the price that a shop will offer for
823 * item based on the shops specialisation. Does not take account of greed, 880 * item based on the shops specialisation. Does not take account of greed,
824 * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any 881 * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any
825 * event is never less than 0.1 (calling functions divide by it) 882 * event is never less than 0.1 (calling functions divide by it)
887 * below the minimum value the shop is prepared to trade in, then we don't 944 * below the minimum value the shop is prepared to trade in, then we don't
888 * want it and offer nothing. If it isn't a shop, check whether we should do generic 945 * want it and offer nothing. If it isn't a shop, check whether we should do generic
889 * value reduction. 946 * value reduction.
890 * 947 *
891 */ 948 */
892static uint64 value_limit(uint64 val, int quantity, const object *who, int isshop) { 949static uint64 value_limit (uint64 val, int quantity, const object *who, int isshop) {
893 uint64 newval, unit_price; 950 uint64 newval, unit_price, tmpshopmax;
894 mapstruct *map; 951 mapstruct *map;
952
895 unit_price=val/quantity; 953 unit_price = val / quantity;
954
896 if (!isshop || !who) { 955 if (!isshop || !who)
956 {
897 if (unit_price > 250000) 957 if (unit_price > 250000)
898 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.; 958 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.;
899 else 959 else
900 newval=unit_price; 960 newval = unit_price;
901 } else { 961 }
962 else
963 {
902 if (!who->map) { 964 if (!who->map)
965 {
903 LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name); 966 LOG(llevError, "value_limit: asked shop price for ob %s on NULL map\n", who->name);
904 return val; 967 return val;
905 } 968 }
906 map=who->map; 969
970 map = who->map;
971
972 tmpshopmax = map->shopmax ? map->shopmax : 100000; // 20 royalties default
973
907 if (map->shopmin && unit_price < map->shopmin) return 0; 974 if (map->shopmin && unit_price < map->shopmin)
908 else if (map->shopmax && unit_price > map->shopmax/2) 975 return 0;
976 else if (unit_price > tmpshopmax / 2)
909 newval=MIN((map->shopmax/2)+isqrt(unit_price-map->shopmax/2), map->shopmax); 977 newval = MIN ((tmpshopmax / 2) + isqrt (unit_price - tmpshopmax / 2), tmpshopmax);
910 else if (unit_price > 250000) 978 else
911 newval = 250000. - pow (250000., .75) * 65. + pow (unit_price, .75) * 65.;
912 else
913 newval=unit_price; 979 newval=unit_price;
914 } 980 }
981
915 newval *= quantity; 982 newval *= quantity;
983
916 return newval; 984 return newval;
917} 985}
918 986
919/* gives a desciption of the shop on their current map to the player op. */ 987/* gives a desciption of the shop on their current map to the player op. */
920int describe_shop(const object *op) { 988int describe_shop(const object *op) {
921 mapstruct *map = op->map; 989 mapstruct *map = op->map;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines