PageRenderTime 128ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/crossfire-1.70.0/types/converter/converter.c

#
C | 178 lines | 103 code | 19 blank | 56 comment | 38 complexity | 9ca4368b50038f47e1afe64ab853f971 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. CrossFire, A Multiplayer game for X-windows
  3. Copyright (C) 2007 Mark Wedel & Crossfire Development Team
  4. Copyright (C) 1992 Frank Tore Johansen
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. The authors can be reached via e-mail at crossfire-devel@real-time.com
  17. */
  18. /** @file converter.c
  19. * The implementation of the Converter class of objects.
  20. */
  21. #include <global.h>
  22. #include <ob_methods.h>
  23. #include <ob_types.h>
  24. #include <sounds.h>
  25. #include <sproto.h>
  26. /*
  27. * convert_item() returns 1 if anything was converted, 0 if the item was not
  28. * what the converter wants, -1 if the converter is broken.
  29. */
  30. #define CONV_FROM(xyz) xyz->slaying
  31. #define CONV_TO(xyz) xyz->other_arch
  32. #define CONV_NR(xyz) (unsigned char)xyz->stats.sp
  33. #define CONV_NEED(xyz) (unsigned long)xyz->stats.food
  34. static int convert_item(object *item, object *converter);
  35. static method_ret converter_type_move_on(ob_methods *context, object *trap, object *victim, object *originator);
  36. /**
  37. * Initializer for the CONVERTER object type.
  38. */
  39. void init_type_converter(void) {
  40. register_move_on(CONVERTER, converter_type_move_on);
  41. }
  42. /**
  43. * Transforms an item into another item.
  44. * @param item The object that triggered the converter - if it isn't of a type
  45. * accepted by the converter, nothing will happen
  46. * @param converter The object that is doing the conversion
  47. * @retval -1 If something went wrong when attempting the conversion
  48. * @retval 0 If the item was not converted
  49. * @retval 1 If the item got converted
  50. */
  51. static int convert_item(object *item, object *converter) {
  52. int nr = 0;
  53. uint32 price_in;
  54. /* We make some assumptions - we assume if it takes money as it type,
  55. * it wants some amount. We don't make change (ie, if something costs
  56. * 3 gp and player drops a platinum, tough luck)
  57. */
  58. if (!strcmp(CONV_FROM(converter), "money")) {
  59. int cost;
  60. if (item->type != MONEY)
  61. return 0;
  62. nr = (item->nrof*item->value)/CONV_NEED(converter);
  63. if (!nr)
  64. return 0;
  65. cost = nr*CONV_NEED(converter)/item->value;
  66. /* take into account rounding errors */
  67. if (nr*CONV_NEED(converter)%item->value)
  68. cost++;
  69. object_decrease_nrof(item, cost);
  70. price_in = cost*item->value;
  71. } else {
  72. if (item->type == PLAYER
  73. || CONV_FROM(converter) != item->arch->name
  74. || (CONV_NEED(converter) && CONV_NEED(converter) > item->nrof))
  75. return 0;
  76. /* silently burn unpaid items (only if they match what we want) */
  77. if (QUERY_FLAG(item, FLAG_UNPAID)) {
  78. object_remove(item);
  79. object_free_drop_inventory(item);
  80. item = create_archetype("burnout");
  81. if (item != NULL)
  82. object_insert_in_map_at(item, converter->map, converter, 0, converter->x, converter->y);
  83. return 1;
  84. }
  85. if (CONV_NEED(converter)) {
  86. nr = item->nrof/CONV_NEED(converter);
  87. object_decrease_nrof(item, nr*CONV_NEED(converter));
  88. price_in = nr*CONV_NEED(converter)*item->value;
  89. } else {
  90. price_in = item->value;
  91. object_remove(item);
  92. object_free_drop_inventory(item);
  93. }
  94. }
  95. if (converter->inv != NULL) {
  96. int i;
  97. object *ob_to_copy;
  98. /* select random object from inventory to copy */
  99. ob_to_copy = converter->inv;
  100. i = 1;
  101. FOR_BELOW_PREPARE(converter->inv, ob) {
  102. if (rndm(0, i) == 0)
  103. ob_to_copy = ob;
  104. i++;
  105. } FOR_BELOW_FINISH();
  106. item = object_create_clone(ob_to_copy);
  107. CLEAR_FLAG(item, FLAG_IS_A_TEMPLATE);
  108. object_unset_flag_inv(item, FLAG_IS_A_TEMPLATE);
  109. } else {
  110. if (converter->other_arch == NULL) {
  111. 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);
  112. return -1;
  113. }
  114. item = object_create_arch(converter->other_arch);
  115. fix_generated_item(item, converter, 0, 0, GT_MINIMAL);
  116. }
  117. if (CONV_NR(converter))
  118. item->nrof = CONV_NR(converter);
  119. if (nr)
  120. item->nrof *= nr;
  121. if (item->type != MONEY && is_in_shop(converter))
  122. SET_FLAG(item, FLAG_UNPAID);
  123. else if (price_in < item->nrof*item->value && settings.allow_broken_converters == FALSE) {
  124. 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);
  125. object_free_drop_inventory(item);
  126. return -1;
  127. }
  128. object_insert_in_map_at(item, converter->map, converter, 0, converter->x, converter->y);
  129. return 1;
  130. }
  131. /**
  132. * Move on this Converter object.
  133. * @param context The method context
  134. * @param trap The Converter we're moving on
  135. * @param victim The object moving over this one
  136. * @param originator The object that caused the move_on event
  137. * @return METHOD_OK
  138. */
  139. static method_ret converter_type_move_on(ob_methods *context, object *trap, object *victim, object *originator) {
  140. if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR)
  141. return METHOD_OK;
  142. if (convert_item(victim, trap) < 0) {
  143. object *op;
  144. char name[MAX_BUF];
  145. query_name(trap, name, MAX_BUF);
  146. draw_ext_info_format(NDI_UNIQUE, 0, originator, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
  147. "The %s seems to be broken!", name);
  148. op = create_archetype("burnout");
  149. if (op != NULL)
  150. object_insert_in_map_at(op, trap->map, trap, 0, trap->x, trap->y);
  151. }
  152. common_post_ob_move_on(trap, victim, originator);
  153. return METHOD_OK;
  154. }