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.22 by root, Sun Sep 10 15:59:57 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.22 2006/09/10 15:59:57 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 = find_archetype (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
737 eat_item (op, improver->slaying, sacrifice_needed); 730 eat_item (op, improver->slaying, sacrifice_needed);
738 weapon->item_power++; 731 weapon->item_power++;
739 732
740 switch (improver->stats.sp) 733 switch (improver->stats.sp)
741 { 734 {
742 case IMPROVE_STR: 735 case IMPROVE_STR:
743 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Str), 1, "strength"); 736 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Str), 1, "strength");
744 case IMPROVE_DEX: 737 case IMPROVE_DEX:
745 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Dex), 1, "dexterity"); 738 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Dex), 1, "dexterity");
746 case IMPROVE_CON: 739 case IMPROVE_CON:
747 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Con), 1, "constitution"); 740 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Con), 1, "constitution");
748 case IMPROVE_WIS: 741 case IMPROVE_WIS:
749 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Wis), 1, "wisdom"); 742 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Wis), 1, "wisdom");
750 case IMPROVE_CHA: 743 case IMPROVE_CHA:
751 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Cha), 1, "charisma"); 744 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Cha), 1, "charisma");
752 case IMPROVE_INT: 745 case IMPROVE_INT:
753 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Int), 1, "intelligence"); 746 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Int), 1, "intelligence");
754 case IMPROVE_POW: 747 case IMPROVE_POW:
755 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Pow), 1, "power"); 748 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Pow), 1, "power");
756 default: 749 default:
757 new_draw_info (NDI_UNIQUE, 0, op, "Unknown improvement type."); 750 new_draw_info (NDI_UNIQUE, 0, op, "Unknown improvement type.");
758 } 751 }
759 LOG (llevError, "improve_weapon: Got to end of function\n"); 752 LOG (llevError, "improve_weapon: Got to end of function\n");
760 return 0; 753 return 0;
761} 754}
762 755
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
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
1328 1320
1329/** 1321/**
1330 * Handles 'movement' of shop mats. 1322 * Handles 'movement' of shop mats.
1331 * Returns 1 if 'op' was destroyed, 0 if not. 1323 * Returns 1 if 'op' was destroyed, 0 if not.
1332 * Largely re-written to not use nearly as many gotos, plus 1324 * Largely re-written to not use nearly as many gotos, plus
1349 * the shop. 1341 * the shop.
1350 */ 1342 */
1351 for (tmp = op->inv; tmp; tmp = next) 1343 for (tmp = op->inv; tmp; tmp = next)
1352 { 1344 {
1353 next = tmp->below; 1345 next = tmp->below;
1346
1354 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 1347 if (QUERY_FLAG (tmp, FLAG_UNPAID))
1355 { 1348 {
1356 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);
1357 1350
1358 remove_ob (tmp); 1351 tmp->remove ();
1352
1359 if (i == -1) 1353 if (i == -1)
1360 i = 0; 1354 i = 0;
1355
1361 tmp->map = op->map; 1356 tmp->map = op->map;
1362 tmp->x = op->x + freearr_x[i]; 1357 tmp->x = op->x + freearr_x[i];
1363 tmp->y = op->y + freearr_y[i]; 1358 tmp->y = op->y + freearr_y[i];
1364 insert_ob_in_map (tmp, op->map, op, 0); 1359 insert_ob_in_map (tmp, op->map, op, 0);
1365 } 1360 }
1377 1372
1378 /* Somebody dropped an unpaid item, just move to an adjacent place. */ 1373 /* Somebody dropped an unpaid item, just move to an adjacent place. */
1379 int i = find_free_spot (op, op->map, op->x, op->y, 1, 9); 1374 int i = find_free_spot (op, op->map, op->x, op->y, 1, 9);
1380 1375
1381 if (i != -1) 1376 if (i != -1)
1382 {
1383 rv = transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 0, shop_mat); 1377 rv = transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 0, shop_mat);
1384 } 1378
1385 return 0; 1379 return 0;
1386 } 1380 }
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 /* immediate block below is only used for players */ 1386 else if (can_pay (op) && get_payment (op))
1393 else if (can_pay (op))
1394 { 1387 {
1395 get_payment (op, op->inv); 1388 /* this is only used for players */
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 {
1400 new_draw_info (NDI_UNIQUE, 0, op, shop_mat->msg); 1392 new_draw_info (NDI_UNIQUE, 0, op, shop_mat->msg);
1401 }
1402 /* 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,
1403 * but there is never a guarantee that the bottom space on the map is 1394 * but there is never a guarantee that the bottom space on the map is
1404 * actually the shop floor. 1395 * actually the shop floor.
1405 */ 1396 */
1406 else if (!rv && !is_in_shop (op)) 1397 else if (!rv && !is_in_shop (op))
1407 { 1398 {
1408 opinion = shopkeeper_approval (op->map, op); 1399 opinion = shopkeeper_approval (op->map, op);
1400
1409 if (opinion > 0.9) 1401 if (opinion > 0.9)
1410 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper gives you a friendly wave."); 1402 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper gives you a friendly wave.");
1411 else if (opinion > 0.75) 1403 else if (opinion > 0.75)
1412 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper waves to you."); 1404 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper waves to you.");
1413 else if (opinion > 0.5) 1405 else if (opinion > 0.5)
1420 { 1412 {
1421 /* 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
1422 * 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
1423 * they are not on the mat anymore 1415 * they are not on the mat anymore
1424 */ 1416 */
1425
1426 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);
1427 1418
1428 if (i == -1) 1419 if (i == -1)
1429 { 1420 {
1430 LOG (llevError, "Internal shop-mat problem.\n"); 1421 LOG (llevError, "Internal shop-mat problem.\n");
1431 } 1422 }
1432 else 1423 else
1433 { 1424 {
1434 remove_ob (op); 1425 op->remove ();
1435 op->x += freearr_x[i]; 1426 op->x += freearr_x[i];
1436 op->y += freearr_y[i]; 1427 op->y += freearr_y[i];
1437 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;
1438 } 1429 }
1439 } 1430 }
1431
1440 CLEAR_FLAG (op, FLAG_NO_APPLY); 1432 CLEAR_FLAG (op, FLAG_NO_APPLY);
1441 return rv; 1433 return rv;
1442} 1434}
1443 1435
1444/** 1436/**
1524 if (INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator))) 1516 if (INVOKE_OBJECT (MOVE_TRIGGER, trap, ARG_OBJECT (victim), ARG_OBJECT (originator)))
1525 goto leave; 1517 goto leave;
1526 1518
1527 switch (trap->type) 1519 switch (trap->type)
1528 { 1520 {
1529 case PLAYERMOVER: 1521 case PLAYERMOVER:
1530 if (trap->attacktype && (trap->level || victim->type != PLAYER) && !should_director_abort (trap, victim)) 1522 if (trap->attacktype && (trap->level || victim->type != PLAYER) && !should_director_abort (trap, victim))
1523 {
1524 if (!trap->stats.maxsp)
1525 trap->stats.maxsp = 2;
1526
1527 /* Is this correct? From the docs, it doesn't look like it
1528 * should be divided by trap->speed
1529 */
1530 victim->speed_left = -FABS (trap->stats.maxsp * victim->speed / trap->speed);
1531
1532 /* Just put in some sanity check. I think there is a bug in the
1533 * above with some objects have zero speed, and thus the player
1534 * getting permanently paralyzed.
1535 */
1536 if (victim->speed_left < -50.0)
1537 victim->speed_left = -50.0;
1538 /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left); */
1539 }
1540 goto leave;
1541
1542 case SPINNER:
1543 if (victim->direction)
1544 {
1545 victim->direction = absdir (victim->direction - trap->stats.sp);
1546 update_turn_face (victim);
1547 }
1548 goto leave;
1549
1550 case DIRECTOR:
1551 if (victim->direction && !should_director_abort (trap, victim))
1552 {
1553 victim->direction = trap->stats.sp;
1554 update_turn_face (victim);
1555 }
1556 goto leave;
1557
1558 case BUTTON:
1559 case PEDESTAL:
1560 update_button (trap);
1561 goto leave;
1562
1563 case ALTAR:
1564 /* sacrifice victim on trap */
1565 apply_altar (trap, victim, originator);
1566 goto leave;
1567
1568 case THROWN_OBJ:
1569 if (trap->inv == NULL)
1570 goto leave;
1571 /* fallthrough */
1572
1573 case ARROW:
1574 /* bad bug: monster throw a object, make a step forwards, step on object ,
1575 * trigger this here and get hit by own missile - and will be own enemy.
1576 * Victim then is his own enemy and will start to kill herself (this is
1577 * removed) but we have not synced victim and his missile. To avoid senseless
1578 * action, we avoid hits here
1579 */
1580 if ((QUERY_FLAG (victim, FLAG_ALIVE) && trap->speed) && trap->owner != victim)
1581 hit_with_arrow (trap, victim);
1582 goto leave;
1583
1584 case SPELL_EFFECT:
1585 apply_spell_effect (trap, victim);
1586 goto leave;
1587
1588 case TRAPDOOR:
1589 {
1590 int max, sound_was_played;
1591 object *ab, *ab_next;
1592
1593 if (!trap->value)
1531 { 1594 {
1532 if (!trap->stats.maxsp) 1595 int tot;
1533 trap->stats.maxsp = 2;
1534 1596
1535 /* Is this correct? From the docs, it doesn't look like it 1597 for (ab = trap->above, tot = 0; ab != NULL; ab = ab->above)
1536 * should be divided by trap->speed 1598 if ((ab->move_type && trap->move_on) || ab->move_type == 0)
1599 tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying;
1600
1601 if (!(trap->value = (tot > trap->weight) ? 1 : 0))
1602 goto leave;
1603
1604 SET_ANIMATION (trap, trap->value);
1605 update_object (trap, UP_OBJ_FACE);
1606 }
1607
1608 for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab; ab = ab_next)
1609 {
1610 /* need to set this up, since if we do transfer the object,
1611 * ab->above would be bogus
1537 */ 1612 */
1538 victim->speed_left = -FABS (trap->stats.maxsp * victim->speed / trap->speed);
1539
1540 /* Just put in some sanity check. I think there is a bug in the
1541 * above with some objects have zero speed, and thus the player
1542 * getting permanently paralyzed.
1543 */
1544 if (victim->speed_left < -50.0)
1545 victim->speed_left = -50.0;
1546 /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left); */
1547 }
1548 goto leave;
1549
1550 case SPINNER:
1551 if (victim->direction)
1552 {
1553 victim->direction = absdir (victim->direction - trap->stats.sp);
1554 update_turn_face (victim);
1555 }
1556 goto leave;
1557
1558 case DIRECTOR:
1559 if (victim->direction && !should_director_abort (trap, victim))
1560 {
1561 victim->direction = trap->stats.sp;
1562 update_turn_face (victim);
1563 }
1564 goto leave;
1565
1566 case BUTTON:
1567 case PEDESTAL:
1568 update_button (trap);
1569 goto leave;
1570
1571 case ALTAR:
1572 /* sacrifice victim on trap */
1573 apply_altar (trap, victim, originator);
1574 goto leave;
1575
1576 case THROWN_OBJ:
1577 if (trap->inv == NULL)
1578 goto leave;
1579 /* fallthrough */
1580
1581 case ARROW:
1582
1583 /* bad bug: monster throw a object, make a step forwards, step on object ,
1584 * trigger this here and get hit by own missile - and will be own enemy.
1585 * Victim then is his own enemy and will start to kill herself (this is
1586 * removed) but we have not synced victim and his missile. To avoid senseless
1587 * action, we avoid hits here
1588 */
1589 if ((QUERY_FLAG (victim, FLAG_ALIVE) && trap->speed) && trap->owner != victim)
1590 hit_with_arrow (trap, victim);
1591 goto leave;
1592
1593 case SPELL_EFFECT:
1594 apply_spell_effect (trap, victim);
1595 goto leave;
1596
1597 case TRAPDOOR:
1598 {
1599 int max, sound_was_played;
1600 object *ab, *ab_next;
1601
1602 if (!trap->value)
1603 {
1604 int tot;
1605
1606 for (ab = trap->above, tot = 0; ab != NULL; ab = ab->above)
1607 if ((ab->move_type && trap->move_on) || ab->move_type == 0)
1608 tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying;
1609
1610 if (!(trap->value = (tot > trap->weight) ? 1 : 0))
1611 goto leave;
1612
1613 SET_ANIMATION (trap, trap->value);
1614 update_object (trap, UP_OBJ_FACE);
1615 }
1616
1617 for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab; ab = ab_next)
1618 {
1619 /* need to set this up, since if we do transfer the object,
1620 * ab->above would be bogus
1621 */
1622 ab_next = ab->above; 1613 ab_next = ab->above;
1623 1614
1624 if ((ab->move_type && trap->move_on) || ab->move_type == 0) 1615 if ((ab->move_type && trap->move_on) || ab->move_type == 0)
1625 {
1626 if (!sound_was_played)
1627 {
1628 play_sound_map (trap->map, trap->x, trap->y, SOUND_FALL_HOLE);
1629 sound_was_played = 1;
1630 }
1631 new_draw_info (NDI_UNIQUE, 0, ab, "You fall into a trapdoor!");
1632 transfer_ob (ab, (int) EXIT_X (trap), (int) EXIT_Y (trap), 0, ab);
1633 }
1634 }
1635 goto leave;
1636 }
1637
1638
1639 case CONVERTER:
1640 if (convert_item (victim, trap) < 0)
1641 {
1642 object *op;
1643
1644 new_draw_info_format (NDI_UNIQUE, 0, originator, "The %s seems to be broken!", query_name (trap));
1645
1646 op = get_archetype ("burnout");
1647 if (op != NULL)
1648 { 1616 {
1649 op->x = trap->x; 1617 if (!sound_was_played)
1650 op->y = trap->y; 1618 {
1651 insert_ob_in_map (op, trap->map, trap, 0); 1619 play_sound_map (trap->map, trap->x, trap->y, SOUND_FALL_HOLE);
1620 sound_was_played = 1;
1621 }
1622 new_draw_info (NDI_UNIQUE, 0, ab, "You fall into a trapdoor!");
1623 transfer_ob (ab, (int) EXIT_X (trap), (int) EXIT_Y (trap), 0, ab);
1652 } 1624 }
1653 } 1625 }
1654 goto leave; 1626 goto leave;
1627 }
1655 1628
1629
1630 case CONVERTER:
1631 if (convert_item (victim, trap) < 0)
1632 {
1633 object *op;
1634
1635 new_draw_info_format (NDI_UNIQUE, 0, originator, "The %s seems to be broken!", query_name (trap));
1636
1637 op = get_archetype ("burnout");
1638 if (op != NULL)
1639 {
1640 op->x = trap->x;
1641 op->y = trap->y;
1642 insert_ob_in_map (op, trap->map, trap, 0);
1643 }
1644 }
1645 goto leave;
1646
1656 case TRIGGER_BUTTON: 1647 case TRIGGER_BUTTON:
1657 case TRIGGER_PEDESTAL: 1648 case TRIGGER_PEDESTAL:
1658 case TRIGGER_ALTAR: 1649 case TRIGGER_ALTAR:
1659 check_trigger (trap, victim); 1650 check_trigger (trap, victim);
1651 goto leave;
1652
1653 case DEEP_SWAMP:
1654 walk_on_deep_swamp (trap, victim);
1655 goto leave;
1656
1657 case CHECK_INV:
1658 check_inv (victim, trap);
1659 goto leave;
1660
1661 case HOLE:
1662 /* Hole not open? */
1663 if (trap->stats.wc > 0)
1660 goto leave; 1664 goto leave;
1661 1665
1662 case DEEP_SWAMP: 1666 /* Is this a multipart monster and not the head? If so, return.
1663 walk_on_deep_swamp (trap, victim); 1667 * Processing will happen if the head runs into the pit
1668 */
1669 if (victim->head)
1664 goto leave; 1670 goto leave;
1665 1671
1666 case CHECK_INV:
1667 check_inv (victim, trap);
1668 goto leave;
1669
1670 case HOLE:
1671 /* Hole not open? */
1672 if (trap->stats.wc > 0)
1673 goto leave;
1674
1675 /* Is this a multipart monster and not the head? If so, return.
1676 * Processing will happen if the head runs into the pit
1677 */
1678 if (victim->head)
1679 goto leave;
1680
1681 play_sound_map (victim->map, victim->x, victim->y, SOUND_FALL_HOLE); 1672 play_sound_map (victim->map, victim->x, victim->y, SOUND_FALL_HOLE);
1682 new_draw_info (NDI_UNIQUE, 0, victim, "You fall through the hole!\n"); 1673 new_draw_info (NDI_UNIQUE, 0, victim, "You fall through the hole!\n");
1683 transfer_ob (victim, EXIT_X (trap), EXIT_Y (trap), 1, victim); 1674 transfer_ob (victim, EXIT_X (trap), EXIT_Y (trap), 1, victim);
1684 goto leave; 1675 goto leave;
1685 1676
1686 case EXIT: 1677 case EXIT:
1687 if (victim->type == PLAYER && EXIT_PATH (trap)) 1678 if (victim->type == PLAYER && EXIT_PATH (trap))
1688 { 1679 {
1689 /* Basically, don't show exits leading to random maps the 1680 /* Basically, don't show exits leading to random maps the
1690 * players output. 1681 * players output.
1691 */ 1682 */
1692 if (trap->msg && strncmp (EXIT_PATH (trap), "/!", 2) && strncmp (EXIT_PATH (trap), "/random/", 8)) 1683 if (trap->msg && strncmp (EXIT_PATH (trap), "/!", 2))
1693 new_draw_info (NDI_NAVY, 0, victim, trap->msg); 1684 new_draw_info (NDI_NAVY, 0, victim, trap->msg);
1685
1694 enter_exit (victim, trap); 1686 victim->enter_exit (trap);
1695 } 1687 }
1696 goto leave; 1688 goto leave;
1697 1689
1698 case ENCOUNTER: 1690 case ENCOUNTER:
1699 /* may be some leftovers on this */ 1691 /* may be some leftovers on this */
1700 goto leave; 1692 goto leave;
1701 1693
1702 case SHOP_MAT: 1694 case SHOP_MAT:
1703 apply_shop_mat (trap, victim); 1695 apply_shop_mat (trap, victim);
1704 goto leave; 1696 goto leave;
1705 1697
1706 /* Drop a certain amount of gold, and have one item identified */ 1698 /* Drop a certain amount of gold, and have one item identified */
1707 case IDENTIFY_ALTAR: 1699 case IDENTIFY_ALTAR:
1708 apply_id_altar (victim, trap, originator); 1700 apply_id_altar (victim, trap, originator);
1709 goto leave; 1701 goto leave;
1710 1702
1711 case SIGN: 1703 case SIGN:
1712 if (victim->type != PLAYER && trap->stats.food > 0) 1704 if (victim->type != PLAYER && trap->stats.food > 0)
1713 goto leave; /* monsters musn't apply magic_mouths with counters */ 1705 goto leave; /* monsters musn't apply magic_mouths with counters */
1714 1706
1715 apply_sign (victim, trap, 1); 1707 apply_sign (victim, trap, 1);
1716 goto leave; 1708 goto leave;
1717 1709
1718 case CONTAINER: 1710 case CONTAINER:
1719 if (victim->type == PLAYER) 1711 if (victim->type == PLAYER)
1720 (void) esrv_apply_container (victim, trap); 1712 (void) esrv_apply_container (victim, trap);
1721 else 1713 else
1722 (void) apply_container (victim, trap); 1714 (void) apply_container (victim, trap);
1723 goto leave; 1715 goto leave;
1724 1716
1725 case RUNE: 1717 case RUNE:
1726 case TRAP: 1718 case TRAP:
1727 if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) 1719 if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE))
1728 { 1720 {
1729 spring_trap (trap, victim); 1721 spring_trap (trap, victim);
1730 } 1722 }
1731 goto leave; 1723 goto leave;
1732 1724
1733 default: 1725 default:
1734 LOG (llevDebug, "name %s, arch %s, type %d with fly/walk on/off not " 1726 LOG (llevDebug, "name %s, arch %s, type %d with fly/walk on/off not "
1735 "handled in move_apply()\n", &trap->name, &trap->arch->name, trap->type); 1727 "handled in move_apply()\n", &trap->name, &trap->arch->name, trap->type);
1736 goto leave; 1728 goto leave;
1737 } 1729 }
1738 1730
1739leave: 1731leave:
1740 recursion_depth--; 1732 recursion_depth--;
1741} 1733}
1798 1790
1799 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 1791 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1800 { 1792 {
1801 /*exp_gain *= 2; because they just identified it too */ 1793 /*exp_gain *= 2; because they just identified it too */
1802 SET_FLAG (tmp, FLAG_IDENTIFIED); 1794 SET_FLAG (tmp, FLAG_IDENTIFIED);
1795
1803 /* If in a container, update how it looks */ 1796 /* If in a container, update how it looks */
1804 if (tmp->env) 1797 if (tmp->env)
1805 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp); 1798 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp);
1806 else 1799 else
1807 op->contr->socket.update_look = 1; 1800 op->contr->ns->floorbox_update ();
1808 } 1801 }
1802
1809 change_exp (op, exp_gain, skill_ob->skill, 0); 1803 change_exp (op, exp_gain, skill_ob->skill, 0);
1810 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 */
1811 } 1805 }
1812} 1806}
1813 1807
1818static void 1812static void
1819apply_skillscroll (object *op, object *tmp) 1813apply_skillscroll (object *op, object *tmp)
1820{ 1814{
1821 switch ((int) learn_skill (op, tmp)) 1815 switch ((int) learn_skill (op, tmp))
1822 { 1816 {
1823 case 0: 1817 case 0:
1824 new_draw_info (NDI_UNIQUE, 0, op, "You already possess the knowledge "); 1818 new_draw_info (NDI_UNIQUE, 0, op, "You already possess the knowledge ");
1825 new_draw_info_format (NDI_UNIQUE, 0, op, "held within the %s.\n", query_name (tmp)); 1819 new_draw_info_format (NDI_UNIQUE, 0, op, "held within the %s.\n", query_name (tmp));
1826 return; 1820 return;
1827 1821
1828 case 1: 1822 case 1:
1829 new_draw_info_format (NDI_UNIQUE, 0, op, "You succeed in learning %s", &tmp->skill); 1823 new_draw_info_format (NDI_UNIQUE, 0, op, "You succeed in learning %s", &tmp->skill);
1830 decrease_ob (tmp); 1824 decrease_ob (tmp);
1831 return; 1825 return;
1832 1826
1833 default: 1827 default:
1834 new_draw_info_format (NDI_UNIQUE, 0, op, "You fail to learn the knowledge of the %s.\n", query_name (tmp)); 1828 new_draw_info_format (NDI_UNIQUE, 0, op, "You fail to learn the knowledge of the %s.\n", query_name (tmp));
1835 decrease_ob (tmp); 1829 decrease_ob (tmp);
1836 return; 1830 return;
1837 } 1831 }
1838} 1832}
1839 1833
1840/** 1834/**
1841 * Actually makes op learn spell. 1835 * Actually makes op learn spell.
1862 } 1856 }
1863 return; 1857 return;
1864 } 1858 }
1865 1859
1866 play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0); 1860 play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0);
1867 tmp = get_object (); 1861 tmp = spell->clone ();
1868 copy_object (spell, tmp);
1869 insert_ob_in_ob (tmp, op); 1862 insert_ob_in_ob (tmp, op);
1870 1863
1871 if (special_prayer) 1864 if (special_prayer)
1872 {
1873 SET_FLAG (tmp, FLAG_STARTEQUIP); 1865 SET_FLAG (tmp, FLAG_STARTEQUIP);
1874 }
1875 1866
1876 esrv_add_spells (op->contr, tmp); 1867 esrv_add_spells (op->contr, tmp);
1877} 1868}
1878 1869
1879/** 1870/**
1896 } 1887 }
1897 1888
1898 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);
1899 player_unready_range_ob (op->contr, spob); 1890 player_unready_range_ob (op->contr, spob);
1900 esrv_remove_spell (op->contr, spob); 1891 esrv_remove_spell (op->contr, spob);
1901 remove_ob (spob); 1892 spob->destroy ();
1902 free_object (spob);
1903} 1893}
1904 1894
1905/** 1895/**
1906 * Handles player applying a spellbook. 1896 * Handles player applying a spellbook.
1907 * 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,
1945 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.");
1946 return; 1936 return;
1947 } 1937 }
1948 1938
1949 spell = tmp->inv; 1939 spell = tmp->inv;
1940
1950 if (!spell) 1941 if (!spell)
1951 { 1942 {
1952 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);
1953 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.");
1954 return; 1945 return;
1955 } 1946 }
1956 if (spell->level > (skop->level + 10)) 1947
1948 if (skop->level < int (sqrtf (spell->level) * 1.5f))
1957 { 1949 {
1958 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.");
1959 return; 1951 return;
1960 } 1952 }
1961 1953
1962 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);
1963 1955
1964 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 1956 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1965 { 1957 {
1966 identify (tmp); 1958 identify (tmp);
1959
1967 if (tmp->env) 1960 if (tmp->env)
1968 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp); 1961 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp);
1969 else 1962 else
1970 op->contr->socket.update_look = 1; 1963 op->contr->ns->floorbox_update ();
1971 } 1964 }
1972 1965
1973 /* 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
1974 * 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
1975 * 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
1982 } 1975 }
1983 1976
1984 if (spell->skill) 1977 if (spell->skill)
1985 { 1978 {
1986 spell_skill = find_skill_by_name (op, spell->skill); 1979 spell_skill = find_skill_by_name (op, spell->skill);
1980
1987 if (!spell_skill) 1981 if (!spell_skill)
1988 { 1982 {
1989 new_draw_info_format (NDI_UNIQUE, 0, op, "You lack the skill %s to use this spell", &spell->skill); 1983 new_draw_info_format (NDI_UNIQUE, 0, op, "You lack the skill %s to use this spell", &spell->skill);
1990 return; 1984 return;
1991 } 1985 }
1986
1992 if (spell_skill->level < spell->level) 1987 if (spell_skill->level < spell->level)
1993 { 1988 {
1994 new_draw_info_format (NDI_UNIQUE, 0, op, "You need to be level %d in %s to learn this spell.", spell->level, &spell->skill); 1989 new_draw_info_format (NDI_UNIQUE, 0, op, "You need to be level %d in %s to learn this spell.", spell->level, &spell->skill);
1995 return; 1990 return;
1996 } 1991 }
2089 */ 2084 */
2090static void 2085static void
2091apply_treasure (object *op, object *tmp) 2086apply_treasure (object *op, object *tmp)
2092{ 2087{
2093 object *treas; 2088 object *treas;
2094 tag_t tmp_tag = tmp->count, op_tag = op->count;
2095 2089
2096 2090
2097 /* 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
2098 * 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
2099 * 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
2110 } 2104 }
2111 while (tmp->inv) 2105 while (tmp->inv)
2112 { 2106 {
2113 treas = tmp->inv; 2107 treas = tmp->inv;
2114 2108
2115 remove_ob (treas); 2109 treas->remove ();
2116 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));
2117 2111
2118 treas->x = op->x; 2112 treas->x = op->x;
2119 treas->y = op->y; 2113 treas->y = op->y;
2120 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);
2121 2115
2122 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))
2123 spring_trap (treas, op); 2117 spring_trap (treas, op);
2118
2124 /* If either player or container was destroyed, no need to do 2119 /* If either player or container was destroyed, no need to do
2125 * further processing. I think this should be enclused with 2120 * further processing. I think this should be enclused with
2126 * spring trap above, as I don't think there is otherwise 2121 * spring trap above, as I don't think there is otherwise
2127 * any way for the treasure chest or player to get killed 2122 * any way for the treasure chest or player to get killed
2128 */ 2123 */
2129 if (was_destroyed (op, op_tag) || was_destroyed (tmp, tmp_tag)) 2124 if (op->destroyed () || tmp->destroyed ())
2130 break; 2125 break;
2131 } 2126 }
2132 2127
2133 if (!was_destroyed (tmp, tmp_tag) && tmp->inv == NULL) 2128 if (!tmp->destroyed () && tmp->inv == NULL)
2134 decrease_ob (tmp); 2129 decrease_ob (tmp);
2135 2130
2136} 2131}
2137 2132
2138/** 2133/**
2333 2328
2334 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95) 2329 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95)
2335 { 2330 {
2336 /* resistance increased! */ 2331 /* resistance increased! */
2337 skin->resist[i]++; 2332 skin->resist[i]++;
2338 fix_player (op); 2333 op->update_stats ();
2339 2334
2340 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]);
2341 new_draw_info (NDI_UNIQUE | NDI_RED, 0, op, buf); 2336 new_draw_info (NDI_UNIQUE | NDI_RED, 0, op, buf);
2342 } 2337 }
2343 2338
2362 } 2357 }
2363 } 2358 }
2364 return 1; 2359 return 1;
2365} 2360}
2366 2361
2367static void
2368apply_savebed (object *pl)
2369{
2370#ifndef COZY_SERVER
2371 if (!pl->contr->name_changed || !pl->stats.exp)
2372 {
2373 new_draw_info (NDI_UNIQUE, 0, pl, "You don't deserve to save your character yet.");
2374 return;
2375 }
2376#endif
2377 INVOKE_PLAYER (LOGOUT, pl->contr);
2378 /* Need to call terminate_all_pets() before we remove the player ob */
2379 terminate_all_pets (pl);
2380 remove_ob (pl);
2381 pl->direction = 0;
2382 new_draw_info_format (NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, pl, "%s leaves the game.", &pl->name);
2383
2384 /* update respawn position */
2385 strcpy (pl->contr->savebed_map, pl->map->path);
2386 pl->contr->bed_x = pl->x;
2387 pl->contr->bed_y = pl->y;
2388
2389 strcpy (pl->contr->killer, "left");
2390 check_score (pl); /* Always check score */
2391 (void) save_player (pl, 0);
2392 pl->map->players--;
2393#if MAP_MAXTIMEOUT
2394 MAP_SWAP_TIME (pl->map) = MAP_TIMEOUT (pl->map);
2395#endif
2396 play_again (pl);
2397 pl->speed = 0;
2398 update_ob_speed (pl);
2399}
2400
2401/** 2362/**
2402 * Handles applying an improve armor scroll. 2363 * Handles applying an improve armor scroll.
2403 * Does some sanity checks, then calls improve_armour. 2364 * Does some sanity checks, then calls improve_armour.
2404 */ 2365 */
2405static void 2366static void
2410 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))
2411 { 2372 {
2412 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.");
2413 return; 2374 return;
2414 } 2375 }
2376
2415 armor = find_marked_object (op); 2377 armor = find_marked_object (op);
2378
2416 if (!armor) 2379 if (!armor)
2417 { 2380 {
2418 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.");
2419 return; 2382 return;
2420 } 2383 }
2384
2421 if (armor->type != ARMOUR 2385 if (armor->type != ARMOUR
2422 && armor->type != CLOAK 2386 && armor->type != CLOAK
2423 && 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)
2424 { 2388 {
2425 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");
2428 2392
2429 new_draw_info (NDI_UNIQUE, 0, op, "Applying armour enchantment."); 2393 new_draw_info (NDI_UNIQUE, 0, op, "Applying armour enchantment.");
2430 improve_armour (op, tmp, armor); 2394 improve_armour (op, tmp, armor);
2431} 2395}
2432 2396
2433
2434extern void 2397extern void
2435apply_poison (object *op, object *tmp) 2398apply_poison (object *op, object *tmp)
2436{ 2399{
2437 if (op->type == PLAYER) 2400 if (op->type == PLAYER)
2438 { 2401 {
2449 handle_apply_yield (tmp); 2412 handle_apply_yield (tmp);
2450 decrease_ob (tmp); 2413 decrease_ob (tmp);
2451} 2414}
2452 2415
2453/** 2416/**
2454 * 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.
2455 * A valid 2 way exit means: 2418 * A valid 2 way exit means:
2456 * -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)
2457 * -You are 2420 * -You are
2458 * ° the owner of the exit 2421 * ° the owner of the exit
2459 * ° or in the same party as the owner 2422 * ° or in the same party as the owner
2460 * 2423 *
2461 * 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
2462 * 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
2463 * 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).
2464 */ 2427 */
2465int 2428int
2466is_legal_2ways_exit (object *op, object *exit) 2429is_legal_2ways_exit (object *op, object *exit)
2467{ 2430{
2468 object *tmp;
2469 object *exit_owner;
2470 player *pp;
2471 mapstruct *exitmap;
2472
2473 if (exit->stats.exp != 1) 2431 if (exit->stats.exp != 1)
2474 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
2475 if (!has_been_loaded (EXIT_PATH (exit)) && exit->race) 2435 if (!has_been_loaded (EXIT_PATH (exit)) && exit->race)
2476 return 0; /* This is a reset town portal */ 2436 return 0; /* This is a reset town portal */
2477 /* To know if an exit has a correspondant, we look at 2437#endif
2478 * all the exits in destination and try to find one with same path as 2438
2479 * the current exit's position */ 2439 maptile *exitmap = maptile::find_sync (EXIT_PATH (exit), exit->map);
2480 if (!strncmp (EXIT_PATH (exit), settings.localdir, strlen (settings.localdir))) 2440
2481 exitmap = ready_map_name (EXIT_PATH (exit), MAP_PLAYER_UNIQUE);
2482 else
2483 exitmap = ready_map_name (EXIT_PATH (exit), 0);
2484 if (exitmap) 2441 if (exitmap)
2485 { 2442 {
2443 exitmap->load_sync ();
2444
2486 tmp = get_map_ob (exitmap, EXIT_X (exit), EXIT_Y (exit)); 2445 object *tmp = exitmap->at (EXIT_X (exit), EXIT_Y (exit)).bot;
2446
2487 if (!tmp) 2447 if (!tmp)
2488 return 0; 2448 return 0;
2489 for ((tmp = get_map_ob (exitmap, EXIT_X (exit), EXIT_Y (exit))); tmp; tmp = tmp->above) 2449
2450 for (; tmp; tmp = tmp->above)
2490 { 2451 {
2491 if (tmp->type != EXIT) 2452 if (tmp->type != EXIT)
2492 continue; /*Not an exit */ 2453 continue; /*Not an exit */
2454
2493 if (!EXIT_PATH (tmp)) 2455 if (!EXIT_PATH (tmp))
2494 continue; /*Not a valid exit */ 2456 continue; /*Not a valid exit */
2457
2495 if ((EXIT_X (tmp) != exit->x) || (EXIT_Y (tmp) != exit->y)) 2458 if ((EXIT_X (tmp) != exit->x) || (EXIT_Y (tmp) != exit->y))
2496 continue; /*Not in the same place */ 2459 continue; /*Not in the same place */
2460
2497 if (strcmp (exit->map->path, EXIT_PATH (tmp)) != 0) 2461 if (strcmp (exit->map->path, EXIT_PATH (tmp)) != 0)
2498 continue; /*Not in the same map */ 2462 continue; /*Not in the same map */
2499 2463
2500 /* 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
2501 * 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
2502 * town portals to prevent strangers from visiting your appartments 2466 * town portals to prevent strangers from visiting your appartments
2503 */ 2467 */
2504 if (!exit->race) 2468 if (!exit->race)
2505 return 1; /*No owner, free for all! */ 2469 return 1; /*No owner, free for all! */
2470
2506 exit_owner = NULL; 2471 object *exit_owner = 0;
2507 for (pp = first_player; pp; pp = pp->next) 2472
2473 for_all_players (pp)
2508 { 2474 {
2509 if (!pp->ob) 2475 if (!pp->ob)
2510 continue; 2476 continue;
2477
2511 if (pp->ob->name != exit->race) 2478 if (pp->ob->name != exit->race)
2512 continue; 2479 continue;
2480
2513 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 */
2514 break; 2482 break;
2515 } 2483 }
2484
2516 if (!exit_owner) 2485 if (!exit_owner)
2517 return 0; /* No more owner */ 2486 return 0; /* No more owner */
2487
2518 if (exit_owner->contr == op->contr) 2488 if (exit_owner->contr == op->contr)
2519 return 1; /*It is your exit */ 2489 return 1; /*It is your exit */
2490
2520 if (exit_owner && /*There is a owner */ 2491 if (exit_owner && /*There is a owner */
2521 (op->contr) && /*A player tries to pass */ 2492 (op->contr) && /*A player tries to pass */
2522 ((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 */
2523 (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 */
2524 return 0; 2495 return 0;
2496
2525 return 1; 2497 return 1;
2526 } 2498 }
2527 } 2499 }
2500
2528 return 0; 2501 return 0;
2529} 2502}
2530 2503
2531 2504
2532/** 2505/**
2558 { 2531 {
2559 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.");
2560 return 1; 2533 return 1;
2561 } 2534 }
2562 else 2535 else
2563 {
2564 return 0; /* monsters just skip unpaid items */ 2536 return 0; /* monsters just skip unpaid items */
2565 }
2566 } 2537 }
2567 2538
2568 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op))) 2539 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op)))
2569 return RESULT_INT (0); 2540 return RESULT_INT (0);
2570 2541
2571 switch (tmp->type) 2542 switch (tmp->type)
2572 { 2543 {
2573
2574 case CF_HANDLE: 2544 case CF_HANDLE:
2575 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle."); 2545 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2576 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);
2577 tmp->value = tmp->value ? 0 : 1; 2547 tmp->value = tmp->value ? 0 : 1;
2578 SET_ANIMATION (tmp, tmp->value); 2548 SET_ANIMATION (tmp, tmp->value);
2579 update_object (tmp, UP_OBJ_FACE); 2549 update_object (tmp, UP_OBJ_FACE);
2580 push_button (tmp); 2550 push_button (tmp);
2581 return 1; 2551 return 1;
2582 2552
2583 case TRIGGER: 2553 case TRIGGER:
2584 if (check_trigger (tmp, op)) 2554 if (check_trigger (tmp, op))
2585 { 2555 {
2586 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle."); 2556 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2587 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);
2588 } 2558 }
2589 else 2559 else
2590 {
2591 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.");
2592 } 2561
2593 return 1; 2562 return 1;
2594 2563
2595 case EXIT: 2564 case EXIT:
2596 if (op->type != PLAYER) 2565 if (op->type != PLAYER)
2566 return 0;
2567
2568 if (!EXIT_PATH (tmp) || !is_legal_2ways_exit (op, tmp))
2569 {
2570 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", query_name (tmp));
2571 }
2572 else
2573 {
2574 /* Don't display messages for random maps. */
2575 if (tmp->msg && strncmp (EXIT_PATH (tmp), "/!", 2))
2576 new_draw_info (NDI_NAVY, 0, op, tmp->msg);
2577
2578 op->enter_exit (tmp);
2579 }
2580 return 1;
2581
2582 case SIGN:
2583 apply_sign (op, tmp, 0);
2584 return 1;
2585
2586 case BOOK:
2587 if (op->type == PLAYER)
2588 {
2589 apply_book (op, tmp);
2590 return 1;
2591 }
2592 else
2593 {
2597 return 0; 2594 return 0;
2598 if (!EXIT_PATH (tmp) || !is_legal_2ways_exit (op, tmp))
2599 {
2600 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s is closed.", query_name (tmp));
2601 } 2595 }
2602 else
2603 {
2604 /* Don't display messages for random maps. */
2605 if (tmp->msg && strncmp (EXIT_PATH (tmp), "/!", 2) && strncmp (EXIT_PATH (tmp), "/random/", 8))
2606 new_draw_info (NDI_NAVY, 0, op, tmp->msg);
2607 enter_exit (op, tmp);
2608 }
2609 return 1;
2610 2596
2611 case SIGN: 2597 case SKILLSCROLL:
2612 apply_sign (op, tmp, 0);
2613 return 1;
2614
2615 case BOOK:
2616 if (op->type == PLAYER) 2598 if (op->type == PLAYER)
2617 { 2599 {
2618 apply_book (op, tmp);
2619 return 1;
2620 }
2621 else
2622 {
2623 return 0;
2624 }
2625
2626 case SKILLSCROLL:
2627 if (op->type == PLAYER)
2628 {
2629 apply_skillscroll (op, tmp); 2600 apply_skillscroll (op, tmp);
2630 return 1; 2601 return 1;
2631 } 2602 }
2603 return 0;
2604
2605 case SPELLBOOK:
2606 if (op->type == PLAYER)
2607 {
2608 apply_spellbook (op, tmp);
2609 return 1;
2610 }
2611 return 0;
2612
2613 case SCROLL:
2614 apply_scroll (op, tmp, 0);
2615 return 1;
2616
2617 case POTION:
2618 (void) apply_potion (op, tmp);
2619 return 1;
2620
2621 /* Eneq(@csd.uu.se): Handle apply on containers. */
2622 case CLOSE_CON:
2623 if (op->type == PLAYER)
2624 (void) esrv_apply_container (op, tmp->env);
2625 else
2626 (void) apply_container (op, tmp->env);
2627 return 1;
2628
2629 case CONTAINER:
2630 if (op->type == PLAYER)
2631 (void) esrv_apply_container (op, tmp);
2632 else
2633 (void) apply_container (op, tmp);
2634 return 1;
2635
2636 case TREASURE:
2637 if (op->type == PLAYER)
2638 {
2639 apply_treasure (op, tmp);
2640 return 1;
2641 }
2642 else
2643 {
2644 return 0;
2645 }
2646
2647 case WEAPON:
2648 case ARMOUR:
2649 case BOOTS:
2650 case GLOVES:
2651 case AMULET:
2652 case GIRDLE:
2653 case BRACERS:
2654 case SHIELD:
2655 case HELMET:
2656 case RING:
2657 case CLOAK:
2658 case WAND:
2659 case ROD:
2660 case HORN:
2661 case SKILL:
2662 case BOW:
2663 case LAMP:
2664 case BUILDER:
2665 case SKILL_TOOL:
2666 if (tmp->env != op)
2667 return 2; /* not in inventory */
2668 (void) apply_special (op, tmp, aflag);
2669 return 1;
2670
2671 case DRINK:
2672 case FOOD:
2673 case FLESH:
2674 apply_food (op, tmp);
2675 return 1;
2676
2677 case POISON:
2678 apply_poison (op, tmp);
2679 return 1;
2680
2681 case SAVEBED:
2682 return 1;
2683
2684 case ARMOUR_IMPROVER:
2685 if (op->type == PLAYER)
2686 {
2687 apply_armour_improver (op, tmp);
2688 return 1;
2689 }
2690 else
2632 return 0; 2691 return 0;
2633 2692
2634 case SPELLBOOK:
2635 if (op->type == PLAYER)
2636 {
2637 apply_spellbook (op, tmp);
2638 return 1;
2639 }
2640 return 0;
2641
2642 case SCROLL:
2643 apply_scroll (op, tmp, 0);
2644 return 1;
2645
2646 case POTION:
2647 (void) apply_potion (op, tmp);
2648 return 1;
2649
2650 /* Eneq(@csd.uu.se): Handle apply on containers. */
2651 case CLOSE_CON:
2652 if (op->type == PLAYER)
2653 (void) esrv_apply_container (op, tmp->env);
2654 else
2655 (void) apply_container (op, tmp->env);
2656 return 1;
2657
2658 case CONTAINER:
2659 if (op->type == PLAYER)
2660 (void) esrv_apply_container (op, tmp);
2661 else
2662 (void) apply_container (op, tmp);
2663 return 1;
2664
2665 case TREASURE:
2666 if (op->type == PLAYER)
2667 {
2668 apply_treasure (op, tmp);
2669 return 1;
2670 }
2671 else
2672 {
2673 return 0;
2674 }
2675
2676 case WEAPON:
2677 case ARMOUR:
2678 case BOOTS:
2679 case GLOVES:
2680 case AMULET:
2681 case GIRDLE:
2682 case BRACERS:
2683 case SHIELD:
2684 case HELMET:
2685 case RING:
2686 case CLOAK:
2687 case WAND:
2688 case ROD:
2689 case HORN:
2690 case SKILL:
2691 case BOW:
2692 case LAMP:
2693 case BUILDER:
2694 case SKILL_TOOL:
2695 if (tmp->env != op)
2696 return 2; /* not in inventory */
2697 (void) apply_special (op, tmp, aflag);
2698 return 1;
2699
2700 case DRINK:
2701 case FOOD:
2702 case FLESH:
2703 apply_food (op, tmp);
2704 return 1;
2705
2706 case POISON:
2707 apply_poison (op, tmp);
2708 return 1;
2709
2710 case SAVEBED:
2711 if (op->type == PLAYER)
2712 {
2713 apply_savebed (op);
2714 return 1;
2715 }
2716 else
2717 {
2718 return 0;
2719 }
2720
2721 case ARMOUR_IMPROVER:
2722 if (op->type == PLAYER)
2723 {
2724 apply_armour_improver (op, tmp);
2725 return 1;
2726 }
2727 else
2728 {
2729 return 0;
2730 }
2731
2732 case WEAPON_IMPROVER: 2693 case WEAPON_IMPROVER:
2733 (void) check_improve_weapon (op, tmp); 2694 (void) check_improve_weapon (op, tmp);
2734 return 1; 2695 return 1;
2735 2696
2736 case CLOCK: 2697 case CLOCK:
2737 if (op->type == PLAYER) 2698 if (op->type == PLAYER)
2738 { 2699 {
2739 char buf[MAX_BUF]; 2700 char buf[MAX_BUF];
2740 timeofday_t tod; 2701 timeofday_t tod;
2741 2702
2742 get_tod (&tod); 2703 get_tod (&tod);
2743 sprintf (buf, "It is %d minute%s past %d o'clock %s", 2704 sprintf (buf, "It is %d minute%s past %d o'clock %s",
2744 tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"), 2705 tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"),
2745 ((tod.hour % 14 == 0) ? 14 : ((tod.hour) % 14)), ((tod.hour >= 14) ? "pm" : "am")); 2706 ((tod.hour % 14 == 0) ? 14 : ((tod.hour) % 14)), ((tod.hour >= 14) ? "pm" : "am"));
2746 play_sound_player_only (op->contr, SOUND_CLOCK, 0, 0); 2707 play_sound_player_only (op->contr, SOUND_CLOCK, 0, 0);
2747 new_draw_info (NDI_UNIQUE, 0, op, buf); 2708 new_draw_info (NDI_UNIQUE, 0, op, buf);
2748 return 1; 2709 return 1;
2749 } 2710 }
2750 else 2711 else
2751 { 2712 {
2752 return 0; 2713 return 0;
2753 } 2714 }
2754 2715
2755 case MENU: 2716 case MENU:
2756 if (op->type == PLAYER) 2717 if (op->type == PLAYER)
2757 { 2718 {
2758 shop_listing (op); 2719 shop_listing (op);
2759 return 1; 2720 return 1;
2760 } 2721 }
2761 else 2722 else
2762 { 2723 {
2763 return 0; 2724 return 0;
2764 } 2725 }
2765 2726
2766 case POWER_CRYSTAL: 2727 case POWER_CRYSTAL:
2767 apply_power_crystal (op, tmp); /* see egoitem.c */ 2728 apply_power_crystal (op, tmp); /* see egoitem.c */
2768 return 1; 2729 return 1;
2769 2730
2770 case LIGHTER: /* for lighting torches/lanterns/etc */ 2731 case LIGHTER: /* for lighting torches/lanterns/etc */
2771 if (op->type == PLAYER) 2732 if (op->type == PLAYER)
2772 { 2733 {
2773 apply_lighter (op, tmp); 2734 apply_lighter (op, tmp);
2774 return 1; 2735 return 1;
2775 } 2736 }
2776 else 2737 else
2777 { 2738 {
2778 return 0; 2739 return 0;
2779 } 2740 }
2780 2741
2781 case ITEM_TRANSFORMER: 2742 case ITEM_TRANSFORMER:
2782 apply_item_transformer (op, tmp); 2743 apply_item_transformer (op, tmp);
2783 return 1; 2744 return 1;
2784 2745
2785 default: 2746 default:
2786 return 0; 2747 return 0;
2787 } 2748 }
2788} 2749}
2789 2750
2790 2751
2791/* quiet suppresses the "don't know how to apply" and "you must get it first" 2752/* quiet suppresses the "don't know how to apply" and "you must get it first"
2815 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))
2816 { 2777 {
2817 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);
2818 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!");
2819 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.");
2820 remove_ob (op); 2781 op->destroy ();
2821 free_object (op);
2822 return 1; 2782 return 1;
2823 } 2783 }
2824 2784
2825 pl->contr->last_used = op; 2785 pl->contr->last_used = op;
2826 pl->contr->last_used_id = op->count;
2827 2786
2828 tmp = manual_apply (pl, op, aflag); 2787 tmp = manual_apply (pl, op, aflag);
2829 if (!quiet) 2788 if (!quiet)
2830 { 2789 {
2831 if (tmp == 0) 2790 if (tmp == 0)
2897 object *tmp2; 2856 object *tmp2;
2898 2857
2899 CLEAR_FLAG (op, FLAG_APPLIED); 2858 CLEAR_FLAG (op, FLAG_APPLIED);
2900 switch (op->type) 2859 switch (op->type)
2901 { 2860 {
2902 case WEAPON: 2861 case WEAPON:
2903 new_draw_info_format (NDI_UNIQUE, 0, who, "You unwield %s.", query_name (op)); 2862 new_draw_info_format (NDI_UNIQUE, 0, who, "You unwield %s.", query_name (op));
2904 2863
2905 (void) change_abil (who, op); 2864 (void) change_abil (who, op);
2906 if (QUERY_FLAG (who, FLAG_READY_WEAPON)) 2865 if (QUERY_FLAG (who, FLAG_READY_WEAPON))
2907 CLEAR_FLAG (who, FLAG_READY_WEAPON); 2866 CLEAR_FLAG (who, FLAG_READY_WEAPON);
2908 clear_skill (who); 2867 clear_skill (who);
2909 break; 2868 break;
2910 2869
2911 case SKILL: /* allows objects to impart skills */ 2870 case SKILL: /* allows objects to impart skills */
2912 case SKILL_TOOL: 2871 case SKILL_TOOL:
2913 if (op != who->chosen_skill) 2872 if (op != who->chosen_skill)
2914 { 2873 {
2915 LOG (llevError, "BUG: apply_special(): applied skill is not a chosen skill\n"); 2874 LOG (llevError, "BUG: apply_special(): applied skill is not a chosen skill\n");
2916 } 2875 }
2917 if (who->type == PLAYER) 2876 if (who->type == PLAYER)
2918 { 2877 {
2919 if (who->contr->shoottype == range_skill) 2878 if (who->contr->shoottype == range_skill)
2920 who->contr->shoottype = range_none;
2921 if (!op->invisible)
2922 {
2923 new_draw_info_format (NDI_UNIQUE, 0, who, "You stop using the %s.", query_name (op));
2924 }
2925 else
2926 {
2927 new_draw_info_format (NDI_UNIQUE, 0, who, "You can no longer use the skill: %s.", &op->skill);
2928 }
2929 }
2930 (void) change_abil (who, op);
2931 who->chosen_skill = NULL;
2932 CLEAR_FLAG (who, FLAG_READY_SKILL);
2933 break;
2934
2935 case ARMOUR:
2936 case HELMET:
2937 case SHIELD:
2938 case RING:
2939 case BOOTS:
2940 case GLOVES:
2941 case AMULET:
2942 case GIRDLE:
2943 case BRACERS:
2944 case CLOAK:
2945 new_draw_info_format (NDI_UNIQUE, 0, who, "You unwear %s.", query_name (op));
2946 (void) change_abil (who, op);
2947 break;
2948 case LAMP:
2949 new_draw_info_format (NDI_UNIQUE, 0, who, "You turn off your %s.", &op->name);
2950 tmp2 = arch_to_object (op->other_arch);
2951 tmp2->x = op->x;
2952 tmp2->y = op->y;
2953 tmp2->map = op->map;
2954 tmp2->below = op->below;
2955 tmp2->above = op->above;
2956 tmp2->stats.food = op->stats.food;
2957 CLEAR_FLAG (tmp2, FLAG_APPLIED);
2958 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
2959 SET_FLAG (tmp2, FLAG_INV_LOCKED);
2960 if (who->type == PLAYER)
2961 esrv_del_item (who->contr, (tag_t) op->count);
2962 remove_ob (op);
2963 free_object (op);
2964 insert_ob_in_ob (tmp2, who);
2965 fix_player (who);
2966 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
2967 {
2968 if (who->type == PLAYER)
2969 {
2970 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!");
2971 SET_FLAG (tmp2, FLAG_KNOWN_CURSED);
2972 }
2973 }
2974 if (who->type == PLAYER)
2975 esrv_send_item (who, tmp2);
2976 return 1; /* otherwise, an attempt to drop causes problems */
2977 break;
2978 case BOW:
2979 case WAND:
2980 case ROD:
2981 case HORN:
2982 clear_skill (who);
2983 new_draw_info_format (NDI_UNIQUE, 0, who, "You unready %s.", query_name (op));
2984 if (who->type == PLAYER)
2985 {
2986 who->contr->shoottype = range_none; 2879 who->contr->shoottype = range_none;
2987 } 2880 if (!op->invisible)
2988 else
2989 { 2881 {
2990 if (op->type == BOW) 2882 new_draw_info_format (NDI_UNIQUE, 0, who, "You stop using the %s.", query_name (op));
2991 CLEAR_FLAG (who, FLAG_READY_BOW); 2883 }
2992 else 2884 else
2993 CLEAR_FLAG (who, FLAG_READY_RANGE); 2885 {
2886 new_draw_info_format (NDI_UNIQUE, 0, who, "You can no longer use the skill: %s.", &op->skill);
2994 } 2887 }
2888 }
2889 (void) change_abil (who, op);
2890 who->chosen_skill = NULL;
2891 CLEAR_FLAG (who, FLAG_READY_SKILL);
2995 break; 2892 break;
2996 2893
2894 case ARMOUR:
2895 case HELMET:
2997 case BUILDER: 2896 case SHIELD:
2897 case RING:
2898 case BOOTS:
2899 case GLOVES:
2900 case AMULET:
2901 case GIRDLE:
2902 case BRACERS:
2903 case CLOAK:
2904 new_draw_info_format (NDI_UNIQUE, 0, who, "You unwear %s.", query_name (op));
2905 (void) change_abil (who, op);
2906 break;
2907 case LAMP:
2908 new_draw_info_format (NDI_UNIQUE, 0, who, "You turn off your %s.", &op->name);
2909 tmp2 = arch_to_object (op->other_arch);
2910 tmp2->x = op->x;
2911 tmp2->y = op->y;
2912 tmp2->map = op->map;
2913 tmp2->below = op->below;
2914 tmp2->above = op->above;
2915 tmp2->stats.food = op->stats.food;
2916 CLEAR_FLAG (tmp2, FLAG_APPLIED);
2917
2918 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
2919 SET_FLAG (tmp2, FLAG_INV_LOCKED);
2920
2921 if (who->type == PLAYER)
2922 esrv_del_item (who->contr, op->count);
2923
2924 op->destroy ();
2925 insert_ob_in_ob (tmp2, who);
2926 who->update_stats ();
2927 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
2928 {
2929 if (who->type == PLAYER)
2930 {
2931 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!");
2932 SET_FLAG (tmp2, FLAG_KNOWN_CURSED);
2933 }
2934 }
2935 if (who->type == PLAYER)
2936 esrv_send_item (who, tmp2);
2937 return 1; /* otherwise, an attempt to drop causes problems */
2938 break;
2939 case BOW:
2940 case WAND:
2941 case ROD:
2942 case HORN:
2943 clear_skill (who);
2998 new_draw_info_format (NDI_UNIQUE, 0, who, "You unready %s.", query_name (op)); 2944 new_draw_info_format (NDI_UNIQUE, 0, who, "You unready %s.", query_name (op));
2945 if (who->type == PLAYER)
2946 {
2999 who->contr->shoottype = range_none; 2947 who->contr->shoottype = range_none;
2948 }
2949 else
2950 {
2951 if (op->type == BOW)
2952 CLEAR_FLAG (who, FLAG_READY_BOW);
2953 else
2954 CLEAR_FLAG (who, FLAG_READY_RANGE);
2955 }
2956 break;
2957
2958 case BUILDER:
2959 new_draw_info_format (NDI_UNIQUE, 0, who, "You unready %s.", query_name (op));
2960 who->contr->shoottype = range_none;
3000 who->contr->ranges[range_builder] = NULL; 2961 who->contr->ranges[range_builder] = NULL;
3001 break; 2962 break;
3002 2963
3003 default: 2964 default:
3004 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));
3005 break; 2966 break;
3006 } 2967 }
3007 2968
3008 fix_player (who); 2969 who->update_stats ();
3009 2970
3010 if (!(aflags & AP_NO_MERGE)) 2971 if (!(aflags & AP_NO_MERGE))
3011 { 2972 {
3012 object *tmp; 2973 object *tmp;
3013
3014 tag_t del_tag = op->count;
3015 2974
3016 tmp = merge_ob (op, NULL); 2975 tmp = merge_ob (op, NULL);
3017 if (who->type == PLAYER) 2976 if (who->type == PLAYER)
3018 { 2977 {
3019 if (tmp) 2978 if (tmp)
3020 { /* it was merged */ 2979 { /* it was merged */
3021 esrv_del_item (who->contr, del_tag); 2980 esrv_del_item (who->contr, op->count);
3022 op = tmp; 2981 op = tmp;
3023 } 2982 }
2983
3024 esrv_send_item (who, op); 2984 esrv_send_item (who, op);
3025 } 2985 }
3026 } 2986 }
3027 return 0; 2987 return 0;
3028} 2988}
3380 } 3340 }
3381 else 3341 else
3382 { 3342 {
3383 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))
3384 { 3344 {
3385 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:");
3386 unapply_for_ob (who, op, AP_PRINT); 3346 unapply_for_ob (who, op, AP_PRINT);
3387 return 1; 3347 return 1;
3388 } 3348 }
3389 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))
3390 { 3350 {
3392 if (i) 3352 if (i)
3393 return 1; 3353 return 1;
3394 } 3354 }
3395 } 3355 }
3396 } 3356 }
3357
3397 if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) 3358 if (op->skill && op->type != SKILL && op->type != SKILL_TOOL)
3398 { 3359 {
3399 skop = find_skill_by_name (who, op->skill); 3360 skop = find_skill_by_name (who, op->skill);
3400 if (!skop) 3361 if (!skop)
3401 { 3362 {
3432 if (INVOKE_OBJECT (BE_READY, op, ARG_OBJECT (who)) || INVOKE_OBJECT (READY, who, ARG_OBJECT (op))) 3393 if (INVOKE_OBJECT (BE_READY, op, ARG_OBJECT (who)) || INVOKE_OBJECT (READY, who, ARG_OBJECT (op)))
3433 return RESULT_INT (0); 3394 return RESULT_INT (0);
3434 3395
3435 switch (op->type) 3396 switch (op->type)
3436 { 3397 {
3437 case WEAPON: 3398 case WEAPON:
3438 if (!check_weapon_power (who, op->last_eat)) 3399 if (!check_weapon_power (who, op->last_eat))
3439 { 3400 {
3440 new_draw_info (NDI_UNIQUE, 0, who, "That weapon is too powerful for you to use."); 3401 new_draw_info (NDI_UNIQUE, 0, who, "That weapon is too powerful for you to use.");
3441 new_draw_info (NDI_UNIQUE, 0, who, "It would consume your soul!."); 3402 new_draw_info (NDI_UNIQUE, 0, who, "It would consume your soul!.");
3442 if (tmp != NULL) 3403 if (tmp != NULL)
3443 (void) insert_ob_in_ob (tmp, who);
3444 return 1;
3445 }
3446 if (op->level && (strncmp (op->name, who->name, strlen (who->name))))
3447 {
3448 /* if the weapon does not have the name as the character, can't use it. */
3449 /* (Ragnarok's sword attempted to be used by Foo: won't work) */
3450 new_draw_info (NDI_UNIQUE, 0, who, "The weapon does not recognize you as its owner.");
3451 if (tmp != NULL)
3452 (void) insert_ob_in_ob (tmp, who);
3453 return 1;
3454 }
3455 SET_FLAG (op, FLAG_APPLIED);
3456
3457 if (skop)
3458 change_skill (who, skop, 1);
3459 if (!QUERY_FLAG (who, FLAG_READY_WEAPON))
3460 SET_FLAG (who, FLAG_READY_WEAPON);
3461
3462 new_draw_info_format (NDI_UNIQUE, 0, who, "You wield %s.", query_name (op));
3463
3464 (void) change_abil (who, op);
3465 break;
3466
3467 case ARMOUR:
3468 case HELMET:
3469 case SHIELD:
3470 case BOOTS:
3471 case GLOVES:
3472 case GIRDLE:
3473 case BRACERS:
3474 case CLOAK:
3475 case RING:
3476 case AMULET:
3477 SET_FLAG (op, FLAG_APPLIED);
3478 new_draw_info_format (NDI_UNIQUE, 0, who, "You wear %s.", query_name (op));
3479 (void) change_abil (who, op);
3480 break;
3481 case LAMP:
3482 if (op->stats.food < 1)
3483 {
3484 new_draw_info_format (NDI_UNIQUE, 0, who, "Your %s is out of" " fuel!", &op->name);
3485 return 1;
3486 }
3487 new_draw_info_format (NDI_UNIQUE, 0, who, "You turn on your %s.", &op->name);
3488 tmp2 = arch_to_object (op->other_arch);
3489 tmp2->stats.food = op->stats.food;
3490 SET_FLAG (tmp2, FLAG_APPLIED);
3491 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
3492 SET_FLAG (tmp2, FLAG_INV_LOCKED);
3493 insert_ob_in_ob (tmp2, who);
3494
3495 /* Remove the old lantern */
3496 if (who->type == PLAYER)
3497 esrv_del_item (who->contr, (tag_t) op->count);
3498 remove_ob (op);
3499 free_object (op);
3500
3501 /* insert the portion that was split off */
3502 if (tmp != NULL)
3503 {
3504 (void) insert_ob_in_ob (tmp, who); 3404 (void) insert_ob_in_ob (tmp, who);
3405 return 1;
3406 }
3407 if (op->level && (strncmp (op->name, who->name, strlen (who->name))))
3408 {
3409 /* if the weapon does not have the name as the character, can't use it. */
3410 /* (Ragnarok's sword attempted to be used by Foo: won't work) */
3411 new_draw_info (NDI_UNIQUE, 0, who, "The weapon does not recognize you as its owner.");
3412 if (tmp != NULL)
3413 (void) insert_ob_in_ob (tmp, who);
3414 return 1;
3415 }
3416 SET_FLAG (op, FLAG_APPLIED);
3417
3418 if (skop)
3419 change_skill (who, skop, 1);
3420 if (!QUERY_FLAG (who, FLAG_READY_WEAPON))
3421 SET_FLAG (who, FLAG_READY_WEAPON);
3422
3423 new_draw_info_format (NDI_UNIQUE, 0, who, "You wield %s.", query_name (op));
3424
3425 (void) change_abil (who, op);
3426 break;
3427
3428 case ARMOUR:
3429 case HELMET:
3430 case SHIELD:
3431 case BOOTS:
3432 case GLOVES:
3433 case GIRDLE:
3434 case BRACERS:
3435 case CLOAK:
3436 case RING:
3437 case AMULET:
3438 SET_FLAG (op, FLAG_APPLIED);
3439 new_draw_info_format (NDI_UNIQUE, 0, who, "You wear %s.", query_name (op));
3440 (void) change_abil (who, op);
3441 break;
3442 case LAMP:
3443 if (op->stats.food < 1)
3444 {
3445 new_draw_info_format (NDI_UNIQUE, 0, who, "Your %s is out of" " fuel!", &op->name);
3446 return 1;
3447 }
3448 new_draw_info_format (NDI_UNIQUE, 0, who, "You turn on your %s.", &op->name);
3449 tmp2 = arch_to_object (op->other_arch);
3450 tmp2->stats.food = op->stats.food;
3451 SET_FLAG (tmp2, FLAG_APPLIED);
3452 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
3453 SET_FLAG (tmp2, FLAG_INV_LOCKED);
3454 insert_ob_in_ob (tmp2, who);
3455
3456 /* Remove the old lantern */
3457 if (who->type == PLAYER)
3458 esrv_del_item (who->contr, op->count);
3459
3460 op->destroy ();
3461
3462 /* insert the portion that was split off */
3463 if (tmp != NULL)
3464 {
3465 (void) insert_ob_in_ob (tmp, who);
3505 if (who->type == PLAYER) 3466 if (who->type == PLAYER)
3506 esrv_send_item (who, tmp); 3467 esrv_send_item (who, tmp);
3507 } 3468 }
3508 fix_player (who); 3469 who->update_stats ();
3509 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)) 3470 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
3510 { 3471 {
3511 if (who->type == PLAYER) 3472 if (who->type == PLAYER)
3512 { 3473 {
3513 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!");
3514 SET_FLAG (tmp2, FLAG_KNOWN_CURSED); 3475 SET_FLAG (tmp2, FLAG_KNOWN_CURSED);
3515 } 3476 }
3516 } 3477 }
3517 if (who->type == PLAYER) 3478 if (who->type == PLAYER)
3518 esrv_send_item (who, tmp2); 3479 esrv_send_item (who, tmp2);
3519 return 0; 3480 return 0;
3520 break; 3481 break;
3521 3482
3522 /* this part is needed for skill-tools */ 3483 /* this part is needed for skill-tools */
3523 case SKILL: 3484 case SKILL:
3524 case SKILL_TOOL: 3485 case SKILL_TOOL:
3525 if (who->chosen_skill) 3486 if (who->chosen_skill)
3526 { 3487 {
3527 LOG (llevError, "BUG: apply_special(): can't apply two skills\n"); 3488 LOG (llevError, "BUG: apply_special(): can't apply two skills\n");
3528 return 1; 3489 return 1;
3529 } 3490 }
3530 if (who->type == PLAYER) 3491 if (who->type == PLAYER)
3531 { 3492 {
3532 who->contr->shoottype = range_skill; 3493 who->contr->shoottype = range_skill;
3533 who->contr->ranges[range_skill] = op; 3494 who->contr->ranges[range_skill] = op;
3534 if (!op->invisible) 3495 if (!op->invisible)
3535 { 3496 {
3536 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name (op)); 3497 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name (op));
3537 new_draw_info_format (NDI_UNIQUE, 0, who, "You can now use the skill: %s.", &op->skill); 3498 new_draw_info_format (NDI_UNIQUE, 0, who, "You can now use the skill: %s.", &op->skill);
3538 } 3499 }
3539 else 3500 else
3540 { 3501 {
3541 new_draw_info_format (NDI_UNIQUE, 0, who, "Readied skill: %s.", op->skill ? &op->skill : &op->name); 3502 new_draw_info_format (NDI_UNIQUE, 0, who, "Readied skill: %s.", op->skill ? &op->skill : &op->name);
3542 } 3503 }
3543 } 3504 }
3544 SET_FLAG (op, FLAG_APPLIED); 3505 SET_FLAG (op, FLAG_APPLIED);
3545 (void) change_abil (who, op); 3506 (void) change_abil (who, op);
3546 who->chosen_skill = op; 3507 who->chosen_skill = op;
3547 SET_FLAG (who, FLAG_READY_SKILL); 3508 SET_FLAG (who, FLAG_READY_SKILL);
3548 break; 3509 break;
3549 3510
3550 case BOW: 3511 case BOW:
3551 if (!check_weapon_power (who, op->last_eat)) 3512 if (!check_weapon_power (who, op->last_eat))
3552 { 3513 {
3553 new_draw_info (NDI_UNIQUE, 0, who, "That item is too powerful for you to use."); 3514 new_draw_info (NDI_UNIQUE, 0, who, "That item is too powerful for you to use.");
3554 new_draw_info (NDI_UNIQUE, 0, who, "It would consume your soul!."); 3515 new_draw_info (NDI_UNIQUE, 0, who, "It would consume your soul!.");
3555 if (tmp != NULL) 3516 if (tmp != NULL)
3556 (void) insert_ob_in_ob (tmp, who); 3517 (void) insert_ob_in_ob (tmp, who);
3557 return 1; 3518 return 1;
3558 } 3519 }
3559 if (op->level && (strncmp (op->name, who->name, strlen (who->name)))) 3520 if (op->level && (strncmp (op->name, who->name, strlen (who->name))))
3560 { 3521 {
3561 new_draw_info (NDI_UNIQUE, 0, who, "The weapon does not recognize you as its owner."); 3522 new_draw_info (NDI_UNIQUE, 0, who, "The weapon does not recognize you as its owner.");
3562 if (tmp != NULL) 3523 if (tmp != NULL)
3563 (void) insert_ob_in_ob (tmp, who); 3524 (void) insert_ob_in_ob (tmp, who);
3564 return 1; 3525 return 1;
3565 } 3526 }
3566 /*FALLTHROUGH*/ case WAND: 3527 /*FALLTHROUGH*/ case WAND:
3567 case ROD: 3528 case ROD:
3568 case HORN: 3529 case HORN:
3569 /* check for skill, alter player status */ 3530 /* check for skill, alter player status */
3570 SET_FLAG (op, FLAG_APPLIED); 3531 SET_FLAG (op, FLAG_APPLIED);
3571 if (skop) 3532 if (skop)
3572 change_skill (who, skop, 0); 3533 change_skill (who, skop, 0);
3573 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name (op)); 3534 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name (op));
3574 3535
3575 if (who->type == PLAYER) 3536 if (who->type == PLAYER)
3576 { 3537 {
3577 if (op->type == BOW) 3538 if (op->type == BOW)
3578 { 3539 {
3579 (void) change_abil (who, op); 3540 (void) change_abil (who, op);
3580 new_draw_info_format (NDI_UNIQUE, 0, who, 3541 new_draw_info_format (NDI_UNIQUE, 0, who,
3581 "You will now fire %s with %s.", op->race ? &op->race : "nothing", query_name (op)); 3542 "You will now fire %s with %s.", op->race ? &op->race : "nothing", query_name (op));
3582 who->contr->shoottype = range_bow; 3543 who->contr->shoottype = range_bow;
3583 } 3544 }
3584 else 3545 else
3585 { 3546 {
3586 who->contr->shoottype = range_misc; 3547 who->contr->shoottype = range_misc;
3587 } 3548 }
3588 } 3549 }
3589 else 3550 else
3590 { 3551 {
3591 if (op->type == BOW) 3552 if (op->type == BOW)
3592 SET_FLAG (who, FLAG_READY_BOW); 3553 SET_FLAG (who, FLAG_READY_BOW);
3593 else 3554 else
3594 SET_FLAG (who, FLAG_READY_RANGE); 3555 SET_FLAG (who, FLAG_READY_RANGE);
3595 } 3556 }
3596 break; 3557 break;
3597 3558
3598 case BUILDER: 3559 case BUILDER:
3599 if (who->contr->ranges[range_builder]) 3560 if (who->contr->ranges[range_builder])
3600 unapply_special (who, who->contr->ranges[range_builder], 0); 3561 unapply_special (who, who->contr->ranges[range_builder], 0);
3601 who->contr->shoottype = range_builder; 3562 who->contr->shoottype = range_builder;
3602 who->contr->ranges[range_builder] = op; 3563 who->contr->ranges[range_builder] = op;
3603 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready your %s.", query_name (op)); 3564 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready your %s.", query_name (op));
3604 break; 3565 break;
3605 3566
3606 default: 3567 default:
3607 new_draw_info_format (NDI_UNIQUE, 0, who, "You apply %s.", query_name (op)); 3568 new_draw_info_format (NDI_UNIQUE, 0, who, "You apply %s.", query_name (op));
3608 } /* end of switch op->type */ 3569 } /* end of switch op->type */
3609 3570
3610 SET_FLAG (op, FLAG_APPLIED); 3571 SET_FLAG (op, FLAG_APPLIED);
3611 3572
3612 if (tmp != NULL) 3573 if (tmp != NULL)
3613 tmp = insert_ob_in_ob (tmp, who); 3574 tmp = insert_ob_in_ob (tmp, who);
3614 3575
3615 fix_player (who); 3576 who->update_stats ();
3616 3577
3617 /* We exclude spell casting objects. The fire code will set the 3578 /* We exclude spell casting objects. The fire code will set the
3618 * been applied flag when they are used - until that point, 3579 * been applied flag when they are used - until that point,
3619 * you don't know anything about them. 3580 * you don't know anything about them.
3620 */ 3581 */
3659 object *tmp = NULL, *tmp2; 3620 object *tmp = NULL, *tmp2;
3660 int i; 3621 int i;
3661 3622
3662 switch (op->type) 3623 switch (op->type)
3663 { 3624 {
3664 case SHOP_FLOOR: 3625 case SHOP_FLOOR:
3665 if (!HAS_RANDOM_ITEMS (op)) 3626 if (!op->has_random_items ())
3666 return 0; 3627 return 0;
3628
3667 do 3629 do
3668 { 3630 {
3669 i = 10; /* let's give it 10 tries */ 3631 i = 10; /* let's give it 10 tries */
3670 while ((tmp = generate_treasure (op->randomitems, 3632 while ((tmp = generate_treasure (op->randomitems,
3671 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);
3672 if (tmp == NULL) 3634 if (tmp == NULL)
3673 return 0; 3635 return 0;
3674 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 3636 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
3675 { 3637 {
3676 free_object (tmp); 3638 tmp->destroy ();
3677 tmp = NULL; 3639 tmp = NULL;
3678 } 3640 }
3679 } 3641 }
3680 while (!tmp); 3642 while (!tmp);
3643
3681 tmp->x = op->x; 3644 tmp->x = op->x;
3682 tmp->y = op->y; 3645 tmp->y = op->y;
3683 SET_FLAG (tmp, FLAG_UNPAID); 3646 SET_FLAG (tmp, FLAG_UNPAID);
3684 insert_ob_in_map (tmp, op->map, NULL, 0); 3647 insert_ob_in_map (tmp, op->map, NULL, 0);
3685 CLEAR_FLAG (op, FLAG_AUTO_APPLY); 3648 CLEAR_FLAG (op, FLAG_AUTO_APPLY);
3686 identify (tmp); 3649 identify (tmp);
3687 break; 3650 break;
3688 3651
3689 case TREASURE: 3652 case TREASURE:
3690 if (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE)) 3653 if (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))
3691 return 0; 3654 return 0;
3655
3692 while ((op->stats.hp--) > 0) 3656 while ((op->stats.hp--) > 0)
3693 create_treasure (op->randomitems, op, op->map ? GT_ENVIRONMENT : 0, 3657 create_treasure (op->randomitems, op, op->map ? GT_ENVIRONMENT : 0,
3694 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);
3695 3659
3696 /* 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,
3697 * move it to the parent object as the current object is about 3661 * move it to the parent object as the current object is about
3698 * to disappear. An example of this item is the random_* stuff 3662 * to disappear. An example of this item is the random_* stuff
3699 * that is put inside other objects. 3663 * that is put inside other objects.
3700 */ 3664 */
3701 for (tmp = op->inv; tmp; tmp = tmp2) 3665 for (tmp = op->inv; tmp; tmp = tmp2)
3702 { 3666 {
3703 tmp2 = tmp->below; 3667 tmp2 = tmp->below;
3704 remove_ob (tmp); 3668 tmp->remove ();
3669
3705 if (op->env) 3670 if (op->env)
3706 insert_ob_in_ob (tmp, op->env); 3671 insert_ob_in_ob (tmp, op->env);
3707 else 3672 else
3708 free_object (tmp); 3673 tmp->destroy ();
3709 } 3674 }
3710 remove_ob (op); 3675
3711 free_object (op); 3676 op->destroy ();
3712 break; 3677 break;
3713 } 3678 }
3714 return tmp ? 1 : 0; 3679 return tmp ? 1 : 0;
3715} 3680}
3716 3681
3717/** 3682/**
3719 * when an original map is loaded) and performs special actions for 3684 * when an original map is loaded) and performs special actions for
3720 * certain objects (most initialization of chests and creation of 3685 * certain objects (most initialization of chests and creation of
3721 * treasures and stuff). Calls auto_apply if appropriate. 3686 * treasures and stuff). Calls auto_apply if appropriate.
3722 */ 3687 */
3723void 3688void
3724fix_auto_apply (mapstruct *m) 3689maptile::fix_auto_apply ()
3725{ 3690{
3726 object *tmp, *above = NULL; 3691 if (!spaces)
3727 int x, y;
3728
3729 if (m == NULL)
3730 return; 3692 return;
3731 3693
3732 for (x = 0; x < MAP_WIDTH (m); x++) 3694 for (mapspace *ms = spaces + size (); ms-- > spaces; )
3733 for (y = 0; y < MAP_HEIGHT (m); y++) 3695 for (object *tmp = ms->bot; tmp; )
3734 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = above)
3735 { 3696 {
3736 above = tmp->above; 3697 object *above = tmp->above;
3737 3698
3738 if (tmp->inv) 3699 if (tmp->inv)
3739 { 3700 {
3740 object *invtmp, *invnext; 3701 object *invtmp, *invnext;
3741 3702
3742 for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext) 3703 for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext)
3743 { 3704 {
3744 invnext = invtmp->below; 3705 invnext = invtmp->below;
3745 3706
3746 if (QUERY_FLAG (invtmp, FLAG_AUTO_APPLY)) 3707 if (QUERY_FLAG (invtmp, FLAG_AUTO_APPLY))
3747 auto_apply (invtmp); 3708 auto_apply (invtmp);
3748 else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS (invtmp)) 3709 else if (invtmp->type == TREASURE && invtmp->has_random_items ())
3749 { 3710 {
3750 while ((invtmp->stats.hp--) > 0) 3711 while ((invtmp->stats.hp--) > 0)
3751 create_treasure (invtmp->randomitems, invtmp, 0, m->difficulty, 0);
3752
3753 invtmp->randomitems = NULL;
3754 }
3755 else if (invtmp && invtmp->arch
3756 && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS && HAS_RANDOM_ITEMS (invtmp))
3757 {
3758 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);
3759 /* Need to clear this so that we never try to create 3720 /* Need to clear this so that we never try to create
3760 * treasure again for this object 3721 * treasure again for this object
3761 */ 3722 */
3762 invtmp->randomitems = NULL; 3723 invtmp->randomitems = NULL;
3763 } 3724 }
3764 } 3725 }
3765 /* This is really temporary - the code at the bottom will 3726 /* This is really temporary - the code at the bottom will
3766 * also set randomitems to null. The problem is there are bunches 3727 * also set randomitems to null. The problem is there are bunches
3767 * of maps/players already out there with items that have spells 3728 * of maps/players already out there with items that have spells
3768 * which haven't had the randomitems set to null yet. 3729 * which haven't had the randomitems set to null yet.
3769 * MSW 2004-05-13 3730 * MSW 2004-05-13
3770 * 3731 *
3771 * 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,
3772 * else you get two spells in the book ^_- 3733 * else you get two spells in the book ^_-
3773 * Ryo 2004-08-16 3734 * Ryo 2004-08-16
3774 */ 3735 */
3775 if (tmp->type == WAND || tmp->type == ROD || tmp->type == SCROLL 3736 if (tmp->type == WAND || tmp->type == ROD || tmp->type == SCROLL
3776 || 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)
3777 tmp->randomitems = NULL;
3778
3779 }
3780
3781 if (QUERY_FLAG (tmp, FLAG_AUTO_APPLY))
3782 auto_apply (tmp);
3783 else if ((tmp->type == TREASURE || (tmp->type == CONTAINER)) && HAS_RANDOM_ITEMS (tmp))
3784 {
3785 while ((tmp->stats.hp--) > 0)
3786 create_treasure (tmp->randomitems, tmp, 0, m->difficulty, 0);
3787 tmp->randomitems = NULL; 3738 tmp->randomitems = NULL;
3739
3788 } 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 }
3789 else if (tmp->type == TIMED_GATE) 3750 else if (tmp->type == TIMED_GATE)
3790 { 3751 {
3791 object *head = tmp->head != NULL ? tmp->head : tmp; 3752 object *head = tmp->head != NULL ? tmp->head : tmp;
3792 3753
3793 if (QUERY_FLAG (head, FLAG_IS_LINKED)) 3754 if (QUERY_FLAG (head, FLAG_IS_LINKED))
3794 {
3795 tmp->speed = 0; 3755 tmp->set_speed (0);
3796 update_ob_speed (tmp);
3797 }
3798 } 3756 }
3799 /* 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
3800 * 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
3801 * 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
3802 * 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.
3803 * 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
3804 * which say how many times to make the treasure. 3762 * which say how many times to make the treasure.
3805 */ 3763 */
3806 else if (tmp && tmp->arch && tmp->type != PLAYER 3764 else if (tmp && tmp->arch && tmp->type != PLAYER
3807 && tmp->type != TREASURE && tmp->type != SPELL 3765 && tmp->type != TREASURE && tmp->type != SPELL
3808 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && HAS_RANDOM_ITEMS (tmp)) 3766 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ())
3809 { 3767 {
3810 create_treasure (tmp->randomitems, tmp, GT_APPLY, m->difficulty, 0); 3768 create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0);
3811 tmp->randomitems = NULL; 3769 tmp->randomitems = NULL;
3812 } 3770 }
3771
3772 tmp = above;
3813 } 3773 }
3814 3774
3815 for (x = 0; x < MAP_WIDTH (m); x++) 3775 for (mapspace *ms = spaces + size (); ms-- > spaces; )
3816 for (y = 0; y < MAP_HEIGHT (m); y++) 3776 for (object *tmp = ms->bot; tmp; tmp = tmp->above)
3817 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above)
3818 if (tmp->above && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL)) 3777 if (tmp->above && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3819 check_trigger (tmp, tmp->above); 3778 check_trigger (tmp, tmp->above);
3820} 3779}
3821 3780
3822/** 3781/**
3823 * Handles player eating food that temporarily changes status (resistances, stats). 3782 * Handles player eating food that temporarily changes status (resistances, stats).
3824 * This used to call cast_change_attr(), but 3783 * This used to call cast_change_attr(), but
3852 { 3811 {
3853 force->resist[i] = food->resist[i] / 2; 3812 force->resist[i] = food->resist[i] / 2;
3854 did_one = 1; 3813 did_one = 1;
3855 } 3814 }
3856 } 3815 }
3816
3857 if (did_one) 3817 if (did_one)
3858 { 3818 {
3859 force->speed = 0.1; 3819 force->set_speed (0.1);
3860 update_ob_speed (force);
3861 /* bigger morsel of food = longer effect time */ 3820 /* bigger morsel of food = longer effect time */
3862 force->stats.food = food->stats.food / 5; 3821 force->duration = food->stats.food / 5;
3863 SET_FLAG (force, FLAG_IS_USED_UP);
3864 SET_FLAG (force, FLAG_APPLIED); 3822 SET_FLAG (force, FLAG_APPLIED);
3865 change_abil (who, force); 3823 change_abil (who, force);
3866 insert_ob_in_ob (force, who); 3824 insert_ob_in_ob (force, who);
3867 } 3825 }
3868 else 3826 else
3869 { 3827 force->destroy ();
3870 free_object (force);
3871 }
3872 3828
3873 /* check for hp, sp change */ 3829 /* check for hp, sp change */
3874 if (food->stats.hp != 0) 3830 if (food->stats.hp != 0)
3875 { 3831 {
3876 if (QUERY_FLAG (food, FLAG_CURSED)) 3832 if (QUERY_FLAG (food, FLAG_CURSED))
3902 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!");
3903 who->stats.sp += food->stats.sp; 3859 who->stats.sp += food->stats.sp;
3904 /* place limit on max sp from food? */ 3860 /* place limit on max sp from food? */
3905 } 3861 }
3906 } 3862 }
3907 fix_player (who); 3863 who->update_stats ();
3908} 3864}
3909
3910 3865
3911/** 3866/**
3912 * Designed primarily to light torches/lanterns/etc. 3867 * Designed primarily to light torches/lanterns/etc.
3913 * 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
3914 * the selected object to "burn". -b.t. 3869 * the selected object to "burn". -b.t.
3915 */ 3870 */
3916
3917void 3871void
3918apply_lighter (object *who, object *lighter) 3872apply_lighter (object *who, object *lighter)
3919{ 3873{
3920 object *item; 3874 object *item;
3921 int is_player_env = 0; 3875 int is_player_env = 0;
3922 uint32 nrof;
3923 tag_t count;
3924 char item_name[MAX_BUF];
3925 3876
3926 item = find_marked_object (who); 3877 item = find_marked_object (who);
3927 if (item) 3878 if (item)
3928 { 3879 {
3929 if (lighter->last_eat && lighter->stats.food) 3880 if (lighter->last_eat && lighter->stats.food)
3930 { /* lighter gets used up */ 3881 { /* lighter gets used up */
3931 /* Split multiple lighters if they're being used up. Otherwise * 3882 /* Split multiple lighters if they're being used up. Otherwise *
3932 * one charge from each would be used up. --DAMN */ 3883 * one charge from each would be used up. --DAMN */
3933 if (lighter->nrof > 1) 3884 if (lighter->nrof > 1)
3934 { 3885 {
3935 object *oneLighter = get_object (); 3886 object *oneLighter = lighter->clone ();
3936 3887
3937 copy_object (lighter, oneLighter);
3938 lighter->nrof -= 1; 3888 lighter->nrof -= 1;
3939 oneLighter->nrof = 1; 3889 oneLighter->nrof = 1;
3940 oneLighter->stats.food--; 3890 oneLighter->stats.food--;
3941 esrv_send_item (who, lighter); 3891 esrv_send_item (who, lighter);
3942 oneLighter = insert_ob_in_ob (oneLighter, who); 3892 oneLighter = insert_ob_in_ob (oneLighter, who);
3943 esrv_send_item (who, oneLighter); 3893 esrv_send_item (who, oneLighter);
3944 } 3894 }
3945 else 3895 else
3946 {
3947 lighter->stats.food--; 3896 lighter->stats.food--;
3948 }
3949
3950 } 3897 }
3951 else if (lighter->last_eat) 3898 else if (lighter->last_eat)
3952 { /* no charges left in lighter */ 3899 { /* no charges left in lighter */
3953 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);
3954 return; 3901 return;
3955 } 3902 }
3903
3956 /* 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?
3957 * 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
3958 * objects at once. 3906 * objects at once.
3959 */ 3907 */
3960 nrof = item->nrof; 3908
3961 count = item->count;
3962 /* If the item is destroyed, we don't have a valid pointer to the
3963 * name object, so make a copy so the message we print out makes
3964 * some sense.
3965 */
3966 strcpy (item_name, item->name);
3967 if (who == is_player_inv (item)) 3909 if (who == item->in_player ())
3968 is_player_env = 1; 3910 is_player_env = 1;
3969 3911
3970 save_throw_object (item, AT_FIRE, who); 3912 save_throw_object (item, AT_FIRE, who);
3971 /* Change to check count and not freed, since the object pointer 3913
3972 * may have gotten recycled 3914 if (item->destroyed ())
3973 */ 3915 {
3974 if ((nrof != item->nrof) || (count != item->count))
3975 {
3976 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);
3977 /* Need to update the player so that the players glow radius 3917 /* Need to update the player so that the players glow radius
3978 * gets changed. 3918 * gets changed.
3979 */ 3919 */
3980 if (is_player_env) 3920 if (is_player_env)
3981 fix_player (who); 3921 who->update_stats ();
3982 } 3922 }
3983 else 3923 else
3984 {
3985 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);
3986 }
3987
3988 } 3925 }
3989 else /* nothing to light */ 3926 else /* nothing to light */
3990 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.");
3991 3928
3992} 3929}
4006 object *tmp; 3943 object *tmp;
4007 3944
4008 new_draw_info (NDI_UNIQUE, 0, op, "Your spell warps!."); 3945 new_draw_info (NDI_UNIQUE, 0, op, "Your spell warps!.");
4009 tmp = get_archetype (SPELL_WONDER); 3946 tmp = get_archetype (SPELL_WONDER);
4010 cast_wonder (op, op, 0, tmp); 3947 cast_wonder (op, op, 0, tmp);
4011 free_object (tmp); 3948 tmp->destroy ();
4012 } 3949 }
4013 else if (failure <= -15 && failure > -35) 3950 else if (failure <= -15 && failure > -35)
4014 { /* drain mana */ 3951 { /* drain mana */
4015 new_draw_info (NDI_UNIQUE, 0, op, "Your mana is drained!."); 3952 new_draw_info (NDI_UNIQUE, 0, op, "Your mana is drained!.");
4016 op->stats.sp -= random_roll (0, power - 1, op, PREFER_LOW); 3953 op->stats.sp -= random_roll (0, power - 1, op, PREFER_LOW);
4039 object *tmp; 3976 object *tmp;
4040 3977
4041 tmp = get_archetype (LOOSE_MANA); 3978 tmp = get_archetype (LOOSE_MANA);
4042 cast_magic_storm (op, tmp, power); 3979 cast_magic_storm (op, tmp, power);
4043 new_draw_info (NDI_UNIQUE, 0, op, "You unlease uncontrolled mana!"); 3980 new_draw_info (NDI_UNIQUE, 0, op, "You unlease uncontrolled mana!");
4044 free_object (tmp); 3981 tmp->destroy ();
4045 } 3982 }
4046 } 3983 }
4047} 3984}
4048 3985
4049void 3986void
4053 for the race, put the excess stat some 3990 for the race, put the excess stat some
4054 where else. */ 3991 where else. */
4055 3992
4056 switch (change->type) 3993 switch (change->type)
4057 { 3994 {
4058 case CLASS: 3995 case CLASS:
4059 { 3996 {
4060 living *stats = &(pl->contr->orig_stats); 3997 living *stats = &(pl->contr->orig_stats);
4061 living *ns = &(change->stats); 3998 living *ns = &(change->stats);
4062 object *walk; 3999 object *walk;
4063 int flag_change_face = 1; 4000 int flag_change_face = 1;
4064 4001
4065 /* the following code assigns stats up to the stat max 4002 /* the following code assigns stats up to the stat max
4066 * for the race, and if the stat max is exceeded, 4003 * for the race, and if the stat max is exceeded,
4067 * tries to randomly reassign the excess stat 4004 * tries to randomly reassign the excess stat
4068 */ 4005 */
4069 int i, j; 4006 int i, j;
4070 4007
4071 for (i = 0; i < NUM_STATS; i++) 4008 for (i = 0; i < NUM_STATS; i++)
4072 { 4009 {
4073 sint8 stat = get_attr_value (stats, i); 4010 sint8 stat = get_attr_value (stats, i);
4074 int race_bonus = get_attr_value (&(pl->arch->clone.stats), i); 4011 int race_bonus = get_attr_value (&(pl->arch->clone.stats), i);
4075 4012
4076 stat += get_attr_value (ns, i); 4013 stat += get_attr_value (ns, i);
4077 if (stat > 20 + race_bonus) 4014 if (stat > 20 + race_bonus)
4078 { 4015 {
4079 excess_stat++; 4016 excess_stat++;
4080 stat = 20 + race_bonus; 4017 stat = 20 + race_bonus;
4081 } 4018 }
4082 set_attr_value (stats, i, stat); 4019 set_attr_value (stats, i, stat);
4083 } 4020 }
4084 4021
4085 for (j = 0; excess_stat > 0 && j < 100; j++) 4022 for (j = 0; excess_stat > 0 && j < 100; j++)
4086 { /* try 100 times to assign excess stats */ 4023 { /* try 100 times to assign excess stats */
4087 int i = rndm (0, 6); 4024 int i = rndm (0, 6);
4088 int stat = get_attr_value (stats, i); 4025 int stat = get_attr_value (stats, i);
4089 int race_bonus = get_attr_value (&(pl->arch->clone.stats), i); 4026 int race_bonus = get_attr_value (&(pl->arch->clone.stats), i);
4090 4027
4091 if (i == CHA) 4028 if (i == CHA)
4092 continue; /* exclude cha from this */ 4029 continue; /* exclude cha from this */
4093 if (stat < 20 + race_bonus) 4030 if (stat < 20 + race_bonus)
4094 { 4031 {
4095 change_attr_value (stats, i, 1); 4032 change_attr_value (stats, i, 1);
4096 excess_stat--; 4033 excess_stat--;
4097 } 4034 }
4098 } 4035 }
4099 4036
4100 /* insert the randomitems from the change's treasurelist into 4037 /* insert the randomitems from the change's treasurelist into
4101 * the player ref: player.c 4038 * the player ref: player.c
4102 */ 4039 */
4103 if (change->randomitems != NULL) 4040 if (change->randomitems != NULL)
4104 give_initial_items (pl, change->randomitems); 4041 give_initial_items (pl, change->randomitems);
4105 4042
4106 4043
4107 /* set up the face, for some races. */ 4044 /* set up the face, for some races. */
4108 4045
4109 /* first, look for the force object banning 4046 /* first, look for the force object banning
4110 * changing the face. Certain races never change face with class. 4047 * changing the face. Certain races never change face with class.
4111 */ 4048 */
4112 for (walk = pl->inv; walk != NULL; walk = walk->below) 4049 for (walk = pl->inv; walk != NULL; walk = walk->below)
4113 if (!strcmp (walk->name, "NOCLASSFACECHANGE")) 4050 if (!strcmp (walk->name, "NOCLASSFACECHANGE"))
4114 flag_change_face = 0; 4051 flag_change_face = 0;
4115 4052
4116 if (flag_change_face) 4053 if (flag_change_face)
4117 { 4054 {
4118 pl->animation_id = GET_ANIM_ID (change); 4055 pl->animation_id = GET_ANIM_ID (change);
4119 pl->face = change->face; 4056 pl->face = change->face;
4120 4057
4121 if (QUERY_FLAG (change, FLAG_ANIMATE)) 4058 if (QUERY_FLAG (change, FLAG_ANIMATE))
4122 SET_FLAG (pl, FLAG_ANIMATE); 4059 SET_FLAG (pl, FLAG_ANIMATE);
4123 else 4060 else
4124 CLEAR_FLAG (pl, FLAG_ANIMATE); 4061 CLEAR_FLAG (pl, FLAG_ANIMATE);
4125 } 4062 }
4126 4063
4127 /* check the special case of can't use weapons */ 4064 /* check the special case of can't use weapons */
4128 /*if(QUERY_FLAG(change,FLAG_USE_WEAPON)) CLEAR_FLAG(pl,FLAG_USE_WEAPON); */ 4065 /*if(QUERY_FLAG(change,FLAG_USE_WEAPON)) CLEAR_FLAG(pl,FLAG_USE_WEAPON); */
4129 if (!strcmp (change->name, "monk")) 4066 if (!strcmp (change->name, "monk"))
4130 CLEAR_FLAG (pl, FLAG_USE_WEAPON); 4067 CLEAR_FLAG (pl, FLAG_USE_WEAPON);
4131 4068
4132 break; 4069 break;
4133 } 4070 }
4134 } 4071 }
4135} 4072}
4136 4073
4137/** 4074/**
4138 * This handles items of type 'transformer'. 4075 * This handles items of type 'transformer'.
4212 if (!new_item) 4149 if (!new_item)
4213 { 4150 {
4214 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));
4215 return; 4152 return;
4216 } 4153 }
4154
4217 new_item->nrof = yield; 4155 new_item->nrof = yield;
4218 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));
4219 insert_ob_in_ob (new_item, pl); 4157 insert_ob_in_ob (new_item, pl);
4220 esrv_send_inventory (pl, pl); 4158 esrv_send_inventory (pl, pl);
4221 /* Eat up one item */ 4159 /* Eat up one item */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines