1 | /* |
1 | /* |
2 | * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
3 | * |
3 | * |
4 | * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team |
4 | * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Crossfire TRT is free software: you can redistribute it and/or modify |
8 | * Deliantra is free software: you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation, either version 3 of the License, or |
10 | * the Free Software Foundation, either version 3 of the License, or |
11 | * (at your option) any later version. |
11 | * (at your option) any later version. |
12 | * |
12 | * |
13 | * This program is distributed in the hope that it will be useful, |
13 | * This program is distributed in the hope that it will be useful, |
… | |
… | |
16 | * GNU General Public License for more details. |
16 | * GNU General Public License for more details. |
17 | * |
17 | * |
18 | * You should have received a copy of the GNU General Public License |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | * |
20 | * |
21 | * The authors can be reached via e-mail to <crossfire@schmorp.de> |
21 | * The authors can be reached via e-mail to <support@deliantra.net> |
22 | */ |
22 | */ |
23 | |
23 | |
24 | #include <cmath> |
24 | #include <cmath> |
25 | |
25 | |
26 | #include <global.h> |
26 | #include <global.h> |
… | |
… | |
836 | if (armour->magic >= settings.armor_max_enchant) |
836 | if (armour->magic >= settings.armor_max_enchant) |
837 | { |
837 | { |
838 | op->failmsg ("This armour can not be enchanted any further!"); |
838 | op->failmsg ("This armour can not be enchanted any further!"); |
839 | return 0; |
839 | return 0; |
840 | } |
840 | } |
|
|
841 | |
841 | /* Dealing with random artifact armor is a lot trickier (in terms of value, weight, |
842 | /* Dealing with random artifact armor is a lot trickier (in terms of value, weight, |
842 | * etc), so take the easy way out and don't worry about it. |
843 | * etc), so take the easy way out and don't worry about it. |
843 | * Note - maybe add scrolls which make the random artifact versions (eg, armour |
844 | * Note - maybe add scrolls which make the random artifact versions (eg, armour |
844 | * of gnarg and what not?) |
845 | * of gnarg and what not?) |
845 | */ |
846 | */ |
… | |
… | |
847 | { |
848 | { |
848 | op->failmsg ("This armour will not accept further enchantment."); |
849 | op->failmsg ("This armour will not accept further enchantment."); |
849 | return 0; |
850 | return 0; |
850 | } |
851 | } |
851 | |
852 | |
852 | /* Split objects if needed. Can't insert tmp until the |
853 | /* Split objects if needed. Can't insert tmp until the |
853 | * end of this function - otherwise it will just re-merge. |
854 | * end of this function - otherwise it will just re-merge. |
854 | */ |
855 | */ |
855 | if (armour->nrof > 1) |
856 | if (armour->nrof > 1) |
856 | tmp = get_split_ob (armour, armour->nrof - 1); |
857 | tmp = get_split_ob (armour, armour->nrof - 1); |
857 | else |
858 | else |
… | |
… | |
918 | } |
919 | } |
919 | |
920 | |
920 | /* |
921 | /* |
921 | * convert_item() returns 1 if anything was converted, 0 if the item was not |
922 | * convert_item() returns 1 if anything was converted, 0 if the item was not |
922 | * what the converter wants, -1 if the converter is broken. |
923 | * what the converter wants, -1 if the converter is broken. |
923 | */ |
924 | * |
924 | #define CONV_FROM(xyz) xyz->slaying |
|
|
925 | #define CONV_TO(xyz) xyz->other_arch |
|
|
926 | #define CONV_NR(xyz) xyz->stats.sp |
|
|
927 | #define CONV_NEED(xyz) xyz->stats.food |
|
|
928 | |
|
|
929 | /* Takes one items and makes another. |
925 | * Takes one type of items and makes another. |
930 | * converter is the object that is doing the conversion. |
926 | * converter is the object that is doing the conversion. |
931 | * item is the object that triggered the converter - if it is not |
927 | * item is the object that triggered the converter - if it is not |
932 | * what the converter wants, this will not do anything. |
928 | * what the converter wants, this will not do anything. |
933 | */ |
929 | */ |
934 | int |
930 | static int |
935 | convert_item (object *item, object *converter) |
931 | convert_item (object *item, object *converter) |
936 | { |
932 | { |
937 | int nr = 0; |
|
|
938 | uint32 price_in; |
933 | sint64 nr, price_in; |
|
|
934 | |
|
|
935 | if (item->flag [FLAG_UNPAID]) |
|
|
936 | return 0; |
|
|
937 | |
|
|
938 | shstr conv_from = converter->slaying; |
|
|
939 | archetype *conv_to = converter->other_arch; |
|
|
940 | sint64 need = converter->stats.food; |
|
|
941 | sint64 give = converter->stats.sp; |
939 | |
942 | |
940 | /* We make some assumptions - we assume if it takes money as it type, |
943 | /* We make some assumptions - we assume if it takes money as it type, |
941 | * it wants some amount. We don't make change (ie, if something costs |
944 | * it wants some amount. We don't make change (ie, if something costs |
942 | * 3 gp and player drops a platinum, tough luck) |
945 | * 3 gp and player drops a platinum, tough luck) |
943 | */ |
946 | */ |
944 | if (CONV_FROM (converter) == shstr_money) |
947 | if (conv_from == shstr_money) |
945 | { |
948 | { |
946 | if (item->type != MONEY) |
949 | if (item->type != MONEY) |
947 | return 0; |
950 | return 0; |
948 | |
951 | |
949 | nr = (item->nrof * item->value) / CONV_NEED (converter); |
952 | nr = sint64 (item->nrof) * item->value / need; |
950 | if (!nr) |
953 | if (!nr) |
951 | return 0; |
954 | return 0; |
952 | |
955 | |
953 | converter->play_sound (sound_find ("shop_buy")); |
956 | converter->play_sound (sound_find ("shop_buy")); |
954 | |
957 | |
955 | int cost = nr * CONV_NEED (converter) / item->value; |
958 | sint64 cost = (nr * need + item->value - 1) / item->value; |
956 | /* take into account rounding errors */ |
|
|
957 | if (nr * CONV_NEED (converter) % item->value) |
|
|
958 | cost++; |
|
|
959 | |
959 | |
960 | decrease_ob_nr (item, cost); |
960 | decrease_ob_nr (item, cost); |
961 | |
961 | |
962 | price_in = cost * item->value; |
962 | price_in = cost * item->value; |
963 | } |
963 | } |
964 | else |
964 | else |
965 | { |
965 | { |
966 | if (item->type == PLAYER || CONV_FROM (converter) != item->arch->archname || |
966 | if (item->type == PLAYER |
967 | (CONV_NEED (converter) && CONV_NEED (converter) > (uint16) item->nrof)) |
967 | || conv_from != item->arch->archname |
|
|
968 | || (need && need > (uint16) item->nrof)) |
968 | return 0; |
969 | return 0; |
969 | |
970 | |
970 | converter->play_sound (sound_find ("convert_item")); |
971 | converter->play_sound (sound_find ("convert_item")); |
971 | |
972 | |
972 | if (CONV_NEED (converter)) |
973 | if (need) |
973 | { |
974 | { |
974 | nr = item->nrof / CONV_NEED (converter); |
975 | nr = sint64 (item->nrof) / need; |
975 | decrease_ob_nr (item, nr * CONV_NEED (converter)); |
976 | decrease_ob_nr (item, nr * need); |
976 | price_in = nr * CONV_NEED (converter) * item->value; |
977 | price_in = nr * need * item->value; |
977 | } |
978 | } |
978 | else |
979 | else |
979 | { |
980 | { |
980 | price_in = item->value; |
981 | price_in = item->value; |
981 | item->destroy (); |
982 | item->destroy (); |
… | |
… | |
998 | CLEAR_FLAG (item, FLAG_IS_A_TEMPLATE); |
999 | CLEAR_FLAG (item, FLAG_IS_A_TEMPLATE); |
999 | unflag_inv (item, FLAG_IS_A_TEMPLATE); |
1000 | unflag_inv (item, FLAG_IS_A_TEMPLATE); |
1000 | } |
1001 | } |
1001 | else |
1002 | else |
1002 | { |
1003 | { |
1003 | if (converter->other_arch == NULL) |
1004 | if (!conv_to) |
1004 | { |
1005 | { |
1005 | LOG (llevError, "move_creator: Converter doesn't have other arch set: %s (%s, %d, %d)\n", |
1006 | LOG (llevError, "move_creator: Converter doesn't have other arch set: %s (%s, %d, %d)\n", |
1006 | &converter->name, &converter->map->path, converter->x, converter->y); |
1007 | &converter->name, &converter->map->path, converter->x, converter->y); |
1007 | return -1; |
1008 | return -1; |
1008 | } |
1009 | } |
1009 | |
1010 | |
1010 | item = object_create_arch (converter->other_arch); |
1011 | item = object_create_arch (conv_to); |
1011 | fix_generated_item (item, converter, 0, 0, GT_MINIMAL); |
1012 | fix_generated_item (item, converter, 0, 0, GT_MINIMAL); |
1012 | } |
1013 | } |
1013 | |
1014 | |
1014 | if (CONV_NR (converter)) |
1015 | if (give) |
1015 | item->nrof = CONV_NR (converter); |
1016 | item->nrof = give; |
1016 | |
1017 | |
1017 | if (nr) |
1018 | if (nr) |
1018 | item->nrof *= nr; |
1019 | item->nrof *= nr; |
1019 | |
1020 | |
1020 | if (is_in_shop (converter)) |
1021 | if (is_in_shop (converter)) |
1021 | SET_FLAG (item, FLAG_UNPAID); |
1022 | SET_FLAG (item, FLAG_UNPAID); |
1022 | else if (price_in < item->nrof * item->value) |
1023 | else if (price_in < sint64 (item->nrof) * item->value) |
1023 | { |
1024 | { |
1024 | LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", |
1025 | LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", |
1025 | &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); |
1026 | &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); |
1026 | /** |
1027 | /** |
1027 | * elmex: we are going to let the game continue, as the mapcreator |
1028 | * elmex: we are going to let the game continue, as the mapcreator |
… | |
… | |
1312 | } |
1313 | } |
1313 | |
1314 | |
1314 | if (op->contr) |
1315 | if (op->contr) |
1315 | if (client *ns = op->contr->ns) |
1316 | if (client *ns = op->contr->ns) |
1316 | { |
1317 | { |
|
|
1318 | if (sign->sound) |
1317 | ns->play_sound (sign->sound); |
1319 | ns->play_sound (sign->sound); |
|
|
1320 | else if (autoapply) |
|
|
1321 | ns->play_sound (sound_find ("msg_voice")); |
1318 | |
1322 | |
1319 | if (ns->can_msg) |
1323 | if (ns->can_msg) |
1320 | op->contr->infobox (MSG_CHANNEL ("examine"), format ("T<%s>\n\n\n\n%s", &sign->name, &sign->msg)); |
1324 | op->contr->infobox (MSG_CHANNEL ("examine"), format ("T<%s>\n\n\n\n%s", &sign->name, &sign->msg)); |
1321 | else |
1325 | else |
1322 | { |
1326 | { |
… | |
… | |
2604 | if (op->env && (pl->move_type & MOVE_FLYING)) |
2608 | if (op->env && (pl->move_type & MOVE_FLYING)) |
2605 | { |
2609 | { |
2606 | /* player is flying and applying object not in inventory */ |
2610 | /* player is flying and applying object not in inventory */ |
2607 | if (!QUERY_FLAG (pl, FLAG_WIZ) && !(op->move_type & MOVE_FLYING)) |
2611 | if (!QUERY_FLAG (pl, FLAG_WIZ) && !(op->move_type & MOVE_FLYING)) |
2608 | { |
2612 | { |
2609 | op->failmsg ("But you are floating high above the ground! H<You have to stop levitating first, if you can.>"); |
2613 | pl->failmsg ("But you are floating high above the ground! H<You have to stop levitating first, if you can.>"); |
2610 | return 0; |
2614 | return 0; |
2611 | } |
2615 | } |
2612 | } |
2616 | } |
2613 | |
2617 | |
2614 | pl->contr->last_used = op; |
2618 | pl->contr->last_used = op; |
2615 | |
2619 | |
2616 | tmp = manual_apply (pl, op, aflag); |
2620 | tmp = manual_apply (pl, op, aflag); |
2617 | if (!quiet) |
2621 | if (!quiet) |
2618 | { |
2622 | { |
2619 | if (tmp == 0) |
2623 | if (tmp == 0) |
2620 | op->statusmsg (format ("I don't know how to apply the %s.", query_name (op))); |
2624 | pl->statusmsg (format ("I don't know how to apply the %s.", query_name (op))); |
2621 | else if (tmp == 2) |
2625 | else if (tmp == 2) |
2622 | op->failmsg ("You must get it first!\n"); |
2626 | pl->failmsg ("You must get it first!\n"); |
2623 | } |
2627 | } |
2624 | |
2628 | |
2625 | return tmp; |
2629 | return tmp; |
2626 | } |
2630 | } |
2627 | |
2631 | |