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.14 by root, Tue Sep 12 19:20:08 2006 UTC vs.
Revision 1.28 by root, Sat Dec 30 10:16:11 2006 UTC

1
2/*
3 * static char *rcsid_shop_c =
4 * "$Id: shop.C,v 1.14 2006/09/12 19:20:08 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
334 325
335 do 326 do
336 { 327 {
337 if (coins[*cointype] == NULL) 328 if (coins[*cointype] == NULL)
338 return NULL; 329 return NULL;
339 coin = find_archetype (coins[*cointype]); 330 coin = archetype::find (coins[*cointype]);
340 if (coin == NULL) 331 if (coin == NULL)
341 return NULL; 332 return NULL;
342 *cointype += 1; 333 *cointype += 1;
343 } 334 }
344 while (coin->clone.value > c); 335 while (coin->clone.value > c);
511 502
512 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below) 503 for (pouch = pl->inv; pouch && to_pay; pouch = pouch->below)
513 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold"))) 504 if (pouch->type == CONTAINER && QUERY_FLAG (pouch, FLAG_APPLIED) && (pouch->race == NULL || strstr (pouch->race, "gold")))
514 pay_from_container (pl, pouch, to_pay); 505 pay_from_container (pl, pouch, to_pay);
515 506
516 fix_player (pl); 507 pl->update_stats ();
517 return 1; 508 return 1;
518} 509}
519 510
520/* DAMN: This is now a wrapper for pay_from_container, which is 511/* DAMN: This is now a wrapper for pay_from_container, which is
521 * called for the player, then for each active container that can hold 512 * called for the player, then for each active container that can hold
551 pay_from_container (pl, pouch, to_pay); 542 pay_from_container (pl, pouch, to_pay);
552 543
553 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) 544 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ))
554 SET_FLAG (op, FLAG_WAS_WIZ); 545 SET_FLAG (op, FLAG_WAS_WIZ);
555 546
556 fix_player (pl); 547 pl->update_stats ();
557 return 1; 548 return 1;
558} 549}
559 550
560/* This pays for the item, and takes the proper amount of money off 551/* This pays for the item, and takes the proper amount of money off
561 * the player. 552 * the player.
596 { 587 {
597 // 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.
598 if (coin_objs [i]) 589 if (coin_objs [i])
599 { 590 {
600 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]);
601 remove_ob (tmp); 592 tmp->remove ();
602 coin_objs[i]->nrof += tmp->nrof; 593 coin_objs[i]->nrof += tmp->nrof;
603 esrv_del_item (pl->contr, tmp->count); 594 esrv_del_item (pl->contr, tmp->count);
604 free_object (tmp); 595 tmp->destroy ();
605 } 596 }
606 else 597 else
607 { 598 {
608 remove_ob (tmp); 599 tmp->remove ();
609 600
610 if (pouch->type == PLAYER) 601 if (pouch->type == PLAYER)
611 esrv_del_item (pl->contr, tmp->count); 602 esrv_del_item (pl->contr, tmp->count);
612 603
613 coin_objs[i] = tmp; 604 coin_objs[i] = tmp;
625 /* 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. */
626 /* 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 */
627 for (i = 0; i < NUM_COINS; i++) 618 for (i = 0; i < NUM_COINS; i++)
628 if (!coin_objs[i]) 619 if (!coin_objs[i])
629 { 620 {
630 at = find_archetype (coins[NUM_COINS - 1 - i]); 621 at = archetype::find (coins[NUM_COINS - 1 - i]);
631 622
632 if (at == NULL) 623 if (at == NULL)
633 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]);
634 625
635 coin_objs[i] = arch_to_object (at); 626 coin_objs[i] = arch_to_object (at);
672 663
673 if (pl->type != PLAYER) 664 if (pl->type != PLAYER)
674 esrv_send_item (pl, pl); 665 esrv_send_item (pl, pl);
675 } 666 }
676 else 667 else
677 free_object (coin_objs[i]); 668 coin_objs[i]->destroy ();
678 } 669 }
679} 670}
680 671
681/* 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
682 * 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.
687can_pay (object *pl) 678can_pay (object *pl)
688{ 679{
689 int unpaid_count = 0; 680 int unpaid_count = 0;
690 sint64 unpaid_price = 0; 681 sint64 unpaid_price = 0;
691 sint64 player_wealth = query_money (pl); 682 sint64 player_wealth = query_money (pl);
692 object *item;
693 683
694 if (!pl || pl->type != PLAYER) 684 if (!pl || pl->type != PLAYER)
695 { 685 {
696 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");
697 return 0; 687 return 0;
753 return 0; 743 return 0;
754 } 744 }
755 else 745 else
756 { 746 {
757 object *tmp; 747 object *tmp;
758 tag_t c = op->count;
759 748
760 CLEAR_FLAG (op, FLAG_UNPAID); 749 CLEAR_FLAG (op, FLAG_UNPAID);
761 CLEAR_FLAG (op, FLAG_PLAYER_SOLD); 750 CLEAR_FLAG (op, FLAG_PLAYER_SOLD);
762 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));
763 tmp = merge_ob (op, NULL); 752 tmp = merge_ob (op, NULL);
764 753
765 if (pl->type == PLAYER) 754 if (pl->type == PLAYER)
766 { 755 {
767 if (tmp) 756 if (tmp)
768 { /* it was merged */ 757 { /* it was merged */
769 esrv_del_item (pl->contr, c); 758 esrv_del_item (pl->contr, op->count);
770 op = tmp; 759 op = tmp;
771 } 760 }
772 761
773 esrv_send_item (pl, op); 762 esrv_send_item (pl, op);
774 } 763 }
800 archetype *at = 0; 789 archetype *at = 0;
801 object *pouch = 0, *tmp = 0; 790 object *pouch = 0, *tmp = 0;
802 791
803 for (count = 0; coins[count] != NULL; count++) 792 for (count = 0; coins[count] != NULL; count++)
804 { 793 {
805 at = find_archetype (coins[count]); 794 at = archetype::find (coins[count]);
806 795
807 if (at == NULL) 796 if (at == NULL)
808 LOG (llevError, "Could not find %s archetype\n", coins[count]); 797 LOG (llevError, "Could not find %s archetype\n", coins[count]);
809 else if ((amount / at->clone.value) > 0) 798 else if ((amount / at->clone.value) > 0)
810 { 799 {
846 } 835 }
847 } 836 }
848 } 837 }
849 838
850 if (amount != 0) 839 if (amount != 0)
851#ifndef WIN32
852 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);
853#else
854 LOG (llevError, "Warning - payment in pay_player () not zero: %I64u\n", amount);
855#endif
856} 841}
857 842
858/* elmex: this is for the bank plugin :( */ 843/* elmex: this is for the bank plugin :( */
859sint64 844sint64
860pay_player_arch (object *pl, const char *arch, sint64 amount) 845pay_player_arch (object *pl, const char *arch, sint64 amount)
861{ 846{
862 archetype *at = find_archetype (arch); 847 archetype *at = archetype::find (arch);
863 object *tmp = NULL; 848 object *tmp = NULL;
864 849
865 if (at == NULL) 850 if (at == NULL)
866 return 0; 851 return 0;
867 852
937 * 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,
938 * 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
939 * 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)
940 */ 925 */
941static double 926static double
942shop_specialisation_ratio (const object *item, const mapstruct *map) 927shop_specialisation_ratio (const object *item, const maptile *map)
943{ 928{
944 shopitems *items = map->shopitems; 929 shopitems *items = map->shopitems;
945 double ratio = SPECIALISATION_EFFECT, likedness = 0.001; 930 double ratio = SPECIALISATION_EFFECT, likedness = 0.001;
946 int i; 931 int i;
947 932
948 if (item == NULL) 933 if (item == NULL)
949 { 934 {
950 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", map->path); 935 LOG (llevError, "shop_specialisation_ratio: passed a NULL item for map %s\n", &map->path);
951 return 0; 936 return 0;
952 } 937 }
953 938
954 if (!item->type) 939 if (!item->type)
955 { 940 {
968 likedness = items[i].strength / 100.0; 953 likedness = items[i].strength / 100.0;
969 } 954 }
970 955
971 if (likedness > 1.0) 956 if (likedness > 1.0)
972 { /* someone has been rather silly with the map headers. */ 957 { /* someone has been rather silly with the map headers. */
973 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, map->path); 958 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is above 100%%\n", item->type, &map->path);
974 likedness = 1.0; 959 likedness = 1.0;
975 } 960 }
976 961
977 if (likedness < -1.0) 962 if (likedness < -1.0)
978 { 963 {
979 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, map->path); 964 LOG (llevDebug, "shop_specialisation ratio: item type %d on map %s is below -100%%\n", item->type, &map->path);
980 likedness = -1.0; 965 likedness = -1.0;
981 } 966 }
982 967
983 ratio = ratio + (1.0 - ratio) * likedness; 968 ratio = ratio + (1.0 - ratio) * likedness;
984 969
988 return ratio; 973 return ratio;
989} 974}
990 975
991/*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. */
992static double 977static double
993shop_greed (const mapstruct *map) 978shop_greed (const maptile *map)
994{ 979{
995 double greed = 1.0; 980 double greed = 1.0;
996 981
997 if (map->shopgreed) 982 if (map->shopgreed)
998 return map->shopgreed; 983 return map->shopgreed;
1001 986
1002/* 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.
1003 * 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.
1004 */ 989 */
1005double 990double
1006shopkeeper_approval (const mapstruct *map, const object *player) 991shopkeeper_approval (const maptile *map, const object *player)
1007{ 992{
1008 double approval = 1.0; 993 double approval = 1.0;
1009 994
1010 if (map->shoprace) 995 if (map->shoprace)
1011 { 996 {
1026 */ 1011 */
1027static sint64 1012static sint64
1028value_limit (sint64 val, int quantity, const object *who, int isshop) 1013value_limit (sint64 val, int quantity, const object *who, int isshop)
1029{ 1014{
1030 sint64 newval, unit_price, tmpshopmax; 1015 sint64 newval, unit_price, tmpshopmax;
1031 mapstruct *map; 1016 maptile *map;
1032 1017
1033 unit_price = val / quantity; 1018 unit_price = val / quantity;
1034 1019
1035 if (!isshop || !who) 1020 if (!isshop || !who)
1036 { 1021 {
1066 1051
1067/* 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. */
1068int 1053int
1069describe_shop (const object *op) 1054describe_shop (const object *op)
1070{ 1055{
1071 mapstruct *map = op->map; 1056 maptile *map = op->map;
1072 1057
1073 /*shopitems *items=map->shopitems; */ 1058 /*shopitems *items=map->shopitems; */
1074 int pos = 0, i; 1059 int pos = 0, i;
1075 double opinion = 0; 1060 double opinion = 0;
1076 char tmp[MAX_BUF] = "\0"; 1061 char tmp[MAX_BUF] = "\0";
1190 case RING: 1175 case RING:
1191 case AMULET: 1176 case AMULET:
1192 case BRACERS: 1177 case BRACERS:
1193 case GIRDLE: 1178 case GIRDLE:
1194 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));
1195 items[*numitems].item_sort = strdup_local (buf); 1180 items[*numitems].item_sort = strdup (buf);
1196 sprintf (buf, "%s %s", query_name (tmp), describe_item (tmp, NULL)); 1181 sprintf (buf, "%s %s", query_name (tmp), describe_item (tmp, NULL));
1197 items[*numitems].item_real = strdup_local (buf); 1182 items[*numitems].item_real = strdup (buf);
1198 (*numitems)++; 1183 (*numitems)++;
1199 break; 1184 break;
1200#endif 1185#endif
1201 1186
1202 default: 1187 default:
1203 items[*numitems].item_sort = strdup_local (query_base_name (tmp, 0)); 1188 items[*numitems].item_sort = strdup (query_base_name (tmp, 0));
1204 items[*numitems].item_real = strdup_local (query_base_name (tmp, 1)); 1189 items[*numitems].item_real = strdup (query_base_name (tmp, 1));
1205 (*numitems)++; 1190 (*numitems)++;
1206 break; 1191 break;
1207 } 1192 }
1208 SET_FLAG (tmp, FLAG_UNPAID); 1193 SET_FLAG (tmp, FLAG_UNPAID);
1209} 1194}
1225 magic_mapping_mark (op, map_mark, 3); 1210 magic_mapping_mark (op, map_mark, 3);
1226 items = (shopinv *) malloc (40 * sizeof (shopinv)); 1211 items = (shopinv *) malloc (40 * sizeof (shopinv));
1227 numallocated = 40; 1212 numallocated = 40;
1228 1213
1229 /* Find all the appropriate items */ 1214 /* Find all the appropriate items */
1230 for (i = 0; i < MAP_WIDTH (op->map); i++) 1215 for (i = 0; i < op->map->width; i++)
1231 { 1216 {
1232 for (j = 0; j < MAP_HEIGHT (op->map); j++) 1217 for (j = 0; j < op->map->height; j++)
1233 { 1218 {
1234 /* magic map code now centers the map on the object at MAGIC_MAP_HALF. 1219 /* magic map code now centers the map on the object at MAGIC_MAP_HALF.
1235 * 1220 *
1236 */ 1221 */
1237 nx = i - op->x + MAGIC_MAP_HALF; 1222 nx = i - op->x + MAGIC_MAP_HALF;
1240 if (nx < 0 || ny < 0 || nx > MAGIC_MAP_SIZE || ny > MAGIC_MAP_SIZE) 1225 if (nx < 0 || ny < 0 || nx > MAGIC_MAP_SIZE || ny > MAGIC_MAP_SIZE)
1241 continue; 1226 continue;
1242 1227
1243 if (map_mark[nx + MAGIC_MAP_SIZE * ny] & FACE_FLOOR) 1228 if (map_mark[nx + MAGIC_MAP_SIZE * ny] & FACE_FLOOR)
1244 { 1229 {
1245 stack = get_map_ob (op->map, i, j); 1230 stack = GET_MAP_OB (op->map, i, j);
1246 1231
1247 while (stack) 1232 while (stack)
1248 { 1233 {
1249 if (QUERY_FLAG (stack, FLAG_UNPAID)) 1234 if (QUERY_FLAG (stack, FLAG_UNPAID))
1250 { 1235 {
1302 return is_in_shop (o->map, o->x, o->y); 1287 return is_in_shop (o->map, o->x, o->y);
1303} 1288}
1304 1289
1305/* 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 */
1306bool 1291bool
1307is_in_shop (mapstruct *map, int x, int y) 1292is_in_shop (maptile *map, int x, int y)
1308{ 1293{
1309 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)
1310 if (floor->type == SHOP_FLOOR) 1295 if (floor->type == SHOP_FLOOR)
1311 return true; 1296 return true;
1312 1297
1313 return false; 1298 return false;
1314} 1299}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines