1 | |
|
|
2 | /* |
|
|
3 | * static char *rcsid_apply_c = |
|
|
4 | * "$Id: apply.C,v 1.24 2006/09/11 20:26:41 root Exp $"; |
|
|
5 | */ |
|
|
6 | |
|
|
7 | /* |
1 | /* |
8 | CrossFire, A Multiplayer game for X-windows |
2 | CrossFire, A Multiplayer game for X-windows |
9 | |
3 | |
10 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
4 | Copyright (C) 2001 Mark Wedel & Crossfire Development Team |
11 | Copyright (C) 1992 Frank Tore Johansen |
5 | Copyright (C) 1992 Frank Tore Johansen |
… | |
… | |
22 | |
16 | |
23 | You should have received a copy of the GNU General Public License |
17 | You should have received a copy of the GNU General Public License |
24 | along with this program; if not, write to the Free Software |
18 | along with this program; if not, write to the Free Software |
25 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | |
20 | |
27 | The authors can be reached via e-mail to crossfire-devel@real-time.com |
21 | The authors can be reached via e-mail to <crossfire@schmorp.de> |
28 | */ |
22 | */ |
29 | |
23 | |
30 | #include <global.h> |
24 | #include <global.h> |
31 | #include <living.h> |
25 | #include <living.h> |
32 | #include <spells.h> |
26 | #include <spells.h> |
… | |
… | |
232 | drain_stat (op); |
226 | drain_stat (op); |
233 | fix_player (op); |
227 | fix_player (op); |
234 | decrease_ob (tmp); |
228 | decrease_ob (tmp); |
235 | return 1; |
229 | return 1; |
236 | } |
230 | } |
237 | if ((at = find_archetype (ARCH_DEPLETION)) == NULL) |
231 | if ((at = archetype::find (ARCH_DEPLETION)) == NULL) |
238 | { |
232 | { |
239 | LOG (llevError, "Could not find archetype depletion\n"); |
233 | LOG (llevError, "Could not find archetype depletion\n"); |
240 | return 0; |
234 | return 0; |
241 | } |
235 | } |
242 | depl = present_arch_in_ob (at, op); |
236 | depl = present_arch_in_ob (at, op); |
… | |
… | |
1315 | else |
1309 | else |
1316 | { |
1310 | { |
1317 | altar->value = 1; /* works only once */ |
1311 | altar->value = 1; /* works only once */ |
1318 | push_button (altar); |
1312 | push_button (altar); |
1319 | } |
1313 | } |
|
|
1314 | |
1320 | return sacrifice == NULL; |
1315 | return !sacrifice; |
1321 | } |
1316 | } |
1322 | else |
1317 | else |
1323 | { |
|
|
1324 | return 0; |
1318 | return 0; |
1325 | } |
|
|
1326 | } |
1319 | } |
1327 | |
1320 | |
1328 | /** |
1321 | /** |
1329 | * Handles 'movement' of shop mats. |
1322 | * Handles 'movement' of shop mats. |
1330 | * Returns 1 if 'op' was destroyed, 0 if not. |
1323 | * Returns 1 if 'op' was destroyed, 0 if not. |
… | |
… | |
1348 | * the shop. |
1341 | * the shop. |
1349 | */ |
1342 | */ |
1350 | for (tmp = op->inv; tmp; tmp = next) |
1343 | for (tmp = op->inv; tmp; tmp = next) |
1351 | { |
1344 | { |
1352 | next = tmp->below; |
1345 | next = tmp->below; |
|
|
1346 | |
1353 | if (QUERY_FLAG (tmp, FLAG_UNPAID)) |
1347 | if (QUERY_FLAG (tmp, FLAG_UNPAID)) |
1354 | { |
1348 | { |
1355 | int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); |
1349 | int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); |
1356 | |
1350 | |
1357 | remove_ob (tmp); |
1351 | remove_ob (tmp); |
… | |
… | |
1387 | /* Removed code that checked for multipart objects - it appears that |
1381 | /* Removed code that checked for multipart objects - it appears that |
1388 | * the teleport function should be able to handle this just fine. |
1382 | * the teleport function should be able to handle this just fine. |
1389 | */ |
1383 | */ |
1390 | rv = teleport (shop_mat, SHOP_MAT, op); |
1384 | rv = teleport (shop_mat, SHOP_MAT, op); |
1391 | } |
1385 | } |
1392 | else if (can_pay (op)) |
1386 | else if (can_pay (op) && get_payment (op)) |
1393 | { |
1387 | { |
1394 | /* this is only used for players */ |
1388 | /* this is only used for players */ |
1395 | get_payment (op, op->inv); |
|
|
1396 | rv = teleport (shop_mat, SHOP_MAT, op); |
1389 | rv = teleport (shop_mat, SHOP_MAT, op); |
1397 | |
1390 | |
1398 | if (shop_mat->msg) |
1391 | if (shop_mat->msg) |
1399 | new_draw_info (NDI_UNIQUE, 0, op, shop_mat->msg); |
1392 | new_draw_info (NDI_UNIQUE, 0, op, shop_mat->msg); |
1400 | /* This check below is a bit simplistic - generally it should be correct, |
1393 | /* This check below is a bit simplistic - generally it should be correct, |
… | |
… | |
1419 | { |
1412 | { |
1420 | /* if we get here, a player tried to leave a shop but was not able |
1413 | /* if we get here, a player tried to leave a shop but was not able |
1421 | * to afford the items he has. We try to move the player so that |
1414 | * to afford the items he has. We try to move the player so that |
1422 | * they are not on the mat anymore |
1415 | * they are not on the mat anymore |
1423 | */ |
1416 | */ |
1424 | |
|
|
1425 | int i = find_free_spot (op, op->map, op->x, op->y, 1, 9); |
1417 | int i = find_free_spot (op, op->map, op->x, op->y, 1, 9); |
1426 | |
1418 | |
1427 | if (i == -1) |
1419 | if (i == -1) |
1428 | { |
1420 | { |
1429 | LOG (llevError, "Internal shop-mat problem.\n"); |
1421 | LOG (llevError, "Internal shop-mat problem.\n"); |
… | |
… | |
1950 | { |
1942 | { |
1951 | LOG (llevError, "apply_spellbook: Book %s has no spell in it!\n", &tmp->name); |
1943 | LOG (llevError, "apply_spellbook: Book %s has no spell in it!\n", &tmp->name); |
1952 | new_draw_info (NDI_UNIQUE, 0, op, "The spellbook symbols make no sense."); |
1944 | new_draw_info (NDI_UNIQUE, 0, op, "The spellbook symbols make no sense."); |
1953 | return; |
1945 | return; |
1954 | } |
1946 | } |
|
|
1947 | |
1955 | if (spell->level > (skop->level + 10)) |
1948 | if (spell->level > (skop->level + 10)) |
1956 | { |
1949 | { |
1957 | new_draw_info (NDI_UNIQUE, 0, op, "You are unable to decipher the strange symbols."); |
1950 | new_draw_info (NDI_UNIQUE, 0, op, "You are unable to decipher the strange symbols."); |
1958 | return; |
1951 | return; |
1959 | } |
1952 | } |
… | |
… | |
1981 | } |
1974 | } |
1982 | |
1975 | |
1983 | if (spell->skill) |
1976 | if (spell->skill) |
1984 | { |
1977 | { |
1985 | spell_skill = find_skill_by_name (op, spell->skill); |
1978 | spell_skill = find_skill_by_name (op, spell->skill); |
|
|
1979 | |
1986 | if (!spell_skill) |
1980 | if (!spell_skill) |
1987 | { |
1981 | { |
1988 | new_draw_info_format (NDI_UNIQUE, 0, op, "You lack the skill %s to use this spell", &spell->skill); |
1982 | new_draw_info_format (NDI_UNIQUE, 0, op, "You lack the skill %s to use this spell", &spell->skill); |
1989 | return; |
1983 | return; |
1990 | } |
1984 | } |
|
|
1985 | |
1991 | if (spell_skill->level < spell->level) |
1986 | if (spell_skill->level < spell->level) |
1992 | { |
1987 | { |
1993 | new_draw_info_format (NDI_UNIQUE, 0, op, "You need to be level %d in %s to learn this spell.", spell->level, &spell->skill); |
1988 | new_draw_info_format (NDI_UNIQUE, 0, op, "You need to be level %d in %s to learn this spell.", spell->level, &spell->skill); |
1994 | return; |
1989 | return; |
1995 | } |
1990 | } |
… | |
… | |
2088 | */ |
2083 | */ |
2089 | static void |
2084 | static void |
2090 | apply_treasure (object *op, object *tmp) |
2085 | apply_treasure (object *op, object *tmp) |
2091 | { |
2086 | { |
2092 | object *treas; |
2087 | object *treas; |
2093 | tag_t tmp_tag = tmp->count, op_tag = op->count; |
|
|
2094 | |
2088 | |
2095 | |
2089 | |
2096 | /* Nice side effect of new treasure creation method is that the treasure |
2090 | /* Nice side effect of new treasure creation method is that the treasure |
2097 | * for the chest is done when the chest is created, and put into the chest |
2091 | * for the chest is done when the chest is created, and put into the chest |
2098 | * inventory. So that when the chest burns up, the items still exist. Also |
2092 | * inventory. So that when the chest burns up, the items still exist. Also |
… | |
… | |
2123 | /* If either player or container was destroyed, no need to do |
2117 | /* If either player or container was destroyed, no need to do |
2124 | * further processing. I think this should be enclused with |
2118 | * further processing. I think this should be enclused with |
2125 | * spring trap above, as I don't think there is otherwise |
2119 | * spring trap above, as I don't think there is otherwise |
2126 | * any way for the treasure chest or player to get killed |
2120 | * any way for the treasure chest or player to get killed |
2127 | */ |
2121 | */ |
2128 | if (was_destroyed (op, op_tag) || was_destroyed (tmp, tmp_tag)) |
2122 | if (op->destroyed () || tmp->destroyed ()) |
2129 | break; |
2123 | break; |
2130 | } |
2124 | } |
2131 | |
2125 | |
2132 | if (!was_destroyed (tmp, tmp_tag) && tmp->inv == NULL) |
2126 | if (!tmp->destroyed () && tmp->inv == NULL) |
2133 | decrease_ob (tmp); |
2127 | decrease_ob (tmp); |
2134 | |
2128 | |
2135 | } |
2129 | } |
2136 | |
2130 | |
2137 | /** |
2131 | /** |
… | |
… | |
2465 | is_legal_2ways_exit (object *op, object *exit) |
2459 | is_legal_2ways_exit (object *op, object *exit) |
2466 | { |
2460 | { |
2467 | object *tmp; |
2461 | object *tmp; |
2468 | object *exit_owner; |
2462 | object *exit_owner; |
2469 | player *pp; |
2463 | player *pp; |
2470 | mapstruct *exitmap; |
2464 | maptile *exitmap; |
2471 | |
2465 | |
2472 | if (exit->stats.exp != 1) |
2466 | if (exit->stats.exp != 1) |
2473 | return 1; /*This is not a 2 way, so it is legal */ |
2467 | return 1; /*This is not a 2 way, so it is legal */ |
2474 | if (!has_been_loaded (EXIT_PATH (exit)) && exit->race) |
2468 | if (!has_been_loaded (EXIT_PATH (exit)) && exit->race) |
2475 | return 0; /* This is a reset town portal */ |
2469 | return 0; /* This is a reset town portal */ |
… | |
… | |
2952 | tmp2->map = op->map; |
2946 | tmp2->map = op->map; |
2953 | tmp2->below = op->below; |
2947 | tmp2->below = op->below; |
2954 | tmp2->above = op->above; |
2948 | tmp2->above = op->above; |
2955 | tmp2->stats.food = op->stats.food; |
2949 | tmp2->stats.food = op->stats.food; |
2956 | CLEAR_FLAG (tmp2, FLAG_APPLIED); |
2950 | CLEAR_FLAG (tmp2, FLAG_APPLIED); |
|
|
2951 | |
2957 | if (QUERY_FLAG (op, FLAG_INV_LOCKED)) |
2952 | if (QUERY_FLAG (op, FLAG_INV_LOCKED)) |
2958 | SET_FLAG (tmp2, FLAG_INV_LOCKED); |
2953 | SET_FLAG (tmp2, FLAG_INV_LOCKED); |
|
|
2954 | |
2959 | if (who->type == PLAYER) |
2955 | if (who->type == PLAYER) |
2960 | esrv_del_item (who->contr, (tag_t) op->count); |
2956 | esrv_del_item (who->contr, op->count); |
|
|
2957 | |
2961 | remove_ob (op); |
2958 | remove_ob (op); |
2962 | free_object (op); |
2959 | free_object (op); |
2963 | insert_ob_in_ob (tmp2, who); |
2960 | insert_ob_in_ob (tmp2, who); |
2964 | fix_player (who); |
2961 | fix_player (who); |
2965 | if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)) |
2962 | if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)) |
… | |
… | |
3008 | |
3005 | |
3009 | if (!(aflags & AP_NO_MERGE)) |
3006 | if (!(aflags & AP_NO_MERGE)) |
3010 | { |
3007 | { |
3011 | object *tmp; |
3008 | object *tmp; |
3012 | |
3009 | |
3013 | tag_t del_tag = op->count; |
|
|
3014 | |
|
|
3015 | tmp = merge_ob (op, NULL); |
3010 | tmp = merge_ob (op, NULL); |
3016 | if (who->type == PLAYER) |
3011 | if (who->type == PLAYER) |
3017 | { |
3012 | { |
3018 | if (tmp) |
3013 | if (tmp) |
3019 | { /* it was merged */ |
3014 | { /* it was merged */ |
3020 | esrv_del_item (who->contr, del_tag); |
3015 | esrv_del_item (who->contr, op->count); |
3021 | op = tmp; |
3016 | op = tmp; |
3022 | } |
3017 | } |
|
|
3018 | |
3023 | esrv_send_item (who, op); |
3019 | esrv_send_item (who, op); |
3024 | } |
3020 | } |
3025 | } |
3021 | } |
3026 | return 0; |
3022 | return 0; |
3027 | } |
3023 | } |
… | |
… | |
3491 | SET_FLAG (tmp2, FLAG_INV_LOCKED); |
3487 | SET_FLAG (tmp2, FLAG_INV_LOCKED); |
3492 | insert_ob_in_ob (tmp2, who); |
3488 | insert_ob_in_ob (tmp2, who); |
3493 | |
3489 | |
3494 | /* Remove the old lantern */ |
3490 | /* Remove the old lantern */ |
3495 | if (who->type == PLAYER) |
3491 | if (who->type == PLAYER) |
3496 | esrv_del_item (who->contr, (tag_t) op->count); |
3492 | esrv_del_item (who->contr, op->count); |
|
|
3493 | |
3497 | remove_ob (op); |
3494 | remove_ob (op); |
3498 | free_object (op); |
3495 | free_object (op); |
3499 | |
3496 | |
3500 | /* insert the portion that was split off */ |
3497 | /* insert the portion that was split off */ |
3501 | if (tmp != NULL) |
3498 | if (tmp != NULL) |
… | |
… | |
3718 | * when an original map is loaded) and performs special actions for |
3715 | * when an original map is loaded) and performs special actions for |
3719 | * certain objects (most initialization of chests and creation of |
3716 | * certain objects (most initialization of chests and creation of |
3720 | * treasures and stuff). Calls auto_apply if appropriate. |
3717 | * treasures and stuff). Calls auto_apply if appropriate. |
3721 | */ |
3718 | */ |
3722 | void |
3719 | void |
3723 | fix_auto_apply (mapstruct *m) |
3720 | fix_auto_apply (maptile *m) |
3724 | { |
3721 | { |
3725 | object *tmp, *above = NULL; |
3722 | object *tmp, *above = NULL; |
3726 | int x, y; |
3723 | int x, y; |
3727 | |
3724 | |
3728 | if (m == NULL) |
3725 | if (m == NULL) |
… | |
… | |
3916 | void |
3913 | void |
3917 | apply_lighter (object *who, object *lighter) |
3914 | apply_lighter (object *who, object *lighter) |
3918 | { |
3915 | { |
3919 | object *item; |
3916 | object *item; |
3920 | int is_player_env = 0; |
3917 | int is_player_env = 0; |
3921 | uint32 nrof; |
|
|
3922 | tag_t count; |
|
|
3923 | char item_name[MAX_BUF]; |
3918 | char item_name[MAX_BUF]; |
3924 | |
3919 | |
3925 | item = find_marked_object (who); |
3920 | item = find_marked_object (who); |
3926 | if (item) |
3921 | if (item) |
3927 | { |
3922 | { |
… | |
… | |
3940 | esrv_send_item (who, lighter); |
3935 | esrv_send_item (who, lighter); |
3941 | oneLighter = insert_ob_in_ob (oneLighter, who); |
3936 | oneLighter = insert_ob_in_ob (oneLighter, who); |
3942 | esrv_send_item (who, oneLighter); |
3937 | esrv_send_item (who, oneLighter); |
3943 | } |
3938 | } |
3944 | else |
3939 | else |
3945 | { |
|
|
3946 | lighter->stats.food--; |
3940 | lighter->stats.food--; |
3947 | } |
|
|
3948 | |
|
|
3949 | } |
3941 | } |
3950 | else if (lighter->last_eat) |
3942 | else if (lighter->last_eat) |
3951 | { /* no charges left in lighter */ |
3943 | { /* no charges left in lighter */ |
3952 | new_draw_info_format (NDI_UNIQUE, 0, who, "You attempt to light the %s with a used up %s.", &item->name, &lighter->name); |
3944 | new_draw_info_format (NDI_UNIQUE, 0, who, "You attempt to light the %s with a used up %s.", &item->name, &lighter->name); |
3953 | return; |
3945 | return; |
3954 | } |
3946 | } |
3955 | /* Perhaps we should split what we are trying to light on fire? |
3947 | /* Perhaps we should split what we are trying to light on fire? |
3956 | * I can't see many times when you would want to light multiple |
3948 | * I can't see many times when you would want to light multiple |
3957 | * objects at once. |
3949 | * objects at once. |
3958 | */ |
3950 | */ |
3959 | nrof = item->nrof; |
|
|
3960 | count = item->count; |
|
|
3961 | /* If the item is destroyed, we don't have a valid pointer to the |
3951 | /* If the item is destroyed, we don't have a valid pointer to the |
3962 | * name object, so make a copy so the message we print out makes |
3952 | * name object, so make a copy so the message we print out makes |
3963 | * some sense. |
3953 | * some sense. |
3964 | */ |
3954 | */ |
3965 | strcpy (item_name, item->name); |
3955 | strcpy (item_name, item->name); |
… | |
… | |
3968 | |
3958 | |
3969 | save_throw_object (item, AT_FIRE, who); |
3959 | save_throw_object (item, AT_FIRE, who); |
3970 | /* Change to check count and not freed, since the object pointer |
3960 | /* Change to check count and not freed, since the object pointer |
3971 | * may have gotten recycled |
3961 | * may have gotten recycled |
3972 | */ |
3962 | */ |
3973 | if ((nrof != item->nrof) || (count != item->count)) |
3963 | if (item->destroyed ()) |
3974 | { |
3964 | { |
3975 | new_draw_info_format (NDI_UNIQUE, 0, who, "You light the %s with the %s.", &item_name, &lighter->name); |
3965 | new_draw_info_format (NDI_UNIQUE, 0, who, "You light the %s with the %s.", &item_name, &lighter->name); |
3976 | /* Need to update the player so that the players glow radius |
3966 | /* Need to update the player so that the players glow radius |
3977 | * gets changed. |
3967 | * gets changed. |
3978 | */ |
3968 | */ |
3979 | if (is_player_env) |
3969 | if (is_player_env) |
3980 | fix_player (who); |
3970 | fix_player (who); |
3981 | } |
3971 | } |
3982 | else |
3972 | else |
3983 | { |
|
|
3984 | new_draw_info_format (NDI_UNIQUE, 0, who, "You attempt to light the %s with the %s and fail.", &item->name, &lighter->name); |
3973 | new_draw_info_format (NDI_UNIQUE, 0, who, "You attempt to light the %s with the %s and fail.", &item->name, &lighter->name); |
3985 | } |
|
|
3986 | |
|
|
3987 | } |
3974 | } |
3988 | else /* nothing to light */ |
3975 | else /* nothing to light */ |
3989 | new_draw_info (NDI_UNIQUE, 0, who, "You need to mark a lightable object."); |
3976 | new_draw_info (NDI_UNIQUE, 0, who, "You need to mark a lightable object."); |
3990 | |
3977 | |
3991 | } |
3978 | } |
… | |
… | |
4211 | if (!new_item) |
4198 | if (!new_item) |
4212 | { |
4199 | { |
4213 | new_draw_info_format (NDI_UNIQUE, 0, pl, "This %s is strange, better to not use it.", query_base_name (marked, 0)); |
4200 | new_draw_info_format (NDI_UNIQUE, 0, pl, "This %s is strange, better to not use it.", query_base_name (marked, 0)); |
4214 | return; |
4201 | return; |
4215 | } |
4202 | } |
|
|
4203 | |
4216 | new_item->nrof = yield; |
4204 | new_item->nrof = yield; |
4217 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You %s the %s.", &transformer->slaying, query_base_name (marked, 0)); |
4205 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You %s the %s.", &transformer->slaying, query_base_name (marked, 0)); |
4218 | insert_ob_in_ob (new_item, pl); |
4206 | insert_ob_in_ob (new_item, pl); |
4219 | esrv_send_inventory (pl, pl); |
4207 | esrv_send_inventory (pl, pl); |
4220 | /* Eat up one item */ |
4208 | /* Eat up one item */ |