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.12 by root, Mon Sep 11 23:33:30 2006 UTC vs.
Revision 1.24 by root, Fri Dec 15 19:59:20 2006 UTC

1
2/*
3 * static char *rcsid_shop_c =
4 * "$Id: shop.C,v 1.12 2006/09/11 23:33:30 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
10 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
22 16
23 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 20
27 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
28*/ 22*/
29 23
30#include <global.h> 24#include <global.h>
31#include <spells.h> 25#include <spells.h>
32#include <skills.h> 26#include <skills.h>
33#include <living.h> 27#include <living.h>
34#include <newclient.h>
35#ifndef __CEXTRACT__
36# include <sproto.h> 28#include <sproto.h>
37#endif
38#include <math.h> 29#include <math.h>
39 30
40/* this is a measure of how effective store specialisation is. A general store 31/* this is a measure of how effective store specialisation is. A general store
41 * will offer this proportion of the 'maximum' price, a specialised store will 32 * will offer this proportion of the 'maximum' price, a specialised store will
42 * offer a range of prices around it such that the maximum price is always one 33 * offer a range of prices around it such that the maximum price is always one
49/* price a shopkeeper will give someone they neither like nor dislike */ 40/* price a shopkeeper will give someone they neither like nor dislike */
50#define NEUTRAL_RATIO 0.8 41#define NEUTRAL_RATIO 0.8
51 42
52static void pay_from_container (object *pl, object *pouch, sint64 &to_pay); 43static void pay_from_container (object *pl, object *pouch, sint64 &to_pay);
53static sint64 value_limit (sint64 val, int quantity, const object *who, int isshop); 44static sint64 value_limit (sint64 val, int quantity, const object *who, int isshop);
54static double shop_specialisation_ratio (const object *item, const mapstruct *map); 45static double shop_specialisation_ratio (const object *item, const maptile *map);
55static double shop_greed (const mapstruct *map); 46static double shop_greed (const maptile *map);
56 47
57#define NUM_COINS 4 /* number of coin types */ 48#define NUM_COINS 4 /* number of coin types */
58static const char *const coins[] = { "royalty", "platinacoin", "goldcoin", "silvercoin", NULL }; 49static const char *const coins[] = { "royalty", "platinacoin", "goldcoin", "silvercoin", NULL };
59 50
60/* Added F_TRUE flag to define.h to mean that the price should not 51/* Added F_TRUE flag to define.h to mean that the price should not
104 approximate = flag & F_APPROX; 95 approximate = flag & F_APPROX;
105 shop = flag & F_SHOP; 96 shop = flag & F_SHOP;
106 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP); 97 flag &= ~(F_NO_BARGAIN | F_IDENTIFIED | F_NOT_CURSED | F_APPROX | F_SHOP);
107 98
108 if (tmp->type == MONEY) 99 if (tmp->type == MONEY)
109 return (tmp->nrof * tmp->value); 100 return tmp->nrof * tmp->value;
101
110 if (tmp->type == GEM) 102 if (tmp->type == GEM)
111 { 103 {
112 if (flag == F_TRUE) 104 if (flag == F_TRUE)
113 return (tmp->nrof * tmp->value); 105 return (tmp->nrof * tmp->value);
106
114 if (flag == F_BUY) 107 if (flag == F_BUY)
115 return (sint64) (1.03 * tmp->nrof * tmp->value); 108 return (sint64) (1.03 * tmp->nrof * tmp->value);
109
116 if (flag == F_SELL) 110 if (flag == F_SELL)
117 return (sint64) (0.97 * tmp->nrof * tmp->value); 111 return (sint64) (0.97 * tmp->nrof * tmp->value);
112
118 LOG (llevError, "Query_cost: Gem type with unknown flag : %d\n", flag); 113 LOG (llevError, "Query_cost: Gem type with unknown flag %d: %s\n", flag, tmp->debug_desc ());
119 return 0; 114 return 0;
120 } 115 }
116
121 number = tmp->nrof; 117 number = tmp->nrof;
122 if (number == 0) 118 if (number == 0)
123 number = 1; 119 number = 1;
124 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified) 120 if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) || !need_identify (tmp) || identified)
125 { 121 {
224 const typedata *tmptype; 220 const typedata *tmptype;
225 221
226 tmptype = get_typedata (tmp->type); 222 tmptype = get_typedata (tmp->type);
227 223
228 if (find_skill_by_number (who, SK_BARGAINING)) 224 if (find_skill_by_number (who, SK_BARGAINING))
229 {
230 lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level; 225 lev_bargain = find_skill_by_number (who, SK_BARGAINING)->level;
231 } 226
232 if (tmptype) 227 if (tmptype)
233 { 228 {
234 idskill1 = tmptype->identifyskill; 229 idskill1 = tmptype->identifyskill;
230
235 if (idskill1) 231 if (idskill1)
236 { 232 {
237 idskill2 = tmptype->identifyskill2; 233 idskill2 = tmptype->identifyskill2;
234
238 if (find_skill_by_number (who, idskill1)) 235 if (find_skill_by_number (who, idskill1))
239 {
240 lev_identify = find_skill_by_number (who, idskill1)->level; 236 lev_identify = find_skill_by_number (who, idskill1)->level;
241 } 237
242 if (idskill2 && find_skill_by_number (who, idskill2)) 238 if (idskill2 && find_skill_by_number (who, idskill2))
243 {
244 lev_identify += find_skill_by_number (who, idskill2)->level; 239 lev_identify += find_skill_by_number (who, idskill2)->level;
245 }
246 } 240 }
247 } 241 }
248 else 242 else
249 LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", &tmp->name); 243 LOG (llevError, "Query_cost: item %s hasn't got a valid type\n", tmp->debug_desc ());
250 244
251 /* ratio determines how much of the price modification 245 /* ratio determines how much of the price modification
252 * will come from the basic stat charisma 246 * will come from the basic stat charisma
253 * the rest will come from the level in bargaining skill 247 * the rest will come from the level in bargaining skill
254 */ 248 */
331 325
332 do 326 do
333 { 327 {
334 if (coins[*cointype] == NULL) 328 if (coins[*cointype] == NULL)
335 return NULL; 329 return NULL;
336 coin = find_archetype (coins[*cointype]); 330 coin = archetype::find (coins[*cointype]);
337 if (coin == NULL) 331 if (coin == NULL)
338 return NULL; 332 return NULL;
339 *cointype += 1; 333 *cointype += 1;
340 } 334 }
341 while (coin->clone.value > c); 335 while (coin->clone.value > c);
593 { 587 {
594 // This should not happen, but if it does, just merge the two. 588 // This should not happen, but if it does, just merge the two.
595 if (coin_objs [i]) 589 if (coin_objs [i])
596 { 590 {
597 LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]); 591 LOG (llevError, "%s has two money entries of (%s)\n", &pouch->name, coins[NUM_COINS - 1 - i]);
598 remove_ob (tmp); 592 tmp->remove ();
599 coin_objs[i]->nrof += tmp->nrof; 593 coin_objs[i]->nrof += tmp->nrof;
600 esrv_del_item (pl->contr, tmp->count); 594 esrv_del_item (pl->contr, tmp->count);
601 free_object (tmp); 595 tmp->destroy ();
602 } 596 }
603 else 597 else
604 { 598 {
605 remove_ob (tmp); 599 tmp->remove ();
606 600
607 if (pouch->type == PLAYER) 601 if (pouch->type == PLAYER)
608 esrv_del_item (pl->contr, tmp->count); 602 esrv_del_item (pl->contr, tmp->count);
609 603
610 coin_objs[i] = tmp; 604 coin_objs[i] = tmp;
622 /* Fill in any gaps in the coin_objs array - needed to make change. */ 616 /* Fill in any gaps in the coin_objs array - needed to make change. */
623 /* Note that the coin_objs array goes from least value to greatest value */ 617 /* Note that the coin_objs array goes from least value to greatest value */
624 for (i = 0; i < NUM_COINS; i++) 618 for (i = 0; i < NUM_COINS; i++)
625 if (!coin_objs[i]) 619 if (!coin_objs[i])
626 { 620 {
627 at = find_archetype (coins[NUM_COINS - 1 - i]); 621 at = archetype::find (coins[NUM_COINS - 1 - i]);
628 622
629 if (at == NULL) 623 if (at == NULL)
630 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]); 624 LOG (llevError, "Could not find %s archetype\n", coins[NUM_COINS - 1 - i]);
631 625
632 coin_objs[i] = arch_to_object (at); 626 coin_objs[i] = arch_to_object (at);
669 663
670 if (pl->type != PLAYER) 664 if (pl->type != PLAYER)
671 esrv_send_item (pl, pl); 665 esrv_send_item (pl, pl);
672 } 666 }
673 else 667 else
674 free_object (coin_objs[i]); 668 coin_objs[i]->destroy ();
675 } 669 }
676} 670}
677 671
678/* Checks all unpaid items in op's inventory, adds up all the money they 672/* Checks all unpaid items in op's inventory, adds up all the money they
679 * have, and checks that they can actually afford what they want to buy. 673 * have, and checks that they can actually afford what they want to buy.
684can_pay (object *pl) 678can_pay (object *pl)
685{ 679{
686 int unpaid_count = 0; 680 int unpaid_count = 0;
687 sint64 unpaid_price = 0; 681 sint64 unpaid_price = 0;
688 sint64 player_wealth = query_money (pl); 682 sint64 player_wealth = query_money (pl);
689 object *item;
690 683
691 if (!pl || pl->type != PLAYER) 684 if (!pl || pl->type != PLAYER)
692 { 685 {
693 LOG (llevError, "can_pay(): called against something that isn't a player\n"); 686 LOG (llevError, "can_pay(): called against something that isn't a player\n");
694 return 0; 687 return 0;
695 } 688 }
696 689
697 for (object::deep_iterator item = pl->begin (); item != pl->end (); ++item) 690 for (object::depth_iterator item = pl->begin (); item != pl->end (); ++item)
698 if (QUERY_FLAG (item, FLAG_UNPAID)) 691 if (QUERY_FLAG (item, FLAG_UNPAID))
699 { 692 {
700 unpaid_count++; 693 unpaid_count++;
701 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP); 694 unpaid_price += query_cost (item, pl, F_BUY | F_SHOP);
702 } 695 }
731{ 724{
732 for (;;) 725 for (;;)
733 { 726 {
734 next_item: 727 next_item:
735 728
736 for (object::deep_iterator op = pl->begin (); op != pl->end (); ++op) 729 for (object::depth_iterator op = pl->begin (); op != pl->end (); ++op)
737 { 730 {
738 if (QUERY_FLAG (op, FLAG_UNPAID)) 731 if (QUERY_FLAG (op, FLAG_UNPAID))
739 { 732 {
740 char buf[MAX_BUF]; 733 char buf[MAX_BUF];
741 snprintf (buf, MAX_BUF, "%s", query_cost_string (op, pl, F_BUY | F_SHOP)); 734 snprintf (buf, MAX_BUF, "%s", query_cost_string (op, pl, F_BUY | F_SHOP));
750 return 0; 743 return 0;
751 } 744 }
752 else 745 else
753 { 746 {
754 object *tmp; 747 object *tmp;
755 tag_t c = op->count;
756 748
757 CLEAR_FLAG (op, FLAG_UNPAID); 749 CLEAR_FLAG (op, FLAG_UNPAID);
758 CLEAR_FLAG (op, FLAG_PLAYER_SOLD); 750 CLEAR_FLAG (op, FLAG_PLAYER_SOLD);
759 new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op)); 751 new_draw_info_format (NDI_UNIQUE, 0, op, "You paid %s for %s.", buf, query_name (op));
760 tmp = merge_ob (op, NULL); 752 tmp = merge_ob (op, NULL);
761 753
762 if (pl->type == PLAYER) 754 if (pl->type == PLAYER)
763 { 755 {
764 if (tmp) 756 if (tmp)
765 { /* it was merged */ 757 { /* it was merged */
766 esrv_del_item (pl->contr, c); 758 esrv_del_item (pl->contr, op->count);
767 op = tmp; 759 op = tmp;
768 } 760 }
769 761
770 esrv_send_item (pl, op); 762 esrv_send_item (pl, op);
771 } 763 }
797 archetype *at = 0; 789 archetype *at = 0;
798 object *pouch = 0, *tmp = 0; 790 object *pouch = 0, *tmp = 0;
799 791
800 for (count = 0; coins[count] != NULL; count++) 792 for (count = 0; coins[count] != NULL; count++)
801 { 793 {
802 at = find_archetype (coins[count]); 794 at = archetype::find (coins[count]);
803 795
804 if (at == NULL) 796 if (at == NULL)
805 LOG (llevError, "Could not find %s archetype\n", coins[count]); 797 LOG (llevError, "Could not find %s archetype\n", coins[count]);
806 else if ((amount / at->clone.value) > 0) 798 else if ((amount / at->clone.value) > 0)
807 { 799 {
843 } 835 }
844 } 836 }
845 } 837 }
846 838
847 if (amount != 0) 839 if (amount != 0)
848#ifndef WIN32
849 LOG (llevError, "Warning - payment in pay_player () not zero: %llu\n", amount); 840 LOG (llevError, "Warning - payment in pay_player () not zero: %llu\n", amount);
850#else
851 LOG (llevError, "Warning - payment in pay_player () not zero: %I64u\n", amount);
852#endif
853} 841}
854 842
855/* elmex: this is for the bank plugin :( */ 843/* elmex: this is for the bank plugin :( */
856sint64 844sint64
857pay_player_arch (object *pl, const char *arch, sint64 amount) 845pay_player_arch (object *pl, const char *arch, sint64 amount)
858{ 846{
859 archetype *at = find_archetype (arch); 847 archetype *at = archetype::find (arch);
860 object *tmp = NULL; 848 object *tmp = NULL;
861 849
862 if (at == NULL) 850 if (at == NULL)
863 return 0; 851 return 0;
864 852
934 * item based on the shops specialisation. Does not take account of greed, 922 * item based on the shops specialisation. Does not take account of greed,
935 * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any 923 * returned value is between (2*SPECIALISATION_EFFECT-1) and 1 and in any
936 * event is never less than 0.1 (calling functions divide by it) 924 * event is never less than 0.1 (calling functions divide by it)
937 */ 925 */
938static double 926static double
939shop_specialisation_ratio (const object *item, const mapstruct *map) 927shop_specialisation_ratio (const object *item, const maptile *map)
940{ 928{
941 shopitems *items = map->shopitems; 929 shopitems *items = map->shopitems;
942 double ratio = SPECIALISATION_EFFECT, likedness = 0.001; 930 double ratio = SPECIALISATION_EFFECT, likedness = 0.001;
943 int i; 931 int i;
944 932
985 return ratio; 973 return ratio;
986} 974}
987 975
988/*returns the greed of the shop on map, or 1 if it isn't specified. */ 976/*returns the greed of the shop on map, or 1 if it isn't specified. */
989static double 977static double
990shop_greed (const mapstruct *map) 978shop_greed (const maptile *map)
991{ 979{
992 double greed = 1.0; 980 double greed = 1.0;
993 981
994 if (map->shopgreed) 982 if (map->shopgreed)
995 return map->shopgreed; 983 return map->shopgreed;
998 986
999/* Returns a double based on how much the shopkeeper approves of the player. 987/* Returns a double based on how much the shopkeeper approves of the player.
1000 * this is based on the race of the shopkeeper and that of the player. 988 * this is based on the race of the shopkeeper and that of the player.
1001 */ 989 */
1002double 990double
1003shopkeeper_approval (const mapstruct *map, const object *player) 991shopkeeper_approval (const maptile *map, const object *player)
1004{ 992{
1005 double approval = 1.0; 993 double approval = 1.0;
1006 994
1007 if (map->shoprace) 995 if (map->shoprace)
1008 { 996 {
1023 */ 1011 */
1024static sint64 1012static sint64
1025value_limit (sint64 val, int quantity, const object *who, int isshop) 1013value_limit (sint64 val, int quantity, const object *who, int isshop)
1026{ 1014{
1027 sint64 newval, unit_price, tmpshopmax; 1015 sint64 newval, unit_price, tmpshopmax;
1028 mapstruct *map; 1016 maptile *map;
1029 1017
1030 unit_price = val / quantity; 1018 unit_price = val / quantity;
1031 1019
1032 if (!isshop || !who) 1020 if (!isshop || !who)
1033 { 1021 {
1063 1051
1064/* gives a desciption of the shop on their current map to the player op. */ 1052/* gives a desciption of the shop on their current map to the player op. */
1065int 1053int
1066describe_shop (const object *op) 1054describe_shop (const object *op)
1067{ 1055{
1068 mapstruct *map = op->map; 1056 maptile *map = op->map;
1069 1057
1070 /*shopitems *items=map->shopitems; */ 1058 /*shopitems *items=map->shopitems; */
1071 int pos = 0, i; 1059 int pos = 0, i;
1072 double opinion = 0; 1060 double opinion = 0;
1073 char tmp[MAX_BUF] = "\0"; 1061 char tmp[MAX_BUF] = "\0";
1187 case RING: 1175 case RING:
1188 case AMULET: 1176 case AMULET:
1189 case BRACERS: 1177 case BRACERS:
1190 case GIRDLE: 1178 case GIRDLE:
1191 sprintf (buf, "%s %s", query_base_name (tmp, 0), describe_item (tmp, NULL)); 1179 sprintf (buf, "%s %s", query_base_name (tmp, 0), describe_item (tmp, NULL));
1192 items[*numitems].item_sort = strdup_local (buf); 1180 items[*numitems].item_sort = strdup (buf);
1193 sprintf (buf, "%s %s", query_name (tmp), describe_item (tmp, NULL)); 1181 sprintf (buf, "%s %s", query_name (tmp), describe_item (tmp, NULL));
1194 items[*numitems].item_real = strdup_local (buf); 1182 items[*numitems].item_real = strdup (buf);
1195 (*numitems)++; 1183 (*numitems)++;
1196 break; 1184 break;
1197#endif 1185#endif
1198 1186
1199 default: 1187 default:
1200 items[*numitems].item_sort = strdup_local (query_base_name (tmp, 0)); 1188 items[*numitems].item_sort = strdup (query_base_name (tmp, 0));
1201 items[*numitems].item_real = strdup_local (query_base_name (tmp, 1)); 1189 items[*numitems].item_real = strdup (query_base_name (tmp, 1));
1202 (*numitems)++; 1190 (*numitems)++;
1203 break; 1191 break;
1204 } 1192 }
1205 SET_FLAG (tmp, FLAG_UNPAID); 1193 SET_FLAG (tmp, FLAG_UNPAID);
1206} 1194}
1299 return is_in_shop (o->map, o->x, o->y); 1287 return is_in_shop (o->map, o->x, o->y);
1300} 1288}
1301 1289
1302/* elmex: this function checks whether we are in a shop or not */ 1290/* elmex: this function checks whether we are in a shop or not */
1303bool 1291bool
1304is_in_shop (mapstruct *map, int x, int y) 1292is_in_shop (maptile *map, int x, int y)
1305{ 1293{
1306 for (object *floor = get_map_ob (map, x, y); floor; floor = floor->above) 1294 for (object *floor = get_map_ob (map, x, y); floor; floor = floor->above)
1307 if (floor->type == SHOP_FLOOR) 1295 if (floor->type == SHOP_FLOOR)
1308 return true; 1296 return true;
1309 1297

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines