ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/apply.C
(Generate patch)

Comparing deliantra/server/server/apply.C (file contents):
Revision 1.27 by root, Thu Sep 14 21:16:12 2006 UTC vs.
Revision 1.59 by pippijn, Sat Jan 6 14:42:30 2007 UTC

1
2/*
3 * static char *rcsid_apply_c =
4 * "$Id: apply.C,v 1.27 2006/09/14 21:16:12 root Exp $";
5 */
6
7/* 1/*
8 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
9 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
10 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
12 7
13 This program is free software; you can redistribute it and/or modify 8 This program is free software; you can redistribute it and/or modify
14 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
22 17
23 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
24 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 21
27 The authors can be reached via e-mail to crossfire-devel@real-time.com 22 The authors can be reached via e-mail to <crossfire@schmorp.de>
28*/ 23*/
29 24
30#include <global.h> 25#include <global.h>
31#include <living.h> 26#include <living.h>
32#include <spells.h> 27#include <spells.h>
33#include <skills.h> 28#include <skills.h>
34#include <tod.h> 29#include <tod.h>
35 30
36#ifndef __CEXTRACT__
37# include <sproto.h> 31#include <sproto.h>
38#endif
39 32
40/* Want this regardless of rplay. */ 33/* Want this regardless of rplay. */
41#include <sounds.h> 34#include <sounds.h>
42 35
43/* need math lib for double-precision and pow() in dragon_eat_flesh() */ 36/* need math lib for double-precision and pow() in dragon_eat_flesh() */
201apply_potion (object *op, object *tmp) 194apply_potion (object *op, object *tmp)
202{ 195{
203 int got_one = 0, i; 196 int got_one = 0, i;
204 object *force = 0, *floor = 0; 197 object *force = 0, *floor = 0;
205 198
206 floor = get_map_ob (op->map, op->x, op->y); 199 floor = GET_MAP_OB (op->map, op->x, op->y);
207 200
208 if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE) 201 if (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_SAFE)
209 { 202 {
210 if (op->type == PLAYER) 203 if (op->type == PLAYER)
211 new_draw_info (NDI_UNIQUE, 0, op, "Gods prevent you from using this here, it's sacred ground!"); 204 new_draw_info (NDI_UNIQUE, 0, op, "Gods prevent you from using this here, it's sacred ground!");
212 CLEAR_FLAG (tmp, FLAG_APPLIED); 205 CLEAR_FLAG (tmp, FLAG_APPLIED);
213 return 0; 206 return 0;
214 } 207 }
215 208
216 if (op->type == PLAYER) 209 if (op->type == PLAYER)
217 {
218 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 210 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
219 identify (tmp); 211 identify (tmp);
220 }
221 212
222 handle_apply_yield (tmp); 213 handle_apply_yield (tmp);
223 214
224 /* Potion of restoration - only for players */ 215 /* Potion of restoration - only for players */
225 if (op->type == PLAYER && (tmp->attacktype & AT_DEPLETE)) 216 if (op->type == PLAYER && (tmp->attacktype & AT_DEPLETE))
227 object *depl; 218 object *depl;
228 archetype *at; 219 archetype *at;
229 220
230 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 221 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
231 { 222 {
232 drain_stat (op); 223 op->drain_stat ();
233 fix_player (op); 224 op->update_stats ();
234 decrease_ob (tmp); 225 decrease_ob (tmp);
235 return 1; 226 return 1;
236 } 227 }
228
237 if ((at = archetype::find (ARCH_DEPLETION)) == NULL) 229 if (!(at = archetype::find (ARCH_DEPLETION)))
238 { 230 {
239 LOG (llevError, "Could not find archetype depletion\n"); 231 LOG (llevError, "Could not find archetype depletion\n");
240 return 0; 232 return 0;
241 } 233 }
242 depl = present_arch_in_ob (at, op); 234 depl = present_arch_in_ob (at, op);
235
243 if (depl != NULL) 236 if (depl)
244 { 237 {
245 for (i = 0; i < NUM_STATS; i++) 238 for (i = 0; i < NUM_STATS; i++)
246 if (get_attr_value (&depl->stats, i)) 239 if (get_attr_value (&depl->stats, i))
247 {
248 new_draw_info (NDI_UNIQUE, 0, op, restore_msg[i]); 240 new_draw_info (NDI_UNIQUE, 0, op, restore_msg[i]);
249 } 241
250 remove_ob (depl); 242 depl->destroy ();
251 free_object (depl); 243 op->update_stats ();
252 fix_player (op);
253 } 244 }
254 else 245 else
255 new_draw_info (NDI_UNIQUE, 0, op, "You potion had no effect."); 246 new_draw_info (NDI_UNIQUE, 0, op, "You potion had no effect.");
256 247
257 decrease_ob (tmp); 248 decrease_ob (tmp);
259 } 250 }
260 251
261 /* improvement potion - only for players */ 252 /* improvement potion - only for players */
262 if (op->type == PLAYER && tmp->attacktype & AT_GODPOWER) 253 if (op->type == PLAYER && tmp->attacktype & AT_GODPOWER)
263 { 254 {
264
265 for (i = 1; i < MIN (11, op->level); i++) 255 for (i = 1; i < MIN (11, op->level); i++)
266 { 256 {
267 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 257 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
268 { 258 {
269 if (op->contr->levhp[i] != 1) 259 if (op->contr->levhp[i] != 1)
299 op->contr->levgrace[i] = 3; 289 op->contr->levgrace[i] = 3;
300 break; 290 break;
301 } 291 }
302 } 292 }
303 } 293 }
294
304 /* Just makes checking easier */ 295 /* Just makes checking easier */
305 if (i < MIN (11, op->level)) 296 if (i < MIN (11, op->level))
306 got_one = 1; 297 got_one = 1;
298
307 if (!QUERY_FLAG (tmp, FLAG_CURSED) && !QUERY_FLAG (tmp, FLAG_DAMNED)) 299 if (!QUERY_FLAG (tmp, FLAG_CURSED) && !QUERY_FLAG (tmp, FLAG_DAMNED))
308 { 300 {
309 if (got_one) 301 if (got_one)
310 { 302 {
311 fix_player (op); 303 op->update_stats ();
312 new_draw_info (NDI_UNIQUE, 0, op, "The Gods smile upon you and remake you"); 304 new_draw_info (NDI_UNIQUE, 0, op, "The Gods smile upon you and remake you");
313 new_draw_info (NDI_UNIQUE, 0, op, "a little more in their image."); 305 new_draw_info (NDI_UNIQUE, 0, op, "a little more in their image.");
314 new_draw_info (NDI_UNIQUE, 0, op, "You feel a little more perfect."); 306 new_draw_info (NDI_UNIQUE, 0, op, "You feel a little more perfect.");
315 } 307 }
316 else 308 else
318 } 310 }
319 else 311 else
320 { /* cursed potion */ 312 { /* cursed potion */
321 if (got_one) 313 if (got_one)
322 { 314 {
323 fix_player (op); 315 op->update_stats ();
324 new_draw_info (NDI_UNIQUE, 0, op, "The Gods are angry and punish you."); 316 new_draw_info (NDI_UNIQUE, 0, op, "The Gods are angry and punish you.");
325 } 317 }
326 else 318 else
327 new_draw_info (NDI_UNIQUE, 0, op, "You are fortunate that you are so pathetic."); 319 new_draw_info (NDI_UNIQUE, 0, op, "You are fortunate that you are so pathetic.");
328 } 320 }
321
329 decrease_ob (tmp); 322 decrease_ob (tmp);
330 return 1; 323 return 1;
331 } 324 }
332 325
333 326
355 cast_spell (op, tmp, op->facing, tmp->inv, NULL); 348 cast_spell (op, tmp, op->facing, tmp->inv, NULL);
356 349
357 decrease_ob (tmp); 350 decrease_ob (tmp);
358 /* if youre dead, no point in doing this... */ 351 /* if youre dead, no point in doing this... */
359 if (!QUERY_FLAG (op, FLAG_REMOVED)) 352 if (!QUERY_FLAG (op, FLAG_REMOVED))
360 fix_player (op); 353 op->update_stats ();
361 return 1; 354 return 1;
362 } 355 }
363 356
364 /* Deal with protection potions */ 357 /* Deal with protection potions */
365 force = NULL; 358 force = NULL;
409 * that were grouped with the one consumed, his 402 * that were grouped with the one consumed, his
410 * stat will not be raised by them. fix_player just clears 403 * stat will not be raised by them. fix_player just clears
411 * up all the stats. 404 * up all the stats.
412 */ 405 */
413 CLEAR_FLAG (tmp, FLAG_APPLIED); 406 CLEAR_FLAG (tmp, FLAG_APPLIED);
414 fix_player (op); 407 op->update_stats ();
415 decrease_ob (tmp); 408 decrease_ob (tmp);
416 return 1; 409 return 1;
417} 410}
418 411
419/**************************************************************************** 412/****************************************************************************
576 weapon->last_eat++; 569 weapon->last_eat++;
577 new_draw_info_format (NDI_UNIQUE, 0, op, "Weapon's bonus to %s improved by %d", statname, sacrifice_count); 570 new_draw_info_format (NDI_UNIQUE, 0, op, "Weapon's bonus to %s improved by %d", statname, sacrifice_count);
578 decrease_ob (improver); 571 decrease_ob (improver);
579 572
580 /* So it updates the players stats and the window */ 573 /* So it updates the players stats and the window */
581 fix_player (op); 574 op->update_stats ();
582 return 1; 575 return 1;
583} 576}
584 577
585/* Types of improvements, hidden in the sp field. */ 578/* Types of improvements, hidden in the sp field. */
586#define IMPROVE_PREPARE 1 579#define IMPROVE_PREPARE 1
889 882
890 if (op->type == PLAYER) 883 if (op->type == PLAYER)
891 { 884 {
892 esrv_send_item (op, armour); 885 esrv_send_item (op, armour);
893 if (QUERY_FLAG (armour, FLAG_APPLIED)) 886 if (QUERY_FLAG (armour, FLAG_APPLIED))
894 fix_player (op); 887 op->update_stats ();
895 } 888 }
896 decrease_ob (improver); 889 decrease_ob (improver);
897 if (tmp) 890 if (tmp)
898 { 891 {
899 insert_ob_in_ob (tmp, op); 892 insert_ob_in_ob (tmp, op);
958 price_in = nr * CONV_NEED (converter) * item->value; 951 price_in = nr * CONV_NEED (converter) * item->value;
959 } 952 }
960 else 953 else
961 { 954 {
962 price_in = item->value; 955 price_in = item->value;
963 remove_ob (item); 956 item->destroy ();
964 free_object (item);
965 } 957 }
966 } 958 }
967 959
968 if (converter->inv != NULL) 960 if (converter->inv != NULL)
969 { 961 {
987 else 979 else
988 { 980 {
989 if (converter->other_arch == NULL) 981 if (converter->other_arch == NULL)
990 { 982 {
991 LOG (llevError, "move_creator: Converter doesn't have other arch set: %s (%s, %d, %d)\n", 983 LOG (llevError, "move_creator: Converter doesn't have other arch set: %s (%s, %d, %d)\n",
992 &converter->name, converter->map->path, converter->x, converter->y); 984 &converter->name, &converter->map->path, converter->x, converter->y);
993 return -1; 985 return -1;
994 } 986 }
995 987
996 item = object_create_arch (converter->other_arch); 988 item = object_create_arch (converter->other_arch);
997 fix_generated_item (item, converter, 0, 0, GT_MINIMAL); 989 fix_generated_item (item, converter, 0, 0, GT_MINIMAL);
1004 if (is_in_shop (converter)) 996 if (is_in_shop (converter))
1005 SET_FLAG (item, FLAG_UNPAID); 997 SET_FLAG (item, FLAG_UNPAID);
1006 else if (price_in < item->nrof * item->value) 998 else if (price_in < item->nrof * item->value)
1007 { 999 {
1008 LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", 1000 LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n",
1009 &converter->name, converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); 1001 &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name);
1010 1002
1011 /** 1003 /**
1012 * elmex: we are going to let the game continue, as the mapcreator 1004 * elmex: we are going to let the game continue, as the mapcreator
1013 * propably had something in mind when doing this 1005 * propably had something in mind when doing this
1014 */ 1006 */
1033 if (op->type != PLAYER) 1025 if (op->type != PLAYER)
1034 return 0; /* This might change */ 1026 return 0; /* This might change */
1035 1027
1036 if (sack == NULL || sack->type != CONTAINER) 1028 if (sack == NULL || sack->type != CONTAINER)
1037 { 1029 {
1038 LOG (llevError, "apply_container: %s is not container!\n", &sack->name); 1030 LOG (llevError, "apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]");
1039 return 0; 1031 return 0;
1040 } 1032 }
1041 op->contr->last_used = NULL; 1033
1042 op->contr->last_used_id = 0; 1034 op->contr->last_used = 0;
1043 1035
1044 if (sack->env != op) 1036 if (sack->env != op)
1045 { 1037 {
1046 if (sack->other_arch == NULL || sack->env != NULL) 1038 if (sack->other_arch == NULL || sack->env != NULL)
1047 { 1039 {
1048 new_draw_info (NDI_UNIQUE, 0, op, "You must get it first."); 1040 new_draw_info (NDI_UNIQUE, 0, op, "You must get it first.");
1049 return 1; 1041 return 1;
1050 } 1042 }
1043
1051 /* It's on the ground, the problems begin */ 1044 /* It's on the ground, the problems begin */
1052 if (op->container != sack) 1045 if (op->container != sack)
1053 { 1046 {
1054 /* it's closed OR some player has opened it */ 1047 /* it's closed OR some player has opened it */
1055 if (QUERY_FLAG (sack, FLAG_APPLIED)) 1048 if (QUERY_FLAG (sack, FLAG_APPLIED))
1056 { 1049 {
1057 for (tmp = get_map_ob (sack->map, sack->x, sack->y); tmp && tmp->container != sack; tmp = tmp->above); 1050 for (tmp = GET_MAP_OB (sack->map, sack->x, sack->y); tmp && tmp->container != sack; tmp = tmp->above);
1058 if (tmp) 1051 if (tmp)
1059 { 1052 {
1060 /* some other player have opened it */ 1053 /* some other player have opened it */
1061 new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack)); 1054 new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack));
1062 return 1; 1055 return 1;
1082 } 1075 }
1083 else 1076 else
1084 { 1077 {
1085 sack->move_off = 0; 1078 sack->move_off = 0;
1086 tmp = sack->inv; 1079 tmp = sack->inv;
1080
1087 if (tmp && tmp->type == CLOSE_CON) 1081 if (tmp && tmp->type == CLOSE_CON)
1088 { 1082 tmp->destroy ();
1089 remove_ob (tmp);
1090 free_object (tmp);
1091 }
1092 } 1083 }
1093 } 1084 }
1094 } 1085 }
1095 1086
1096 if (QUERY_FLAG (sack, FLAG_APPLIED)) 1087 if (QUERY_FLAG (sack, FLAG_APPLIED))
1128 tmp = find_key (op, op, sack); 1119 tmp = find_key (op, op, sack);
1129 if (tmp) 1120 if (tmp)
1130 { 1121 {
1131 sprintf (buf, "You unlock %s with %s.", query_name (sack), query_name (tmp)); 1122 sprintf (buf, "You unlock %s with %s.", query_name (sack), query_name (tmp));
1132 SET_FLAG (sack, FLAG_APPLIED); 1123 SET_FLAG (sack, FLAG_APPLIED);
1124
1133 if (sack->env == NULL) 1125 if (sack->env == NULL)
1134 { /* if it's on ground,open it also */ 1126 { /* if it's on ground,open it also */
1135 new_draw_info (NDI_UNIQUE, 0, op, buf); 1127 new_draw_info (NDI_UNIQUE, 0, op, buf);
1136 apply_container (op, sack); 1128 apply_container (op, sack);
1137 return 1; 1129 return 1;
1138 } 1130 }
1139 } 1131 }
1140 else 1132 else
1141 {
1142 sprintf (buf, "You don't have the key to unlock %s.", query_name (sack)); 1133 sprintf (buf, "You don't have the key to unlock %s.", query_name (sack));
1143 }
1144 } 1134 }
1145 else 1135 else
1146 { 1136 {
1147 sprintf (buf, "You readied %s.", query_name (sack)); 1137 sprintf (buf, "You readied %s.", query_name (sack));
1148 SET_FLAG (sack, FLAG_APPLIED); 1138 SET_FLAG (sack, FLAG_APPLIED);
1139
1149 if (sack->env == NULL) 1140 if (sack->env == NULL)
1150 { /* if it's on ground,open it also */ 1141 { /* if it's on ground,open it also */
1151 new_draw_info (NDI_UNIQUE, 0, op, buf); 1142 new_draw_info (NDI_UNIQUE, 0, op, buf);
1152 apply_container (op, sack); 1143 apply_container (op, sack);
1153 return 1; 1144 return 1;
1154 } 1145 }
1155 } 1146 }
1156 } 1147 }
1148
1157 new_draw_info (NDI_UNIQUE, 0, op, buf); 1149 new_draw_info (NDI_UNIQUE, 0, op, buf);
1150
1158 if (op->contr) 1151 if (op->contr)
1159 op->contr->socket.update_look = 1; 1152 op->contr->ns->floorbox_update ();
1153
1160 return 1; 1154 return 1;
1161} 1155}
1162 1156
1163/** 1157/**
1164 * Eneq(@csd.uu.se): Handle apply on containers. This is for containers 1158 * Eneq(@csd.uu.se): Handle apply on containers. This is for containers
1182 if (op->type != PLAYER) 1176 if (op->type != PLAYER)
1183 return 0; /* This might change */ 1177 return 0; /* This might change */
1184 1178
1185 if (sack == NULL || sack->type != CONTAINER) 1179 if (sack == NULL || sack->type != CONTAINER)
1186 { 1180 {
1187 LOG (llevError, "esrv_apply_container: %s is not container!\n", &sack->name); 1181 LOG (llevError, "esrv_apply_container: %s is not container!\n", sack ? &sack->name : "[nullobject]");
1188 return 0; 1182 return 0;
1189 } 1183 }
1190 1184
1191 /* If we have a currently open container, then it needs to be closed in all cases 1185 /* If we have a currently open container, then it needs to be closed in all cases
1192 * if we are opening this one up. We then fall through if appropriate for 1186 * if we are opening this one up. We then fall through if appropriate for
1352 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 tmp->remove ();
1358 1352
1359 if (i == -1) 1353 if (i == -1)
1360 i = 0; 1354 i = 0;
1361 1355
1362 tmp->map = op->map; 1356 tmp->map = op->map;
1426 { 1420 {
1427 LOG (llevError, "Internal shop-mat problem.\n"); 1421 LOG (llevError, "Internal shop-mat problem.\n");
1428 } 1422 }
1429 else 1423 else
1430 { 1424 {
1431 remove_ob (op); 1425 op->remove ();
1432 op->x += freearr_x[i]; 1426 op->x += freearr_x[i];
1433 op->y += freearr_y[i]; 1427 op->y += freearr_y[i];
1434 rv = insert_ob_in_map (op, op->map, shop_mat, 0) == NULL; 1428 rv = insert_ob_in_map (op, op->map, shop_mat, 0) == NULL;
1435 } 1429 }
1436 } 1430 }
1684 if (victim->type == PLAYER && EXIT_PATH (trap)) 1678 if (victim->type == PLAYER && EXIT_PATH (trap))
1685 { 1679 {
1686 /* Basically, don't show exits leading to random maps the 1680 /* Basically, don't show exits leading to random maps the
1687 * players output. 1681 * players output.
1688 */ 1682 */
1689 if (trap->msg && strncmp (EXIT_PATH (trap), "/!", 2) && strncmp (EXIT_PATH (trap), "/random/", 8)) 1683 if (trap->msg && strncmp (EXIT_PATH (trap), "/!", 2))
1690 new_draw_info (NDI_NAVY, 0, victim, trap->msg); 1684 new_draw_info (NDI_NAVY, 0, victim, trap->msg);
1685
1691 enter_exit (victim, trap); 1686 victim->enter_exit (trap);
1692 } 1687 }
1693 goto leave; 1688 goto leave;
1694 1689
1695 case ENCOUNTER: 1690 case ENCOUNTER:
1696 /* may be some leftovers on this */ 1691 /* may be some leftovers on this */
1795 1790
1796 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 1791 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1797 { 1792 {
1798 /*exp_gain *= 2; because they just identified it too */ 1793 /*exp_gain *= 2; because they just identified it too */
1799 SET_FLAG (tmp, FLAG_IDENTIFIED); 1794 SET_FLAG (tmp, FLAG_IDENTIFIED);
1795
1800 /* If in a container, update how it looks */ 1796 /* If in a container, update how it looks */
1801 if (tmp->env) 1797 if (tmp->env)
1802 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp); 1798 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp);
1803 else 1799 else
1804 op->contr->socket.update_look = 1; 1800 op->contr->ns->floorbox_update ();
1805 } 1801 }
1802
1806 change_exp (op, exp_gain, skill_ob->skill, 0); 1803 change_exp (op, exp_gain, skill_ob->skill, 0);
1807 SET_FLAG (tmp, FLAG_NO_SKILL_IDENT); /* so no more xp gained from this book */ 1804 SET_FLAG (tmp, FLAG_NO_SKILL_IDENT); /* so no more xp gained from this book */
1808 } 1805 }
1809} 1806}
1810 1807
1859 } 1856 }
1860 return; 1857 return;
1861 } 1858 }
1862 1859
1863 play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0); 1860 play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0);
1864 tmp = get_object (); 1861 tmp = spell->clone ();
1865 copy_object (spell, tmp);
1866 insert_ob_in_ob (tmp, op); 1862 insert_ob_in_ob (tmp, op);
1867 1863
1868 if (special_prayer) 1864 if (special_prayer)
1869 {
1870 SET_FLAG (tmp, FLAG_STARTEQUIP); 1865 SET_FLAG (tmp, FLAG_STARTEQUIP);
1871 }
1872 1866
1873 esrv_add_spells (op->contr, tmp); 1867 esrv_add_spells (op->contr, tmp);
1874} 1868}
1875 1869
1876/** 1870/**
1893 } 1887 }
1894 1888
1895 new_draw_info_format (NDI_UNIQUE | NDI_NAVY, 0, op, "You lose knowledge of %s.", spell); 1889 new_draw_info_format (NDI_UNIQUE | NDI_NAVY, 0, op, "You lose knowledge of %s.", spell);
1896 player_unready_range_ob (op->contr, spob); 1890 player_unready_range_ob (op->contr, spob);
1897 esrv_remove_spell (op->contr, spob); 1891 esrv_remove_spell (op->contr, spob);
1898 remove_ob (spob); 1892 spob->destroy ();
1899 free_object (spob);
1900} 1893}
1901 1894
1902/** 1895/**
1903 * Handles player applying a spellbook. 1896 * Handles player applying a spellbook.
1904 * Checks whether player has knowledge of required skill, doesn't already know the spell, 1897 * Checks whether player has knowledge of required skill, doesn't already know the spell,
1942 new_draw_info (NDI_UNIQUE, 0, op, "You can't read! Your attempt fails."); 1935 new_draw_info (NDI_UNIQUE, 0, op, "You can't read! Your attempt fails.");
1943 return; 1936 return;
1944 } 1937 }
1945 1938
1946 spell = tmp->inv; 1939 spell = tmp->inv;
1940
1947 if (!spell) 1941 if (!spell)
1948 { 1942 {
1949 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);
1950 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.");
1951 return; 1945 return;
1952 } 1946 }
1953 if (spell->level > (skop->level + 10)) 1947
1948 if (skop->level < int (sqrtf (spell->level) * 1.5f))
1954 { 1949 {
1955 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to decipher the strange symbols."); 1950 new_draw_info (NDI_UNIQUE, 0, op, "It is too hard to read at your level: You are unable to decipher the strange symbols.");
1956 return; 1951 return;
1957 } 1952 }
1958 1953
1959 new_draw_info_format (NDI_UNIQUE, 0, op, "The spellbook contains the %s level spell %s.", get_levelnumber (spell->level), &spell->name); 1954 new_draw_info_format (NDI_UNIQUE, 0, op, "The spellbook contains the %s level spell %s.", get_levelnumber (spell->level), &spell->name);
1960 1955
1961 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 1956 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1962 { 1957 {
1963 identify (tmp); 1958 identify (tmp);
1959
1964 if (tmp->env) 1960 if (tmp->env)
1965 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp); 1961 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp);
1966 else 1962 else
1967 op->contr->socket.update_look = 1; 1963 op->contr->ns->floorbox_update ();
1968 } 1964 }
1969 1965
1970 /* I removed the check for special_prayer_mark here - it didn't make 1966 /* I removed the check for special_prayer_mark here - it didn't make
1971 * a lot of sense - special prayers are not found in spellbooks, and 1967 * a lot of sense - special prayers are not found in spellbooks, and
1972 * if the player doesn't know the spell, doesn't make a lot of sense that 1968 * if the player doesn't know the spell, doesn't make a lot of sense that
2088 */ 2084 */
2089static void 2085static void
2090apply_treasure (object *op, object *tmp) 2086apply_treasure (object *op, object *tmp)
2091{ 2087{
2092 object *treas; 2088 object *treas;
2093 tag_t tmp_tag = tmp->count, op_tag = op->count;
2094 2089
2095 2090
2096 /* Nice side effect of new treasure creation method is that the treasure 2091 /* 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 2092 * 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 2093 * inventory. So that when the chest burns up, the items still exist. Also
2109 } 2104 }
2110 while (tmp->inv) 2105 while (tmp->inv)
2111 { 2106 {
2112 treas = tmp->inv; 2107 treas = tmp->inv;
2113 2108
2114 remove_ob (treas); 2109 treas->remove ();
2115 new_draw_info_format (NDI_UNIQUE, 0, op, "You find %s in the chest.", query_name (treas)); 2110 new_draw_info_format (NDI_UNIQUE, 0, op, "You find %s in the chest.", query_name (treas));
2116 2111
2117 treas->x = op->x; 2112 treas->x = op->x;
2118 treas->y = op->y; 2113 treas->y = op->y;
2119 treas = insert_ob_in_map (treas, op->map, op, INS_BELOW_ORIGINATOR); 2114 treas = insert_ob_in_map (treas, op->map, op, INS_BELOW_ORIGINATOR);
2120 2115
2121 if (treas && (treas->type == RUNE || treas->type == TRAP) && treas->level && QUERY_FLAG (op, FLAG_ALIVE)) 2116 if (treas && (treas->type == RUNE || treas->type == TRAP) && treas->level && QUERY_FLAG (op, FLAG_ALIVE))
2122 spring_trap (treas, op); 2117 spring_trap (treas, op);
2118
2123 /* If either player or container was destroyed, no need to do 2119 /* If either player or container was destroyed, no need to do
2124 * further processing. I think this should be enclused with 2120 * further processing. I think this should be enclused with
2125 * spring trap above, as I don't think there is otherwise 2121 * spring trap above, as I don't think there is otherwise
2126 * any way for the treasure chest or player to get killed 2122 * any way for the treasure chest or player to get killed
2127 */ 2123 */
2128 if (was_destroyed (op, op_tag) || was_destroyed (tmp, tmp_tag)) 2124 if (op->destroyed () || tmp->destroyed ())
2129 break; 2125 break;
2130 } 2126 }
2131 2127
2132 if (!was_destroyed (tmp, tmp_tag) && tmp->inv == NULL) 2128 if (!tmp->destroyed () && tmp->inv == NULL)
2133 decrease_ob (tmp); 2129 decrease_ob (tmp);
2134 2130
2135} 2131}
2136 2132
2137/** 2133/**
2332 2328
2333 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95) 2329 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95)
2334 { 2330 {
2335 /* resistance increased! */ 2331 /* resistance increased! */
2336 skin->resist[i]++; 2332 skin->resist[i]++;
2337 fix_player (op); 2333 op->update_stats ();
2338 2334
2339 sprintf (buf, "Your skin is now more resistant to %s!", change_resist_msg[i]); 2335 sprintf (buf, "Your skin is now more resistant to %s!", change_resist_msg[i]);
2340 new_draw_info (NDI_UNIQUE | NDI_RED, 0, op, buf); 2336 new_draw_info (NDI_UNIQUE | NDI_RED, 0, op, buf);
2341 } 2337 }
2342 2338
2361 } 2357 }
2362 } 2358 }
2363 return 1; 2359 return 1;
2364} 2360}
2365 2361
2366static void
2367apply_savebed (object *pl)
2368{
2369#ifndef COZY_SERVER
2370 if (!pl->contr->name_changed || !pl->stats.exp)
2371 {
2372 new_draw_info (NDI_UNIQUE, 0, pl, "You don't deserve to save your character yet.");
2373 return;
2374 }
2375#endif
2376 INVOKE_PLAYER (LOGOUT, pl->contr);
2377 /* Need to call terminate_all_pets() before we remove the player ob */
2378 terminate_all_pets (pl);
2379 remove_ob (pl);
2380 pl->direction = 0;
2381 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, pl, "%s leaves the game.", &pl->name);
2382
2383 /* update respawn position */
2384 strcpy (pl->contr->savebed_map, pl->map->path);
2385 pl->contr->bed_x = pl->x;
2386 pl->contr->bed_y = pl->y;
2387
2388 strcpy (pl->contr->killer, "left");
2389 check_score (pl); /* Always check score */
2390 (void) save_player (pl, 0);
2391 pl->map->players--;
2392#if MAP_MAXTIMEOUT
2393 MAP_SWAP_TIME (pl->map) = MAP_TIMEOUT (pl->map);
2394#endif
2395 play_again (pl);
2396 pl->speed = 0;
2397 update_ob_speed (pl);
2398}
2399
2400/** 2362/**
2401 * Handles applying an improve armor scroll. 2363 * Handles applying an improve armor scroll.
2402 * Does some sanity checks, then calls improve_armour. 2364 * Does some sanity checks, then calls improve_armour.
2403 */ 2365 */
2404static void 2366static void
2409 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_NO_MAGIC)) 2371 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_NO_MAGIC))
2410 { 2372 {
2411 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the scroll."); 2373 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the scroll.");
2412 return; 2374 return;
2413 } 2375 }
2376
2414 armor = find_marked_object (op); 2377 armor = find_marked_object (op);
2378
2415 if (!armor) 2379 if (!armor)
2416 { 2380 {
2417 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark an armor object."); 2381 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark an armor object.");
2418 return; 2382 return;
2419 } 2383 }
2384
2420 if (armor->type != ARMOUR 2385 if (armor->type != ARMOUR
2421 && armor->type != CLOAK 2386 && armor->type != CLOAK
2422 && armor->type != BOOTS && armor->type != GLOVES && armor->type != BRACERS && armor->type != SHIELD && armor->type != HELMET) 2387 && armor->type != BOOTS && armor->type != GLOVES && armor->type != BRACERS && armor->type != SHIELD && armor->type != HELMET)
2423 { 2388 {
2424 new_draw_info (NDI_UNIQUE, 0, op, "Your marked item is not armour!\n"); 2389 new_draw_info (NDI_UNIQUE, 0, op, "Your marked item is not armour!\n");
2427 2392
2428 new_draw_info (NDI_UNIQUE, 0, op, "Applying armour enchantment."); 2393 new_draw_info (NDI_UNIQUE, 0, op, "Applying armour enchantment.");
2429 improve_armour (op, tmp, armor); 2394 improve_armour (op, tmp, armor);
2430} 2395}
2431 2396
2432
2433extern void 2397extern void
2434apply_poison (object *op, object *tmp) 2398apply_poison (object *op, object *tmp)
2435{ 2399{
2436 if (op->type == PLAYER) 2400 if (op->type == PLAYER)
2437 { 2401 {
2448 handle_apply_yield (tmp); 2412 handle_apply_yield (tmp);
2449 decrease_ob (tmp); 2413 decrease_ob (tmp);
2450} 2414}
2451 2415
2452/** 2416/**
2453 * This fonction return true if the exit is not a 2 ways one or it is 2 ways, valid exit. 2417 * This function return true if the exit is not a 2 ways one or it is 2 ways, valid exit.
2454 * A valid 2 way exit means: 2418 * A valid 2 way exit means:
2455 * -You can come back (there is another exit at the other side) 2419 * -You can come back (there is another exit at the other side)
2456 * -You are 2420 * -You are
2457 * ° the owner of the exit 2421 * ° the owner of the exit
2458 * ° or in the same party as the owner 2422 * ° or in the same party as the owner
2459 * 2423 *
2460 * Note: a owner in a 2 way exit is saved as the owner's name 2424 * Note: a owner in a 2 way exit is saved as the owner's name
2461 * in the field exit->name cause the field exit->owner doesn't 2425 * in the field exit->name cause the field exit->owner doesn't
2462 * survive in the swapping (in fact the whole exit doesn't survive). 2426 * survive in the swapping (in fact the whole exit doesn't survive).
2463 */ 2427 */
2464int 2428int
2465is_legal_2ways_exit (object *op, object *exit) 2429is_legal_2ways_exit (object *op, object *exit)
2466{ 2430{
2467 object *tmp;
2468 object *exit_owner;
2469 player *pp;
2470 mapstruct *exitmap;
2471
2472 if (exit->stats.exp != 1) 2431 if (exit->stats.exp != 1)
2473 return 1; /*This is not a 2 way, so it is legal */ 2432 return 1; /*This is not a 2 way, so it is legal */
2433
2434#if 0 //TODO
2474 if (!has_been_loaded (EXIT_PATH (exit)) && exit->race) 2435 if (!has_been_loaded (EXIT_PATH (exit)) && exit->race)
2475 return 0; /* This is a reset town portal */ 2436 return 0; /* This is a reset town portal */
2476 /* To know if an exit has a correspondant, we look at 2437#endif
2477 * all the exits in destination and try to find one with same path as 2438
2478 * the current exit's position */ 2439 maptile *exitmap = maptile::find_sync (EXIT_PATH (exit), exit->map);
2479 if (!strncmp (EXIT_PATH (exit), settings.localdir, strlen (settings.localdir))) 2440
2480 exitmap = ready_map_name (EXIT_PATH (exit), MAP_PLAYER_UNIQUE);
2481 else
2482 exitmap = ready_map_name (EXIT_PATH (exit), 0);
2483 if (exitmap) 2441 if (exitmap)
2484 { 2442 {
2443 exitmap->load_sync ();
2444
2485 tmp = get_map_ob (exitmap, EXIT_X (exit), EXIT_Y (exit)); 2445 object *tmp = exitmap->at (EXIT_X (exit), EXIT_Y (exit)).bot;
2446
2486 if (!tmp) 2447 if (!tmp)
2487 return 0; 2448 return 0;
2488 for ((tmp = get_map_ob (exitmap, EXIT_X (exit), EXIT_Y (exit))); tmp; tmp = tmp->above) 2449
2450 for (; tmp; tmp = tmp->above)
2489 { 2451 {
2490 if (tmp->type != EXIT) 2452 if (tmp->type != EXIT)
2491 continue; /*Not an exit */ 2453 continue; /*Not an exit */
2454
2492 if (!EXIT_PATH (tmp)) 2455 if (!EXIT_PATH (tmp))
2493 continue; /*Not a valid exit */ 2456 continue; /*Not a valid exit */
2457
2494 if ((EXIT_X (tmp) != exit->x) || (EXIT_Y (tmp) != exit->y)) 2458 if ((EXIT_X (tmp) != exit->x) || (EXIT_Y (tmp) != exit->y))
2495 continue; /*Not in the same place */ 2459 continue; /*Not in the same place */
2460
2496 if (strcmp (exit->map->path, EXIT_PATH (tmp)) != 0) 2461 if (strcmp (exit->map->path, EXIT_PATH (tmp)) != 0)
2497 continue; /*Not in the same map */ 2462 continue; /*Not in the same map */
2498 2463
2499 /* From here we have found the exit is valid. However we do 2464 /* From here we have found the exit is valid. However we do
2500 * here the check of the exit owner. It is important for the 2465 * here the check of the exit owner. It is important for the
2501 * town portals to prevent strangers from visiting your appartments 2466 * town portals to prevent strangers from visiting your appartments
2502 */ 2467 */
2503 if (!exit->race) 2468 if (!exit->race)
2504 return 1; /*No owner, free for all! */ 2469 return 1; /*No owner, free for all! */
2470
2505 exit_owner = NULL; 2471 object *exit_owner = 0;
2506 for (pp = first_player; pp; pp = pp->next) 2472
2473 for_all_players (pp)
2507 { 2474 {
2508 if (!pp->ob) 2475 if (!pp->ob)
2509 continue; 2476 continue;
2477
2510 if (pp->ob->name != exit->race) 2478 if (pp->ob->name != exit->race)
2511 continue; 2479 continue;
2480
2512 exit_owner = pp->ob; /*We found a player which correspond to the player name */ 2481 exit_owner = pp->ob; /*We found a player which correspond to the player name */
2513 break; 2482 break;
2514 } 2483 }
2484
2515 if (!exit_owner) 2485 if (!exit_owner)
2516 return 0; /* No more owner */ 2486 return 0; /* No more owner */
2487
2517 if (exit_owner->contr == op->contr) 2488 if (exit_owner->contr == op->contr)
2518 return 1; /*It is your exit */ 2489 return 1; /*It is your exit */
2490
2519 if (exit_owner && /*There is a owner */ 2491 if (exit_owner && /*There is a owner */
2520 (op->contr) && /*A player tries to pass */ 2492 (op->contr) && /*A player tries to pass */
2521 ((exit_owner->contr->party == NULL) || /*No pass if controller has no party */ 2493 ((exit_owner->contr->party == NULL) || /*No pass if controller has no party */
2522 (exit_owner->contr->party != op->contr->party))) /* Or not the same as op */ 2494 (exit_owner->contr->party != op->contr->party))) /* Or not the same as op */
2523 return 0; 2495 return 0;
2496
2524 return 1; 2497 return 1;
2525 } 2498 }
2526 } 2499 }
2500
2527 return 0; 2501 return 0;
2528} 2502}
2529 2503
2530 2504
2531/** 2505/**
2557 { 2531 {
2558 new_draw_info (NDI_UNIQUE, 0, op, "You should pay for it first."); 2532 new_draw_info (NDI_UNIQUE, 0, op, "You should pay for it first.");
2559 return 1; 2533 return 1;
2560 } 2534 }
2561 else 2535 else
2562 {
2563 return 0; /* monsters just skip unpaid items */ 2536 return 0; /* monsters just skip unpaid items */
2564 }
2565 } 2537 }
2566 2538
2567 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op))) 2539 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op)))
2568 return RESULT_INT (0); 2540 return RESULT_INT (0);
2569 2541
2570 switch (tmp->type) 2542 switch (tmp->type)
2571 { 2543 {
2572
2573 case CF_HANDLE: 2544 case CF_HANDLE:
2574 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle."); 2545 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2575 play_sound_map (op->map, op->x, op->y, SOUND_TURN_HANDLE); 2546 play_sound_map (op->map, op->x, op->y, SOUND_TURN_HANDLE);
2576 tmp->value = tmp->value ? 0 : 1; 2547 tmp->value = tmp->value ? 0 : 1;
2577 SET_ANIMATION (tmp, tmp->value); 2548 SET_ANIMATION (tmp, tmp->value);
2584 { 2555 {
2585 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle."); 2556 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2586 play_sound_map (tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE); 2557 play_sound_map (tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE);
2587 } 2558 }
2588 else 2559 else
2589 {
2590 new_draw_info (NDI_UNIQUE, 0, op, "The handle doesn't move."); 2560 new_draw_info (NDI_UNIQUE, 0, op, "The handle doesn't move.");
2591 } 2561
2592 return 1; 2562 return 1;
2593 2563
2594 case EXIT: 2564 case EXIT:
2595 if (op->type != PLAYER) 2565 if (op->type != PLAYER)
2596 return 0; 2566 return 0;
2567
2597 if (!EXIT_PATH (tmp) || !is_legal_2ways_exit (op, tmp)) 2568 if (!EXIT_PATH (tmp) || !is_legal_2ways_exit (op, tmp))
2598 { 2569 {
2599 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", query_name (tmp)); 2570 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", query_name (tmp));
2600 } 2571 }
2601 else 2572 else
2602 { 2573 {
2603 /* Don't display messages for random maps. */ 2574 /* Don't display messages for random maps. */
2604 if (tmp->msg && strncmp (EXIT_PATH (tmp), "/!", 2) && strncmp (EXIT_PATH (tmp), "/random/", 8)) 2575 if (tmp->msg && strncmp (EXIT_PATH (tmp), "/!", 2))
2605 new_draw_info (NDI_NAVY, 0, op, tmp->msg); 2576 new_draw_info (NDI_NAVY, 0, op, tmp->msg);
2577
2606 enter_exit (op, tmp); 2578 op->enter_exit (tmp);
2607 } 2579 }
2608 return 1; 2580 return 1;
2609 2581
2610 case SIGN: 2582 case SIGN:
2611 apply_sign (op, tmp, 0); 2583 apply_sign (op, tmp, 0);
2705 case POISON: 2677 case POISON:
2706 apply_poison (op, tmp); 2678 apply_poison (op, tmp);
2707 return 1; 2679 return 1;
2708 2680
2709 case SAVEBED: 2681 case SAVEBED:
2710 if (op->type == PLAYER)
2711 {
2712 apply_savebed (op);
2713 return 1; 2682 return 1;
2714 }
2715 else
2716 {
2717 return 0;
2718 }
2719 2683
2720 case ARMOUR_IMPROVER: 2684 case ARMOUR_IMPROVER:
2721 if (op->type == PLAYER) 2685 if (op->type == PLAYER)
2722 { 2686 {
2723 apply_armour_improver (op, tmp); 2687 apply_armour_improver (op, tmp);
2724 return 1; 2688 return 1;
2725 } 2689 }
2726 else 2690 else
2727 {
2728 return 0; 2691 return 0;
2729 }
2730 2692
2731 case WEAPON_IMPROVER: 2693 case WEAPON_IMPROVER:
2732 (void) check_improve_weapon (op, tmp); 2694 (void) check_improve_weapon (op, tmp);
2733 return 1; 2695 return 1;
2734 2696
2814 if (op->type != PLAYER && QUERY_FLAG (op, FLAG_WAS_WIZ) && !QUERY_FLAG (pl, FLAG_WAS_WIZ)) 2776 if (op->type != PLAYER && QUERY_FLAG (op, FLAG_WAS_WIZ) && !QUERY_FLAG (pl, FLAG_WAS_WIZ))
2815 { 2777 {
2816 play_sound_map (pl->map, pl->x, pl->y, SOUND_OB_EVAPORATE); 2778 play_sound_map (pl->map, pl->x, pl->y, SOUND_OB_EVAPORATE);
2817 new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff " "of smoke!"); 2779 new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff " "of smoke!");
2818 new_draw_info (NDI_UNIQUE, 0, pl, "It must have been an illusion."); 2780 new_draw_info (NDI_UNIQUE, 0, pl, "It must have been an illusion.");
2819 remove_ob (op); 2781 op->destroy ();
2820 free_object (op);
2821 return 1; 2782 return 1;
2822 } 2783 }
2823 2784
2824 pl->contr->last_used = op; 2785 pl->contr->last_used = op;
2825 pl->contr->last_used_id = op->count;
2826 2786
2827 tmp = manual_apply (pl, op, aflag); 2787 tmp = manual_apply (pl, op, aflag);
2828 if (!quiet) 2788 if (!quiet)
2829 { 2789 {
2830 if (tmp == 0) 2790 if (tmp == 0)
2952 tmp2->map = op->map; 2912 tmp2->map = op->map;
2953 tmp2->below = op->below; 2913 tmp2->below = op->below;
2954 tmp2->above = op->above; 2914 tmp2->above = op->above;
2955 tmp2->stats.food = op->stats.food; 2915 tmp2->stats.food = op->stats.food;
2956 CLEAR_FLAG (tmp2, FLAG_APPLIED); 2916 CLEAR_FLAG (tmp2, FLAG_APPLIED);
2917
2957 if (QUERY_FLAG (op, FLAG_INV_LOCKED)) 2918 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
2958 SET_FLAG (tmp2, FLAG_INV_LOCKED); 2919 SET_FLAG (tmp2, FLAG_INV_LOCKED);
2920
2959 if (who->type == PLAYER) 2921 if (who->type == PLAYER)
2960 esrv_del_item (who->contr, (tag_t) op->count); 2922 esrv_del_item (who->contr, op->count);
2961 remove_ob (op); 2923
2962 free_object (op); 2924 op->destroy ();
2963 insert_ob_in_ob (tmp2, who); 2925 insert_ob_in_ob (tmp2, who);
2964 fix_player (who); 2926 who->update_stats ();
2965 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)) 2927 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
2966 { 2928 {
2967 if (who->type == PLAYER) 2929 if (who->type == PLAYER)
2968 { 2930 {
2969 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!"); 2931 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!");
3002 default: 2964 default:
3003 new_draw_info_format (NDI_UNIQUE, 0, who, "You unapply %s.", query_name (op)); 2965 new_draw_info_format (NDI_UNIQUE, 0, who, "You unapply %s.", query_name (op));
3004 break; 2966 break;
3005 } 2967 }
3006 2968
3007 fix_player (who); 2969 who->update_stats ();
3008 2970
3009 if (!(aflags & AP_NO_MERGE)) 2971 if (!(aflags & AP_NO_MERGE))
3010 { 2972 {
3011 object *tmp; 2973 object *tmp;
3012
3013 tag_t del_tag = op->count;
3014 2974
3015 tmp = merge_ob (op, NULL); 2975 tmp = merge_ob (op, NULL);
3016 if (who->type == PLAYER) 2976 if (who->type == PLAYER)
3017 { 2977 {
3018 if (tmp) 2978 if (tmp)
3019 { /* it was merged */ 2979 { /* it was merged */
3020 esrv_del_item (who->contr, del_tag); 2980 esrv_del_item (who->contr, op->count);
3021 op = tmp; 2981 op = tmp;
3022 } 2982 }
2983
3023 esrv_send_item (who, op); 2984 esrv_send_item (who, op);
3024 } 2985 }
3025 } 2986 }
3026 return 0; 2987 return 0;
3027} 2988}
3379 } 3340 }
3380 else 3341 else
3381 { 3342 {
3382 if (who->contr->unapply == unapply_never || (i & CAN_APPLY_UNAPPLY_CHOICE && who->contr->unapply == unapply_nochoice)) 3343 if (who->contr->unapply == unapply_never || (i & CAN_APPLY_UNAPPLY_CHOICE && who->contr->unapply == unapply_nochoice))
3383 { 3344 {
3384 new_draw_info (NDI_UNIQUE, 0, who, "You need to unapply some item(s):"); 3345 new_draw_info (NDI_UNIQUE, 0, who, "You need to unapply some of the following item(s) or change your applymode:");
3385 unapply_for_ob (who, op, AP_PRINT); 3346 unapply_for_ob (who, op, AP_PRINT);
3386 return 1; 3347 return 1;
3387 } 3348 }
3388 else if (who->contr->unapply == unapply_always || !(i & CAN_APPLY_UNAPPLY_CHOICE)) 3349 else if (who->contr->unapply == unapply_always || !(i & CAN_APPLY_UNAPPLY_CHOICE))
3389 { 3350 {
3391 if (i) 3352 if (i)
3392 return 1; 3353 return 1;
3393 } 3354 }
3394 } 3355 }
3395 } 3356 }
3357
3396 if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) 3358 if (op->skill && op->type != SKILL && op->type != SKILL_TOOL)
3397 { 3359 {
3398 skop = find_skill_by_name (who, op->skill); 3360 skop = find_skill_by_name (who, op->skill);
3399 if (!skop) 3361 if (!skop)
3400 { 3362 {
3491 SET_FLAG (tmp2, FLAG_INV_LOCKED); 3453 SET_FLAG (tmp2, FLAG_INV_LOCKED);
3492 insert_ob_in_ob (tmp2, who); 3454 insert_ob_in_ob (tmp2, who);
3493 3455
3494 /* Remove the old lantern */ 3456 /* Remove the old lantern */
3495 if (who->type == PLAYER) 3457 if (who->type == PLAYER)
3496 esrv_del_item (who->contr, (tag_t) op->count); 3458 esrv_del_item (who->contr, op->count);
3497 remove_ob (op); 3459
3498 free_object (op); 3460 op->destroy ();
3499 3461
3500 /* insert the portion that was split off */ 3462 /* insert the portion that was split off */
3501 if (tmp != NULL) 3463 if (tmp != NULL)
3502 { 3464 {
3503 (void) insert_ob_in_ob (tmp, who); 3465 (void) insert_ob_in_ob (tmp, who);
3504 if (who->type == PLAYER) 3466 if (who->type == PLAYER)
3505 esrv_send_item (who, tmp); 3467 esrv_send_item (who, tmp);
3506 } 3468 }
3507 fix_player (who); 3469 who->update_stats ();
3508 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)) 3470 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
3509 { 3471 {
3510 if (who->type == PLAYER) 3472 if (who->type == PLAYER)
3511 { 3473 {
3512 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!"); 3474 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!");
3609 SET_FLAG (op, FLAG_APPLIED); 3571 SET_FLAG (op, FLAG_APPLIED);
3610 3572
3611 if (tmp != NULL) 3573 if (tmp != NULL)
3612 tmp = insert_ob_in_ob (tmp, who); 3574 tmp = insert_ob_in_ob (tmp, who);
3613 3575
3614 fix_player (who); 3576 who->update_stats ();
3615 3577
3616 /* We exclude spell casting objects. The fire code will set the 3578 /* We exclude spell casting objects. The fire code will set the
3617 * been applied flag when they are used - until that point, 3579 * been applied flag when they are used - until that point,
3618 * you don't know anything about them. 3580 * you don't know anything about them.
3619 */ 3581 */
3659 int i; 3621 int i;
3660 3622
3661 switch (op->type) 3623 switch (op->type)
3662 { 3624 {
3663 case SHOP_FLOOR: 3625 case SHOP_FLOOR:
3664 if (!HAS_RANDOM_ITEMS (op)) 3626 if (!op->has_random_items ())
3665 return 0; 3627 return 0;
3628
3666 do 3629 do
3667 { 3630 {
3668 i = 10; /* let's give it 10 tries */ 3631 i = 10; /* let's give it 10 tries */
3669 while ((tmp = generate_treasure (op->randomitems, 3632 while ((tmp = generate_treasure (op->randomitems,
3670 op->stats.exp ? (int) op->stats.exp : MAX (op->map->difficulty, 5))) == NULL && --i); 3633 op->stats.exp ? (int) op->stats.exp : MAX (op->map->difficulty, 5))) == NULL && --i);
3671 if (tmp == NULL) 3634 if (tmp == NULL)
3672 return 0; 3635 return 0;
3673 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 3636 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
3674 { 3637 {
3675 free_object (tmp); 3638 tmp->destroy ();
3676 tmp = NULL; 3639 tmp = NULL;
3677 } 3640 }
3678 } 3641 }
3679 while (!tmp); 3642 while (!tmp);
3643
3680 tmp->x = op->x; 3644 tmp->x = op->x;
3681 tmp->y = op->y; 3645 tmp->y = op->y;
3682 SET_FLAG (tmp, FLAG_UNPAID); 3646 SET_FLAG (tmp, FLAG_UNPAID);
3683 insert_ob_in_map (tmp, op->map, NULL, 0); 3647 insert_ob_in_map (tmp, op->map, NULL, 0);
3684 CLEAR_FLAG (op, FLAG_AUTO_APPLY); 3648 CLEAR_FLAG (op, FLAG_AUTO_APPLY);
3686 break; 3650 break;
3687 3651
3688 case TREASURE: 3652 case TREASURE:
3689 if (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)) 3653 if (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))
3690 return 0; 3654 return 0;
3655
3691 while ((op->stats.hp--) > 0) 3656 while ((op->stats.hp--) > 0)
3692 create_treasure (op->randomitems, op, op->map ? GT_ENVIRONMENT : 0, 3657 create_treasure (op->randomitems, op, op->map ? GT_ENVIRONMENT : 0,
3693 op->stats.exp ? (int) op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0); 3658 op->stats.exp ? (int) op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3694 3659
3695 /* If we generated an object and put it in this object inventory, 3660 /* If we generated an object and put it in this object inventory,
3698 * that is put inside other objects. 3663 * that is put inside other objects.
3699 */ 3664 */
3700 for (tmp = op->inv; tmp; tmp = tmp2) 3665 for (tmp = op->inv; tmp; tmp = tmp2)
3701 { 3666 {
3702 tmp2 = tmp->below; 3667 tmp2 = tmp->below;
3703 remove_ob (tmp); 3668 tmp->remove ();
3669
3704 if (op->env) 3670 if (op->env)
3705 insert_ob_in_ob (tmp, op->env); 3671 insert_ob_in_ob (tmp, op->env);
3706 else 3672 else
3707 free_object (tmp); 3673 tmp->destroy ();
3708 } 3674 }
3709 remove_ob (op); 3675
3710 free_object (op); 3676 op->destroy ();
3711 break; 3677 break;
3712 } 3678 }
3713 return tmp ? 1 : 0; 3679 return tmp ? 1 : 0;
3714} 3680}
3715 3681
3718 * when an original map is loaded) and performs special actions for 3684 * when an original map is loaded) and performs special actions for
3719 * certain objects (most initialization of chests and creation of 3685 * certain objects (most initialization of chests and creation of
3720 * treasures and stuff). Calls auto_apply if appropriate. 3686 * treasures and stuff). Calls auto_apply if appropriate.
3721 */ 3687 */
3722void 3688void
3723fix_auto_apply (mapstruct *m) 3689maptile::fix_auto_apply ()
3724{ 3690{
3725 object *tmp, *above = NULL; 3691 if (!spaces)
3726 int x, y;
3727
3728 if (m == NULL)
3729 return; 3692 return;
3730 3693
3731 for (x = 0; x < MAP_WIDTH (m); x++) 3694 for (mapspace *ms = spaces + size (); ms-- > spaces; )
3732 for (y = 0; y < MAP_HEIGHT (m); y++) 3695 for (object *tmp = ms->bot; tmp; )
3733 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = above)
3734 { 3696 {
3735 above = tmp->above; 3697 object *above = tmp->above;
3736 3698
3737 if (tmp->inv) 3699 if (tmp->inv)
3738 { 3700 {
3739 object *invtmp, *invnext; 3701 object *invtmp, *invnext;
3740 3702
3741 for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext) 3703 for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext)
3742 { 3704 {
3743 invnext = invtmp->below; 3705 invnext = invtmp->below;
3744 3706
3745 if (QUERY_FLAG (invtmp, FLAG_AUTO_APPLY)) 3707 if (QUERY_FLAG (invtmp, FLAG_AUTO_APPLY))
3746 auto_apply (invtmp); 3708 auto_apply (invtmp);
3747 else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS (invtmp)) 3709 else if (invtmp->type == TREASURE && invtmp->has_random_items ())
3748 { 3710 {
3749 while ((invtmp->stats.hp--) > 0) 3711 while ((invtmp->stats.hp--) > 0)
3750 create_treasure (invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3751
3752 invtmp->randomitems = NULL;
3753 }
3754 else if (invtmp && invtmp->arch
3755 && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS && HAS_RANDOM_ITEMS (invtmp))
3756 {
3757 create_treasure (invtmp->randomitems, invtmp, 0, m->difficulty, 0); 3712 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0);
3713
3714 invtmp->randomitems = NULL;
3715 }
3716 else if (invtmp && invtmp->arch
3717 && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS && invtmp->has_random_items ())
3718 {
3719 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0);
3758 /* Need to clear this so that we never try to create 3720 /* Need to clear this so that we never try to create
3759 * treasure again for this object 3721 * treasure again for this object
3760 */ 3722 */
3761 invtmp->randomitems = NULL; 3723 invtmp->randomitems = NULL;
3762 } 3724 }
3763 } 3725 }
3764 /* This is really temporary - the code at the bottom will 3726 /* This is really temporary - the code at the bottom will
3765 * also set randomitems to null. The problem is there are bunches 3727 * also set randomitems to null. The problem is there are bunches
3766 * of maps/players already out there with items that have spells 3728 * of maps/players already out there with items that have spells
3767 * which haven't had the randomitems set to null yet. 3729 * which haven't had the randomitems set to null yet.
3768 * MSW 2004-05-13 3730 * MSW 2004-05-13
3769 * 3731 *
3770 * And if it's a spellbook, it's better to set randomitems to NULL too, 3732 * And if it's a spellbook, it's better to set randomitems to NULL too,
3771 * else you get two spells in the book ^_- 3733 * else you get two spells in the book ^_-
3772 * Ryo 2004-08-16 3734 * Ryo 2004-08-16
3773 */ 3735 */
3774 if (tmp->type == WAND || tmp->type == ROD || tmp->type == SCROLL 3736 if (tmp->type == WAND || tmp->type == ROD || tmp->type == SCROLL
3775 || tmp->type == HORN || tmp->type == FIREWALL || tmp->type == POTION || tmp->type == ALTAR || tmp->type == SPELLBOOK) 3737 || tmp->type == HORN || tmp->type == FIREWALL || tmp->type == POTION || tmp->type == ALTAR || tmp->type == SPELLBOOK)
3776 tmp->randomitems = NULL;
3777
3778 }
3779
3780 if (QUERY_FLAG (tmp, FLAG_AUTO_APPLY))
3781 auto_apply (tmp);
3782 else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS (tmp))
3783 {
3784 while ((tmp->stats.hp--) > 0)
3785 create_treasure (tmp->randomitems, tmp, 0, m->difficulty, 0);
3786 tmp->randomitems = NULL; 3738 tmp->randomitems = NULL;
3739
3787 } 3740 }
3741
3742 if (QUERY_FLAG (tmp, FLAG_AUTO_APPLY))
3743 auto_apply (tmp);
3744 else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && tmp->has_random_items ())
3745 {
3746 while ((tmp->stats.hp--) > 0)
3747 create_treasure (tmp->randomitems, tmp, 0, difficulty, 0);
3748 tmp->randomitems = NULL;
3749 }
3788 else if (tmp->type == TIMED_GATE) 3750 else if (tmp->type == TIMED_GATE)
3789 { 3751 {
3790 object *head = tmp->head != NULL ? tmp->head : tmp; 3752 object *head = tmp->head != NULL ? tmp->head : tmp;
3791 3753
3792 if (QUERY_FLAG (head, FLAG_IS_LINKED)) 3754 if (QUERY_FLAG (head, FLAG_IS_LINKED))
3793 {
3794 tmp->speed = 0; 3755 tmp->set_speed (0);
3795 update_ob_speed (tmp);
3796 }
3797 } 3756 }
3798 /* This function can be called everytime a map is loaded, even when 3757 /* This function can be called everytime a map is loaded, even when
3799 * swapping back in. As such, we don't want to create the treasure 3758 * swapping back in. As such, we don't want to create the treasure
3800 * over and ove again, so after we generate the treasure, blank out 3759 * over and ove again, so after we generate the treasure, blank out
3801 * randomitems so if it is swapped in again, it won't make anything. 3760 * randomitems so if it is swapped in again, it won't make anything.
3802 * This is a problem for the above objects, because they have counters 3761 * This is a problem for the above objects, because they have counters
3803 * which say how many times to make the treasure. 3762 * which say how many times to make the treasure.
3804 */ 3763 */
3805 else if (tmp && tmp->arch && tmp->type != PLAYER 3764 else if (tmp && tmp->arch && tmp->type != PLAYER
3806 && tmp->type != TREASURE && tmp->type != SPELL 3765 && tmp->type != TREASURE && tmp->type != SPELL
3807 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && HAS_RANDOM_ITEMS (tmp)) 3766 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ())
3808 { 3767 {
3809 create_treasure (tmp->randomitems, tmp, GT_APPLY, m->difficulty, 0); 3768 create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0);
3810 tmp->randomitems = NULL; 3769 tmp->randomitems = NULL;
3811 } 3770 }
3771
3772 tmp = above;
3812 } 3773 }
3813 3774
3814 for (x = 0; x < MAP_WIDTH (m); x++) 3775 for (mapspace *ms = spaces + size (); ms-- > spaces; )
3815 for (y = 0; y < MAP_HEIGHT (m); y++) 3776 for (object *tmp = ms->bot; tmp; tmp = tmp->above)
3816 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above)
3817 if (tmp->above && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL)) 3777 if (tmp->above && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3818 check_trigger (tmp, tmp->above); 3778 check_trigger (tmp, tmp->above);
3819} 3779}
3820 3780
3821/** 3781/**
3822 * Handles player eating food that temporarily changes status (resistances, stats). 3782 * Handles player eating food that temporarily changes status (resistances, stats).
3823 * This used to call cast_change_attr(), but 3783 * This used to call cast_change_attr(), but
3851 { 3811 {
3852 force->resist[i] = food->resist[i] / 2; 3812 force->resist[i] = food->resist[i] / 2;
3853 did_one = 1; 3813 did_one = 1;
3854 } 3814 }
3855 } 3815 }
3816
3856 if (did_one) 3817 if (did_one)
3857 { 3818 {
3858 force->speed = 0.1; 3819 force->set_speed (0.1);
3859 update_ob_speed (force);
3860 /* bigger morsel of food = longer effect time */ 3820 /* bigger morsel of food = longer effect time */
3861 force->stats.food = food->stats.food / 5; 3821 force->duration = food->stats.food / 5;
3862 SET_FLAG (force, FLAG_IS_USED_UP);
3863 SET_FLAG (force, FLAG_APPLIED); 3822 SET_FLAG (force, FLAG_APPLIED);
3864 change_abil (who, force); 3823 change_abil (who, force);
3865 insert_ob_in_ob (force, who); 3824 insert_ob_in_ob (force, who);
3866 } 3825 }
3867 else 3826 else
3868 { 3827 force->destroy ();
3869 free_object (force);
3870 }
3871 3828
3872 /* check for hp, sp change */ 3829 /* check for hp, sp change */
3873 if (food->stats.hp != 0) 3830 if (food->stats.hp != 0)
3874 { 3831 {
3875 if (QUERY_FLAG (food, FLAG_CURSED)) 3832 if (QUERY_FLAG (food, FLAG_CURSED))
3901 new_draw_info (NDI_UNIQUE, 0, who, "You feel a rush of magical energy!"); 3858 new_draw_info (NDI_UNIQUE, 0, who, "You feel a rush of magical energy!");
3902 who->stats.sp += food->stats.sp; 3859 who->stats.sp += food->stats.sp;
3903 /* place limit on max sp from food? */ 3860 /* place limit on max sp from food? */
3904 } 3861 }
3905 } 3862 }
3906 fix_player (who); 3863 who->update_stats ();
3907} 3864}
3908
3909 3865
3910/** 3866/**
3911 * Designed primarily to light torches/lanterns/etc. 3867 * Designed primarily to light torches/lanterns/etc.
3912 * Also burns up burnable material too. First object in the inventory is 3868 * Also burns up burnable material too. First object in the inventory is
3913 * the selected object to "burn". -b.t. 3869 * the selected object to "burn". -b.t.
3914 */ 3870 */
3915
3916void 3871void
3917apply_lighter (object *who, object *lighter) 3872apply_lighter (object *who, object *lighter)
3918{ 3873{
3919 object *item; 3874 object *item;
3920 int is_player_env = 0; 3875 int is_player_env = 0;
3921 uint32 nrof;
3922 tag_t count;
3923 char item_name[MAX_BUF];
3924 3876
3925 item = find_marked_object (who); 3877 item = find_marked_object (who);
3926 if (item) 3878 if (item)
3927 { 3879 {
3928 if (lighter->last_eat && lighter->stats.food) 3880 if (lighter->last_eat && lighter->stats.food)
3929 { /* lighter gets used up */ 3881 { /* lighter gets used up */
3930 /* Split multiple lighters if they're being used up. Otherwise * 3882 /* Split multiple lighters if they're being used up. Otherwise *
3931 * one charge from each would be used up. --DAMN */ 3883 * one charge from each would be used up. --DAMN */
3932 if (lighter->nrof > 1) 3884 if (lighter->nrof > 1)
3933 { 3885 {
3934 object *oneLighter = get_object (); 3886 object *oneLighter = lighter->clone ();
3935 3887
3936 copy_object (lighter, oneLighter);
3937 lighter->nrof -= 1; 3888 lighter->nrof -= 1;
3938 oneLighter->nrof = 1; 3889 oneLighter->nrof = 1;
3939 oneLighter->stats.food--; 3890 oneLighter->stats.food--;
3940 esrv_send_item (who, lighter); 3891 esrv_send_item (who, lighter);
3941 oneLighter = insert_ob_in_ob (oneLighter, who); 3892 oneLighter = insert_ob_in_ob (oneLighter, who);
3942 esrv_send_item (who, oneLighter); 3893 esrv_send_item (who, oneLighter);
3943 } 3894 }
3944 else 3895 else
3945 {
3946 lighter->stats.food--; 3896 lighter->stats.food--;
3947 }
3948
3949 } 3897 }
3950 else if (lighter->last_eat) 3898 else if (lighter->last_eat)
3951 { /* no charges left in lighter */ 3899 { /* 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); 3900 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; 3901 return;
3954 } 3902 }
3903
3955 /* Perhaps we should split what we are trying to light on fire? 3904 /* 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 3905 * I can't see many times when you would want to light multiple
3957 * objects at once. 3906 * objects at once.
3958 */ 3907 */
3959 nrof = item->nrof; 3908
3960 count = item->count;
3961 /* 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
3963 * some sense.
3964 */
3965 strcpy (item_name, item->name);
3966 if (who == is_player_inv (item)) 3909 if (who == item->in_player ())
3967 is_player_env = 1; 3910 is_player_env = 1;
3968 3911
3969 save_throw_object (item, AT_FIRE, who); 3912 save_throw_object (item, AT_FIRE, who);
3970 /* Change to check count and not freed, since the object pointer 3913
3971 * may have gotten recycled 3914 if (item->destroyed ())
3972 */ 3915 {
3973 if ((nrof != item->nrof) || (count != item->count))
3974 {
3975 new_draw_info_format (NDI_UNIQUE, 0, who, "You light the %s with the %s.", &item_name, &lighter->name); 3916 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 3917 /* Need to update the player so that the players glow radius
3977 * gets changed. 3918 * gets changed.
3978 */ 3919 */
3979 if (is_player_env) 3920 if (is_player_env)
3980 fix_player (who); 3921 who->update_stats ();
3981 } 3922 }
3982 else 3923 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); 3924 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 } 3925 }
3988 else /* nothing to light */ 3926 else /* nothing to light */
3989 new_draw_info (NDI_UNIQUE, 0, who, "You need to mark a lightable object."); 3927 new_draw_info (NDI_UNIQUE, 0, who, "You need to mark a lightable object.");
3990 3928
3991} 3929}
4005 object *tmp; 3943 object *tmp;
4006 3944
4007 new_draw_info (NDI_UNIQUE, 0, op, "Your spell warps!."); 3945 new_draw_info (NDI_UNIQUE, 0, op, "Your spell warps!.");
4008 tmp = get_archetype (SPELL_WONDER); 3946 tmp = get_archetype (SPELL_WONDER);
4009 cast_wonder (op, op, 0, tmp); 3947 cast_wonder (op, op, 0, tmp);
4010 free_object (tmp); 3948 tmp->destroy ();
4011 } 3949 }
4012 else if (failure <= -15 && failure > -35) 3950 else if (failure <= -15 && failure > -35)
4013 { /* drain mana */ 3951 { /* drain mana */
4014 new_draw_info (NDI_UNIQUE, 0, op, "Your mana is drained!."); 3952 new_draw_info (NDI_UNIQUE, 0, op, "Your mana is drained!.");
4015 op->stats.sp -= random_roll (0, power - 1, op, PREFER_LOW); 3953 op->stats.sp -= random_roll (0, power - 1, op, PREFER_LOW);
4038 object *tmp; 3976 object *tmp;
4039 3977
4040 tmp = get_archetype (LOOSE_MANA); 3978 tmp = get_archetype (LOOSE_MANA);
4041 cast_magic_storm (op, tmp, power); 3979 cast_magic_storm (op, tmp, power);
4042 new_draw_info (NDI_UNIQUE, 0, op, "You unlease uncontrolled mana!"); 3980 new_draw_info (NDI_UNIQUE, 0, op, "You unlease uncontrolled mana!");
4043 free_object (tmp); 3981 tmp->destroy ();
4044 } 3982 }
4045 } 3983 }
4046} 3984}
4047 3985
4048void 3986void
4211 if (!new_item) 4149 if (!new_item)
4212 { 4150 {
4213 new_draw_info_format (NDI_UNIQUE, 0, pl, "This %s is strange, better to not use it.", query_base_name (marked, 0)); 4151 new_draw_info_format (NDI_UNIQUE, 0, pl, "This %s is strange, better to not use it.", query_base_name (marked, 0));
4214 return; 4152 return;
4215 } 4153 }
4154
4216 new_item->nrof = yield; 4155 new_item->nrof = yield;
4217 new_draw_info_format (NDI_UNIQUE, 0, pl, "You %s the %s.", &transformer->slaying, query_base_name (marked, 0)); 4156 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); 4157 insert_ob_in_ob (new_item, pl);
4219 esrv_send_inventory (pl, pl); 4158 esrv_send_inventory (pl, pl);
4220 /* Eat up one item */ 4159 /* Eat up one item */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines