1 | /* |
1 | /* |
2 | * CrossFire, A Multiplayer game |
2 | * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. |
3 | * |
3 | * |
4 | * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
4 | * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team |
5 | * Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team |
6 | * Copyright (C) 1992 Frank Tore Johansen |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
7 | * |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
8 | * Crossfire TRT 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 2 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, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
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, write to the Free Software |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|
|
21 | * |
20 | * |
22 | * The authors can be reached via e-mail to <crossfire@schmorp.de> |
21 | * The authors can be reached via e-mail to <crossfire@schmorp.de> |
23 | */ |
22 | */ |
24 | |
23 | |
25 | #include <cmath> |
24 | #include <cmath> |
26 | |
25 | |
… | |
… | |
69 | |
68 | |
70 | /* If the director has race set, only affect objects with a arch, |
69 | /* If the director has race set, only affect objects with a arch, |
71 | * name or race that matches. |
70 | * name or race that matches. |
72 | */ |
71 | */ |
73 | if ((op->race) && |
72 | if ((op->race) && |
74 | ((!(victim->arch && arch_flag && victim->arch->name) || op->race != victim->arch->name)) && |
73 | ((!(victim->arch && arch_flag && victim->arch->archname) || op->race != victim->arch->archname)) && |
75 | ((!(victim->name && name_flag) || op->race != victim->name)) && |
74 | ((!(victim->name && name_flag) || op->race != victim->name)) && |
76 | ((!(victim->race && race_flag) || op->race != victim->race))) |
75 | ((!(victim->race && race_flag) || op->race != victim->race))) |
77 | return 1; |
76 | return 1; |
78 | |
77 | |
79 | /* If the director has slaying set, only affect objects where none |
78 | /* If the director has slaying set, only affect objects where none |
80 | * of arch, name, or race match. |
79 | * of arch, name, or race match. |
81 | */ |
80 | */ |
82 | if ((op->slaying) && (((victim->arch && arch_flag && victim->arch->name && op->slaying == victim->arch->name))) || |
81 | if ((op->slaying) && (((victim->arch && arch_flag && victim->arch->archname && op->slaying == victim->arch->archname))) || |
83 | ((victim->name && name_flag && op->slaying == victim->name)) || |
82 | ((victim->name && name_flag && op->slaying == victim->name)) || |
84 | ((victim->race && race_flag && op->slaying == victim->race))) |
83 | ((victim->race && race_flag && op->slaying == victim->race))) |
85 | return 1; |
84 | return 1; |
86 | |
85 | |
87 | return 0; |
86 | return 0; |
… | |
… | |
425 | return 0; |
424 | return 0; |
426 | |
425 | |
427 | op = op->below; |
426 | op = op->below; |
428 | while (op != NULL) |
427 | while (op != NULL) |
429 | { |
428 | { |
430 | if (strcmp (op->arch->name, item) == 0) |
429 | if (strcmp (op->arch->archname, item) == 0) |
431 | { |
430 | { |
432 | if (!QUERY_FLAG (op, FLAG_CURSED) && !QUERY_FLAG (op, FLAG_DAMNED) |
431 | if (!QUERY_FLAG (op, FLAG_CURSED) && !QUERY_FLAG (op, FLAG_DAMNED) |
433 | /* Loophole bug? -FD- */ && !QUERY_FLAG (op, FLAG_UNPAID)) |
432 | /* Loophole bug? -FD- */ && !QUERY_FLAG (op, FLAG_UNPAID)) |
434 | { |
433 | { |
435 | if (op->nrof == 0) /* this is necessary for artifact sacrifices --FD-- */ |
434 | if (op->nrof == 0) /* this is necessary for artifact sacrifices --FD-- */ |
… | |
… | |
459 | prev = op; |
458 | prev = op; |
460 | op = op->below; |
459 | op = op->below; |
461 | |
460 | |
462 | while (op != NULL) |
461 | while (op != NULL) |
463 | { |
462 | { |
464 | if (strcmp (op->arch->name, item) == 0) |
463 | if (strcmp (op->arch->archname, item) == 0) |
465 | { |
464 | { |
466 | if (op->nrof >= nrof) |
465 | if (op->nrof >= nrof) |
467 | { |
466 | { |
468 | decrease_ob_nr (op, nrof); |
467 | decrease_ob_nr (op, nrof); |
469 | return; |
468 | return; |
… | |
… | |
855 | { |
854 | { |
856 | base = base - (base * settings.armor_speed_improvement) / 100; |
855 | base = base - (base * settings.armor_speed_improvement) / 100; |
857 | pow++; |
856 | pow++; |
858 | } |
857 | } |
859 | |
858 | |
860 | ARMOUR_SPEED (armour) = (ARMOUR_SPEED (&armour->arch->clone) * base) / 100; |
859 | ARMOUR_SPEED (armour) = (ARMOUR_SPEED (armour->arch) * base) / 100; |
861 | } |
860 | } |
862 | else |
861 | else |
863 | ARMOUR_SPEED (armour) = (ARMOUR_SPEED (&armour->arch->clone) * (100 + armour->magic * settings.armor_speed_improvement)) / 100; |
862 | ARMOUR_SPEED (armour) = (ARMOUR_SPEED (armour->arch) * (100 + armour->magic * settings.armor_speed_improvement)) / 100; |
864 | |
863 | |
865 | if (!settings.armor_weight_linear) |
864 | if (!settings.armor_weight_linear) |
866 | { |
865 | { |
867 | int base = 100; |
866 | int base = 100; |
868 | int pow = 0; |
867 | int pow = 0; |
… | |
… | |
871 | { |
870 | { |
872 | base = base - (base * settings.armor_weight_reduction) / 100; |
871 | base = base - (base * settings.armor_weight_reduction) / 100; |
873 | pow++; |
872 | pow++; |
874 | } |
873 | } |
875 | |
874 | |
876 | armour->weight = (armour->arch->clone.weight * base) / 100; |
875 | armour->weight = (armour->arch->weight * base) / 100; |
877 | } |
876 | } |
878 | else |
877 | else |
879 | armour->weight = (armour->arch->clone.weight * (100 - armour->magic * settings.armor_weight_reduction)) / 100; |
878 | armour->weight = (armour->arch->weight * (100 - armour->magic * settings.armor_weight_reduction)) / 100; |
880 | |
879 | |
881 | if (armour->weight <= 0) |
880 | if (armour->weight <= 0) |
882 | { |
881 | { |
883 | LOG (llevInfo, "Warning: enchanted armours can have negative weight\n."); |
882 | LOG (llevInfo, "Warning: enchanted armours can have negative weight\n."); |
884 | armour->weight = 1; |
883 | armour->weight = 1; |
885 | } |
884 | } |
886 | |
885 | |
887 | armour->item_power = get_power_from_ench (armour->arch->clone.item_power + armour->magic); |
886 | armour->item_power = get_power_from_ench (armour->arch->item_power + armour->magic); |
888 | |
887 | |
889 | if (op->type == PLAYER) |
888 | if (op->type == PLAYER) |
890 | { |
889 | { |
891 | esrv_send_item (op, armour); |
890 | esrv_send_item (op, armour); |
892 | if (QUERY_FLAG (armour, FLAG_APPLIED)) |
891 | if (QUERY_FLAG (armour, FLAG_APPLIED)) |
… | |
… | |
944 | |
943 | |
945 | price_in = cost * item->value; |
944 | price_in = cost * item->value; |
946 | } |
945 | } |
947 | else |
946 | else |
948 | { |
947 | { |
949 | if (item->type == PLAYER || CONV_FROM (converter) != item->arch->name || |
948 | if (item->type == PLAYER || CONV_FROM (converter) != item->arch->archname || |
950 | (CONV_NEED (converter) && CONV_NEED (converter) > (uint16) item->nrof)) |
949 | (CONV_NEED (converter) && CONV_NEED (converter) > (uint16) item->nrof)) |
951 | return 0; |
950 | return 0; |
952 | |
951 | |
953 | if (CONV_NEED (converter)) |
952 | if (CONV_NEED (converter)) |
954 | { |
953 | { |
… | |
… | |
1006 | LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", |
1005 | LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", |
1007 | &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); |
1006 | &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); |
1008 | |
1007 | |
1009 | /** |
1008 | /** |
1010 | * elmex: we are going to let the game continue, as the mapcreator |
1009 | * elmex: we are going to let the game continue, as the mapcreator |
1011 | * propably had something in mind when doing this |
1010 | * probably had something in mind when doing this |
1012 | */ |
1011 | */ |
1013 | } |
1012 | } |
1014 | insert_ob_in_map_at (item, converter->map, converter, 0, converter->x, converter->y); |
1013 | insert_ob_in_map_at (item, converter->map, converter, 0, converter->x, converter->y); |
1015 | return 1; |
1014 | return 1; |
1016 | } |
1015 | } |
… | |
… | |
1245 | */ |
1244 | */ |
1246 | static void |
1245 | static void |
1247 | apply_sign (object *op, object *sign, int autoapply) |
1246 | apply_sign (object *op, object *sign, int autoapply) |
1248 | { |
1247 | { |
1249 | readable_message_type *msgType; |
1248 | readable_message_type *msgType; |
1250 | char newbuf[HUGE_BUF]; |
|
|
1251 | |
1249 | |
1252 | if (sign->msg == NULL) |
1250 | if (sign->msg == NULL) |
1253 | { |
1251 | { |
1254 | new_draw_info (NDI_UNIQUE, 0, op, "Nothing is written on it."); |
1252 | new_draw_info (NDI_UNIQUE, 0, op, "Nothing is written on it."); |
1255 | return; |
1253 | return; |
… | |
… | |
1276 | if (QUERY_FLAG (op, FLAG_BLIND) && !QUERY_FLAG (op, FLAG_WIZ) && !sign->move_on) |
1274 | if (QUERY_FLAG (op, FLAG_BLIND) && !QUERY_FLAG (op, FLAG_WIZ) && !sign->move_on) |
1277 | { |
1275 | { |
1278 | new_draw_info (NDI_UNIQUE, 0, op, "You are unable to read while blind."); |
1276 | new_draw_info (NDI_UNIQUE, 0, op, "You are unable to read while blind."); |
1279 | return; |
1277 | return; |
1280 | } |
1278 | } |
|
|
1279 | |
|
|
1280 | if (op->contr) |
|
|
1281 | if (client *ns = op->contr->ns) |
|
|
1282 | { |
1281 | msgType = get_readable_message_type (sign); |
1283 | msgType = get_readable_message_type (sign); |
|
|
1284 | |
|
|
1285 | if (ns->can_msg) |
|
|
1286 | ns->send_msg (NDI_NAVY, msgType->msgtype, &sign->msg); |
|
|
1287 | else |
|
|
1288 | { |
|
|
1289 | char newbuf[HUGE_BUF]; |
1282 | snprintf (newbuf, sizeof (newbuf), "%hhu %s", autoapply ? 1 : 0, &sign->msg); |
1290 | snprintf (newbuf, sizeof (newbuf), "%u %s", autoapply ? 1 : 0, &sign->msg); |
1283 | draw_ext_info (NDI_UNIQUE | NDI_NAVY, 0, op, msgType->message_type, msgType->message_subtype, newbuf, &sign->msg); |
1291 | draw_ext_info (NDI_UNIQUE | NDI_NAVY, 0, op, msgType->message_type, msgType->message_subtype, newbuf, &sign->msg); |
|
|
1292 | } |
|
|
1293 | } |
1284 | } |
1294 | } |
1285 | |
1295 | |
1286 | /** |
1296 | /** |
1287 | * 'victim' moves onto 'trap' |
1297 | * 'victim' moves onto 'trap' |
1288 | * 'victim' leaves 'trap' |
1298 | * 'victim' leaves 'trap' |
… | |
… | |
1311 | * proper. This code was causing needless crashes. |
1321 | * proper. This code was causing needless crashes. |
1312 | */ |
1322 | */ |
1313 | if (recursion_depth >= 500) |
1323 | if (recursion_depth >= 500) |
1314 | { |
1324 | { |
1315 | LOG (llevDebug, "WARNING: move_apply(): aborting recursion " |
1325 | LOG (llevDebug, "WARNING: move_apply(): aborting recursion " |
1316 | "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->name, &trap->name, &victim->arch->name, &victim->name); |
1326 | "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->archname, &trap->name, &victim->arch->archname, &victim->name); |
1317 | return; |
1327 | return; |
1318 | } |
1328 | } |
|
|
1329 | |
1319 | recursion_depth++; |
1330 | recursion_depth++; |
1320 | if (trap->head) |
1331 | if (trap->head) |
1321 | trap = trap->head; |
1332 | trap = trap->head; |
1322 | |
1333 | |
1323 | if (INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) |
1334 | if (INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) |
… | |
… | |
1518 | } |
1529 | } |
1519 | goto leave; |
1530 | goto leave; |
1520 | |
1531 | |
1521 | default: |
1532 | default: |
1522 | LOG (llevDebug, "name %s, arch %s, type %d with fly/walk on/off not " |
1533 | LOG (llevDebug, "name %s, arch %s, type %d with fly/walk on/off not " |
1523 | "handled in move_apply()\n", &trap->name, &trap->arch->name, trap->type); |
1534 | "handled in move_apply()\n", &trap->name, &trap->arch->archname, trap->type); |
1524 | goto leave; |
1535 | goto leave; |
1525 | } |
1536 | } |
1526 | |
1537 | |
1527 | leave: |
1538 | leave: |
1528 | recursion_depth--; |
1539 | recursion_depth--; |
… | |
… | |
2027 | shstr_cmp dragon_ability_force ("dragon_ability_force"); |
2038 | shstr_cmp dragon_ability_force ("dragon_ability_force"); |
2028 | shstr_cmp dragon_skin_force ("dragon_skin_force"); |
2039 | shstr_cmp dragon_skin_force ("dragon_skin_force"); |
2029 | |
2040 | |
2030 | for (tmp = op->inv; tmp; tmp = tmp->below) |
2041 | for (tmp = op->inv; tmp; tmp = tmp->below) |
2031 | if (tmp->type == FORCE) |
2042 | if (tmp->type == FORCE) |
2032 | if (tmp->arch->name == dragon_skin_force) |
2043 | if (tmp->arch->archname == dragon_skin_force) |
2033 | skin = tmp; |
2044 | skin = tmp; |
2034 | else if (tmp->arch->name == dragon_ability_force) |
2045 | else if (tmp->arch->archname == dragon_ability_force) |
2035 | abil = tmp; |
2046 | abil = tmp; |
2036 | |
2047 | |
2037 | /* if either skin or ability are missing, this is an old player |
2048 | /* if either skin or ability are missing, this is an old player |
2038 | which is not to be considered a dragon -> bail out */ |
2049 | which is not to be considered a dragon -> bail out */ |
2039 | if (skin == NULL || abil == NULL) |
2050 | if (skin == NULL || abil == NULL) |
… | |
… | |
3846 | */ |
3857 | */ |
3847 | int i, j; |
3858 | int i, j; |
3848 | |
3859 | |
3849 | for (i = 0; i < NUM_STATS; i++) |
3860 | for (i = 0; i < NUM_STATS; i++) |
3850 | { |
3861 | { |
3851 | int race_bonus = pl->arch->clone.stats.stat (i); |
3862 | int race_bonus = pl->arch->stats.stat (i); |
3852 | sint8 stat = stats->stat (i) + ns->stat (i); |
3863 | sint8 stat = stats->stat (i) + ns->stat (i); |
3853 | |
3864 | |
3854 | if (stat > 20 + race_bonus) |
3865 | if (stat > 20 + race_bonus) |
3855 | { |
3866 | { |
3856 | excess_stat++; |
3867 | excess_stat++; |
… | |
… | |
3866 | |
3877 | |
3867 | if (i == CHA) |
3878 | if (i == CHA) |
3868 | continue; /* exclude cha from this */ |
3879 | continue; /* exclude cha from this */ |
3869 | |
3880 | |
3870 | int stat = stats->stat (i); |
3881 | int stat = stats->stat (i); |
3871 | int race_bonus = pl->arch->clone.stats.stat (i); |
3882 | int race_bonus = pl->arch->stats.stat (i); |
3872 | if (stat < 20 + race_bonus) |
3883 | if (stat < 20 + race_bonus) |
3873 | { |
3884 | { |
3874 | change_attr_value (stats, i, 1); |
3885 | change_attr_value (stats, i, 1); |
3875 | excess_stat--; |
3886 | excess_stat--; |
3876 | } |
3887 | } |
… | |
… | |
3945 | { |
3956 | { |
3946 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name (transformer), query_name (marked)); |
3957 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name (transformer), query_name (marked)); |
3947 | return; |
3958 | return; |
3948 | } |
3959 | } |
3949 | /* check whether they are compatible or not */ |
3960 | /* check whether they are compatible or not */ |
3950 | find = strstr (marked->slaying, transformer->arch->name); |
3961 | find = strstr (marked->slaying, transformer->arch->archname); |
3951 | if (!find || (*(find + strlen (transformer->arch->name)) != ':')) |
3962 | if (!find || (*(find + strlen (transformer->arch->archname)) != ':')) |
3952 | { |
3963 | { |
3953 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name (transformer), query_name (marked)); |
3964 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name (transformer), query_name (marked)); |
3954 | return; |
3965 | return; |
3955 | } |
3966 | } |
3956 | find += strlen (transformer->arch->name) + 1; |
3967 | find += strlen (transformer->arch->archname) + 1; |
3957 | /* Item can be used, now find how many and what it yields */ |
3968 | /* Item can be used, now find how many and what it yields */ |
3958 | if (isdigit (*(find))) |
3969 | if (isdigit (*(find))) |
3959 | { |
3970 | { |
3960 | yield = atoi (find); |
3971 | yield = atoi (find); |
3961 | if (yield < 1) |
3972 | if (yield < 1) |