Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2007 Crossfire Development Team 00005 Copyright (C) 1992 Frank Tore Johansen 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 00021 The authors can be reached via e-mail at crossfire-devel@real-time.com 00022 */ 00023 00027 #include <global.h> 00028 #include <ob_methods.h> 00029 #include <ob_types.h> 00030 #include <sounds.h> 00031 #include <sproto.h> 00032 00033 static method_ret shop_inventory_type_apply(ob_methods *context, object *lighter, object *applier, int aflags); 00034 00038 void init_type_shop_inventory(void) { 00039 register_apply(SHOP_INVENTORY, shop_inventory_type_apply); 00040 } 00041 00045 typedef struct shopinv { 00046 char *item_sort; 00047 char *item_real; 00048 uint16 type; 00049 uint32 nrof; 00050 } shopinv; 00051 00065 static int shop_sort(const void *a1, const void *a2) { 00066 const shopinv *s1 = (const shopinv *)a1, *s2 = (const shopinv *)a2; 00067 00068 if (s1->type < s2->type) 00069 return -1; 00070 if (s1->type > s2->type) 00071 return 1; 00072 /* the type is the same (what atoi gets), so do a strcasecmp to sort 00073 * via alphabetical order 00074 */ 00075 return strcasecmp(s1->item_sort, s2->item_sort); 00076 } 00077 00087 static void add_shop_item(object *tmp, shopinv *items, size_t *numitems) { 00088 /* clear unpaid flag so that doesn't come up in query 00089 * string. We clear nrof so that we can better sort 00090 * the object names. 00091 */ 00092 char name[MAX_BUF]; 00093 00094 CLEAR_FLAG(tmp, FLAG_UNPAID); 00095 items[*numitems].nrof = tmp->nrof; 00096 /* Non mergable items have nrof of 0, but count them as one 00097 * so the display is properly. 00098 */ 00099 if (tmp->nrof == 0) 00100 items[*numitems].nrof++; 00101 items[*numitems].type = tmp->type; 00102 query_base_name(tmp, 0, name, MAX_BUF); 00103 items[*numitems].item_sort = strdup_local(name); 00104 query_base_name(tmp, 1, name, MAX_BUF); 00105 items[*numitems].item_real = strdup_local(name); 00106 (*numitems)++; 00107 00108 SET_FLAG(tmp, FLAG_UNPAID); 00109 } 00110 00125 static method_ret shop_inventory_type_apply(ob_methods *context, object *lighter, object *applier, int aflags) { 00126 size_t i, j, numitems = 0, numallocated = 0; 00127 object *stack; 00128 shopinv *items; 00129 00130 if (applier->type != PLAYER) 00131 return METHOD_UNHANDLED; 00132 00133 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING, 00134 "\nThe shop contains:", NULL); 00135 00136 items = malloc(40*sizeof(shopinv)); 00137 numallocated = 40; 00138 00139 /* Find all the appropriate items */ 00140 for (i = 0; i < MAP_WIDTH(applier->map); i++) { 00141 for (j = 0; j < MAP_HEIGHT(applier->map); j++) { 00142 stack = GET_MAP_OB(applier->map, i, j); 00143 00144 while (stack) { 00145 if (QUERY_FLAG(stack, FLAG_UNPAID)) { 00146 if (numitems == numallocated) { 00147 items = realloc(items, sizeof(shopinv)*(numallocated+10)); 00148 numallocated += 10; 00149 } 00150 add_shop_item(stack, items, &numitems); 00151 } 00152 stack = stack->above; 00153 } 00154 } 00155 } 00156 if (numitems == 0) { 00157 draw_ext_info(NDI_UNIQUE, 0, applier, MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING, 00158 "The shop is currently empty.\n", NULL); 00159 free(items); 00160 return METHOD_OK; 00161 } 00162 qsort(items, numitems, sizeof(shopinv), (int (*)(const void *, const void *))shop_sort); 00163 00164 for (i = 0; i < numitems; i++) { 00165 /* Collapse items of the same name together */ 00166 if ((i+1) < numitems && !strcmp(items[i].item_real, items[i+1].item_real)) { 00167 items[i+1].nrof += items[i].nrof; 00168 free(items[i].item_sort); 00169 free(items[i].item_real); 00170 } else { 00171 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_SHOP, MSG_TYPE_SHOP_LISTING, 00172 "%d %s", "%d %s", 00173 items[i].nrof ? items[i].nrof : 1, 00174 items[i].nrof == 1 ? items[i].item_sort : items[i].item_real); 00175 free(items[i].item_sort); 00176 free(items[i].item_real); 00177 } 00178 } 00179 free(items); 00180 return METHOD_OK; 00181 }