Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2007 Mark Wedel & 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 /* 00034 * convert_item() returns 1 if anything was converted, 0 if the item was not 00035 * what the converter wants, -1 if the converter is broken. 00036 */ 00037 #define CONV_FROM(xyz) xyz->slaying 00038 #define CONV_TO(xyz) xyz->other_arch 00039 #define CONV_NR(xyz) (unsigned char)xyz->stats.sp 00040 #define CONV_NEED(xyz) (unsigned long)xyz->stats.food 00041 00042 static int convert_item(object *item, object *converter); 00043 00044 static method_ret converter_type_move_on(ob_methods *context, object *trap, object *victim, object *originator); 00045 00049 void init_type_converter(void) { 00050 register_move_on(CONVERTER, converter_type_move_on); 00051 } 00052 00062 static int convert_item(object *item, object *converter) { 00063 int nr = 0; 00064 uint32 price_in; 00065 00066 /* We make some assumptions - we assume if it takes money as it type, 00067 * it wants some amount. We don't make change (ie, if something costs 00068 * 3 gp and player drops a platinum, tough luck) 00069 */ 00070 if (!strcmp(CONV_FROM(converter), "money")) { 00071 int cost; 00072 00073 if (item->type != MONEY) 00074 return 0; 00075 00076 nr = (item->nrof*item->value)/CONV_NEED(converter); 00077 if (!nr) 00078 return 0; 00079 00080 cost = nr*CONV_NEED(converter)/item->value; 00081 /* take into account rounding errors */ 00082 if (nr*CONV_NEED(converter)%item->value) 00083 cost++; 00084 decrease_ob_nr(item, cost); 00085 00086 price_in = cost*item->value; 00087 } else { 00088 if (item->type == PLAYER 00089 || CONV_FROM(converter) != item->arch->name 00090 || (CONV_NEED(converter) && CONV_NEED(converter) > item->nrof)) 00091 return 0; 00092 00093 /* silently burn unpaid items (only if they match what we want) */ 00094 if (QUERY_FLAG(item, FLAG_UNPAID)) { 00095 remove_ob(item); 00096 free_object(item); 00097 item = create_archetype("burnout"); 00098 if (item != NULL) 00099 insert_ob_in_map_at(item, converter->map, converter, 0, converter->x, converter->y); 00100 return 1; 00101 } 00102 00103 if (CONV_NEED(converter)) { 00104 nr = item->nrof/CONV_NEED(converter); 00105 decrease_ob_nr(item, nr*CONV_NEED(converter)); 00106 price_in = nr*CONV_NEED(converter)*item->value; 00107 } else { 00108 price_in = item->value; 00109 remove_ob(item); 00110 free_object(item); 00111 } 00112 } 00113 00114 if (converter->inv != NULL) { 00115 object *ob; 00116 int i; 00117 object *ob_to_copy; 00118 00119 /* select random object from inventory to copy */ 00120 ob_to_copy = converter->inv; 00121 for (ob = converter->inv->below, i = 1; ob != NULL; ob = ob->below, i++) { 00122 if (rndm(0, i) == 0) 00123 ob_to_copy = ob; 00124 } 00125 item = object_create_clone(ob_to_copy); 00126 CLEAR_FLAG(item, FLAG_IS_A_TEMPLATE); 00127 unflag_inv(item, FLAG_IS_A_TEMPLATE); 00128 } else { 00129 if (converter->other_arch == NULL) { 00130 LOG(llevError, "move_creator: Converter doesn't have other arch set: %s (%s, %d, %d)\n", converter->name ? converter->name : "(null)", converter->map->path, converter->x, converter->y); 00131 return -1; 00132 } 00133 item = object_create_arch(converter->other_arch); 00134 fix_generated_item(item, converter, 0, 0, GT_MINIMAL); 00135 } 00136 00137 if (CONV_NR(converter)) 00138 item->nrof = CONV_NR(converter); 00139 if (nr) 00140 item->nrof *= nr; 00141 if (is_in_shop(converter)) 00142 SET_FLAG(item, FLAG_UNPAID); 00143 else if (price_in < item->nrof*item->value && settings.allow_broken_converters == FALSE) { 00144 LOG(llevError, "Broken converter %s at %s (%d, %d) in value %d, out value %d for %s\n", converter->name, converter->map->path, converter->x, converter->y, price_in, item->nrof*item->value, item->name); 00145 free_object(item); 00146 return -1; 00147 } 00148 insert_ob_in_map_at(item, converter->map, converter, 0, converter->x, converter->y); 00149 return 1; 00150 } 00151 00160 static method_ret converter_type_move_on(ob_methods *context, object *trap, object *victim, object *originator) { 00161 if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR) 00162 return METHOD_OK; 00163 if (convert_item(victim, trap) < 0) { 00164 object *op; 00165 char name[MAX_BUF]; 00166 00167 query_name(trap, name, MAX_BUF); 00168 draw_ext_info_format(NDI_UNIQUE, 0, originator, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE, 00169 "The %s seems to be broken!", "The %s seems to be broken!", 00170 name); 00171 00172 op = create_archetype("burnout"); 00173 if (op != NULL) { 00174 op->x = trap->x; 00175 op->y = trap->y; 00176 insert_ob_in_map(op, trap->map, trap, 0); 00177 } 00178 } 00179 common_post_ob_move_on(trap, victim, originator); 00180 return METHOD_OK; 00181 }