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.20 by root, Mon Sep 4 16:46:33 2006 UTC vs.
Revision 1.59 by pippijn, Sat Jan 6 14:42:30 2007 UTC

1/*
2 * static char *rcsid_apply_c =
3 * "$Id: apply.C,v 1.20 2006/09/04 16:46:33 root Exp $";
4 */
5/* 1/*
6 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
7 3
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
8 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 5 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
9 Copyright (C) 1992 Frank Tore Johansen 6 Copyright (C) 1992 Frank Tore Johansen
10 7
11 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
12 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
20 17
21 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
22 along with this program; if not, write to the Free Software 19 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 21
25 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>
26*/ 23*/
27 24
28#include <global.h> 25#include <global.h>
29#include <living.h> 26#include <living.h>
30#include <spells.h> 27#include <spells.h>
31#include <skills.h> 28#include <skills.h>
32#include <tod.h> 29#include <tod.h>
33 30
34#ifndef __CEXTRACT__
35#include <sproto.h> 31#include <sproto.h>
36#endif
37 32
38/* Want this regardless of rplay. */ 33/* Want this regardless of rplay. */
39#include <sounds.h> 34#include <sounds.h>
40 35
41/* 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() */
43 38
44/** 39/**
45 * Check if op should abort moving victim because of it's race or slaying. 40 * Check if op should abort moving victim because of it's race or slaying.
46 * Returns 1 if it should abort, returns 0 if it should continue. 41 * Returns 1 if it should abort, returns 0 if it should continue.
47 */ 42 */
43int
48int should_director_abort(object *op, object *victim) 44should_director_abort (object *op, object *victim)
49{ 45{
50 int arch_flag, name_flag, race_flag; 46 int arch_flag, name_flag, race_flag;
47
51 /* Get flags to determine what of arch, name, and race should be checked. 48 /* Get flags to determine what of arch, name, and race should be checked.
52 * This is stored in subtype, and is a bitmask, the LSB is the arch flag, 49 * This is stored in subtype, and is a bitmask, the LSB is the arch flag,
53 * the next is the name flag, and the last is the race flag. Also note, 50 * the next is the name flag, and the last is the race flag. Also note,
54 * if subtype is set to zero, that also goes to defaults of all affecting 51 * if subtype is set to zero, that also goes to defaults of all affecting
55 * it. Examples: 52 * it. Examples:
56 * subtype 1: only arch 53 * subtype 1: only arch
57 * subtype 3: arch or name 54 * subtype 3: arch or name
58 * subtype 5: arch or race 55 * subtype 5: arch or race
59 * subtype 7: all three 56 * subtype 7: all three
60 */ 57 */
61 if (op->subtype) 58 if (op->subtype)
62 { 59 {
63 arch_flag = (op->subtype & 1); 60 arch_flag = (op->subtype & 1);
64 name_flag = (op->subtype & 2); 61 name_flag = (op->subtype & 2);
65 race_flag = (op->subtype & 4); 62 race_flag = (op->subtype & 4);
66 } else { 63 }
64 else
65 {
67 arch_flag = 1; 66 arch_flag = 1;
68 name_flag = 1; 67 name_flag = 1;
69 race_flag = 1; 68 race_flag = 1;
70 } 69 }
71 /* If the director has race set, only affect objects with a arch, 70 /* If the director has race set, only affect objects with a arch,
72 * name or race that matches. 71 * name or race that matches.
73 */ 72 */
74 if ( (op->race) && 73 if ((op->race) &&
75 ((!(victim->arch && arch_flag && victim->arch->name) || strcmp(op->race, victim->arch->name))) && 74 ((!(victim->arch && arch_flag && victim->arch->name) || strcmp (op->race, victim->arch->name))) &&
76 ((!(victim->name && name_flag) || strcmp(op->race, victim->name))) && 75 ((!(victim->name && name_flag) || strcmp (op->race, victim->name))) &&
77 ((!(victim->race && race_flag) || strcmp(op->race, victim->race))) ) { 76 ((!(victim->race && race_flag) || strcmp (op->race, victim->race))))
77 {
78 return 1; 78 return 1;
79 } 79 }
80 /* If the director has slaying set, only affect objects where none 80 /* If the director has slaying set, only affect objects where none
81 * of arch, name, or race match. 81 * of arch, name, or race match.
82 */ 82 */
83 if ( (op->slaying) && (
84 ((victim->arch && arch_flag && victim->arch->name && !strcmp(op->slaying, victim->arch->name))) || 83 if ((op->slaying) && (((victim->arch && arch_flag && victim->arch->name && !strcmp (op->slaying, victim->arch->name))) ||
85 ((victim->name && name_flag && !strcmp(op->slaying, victim->name))) || 84 ((victim->name && name_flag && !strcmp (op->slaying, victim->name))) ||
86 ((victim->race && race_flag && !strcmp(op->slaying, victim->race)))) ) { 85 ((victim->race && race_flag && !strcmp (op->slaying, victim->race)))))
86 {
87 return 1; 87 return 1;
88 } 88 }
89 return 0; 89 return 0;
90} 90}
91 91
92/** 92/**
93 * This handles a player dropping money on an altar to identify stuff. 93 * This handles a player dropping money on an altar to identify stuff.
94 * It'll identify marked item, if none all items up to dropped money. 94 * It'll identify marked item, if none all items up to dropped money.
95 * Return value: 1 if money was destroyed, 0 if not. 95 * Return value: 1 if money was destroyed, 0 if not.
96 */ 96 */
97static int
97static int apply_id_altar (object *money, object *altar, object *pl) 98apply_id_altar (object *money, object *altar, object *pl)
98{ 99{
99 object *id, *marked; 100 object *id, *marked;
100 int success=0; 101 int success = 0;
101 102
102 if (pl == NULL || pl->type != PLAYER) 103 if (pl == NULL || pl->type != PLAYER)
103 return 0; 104 return 0;
104 105
105 /* Check for MONEY type is a special hack - it prevents 'nothing needs 106 /* Check for MONEY type is a special hack - it prevents 'nothing needs
106 * identifying' from being printed out more than it needs to be. 107 * identifying' from being printed out more than it needs to be.
107 */ 108 */
108 if ( ! check_altar_sacrifice (altar, money) || money->type != MONEY) 109 if (!check_altar_sacrifice (altar, money) || money->type != MONEY)
109 return 0; 110 return 0;
110 111
111 marked = find_marked_object (pl); 112 marked = find_marked_object (pl);
112 /* if the player has a marked item, identify that if it needs to be 113 /* if the player has a marked item, identify that if it needs to be
113 * identified. IF it doesn't, then go through the player inventory. 114 * identified. IF it doesn't, then go through the player inventory.
114 */ 115 */
115 if (marked && ! QUERY_FLAG (marked, FLAG_IDENTIFIED) 116 if (marked && !QUERY_FLAG (marked, FLAG_IDENTIFIED) && need_identify (marked))
116 && need_identify (marked))
117 { 117 {
118 if (operate_altar (altar, &money)) { 118 if (operate_altar (altar, &money))
119 {
119 identify (marked); 120 identify (marked);
120 new_draw_info_format(NDI_UNIQUE, 0, pl, 121 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have %s.", long_desc (marked, pl));
121 "You have %s.", long_desc(marked, pl));
122 if (marked->msg) { 122 if (marked->msg)
123 {
123 new_draw_info(NDI_UNIQUE, 0,pl, "The item has a story:"); 124 new_draw_info (NDI_UNIQUE, 0, pl, "The item has a story:");
124 new_draw_info(NDI_UNIQUE, 0,pl, marked->msg); 125 new_draw_info (NDI_UNIQUE, 0, pl, marked->msg);
125 } 126 }
126 return money == NULL; 127 return money == NULL;
127 } 128 }
128 } 129 }
129 130
130 for (id=pl->inv; id; id=id->below) { 131 for (id = pl->inv; id; id = id->below)
132 {
131 if (!QUERY_FLAG(id, FLAG_IDENTIFIED) && !id->invisible && 133 if (!QUERY_FLAG (id, FLAG_IDENTIFIED) && !id->invisible && need_identify (id))
132 need_identify(id)) { 134 {
133 if (operate_altar(altar,&money)) { 135 if (operate_altar (altar, &money))
136 {
134 identify(id); 137 identify (id);
135 new_draw_info_format(NDI_UNIQUE, 0, pl, 138 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have %s.", long_desc (id, pl));
136 "You have %s.", long_desc(id, pl));
137 if (id->msg) { 139 if (id->msg)
140 {
138 new_draw_info(NDI_UNIQUE, 0,pl, "The item has a story:"); 141 new_draw_info (NDI_UNIQUE, 0, pl, "The item has a story:");
139 new_draw_info(NDI_UNIQUE, 0,pl, id->msg); 142 new_draw_info (NDI_UNIQUE, 0, pl, id->msg);
140 }
141 success=1;
142 /* If no more money, might as well quit now */
143 if (money == NULL || ! check_altar_sacrifice (altar,money))
144 break;
145 } 143 }
144 success = 1;
145 /* If no more money, might as well quit now */
146 if (money == NULL || !check_altar_sacrifice (altar, money))
147 break;
148 }
146 else { 149 else
150 {
147 LOG(llevError,"check_id_altar: Couldn't do sacrifice when we should have been able to\n"); 151 LOG (llevError, "check_id_altar: Couldn't do sacrifice when we should have been able to\n");
148 break; 152 break;
149 } 153 }
150 } 154 }
151 } 155 }
156 if (!success)
152 if (!success) new_draw_info(NDI_UNIQUE, 0,pl,"You have nothing that needs identifying"); 157 new_draw_info (NDI_UNIQUE, 0, pl, "You have nothing that needs identifying");
153 return money == NULL; 158 return money == NULL;
154} 159}
155 160
156/** 161/**
157 * This checks whether the object has a "on_use_yield" field, and if so generated and drops 162 * This checks whether the object has a "on_use_yield" field, and if so generated and drops
158 * matching item. 163 * matching item.
159 **/ 164 **/
165static void
160static void handle_apply_yield(object* tmp) 166handle_apply_yield (object *tmp)
161{ 167{
162 const char* yield; 168 const char *yield;
163 169
164 yield = get_ob_key_value(tmp,"on_use_yield"); 170 yield = get_ob_key_value (tmp, "on_use_yield");
165 if (yield != NULL) 171 if (yield != NULL)
166 { 172 {
167 object* drop = get_archetype(yield); 173 object *drop = get_archetype (yield);
174
168 if (tmp->env) 175 if (tmp->env)
169 { 176 {
170 drop = insert_ob_in_ob(drop,tmp->env); 177 drop = insert_ob_in_ob (drop, tmp->env);
171 if (tmp->env->type == PLAYER) 178 if (tmp->env->type == PLAYER)
172 esrv_send_item(tmp->env,drop); 179 esrv_send_item (tmp->env, drop);
173 } 180 }
174 else 181 else
175 { 182 {
176 drop->x = tmp->x; 183 drop->x = tmp->x;
177 drop->y = tmp->y; 184 drop->y = tmp->y;
178 insert_ob_in_map(drop,tmp->map,tmp,INS_BELOW_ORIGINATOR); 185 insert_ob_in_map (drop, tmp->map, tmp, INS_BELOW_ORIGINATOR);
179 } 186 }
180 } 187 }
181} 188}
182 189
183/** 190/**
184 * Handles applying a potion. 191 * Handles applying a potion.
185 */ 192 */
193int
186int apply_potion (object * op, object * tmp) 194apply_potion (object *op, object *tmp)
187{ 195{
188 int got_one = 0, i; 196 int got_one = 0, i;
189 object *force = 0, *floor = 0; 197 object *force = 0, *floor = 0;
190 198
191 floor = get_map_ob (op->map, op->x, op->y); 199 floor = GET_MAP_OB (op->map, op->x, op->y);
192 200
193 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)
194 { 202 {
195 if (op->type == PLAYER) 203 if (op->type == PLAYER)
196 new_draw_info (NDI_UNIQUE, 0, op,
197 "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!");
198 );
199 CLEAR_FLAG (tmp, FLAG_APPLIED); 205 CLEAR_FLAG (tmp, FLAG_APPLIED);
200 return 0; 206 return 0;
201 } 207 }
202 208
203 if (op->type == PLAYER) 209 if (op->type == PLAYER)
204 {
205 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED)) 210 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
206 identify (tmp); 211 identify (tmp);
207 }
208 212
209 handle_apply_yield (tmp); 213 handle_apply_yield (tmp);
210 214
211 /* Potion of restoration - only for players */ 215 /* Potion of restoration - only for players */
212 if (op->type == PLAYER && (tmp->attacktype & AT_DEPLETE)) 216 if (op->type == PLAYER && (tmp->attacktype & AT_DEPLETE))
214 object *depl; 218 object *depl;
215 archetype *at; 219 archetype *at;
216 220
217 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 221 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
218 { 222 {
219 drain_stat (op); 223 op->drain_stat ();
220 fix_player (op); 224 op->update_stats ();
221 decrease_ob (tmp); 225 decrease_ob (tmp);
222 return 1; 226 return 1;
223 } 227 }
228
224 if ((at = find_archetype (ARCH_DEPLETION)) == NULL) 229 if (!(at = archetype::find (ARCH_DEPLETION)))
225 { 230 {
226 LOG (llevError, "Could not find archetype depletion\n"); 231 LOG (llevError, "Could not find archetype depletion\n");
227 return 0; 232 return 0;
228 } 233 }
229 depl = present_arch_in_ob (at, op); 234 depl = present_arch_in_ob (at, op);
235
230 if (depl != NULL) 236 if (depl)
231 { 237 {
232 for (i = 0; i < NUM_STATS; i++) 238 for (i = 0; i < NUM_STATS; i++)
233 if (get_attr_value (&depl->stats, i)) 239 if (get_attr_value (&depl->stats, i))
234 {
235 new_draw_info (NDI_UNIQUE, 0, op, restore_msg[i]); 240 new_draw_info (NDI_UNIQUE, 0, op, restore_msg[i]);
236 } 241
237 remove_ob (depl); 242 depl->destroy ();
238 free_object (depl); 243 op->update_stats ();
239 fix_player (op);
240 } 244 }
241 else 245 else
242 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.");
243 247
244 decrease_ob (tmp); 248 decrease_ob (tmp);
246 } 250 }
247 251
248 /* improvement potion - only for players */ 252 /* improvement potion - only for players */
249 if (op->type == PLAYER && tmp->attacktype & AT_GODPOWER) 253 if (op->type == PLAYER && tmp->attacktype & AT_GODPOWER)
250 { 254 {
251
252 for (i = 1; i < MIN (11, op->level); i++) 255 for (i = 1; i < MIN (11, op->level); i++)
253 { 256 {
254 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 257 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
255 { 258 {
256 if (op->contr->levhp[i] != 1) 259 if (op->contr->levhp[i] != 1)
286 op->contr->levgrace[i] = 3; 289 op->contr->levgrace[i] = 3;
287 break; 290 break;
288 } 291 }
289 } 292 }
290 } 293 }
294
291 /* Just makes checking easier */ 295 /* Just makes checking easier */
292 if (i < MIN (11, op->level)) 296 if (i < MIN (11, op->level))
293 got_one = 1; 297 got_one = 1;
298
294 if (!QUERY_FLAG (tmp, FLAG_CURSED) && !QUERY_FLAG (tmp, FLAG_DAMNED)) 299 if (!QUERY_FLAG (tmp, FLAG_CURSED) && !QUERY_FLAG (tmp, FLAG_DAMNED))
295 { 300 {
296 if (got_one) 301 if (got_one)
297 { 302 {
298 fix_player (op); 303 op->update_stats ();
299 new_draw_info (NDI_UNIQUE, 0, op, 304 new_draw_info (NDI_UNIQUE, 0, op, "The Gods smile upon you and remake you");
300 "The Gods smile upon you and remake you"); 305 new_draw_info (NDI_UNIQUE, 0, op, "a little more in their image.");
301 new_draw_info (NDI_UNIQUE, 0, op, 306 new_draw_info (NDI_UNIQUE, 0, op, "You feel a little more perfect.");
302 "a little more in their image.");
303 new_draw_info (NDI_UNIQUE, 0, op,
304 "You feel a little more perfect.");
305 } 307 }
306 else 308 else
307 new_draw_info (NDI_UNIQUE, 0, op, 309 new_draw_info (NDI_UNIQUE, 0, op, "The potion had no effect - you are already perfect");
308 "The potion had no effect - you are already perfect");
309 } 310 }
310 else 311 else
311 { /* cursed potion */ 312 { /* cursed potion */
312 if (got_one) 313 if (got_one)
313 { 314 {
314 fix_player (op); 315 op->update_stats ();
315 new_draw_info (NDI_UNIQUE, 0, op, 316 new_draw_info (NDI_UNIQUE, 0, op, "The Gods are angry and punish you.");
316 "The Gods are angry and punish you.");
317 } 317 }
318 else 318 else
319 new_draw_info (NDI_UNIQUE, 0, op, 319 new_draw_info (NDI_UNIQUE, 0, op, "You are fortunate that you are so pathetic.");
320 "You are fortunate that you are so pathetic.");
321 } 320 }
321
322 decrease_ob (tmp); 322 decrease_ob (tmp);
323 return 1; 323 return 1;
324 } 324 }
325 325
326 326
336 object *fball; 336 object *fball;
337 337
338 new_draw_info (NDI_UNIQUE, 0, op, "Yech! Your lungs are on fire!"); 338 new_draw_info (NDI_UNIQUE, 0, op, "Yech! Your lungs are on fire!");
339 /* Explodes a fireball centered at player */ 339 /* Explodes a fireball centered at player */
340 fball = get_archetype (EXPLODING_FIREBALL); 340 fball = get_archetype (EXPLODING_FIREBALL);
341 fball->dam_modifier =
342 random_roll (1, op->level, op, PREFER_LOW) / 5 + 1; 341 fball->dam_modifier = random_roll (1, op->level, op, PREFER_LOW) / 5 + 1;
343 fball->stats.maxhp =
344 random_roll (1, op->level, op, PREFER_LOW) / 10 + 2; 342 fball->stats.maxhp = random_roll (1, op->level, op, PREFER_LOW) / 10 + 2;
345 fball->x = op->x; 343 fball->x = op->x;
346 fball->y = op->y; 344 fball->y = op->y;
347 insert_ob_in_map (fball, op->map, NULL, 0); 345 insert_ob_in_map (fball, op->map, NULL, 0);
348 } 346 }
349 else 347 else
350 cast_spell (op, tmp, op->facing, tmp->inv, NULL); 348 cast_spell (op, tmp, op->facing, tmp->inv, NULL);
351 349
352 decrease_ob (tmp); 350 decrease_ob (tmp);
353 /* if youre dead, no point in doing this... */ 351 /* if youre dead, no point in doing this... */
354 if (!QUERY_FLAG (op, FLAG_REMOVED)) 352 if (!QUERY_FLAG (op, FLAG_REMOVED))
355 fix_player (op); 353 op->update_stats ();
356 return 1; 354 return 1;
357 } 355 }
358 356
359 /* Deal with protection potions */ 357 /* Deal with protection potions */
360 force = NULL; 358 force = NULL;
390 } 388 }
391 389
392 /* Only thing left are the stat potions */ 390 /* Only thing left are the stat potions */
393 if (op->type == PLAYER) 391 if (op->type == PLAYER)
394 { /* only for players */ 392 { /* only for players */
395 if ((QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) 393 if ((QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) && tmp->value != 0)
396 && tmp->value != 0)
397 CLEAR_FLAG (tmp, FLAG_APPLIED); 394 CLEAR_FLAG (tmp, FLAG_APPLIED);
398 else 395 else
399 SET_FLAG (tmp, FLAG_APPLIED); 396 SET_FLAG (tmp, FLAG_APPLIED);
400 if (!change_abil (op, tmp)) 397 if (!change_abil (op, tmp))
401 new_draw_info (NDI_UNIQUE, 0, op, "Nothing happened."); 398 new_draw_info (NDI_UNIQUE, 0, op, "Nothing happened.");
405 * that were grouped with the one consumed, his 402 * that were grouped with the one consumed, his
406 * stat will not be raised by them. fix_player just clears 403 * stat will not be raised by them. fix_player just clears
407 * up all the stats. 404 * up all the stats.
408 */ 405 */
409 CLEAR_FLAG (tmp, FLAG_APPLIED); 406 CLEAR_FLAG (tmp, FLAG_APPLIED);
410 fix_player (op); 407 op->update_stats ();
411 decrease_ob (tmp); 408 decrease_ob (tmp);
412 return 1; 409 return 1;
413} 410}
414 411
415/**************************************************************************** 412/****************************************************************************
417 ****************************************************************************/ 414 ****************************************************************************/
418 415
419/** 416/**
420 * This returns the sum of nrof of item (arch name). 417 * This returns the sum of nrof of item (arch name).
421 */ 418 */
419static int
422static int check_item(object *op, const char *item) 420check_item (object *op, const char *item)
423{ 421{
424 int count=0; 422 int count = 0;
425 423
426 424
427 if (item==NULL) return 0; 425 if (item == NULL)
426 return 0;
428 op=op->below; 427 op = op->below;
429 while(op!=NULL) { 428 while (op != NULL)
429 {
430 if (strcmp(op->arch->name,item)==0){ 430 if (strcmp (op->arch->name, item) == 0)
431 {
431 if (!QUERY_FLAG (op, FLAG_CURSED) && !QUERY_FLAG (op, FLAG_DAMNED) 432 if (!QUERY_FLAG (op, FLAG_CURSED) && !QUERY_FLAG (op, FLAG_DAMNED)
432 /* Loophole bug? -FD- */ && !QUERY_FLAG (op, FLAG_UNPAID) ) 433 /* Loophole bug? -FD- */ && !QUERY_FLAG (op, FLAG_UNPAID))
433 { 434 {
434 if (op->nrof == 0)/* this is necessary for artifact sacrifices --FD-- */ 435 if (op->nrof == 0) /* this is necessary for artifact sacrifices --FD-- */
435 count++; 436 count++;
436 else 437 else
437 count += op->nrof; 438 count += op->nrof;
438 } 439 }
439 } 440 }
440 op=op->below; 441 op = op->below;
441 } 442 }
442 return count; 443 return count;
443} 444}
444 445
445/** 446/**
446 * This removes 'nrof' of what item->slaying says to remove. 447 * This removes 'nrof' of what item->slaying says to remove.
447 * op is typically the player, which is only 448 * op is typically the player, which is only
448 * really used to determine what space to look at. 449 * really used to determine what space to look at.
449 * Modified to only eat 'nrof' of objects. 450 * Modified to only eat 'nrof' of objects.
450 */ 451 */
452static void
451static void eat_item(object *op,const char *item, uint32 nrof) 453eat_item (object *op, const char *item, uint32 nrof)
452{ 454{
453 object *prev; 455 object *prev;
454 456
455 prev = op; 457 prev = op;
456 op=op->below; 458 op = op->below;
457 459
458 while(op!=NULL) { 460 while (op != NULL)
461 {
459 if (strcmp(op->arch->name,item)==0) { 462 if (strcmp (op->arch->name, item) == 0)
463 {
460 if (op->nrof >= nrof) { 464 if (op->nrof >= nrof)
465 {
461 decrease_ob_nr(op,nrof); 466 decrease_ob_nr (op, nrof);
462 return; 467 return;
463 } else {
464 decrease_ob_nr(op,op->nrof);
465 nrof -= op->nrof;
466 } 468 }
469 else
470 {
471 decrease_ob_nr (op, op->nrof);
472 nrof -= op->nrof;
473 }
467 op=prev; 474 op = prev;
468 } 475 }
469 prev = op; 476 prev = op;
470 op=op->below; 477 op = op->below;
471 } 478 }
472} 479}
473 480
474/** 481/**
475 * This checks to see of the player (who) is sufficient level to use a weapon 482 * This checks to see of the player (who) is sufficient level to use a weapon
476 * with improvs improvements (typically last_eat). We take an int here 483 * with improvs improvements (typically last_eat). We take an int here
477 * instead of the object so that the improvement code can pass along the 484 * instead of the object so that the improvement code can pass along the
478 * increased value to see if the object is usuable. 485 * increased value to see if the object is usuable.
479 * we return 1 (true) if the player can use the weapon. 486 * we return 1 (true) if the player can use the weapon.
480 */ 487 */
488static int
481static int check_weapon_power(const object *who, int improvs) 489check_weapon_power (const object *who, int improvs)
482{ 490{
491
483/* Old code is below (commented out). Basically, since weapons are the only 492/* Old code is below (commented out). Basically, since weapons are the only
484 * object players really have any control to improve, it's a bit harsh to 493 * object players really have any control to improve, it's a bit harsh to
485 * require high level in some combat skill, so we just use overall level. 494 * require high level in some combat skill, so we just use overall level.
486 */ 495 */
487#if 1 496#if 1
488 if (((who->level/5)+5) >= improvs) return 1; 497 if (((who->level / 5) + 5) >= improvs)
498 return 1;
499 else
489 else return 0; 500 return 0;
490 501
491#else 502#else
492 int level=0; 503 int level = 0;
493 504
494 /* The skill system hands out wc and dam bonuses to fighters 505 /* The skill system hands out wc and dam bonuses to fighters
495 * more generously than the old system (see fix_player). Thus 506 * more generously than the old system (see fix_player). Thus
496 * we need to curtail the power of player enchanted weapons. 507 * we need to curtail the power of player enchanted weapons.
497 * I changed this to 1 improvement per "fighter" level/5 -b.t. 508 * I changed this to 1 improvement per "fighter" level/5 -b.t.
498 * Note: Nothing should break by allowing this ratio to be different or 509 * Note: Nothing should break by allowing this ratio to be different or
499 * using normal level - it is just a matter of play balance. 510 * using normal level - it is just a matter of play balance.
500 */ 511 */
501 if(who->type==PLAYER) { 512 if (who->type == PLAYER)
513 {
502 object *wc_obj=NULL; 514 object *wc_obj = NULL;
503 515
504 for(wc_obj=who->inv;wc_obj;wc_obj=wc_obj->below) 516 for (wc_obj = who->inv; wc_obj; wc_obj = wc_obj->below)
505 if (wc_obj->type == SKILL && IS_COMBAT_SKILL(wc_obj->subtype) && wc_obj->level > level) 517 if (wc_obj->type == SKILL && IS_COMBAT_SKILL (wc_obj->subtype) && wc_obj->level > level)
506 level = wc_obj->level; 518 level = wc_obj->level;
507 519
508 if (!level ) { 520 if (!level)
521 {
509 LOG(llevError,"Error: Player: %s lacks wc experience object\n",who->name); 522 LOG (llevError, "Error: Player: %s lacks wc experience object\n", who->name);
510 level = who->level; 523 level = who->level;
511 } 524 }
512 } 525 }
513 else 526 else
514 level=who->level; 527 level = who->level;
515 528
516 return (improvs <= ((level/5)+5)); 529 return (improvs <= ((level / 5) + 5));
517#endif 530#endif
518} 531}
519 532
520/** 533/**
521 * Returns how many items of type improver->slaying there are under op. 534 * Returns how many items of type improver->slaying there are under op.
522 * Will display a message if none found, and 1 if improver->slaying is NULL. 535 * Will display a message if none found, and 1 if improver->slaying is NULL.
523 */ 536 */
537static int
524static int check_sacrifice(object *op, const object *improver) 538check_sacrifice (object *op, const object *improver)
525{ 539{
526 int count=0; 540 int count = 0;
527 541
528 if (improver->slaying!=NULL) { 542 if (improver->slaying != NULL)
543 {
529 count = check_item(op,improver->slaying); 544 count = check_item (op, improver->slaying);
530 if (count<1) { 545 if (count < 1)
546 {
531 char buf[200]; 547 char buf[200];
548
532 sprintf(buf,"The gods want more %ss", &improver->slaying); 549 sprintf (buf, "The gods want more %ss", &improver->slaying);
533 new_draw_info(NDI_UNIQUE,0,op,buf); 550 new_draw_info (NDI_UNIQUE, 0, op, buf);
534 return 0; 551 return 0;
535 } 552 }
536 } 553 }
537 else 554 else
538 count=1; 555 count = 1;
539 556
540 return count; 557 return count;
541} 558}
542 559
543/** 560/**
544 * Actually improves the weapon, and tells user. 561 * Actually improves the weapon, and tells user.
545 */ 562 */
546int improve_weapon_stat(object *op,object *improver,object *weapon, 563int
547 signed char *stat,int sacrifice_count,const char *statname) 564improve_weapon_stat (object *op, object *improver, object *weapon, signed char *stat, int sacrifice_count, const char *statname)
548{ 565{
549 566
550 new_draw_info(NDI_UNIQUE,0,op,"Your sacrifice was accepted."); 567 new_draw_info (NDI_UNIQUE, 0, op, "Your sacrifice was accepted.");
551 *stat += sacrifice_count; 568 *stat += sacrifice_count;
552 weapon->last_eat++; 569 weapon->last_eat++;
553 new_draw_info_format(NDI_UNIQUE,0,op, 570 new_draw_info_format (NDI_UNIQUE, 0, op, "Weapon's bonus to %s improved by %d", statname, sacrifice_count);
554 "Weapon's bonus to %s improved by %d",statname,sacrifice_count);
555 decrease_ob(improver); 571 decrease_ob (improver);
556 572
557 /* So it updates the players stats and the window */ 573 /* So it updates the players stats and the window */
558 fix_player(op); 574 op->update_stats ();
559 return 1; 575 return 1;
560} 576}
561 577
562/* Types of improvements, hidden in the sp field. */ 578/* Types of improvements, hidden in the sp field. */
563#define IMPROVE_PREPARE 1 579#define IMPROVE_PREPARE 1
576/** 592/**
577 * This does the prepare weapon scroll. 593 * This does the prepare weapon scroll.
578 * Checks for sacrifice, and so on. 594 * Checks for sacrifice, and so on.
579 */ 595 */
580 596
597int
581int prepare_weapon(object *op, object *improver, object *weapon) 598prepare_weapon (object *op, object *improver, object *weapon)
582{ 599{
583 int sacrifice_count,i; 600 int sacrifice_count, i;
584 char buf[MAX_BUF]; 601 char buf[MAX_BUF];
585 602
586 if (weapon->level!=0) { 603 if (weapon->level != 0)
604 {
587 new_draw_info(NDI_UNIQUE,0,op,"Weapon already prepared."); 605 new_draw_info (NDI_UNIQUE, 0, op, "Weapon already prepared.");
588 return 0; 606 return 0;
589 } 607 }
590 for (i=0; i<NROFATTACKS; i++) 608 for (i = 0; i < NROFATTACKS; i++)
591 if (weapon->resist[i]) break; 609 if (weapon->resist[i])
610 break;
592 611
593 /* If we break out, i will be less than nrofattacks, preventing 612 /* If we break out, i will be less than nrofattacks, preventing
594 * improvement of items that already have protections. 613 * improvement of items that already have protections.
595 */ 614 */
596 if (i<NROFATTACKS || 615 if (i < NROFATTACKS || weapon->stats.hp || /* regeneration */
597 weapon->stats.hp || /* regeneration */
598 (weapon->stats.sp && weapon->type == WEAPON) || /* sp regeneration */ 616 (weapon->stats.sp && weapon->type == WEAPON) || /* sp regeneration */
599 weapon->stats.exp || /* speed */ 617 weapon->stats.exp || /* speed */
600 weapon->stats.ac) /* AC - only taifu's I think */ 618 weapon->stats.ac) /* AC - only taifu's I think */
601 { 619 {
602 new_draw_info(NDI_UNIQUE,0,op,"Cannot prepare magic weapons."); 620 new_draw_info (NDI_UNIQUE, 0, op, "Cannot prepare magic weapons.");
603 return 0; 621 return 0;
604 } 622 }
605 sacrifice_count=check_sacrifice(op,improver); 623 sacrifice_count = check_sacrifice (op, improver);
606 if (sacrifice_count<=0) 624 if (sacrifice_count <= 0)
607 return 0; 625 return 0;
608 weapon->level=isqrt(sacrifice_count); 626 weapon->level = isqrt (sacrifice_count);
609 new_draw_info(NDI_UNIQUE,0,op,"Your sacrifice was accepted."); 627 new_draw_info (NDI_UNIQUE, 0, op, "Your sacrifice was accepted.");
610 eat_item(op, improver->slaying, sacrifice_count); 628 eat_item (op, improver->slaying, sacrifice_count);
611 629
612 new_draw_info_format(NDI_UNIQUE, 0, op,"Your *%s may be improved %d times.", 630 new_draw_info_format (NDI_UNIQUE, 0, op, "Your *%s may be improved %d times.", &weapon->name, weapon->level);
613 &weapon->name,weapon->level);
614 631
615 sprintf(buf,"%s's %s",&op->name,&weapon->name); 632 sprintf (buf, "%s's %s", &op->name, &weapon->name);
616 weapon->name = weapon->name_pl = buf; 633 weapon->name = weapon->name_pl = buf;
617 weapon->nrof=0; /* prevents preparing n weapons in the same 634 weapon->nrof = 0; /* prevents preparing n weapons in the same
618 slot at once! */ 635 slot at once! */
619 decrease_ob(improver); 636 decrease_ob (improver);
620 weapon->last_eat=0; 637 weapon->last_eat = 0;
621 return 1; 638 return 1;
622} 639}
623 640
624 641
625/** 642/**
626 * Does the dirty job for 'improve weapon' scroll, prepare or add something. 643 * Does the dirty job for 'improve weapon' scroll, prepare or add something.
631 * 648 *
632 * We are hiding extra information about the weapon in the level and 649 * We are hiding extra information about the weapon in the level and
633 * last_eat numbers for an object. Hopefully this won't break anything ?? 650 * last_eat numbers for an object. Hopefully this won't break anything ??
634 * level == max improve last_eat == current improve 651 * level == max improve last_eat == current improve
635 */ 652 */
653int
636int improve_weapon(object *op,object *improver,object *weapon) 654improve_weapon (object *op, object *improver, object *weapon)
637{ 655{
638 int sacrifice_count, sacrifice_needed=0; 656 int sacrifice_count, sacrifice_needed = 0;
639 657
640 if(improver->stats.sp==IMPROVE_PREPARE) { 658 if (improver->stats.sp == IMPROVE_PREPARE)
659 {
641 return prepare_weapon(op, improver, weapon); 660 return prepare_weapon (op, improver, weapon);
642 } 661 }
643 if (weapon->level==0) { 662 if (weapon->level == 0)
663 {
644 new_draw_info(NDI_UNIQUE, 0,op,"This weapon has not been prepared."); 664 new_draw_info (NDI_UNIQUE, 0, op, "This weapon has not been prepared.");
645 return 0; 665 return 0;
646 } 666 }
647 if (weapon->level==weapon->last_eat && weapon->item_power >=100) { 667 if (weapon->level == weapon->last_eat && weapon->item_power >= 100)
668 {
648 new_draw_info(NDI_UNIQUE, 0,op,"This weapon cannot be improved any more."); 669 new_draw_info (NDI_UNIQUE, 0, op, "This weapon cannot be improved any more.");
649 return 0; 670 return 0;
650 } 671 }
651 if (QUERY_FLAG(weapon, FLAG_APPLIED) && 672 if (QUERY_FLAG (weapon, FLAG_APPLIED) && !check_weapon_power (op, weapon->last_eat + 1))
652 !check_weapon_power(op, weapon->last_eat+1)) { 673 {
653 new_draw_info(NDI_UNIQUE, 0,op,"Improving the weapon will make it too"); 674 new_draw_info (NDI_UNIQUE, 0, op, "Improving the weapon will make it too");
654 new_draw_info(NDI_UNIQUE, 0,op,"powerful for you to use. Unready it if you"); 675 new_draw_info (NDI_UNIQUE, 0, op, "powerful for you to use. Unready it if you");
655 new_draw_info(NDI_UNIQUE, 0,op,"really want to improve it."); 676 new_draw_info (NDI_UNIQUE, 0, op, "really want to improve it.");
656 return 0; 677 return 0;
657 } 678 }
658 /* This just increases damage by 5 points, no matter what. No sacrifice 679 /* This just increases damage by 5 points, no matter what. No sacrifice
659 * is needed. Since stats.dam is now a 16 bit value and not 8 bit, 680 * is needed. Since stats.dam is now a 16 bit value and not 8 bit,
660 * don't put any maximum value on damage - the limit is how much the 681 * don't put any maximum value on damage - the limit is how much the
661 * weapon can be improved. 682 * weapon can be improved.
662 */ 683 */
663 if (improver->stats.sp==IMPROVE_DAMAGE) { 684 if (improver->stats.sp == IMPROVE_DAMAGE)
685 {
664 weapon->stats.dam += 5; 686 weapon->stats.dam += 5;
665 weapon->weight += 5000; /* 5 KG's */ 687 weapon->weight += 5000; /* 5 KG's */
666 new_draw_info_format(NDI_UNIQUE, 0, op, 688 new_draw_info_format (NDI_UNIQUE, 0, op, "Damage has been increased by 5 to %d", weapon->stats.dam);
667 "Damage has been increased by 5 to %d", weapon->stats.dam);
668 weapon->last_eat++; 689 weapon->last_eat++;
669 690
670 weapon->item_power++; 691 weapon->item_power++;
671 decrease_ob(improver); 692 decrease_ob (improver);
672 return 1; 693 return 1;
673 } 694 }
674 if (improver->stats.sp == IMPROVE_WEIGHT) { 695 if (improver->stats.sp == IMPROVE_WEIGHT)
696 {
675 /* Reduce weight by 20% */ 697 /* Reduce weight by 20% */
676 weapon->weight = (weapon->weight * 8)/10; 698 weapon->weight = (weapon->weight * 8) / 10;
677 if (weapon->weight < 1) weapon->weight = 1; 699 if (weapon->weight < 1)
678 new_draw_info_format(NDI_UNIQUE, 0, op, 700 weapon->weight = 1;
679 "Weapon weight reduced to %6.1f kg", 701 new_draw_info_format (NDI_UNIQUE, 0, op, "Weapon weight reduced to %6.1f kg", (float) weapon->weight / 1000.0);
680 (float)weapon->weight/1000.0);
681 weapon->last_eat++; 702 weapon->last_eat++;
682 weapon->item_power++; 703 weapon->item_power++;
683 decrease_ob(improver); 704 decrease_ob (improver);
684 return 1; 705 return 1;
685 } 706 }
686 if (improver->stats.sp == IMPROVE_ENCHANT) { 707 if (improver->stats.sp == IMPROVE_ENCHANT)
708 {
687 weapon->magic++; 709 weapon->magic++;
688 weapon->last_eat++; 710 weapon->last_eat++;
689 new_draw_info_format(NDI_UNIQUE, 0, op 711 new_draw_info_format (NDI_UNIQUE, 0, op, "Weapon magic increased to %d", weapon->magic);
690 ,"Weapon magic increased to %d",weapon->magic);
691 decrease_ob(improver); 712 decrease_ob (improver);
692 weapon->item_power++; 713 weapon->item_power++;
693 return 1; 714 return 1;
694 } 715 }
695 716
696 sacrifice_needed = weapon->stats.Str + weapon->stats.Int + weapon->stats.Dex+ 717 sacrifice_needed = weapon->stats.Str + weapon->stats.Int + weapon->stats.Dex +
697 weapon->stats.Pow + weapon->stats.Con + weapon->stats.Cha + 718 weapon->stats.Pow + weapon->stats.Con + weapon->stats.Cha + weapon->stats.Wis;
698 weapon->stats.Wis;
699 719
700 if (sacrifice_needed<1) 720 if (sacrifice_needed < 1)
701 sacrifice_needed =1; 721 sacrifice_needed = 1;
702 sacrifice_needed *=2; 722 sacrifice_needed *= 2;
703 723
704 sacrifice_count = check_sacrifice(op,improver); 724 sacrifice_count = check_sacrifice (op, improver);
705 if (sacrifice_count < sacrifice_needed) { 725 if (sacrifice_count < sacrifice_needed)
706 new_draw_info_format(NDI_UNIQUE, 0, op, 726 {
707 "You need at least %d %s", sacrifice_needed, &improver->slaying); 727 new_draw_info_format (NDI_UNIQUE, 0, op, "You need at least %d %s", sacrifice_needed, &improver->slaying);
708 return 0; 728 return 0;
709 } 729 }
710 eat_item(op,improver->slaying, sacrifice_needed); 730 eat_item (op, improver->slaying, sacrifice_needed);
711 weapon->item_power++; 731 weapon->item_power++;
712 732
713 switch (improver->stats.sp) { 733 switch (improver->stats.sp)
734 {
714 case IMPROVE_STR: 735 case IMPROVE_STR:
715 return improve_weapon_stat(op,improver,weapon, 736 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Str), 1, "strength");
716 (signed char *) &(weapon->stats.Str),
717 1, "strength");
718 case IMPROVE_DEX: 737 case IMPROVE_DEX:
719 return improve_weapon_stat(op,improver,weapon, 738 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Dex), 1, "dexterity");
720 (signed char *) &(weapon->stats.Dex),
721 1, "dexterity");
722 case IMPROVE_CON: 739 case IMPROVE_CON:
723 return improve_weapon_stat(op,improver,weapon, 740 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Con), 1, "constitution");
724 (signed char *) &(weapon->stats.Con),
725 1, "constitution");
726 case IMPROVE_WIS: 741 case IMPROVE_WIS:
727 return improve_weapon_stat(op,improver,weapon, 742 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Wis), 1, "wisdom");
728 (signed char *) &(weapon->stats.Wis),
729 1, "wisdom");
730 case IMPROVE_CHA: 743 case IMPROVE_CHA:
731 return improve_weapon_stat(op,improver,weapon, 744 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Cha), 1, "charisma");
732 (signed char *) &(weapon->stats.Cha),
733 1, "charisma");
734 case IMPROVE_INT: 745 case IMPROVE_INT:
735 return improve_weapon_stat(op,improver,weapon, 746 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Int), 1, "intelligence");
736 (signed char *) &(weapon->stats.Int),
737 1, "intelligence");
738 case IMPROVE_POW: 747 case IMPROVE_POW:
739 return improve_weapon_stat(op,improver,weapon, 748 return improve_weapon_stat (op, improver, weapon, (signed char *) &(weapon->stats.Pow), 1, "power");
740 (signed char *) &(weapon->stats.Pow),
741 1, "power");
742 default: 749 default:
743 new_draw_info(NDI_UNIQUE, 0,op,"Unknown improvement type."); 750 new_draw_info (NDI_UNIQUE, 0, op, "Unknown improvement type.");
744 } 751 }
745 LOG(llevError,"improve_weapon: Got to end of function\n"); 752 LOG (llevError, "improve_weapon: Got to end of function\n");
746 return 0; 753 return 0;
747} 754}
748 755
749/** 756/**
750 * Handles the applying of improve/prepare/enchant weapon scroll. 757 * Handles the applying of improve/prepare/enchant weapon scroll.
751 * Checks a few things (not on a non-magic square, marked weapon, ...), 758 * Checks a few things (not on a non-magic square, marked weapon, ...),
752 * then calls improve_weapon to do the dirty work. 759 * then calls improve_weapon to do the dirty work.
753 */ 760 */
761int
754int check_improve_weapon (object *op, object *tmp) 762check_improve_weapon (object *op, object *tmp)
755{ 763{
756 object *otmp; 764 object *otmp;
757 765
758 if(op->type!=PLAYER) 766 if (op->type != PLAYER)
767 return 0;
768 if (!QUERY_FLAG (op, FLAG_WIZCAST) && (get_map_flags (op->map, NULL, op->x, op->y, NULL, NULL) & P_NO_MAGIC))
769 {
770 new_draw_info (NDI_UNIQUE, 0, op, "Something blocks the magic of the scroll.");
759 return 0; 771 return 0;
760 if (!QUERY_FLAG(op, FLAG_WIZCAST) && (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL) & P_NO_MAGIC)) {
761 new_draw_info(NDI_UNIQUE, 0,op,"Something blocks the magic of the scroll.");
762 return 0;
763 } 772 }
764 otmp=find_marked_object(op); 773 otmp = find_marked_object (op);
765 if(!otmp) { 774 if (!otmp)
775 {
766 new_draw_info(NDI_UNIQUE, 0, op, "You need to mark a weapon object."); 776 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark a weapon object.");
767 return 0; 777 return 0;
768 } 778 }
769 if (otmp->type != WEAPON && otmp->type != BOW) { 779 if (otmp->type != WEAPON && otmp->type != BOW)
780 {
770 new_draw_info(NDI_UNIQUE, 0,op,"Marked item is not a weapon or bow"); 781 new_draw_info (NDI_UNIQUE, 0, op, "Marked item is not a weapon or bow");
771 return 0; 782 return 0;
772 } 783 }
773 new_draw_info(NDI_UNIQUE, 0,op,"Applied weapon builder."); 784 new_draw_info (NDI_UNIQUE, 0, op, "Applied weapon builder.");
774 improve_weapon(op,tmp,otmp); 785 improve_weapon (op, tmp, otmp);
775 esrv_send_item(op, otmp); 786 esrv_send_item (op, otmp);
776 return 1; 787 return 1;
777} 788}
778 789
779/** 790/**
780 * This code deals with the armour improvment scrolls. 791 * This code deals with the armour improvment scrolls.
781 * Change limits on improvement - let players go up to 792 * Change limits on improvement - let players go up to
796 * the armour value of the piece of equipment exceed either 807 * the armour value of the piece of equipment exceed either
797 * the users level or 90) 808 * the users level or 90)
798 * Modified by MSW for partial resistance. Only support 809 * Modified by MSW for partial resistance. Only support
799 * changing of physical area right now. 810 * changing of physical area right now.
800 */ 811 */
812int
801int improve_armour(object *op, object *improver, object *armour) 813improve_armour (object *op, object *improver, object *armour)
802{ 814{
803 object *tmp; 815 object *tmp;
804 816
805 if (armour->magic >= settings.armor_max_enchant) { 817 if (armour->magic >= settings.armor_max_enchant)
818 {
806 new_draw_info(NDI_UNIQUE, 0,op,"This armour can not be enchanted any further."); 819 new_draw_info (NDI_UNIQUE, 0, op, "This armour can not be enchanted any further.");
807 return 0; 820 return 0;
808 } 821 }
809 /* Dealing with random artifact armor is a lot trickier (in terms of value, weight, 822 /* Dealing with random artifact armor is a lot trickier (in terms of value, weight,
810 * etc), so take the easy way out and don't worry about it. 823 * etc), so take the easy way out and don't worry about it.
811 * Note - maybe add scrolls which make the random artifact versions (eg, armour 824 * Note - maybe add scrolls which make the random artifact versions (eg, armour
812 * of gnarg and what not?) 825 * of gnarg and what not?)
813 */ 826 */
814 if (armour->title) { 827 if (armour->title)
828 {
815 new_draw_info(NDI_UNIQUE, 0, op, "This armour will not accept further enchantment."); 829 new_draw_info (NDI_UNIQUE, 0, op, "This armour will not accept further enchantment.");
816 return 0; 830 return 0;
817 } 831 }
818 832
819 /* Split objects if needed. Can't insert tmp until the 833 /* Split objects if needed. Can't insert tmp until the
820 * end of this function - otherwise it will just re-merge. 834 * end of this function - otherwise it will just re-merge.
821 */ 835 */
822 if(armour->nrof > 1) 836 if (armour->nrof > 1)
823 tmp = get_split_ob(armour,armour->nrof - 1); 837 tmp = get_split_ob (armour, armour->nrof - 1);
824 else 838 else
825 tmp = NULL; 839 tmp = NULL;
826 840
827 armour->magic++; 841 armour->magic++;
828 842
829 if ( !settings.armor_speed_linear ) 843 if (!settings.armor_speed_linear)
830 { 844 {
831 int base = 100; 845 int base = 100;
832 int pow = 0; 846 int pow = 0;
847
833 while ( pow < armour->magic ) 848 while (pow < armour->magic)
834 { 849 {
835 base = base - ( base * settings.armor_speed_improvement ) / 100; 850 base = base - (base * settings.armor_speed_improvement) / 100;
836 pow++; 851 pow++;
837 } 852 }
838 853
839 ARMOUR_SPEED( armour ) = ( ARMOUR_SPEED( &armour->arch->clone ) * base ) / 100; 854 ARMOUR_SPEED (armour) = (ARMOUR_SPEED (&armour->arch->clone) * base) / 100;
840 } 855 }
841 else 856 else
842 ARMOUR_SPEED( armour ) = ( ARMOUR_SPEED( &armour->arch->clone ) * ( 100 + armour->magic * settings.armor_speed_improvement ) )/100; 857 ARMOUR_SPEED (armour) = (ARMOUR_SPEED (&armour->arch->clone) * (100 + armour->magic * settings.armor_speed_improvement)) / 100;
843 858
844 if ( !settings.armor_weight_linear ) 859 if (!settings.armor_weight_linear)
845 { 860 {
846 int base = 100; 861 int base = 100;
847 int pow = 0; 862 int pow = 0;
863
848 while ( pow < armour->magic ) 864 while (pow < armour->magic)
849 { 865 {
850 base = base - ( base * settings.armor_weight_reduction ) / 100; 866 base = base - (base * settings.armor_weight_reduction) / 100;
851 pow++; 867 pow++;
852 } 868 }
853 869
854 armour->weight = ( armour->arch->clone.weight * base ) / 100; 870 armour->weight = (armour->arch->clone.weight * base) / 100;
855 } 871 }
856 else 872 else
857 armour->weight = ( armour->arch->clone.weight * ( 100 - armour->magic * settings.armor_weight_reduction ) ) / 100; 873 armour->weight = (armour->arch->clone.weight * (100 - armour->magic * settings.armor_weight_reduction)) / 100;
858 874
859 if ( armour->weight <= 0 ) 875 if (armour->weight <= 0)
860 { 876 {
861 LOG( llevInfo, "Warning: enchanted armours can have negative weight\n." ); 877 LOG (llevInfo, "Warning: enchanted armours can have negative weight\n.");
862 armour->weight = 1; 878 armour->weight = 1;
863 } 879 }
864 880
865 armour->item_power = get_power_from_ench(armour->arch->clone.item_power + armour->magic); 881 armour->item_power = get_power_from_ench (armour->arch->clone.item_power + armour->magic);
866 882
867 if (op->type == PLAYER) { 883 if (op->type == PLAYER)
884 {
868 esrv_send_item(op, armour); 885 esrv_send_item (op, armour);
869 if(QUERY_FLAG(armour, FLAG_APPLIED)) 886 if (QUERY_FLAG (armour, FLAG_APPLIED))
870 fix_player(op); 887 op->update_stats ();
871 } 888 }
872 decrease_ob(improver); 889 decrease_ob (improver);
873 if (tmp) { 890 if (tmp)
891 {
874 insert_ob_in_ob(tmp, op); 892 insert_ob_in_ob (tmp, op);
875 esrv_send_item(op, tmp); 893 esrv_send_item (op, tmp);
876 } 894 }
877 return 1; 895 return 1;
878} 896}
879 897
880 898
881/* 899/*
882 * convert_item() returns 1 if anything was converted, 0 if the item was not 900 * convert_item() returns 1 if anything was converted, 0 if the item was not
890/* Takes one items and makes another. 908/* Takes one items and makes another.
891 * converter is the object that is doing the conversion. 909 * converter is the object that is doing the conversion.
892 * item is the object that triggered the converter - if it is not 910 * item is the object that triggered the converter - if it is not
893 * what the converter wants, this will not do anything. 911 * what the converter wants, this will not do anything.
894 */ 912 */
913int
895int convert_item(object *item, object *converter) { 914convert_item (object *item, object *converter)
915{
896 int nr=0; 916 int nr = 0;
897 object *tmp;
898 uint32 price_in; 917 uint32 price_in;
899 918
900 /* We make some assumptions - we assume if it takes money as it type, 919 /* We make some assumptions - we assume if it takes money as it type,
901 * it wants some amount. We don't make change (ie, if something costs 920 * it wants some amount. We don't make change (ie, if something costs
902 * 3 gp and player drops a platinum, tough luck) 921 * 3 gp and player drops a platinum, tough luck)
903 */ 922 */
904 if (!strcmp(CONV_FROM(converter),"money")) { 923 if (!strcmp (CONV_FROM (converter), "money"))
924 {
905 int cost; 925 int cost;
906 926
907 if(item->type!=MONEY) 927 if (item->type != MONEY)
908 return 0; 928 return 0;
909 929
910 nr=(item->nrof*item->value)/CONV_NEED(converter); 930 nr = (item->nrof * item->value) / CONV_NEED (converter);
931 if (!nr)
911 if (!nr) return 0; 932 return 0;
912 cost=nr*CONV_NEED(converter)/item->value; 933 cost = nr * CONV_NEED (converter) / item->value;
913 /* take into account rounding errors */ 934 /* take into account rounding errors */
914 if (nr*CONV_NEED(converter)%item->value) cost++; 935 if (nr * CONV_NEED (converter) % item->value)
936 cost++;
915 decrease_ob_nr(item, cost); 937 decrease_ob_nr (item, cost);
916 938
917 price_in = cost*item->value; 939 price_in = cost * item->value;
940 }
941 else
918 } 942 {
919 else {
920 if(item->type==PLAYER||CONV_FROM(converter)!=item->arch->name|| 943 if (item->type == PLAYER || CONV_FROM (converter) != item->arch->name ||
921 (CONV_NEED(converter)&&CONV_NEED(converter)>item->nrof)) 944 (CONV_NEED (converter) && CONV_NEED (converter) > (uint16) item->nrof))
922 return 0; 945 return 0;
923 946
924 if(CONV_NEED(converter)) { 947 if (CONV_NEED (converter))
948 {
925 nr=item->nrof/CONV_NEED(converter); 949 nr = item->nrof / CONV_NEED (converter);
926 decrease_ob_nr(item,nr*CONV_NEED(converter)); 950 decrease_ob_nr (item, nr * CONV_NEED (converter));
927 price_in = nr*CONV_NEED(converter)*item->value; 951 price_in = nr * CONV_NEED (converter) * item->value;
952 }
928 } else { 953 else
954 {
929 price_in = item->value; 955 price_in = item->value;
930 remove_ob(item); 956 item->destroy ();
931 free_object(item);
932 } 957 }
933 } 958 }
934 959
935 if (converter->inv != NULL) { 960 if (converter->inv != NULL)
961 {
936 object *ob; 962 object *ob;
937 int i; 963 int i;
938 object *ob_to_copy; 964 object *ob_to_copy;
939 965
940 /* select random object from inventory to copy */ 966 /* select random object from inventory to copy */
941 ob_to_copy = converter->inv; 967 ob_to_copy = converter->inv;
942 for (ob = converter->inv->below, i = 1; ob != NULL; ob = ob->below, i++) { 968 for (ob = converter->inv->below, i = 1; ob != NULL; ob = ob->below, i++)
969 {
943 if (rndm(0, i) == 0) { 970 if (rndm (0, i) == 0)
971 {
944 ob_to_copy = ob; 972 ob_to_copy = ob;
945 } 973 }
946 } 974 }
947 item = object_create_clone(ob_to_copy); 975 item = object_create_clone (ob_to_copy);
948 CLEAR_FLAG(item, FLAG_IS_A_TEMPLATE); 976 CLEAR_FLAG (item, FLAG_IS_A_TEMPLATE);
949 unflag_inv(item, FLAG_IS_A_TEMPLATE); 977 unflag_inv (item, FLAG_IS_A_TEMPLATE);
950 } else { 978 }
979 else
980 {
951 if (converter->other_arch == NULL) { 981 if (converter->other_arch == NULL)
982 {
952 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",
953 &converter->name, converter->map->path, converter->x, converter->y); 984 &converter->name, &converter->map->path, converter->x, converter->y);
954 return -1; 985 return -1;
955 } 986 }
956 987
957 item = object_create_arch(converter->other_arch); 988 item = object_create_arch (converter->other_arch);
958 fix_generated_item(item, converter, 0, 0, GT_MINIMAL); 989 fix_generated_item (item, converter, 0, 0, GT_MINIMAL);
959 } 990 }
960 991
961 if(CONV_NR(converter)) 992 if (CONV_NR (converter))
962 item->nrof=CONV_NR(converter); 993 item->nrof = CONV_NR (converter);
963 if(nr) 994 if (nr)
964 item->nrof*=nr; 995 item->nrof *= nr;
965 if(is_in_shop (converter)) 996 if (is_in_shop (converter))
966 SET_FLAG(item,FLAG_UNPAID); 997 SET_FLAG (item, FLAG_UNPAID);
967 else if(price_in < item->nrof*item->value) { 998 else if (price_in < item->nrof * item->value)
999 {
968 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",
969 &converter->name, converter->map->path, converter->x, converter->y, price_in, 1001 &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name);
970 item->nrof*item->value, &item->name); 1002
971 /** 1003 /**
972 * 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
973 * propably had something in mind when doing this 1005 * propably had something in mind when doing this
974 */ 1006 */
975 } 1007 }
976 insert_ob_in_map_at(item, converter->map, converter, 0, converter->x, converter->y); 1008 insert_ob_in_map_at (item, converter->map, converter, 0, converter->x, converter->y);
977 return 1; 1009 return 1;
978} 1010}
979 1011
980/** 1012/**
981 * Handle apply on containers. 1013 * Handle apply on containers.
982 * By Eneq(@csd.uu.se). 1014 * By Eneq(@csd.uu.se).
983 * Moved to own function and added many features [Tero.Haatanen@lut.fi] 1015 * Moved to own function and added many features [Tero.Haatanen@lut.fi]
984 * added the alchemical cauldron to the code -b.t. 1016 * added the alchemical cauldron to the code -b.t.
985 */ 1017 */
986 1018
1019int
987int apply_container (object *op, object *sack) 1020apply_container (object *op, object *sack)
988{ 1021{
989 char buf[MAX_BUF]; 1022 char buf[MAX_BUF];
990 object *tmp; 1023 object *tmp;
991 1024
992 if(op->type!=PLAYER) 1025 if (op->type != PLAYER)
993 return 0; /* This might change */ 1026 return 0; /* This might change */
994 1027
995 if (sack==NULL || sack->type != CONTAINER) { 1028 if (sack == NULL || sack->type != CONTAINER)
1029 {
996 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]");
997 return 0; 1031 return 0;
998 } 1032 }
999 op->contr->last_used = NULL; 1033
1000 op->contr->last_used_id = 0; 1034 op->contr->last_used = 0;
1001 1035
1002 if (sack->env!=op) { 1036 if (sack->env != op)
1037 {
1003 if (sack->other_arch == NULL || sack->env != NULL) { 1038 if (sack->other_arch == NULL || sack->env != NULL)
1039 {
1004 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.");
1005 return 1; 1041 return 1;
1006 } 1042 }
1043
1007 /* It's on the ground, the problems begin */ 1044 /* It's on the ground, the problems begin */
1008 if (op->container != sack) { 1045 if (op->container != sack)
1046 {
1009 /* it's closed OR some player has opened it */ 1047 /* it's closed OR some player has opened it */
1010 if (QUERY_FLAG(sack, FLAG_APPLIED)) { 1048 if (QUERY_FLAG (sack, FLAG_APPLIED))
1011 for(tmp=get_map_ob(sack->map, sack->x, sack->y); 1049 {
1012 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);
1013 if (tmp) { 1051 if (tmp)
1052 {
1014 /* some other player have opened it */ 1053 /* some other player have opened it */
1015 new_draw_info_format(NDI_UNIQUE, 0, op, 1054 new_draw_info_format (NDI_UNIQUE, 0, op, "%s is already occupied.", query_name (sack));
1016 "%s is already occupied.", query_name(sack));
1017 return 1; 1055 return 1;
1018 } 1056 }
1019 } 1057 }
1020 } 1058 }
1021 if ( QUERY_FLAG(sack, FLAG_APPLIED)) { 1059 if (QUERY_FLAG (sack, FLAG_APPLIED))
1060 {
1022 if (op->container == NULL) { 1061 if (op->container == NULL)
1062 {
1023 tmp = arch_to_object (sack->other_arch); 1063 tmp = arch_to_object (sack->other_arch);
1024 /* not good, but insert_ob_in_ob() is too smart */ 1064 /* not good, but insert_ob_in_ob() is too smart */
1025 CLEAR_FLAG (tmp, FLAG_REMOVED); 1065 CLEAR_FLAG (tmp, FLAG_REMOVED);
1026 tmp->x= tmp->y = 0; 1066 tmp->x = tmp->y = 0;
1027 tmp->map = NULL; 1067 tmp->map = NULL;
1028 tmp->env = sack; 1068 tmp->env = sack;
1029 if (sack->inv) 1069 if (sack->inv)
1030 sack->inv->above = tmp; 1070 sack->inv->above = tmp;
1031 tmp->below = sack->inv; 1071 tmp->below = sack->inv;
1032 tmp->above = NULL; 1072 tmp->above = NULL;
1033 sack->inv = tmp; 1073 sack->inv = tmp;
1034 sack->move_off = MOVE_ALL; /* trying force closing it */ 1074 sack->move_off = MOVE_ALL; /* trying force closing it */
1075 }
1035 } else { 1076 else
1077 {
1036 sack->move_off = 0; 1078 sack->move_off = 0;
1037 tmp = sack->inv; 1079 tmp = sack->inv;
1080
1038 if (tmp && tmp->type == CLOSE_CON) { 1081 if (tmp && tmp->type == CLOSE_CON)
1039 remove_ob(tmp); 1082 tmp->destroy ();
1040 free_object (tmp); 1083 }
1084 }
1085 }
1086
1087 if (QUERY_FLAG (sack, FLAG_APPLIED))
1088 {
1089 if (op->container)
1090 {
1091 if (op->container != sack)
1092 {
1093 tmp = op->container;
1094 apply_container (op, tmp);
1095 sprintf (buf, "You close %s and open ", query_name (tmp));
1096 op->container = sack;
1097 strcat (buf, query_name (sack));
1098 strcat (buf, ".");
1099 }
1100 else
1101 {
1102 CLEAR_FLAG (sack, FLAG_APPLIED);
1103 op->container = NULL;
1104 sprintf (buf, "You close %s.", query_name (sack));
1105 }
1106 }
1107 else
1108 {
1109 CLEAR_FLAG (sack, FLAG_APPLIED);
1110 sprintf (buf, "You open %s.", query_name (sack));
1111 SET_FLAG (sack, FLAG_APPLIED);
1112 op->container = sack;
1113 }
1114 }
1115 else
1116 { /* not applied */
1117 if (sack->slaying)
1118 { /* it's locked */
1119 tmp = find_key (op, op, sack);
1120 if (tmp)
1121 {
1122 sprintf (buf, "You unlock %s with %s.", query_name (sack), query_name (tmp));
1123 SET_FLAG (sack, FLAG_APPLIED);
1124
1125 if (sack->env == NULL)
1126 { /* if it's on ground,open it also */
1127 new_draw_info (NDI_UNIQUE, 0, op, buf);
1128 apply_container (op, sack);
1129 return 1;
1041 } 1130 }
1042 } 1131 }
1132 else
1133 sprintf (buf, "You don't have the key to unlock %s.", query_name (sack));
1134 }
1135 else
1043 } 1136 {
1044 }
1045
1046 if (QUERY_FLAG (sack, FLAG_APPLIED)) {
1047 if (op->container) {
1048 if (op->container != sack) {
1049 tmp = op->container;
1050 apply_container (op, tmp);
1051 sprintf (buf, "You close %s and open ", query_name(tmp));
1052 op->container = sack;
1053 strcat (buf, query_name(sack));
1054 strcat (buf, ".");
1055 } else {
1056 CLEAR_FLAG (sack, FLAG_APPLIED);
1057 op->container = NULL;
1058 sprintf (buf, "You close %s.", query_name(sack));
1059 }
1060 } else {
1061 CLEAR_FLAG (sack, FLAG_APPLIED);
1062 sprintf (buf, "You open %s.", query_name(sack)); 1137 sprintf (buf, "You readied %s.", query_name (sack));
1063 SET_FLAG (sack, FLAG_APPLIED); 1138 SET_FLAG (sack, FLAG_APPLIED);
1064 op->container = sack; 1139
1065 } 1140 if (sack->env == NULL)
1066 } else { /* not applied */ 1141 { /* if it's on ground,open it also */
1067 if (sack->slaying) { /* it's locked */
1068 tmp = find_key(op, op, sack);
1069 if (tmp) {
1070 sprintf (buf, "You unlock %s with %s.", query_name(sack), query_name(tmp));
1071 SET_FLAG (sack, FLAG_APPLIED);
1072 if (sack->env == NULL) { /* if it's on ground,open it also */
1073 new_draw_info (NDI_UNIQUE,0,op, buf); 1142 new_draw_info (NDI_UNIQUE, 0, op, buf);
1074 apply_container (op, sack); 1143 apply_container (op, sack);
1075 return 1; 1144 return 1;
1076 } 1145 }
1077 } else {
1078 sprintf (buf, "You don't have the key to unlock %s.",
1079 query_name(sack));
1080 } 1146 }
1081 } else {
1082 sprintf (buf, "You readied %s.", query_name(sack));
1083 SET_FLAG (sack, FLAG_APPLIED);
1084 if (sack->env == NULL) { /* if it's on ground,open it also */
1085 new_draw_info (NDI_UNIQUE, 0, op, buf);
1086 apply_container (op, sack);
1087 return 1;
1088 }
1089 }
1090 } 1147 }
1148
1091 new_draw_info (NDI_UNIQUE, 0, op, buf); 1149 new_draw_info (NDI_UNIQUE, 0, op, buf);
1092 if (op->contr) op->contr->socket.update_look=1; 1150
1151 if (op->contr)
1152 op->contr->ns->floorbox_update ();
1153
1093 return 1; 1154 return 1;
1094} 1155}
1095 1156
1096/** 1157/**
1097 * 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
1098 * the player has in their inventory, eg, sacks, luggages, etc. 1159 * the player has in their inventory, eg, sacks, luggages, etc.
1105 * Reminder - there are three states for any container - closed (non applied), 1166 * Reminder - there are three states for any container - closed (non applied),
1106 * applied (not open, but objects that match get tossed into it), and open 1167 * applied (not open, but objects that match get tossed into it), and open
1107 * (applied flag set, and op->container points to the open container) 1168 * (applied flag set, and op->container points to the open container)
1108 */ 1169 */
1109 1170
1171int
1110int esrv_apply_container (object *op, object *sack) 1172esrv_apply_container (object *op, object *sack)
1111{ 1173{
1112 object *tmp=op->container; 1174 object *tmp = op->container;
1175
1113 if(op->type!=PLAYER) 1176 if (op->type != PLAYER)
1114 return 0; /* This might change */ 1177 return 0; /* This might change */
1115 1178
1116 if (sack==NULL || sack->type != CONTAINER) { 1179 if (sack == NULL || sack->type != CONTAINER)
1180 {
1117 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]");
1118 return 0; 1182 return 0;
1119 } 1183 }
1120 1184
1121 /* 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
1122 * 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
1123 * openening the new container. 1187 * openening the new container.
1124 */ 1188 */
1125 1189
1126 if (op->container && QUERY_FLAG(sack, FLAG_APPLIED)) { 1190 if (op->container && QUERY_FLAG (sack, FLAG_APPLIED))
1127 if (op->container->env != op) { /* if container is on the ground */ 1191 {
1192 if (op->container->env != op)
1193 { /* if container is on the ground */
1128 op->container->move_off = 0; 1194 op->container->move_off = 0;
1129 } 1195 }
1130 1196
1131 if (INVOKE_OBJECT (CLOSE, tmp, ARG_OBJECT (op))) 1197 if (INVOKE_OBJECT (CLOSE, tmp, ARG_OBJECT (op)))
1132 return 1; 1198 return 1;
1133 1199
1134 new_draw_info_format(NDI_UNIQUE, 0, op, "You close %s.", 1200 new_draw_info_format (NDI_UNIQUE, 0, op, "You close %s.", query_name (op->container));
1135 query_name(op->container));
1136 CLEAR_FLAG(op->container, FLAG_APPLIED); 1201 CLEAR_FLAG (op->container, FLAG_APPLIED);
1137 op->container=NULL; 1202 op->container = NULL;
1138 esrv_update_item (UPD_FLAGS, op, tmp); 1203 esrv_update_item (UPD_FLAGS, op, tmp);
1139 if (tmp == sack) return 1; 1204 if (tmp == sack)
1205 return 1;
1140 } 1206 }
1141 1207
1142 1208
1143 /* If the player is trying to open it (which he must be doing if we got here), 1209 /* If the player is trying to open it (which he must be doing if we got here),
1144 * and it is locked, check to see if player has the equipment to open it. 1210 * and it is locked, check to see if player has the equipment to open it.
1145 */ 1211 */
1146 1212
1147 if (sack->slaying) { /* it's locked */ 1213 if (sack->slaying)
1214 { /* it's locked */
1148 tmp=find_key(op, op, sack); 1215 tmp = find_key (op, op, sack);
1149 if (tmp) { 1216 if (tmp)
1217 {
1150 new_draw_info_format(NDI_UNIQUE, 0, op, "You unlock %s with %s.", query_name(sack), query_name(tmp)); 1218 new_draw_info_format (NDI_UNIQUE, 0, op, "You unlock %s with %s.", query_name (sack), query_name (tmp));
1219 }
1151 } else { 1220 else
1221 {
1152 new_draw_info_format(NDI_UNIQUE, 0, op, "You don't have the key to unlock %s.", 1222 new_draw_info_format (NDI_UNIQUE, 0, op, "You don't have the key to unlock %s.", query_name (sack));
1153 query_name(sack));
1154 return 0; 1223 return 0;
1155 } 1224 }
1156 } 1225 }
1157 1226
1158 /* By the time we get here, we have made sure any other container has been closed and 1227 /* By the time we get here, we have made sure any other container has been closed and
1159 * if this is a locked container, the player they key to open it. 1228 * if this is a locked container, the player they key to open it.
1160 */ 1229 */
1161 1230
1162 /* There are really two cases - the sack is either on the ground, or the sack is 1231 /* There are really two cases - the sack is either on the ground, or the sack is
1163 * part of the players inventory. If on the ground, we assume that the player is 1232 * part of the players inventory. If on the ground, we assume that the player is
1164 * opening it, since if it was being closed, that would have been taken care of above. 1233 * opening it, since if it was being closed, that would have been taken care of above.
1165 */ 1234 */
1166 1235
1167 1236
1168 if (sack->env != op) { 1237 if (sack->env != op)
1238 {
1169 /* Hypothetical case - the player is trying to open a sack that belong to someone 1239 /* Hypothetical case - the player is trying to open a sack that belong to someone
1170 * else. This normally should not happen, but a misbehaving client/player could 1240 * else. This normally should not happen, but a misbehaving client/player could
1171 * try to do it, so lets handle it gracefully. 1241 * try to do it, so lets handle it gracefully.
1172 */ 1242 */
1173 if (sack->env) { 1243 if (sack->env)
1244 {
1174 new_draw_info_format(NDI_UNIQUE, 0, op, "You can't open %s", 1245 new_draw_info_format (NDI_UNIQUE, 0, op, "You can't open %s", query_name (sack));
1175 query_name(sack));
1176 return 0; 1246 return 0;
1177 } 1247 }
1178 /* set these so when the player walks off, we can unapply the sack */ 1248 /* set these so when the player walks off, we can unapply the sack */
1179 sack->move_off = MOVE_ALL; /* trying force closing it */ 1249 sack->move_off = MOVE_ALL; /* trying force closing it */
1180 1250
1181 CLEAR_FLAG (sack, FLAG_APPLIED); 1251 CLEAR_FLAG (sack, FLAG_APPLIED);
1182 new_draw_info_format(NDI_UNIQUE, 0, op, "You open %s.", query_name(sack)); 1252 new_draw_info_format (NDI_UNIQUE, 0, op, "You open %s.", query_name (sack));
1183 SET_FLAG (sack, FLAG_APPLIED); 1253 SET_FLAG (sack, FLAG_APPLIED);
1184 op->container = sack; 1254 op->container = sack;
1185 esrv_update_item (UPD_FLAGS, op, sack); 1255 esrv_update_item (UPD_FLAGS, op, sack);
1186 esrv_send_inventory (op, sack); 1256 esrv_send_inventory (op, sack);
1187 1257
1188 } else { /* sack is in players inventory */ 1258 }
1189 if (QUERY_FLAG (sack, FLAG_APPLIED)) { /* readied sack becoming open */ 1259 else
1260 { /* sack is in players inventory */
1261 if (QUERY_FLAG (sack, FLAG_APPLIED))
1262 { /* readied sack becoming open */
1190 CLEAR_FLAG (sack, FLAG_APPLIED); 1263 CLEAR_FLAG (sack, FLAG_APPLIED);
1191 new_draw_info_format(NDI_UNIQUE, 0, op, "You open %s.", query_name(sack)); 1264 new_draw_info_format (NDI_UNIQUE, 0, op, "You open %s.", query_name (sack));
1192 SET_FLAG (sack, FLAG_APPLIED); 1265 SET_FLAG (sack, FLAG_APPLIED);
1193 op->container = sack; 1266 op->container = sack;
1194 esrv_update_item (UPD_FLAGS, op, sack); 1267 esrv_update_item (UPD_FLAGS, op, sack);
1195 esrv_send_inventory (op, sack); 1268 esrv_send_inventory (op, sack);
1269 }
1270 else
1196 } 1271 {
1197 else {
1198 CLEAR_FLAG (sack, FLAG_APPLIED); 1272 CLEAR_FLAG (sack, FLAG_APPLIED);
1199 new_draw_info_format(NDI_UNIQUE, 0, op, "You readied %s.", query_name(sack)); 1273 new_draw_info_format (NDI_UNIQUE, 0, op, "You readied %s.", query_name (sack));
1200 SET_FLAG (sack, FLAG_APPLIED); 1274 SET_FLAG (sack, FLAG_APPLIED);
1201 esrv_update_item (UPD_FLAGS, op, sack); 1275 esrv_update_item (UPD_FLAGS, op, sack);
1202 } 1276 }
1203 } 1277 }
1204 return 1; 1278 return 1;
1205} 1279}
1206 1280
1207 1281
1208/** 1282/**
1209 * Handles dropping things on altar. 1283 * Handles dropping things on altar.
1210 * Returns true if sacrifice was accepted. 1284 * Returns true if sacrifice was accepted.
1211 */ 1285 */
1286static int
1212static int apply_altar (object *altar, object *sacrifice, object *originator) 1287apply_altar (object *altar, object *sacrifice, object *originator)
1213{ 1288{
1214 /* Only players can make sacrifices on spell casting altars. */ 1289 /* Only players can make sacrifices on spell casting altars. */
1215 if (altar->inv && ( ! originator || originator->type != PLAYER)) 1290 if (altar->inv && (!originator || originator->type != PLAYER))
1216 return 0; 1291 return 0;
1217 1292
1218 if (operate_altar (altar, &sacrifice)) { 1293 if (operate_altar (altar, &sacrifice))
1294 {
1219 /* Simple check. Unfortunately, it means you can't cast magic bullet 1295 /* Simple check. Unfortunately, it means you can't cast magic bullet
1220 * with an altar. We call it a Potion - altars are stationary - it 1296 * with an altar. We call it a Potion - altars are stationary - it
1221 * is up to map designers to use them properly. 1297 * is up to map designers to use them properly.
1222 */ 1298 */
1223 if (altar->inv && altar->inv->type==SPELL) { 1299 if (altar->inv && altar->inv->type == SPELL)
1300 {
1224 new_draw_info_format (NDI_BLACK, 0, originator, "The altar casts %s.", &altar->inv->name); 1301 new_draw_info_format (NDI_BLACK, 0, originator, "The altar casts %s.", &altar->inv->name);
1225 cast_spell (originator, altar, 0, altar->inv, NULL); 1302 cast_spell (originator, altar, 0, altar->inv, NULL);
1226 /* If it is connected, push the button. Fixes some problems with 1303 /* If it is connected, push the button. Fixes some problems with
1227 * old maps. 1304 * old maps.
1228 */ 1305 */
1306
1229/* push_button (altar);*/ 1307/* push_button (altar);*/
1308 }
1230 } else { 1309 else
1310 {
1231 altar->value = 1; /* works only once */ 1311 altar->value = 1; /* works only once */
1232 push_button (altar); 1312 push_button (altar);
1233 } 1313 }
1314
1234 return sacrifice == NULL; 1315 return !sacrifice;
1235 } else { 1316 }
1317 else
1236 return 0; 1318 return 0;
1237 }
1238} 1319}
1239
1240 1320
1241/** 1321/**
1242 * Handles 'movement' of shop mats. 1322 * Handles 'movement' of shop mats.
1243 * Returns 1 if 'op' was destroyed, 0 if not. 1323 * Returns 1 if 'op' was destroyed, 0 if not.
1244 * Largely re-written to not use nearly as many gotos, plus 1324 * Largely re-written to not use nearly as many gotos, plus
1245 * some of this code just looked plain out of date. 1325 * some of this code just looked plain out of date.
1246 * MSW 2001-08-29 1326 * MSW 2001-08-29
1247 */ 1327 */
1328int
1248int apply_shop_mat (object * shop_mat, object * op) 1329apply_shop_mat (object *shop_mat, object *op)
1249{ 1330{
1250 int rv = 0; 1331 int rv = 0;
1251 double opinion; 1332 double opinion;
1252 object *tmp, *next; 1333 object *tmp, *next;
1253 1334
1260 * the shop. 1341 * the shop.
1261 */ 1342 */
1262 for (tmp = op->inv; tmp; tmp = next) 1343 for (tmp = op->inv; tmp; tmp = next)
1263 { 1344 {
1264 next = tmp->below; 1345 next = tmp->below;
1346
1265 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 1347 if (QUERY_FLAG (tmp, FLAG_UNPAID))
1266 { 1348 {
1267 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);
1268 1350
1269 remove_ob (tmp); 1351 tmp->remove ();
1352
1270 if (i == -1) 1353 if (i == -1)
1271 i = 0; 1354 i = 0;
1355
1272 tmp->map = op->map; 1356 tmp->map = op->map;
1273 tmp->x = op->x + freearr_x[i]; 1357 tmp->x = op->x + freearr_x[i];
1274 tmp->y = op->y + freearr_y[i]; 1358 tmp->y = op->y + freearr_y[i];
1275 insert_ob_in_map (tmp, op->map, op, 0); 1359 insert_ob_in_map (tmp, op->map, op, 0);
1276 } 1360 }
1286 if (QUERY_FLAG (op, FLAG_UNPAID) || !QUERY_FLAG (op, FLAG_ALIVE)) 1370 if (QUERY_FLAG (op, FLAG_UNPAID) || !QUERY_FLAG (op, FLAG_ALIVE))
1287 { 1371 {
1288 1372
1289 /* Somebody dropped an unpaid item, just move to an adjacent place. */ 1373 /* Somebody dropped an unpaid item, just move to an adjacent place. */
1290 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);
1375
1291 if (i != -1) 1376 if (i != -1)
1292 {
1293 rv =
1294 transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 1377 rv = transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 0, shop_mat);
1295 0, shop_mat); 1378
1296 }
1297 return 0; 1379 return 0;
1298 } 1380 }
1299 /* Removed code that checked for multipart objects - it appears that 1381 /* Removed code that checked for multipart objects - it appears that
1300 * the teleport function should be able to handle this just fine. 1382 * the teleport function should be able to handle this just fine.
1301 */ 1383 */
1302 rv = teleport (shop_mat, SHOP_MAT, op); 1384 rv = teleport (shop_mat, SHOP_MAT, op);
1303 } 1385 }
1304 /* immediate block below is only used for players */ 1386 else if (can_pay (op) && get_payment (op))
1305 else if (can_pay (op))
1306 { 1387 {
1307 get_payment (op, op->inv); 1388 /* this is only used for players */
1308 rv = teleport (shop_mat, SHOP_MAT, op); 1389 rv = teleport (shop_mat, SHOP_MAT, op);
1309 1390
1310 if (shop_mat->msg) 1391 if (shop_mat->msg)
1311 {
1312 new_draw_info (NDI_UNIQUE, 0, op, shop_mat->msg); 1392 new_draw_info (NDI_UNIQUE, 0, op, shop_mat->msg);
1313 }
1314 /* 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,
1315 * 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
1316 * actually the shop floor. 1395 * actually the shop floor.
1317 */ 1396 */
1318 else if (!rv && !is_in_shop (op)) 1397 else if (!rv && !is_in_shop (op))
1319 { 1398 {
1320 opinion = shopkeeper_approval (op->map, op); 1399 opinion = shopkeeper_approval (op->map, op);
1400
1321 if (opinion > 0.9) 1401 if (opinion > 0.9)
1322 new_draw_info (NDI_UNIQUE, 0, op, 1402 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper gives you a friendly wave.");
1323 "The shopkeeper gives you a friendly wave.");
1324 else if (opinion > 0.75) 1403 else if (opinion > 0.75)
1325 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.");
1326 else if (opinion > 0.5) 1405 else if (opinion > 0.5)
1327 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper ignores you."); 1406 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper ignores you.");
1328 else 1407 else
1329 new_draw_info (NDI_UNIQUE, 0, op, 1408 new_draw_info (NDI_UNIQUE, 0, op, "The shopkeeper glares at you with contempt.");
1330 "The shopkeeper glares at you with contempt.");
1331 } 1409 }
1332 } 1410 }
1333 else 1411 else
1334 { 1412 {
1335 /* 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
1336 * 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
1337 * they are not on the mat anymore 1415 * they are not on the mat anymore
1338 */ 1416 */
1339
1340 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);
1418
1341 if (i == -1) 1419 if (i == -1)
1342 { 1420 {
1343 LOG (llevError, "Internal shop-mat problem.\n"); 1421 LOG (llevError, "Internal shop-mat problem.\n");
1344 } 1422 }
1345 else 1423 else
1346 { 1424 {
1347 remove_ob (op); 1425 op->remove ();
1348 op->x += freearr_x[i]; 1426 op->x += freearr_x[i];
1349 op->y += freearr_y[i]; 1427 op->y += freearr_y[i];
1350 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;
1351 } 1429 }
1352 } 1430 }
1431
1353 CLEAR_FLAG (op, FLAG_NO_APPLY); 1432 CLEAR_FLAG (op, FLAG_NO_APPLY);
1354 return rv; 1433 return rv;
1355} 1434}
1356 1435
1357/** 1436/**
1358 * Handles applying a sign. 1437 * Handles applying a sign.
1359 */ 1438 */
1439static void
1360static void apply_sign (object *op, object *sign, int autoapply) 1440apply_sign (object *op, object *sign, int autoapply)
1361{ 1441{
1362 readable_message_type* msgType; 1442 readable_message_type *msgType;
1363 char newbuf[HUGE_BUF]; 1443 char newbuf[HUGE_BUF];
1444
1364 if (sign->msg == NULL) { 1445 if (sign->msg == NULL)
1446 {
1365 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is written on it."); 1447 new_draw_info (NDI_UNIQUE, 0, op, "Nothing is written on it.");
1366 return; 1448 return;
1367 } 1449 }
1368 1450
1369 if (sign->stats.food) { 1451 if (sign->stats.food)
1452 {
1370 if (sign->last_eat >= sign->stats.food) { 1453 if (sign->last_eat >= sign->stats.food)
1454 {
1371 if (!sign->move_on) 1455 if (!sign->move_on)
1372 new_draw_info (NDI_UNIQUE, 0, op, "You cannot read it anymore."); 1456 new_draw_info (NDI_UNIQUE, 0, op, "You cannot read it anymore.");
1373 return; 1457 return;
1374 } 1458 }
1375 1459
1376 if (!QUERY_FLAG(op, FLAG_WIZPASS)) 1460 if (!QUERY_FLAG (op, FLAG_WIZPASS))
1377 sign->last_eat++; 1461 sign->last_eat++;
1378 } 1462 }
1379 1463
1380 /* Sign or magic mouth? Do we need to see it, or does it talk to us? 1464 /* Sign or magic mouth? Do we need to see it, or does it talk to us?
1381 * No way to know for sure. The presumption is basically that if 1465 * No way to know for sure. The presumption is basically that if
1382 * move_on is zero, it needs to be manually applied (doesn't talk 1466 * move_on is zero, it needs to be manually applied (doesn't talk
1383 * to us). 1467 * to us).
1384 */ 1468 */
1385 if (QUERY_FLAG (op, FLAG_BLIND) && ! QUERY_FLAG (op, FLAG_WIZ) && !sign->move_on) { 1469 if (QUERY_FLAG (op, FLAG_BLIND) && !QUERY_FLAG (op, FLAG_WIZ) && !sign->move_on)
1386 new_draw_info (NDI_UNIQUE, 0, op, 1470 {
1387 "You are unable to read while blind."); 1471 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to read while blind.");
1388 return; 1472 return;
1389 } 1473 }
1390 msgType=get_readable_message_type(sign); 1474 msgType = get_readable_message_type (sign);
1391 snprintf(newbuf,sizeof(newbuf),"%hhu %s", autoapply?1:0, &sign->msg); 1475 snprintf (newbuf, sizeof (newbuf), "%hhu %s", autoapply ? 1 : 0, &sign->msg);
1392 draw_ext_info(NDI_UNIQUE | NDI_NAVY, 0, op, msgType->message_type, msgType->message_subtype, newbuf, &sign->msg); 1476 draw_ext_info (NDI_UNIQUE | NDI_NAVY, 0, op, msgType->message_type, msgType->message_subtype, newbuf, &sign->msg);
1393} 1477}
1394 1478
1395/** 1479/**
1396 * 'victim' moves onto 'trap' 1480 * 'victim' moves onto 'trap'
1397 * 'victim' leaves 'trap' 1481 * 'victim' leaves 'trap'
1399 * 1483 *
1400 * originator: Player, monster or other object that caused 'victim' to move 1484 * originator: Player, monster or other object that caused 'victim' to move
1401 * onto 'trap'. Will receive messages caused by this action. May be NULL. 1485 * onto 'trap'. Will receive messages caused by this action. May be NULL.
1402 * However, some types of traps require an originator to function. 1486 * However, some types of traps require an originator to function.
1403 */ 1487 */
1488void
1404void move_apply (object *trap, object *victim, object *originator) 1489move_apply (object *trap, object *victim, object *originator)
1405{ 1490{
1406 static int recursion_depth = 0; 1491 static int recursion_depth = 0;
1407 1492
1408 /* Only exits affect DMs. */ 1493 /* Only exits affect DMs. */
1409 if (QUERY_FLAG(victim, FLAG_WIZPASS) && trap->type != EXIT && trap->type != SIGN) 1494 if (QUERY_FLAG (victim, FLAG_WIZPASS) && trap->type != EXIT && trap->type != SIGN)
1410 return; 1495 return;
1411 1496
1412 /* move_apply() is the most likely candidate for causing unwanted and 1497 /* move_apply() is the most likely candidate for causing unwanted and
1413 * possibly unlimited recursion. 1498 * possibly unlimited recursion.
1414 */ 1499 */
1416 * maps to fail. 1) it's not an error to recurse: 1501 * maps to fail. 1) it's not an error to recurse:
1417 * rune detonates, summoning monster. monster lands on nearby rune. 1502 * rune detonates, summoning monster. monster lands on nearby rune.
1418 * nearby rune detonates. This sort of recursion is expected and 1503 * nearby rune detonates. This sort of recursion is expected and
1419 * proper. This code was causing needless crashes. 1504 * proper. This code was causing needless crashes.
1420 */ 1505 */
1421 if (recursion_depth >= 500) { 1506 if (recursion_depth >= 500)
1507 {
1422 LOG (llevDebug, "WARNING: move_apply(): aborting recursion " 1508 LOG (llevDebug, "WARNING: move_apply(): aborting recursion "
1423 "[trap arch %s, name %s; victim arch %s, name %s]\n", 1509 "[trap arch %s, name %s; victim arch %s, name %s]\n", &trap->arch->name, &trap->name, &victim->arch->name, &victim->name);
1424 &trap->arch->name, &trap->name, &victim->arch->name, &victim->name);
1425 return; 1510 return;
1426 } 1511 }
1427 recursion_depth++; 1512 recursion_depth++;
1428 if (trap->head) trap=trap->head; 1513 if (trap->head)
1514 trap = trap->head;
1429 1515
1430 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)))
1517 goto leave;
1518
1519 switch (trap->type)
1520 {
1521 case PLAYERMOVER:
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 }
1431 goto leave; 1540 goto leave;
1432 1541
1433 switch (trap->type) { 1542 case SPINNER:
1434 case PLAYERMOVER: 1543 if (victim->direction)
1435 if (trap->attacktype && (trap->level || victim->type!=PLAYER) && 1544 {
1436 !should_director_abort(trap, victim)) { 1545 victim->direction = absdir (victim->direction - trap->stats.sp);
1437 if (!trap->stats.maxsp) trap->stats.maxsp=2; 1546 update_turn_face (victim);
1547 }
1548 goto leave;
1438 1549
1439 /* Is this correct? From the docs, it doesn't look like it 1550 case DIRECTOR:
1440 * should be divided by trap->speed 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)
1441 */ 1594 {
1442 victim->speed_left = -FABS(trap->stats.maxsp*victim->speed/trap->speed); 1595 int tot;
1443 1596
1444 /* Just put in some sanity check. I think there is a bug in the 1597 for (ab = trap->above, tot = 0; ab != NULL; ab = ab->above)
1445 * above with some objects have zero speed, and thus the player 1598 if ((ab->move_type && trap->move_on) || ab->move_type == 0)
1446 * getting permanently paralyzed. 1599 tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying;
1447 */ 1600
1448 if (victim->speed_left<-50.0) victim->speed_left=-50.0; 1601 if (!(trap->value = (tot > trap->weight) ? 1 : 0))
1449 /* LOG(llevDebug, "apply, playermove, player speed_left=%f\n", victim->speed_left);*/ 1602 goto leave;
1603
1604 SET_ANIMATION (trap, trap->value);
1605 update_object (trap, UP_OBJ_FACE);
1450 } 1606 }
1451 goto leave;
1452 1607
1453 case SPINNER:
1454 if(victim->direction) {
1455 victim->direction=absdir(victim->direction-trap->stats.sp);
1456 update_turn_face(victim);
1457 }
1458 goto leave;
1459
1460 case DIRECTOR:
1461 if(victim->direction && !should_director_abort(trap, victim)) {
1462 victim->direction=trap->stats.sp;
1463 update_turn_face(victim);
1464 }
1465 goto leave;
1466
1467 case BUTTON:
1468 case PEDESTAL:
1469 update_button(trap);
1470 goto leave;
1471
1472 case ALTAR:
1473 /* sacrifice victim on trap */
1474 apply_altar (trap, victim, originator);
1475 goto leave;
1476
1477 case THROWN_OBJ:
1478 if (trap->inv == NULL)
1479 goto leave;
1480 /* fallthrough */
1481
1482 case ARROW:
1483
1484 /* bad bug: monster throw a object, make a step forwards, step on object ,
1485 * trigger this here and get hit by own missile - and will be own enemy.
1486 * Victim then is his own enemy and will start to kill herself (this is
1487 * removed) but we have not synced victim and his missile. To avoid senseless
1488 * action, we avoid hits here
1489 */
1490 if ((QUERY_FLAG (victim, FLAG_ALIVE) && trap->speed) && trap->owner != victim)
1491 hit_with_arrow (trap, victim);
1492 goto leave;
1493
1494 case SPELL_EFFECT:
1495 apply_spell_effect(trap, victim);
1496 goto leave;
1497
1498 case TRAPDOOR:
1499 {
1500 int max, sound_was_played;
1501 object *ab, *ab_next;
1502 if(!trap->value) {
1503 int tot;
1504 for(ab=trap->above,tot=0;ab!=NULL;ab=ab->above)
1505 if ((ab->move_type && trap->move_on) || ab->move_type==0)
1506 tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying;
1507
1508 if(!(trap->value=(tot>trap->weight)?1:0))
1509 goto leave;
1510
1511 SET_ANIMATION(trap, trap->value);
1512 update_object(trap,UP_OBJ_FACE);
1513 }
1514
1515 for (ab = trap->above, max=100, sound_was_played = 0; --max && ab; ab=ab_next) { 1608 for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab; ab = ab_next)
1609 {
1516 /* need to set this up, since if we do transfer the object, 1610 /* need to set this up, since if we do transfer the object,
1517 * ab->above would be bogus 1611 * ab->above would be bogus
1518 */ 1612 */
1519 ab_next = ab->above; 1613 ab_next = ab->above;
1520 1614
1521 if ((ab->move_type && trap->move_on) || ab->move_type==0) { 1615 if ((ab->move_type && trap->move_on) || ab->move_type == 0)
1616 {
1522 if ( ! sound_was_played) { 1617 if (!sound_was_played)
1618 {
1523 play_sound_map(trap->map, trap->x, trap->y, SOUND_FALL_HOLE); 1619 play_sound_map (trap->map, trap->x, trap->y, SOUND_FALL_HOLE);
1524 sound_was_played = 1; 1620 sound_was_played = 1;
1525 } 1621 }
1526 new_draw_info(NDI_UNIQUE, 0,ab,"You fall into a trapdoor!"); 1622 new_draw_info (NDI_UNIQUE, 0, ab, "You fall into a trapdoor!");
1527 transfer_ob(ab,(int)EXIT_X(trap),(int)EXIT_Y(trap),0,ab); 1623 transfer_ob (ab, (int) EXIT_X (trap), (int) EXIT_Y (trap), 0, ab);
1528 } 1624 }
1529 } 1625 }
1530 goto leave; 1626 goto leave;
1531 } 1627 }
1532 1628
1533 1629
1534 case CONVERTER: 1630 case CONVERTER:
1535 if (convert_item (victim, trap) < 0) { 1631 if (convert_item (victim, trap) < 0)
1632 {
1536 object *op; 1633 object *op;
1537 1634
1538 new_draw_info_format(NDI_UNIQUE, 0, originator, "The %s seems to be broken!", query_name(trap)); 1635 new_draw_info_format (NDI_UNIQUE, 0, originator, "The %s seems to be broken!", query_name (trap));
1539 1636
1540 op = get_archetype("burnout"); 1637 op = get_archetype ("burnout");
1541 if (op != NULL) { 1638 if (op != NULL)
1639 {
1542 op->x = trap->x; 1640 op->x = trap->x;
1543 op->y = trap->y; 1641 op->y = trap->y;
1544 insert_ob_in_map(op, trap->map, trap, 0); 1642 insert_ob_in_map (op, trap->map, trap, 0);
1545 } 1643 }
1546 } 1644 }
1547 goto leave; 1645 goto leave;
1548 1646
1549 case TRIGGER_BUTTON: 1647 case TRIGGER_BUTTON:
1550 case TRIGGER_PEDESTAL: 1648 case TRIGGER_PEDESTAL:
1551 case TRIGGER_ALTAR: 1649 case TRIGGER_ALTAR:
1552 check_trigger (trap, victim); 1650 check_trigger (trap, victim);
1553 goto leave; 1651 goto leave;
1554 1652
1555 case DEEP_SWAMP: 1653 case DEEP_SWAMP:
1556 walk_on_deep_swamp (trap, victim); 1654 walk_on_deep_swamp (trap, victim);
1557 goto leave; 1655 goto leave;
1558 1656
1559 case CHECK_INV: 1657 case CHECK_INV:
1560 check_inv (victim, trap); 1658 check_inv (victim, trap);
1659 goto leave;
1660
1661 case HOLE:
1662 /* Hole not open? */
1663 if (trap->stats.wc > 0)
1561 goto leave; 1664 goto leave;
1562 1665
1563 case HOLE:
1564 /* Hole not open? */
1565 if(trap->stats.wc > 0)
1566 goto leave;
1567
1568 /* Is this a multipart monster and not the head? If so, return. 1666 /* Is this a multipart monster and not the head? If so, return.
1569 * Processing will happen if the head runs into the pit 1667 * Processing will happen if the head runs into the pit
1668 */
1669 if (victim->head)
1670 goto leave;
1671
1672 play_sound_map (victim->map, victim->x, victim->y, SOUND_FALL_HOLE);
1673 new_draw_info (NDI_UNIQUE, 0, victim, "You fall through the hole!\n");
1674 transfer_ob (victim, EXIT_X (trap), EXIT_Y (trap), 1, victim);
1675 goto leave;
1676
1677 case EXIT:
1678 if (victim->type == PLAYER && EXIT_PATH (trap))
1679 {
1680 /* Basically, don't show exits leading to random maps the
1681 * players output.
1570 */ 1682 */
1571 if (victim->head) 1683 if (trap->msg && strncmp (EXIT_PATH (trap), "/!", 2))
1572 goto leave;
1573
1574 play_sound_map (victim->map, victim->x, victim->y, SOUND_FALL_HOLE);
1575 new_draw_info (NDI_UNIQUE, 0, victim, "You fall through the hole!\n");
1576 transfer_ob (victim, EXIT_X (trap), EXIT_Y (trap), 1, victim);
1577 goto leave;
1578
1579 case EXIT:
1580 if (victim->type == PLAYER && EXIT_PATH (trap)) {
1581 /* Basically, don't show exits leading to random maps the
1582 * players output.
1583 */
1584 if (trap->msg && strncmp(EXIT_PATH(trap),"/!",2) && strncmp(EXIT_PATH(trap), "/random/", 8))
1585 new_draw_info (NDI_NAVY, 0, victim, trap->msg); 1684 new_draw_info (NDI_NAVY, 0, victim, trap->msg);
1685
1586 enter_exit (victim, trap); 1686 victim->enter_exit (trap);
1587 } 1687 }
1588 goto leave; 1688 goto leave;
1589 1689
1590 case ENCOUNTER: 1690 case ENCOUNTER:
1591 /* may be some leftovers on this */ 1691 /* may be some leftovers on this */
1592 goto leave; 1692 goto leave;
1593 1693
1594 case SHOP_MAT: 1694 case SHOP_MAT:
1595 apply_shop_mat (trap, victim); 1695 apply_shop_mat (trap, victim);
1596 goto leave; 1696 goto leave;
1597 1697
1598 /* Drop a certain amount of gold, and have one item identified */ 1698 /* Drop a certain amount of gold, and have one item identified */
1599 case IDENTIFY_ALTAR: 1699 case IDENTIFY_ALTAR:
1600 apply_id_altar (victim, trap, originator); 1700 apply_id_altar (victim, trap, originator);
1601 goto leave; 1701 goto leave;
1602 1702
1603 case SIGN: 1703 case SIGN:
1604 if (victim->type != PLAYER && trap->stats.food > 0) 1704 if (victim->type != PLAYER && trap->stats.food > 0)
1605 goto leave; /* monsters musn't apply magic_mouths with counters */ 1705 goto leave; /* monsters musn't apply magic_mouths with counters */
1606 1706
1607 apply_sign (victim, trap, 1); 1707 apply_sign (victim, trap, 1);
1608 goto leave; 1708 goto leave;
1609 1709
1610 case CONTAINER: 1710 case CONTAINER:
1611 if (victim->type==PLAYER) 1711 if (victim->type == PLAYER)
1612 (void) esrv_apply_container (victim, trap); 1712 (void) esrv_apply_container (victim, trap);
1613 else 1713 else
1614 (void) apply_container (victim, trap); 1714 (void) apply_container (victim, trap);
1615 goto leave; 1715 goto leave;
1616 1716
1617 case RUNE: 1717 case RUNE:
1618 case TRAP: 1718 case TRAP:
1619 if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE)) { 1719 if (trap->level && QUERY_FLAG (victim, FLAG_ALIVE))
1720 {
1620 spring_trap(trap, victim); 1721 spring_trap (trap, victim);
1621 } 1722 }
1622 goto leave; 1723 goto leave;
1623 1724
1624 default: 1725 default:
1625 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 "
1626 "handled in move_apply()\n", &trap->name, &trap->arch->name, 1727 "handled in move_apply()\n", &trap->name, &trap->arch->name, trap->type);
1627 trap->type);
1628 goto leave; 1728 goto leave;
1629 } 1729 }
1630 1730
1631 leave: 1731leave:
1632 recursion_depth--; 1732 recursion_depth--;
1633} 1733}
1634 1734
1635/** 1735/**
1636 * Handles reading a regular (ie not containing a spell) book. 1736 * Handles reading a regular (ie not containing a spell) book.
1637 */ 1737 */
1738static void
1638static void apply_book (object *op, object *tmp) 1739apply_book (object *op, object *tmp)
1639{ 1740{
1640 int lev_diff; 1741 int lev_diff;
1641 object *skill_ob; 1742 object *skill_ob;
1642 1743
1643 if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) { 1744 if (QUERY_FLAG (op, FLAG_BLIND) && !QUERY_FLAG (op, FLAG_WIZ))
1745 {
1644 new_draw_info(NDI_UNIQUE, 0,op,"You are unable to read while blind."); 1746 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to read while blind.");
1645 return; 1747 return;
1646 } 1748 }
1647 if(tmp->msg==NULL) { 1749 if (tmp->msg == NULL)
1648 new_draw_info_format(NDI_UNIQUE, 0, op, 1750 {
1649 "You open the %s and find it empty.", &tmp->name); 1751 new_draw_info_format (NDI_UNIQUE, 0, op, "You open the %s and find it empty.", &tmp->name);
1650 return; 1752 return;
1651 } 1753 }
1652 1754
1653 /* need a literacy skill to read stuff! */ 1755 /* need a literacy skill to read stuff! */
1654 skill_ob = find_skill_by_name(op, tmp->skill); 1756 skill_ob = find_skill_by_name (op, tmp->skill);
1655 if ( ! skill_ob) { 1757 if (!skill_ob)
1656 new_draw_info(NDI_UNIQUE, 0,op, 1758 {
1657 "You are unable to decipher the strange symbols."); 1759 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to decipher the strange symbols.");
1658 return; 1760 return;
1659 } 1761 }
1660 lev_diff = tmp->level - (skill_ob->level + 5); 1762 lev_diff = tmp->level - (skill_ob->level + 5);
1661 if ( ! QUERY_FLAG (op, FLAG_WIZ) && lev_diff > 0) { 1763 if (!QUERY_FLAG (op, FLAG_WIZ) && lev_diff > 0)
1764 {
1662 if (lev_diff < 2) 1765 if (lev_diff < 2)
1663 new_draw_info(NDI_UNIQUE, 0,op,"This book is just barely beyond your comprehension."); 1766 new_draw_info (NDI_UNIQUE, 0, op, "This book is just barely beyond your comprehension.");
1664 else if (lev_diff < 3) 1767 else if (lev_diff < 3)
1665 new_draw_info(NDI_UNIQUE, 0,op,"This book is slightly beyond your comprehension."); 1768 new_draw_info (NDI_UNIQUE, 0, op, "This book is slightly beyond your comprehension.");
1666 else if (lev_diff < 5) 1769 else if (lev_diff < 5)
1667 new_draw_info(NDI_UNIQUE, 0,op,"This book is beyond your comprehension."); 1770 new_draw_info (NDI_UNIQUE, 0, op, "This book is beyond your comprehension.");
1668 else if (lev_diff < 8) 1771 else if (lev_diff < 8)
1669 new_draw_info(NDI_UNIQUE, 0,op,"This book is quite a bit beyond your comprehension."); 1772 new_draw_info (NDI_UNIQUE, 0, op, "This book is quite a bit beyond your comprehension.");
1670 else if (lev_diff < 15) 1773 else if (lev_diff < 15)
1671 new_draw_info(NDI_UNIQUE, 0,op,"This book is way beyond your comprehension."); 1774 new_draw_info (NDI_UNIQUE, 0, op, "This book is way beyond your comprehension.");
1672 else 1775 else
1673 new_draw_info(NDI_UNIQUE, 0,op,"This book is totally beyond your comprehension."); 1776 new_draw_info (NDI_UNIQUE, 0, op, "This book is totally beyond your comprehension.");
1674 return; 1777 return;
1675 } 1778 }
1676 1779
1677 readable_message_type* msgType = get_readable_message_type(tmp); 1780 readable_message_type *msgType = get_readable_message_type (tmp);
1781
1678 draw_ext_info_format(NDI_UNIQUE | NDI_NAVY, 0, op, 1782 draw_ext_info_format (NDI_UNIQUE | NDI_NAVY, 0, op,
1679 msgType->message_type, msgType->message_subtype, 1783 msgType->message_type, msgType->message_subtype,
1680 "You open the %s and start reading.\n%s", 1784 "You open the %s and start reading.\n%s", "%s\n%s", long_desc (tmp, op), &tmp->msg);
1681 "%s\n%s",
1682 long_desc(tmp,op), &tmp->msg);
1683 1785
1684 /* gain xp from reading */ 1786 /* gain xp from reading */
1685 if(!QUERY_FLAG(tmp,FLAG_NO_SKILL_IDENT)) { /* only if not read before */ 1787 if (!QUERY_FLAG (tmp, FLAG_NO_SKILL_IDENT))
1788 { /* only if not read before */
1686 int exp_gain=calc_skill_exp(op,tmp, skill_ob); 1789 int exp_gain = calc_skill_exp (op, tmp, skill_ob);
1790
1687 if(!QUERY_FLAG(tmp,FLAG_IDENTIFIED)) { 1791 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1792 {
1688 /*exp_gain *= 2; because they just identified it too */ 1793 /*exp_gain *= 2; because they just identified it too */
1689 SET_FLAG(tmp,FLAG_IDENTIFIED); 1794 SET_FLAG (tmp, FLAG_IDENTIFIED);
1795
1690 /* If in a container, update how it looks */ 1796 /* If in a container, update how it looks */
1797 if (tmp->env)
1691 if(tmp->env) esrv_update_item(UPD_FLAGS|UPD_NAME, op,tmp); 1798 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp);
1692 else op->contr->socket.update_look=1; 1799 else
1800 op->contr->ns->floorbox_update ();
1693 } 1801 }
1802
1694 change_exp(op,exp_gain, skill_ob->skill, 0); 1803 change_exp (op, exp_gain, skill_ob->skill, 0);
1695 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 */
1696 } 1805 }
1697} 1806}
1698 1807
1699/** 1808/**
1700 * Handles the applying of a skill scroll, calling learn_skill straight. 1809 * Handles the applying of a skill scroll, calling learn_skill straight.
1701 * op is the person learning the skill, tmp is the skill scroll object 1810 * op is the person learning the skill, tmp is the skill scroll object
1702 */ 1811 */
1812static void
1703static void apply_skillscroll (object *op, object *tmp) 1813apply_skillscroll (object *op, object *tmp)
1704{ 1814{
1705 switch ((int) learn_skill (op, tmp)) { 1815 switch ((int) learn_skill (op, tmp))
1816 {
1706 case 0: 1817 case 0:
1707 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 ");
1708 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));
1709 return; 1820 return;
1710 1821
1711 case 1: 1822 case 1:
1712 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);
1713 decrease_ob(tmp); 1824 decrease_ob (tmp);
1714 return; 1825 return;
1715 1826
1716 default: 1827 default:
1717 new_draw_info_format(NDI_UNIQUE,0,op, 1828 new_draw_info_format (NDI_UNIQUE, 0, op, "You fail to learn the knowledge of the %s.\n", query_name (tmp));
1718 "You fail to learn the knowledge of the %s.\n",query_name(tmp));
1719 decrease_ob(tmp); 1829 decrease_ob (tmp);
1720 return; 1830 return;
1721 } 1831 }
1722} 1832}
1723 1833
1724/** 1834/**
1725 * Actually makes op learn spell. 1835 * Actually makes op learn spell.
1726 * Informs player of what happens. 1836 * Informs player of what happens.
1727 */ 1837 */
1838void
1728void do_learn_spell (object *op, object *spell, int special_prayer) 1839do_learn_spell (object *op, object *spell, int special_prayer)
1729{ 1840{
1730 object *tmp; 1841 object *tmp;
1731 1842
1732 if (op->type != PLAYER) { 1843 if (op->type != PLAYER)
1844 {
1733 LOG (llevError, "BUG: do_learn_spell(): not a player\n"); 1845 LOG (llevError, "BUG: do_learn_spell(): not a player\n");
1734 return; 1846 return;
1735 } 1847 }
1736 1848
1737 /* Upgrade special prayers to normal prayers */ 1849 /* Upgrade special prayers to normal prayers */
1738 if ((tmp=check_spell_known (op, spell->name))!=NULL) { 1850 if ((tmp = check_spell_known (op, spell->name)) != NULL)
1851 {
1739 if (special_prayer && !QUERY_FLAG(tmp, FLAG_STARTEQUIP)) { 1852 if (special_prayer && !QUERY_FLAG (tmp, FLAG_STARTEQUIP))
1853 {
1740 LOG (llevError, "BUG: do_learn_spell(): spell already known, but not marked as startequip\n"); 1854 LOG (llevError, "BUG: do_learn_spell(): spell already known, but not marked as startequip\n");
1741 return; 1855 return;
1742 } 1856 }
1743 return; 1857 return;
1744 } 1858 }
1745 1859
1746 play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0); 1860 play_sound_player_only (op->contr, SOUND_LEARN_SPELL, 0, 0);
1747 tmp = get_object(); 1861 tmp = spell->clone ();
1748 copy_object(spell, tmp);
1749 insert_ob_in_ob(tmp, op); 1862 insert_ob_in_ob (tmp, op);
1750 1863
1751 if (special_prayer) { 1864 if (special_prayer)
1752 SET_FLAG(tmp, FLAG_STARTEQUIP); 1865 SET_FLAG (tmp, FLAG_STARTEQUIP);
1753 }
1754 1866
1755 esrv_add_spells(op->contr, tmp); 1867 esrv_add_spells (op->contr, tmp);
1756} 1868}
1757 1869
1758/** 1870/**
1759 * Erases spell from player's inventory. 1871 * Erases spell from player's inventory.
1760 */ 1872 */
1873void
1761void do_forget_spell (object *op, const char *spell) 1874do_forget_spell (object *op, const char *spell)
1762{ 1875{
1763 object *spob; 1876 object *spob;
1764 1877
1765 if (op->type != PLAYER) { 1878 if (op->type != PLAYER)
1879 {
1766 LOG (llevError, "BUG: do_forget_spell(): not a player\n"); 1880 LOG (llevError, "BUG: do_forget_spell(): not a player\n");
1767 return; 1881 return;
1768 } 1882 }
1769 if ( (spob=check_spell_known (op, spell)) == NULL) { 1883 if ((spob = check_spell_known (op, spell)) == NULL)
1884 {
1770 LOG (llevError, "BUG: do_forget_spell(): spell not known\n"); 1885 LOG (llevError, "BUG: do_forget_spell(): spell not known\n");
1771 return; 1886 return;
1772 }
1773 1887 }
1774 new_draw_info_format (NDI_UNIQUE|NDI_NAVY, 0, op, 1888
1775 "You lose knowledge of %s.", spell); 1889 new_draw_info_format (NDI_UNIQUE | NDI_NAVY, 0, op, "You lose knowledge of %s.", spell);
1776 player_unready_range_ob(op->contr, spob); 1890 player_unready_range_ob (op->contr, spob);
1777 esrv_remove_spell(op->contr, spob); 1891 esrv_remove_spell (op->contr, spob);
1778 remove_ob(spob); 1892 spob->destroy ();
1779 free_object(spob);
1780} 1893}
1781 1894
1782/** 1895/**
1783 * Handles player applying a spellbook. 1896 * Handles player applying a spellbook.
1784 * 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,
1785 * stuff like that. Random learning failure too. 1898 * stuff like that. Random learning failure too.
1786 */ 1899 */
1900static void
1787static void apply_spellbook (object *op, object *tmp) 1901apply_spellbook (object *op, object *tmp)
1788{ 1902{
1789 object *skop, *spell, *spell_skill; 1903 object *skop, *spell, *spell_skill;
1790 1904
1791 if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) { 1905 if (QUERY_FLAG (op, FLAG_BLIND) && !QUERY_FLAG (op, FLAG_WIZ))
1906 {
1792 new_draw_info(NDI_UNIQUE, 0,op,"You are unable to read while blind."); 1907 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to read while blind.");
1793 return; 1908 return;
1794 } 1909 }
1795 1910
1796 /* artifact_spellbooks have 'slaying' field point to a spell name, 1911 /* artifact_spellbooks have 'slaying' field point to a spell name,
1797 * instead of having their spell stored in stats.sp. These are 1912 * instead of having their spell stored in stats.sp. These are
1798 * legacy spellbooks 1913 * legacy spellbooks
1799 */ 1914 */
1800 1915
1801 if(tmp->slaying != NULL) { 1916 if (tmp->slaying != NULL)
1917 {
1802 spell=arch_to_object(find_archetype_by_object_name(tmp->slaying)); 1918 spell = arch_to_object (find_archetype_by_object_name (tmp->slaying));
1803 if (!spell) { 1919 if (!spell)
1804 new_draw_info_format(NDI_UNIQUE, 0, op, 1920 {
1805 "The book's formula for %s is incomplete", &tmp->slaying); 1921 new_draw_info_format (NDI_UNIQUE, 0, op, "The book's formula for %s is incomplete", &tmp->slaying);
1806 return; 1922 return;
1807 } 1923 }
1808 else 1924 else
1809 insert_ob_in_ob(spell, tmp); 1925 insert_ob_in_ob (spell, tmp);
1810 tmp->slaying=NULL; 1926 tmp->slaying = NULL;
1811 } 1927 }
1812 1928
1813 skop = find_skill_by_name(op, tmp->skill); 1929 skop = find_skill_by_name (op, tmp->skill);
1814 1930
1815 /* need a literacy skill to learn spells. Also, having a literacy level 1931 /* need a literacy skill to learn spells. Also, having a literacy level
1816 * lower than the spell will make learning the spell more difficult */ 1932 * lower than the spell will make learning the spell more difficult */
1817 if ( !skop) { 1933 if (!skop)
1934 {
1818 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.");
1819 return; 1936 return;
1820 } 1937 }
1821 1938
1822 spell = tmp->inv; 1939 spell = tmp->inv;
1940
1823 if (!spell) { 1941 if (!spell)
1942 {
1824 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);
1825 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.");
1826 return;
1827 }
1828 if (spell->level > (skop->level+10)) {
1829 new_draw_info(NDI_UNIQUE, 0,op,"You are unable to decipher the strange symbols.");
1830 return; 1945 return;
1831 } 1946 }
1832 1947
1833 new_draw_info_format(NDI_UNIQUE, 0, op, 1948 if (skop->level < int (sqrtf (spell->level) * 1.5f))
1834 "The spellbook contains the %s level spell %s.", 1949 {
1835 get_levelnumber(spell->level), &spell->name); 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.");
1951 return;
1952 }
1836 1953
1954 new_draw_info_format (NDI_UNIQUE, 0, op, "The spellbook contains the %s level spell %s.", get_levelnumber (spell->level), &spell->name);
1955
1837 if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)) { 1956 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1957 {
1838 identify(tmp); 1958 identify (tmp);
1959
1839 if (tmp->env) 1960 if (tmp->env)
1840 esrv_update_item(UPD_FLAGS|UPD_NAME,op,tmp); 1961 esrv_update_item (UPD_FLAGS | UPD_NAME, op, tmp);
1841 else 1962 else
1842 op->contr->socket.update_look=1; 1963 op->contr->ns->floorbox_update ();
1843 } 1964 }
1844 1965
1845 /* 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
1846 * 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
1847 * 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
1848 * they would have a special prayer mark. 1969 * they would have a special prayer mark.
1849 */ 1970 */
1850 if (check_spell_known (op, spell->name)) { 1971 if (check_spell_known (op, spell->name))
1972 {
1851 new_draw_info(NDI_UNIQUE, 0,op,"You already know that spell.\n"); 1973 new_draw_info (NDI_UNIQUE, 0, op, "You already know that spell.\n");
1852 return; 1974 return;
1853 } 1975 }
1854 1976
1855 if (spell->skill) { 1977 if (spell->skill)
1978 {
1856 spell_skill = find_skill_by_name(op, spell->skill); 1979 spell_skill = find_skill_by_name (op, spell->skill);
1980
1857 if (!spell_skill) { 1981 if (!spell_skill)
1858 new_draw_info_format(NDI_UNIQUE, 0, op, 1982 {
1859 "You lack the skill %s to use this spell", 1983 new_draw_info_format (NDI_UNIQUE, 0, op, "You lack the skill %s to use this spell", &spell->skill);
1860 &spell->skill);
1861 return; 1984 return;
1862 } 1985 }
1986
1863 if (spell_skill->level < spell->level) { 1987 if (spell_skill->level < spell->level)
1864 new_draw_info_format(NDI_UNIQUE, 0, op, 1988 {
1865 "You need to be level %d in %s to learn this spell.", 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);
1866 spell->level, &spell->skill);
1867 return; 1990 return;
1868 } 1991 }
1869 } 1992 }
1870 1993
1871 /* Logic as follows 1994 /* Logic as follows
1872 * 1995 *
1873 * 1- MU spells use Int to learn, Cleric spells use Wisdom 1996 * 1- MU spells use Int to learn, Cleric spells use Wisdom
1874 * 1997 *
1875 * 2- The learner's skill level in literacy adjusts the chance to learn 1998 * 2- The learner's skill level in literacy adjusts the chance to learn
1876 * a spell. 1999 * a spell.
1877 * 2000 *
1878 * 3 -Automatically fail to learn if you read while confused 2001 * 3 -Automatically fail to learn if you read while confused
1879 * 2002 *
1880 * Overall, chances are the same but a player will find having a high 2003 * Overall, chances are the same but a player will find having a high
1881 * literacy rate very useful! -b.t. 2004 * literacy rate very useful! -b.t.
1882 */ 2005 */
1883 if(QUERY_FLAG(op,FLAG_CONFUSED)) { 2006 if (QUERY_FLAG (op, FLAG_CONFUSED))
2007 {
1884 new_draw_info(NDI_UNIQUE,0,op,"In your confused state you flub the wording of the text!"); 2008 new_draw_info (NDI_UNIQUE, 0, op, "In your confused state you flub the wording of the text!");
1885 scroll_failure(op, 0 - random_roll(0, spell->level, op, PREFER_LOW), MAX(spell->stats.sp, spell->stats.grace)); 2009 scroll_failure (op, 0 - random_roll (0, spell->level, op, PREFER_LOW), MAX (spell->stats.sp, spell->stats.grace));
2010 }
1886 } else if(QUERY_FLAG(tmp,FLAG_STARTEQUIP) || 2011 else if (QUERY_FLAG (tmp, FLAG_STARTEQUIP) ||
1887 (random_roll(0, 100, op, PREFER_LOW)-(5*skop->level)) < 2012 (random_roll (0, 100, op, PREFER_LOW) - (5 * skop->level)) < learn_spell[spell->stats.grace ? op->stats.Wis : op->stats.Int])
1888 learn_spell[spell->stats.grace ? op->stats.Wis : op->stats.Int]) { 2013 {
1889 2014
1890 new_draw_info(NDI_UNIQUE, 0,op,"You succeed in learning the spell!"); 2015 new_draw_info (NDI_UNIQUE, 0, op, "You succeed in learning the spell!");
1891 do_learn_spell (op, spell, 0); 2016 do_learn_spell (op, spell, 0);
1892 2017
1893 /* xp gain to literacy for spell learning */ 2018 /* xp gain to literacy for spell learning */
1894 if ( ! QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 2019 if (!QUERY_FLAG (tmp, FLAG_STARTEQUIP))
1895 change_exp(op,calc_skill_exp(op,tmp,skop), skop->skill, 0); 2020 change_exp (op, calc_skill_exp (op, tmp, skop), skop->skill, 0);
1896 } else { 2021 }
2022 else
2023 {
1897 play_sound_player_only(op->contr, SOUND_FUMBLE_SPELL,0,0); 2024 play_sound_player_only (op->contr, SOUND_FUMBLE_SPELL, 0, 0);
1898 new_draw_info(NDI_UNIQUE, 0,op,"You fail to learn the spell.\n"); 2025 new_draw_info (NDI_UNIQUE, 0, op, "You fail to learn the spell.\n");
1899 } 2026 }
1900 decrease_ob(tmp); 2027 decrease_ob (tmp);
1901} 2028}
1902 2029
1903/** 2030/**
1904 * Handles applying a spell scroll. 2031 * Handles applying a spell scroll.
1905 */ 2032 */
2033void
1906void apply_scroll (object *op, object *tmp, int dir) 2034apply_scroll (object *op, object *tmp, int dir)
1907{ 2035{
1908 object *skop; 2036 object *skop;
1909 2037
1910 if(QUERY_FLAG(op, FLAG_BLIND)&&!QUERY_FLAG(op,FLAG_WIZ)) { 2038 if (QUERY_FLAG (op, FLAG_BLIND) && !QUERY_FLAG (op, FLAG_WIZ))
2039 {
1911 new_draw_info(NDI_UNIQUE, 0,op, "You are unable to read while blind."); 2040 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to read while blind.");
1912 return; 2041 return;
1913 } 2042 }
1914 2043
1915 if (!tmp->inv || tmp->inv->type != SPELL) { 2044 if (!tmp->inv || tmp->inv->type != SPELL)
1916 new_draw_info (NDI_UNIQUE, 0, op, 2045 {
1917 "The scroll just doesn't make sense!"); 2046 new_draw_info (NDI_UNIQUE, 0, op, "The scroll just doesn't make sense!");
1918 return; 2047 return;
1919 } 2048 }
1920 2049
1921 if(op->type==PLAYER) { 2050 if (op->type == PLAYER)
2051 {
1922 /* players need a literacy skill to read stuff! */ 2052 /* players need a literacy skill to read stuff! */
1923 int exp_gain=0; 2053 int exp_gain = 0;
1924 2054
1925 /* hard code literacy - tmp->skill points to where the exp 2055 /* hard code literacy - tmp->skill points to where the exp
1926 * should go for anything killed by the spell. 2056 * should go for anything killed by the spell.
1927 */ 2057 */
1928 skop = find_skill_by_name(op, skill_names[SK_LITERACY]); 2058 skop = find_skill_by_name (op, skill_names[SK_LITERACY]);
1929 2059
1930 if ( ! skop) { 2060 if (!skop)
1931 new_draw_info(NDI_UNIQUE, 0,op, 2061 {
1932 "You are unable to decipher the strange symbols."); 2062 new_draw_info (NDI_UNIQUE, 0, op, "You are unable to decipher the strange symbols.");
1933 return; 2063 return;
1934 } 2064 }
1935 2065
1936 if((exp_gain = calc_skill_exp(op,tmp, skop))) 2066 if ((exp_gain = calc_skill_exp (op, tmp, skop)))
1937 change_exp(op,exp_gain, skop->skill, 0); 2067 change_exp (op, exp_gain, skop->skill, 0);
1938 } 2068 }
1939 2069
1940 if (!QUERY_FLAG(tmp, FLAG_IDENTIFIED)) 2070 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED))
1941 identify(tmp); 2071 identify (tmp);
1942 2072
1943 new_draw_info_format(NDI_BLACK, 0, op, 2073 new_draw_info_format (NDI_BLACK, 0, op, "The scroll of %s turns to dust.", &tmp->inv->name);
1944 "The scroll of %s turns to dust.", &tmp->inv->name);
1945 2074
1946 2075
1947 cast_spell(op,tmp,dir,tmp->inv, NULL); 2076 cast_spell (op, tmp, dir, tmp->inv, NULL);
1948 decrease_ob(tmp); 2077 decrease_ob (tmp);
1949} 2078}
1950 2079
1951/** 2080/**
1952 * Applies a treasure object - by default, chest. op 2081 * Applies a treasure object - by default, chest. op
1953 * is the person doing the applying, tmp is the treasure 2082 * is the person doing the applying, tmp is the treasure
1954 * chest. 2083 * chest.
1955 */ 2084 */
2085static void
1956static void apply_treasure (object *op, object *tmp) 2086apply_treasure (object *op, object *tmp)
1957{ 2087{
1958 object *treas; 2088 object *treas;
1959 tag_t tmp_tag = tmp->count, op_tag = op->count;
1960 2089
1961 2090
1962 /* 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
1963 * 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
1964 * 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
1965 * prevents people fromt moving chests to more difficult maps to get better 2094 * prevents people fromt moving chests to more difficult maps to get better
1966 * treasure 2095 * treasure
1967 */ 2096 */
1968 2097
1969 treas = tmp->inv; 2098 treas = tmp->inv;
1970 if(treas==NULL) { 2099 if (treas == NULL)
2100 {
1971 new_draw_info(NDI_UNIQUE, 0,op,"The chest was empty."); 2101 new_draw_info (NDI_UNIQUE, 0, op, "The chest was empty.");
1972 decrease_ob(tmp);
1973 return;
1974 }
1975 while (tmp->inv) {
1976 treas = tmp->inv;
1977
1978 remove_ob(treas);
1979 new_draw_info_format(NDI_UNIQUE, 0, op, "You find %s in the chest.",
1980 query_name(treas));
1981
1982 treas->x=op->x;
1983 treas->y=op->y;
1984 treas = insert_ob_in_map (treas, op->map, op,INS_BELOW_ORIGINATOR);
1985
1986 if (treas && (treas->type == RUNE || treas->type == TRAP) && treas->level
1987 && QUERY_FLAG (op, FLAG_ALIVE))
1988 spring_trap (treas, op);
1989 /* If either player or container was destroyed, no need to do
1990 * further processing. I think this should be enclused with
1991 * spring trap above, as I don't think there is otherwise
1992 * any way for the treasure chest or player to get killed
1993 */
1994 if (was_destroyed (op, op_tag) || was_destroyed (tmp, tmp_tag))
1995 break;
1996 }
1997
1998 if ( ! was_destroyed (tmp, tmp_tag) && tmp->inv == NULL)
1999 decrease_ob (tmp); 2102 decrease_ob (tmp);
2103 return;
2104 }
2105 while (tmp->inv)
2106 {
2107 treas = tmp->inv;
2108
2109 treas->remove ();
2110 new_draw_info_format (NDI_UNIQUE, 0, op, "You find %s in the chest.", query_name (treas));
2111
2112 treas->x = op->x;
2113 treas->y = op->y;
2114 treas = insert_ob_in_map (treas, op->map, op, INS_BELOW_ORIGINATOR);
2115
2116 if (treas && (treas->type == RUNE || treas->type == TRAP) && treas->level && QUERY_FLAG (op, FLAG_ALIVE))
2117 spring_trap (treas, op);
2118
2119 /* If either player or container was destroyed, no need to do
2120 * further processing. I think this should be enclused with
2121 * spring trap above, as I don't think there is otherwise
2122 * any way for the treasure chest or player to get killed
2123 */
2124 if (op->destroyed () || tmp->destroyed ())
2125 break;
2126 }
2127
2128 if (!tmp->destroyed () && tmp->inv == NULL)
2129 decrease_ob (tmp);
2000 2130
2001} 2131}
2002 2132
2003/** 2133/**
2004 * op eats food. 2134 * op eats food.
2005 * If player, takes care of messages and dragon special food. 2135 * If player, takes care of messages and dragon special food.
2006 */ 2136 */
2137static void
2007static void apply_food (object *op, object *tmp) 2138apply_food (object *op, object *tmp)
2008{ 2139{
2009 int capacity_remaining; 2140 int capacity_remaining;
2010 2141
2011 if(op->type!=PLAYER) 2142 if (op->type != PLAYER)
2012 op->stats.hp=op->stats.maxhp; 2143 op->stats.hp = op->stats.maxhp;
2013 else { 2144 else
2145 {
2014 /* check if this is a dragon (player), eating some flesh */ 2146 /* check if this is a dragon (player), eating some flesh */
2015 if (tmp->type==FLESH && is_dragon_pl(op) && dragon_eat_flesh(op, tmp)) 2147 if (tmp->type == FLESH && is_dragon_pl (op) && dragon_eat_flesh (op, tmp))
2016 ; 2148 ;
2017 else { 2149 else
2150 {
2018 /* usual case - no dragon meal: */ 2151 /* usual case - no dragon meal: */
2019 if(op->stats.food+tmp->stats.food>999) { 2152 if (op->stats.food + tmp->stats.food > 999)
2153 {
2020 if(tmp->type==FOOD || tmp->type==FLESH) 2154 if (tmp->type == FOOD || tmp->type == FLESH)
2021 new_draw_info(NDI_UNIQUE, 0,op,"You feel full, but what a waste of food!"); 2155 new_draw_info (NDI_UNIQUE, 0, op, "You feel full, but what a waste of food!");
2022 else 2156 else
2023 new_draw_info(NDI_UNIQUE, 0,op,"Most of the drink goes down your face not your throat!"); 2157 new_draw_info (NDI_UNIQUE, 0, op, "Most of the drink goes down your face not your throat!");
2024 } 2158 }
2025 2159
2026 if(!QUERY_FLAG(tmp, FLAG_CURSED)) { 2160 if (!QUERY_FLAG (tmp, FLAG_CURSED))
2161 {
2027 char buf[MAX_BUF]; 2162 char buf[MAX_BUF];
2028 2163
2029 if (!is_dragon_pl(op)) { 2164 if (!is_dragon_pl (op))
2165 {
2030 /* eating message for normal players*/ 2166 /* eating message for normal players */
2031 if(tmp->type==DRINK) 2167 if (tmp->type == DRINK)
2032 sprintf(buf,"Ahhh...that %s tasted good.",&tmp->name); 2168 sprintf (buf, "Ahhh...that %s tasted good.", &tmp->name);
2169 else
2170 sprintf (buf, "The %s tasted %s", &tmp->name, tmp->type == FLESH ? "terrible!" : "good.");
2171 }
2033 else 2172 else
2034 sprintf(buf,"The %s tasted %s",&tmp->name, 2173 {
2035 tmp->type==FLESH?"terrible!":"good.");
2036 }
2037 else {
2038 /* eating message for dragon players*/ 2174 /* eating message for dragon players */
2039 sprintf(buf,"The %s tasted terrible!",&tmp->name); 2175 sprintf (buf, "The %s tasted terrible!", &tmp->name);
2040 } 2176 }
2041 2177
2042 new_draw_info(NDI_UNIQUE, 0,op,buf); 2178 new_draw_info (NDI_UNIQUE, 0, op, buf);
2043 capacity_remaining = 999 - op->stats.food; 2179 capacity_remaining = 999 - op->stats.food;
2044 op->stats.food+=tmp->stats.food; 2180 op->stats.food += tmp->stats.food;
2045 if(capacity_remaining < tmp->stats.food) 2181 if (capacity_remaining < tmp->stats.food)
2046 op->stats.hp += capacity_remaining / 50; 2182 op->stats.hp += capacity_remaining / 50;
2047 else 2183 else
2048 op->stats.hp+=tmp->stats.food/50; 2184 op->stats.hp += tmp->stats.food / 50;
2049 if(op->stats.hp>op->stats.maxhp) 2185 if (op->stats.hp > op->stats.maxhp)
2050 op->stats.hp=op->stats.maxhp; 2186 op->stats.hp = op->stats.maxhp;
2051 if (op->stats.food > 999) 2187 if (op->stats.food > 999)
2052 op->stats.food = 999; 2188 op->stats.food = 999;
2053 } 2189 }
2054 2190
2055 /* special food hack -b.t. */ 2191 /* special food hack -b.t. */
2056 if(tmp->title || QUERY_FLAG(tmp,FLAG_CURSED)) 2192 if (tmp->title || QUERY_FLAG (tmp, FLAG_CURSED))
2057 eat_special_food(op,tmp); 2193 eat_special_food (op, tmp);
2058 } 2194 }
2059 } 2195 }
2060 handle_apply_yield(tmp); 2196 handle_apply_yield (tmp);
2061 decrease_ob(tmp); 2197 decrease_ob (tmp);
2062} 2198}
2063 2199
2064/** 2200/**
2065 * A dragon is eating some flesh. If the flesh contains resistances, 2201 * A dragon is eating some flesh. If the flesh contains resistances,
2066 * there is a chance for the dragon's skin to get improved. 2202 * there is a chance for the dragon's skin to get improved.
2069 * object *op the object (dragon player) eating the flesh 2205 * object *op the object (dragon player) eating the flesh
2070 * object *meal the flesh item, getting chewed in dragon's mouth 2206 * object *meal the flesh item, getting chewed in dragon's mouth
2071 * return: 2207 * return:
2072 * int 1 if eating successful, 0 if it doesn't work 2208 * int 1 if eating successful, 0 if it doesn't work
2073 */ 2209 */
2210int
2074int dragon_eat_flesh(object *op, object *meal) { 2211dragon_eat_flesh (object *op, object *meal)
2212{
2075 object *skin = NULL; /* pointer to dragon skin force*/ 2213 object *skin = NULL; /* pointer to dragon skin force */
2076 object *abil = NULL; /* pointer to dragon ability force*/ 2214 object *abil = NULL; /* pointer to dragon ability force */
2077 object *tmp = NULL; /* tmp. object */ 2215 object *tmp = NULL; /* tmp. object */
2078 2216
2079 char buf[MAX_BUF]; /* tmp. string buffer */ 2217 char buf[MAX_BUF]; /* tmp. string buffer */
2080 double chance; /* improvement-chance of one resistance type */ 2218 double chance; /* improvement-chance of one resistance type */
2081 double totalchance=1; /* total chance of gaining one resistance */ 2219 double totalchance = 1; /* total chance of gaining one resistance */
2082 double bonus=0; /* level bonus (improvement is easier at lowlevel) */ 2220 double bonus = 0; /* level bonus (improvement is easier at lowlevel) */
2083 double mbonus=0; /* monster bonus */ 2221 double mbonus = 0; /* monster bonus */
2084 int atnr_winner[NROFATTACKS]; /* winning candidates for resistance improvement */ 2222 int atnr_winner[NROFATTACKS]; /* winning candidates for resistance improvement */
2085 int winners=0; /* number of winners */ 2223 int winners = 0; /* number of winners */
2086 int i; /* index */ 2224 int i; /* index */
2087 2225
2088 /* let's make sure and doublecheck the parameters */ 2226 /* let's make sure and doublecheck the parameters */
2089 if (meal->type!=FLESH || !is_dragon_pl(op)) 2227 if (meal->type != FLESH || !is_dragon_pl (op))
2090 return 0; 2228 return 0;
2091 2229
2092 /* now grab the 'dragon_skin'- and 'dragon_ability'-forces 2230 /* now grab the 'dragon_skin'- and 'dragon_ability'-forces
2093 from the player's inventory */ 2231 from the player's inventory */
2094 for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { 2232 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
2233 {
2095 if (tmp->type == FORCE) { 2234 if (tmp->type == FORCE)
2235 {
2096 if (strcmp(tmp->arch->name, "dragon_skin_force")==0) 2236 if (strcmp (tmp->arch->name, "dragon_skin_force") == 0)
2097 skin = tmp; 2237 skin = tmp;
2098 else if (strcmp(tmp->arch->name, "dragon_ability_force")==0) 2238 else if (strcmp (tmp->arch->name, "dragon_ability_force") == 0)
2099 abil = tmp; 2239 abil = tmp;
2100 } 2240 }
2101 } 2241 }
2102 2242
2103 /* if either skin or ability are missing, this is an old player 2243 /* if either skin or ability are missing, this is an old player
2104 which is not to be considered a dragon -> bail out */ 2244 which is not to be considered a dragon -> bail out */
2105 if (skin == NULL || abil == NULL) return 0; 2245 if (skin == NULL || abil == NULL)
2106 2246 return 0;
2247
2107 /* now start by filling stomache and health, according to food-value */ 2248 /* now start by filling stomache and health, according to food-value */
2108 if((999 - op->stats.food) < meal->stats.food) 2249 if ((999 - op->stats.food) < meal->stats.food)
2109 op->stats.hp += (999 - op->stats.food) / 50; 2250 op->stats.hp += (999 - op->stats.food) / 50;
2110 else 2251 else
2111 op->stats.hp += meal->stats.food/50; 2252 op->stats.hp += meal->stats.food / 50;
2112 if(op->stats.hp>op->stats.maxhp) 2253 if (op->stats.hp > op->stats.maxhp)
2113 op->stats.hp=op->stats.maxhp; 2254 op->stats.hp = op->stats.maxhp;
2114 2255
2115 op->stats.food = MIN(999, op->stats.food + meal->stats.food); 2256 op->stats.food = MIN (999, op->stats.food + meal->stats.food);
2116 2257
2117 /*LOG(llevDebug, "-> player: %d, flesh: %d\n", op->level, meal->level);*/ 2258 /*LOG(llevDebug, "-> player: %d, flesh: %d\n", op->level, meal->level); */
2118 2259
2119 /* on to the interesting part: chances for adding resistance */ 2260 /* on to the interesting part: chances for adding resistance */
2120 for (i=0; i<NROFATTACKS; i++) { 2261 for (i = 0; i < NROFATTACKS; i++)
2262 {
2121 if (meal->resist[i] > 0 && atnr_is_dragon_enabled(i)) { 2263 if (meal->resist[i] > 0 && atnr_is_dragon_enabled (i))
2264 {
2122 /* got positive resistance, now calculate improvement chance (0-100) */ 2265 /* got positive resistance, now calculate improvement chance (0-100) */
2123 2266
2124 /* this bonus makes resistance increase easier at lower levels */ 2267 /* this bonus makes resistance increase easier at lower levels */
2125 bonus = (settings.max_level - op->level) * 30. / ((double)settings.max_level); 2268 bonus = (settings.max_level - op->level) * 30. / ((double) settings.max_level);
2126 if (i == abil->stats.exp) 2269 if (i == abil->stats.exp)
2127 bonus += 5; /* additional bonus for resistance of ability-focus */ 2270 bonus += 5; /* additional bonus for resistance of ability-focus */
2128 2271
2129 /* monster bonus increases with level, because high-level 2272 /* monster bonus increases with level, because high-level
2130 flesh is too rare */ 2273 flesh is too rare */
2131 mbonus = op->level * 20. / ((double)settings.max_level); 2274 mbonus = op->level * 20. / ((double) settings.max_level);
2132 2275
2133 chance = (((double)MIN(op->level+bonus, meal->level+bonus+mbonus))*100. / 2276 chance = (((double) MIN (op->level + bonus, meal->level + bonus + mbonus)) * 100. /
2134 ((double)settings.max_level)) - skin->resist[i]; 2277 ((double) settings.max_level)) - skin->resist[i];
2135 2278
2136 if (chance >= 0.) 2279 if (chance >= 0.)
2137 chance += 1.; 2280 chance += 1.;
2138 else 2281 else
2139 chance = (chance < -12) ? 0. : 1./pow(2., -chance); 2282 chance = (chance < -12) ? 0. : 1. / pow (2., -chance);
2140 2283
2141 /* chance is proportional to amount of resistance (max. 50) */ 2284 /* chance is proportional to amount of resistance (max. 50) */
2142 chance *= ((double)(MIN(meal->resist[i], 50)))/50.; 2285 chance *= ((double) (MIN (meal->resist[i], 50))) / 50.;
2143 2286
2144 /* doubled chance for resistance of ability-focus */ 2287 /* doubled chance for resistance of ability-focus */
2145 if (i == abil->stats.exp) 2288 if (i == abil->stats.exp)
2146 chance = MIN(100., chance*2.); 2289 chance = MIN (100., chance * 2.);
2147 2290
2148 /* now make the throw and save all winners (Don't insert luck bonus here!) */ 2291 /* now make the throw and save all winners (Don't insert luck bonus here!) */
2149 if (RANDOM()%10000 < (int)(chance*100)) { 2292 if (RANDOM () % 10000 < (int) (chance * 100))
2293 {
2150 atnr_winner[winners] = i; 2294 atnr_winner[winners] = i;
2151 winners++; 2295 winners++;
2152 } 2296 }
2153 2297
2154 if (chance >= 0.01 ) totalchance *= 1 - chance/100; 2298 if (chance >= 0.01)
2155 2299 totalchance *= 1 - chance / 100;
2300
2156 /*LOG(llevDebug, " %s: bonus %.1f, chance %.1f\n", attacks[i], bonus, chance);*/ 2301 /*LOG(llevDebug, " %s: bonus %.1f, chance %.1f\n", attacks[i], bonus, chance); */
2157 } 2302 }
2158 } 2303 }
2159 2304
2160 /* inverse totalchance as until now we have the failure-chance */ 2305 /* inverse totalchance as until now we have the failure-chance */
2161 totalchance = 100 - totalchance*100; 2306 totalchance = 100 - totalchance * 100;
2162 /* print message according to totalchance */ 2307 /* print message according to totalchance */
2163 if (totalchance > 50.) 2308 if (totalchance > 50.)
2164 sprintf(buf, "Hmm! The %s tasted delicious!", &meal->name); 2309 sprintf (buf, "Hmm! The %s tasted delicious!", &meal->name);
2165 else if (totalchance > 10.) 2310 else if (totalchance > 10.)
2166 sprintf(buf, "The %s tasted very good.", &meal->name); 2311 sprintf (buf, "The %s tasted very good.", &meal->name);
2167 else if (totalchance > 1.) 2312 else if (totalchance > 1.)
2168 sprintf(buf, "The %s tasted good.", &meal->name); 2313 sprintf (buf, "The %s tasted good.", &meal->name);
2169 else if (totalchance > 0.1) 2314 else if (totalchance > 0.1)
2170 sprintf(buf, "The %s tasted bland.", &meal->name); 2315 sprintf (buf, "The %s tasted bland.", &meal->name);
2171 else if (totalchance >= 0.01) 2316 else if (totalchance >= 0.01)
2172 sprintf(buf, "The %s had a boring taste.", &meal->name); 2317 sprintf (buf, "The %s had a boring taste.", &meal->name);
2173 else if (meal->last_eat > 0 && atnr_is_dragon_enabled(meal->last_eat)) 2318 else if (meal->last_eat > 0 && atnr_is_dragon_enabled (meal->last_eat))
2174 sprintf(buf, "The %s tasted strange.", &meal->name); 2319 sprintf (buf, "The %s tasted strange.", &meal->name);
2175 else 2320 else
2176 sprintf(buf, "The %s had no taste.", &meal->name); 2321 sprintf (buf, "The %s had no taste.", &meal->name);
2177 new_draw_info(NDI_UNIQUE, 0, op, buf); 2322 new_draw_info (NDI_UNIQUE, 0, op, buf);
2178 2323
2179 /* now choose a winner if we have any */ 2324 /* now choose a winner if we have any */
2180 i = -1; 2325 i = -1;
2181 if (winners>0) 2326 if (winners > 0)
2182 i = atnr_winner[RANDOM()%winners]; 2327 i = atnr_winner[RANDOM () % winners];
2183 2328
2184 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95) { 2329 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95)
2330 {
2185 /* resistance increased! */ 2331 /* resistance increased! */
2186 skin->resist[i]++; 2332 skin->resist[i]++;
2187 fix_player(op); 2333 op->update_stats ();
2188 2334
2189 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]);
2190 new_draw_info(NDI_UNIQUE|NDI_RED, 0, op, buf); 2336 new_draw_info (NDI_UNIQUE | NDI_RED, 0, op, buf);
2191 } 2337 }
2192 2338
2193 /* if this flesh contains a new ability focus, we mark it 2339 /* if this flesh contains a new ability focus, we mark it
2194 into the ability_force and it will take effect on next level */ 2340 into the ability_force and it will take effect on next level */
2195 if (meal->last_eat > 0 && atnr_is_dragon_enabled(meal->last_eat) 2341 if (meal->last_eat > 0 && atnr_is_dragon_enabled (meal->last_eat) && meal->last_eat != abil->last_eat)
2196 && meal->last_eat != abil->last_eat) { 2342 {
2197 abil->last_eat = meal->last_eat; /* write: last_eat <new attnr focus> */ 2343 abil->last_eat = meal->last_eat; /* write: last_eat <new attnr focus> */
2198 2344
2199 if (meal->last_eat != abil->stats.exp) { 2345 if (meal->last_eat != abil->stats.exp)
2346 {
2200 sprintf(buf, "Your metabolism prepares to focus on %s!", 2347 sprintf (buf, "Your metabolism prepares to focus on %s!", change_resist_msg[meal->last_eat]);
2201 change_resist_msg[meal->last_eat]);
2202 new_draw_info(NDI_UNIQUE, 0, op, buf); 2348 new_draw_info (NDI_UNIQUE, 0, op, buf);
2203 sprintf(buf, "The change will happen at level %d", abil->level + 1); 2349 sprintf (buf, "The change will happen at level %d", abil->level + 1);
2204 new_draw_info(NDI_UNIQUE, 0, op, buf); 2350 new_draw_info (NDI_UNIQUE, 0, op, buf);
2205 } 2351 }
2206 else { 2352 else
2353 {
2207 sprintf(buf, "Your metabolism will continue to focus on %s.", 2354 sprintf (buf, "Your metabolism will continue to focus on %s.", change_resist_msg[meal->last_eat]);
2208 change_resist_msg[meal->last_eat]);
2209 new_draw_info(NDI_UNIQUE, 0, op, buf); 2355 new_draw_info (NDI_UNIQUE, 0, op, buf);
2210 abil->last_eat = 0; 2356 abil->last_eat = 0;
2211 } 2357 }
2212 } 2358 }
2213 return 1; 2359 return 1;
2214}
2215
2216static void apply_savebed (object *pl)
2217{
2218#ifndef COZY_SERVER
2219 if(!pl->contr->name_changed||!pl->stats.exp) {
2220 new_draw_info(NDI_UNIQUE, 0,pl,"You don't deserve to save your character yet.");
2221 return;
2222 }
2223#endif
2224 INVOKE_PLAYER (LOGOUT, pl->contr);
2225 /* Need to call terminate_all_pets() before we remove the player ob */
2226 terminate_all_pets(pl);
2227 remove_ob(pl);
2228 pl->direction=0;
2229 new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, 5, pl,
2230 "%s leaves the game.", &pl->name);
2231
2232 /* update respawn position */
2233 strcpy(pl->contr->savebed_map, pl->map->path);
2234 pl->contr->bed_x = pl->x;
2235 pl->contr->bed_y = pl->y;
2236
2237 strcpy(pl->contr->killer,"left");
2238 check_score(pl); /* Always check score */
2239 (void)save_player(pl,0);
2240 pl->map->players--;
2241#if MAP_MAXTIMEOUT
2242 MAP_SWAP_TIME(pl->map) = MAP_TIMEOUT(pl->map);
2243#endif
2244 play_again(pl);
2245 pl->speed = 0;
2246 update_ob_speed(pl);
2247} 2360}
2248 2361
2249/** 2362/**
2250 * Handles applying an improve armor scroll. 2363 * Handles applying an improve armor scroll.
2251 * Does some sanity checks, then calls improve_armour. 2364 * Does some sanity checks, then calls improve_armour.
2252 */ 2365 */
2366static void
2253static void apply_armour_improver (object *op, object *tmp) 2367apply_armour_improver (object *op, object *tmp)
2254{ 2368{
2255 object *armor; 2369 object *armor;
2256 2370
2257 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))
2372 {
2258 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.");
2259 return;
2260 }
2261 armor=find_marked_object(op);
2262 if ( ! armor) {
2263 new_draw_info(NDI_UNIQUE, 0, op, "You need to mark an armor object.");
2264 return; 2374 return;
2265 } 2375 }
2376
2377 armor = find_marked_object (op);
2378
2379 if (!armor)
2380 {
2381 new_draw_info (NDI_UNIQUE, 0, op, "You need to mark an armor object.");
2382 return;
2383 }
2384
2266 if (armor->type != ARMOUR 2385 if (armor->type != ARMOUR
2267 && armor->type != CLOAK 2386 && armor->type != CLOAK
2268 && armor->type != BOOTS && armor->type != GLOVES 2387 && armor->type != BOOTS && armor->type != GLOVES && armor->type != BRACERS && armor->type != SHIELD && armor->type != HELMET)
2269 && armor->type != BRACERS && armor->type != SHIELD
2270 && armor->type != HELMET)
2271 { 2388 {
2272 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");
2273 return; 2390 return;
2274 } 2391 }
2275 2392
2276 new_draw_info(NDI_UNIQUE, 0,op,"Applying armour enchantment."); 2393 new_draw_info (NDI_UNIQUE, 0, op, "Applying armour enchantment.");
2277 improve_armour(op,tmp,armor); 2394 improve_armour (op, tmp, armor);
2278} 2395}
2279 2396
2280 2397extern void
2281extern void apply_poison (object *op, object *tmp) 2398apply_poison (object *op, object *tmp)
2282{ 2399{
2283 if (op->type == PLAYER) { 2400 if (op->type == PLAYER)
2401 {
2284 play_sound_player_only(op->contr, SOUND_DRINK_POISON,0,0); 2402 play_sound_player_only (op->contr, SOUND_DRINK_POISON, 0, 0);
2285 new_draw_info(NDI_UNIQUE, 0,op,"Yech! That tasted poisonous!"); 2403 new_draw_info (NDI_UNIQUE, 0, op, "Yech! That tasted poisonous!");
2286 strcpy(op->contr->killer,"poisonous booze"); 2404 strcpy (op->contr->killer, "poisonous booze");
2287 } 2405 }
2288 if (tmp->stats.hp > 0) { 2406 if (tmp->stats.hp > 0)
2407 {
2289 LOG(llevDebug,"Trying to poison player/monster for %d hp\n", 2408 LOG (llevDebug, "Trying to poison player/monster for %d hp\n", tmp->stats.hp);
2290 tmp->stats.hp);
2291 hit_player(op, tmp->stats.hp, tmp, AT_POISON, 1); 2409 hit_player (op, tmp->stats.hp, tmp, AT_POISON, 1);
2292 } 2410 }
2293 op->stats.food-=op->stats.food/4; 2411 op->stats.food -= op->stats.food / 4;
2294 handle_apply_yield(tmp); 2412 handle_apply_yield (tmp);
2295 decrease_ob(tmp); 2413 decrease_ob (tmp);
2296} 2414}
2297 2415
2298/** 2416/**
2299 * 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.
2300 * A valid 2 way exit means: 2418 * A valid 2 way exit means:
2301 * -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)
2302 * -You are 2420 * -You are
2303 * ° the owner of the exit 2421 * ° the owner of the exit
2304 * ° or in the same party as the owner 2422 * ° or in the same party as the owner
2305 * 2423 *
2306 * 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
2307 * 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
2308 * 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).
2309 */ 2427 */
2428int
2310int is_legal_2ways_exit (object* op, object *exit) 2429is_legal_2ways_exit (object *op, object *exit)
2311 { 2430{
2312 object * tmp; 2431 if (exit->stats.exp != 1)
2313 object * exit_owner; 2432 return 1; /*This is not a 2 way, so it is legal */
2314 player * pp; 2433
2315 mapstruct * exitmap; 2434#if 0 //TODO
2316 if (exit->stats.exp!=1) return 1; /*This is not a 2 way, so it is legal*/ 2435 if (!has_been_loaded (EXIT_PATH (exit)) && exit->race)
2317 if (!has_been_loaded(EXIT_PATH(exit)) && exit->race) return 0; /* This is a reset town portal */ 2436 return 0; /* This is a reset town portal */
2318 /* To know if an exit has a correspondant, we look at 2437#endif
2319 * all the exits in destination and try to find one with same path as 2438
2320 * the current exit's position */ 2439 maptile *exitmap = maptile::find_sync (EXIT_PATH (exit), exit->map);
2321 if (!strncmp(EXIT_PATH (exit), settings.localdir, strlen(settings.localdir))) 2440
2322 exitmap = ready_map_name(EXIT_PATH (exit), MAP_PLAYER_UNIQUE);
2323 else exitmap = ready_map_name(EXIT_PATH (exit), 0);
2324 if (exitmap) 2441 if (exitmap)
2325 { 2442 {
2326 tmp=get_map_ob (exitmap,EXIT_X(exit),EXIT_Y(exit)); 2443 exitmap->load_sync ();
2327 if (!tmp) return 0; 2444
2328 for ( (tmp=get_map_ob(exitmap,EXIT_X(exit),EXIT_Y(exit)));tmp;tmp=tmp->above) 2445 object *tmp = exitmap->at (EXIT_X (exit), EXIT_Y (exit)).bot;
2446
2447 if (!tmp)
2448 return 0;
2449
2450 for (; tmp; tmp = tmp->above)
2329 { 2451 {
2330 if (tmp->type!=EXIT) continue; /*Not an exit*/ 2452 if (tmp->type != EXIT)
2331 if (!EXIT_PATH (tmp)) continue; /*Not a valid exit*/ 2453 continue; /*Not an exit */
2332 if ( (EXIT_X(tmp)!=exit->x) || (EXIT_Y(tmp)!=exit->y)) continue; /*Not in the same place*/
2333 if (strcmp(exit->map->path,EXIT_PATH(tmp))!=0) continue; /*Not in the same map*/
2334 2454
2455 if (!EXIT_PATH (tmp))
2456 continue; /*Not a valid exit */
2457
2458 if ((EXIT_X (tmp) != exit->x) || (EXIT_Y (tmp) != exit->y))
2459 continue; /*Not in the same place */
2460
2461 if (strcmp (exit->map->path, EXIT_PATH (tmp)) != 0)
2462 continue; /*Not in the same map */
2463
2335 /* 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
2336 * 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
2337 * town portals to prevent strangers from visiting your appartments 2466 * town portals to prevent strangers from visiting your appartments
2338 */ 2467 */
2468 if (!exit->race)
2339 if (!exit->race) return 1; /*No owner, free for all!*/ 2469 return 1; /*No owner, free for all! */
2340 exit_owner=NULL; 2470
2341 for (pp=first_player;pp;pp=pp->next) 2471 object *exit_owner = 0;
2472
2473 for_all_players (pp)
2342 { 2474 {
2343 if (!pp->ob) continue; 2475 if (!pp->ob)
2476 continue;
2477
2344 if (pp->ob->name!=exit->race) continue; 2478 if (pp->ob->name != exit->race)
2479 continue;
2480
2345 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 */
2346 break; 2482 break;
2347 } 2483 }
2348 if (!exit_owner) return 0; /* No more owner*/ 2484
2349 if (exit_owner->contr==op->contr) return 1; /*It is your exit*/ 2485 if (!exit_owner)
2486 return 0; /* No more owner */
2487
2488 if (exit_owner->contr == op->contr)
2489 return 1; /*It is your exit */
2490
2350 if ( exit_owner && /*There is a owner*/ 2491 if (exit_owner && /*There is a owner */
2351 (op->contr) && /*A player tries to pass */ 2492 (op->contr) && /*A player tries to pass */
2352 ( (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 */
2353 (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 */
2354 return 0; 2495 return 0;
2496
2355 return 1; 2497 return 1;
2356 } 2498 }
2357 } 2499 }
2500
2358 return 0; 2501 return 0;
2359 } 2502}
2360 2503
2361 2504
2362/** 2505/**
2363 * Main apply handler. 2506 * Main apply handler.
2364 * 2507 *
2374 * 2517 *
2375 * aflag is special (always apply/unapply) flags. Nothing is done with 2518 * aflag is special (always apply/unapply) flags. Nothing is done with
2376 * them in this function - they are passed to apply_special 2519 * them in this function - they are passed to apply_special
2377 */ 2520 */
2378 2521
2522int
2379int manual_apply (object *op, object *tmp, int aflag) 2523manual_apply (object *op, object *tmp, int aflag)
2380{ 2524{
2381 if (tmp->head) tmp=tmp->head; 2525 if (tmp->head)
2526 tmp = tmp->head;
2382 2527
2383 if (QUERY_FLAG (tmp, FLAG_UNPAID) && ! QUERY_FLAG (tmp, FLAG_APPLIED)) { 2528 if (QUERY_FLAG (tmp, FLAG_UNPAID) && !QUERY_FLAG (tmp, FLAG_APPLIED))
2529 {
2384 if (op->type == PLAYER) { 2530 if (op->type == PLAYER)
2531 {
2385 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.");
2533 return 1;
2534 }
2535 else
2536 return 0; /* monsters just skip unpaid items */
2537 }
2538
2539 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op)))
2540 return RESULT_INT (0);
2541
2542 switch (tmp->type)
2543 {
2544 case CF_HANDLE:
2545 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2546 play_sound_map (op->map, op->x, op->y, SOUND_TURN_HANDLE);
2547 tmp->value = tmp->value ? 0 : 1;
2548 SET_ANIMATION (tmp, tmp->value);
2549 update_object (tmp, UP_OBJ_FACE);
2550 push_button (tmp);
2551 return 1;
2552
2553 case TRIGGER:
2554 if (check_trigger (tmp, op))
2555 {
2556 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2557 play_sound_map (tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE);
2558 }
2559 else
2560 new_draw_info (NDI_UNIQUE, 0, op, "The handle doesn't move.");
2561
2562 return 1;
2563
2564 case EXIT:
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);
2386 return 1; 2590 return 1;
2387 } else {
2388 return 0; /* monsters just skip unpaid items */
2389 } 2591 }
2390 } 2592 else
2593 {
2594 return 0;
2595 }
2391 2596
2392 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op))) 2597 case SKILLSCROLL:
2393 return RESULT_INT (0); 2598 if (op->type == PLAYER)
2394 2599 {
2395 switch (tmp->type) { 2600 apply_skillscroll (op, tmp);
2396
2397 case CF_HANDLE:
2398 new_draw_info(NDI_UNIQUE, 0,op,"You turn the handle.");
2399 play_sound_map(op->map, op->x, op->y, SOUND_TURN_HANDLE);
2400 tmp->value=tmp->value?0:1;
2401 SET_ANIMATION(tmp, tmp->value);
2402 update_object(tmp,UP_OBJ_FACE);
2403 push_button(tmp);
2404 return 1; 2601 return 1;
2405
2406 case TRIGGER:
2407 if (check_trigger (tmp, op)) {
2408 new_draw_info (NDI_UNIQUE, 0, op, "You turn the handle.");
2409 play_sound_map (tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE);
2410 } else {
2411 new_draw_info (NDI_UNIQUE, 0, op, "The handle doesn't move.");
2412 } 2602 }
2603 return 0;
2604
2605 case SPELLBOOK:
2606 if (op->type == PLAYER)
2607 {
2608 apply_spellbook (op, tmp);
2413 return 1; 2609 return 1;
2414
2415 case EXIT:
2416 if (op->type != PLAYER)
2417 return 0;
2418 if( ! EXIT_PATH (tmp) || !is_legal_2ways_exit(op,tmp)) {
2419 new_draw_info_format(NDI_UNIQUE, 0, op, "The %s is closed.",
2420 query_name(tmp));
2421 } else {
2422 /* Don't display messages for random maps. */
2423 if (tmp->msg && strncmp(EXIT_PATH(tmp),"/!",2) &&
2424 strncmp(EXIT_PATH(tmp), "/random/", 8))
2425 new_draw_info (NDI_NAVY, 0, op, tmp->msg);
2426 enter_exit(op,tmp);
2427 } 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);
2428 return 1; 2640 return 1;
2641 }
2642 else
2643 {
2644 return 0;
2645 }
2429 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:
2430 case SIGN: 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:
2431 apply_sign (op, tmp, 0); 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);
2432 return 1; 2688 return 1;
2433
2434 case BOOK:
2435 if (op->type == PLAYER) {
2436 apply_book (op, tmp);
2437 return 1;
2438 } else {
2439 return 0;
2440 } 2689 }
2690 else
2691 return 0;
2441 2692
2442 case SKILLSCROLL: 2693 case WEAPON_IMPROVER:
2694 (void) check_improve_weapon (op, tmp);
2695 return 1;
2696
2697 case CLOCK:
2443 if (op->type == PLAYER) { 2698 if (op->type == PLAYER)
2444 apply_skillscroll (op, tmp); 2699 {
2700 char buf[MAX_BUF];
2701 timeofday_t tod;
2702
2703 get_tod (&tod);
2704 sprintf (buf, "It is %d minute%s past %d o'clock %s",
2705 tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"),
2706 ((tod.hour % 14 == 0) ? 14 : ((tod.hour) % 14)), ((tod.hour >= 14) ? "pm" : "am"));
2707 play_sound_player_only (op->contr, SOUND_CLOCK, 0, 0);
2708 new_draw_info (NDI_UNIQUE, 0, op, buf);
2445 return 1; 2709 return 1;
2446 } 2710 }
2711 else
2712 {
2447 return 0; 2713 return 0;
2448
2449 case SPELLBOOK:
2450 if (op->type == PLAYER) {
2451 apply_spellbook (op, tmp);
2452 return 1;
2453 } 2714 }
2715
2716 case MENU:
2717 if (op->type == PLAYER)
2718 {
2719 shop_listing (op);
2720 return 1;
2721 }
2722 else
2723 {
2454 return 0; 2724 return 0;
2725 }
2455 2726
2456 case SCROLL: 2727 case POWER_CRYSTAL:
2728 apply_power_crystal (op, tmp); /* see egoitem.c */
2729 return 1;
2730
2731 case LIGHTER: /* for lighting torches/lanterns/etc */
2732 if (op->type == PLAYER)
2733 {
2457 apply_scroll (op, tmp, 0); 2734 apply_lighter (op, tmp);
2458 return 1; 2735 return 1;
2459
2460 case POTION:
2461 (void) apply_potion(op, tmp);
2462 return 1;
2463
2464 /* Eneq(@csd.uu.se): Handle apply on containers. */
2465 case CLOSE_CON:
2466 if (op->type==PLAYER)
2467 (void) esrv_apply_container (op, tmp->env);
2468 else
2469 (void) apply_container (op, tmp->env);
2470 return 1;
2471
2472 case CONTAINER:
2473 if (op->type==PLAYER)
2474 (void) esrv_apply_container (op, tmp);
2475 else
2476 (void) apply_container (op, tmp);
2477 return 1;
2478
2479 case TREASURE:
2480 if (op->type == PLAYER) {
2481 apply_treasure (op, tmp);
2482 return 1;
2483 } else {
2484 return 0;
2485 } 2736 }
2486
2487 case WEAPON:
2488 case ARMOUR:
2489 case BOOTS:
2490 case GLOVES:
2491 case AMULET:
2492 case GIRDLE:
2493 case BRACERS:
2494 case SHIELD:
2495 case HELMET:
2496 case RING:
2497 case CLOAK:
2498 case WAND:
2499 case ROD:
2500 case HORN:
2501 case SKILL:
2502 case BOW:
2503 case LAMP:
2504 case BUILDER:
2505 case SKILL_TOOL:
2506 if (tmp->env != op)
2507 return 2; /* not in inventory */
2508 (void) apply_special (op, tmp, aflag);
2509 return 1;
2510
2511 case DRINK:
2512 case FOOD:
2513 case FLESH:
2514 apply_food (op, tmp);
2515 return 1;
2516
2517 case POISON:
2518 apply_poison (op, tmp);
2519 return 1;
2520
2521 case SAVEBED:
2522 if (op->type == PLAYER) {
2523 apply_savebed (op);
2524 return 1;
2525 } else { 2737 else
2526 return 0;
2527 } 2738 {
2528
2529 case ARMOUR_IMPROVER:
2530 if (op->type == PLAYER) {
2531 apply_armour_improver (op, tmp);
2532 return 1;
2533 } else {
2534 return 0;
2535 }
2536
2537 case WEAPON_IMPROVER:
2538 (void) check_improve_weapon(op, tmp);
2539 return 1;
2540
2541 case CLOCK:
2542 if (op->type == PLAYER) {
2543 char buf[MAX_BUF];
2544 timeofday_t tod;
2545
2546 get_tod(&tod);
2547 sprintf(buf, "It is %d minute%s past %d o'clock %s",
2548 tod.minute+1, ((tod.minute+1 < 2) ? "" : "s"),
2549 ((tod.hour % 14 == 0) ? 14 : ((tod.hour)%14)),
2550 ((tod.hour >= 14) ? "pm" : "am"));
2551 play_sound_player_only(op->contr, SOUND_CLOCK,0,0);
2552 new_draw_info(NDI_UNIQUE, 0,op, buf);
2553 return 1;
2554 } else {
2555 return 0;
2556 }
2557
2558 case MENU:
2559 if (op->type == PLAYER) {
2560 shop_listing (op);
2561 return 1;
2562 } else {
2563 return 0;
2564 }
2565
2566 case POWER_CRYSTAL:
2567 apply_power_crystal(op,tmp); /* see egoitem.c */
2568 return 1;
2569
2570 case LIGHTER: /* for lighting torches/lanterns/etc */
2571 if (op->type == PLAYER) {
2572 apply_lighter(op,tmp);
2573 return 1;
2574 } else {
2575 return 0;
2576 }
2577
2578 case ITEM_TRANSFORMER:
2579 apply_item_transformer( op, tmp );
2580 return 1;
2581
2582 default:
2583 return 0; 2739 return 0;
2740 }
2741
2742 case ITEM_TRANSFORMER:
2743 apply_item_transformer (op, tmp);
2744 return 1;
2745
2746 default:
2747 return 0;
2584 } 2748 }
2585} 2749}
2586 2750
2587 2751
2588/* 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"
2589 * messages as needed by player_apply_below(). But there can still be 2753 * messages as needed by player_apply_below(). But there can still be
2590 * "but you are floating high above the ground" messages. 2754 * "but you are floating high above the ground" messages.
2591 * 2755 *
2592 * Same return value as apply() function. 2756 * Same return value as apply() function.
2593 */ 2757 */
2758int
2594int player_apply (object *pl, object *op, int aflag, int quiet) 2759player_apply (object *pl, object *op, int aflag, int quiet)
2595{ 2760{
2596 int tmp; 2761 int tmp;
2597 2762
2598 if (op->env == NULL && (pl->move_type & MOVE_FLYING)) { 2763 if (op->env == NULL && (pl->move_type & MOVE_FLYING))
2764 {
2599 /* player is flying and applying object not in inventory */ 2765 /* player is flying and applying object not in inventory */
2600 if ( ! QUERY_FLAG (pl, FLAG_WIZ) && !(op->move_type & MOVE_FLYING)) { 2766 if (!QUERY_FLAG (pl, FLAG_WIZ) && !(op->move_type & MOVE_FLYING))
2767 {
2601 new_draw_info (NDI_UNIQUE, 0, pl, "But you are floating high " 2768 new_draw_info (NDI_UNIQUE, 0, pl, "But you are floating high " "above the ground!");
2602 "above the ground!");
2603 return 0; 2769 return 0;
2604 } 2770 }
2605 } 2771 }
2606 2772
2607 /* Check for PLAYER to avoid a DM to disappear in a puff of smoke if 2773 /* Check for PLAYER to avoid a DM to disappear in a puff of smoke if
2608 * applied. 2774 * applied.
2609 */ 2775 */
2610 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))
2611 { 2777 {
2612 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);
2613 new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff " 2779 new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff " "of smoke!");
2614 "of smoke!");
2615 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.");
2616 remove_ob (op); 2781 op->destroy ();
2617 free_object (op);
2618 return 1; 2782 return 1;
2619 } 2783 }
2620 2784
2621 pl->contr->last_used = op; 2785 pl->contr->last_used = op;
2622 pl->contr->last_used_id = op->count;
2623 2786
2624 tmp = manual_apply (pl, op, aflag); 2787 tmp = manual_apply (pl, op, aflag);
2625 if ( ! quiet) { 2788 if (!quiet)
2789 {
2626 if (tmp == 0) 2790 if (tmp == 0)
2627 new_draw_info_format (NDI_UNIQUE, 0, pl, 2791 new_draw_info_format (NDI_UNIQUE, 0, pl, "I don't know how to apply the %s.", query_name (op));
2628 "I don't know how to apply the %s.",
2629 query_name (op));
2630 else if (tmp == 2) 2792 else if (tmp == 2)
2631 new_draw_info_format (NDI_UNIQUE, 0, pl, 2793 new_draw_info_format (NDI_UNIQUE, 0, pl, "You must get it first!\n");
2632 "You must get it first!\n");
2633 } 2794 }
2634 return tmp; 2795 return tmp;
2635} 2796}
2636 2797
2637/** 2798/**
2638 * player_apply_below attempts to apply the object 'below' the player. 2799 * player_apply_below attempts to apply the object 'below' the player.
2639 * If the player has an open container, we use that for below, otherwise 2800 * If the player has an open container, we use that for below, otherwise
2640 * we use the ground. 2801 * we use the ground.
2641 */ 2802 */
2642 2803
2804void
2643void player_apply_below (object *pl) 2805player_apply_below (object *pl)
2644{ 2806{
2645 object *tmp, *next; 2807 object *tmp, *next;
2646 int floors; 2808 int floors;
2647 2809
2648 /* If using a container, set the starting item to be the top 2810 /* If using a container, set the starting item to be the top
2649 * item in the container. Otherwise, use the map. 2811 * item in the container. Otherwise, use the map.
2650 */ 2812 */
2651 tmp = (pl->container != NULL) ? pl->container->inv : pl->below; 2813 tmp = (pl->container != NULL) ? pl->container->inv : pl->below;
2652 2814
2653 /* This is perhaps more complicated. However, I want to make sure that 2815 /* This is perhaps more complicated. However, I want to make sure that
2654 * we don't use a corrupt pointer for the next object, so we get the 2816 * we don't use a corrupt pointer for the next object, so we get the
2655 * next object in the stack before applying. This is can only be a 2817 * next object in the stack before applying. This is can only be a
2656 * problem if player_apply() has a bug in that it uses the object but does 2818 * problem if player_apply() has a bug in that it uses the object but does
2657 * not return a proper value. 2819 * not return a proper value.
2658 */ 2820 */
2659 for (floors = 0; tmp!=NULL; tmp=next) { 2821 for (floors = 0; tmp != NULL; tmp = next)
2822 {
2660 next = tmp->below; 2823 next = tmp->below;
2661 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR)) 2824 if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
2662 floors++; 2825 floors++;
2663 else if (floors > 0) 2826 else if (floors > 0)
2664 return; /* process only floor objects after first floor object */ 2827 return; /* process only floor objects after first floor object */
2665 2828
2666 /* If it is visible, player can apply it. If it is applied by 2829 /* If it is visible, player can apply it. If it is applied by
2667 * person moving on it, also activate. Added code to make it 2830 * person moving on it, also activate. Added code to make it
2668 * so that at least one of players movement types be that which 2831 * so that at least one of players movement types be that which
2669 * the item needs. 2832 * the item needs.
2670 */ 2833 */
2671 if ( ! tmp->invisible || (tmp->move_on & pl->move_type)) { 2834 if (!tmp->invisible || (tmp->move_on & pl->move_type))
2835 {
2672 if (player_apply (pl, tmp, 0, 1) == 1) 2836 if (player_apply (pl, tmp, 0, 1) == 1)
2673 return; 2837 return;
2674 } 2838 }
2675 if (floors >= 2) 2839 if (floors >= 2)
2676 return; /* process at most two floor objects */ 2840 return; /* process at most two floor objects */
2677 } 2841 }
2678} 2842}
2679 2843
2680/** 2844/**
2681 * Unapplies specified item. 2845 * Unapplies specified item.
2682 * No check done on cursed/damned. 2846 * No check done on cursed/damned.
2683 * Break this out of apply_special - this is just done 2847 * Break this out of apply_special - this is just done
2684 * to keep the size of apply_special to a more managable size. 2848 * to keep the size of apply_special to a more managable size.
2685 */ 2849 */
2850static int
2686static int unapply_special (object *who, object *op, int aflags) 2851unapply_special (object *who, object *op, int aflags)
2687{ 2852{
2688 if (INVOKE_OBJECT (BE_UNREADY, op, ARG_OBJECT (who), ARG_INT (aflags)) 2853 if (INVOKE_OBJECT (BE_UNREADY, op, ARG_OBJECT (who), ARG_INT (aflags)) || INVOKE_OBJECT (UNREADY, who, ARG_OBJECT (op), ARG_INT (aflags)))
2689 || INVOKE_OBJECT (UNREADY, who, ARG_OBJECT (op), ARG_INT (aflags)))
2690 return RESULT_INT (0); 2854 return RESULT_INT (0);
2691 2855
2692 object *tmp2; 2856 object *tmp2;
2693 2857
2694 CLEAR_FLAG(op, FLAG_APPLIED); 2858 CLEAR_FLAG (op, FLAG_APPLIED);
2695 switch(op->type) { 2859 switch (op->type)
2860 {
2696 case WEAPON: 2861 case WEAPON:
2697 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));
2698 2863
2699 (void) change_abil (who,op); 2864 (void) change_abil (who, op);
2700 if(QUERY_FLAG(who,FLAG_READY_WEAPON)) 2865 if (QUERY_FLAG (who, FLAG_READY_WEAPON))
2701 CLEAR_FLAG(who,FLAG_READY_WEAPON); 2866 CLEAR_FLAG (who, FLAG_READY_WEAPON);
2702 clear_skill(who); 2867 clear_skill (who);
2703 break; 2868 break;
2704 2869
2705 case SKILL: /* allows objects to impart skills */ 2870 case SKILL: /* allows objects to impart skills */
2706 case SKILL_TOOL: 2871 case SKILL_TOOL:
2707 if (op != who->chosen_skill) { 2872 if (op != who->chosen_skill)
2873 {
2708 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");
2875 }
2876 if (who->type == PLAYER)
2877 {
2878 if (who->contr->shoottype == range_skill)
2879 who->contr->shoottype = range_none;
2880 if (!op->invisible)
2881 {
2882 new_draw_info_format (NDI_UNIQUE, 0, who, "You stop using the %s.", query_name (op));
2883 }
2884 else
2885 {
2886 new_draw_info_format (NDI_UNIQUE, 0, who, "You can no longer use the skill: %s.", &op->skill);
2887 }
2888 }
2889 (void) change_abil (who, op);
2890 who->chosen_skill = NULL;
2891 CLEAR_FLAG (who, FLAG_READY_SKILL);
2892 break;
2893
2894 case ARMOUR:
2895 case HELMET:
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);
2944 new_draw_info_format (NDI_UNIQUE, 0, who, "You unready %s.", query_name (op));
2945 if (who->type == PLAYER)
2946 {
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;
2961 who->contr->ranges[range_builder] = NULL;
2962 break;
2963
2964 default:
2965 new_draw_info_format (NDI_UNIQUE, 0, who, "You unapply %s.", query_name (op));
2966 break;
2967 }
2968
2969 who->update_stats ();
2970
2971 if (!(aflags & AP_NO_MERGE))
2972 {
2973 object *tmp;
2974
2975 tmp = merge_ob (op, NULL);
2976 if (who->type == PLAYER)
2977 {
2978 if (tmp)
2979 { /* it was merged */
2980 esrv_del_item (who->contr, op->count);
2981 op = tmp;
2709 } 2982 }
2710 if (who->type==PLAYER) {
2711 if (who->contr->shoottype == range_skill)
2712 who->contr->shoottype = range_none;
2713 if ( ! op->invisible) {
2714 new_draw_info_format (NDI_UNIQUE, 0, who,
2715 "You stop using the %s.", query_name(op));
2716 } else {
2717 new_draw_info_format (NDI_UNIQUE, 0, who,
2718 "You can no longer use the skill: %s.",
2719 &op->skill);
2720 }
2721 }
2722 (void) change_abil (who, op);
2723 who->chosen_skill = NULL;
2724 CLEAR_FLAG (who, FLAG_READY_SKILL);
2725 break;
2726 2983
2727 case ARMOUR:
2728 case HELMET:
2729 case SHIELD:
2730 case RING:
2731 case BOOTS:
2732 case GLOVES:
2733 case AMULET:
2734 case GIRDLE:
2735 case BRACERS:
2736 case CLOAK:
2737 new_draw_info_format(NDI_UNIQUE, 0, who, "You unwear %s.",query_name(op));
2738 (void) change_abil (who,op);
2739 break;
2740 case LAMP:
2741 new_draw_info_format(NDI_UNIQUE, 0, who, "You turn off your %s.",
2742 &op->name);
2743 tmp2 = arch_to_object(op->other_arch);
2744 tmp2->x = op->x;
2745 tmp2->y = op->y;
2746 tmp2->map = op->map;
2747 tmp2->below = op->below;
2748 tmp2->above = op->above;
2749 tmp2->stats.food = op->stats.food;
2750 CLEAR_FLAG(tmp2, FLAG_APPLIED);
2751 if (QUERY_FLAG(op, FLAG_INV_LOCKED))
2752 SET_FLAG(tmp2, FLAG_INV_LOCKED);
2753 if (who->type == PLAYER)
2754 esrv_del_item(who->contr, (tag_t)op->count);
2755 remove_ob(op);
2756 free_object(op);
2757 insert_ob_in_ob(tmp2, who);
2758 fix_player(who);
2759 if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)) {
2760 if (who->type == PLAYER) {
2761 new_draw_info(NDI_UNIQUE, 0,who, "Oops, it feels deadly cold!");
2762 SET_FLAG(tmp2, FLAG_KNOWN_CURSED);
2763 }
2764 }
2765 if(who->type==PLAYER)
2766 esrv_send_item(who, tmp2);
2767 return 1; /* otherwise, an attempt to drop causes problems */
2768 break;
2769 case BOW:
2770 case WAND:
2771 case ROD:
2772 case HORN:
2773 clear_skill(who);
2774 new_draw_info_format(NDI_UNIQUE, 0, who, "You unready %s.",query_name(op));
2775 if(who->type==PLAYER) {
2776 who->contr->shoottype = range_none;
2777 } else {
2778 if (op->type == BOW)
2779 CLEAR_FLAG (who, FLAG_READY_BOW);
2780 else
2781 CLEAR_FLAG(who, FLAG_READY_RANGE);
2782 }
2783 break;
2784
2785 case BUILDER:
2786 new_draw_info_format(NDI_UNIQUE, 0, who, "You unready %s.",query_name(op));
2787 who->contr->shoottype = range_none;
2788 who->contr->ranges[ range_builder ] = NULL;
2789 break;
2790
2791 default:
2792 new_draw_info_format(NDI_UNIQUE, 0, who, "You unapply %s.",query_name(op));
2793 break;
2794 }
2795
2796 fix_player(who);
2797
2798 if ( ! (aflags & AP_NO_MERGE)) {
2799 object *tmp;
2800
2801 tag_t del_tag = op->count;
2802 tmp = merge_ob (op, NULL);
2803 if (who->type == PLAYER) {
2804 if (tmp) { /* it was merged */
2805 esrv_del_item (who->contr, del_tag);
2806 op = tmp;
2807 }
2808 esrv_send_item (who, op); 2984 esrv_send_item (who, op);
2809 } 2985 }
2810 } 2986 }
2811 return 0; 2987 return 0;
2812} 2988}
2813 2989
2814/** 2990/**
2815 * Returns the object that is using location 'loc'. 2991 * Returns the object that is using location 'loc'.
2816 * Note that 'start' is the first object to start examing - we 2992 * Note that 'start' is the first object to start examing - we
2823 * loc is the index into the array we are looking for a match. 2999 * loc is the index into the array we are looking for a match.
2824 * don't return invisible objects unless they are skill objects 3000 * don't return invisible objects unless they are skill objects
2825 * invisible other objects that use 3001 * invisible other objects that use
2826 * up body locations can be used as restrictions. 3002 * up body locations can be used as restrictions.
2827 */ 3003 */
3004object *
2828object *get_item_from_body_location(object *start, int loc) 3005get_item_from_body_location (object *start, int loc)
2829{ 3006{
2830 object *tmp; 3007 object *tmp;
2831 3008
2832 if (!start) return NULL; 3009 if (!start)
2833
2834 for (tmp=start; tmp; tmp=tmp->below)
2835 if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->body_info[loc] &&
2836 (!tmp->invisible || tmp->type==SKILL)) return tmp;
2837
2838 return NULL; 3010 return NULL;
3011
3012 for (tmp = start; tmp; tmp = tmp->below)
3013 if (QUERY_FLAG (tmp, FLAG_APPLIED) && tmp->body_info[loc] && (!tmp->invisible || tmp->type == SKILL))
3014 return tmp;
3015
3016 return NULL;
2839} 3017}
2840 3018
2841 3019
2842 3020
2843/** 3021/**
2849 * Returns 0 on success, returns 1 if there is some problem. 3027 * Returns 0 on success, returns 1 if there is some problem.
2850 * if aflags is AP_PRINT, we instead print out waht to unapply 3028 * if aflags is AP_PRINT, we instead print out waht to unapply
2851 * instead of doing it. This is a lot less code than having 3029 * instead of doing it. This is a lot less code than having
2852 * another function that does just that. 3030 * another function that does just that.
2853 */ 3031 */
3032int
2854int unapply_for_ob(object *who, object *op, int aflags) 3033unapply_for_ob (object *who, object *op, int aflags)
2855{ 3034{
2856 int i; 3035 int i;
2857 object *tmp=NULL, *last; 3036 object *tmp = NULL, *last;
2858 3037
2859 /* If we are applying a shield or weapon, unapply any equipped shield 3038 /* If we are applying a shield or weapon, unapply any equipped shield
2860 * or weapons first - only allowed to use one weapon/shield at a time. 3039 * or weapons first - only allowed to use one weapon/shield at a time.
2861 */ 3040 */
2862 if (op->type == WEAPON || op->type == SHIELD) { 3041 if (op->type == WEAPON || op->type == SHIELD)
3042 {
2863 for (tmp=who->inv; tmp; tmp=tmp->below) { 3043 for (tmp = who->inv; tmp; tmp = tmp->below)
3044 {
2864 if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == op->type) { 3045 if (QUERY_FLAG (tmp, FLAG_APPLIED) && tmp->type == op->type)
2865 if ((aflags & AP_IGNORE_CURSE) || (aflags & AP_PRINT) || 3046 {
2866 (!QUERY_FLAG(tmp, FLAG_CURSED) && !QUERY_FLAG(tmp, FLAG_DAMNED))) { 3047 if ((aflags & AP_IGNORE_CURSE) || (aflags & AP_PRINT) || (!QUERY_FLAG (tmp, FLAG_CURSED) && !QUERY_FLAG (tmp, FLAG_DAMNED)))
3048 {
2867 if (aflags & AP_PRINT) 3049 if (aflags & AP_PRINT)
2868 new_draw_info(NDI_UNIQUE, 0, who, query_name(tmp)); 3050 new_draw_info (NDI_UNIQUE, 0, who, query_name (tmp));
2869 else 3051 else
2870 unapply_special(who, tmp, aflags); 3052 unapply_special (who, tmp, aflags);
2871 } 3053 }
2872 else { 3054 else
3055 {
2873 /* In this case, we want to try and remove a cursed item. 3056 /* In this case, we want to try and remove a cursed item.
2874 * While we know it won't work, we want unapply_special to 3057 * While we know it won't work, we want unapply_special to
2875 * at least generate the message. 3058 * at least generate the message.
2876 */ 3059 */
2877 new_draw_info_format(NDI_UNIQUE, 0, who, 3060 new_draw_info_format (NDI_UNIQUE, 0, who, "No matter how hard you try, you just can't\nremove %s.", query_name (tmp));
2878 "No matter how hard you try, you just can't\nremove %s.",
2879 query_name(tmp));
2880 return 1; 3061 return 1;
2881 } 3062 }
2882 3063
2883 } 3064 }
2884 } 3065 }
2885 } 3066 }
2886 3067
2887 for (i=0; i<NUM_BODY_LOCATIONS; i++) { 3068 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
3069 {
2888 /* this used up a slot that we need to free */ 3070 /* this used up a slot that we need to free */
2889 if (op->body_info[i]) { 3071 if (op->body_info[i])
3072 {
2890 last = who->inv; 3073 last = who->inv;
2891 3074
2892 /* We do a while loop - may need to remove several items in order 3075 /* We do a while loop - may need to remove several items in order
2893 * to free up enough slots. 3076 * to free up enough slots.
2894 */ 3077 */
2895 while ((who->body_used[i] + op->body_info[i]) < 0) { 3078 while ((who->body_used[i] + op->body_info[i]) < 0)
3079 {
2896 tmp = get_item_from_body_location(last, i); 3080 tmp = get_item_from_body_location (last, i);
2897 if (!tmp) { 3081 if (!tmp)
3082 {
2898#if 0 3083#if 0
2899 /* Not a bug - we'll get this if the player has cursed items 3084 /* Not a bug - we'll get this if the player has cursed items
2900 * equipped. 3085 * equipped.
2901 */ 3086 */
2902 LOG(llevError,"Can't find object using location %d (%s) on %s\n", 3087 LOG (llevError, "Can't find object using location %d (%s) on %s\n", i, body_locations[i].save_name, who->name);
2903 i, body_locations[i].save_name, who->name);
2904#endif 3088#endif
2905 return 1; 3089 return 1;
2906 } 3090 }
2907 /* If we are just printing, we don't care about cursed status */ 3091 /* If we are just printing, we don't care about cursed status */
2908 if ((aflags & AP_IGNORE_CURSE) || (aflags & AP_PRINT) || 3092 if ((aflags & AP_IGNORE_CURSE) || (aflags & AP_PRINT) || (!(QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))))
2909 (!(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)))) { 3093 {
2910 if (aflags & AP_PRINT) 3094 if (aflags & AP_PRINT)
2911 new_draw_info(NDI_UNIQUE, 0, who, query_name(tmp)); 3095 new_draw_info (NDI_UNIQUE, 0, who, query_name (tmp));
2912 else 3096 else
2913 unapply_special(who, tmp, aflags); 3097 unapply_special (who, tmp, aflags);
2914 } 3098 }
2915 else { 3099 else
3100 {
2916 /* Cursed item that we can't unequip - tell the player. 3101 /* Cursed item that we can't unequip - tell the player.
2917 * Note this could be annoying if this is just one of a few, 3102 * Note this could be annoying if this is just one of a few,
2918 * so it may not be critical (eg, putting on a ring and you have 3103 * so it may not be critical (eg, putting on a ring and you have
2919 * one cursed ring.) 3104 * one cursed ring.)
2920 */ 3105 */
2921 new_draw_info_format(NDI_UNIQUE, 0, who, "The %s just won't come off", query_name(tmp)); 3106 new_draw_info_format (NDI_UNIQUE, 0, who, "The %s just won't come off", query_name (tmp));
2922 } 3107 }
2923 last = tmp->below; 3108 last = tmp->below;
2924 } 3109 }
2925 /* if we got here, this slot is freed up - otherwise, if it wasn't freed up, the 3110 /* if we got here, this slot is freed up - otherwise, if it wasn't freed up, the
2926 * return in the !tmp would have kicked in. 3111 * return in the !tmp would have kicked in.
2927 */ 3112 */
2928 } /* if op is using this body location */ 3113 } /* if op is using this body location */
2929 } /* for body lcoations */ 3114 } /* for body lcoations */
2930 return 0; 3115 return 0;
2931} 3116}
2932 3117
2933/** 3118/**
2934 * Checks to see if 'who' can apply object 'op'. 3119 * Checks to see if 'who' can apply object 'op'.
2935 * Returns 0 if apply can be done without anything special. 3120 * Returns 0 if apply can be done without anything special.
2939 * is set, do we really are what the other flags may be?) 3124 * is set, do we really are what the other flags may be?)
2940 * 3125 *
2941 * See include/define.h for detailed description of the meaning of 3126 * See include/define.h for detailed description of the meaning of
2942 * these return values. 3127 * these return values.
2943 */ 3128 */
3129int
2944int can_apply_object(object *who, object *op) 3130can_apply_object (object *who, object *op)
2945{ 3131{
2946 if (INVOKE_OBJECT (CAN_BE_APPLIED, op, ARG_OBJECT (who)) 3132 if (INVOKE_OBJECT (CAN_BE_APPLIED, op, ARG_OBJECT (who)) || INVOKE_OBJECT (CAN_APPLY, who, ARG_OBJECT (op)))
2947 || INVOKE_OBJECT (CAN_APPLY, who, ARG_OBJECT (op)))
2948 return RESULT_INT (0); 3133 return RESULT_INT (0);
2949 3134
2950 int i, retval=0; 3135 int i, retval = 0;
2951 object *tmp=NULL, *ws=NULL; 3136 object *tmp = NULL, *ws = NULL;
2952 3137
2953 /* Players have 2 'arm's, so they could in theory equip 2 shields or 3138 /* Players have 2 'arm's, so they could in theory equip 2 shields or
2954 * 2 weapons, but we don't want to let them do that. So if they are 3139 * 2 weapons, but we don't want to let them do that. So if they are
2955 * trying to equip a weapon or shield, see if they already have one 3140 * trying to equip a weapon or shield, see if they already have one
2956 * in place and store that way. 3141 * in place and store that way.
2957 */ 3142 */
2958 if (op->type == WEAPON || op->type == SHIELD) { 3143 if (op->type == WEAPON || op->type == SHIELD)
3144 {
2959 for (tmp=who->inv; tmp && !ws; tmp=tmp->below) { 3145 for (tmp = who->inv; tmp && !ws; tmp = tmp->below)
3146 {
2960 if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == op->type) { 3147 if (QUERY_FLAG (tmp, FLAG_APPLIED) && tmp->type == op->type)
3148 {
2961 retval = CAN_APPLY_UNAPPLY; 3149 retval = CAN_APPLY_UNAPPLY;
2962 ws = tmp; 3150 ws = tmp;
2963 } 3151 }
2964 } 3152 }
2965 } 3153 }
3154
3155
3156 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
3157 {
3158 if (op->body_info[i])
2966 3159 {
2967
2968 for (i=0; i<NUM_BODY_LOCATIONS; i++) {
2969 if (op->body_info[i]) {
2970 /* Item uses more slots than we have */ 3160 /* Item uses more slots than we have */
2971 if (FABS(op->body_info[i]) > who->body_info[i]) { 3161 if (FABS (op->body_info[i]) > who->body_info[i])
3162 {
2972 /* Could return now for efficiently - rest of info below isn' 3163 /* Could return now for efficiently - rest of info below isn'
2973 * really needed. 3164 * really needed.
2974 */ 3165 */
2975 retval |= CAN_APPLY_NEVER; 3166 retval |= CAN_APPLY_NEVER;
3167 }
2976 } else if ((who->body_used[i] + op->body_info[i]) < 0) { 3168 else if ((who->body_used[i] + op->body_info[i]) < 0)
3169 {
2977 /* in this case, equipping this would use more free spots than 3170 /* in this case, equipping this would use more free spots than
2978 * we have. 3171 * we have.
2979 */ 3172 */
2980 object *tmp1; 3173 object *tmp1;
2981 3174
2982 3175
2983 /* if we have an applied weapon/shield, and unapply it would free 3176 /* if we have an applied weapon/shield, and unapply it would free
2984 * enough slots to equip the new item, then just set this can 3177 * enough slots to equip the new item, then just set this can
2985 * continue. We don't care about the logic below - if you have 3178 * continue. We don't care about the logic below - if you have
2986 * shield equipped and try to equip another shield, there is only 3179 * shield equipped and try to equip another shield, there is only
2987 * one choice. However, the check for the number of body locations 3180 * one choice. However, the check for the number of body locations
2988 * does take into the account cases where what is being applied 3181 * does take into the account cases where what is being applied
2989 * may be two handed for example. 3182 * may be two handed for example.
2990 */ 3183 */
2991 if (ws) { 3184 if (ws)
3185 {
2992 if ((who->body_used[i] - ws->body_info[i] + op->body_info[i]) >=0) { 3186 if ((who->body_used[i] - ws->body_info[i] + op->body_info[i]) >= 0)
3187 {
2993 retval |= CAN_APPLY_UNAPPLY; 3188 retval |= CAN_APPLY_UNAPPLY;
2994 continue; 3189 continue;
2995 } 3190 }
2996 } 3191 }
2997 3192
2998 tmp1 = get_item_from_body_location(who->inv, i); 3193 tmp1 = get_item_from_body_location (who->inv, i);
2999 if (!tmp1) { 3194 if (!tmp1)
3195 {
3000#if 0 3196#if 0
3001 /* This is sort of an error, but happens a lot when old players 3197 /* This is sort of an error, but happens a lot when old players
3002 * join in with more stuff equipped than they are now allowed. 3198 * join in with more stuff equipped than they are now allowed.
3003 */ 3199 */
3004 LOG(llevError,"Can't find object using location %d on %s\n", 3200 LOG (llevError, "Can't find object using location %d on %s\n", i, who->name);
3005 i, who->name);
3006#endif 3201#endif
3007 retval |= CAN_APPLY_NEVER; 3202 retval |= CAN_APPLY_NEVER;
3203 }
3008 } else { 3204 else
3205 {
3009 /* need to unapply something. However, if this something 3206 /* need to unapply something. However, if this something
3010 * is different than we had found before, it means they need 3207 * is different than we had found before, it means they need
3011 * to apply multiple objects 3208 * to apply multiple objects
3012 */ 3209 */
3013 retval |= CAN_APPLY_UNAPPLY; 3210 retval |= CAN_APPLY_UNAPPLY;
3211 if (!tmp)
3014 if (!tmp) tmp = tmp1; 3212 tmp = tmp1;
3015 else if (tmp != tmp1) { 3213 else if (tmp != tmp1)
3214 {
3016 retval |= CAN_APPLY_UNAPPLY_MULT; 3215 retval |= CAN_APPLY_UNAPPLY_MULT;
3017 } 3216 }
3018 /* This object isn't using up all the slots, so there must 3217 /* This object isn't using up all the slots, so there must
3019 * be another. If so, and it the new item doesn't need all 3218 * be another. If so, and it the new item doesn't need all
3020 * the slots, the player then has a choice. 3219 * the slots, the player then has a choice.
3021 */ 3220 */
3022 if (((who->body_used[i] - tmp1->body_info[i]) != who->body_info[i]) && 3221 if (((who->body_used[i] - tmp1->body_info[i]) != who->body_info[i]) && (FABS (op->body_info[i]) < who->body_info[i]))
3023 (FABS(op->body_info[i]) < who->body_info[i]))
3024 retval |= CAN_APPLY_UNAPPLY_CHOICE; 3222 retval |= CAN_APPLY_UNAPPLY_CHOICE;
3025 3223
3026 /* Does unequippint 'tmp1' free up enough slots for this to be 3224 /* Does unequippint 'tmp1' free up enough slots for this to be
3027 * equipped? If not, there must be something else to unapply. 3225 * equipped? If not, there must be something else to unapply.
3028 */ 3226 */
3029 if ((who->body_used[i] + op->body_info[i] - tmp1->body_info[i]) < 0) 3227 if ((who->body_used[i] + op->body_info[i] - tmp1->body_info[i]) < 0)
3030 retval |= CAN_APPLY_UNAPPLY_MULT; 3228 retval |= CAN_APPLY_UNAPPLY_MULT;
3031 3229
3032 } 3230 }
3033 } /* if not enough free slots */ 3231 } /* if not enough free slots */
3034 } /* if this object uses location i */ 3232 } /* if this object uses location i */
3035 } /* for i -> num_body_locations loop */ 3233 } /* for i -> num_body_locations loop */
3036 3234
3037 /* Note that we don't check for FLAG_USE_ARMOUR - that should 3235 /* Note that we don't check for FLAG_USE_ARMOUR - that should
3038 * really be controlled by use of body locations. We do have 3236 * really be controlled by use of body locations. We do have
3039 * the weapon/shield checks, and the range checks for monsters, 3237 * the weapon/shield checks, and the range checks for monsters,
3040 * because you can't control those just by body location - bows, shields, 3238 * because you can't control those just by body location - bows, shields,
3041 * and weapons all use the same slot. Similar for horn/rod/wand - they 3239 * and weapons all use the same slot. Similar for horn/rod/wand - they
3042 * all use the same location. 3240 * all use the same location.
3043 */ 3241 */
3044 if (op->type == WEAPON && !QUERY_FLAG(who,FLAG_USE_WEAPON)) 3242 if (op->type == WEAPON && !QUERY_FLAG (who, FLAG_USE_WEAPON))
3243 retval |= CAN_APPLY_RESTRICTION;
3244 if (op->type == SHIELD && !QUERY_FLAG (who, FLAG_USE_SHIELD))
3245 retval |= CAN_APPLY_RESTRICTION;
3246
3247
3248 if (who->type != PLAYER)
3249 {
3250 if ((op->type == WAND || op->type == HORN || op->type == ROD) && !QUERY_FLAG (who, FLAG_USE_RANGE))
3045 retval |= CAN_APPLY_RESTRICTION; 3251 retval |= CAN_APPLY_RESTRICTION;
3046 if (op->type == SHIELD && !QUERY_FLAG(who,FLAG_USE_SHIELD)) 3252 if (op->type == BOW && !QUERY_FLAG (who, FLAG_USE_BOW))
3047 retval |= CAN_APPLY_RESTRICTION; 3253 retval |= CAN_APPLY_RESTRICTION;
3048
3049
3050 if (who->type != PLAYER) {
3051 if ((op->type == WAND || op->type == HORN || op->type==ROD)
3052 && !QUERY_FLAG(who, FLAG_USE_RANGE))
3053 retval |= CAN_APPLY_RESTRICTION;
3054 if (op->type == BOW && !QUERY_FLAG(who, FLAG_USE_BOW))
3055 retval |= CAN_APPLY_RESTRICTION;
3056 if (op->type == RING && !QUERY_FLAG(who, FLAG_USE_RING)) 3254 if (op->type == RING && !QUERY_FLAG (who, FLAG_USE_RING))
3057 retval |= CAN_APPLY_RESTRICTION; 3255 retval |= CAN_APPLY_RESTRICTION;
3058 if (op->type == BOW && !QUERY_FLAG(who, FLAG_USE_BOW)) 3256 if (op->type == BOW && !QUERY_FLAG (who, FLAG_USE_BOW))
3059 retval |= CAN_APPLY_RESTRICTION; 3257 retval |= CAN_APPLY_RESTRICTION;
3060 } 3258 }
3061 return retval; 3259 return retval;
3062} 3260}
3063 3261
3064 3262
3065 3263
3066/** 3264/**
3067 * who is the object using the object. It can be a monster. 3265 * who is the object using the object. It can be a monster.
3068 * op is the object they are using. op is an equipment type item, 3266 * op is the object they are using. op is an equipment type item,
3069 * eg, one which you put on and keep on for a while, and not something 3267 * eg, one which you put on and keep on for a while, and not something
3083 * 3281 *
3084 * Usage example: apply_special (who, op, AP_UNAPPLY | AP_IGNORE_CURSE) 3282 * Usage example: apply_special (who, op, AP_UNAPPLY | AP_IGNORE_CURSE)
3085 * 3283 *
3086 * apply_special() doesn't check for unpaid items. 3284 * apply_special() doesn't check for unpaid items.
3087 */ 3285 */
3286int
3088int apply_special (object *who, object *op, int aflags) 3287apply_special (object *who, object *op, int aflags)
3089{ 3288{
3090 int basic_flag = aflags & AP_BASIC_FLAGS; 3289 int basic_flag = aflags & AP_BASIC_FLAGS;
3091 object *tmp, *tmp2, *skop=NULL; 3290 object *tmp, *tmp2, *skop = NULL;
3092 int i; 3291 int i;
3093 3292
3094 if(who==NULL) { 3293 if (who == NULL)
3294 {
3095 LOG(llevError,"apply_special() from object without environment.\n"); 3295 LOG (llevError, "apply_special() from object without environment.\n");
3096 return 1; 3296 return 1;
3097 } 3297 }
3098 3298
3099 if(op->env!=who) 3299 if (op->env != who)
3100 return 1; /* op is not in inventory */ 3300 return 1; /* op is not in inventory */
3101 3301
3102 /* trying to unequip op */ 3302 /* trying to unequip op */
3103 if (QUERY_FLAG(op,FLAG_APPLIED)) { 3303 if (QUERY_FLAG (op, FLAG_APPLIED))
3304 {
3104 /* always apply, so no reason to unapply */ 3305 /* always apply, so no reason to unapply */
3105 if (basic_flag == AP_APPLY) return 0; 3306 if (basic_flag == AP_APPLY)
3307 return 0;
3106 3308
3107 if ( ! (aflags & AP_IGNORE_CURSE)
3108 && (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))) { 3309 if (!(aflags & AP_IGNORE_CURSE) && (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)))
3109 new_draw_info_format(NDI_UNIQUE, 0, who, 3310 {
3110 "No matter how hard you try, you just can't\nremove %s.", 3311 new_draw_info_format (NDI_UNIQUE, 0, who, "No matter how hard you try, you just can't\nremove %s.", query_name (op));
3111 query_name(op)); 3312 return 1;
3313 }
3314 return unapply_special (who, op, aflags);
3315 }
3316
3317 if (basic_flag == AP_UNAPPLY)
3318 return 0;
3319
3320 i = can_apply_object (who, op);
3321
3322 /* Can't just apply this object. Lets see what not and what to do */
3323 if (i)
3324 {
3325 if (i & CAN_APPLY_NEVER)
3326 {
3327 new_draw_info_format (NDI_UNIQUE, 0, who, "You don't have the body to use a %s\n", query_name (op));
3328 return 1;
3329 }
3330 else if (i & CAN_APPLY_RESTRICTION)
3331 {
3332 new_draw_info_format (NDI_UNIQUE, 0, who, "You have a prohibition against using a %s\n", query_name (op));
3333 return 1;
3334 }
3335 if (who->type != PLAYER)
3336 {
3337 /* Some error, so don't try to equip something more */
3338 if (unapply_for_ob (who, op, aflags))
3112 return 1; 3339 return 1;
3113 } 3340 }
3114 return unapply_special(who, op, aflags); 3341 else
3115 }
3116
3117 if (basic_flag == AP_UNAPPLY) return 0;
3118
3119 i = can_apply_object(who, op);
3120
3121 /* Can't just apply this object. Lets see what not and what to do */
3122 if (i) {
3123 if (i & CAN_APPLY_NEVER) {
3124 new_draw_info_format(NDI_UNIQUE, 0, who, "You don't have the body to use a %s\n", query_name(op));
3125 return 1;
3126 } else if (i & CAN_APPLY_RESTRICTION) {
3127 new_draw_info_format(NDI_UNIQUE, 0, who, "You have a prohibition against using a %s\n", query_name(op));
3128 return 1;
3129 } 3342 {
3130 if (who->type != PLAYER) {
3131 /* Some error, so don't try to equip something more */
3132 if (unapply_for_ob(who, op, aflags)) return 1;
3133 } else {
3134 if (who->contr->unapply == unapply_never ||
3135 (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))
3344 {
3136 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:");
3137 unapply_for_ob(who, op, AP_PRINT); 3346 unapply_for_ob (who, op, AP_PRINT);
3347 return 1;
3348 }
3349 else if (who->contr->unapply == unapply_always || !(i & CAN_APPLY_UNAPPLY_CHOICE))
3350 {
3351 i = unapply_for_ob (who, op, aflags);
3352 if (i)
3138 return 1; 3353 return 1;
3139 } 3354 }
3140 else if (who->contr->unapply == unapply_always || !(i & CAN_APPLY_UNAPPLY_CHOICE)) {
3141 i = unapply_for_ob(who, op, aflags);
3142 if (i) return 1;
3143 } 3355 }
3144 }
3145 } 3356 }
3357
3146 if (op->skill && op->type != SKILL && op->type != SKILL_TOOL) { 3358 if (op->skill && op->type != SKILL && op->type != SKILL_TOOL)
3359 {
3147 skop=find_skill_by_name(who, op->skill); 3360 skop = find_skill_by_name (who, op->skill);
3148 if (!skop) { 3361 if (!skop)
3362 {
3149 new_draw_info_format(NDI_UNIQUE, 0, who, "You need the %s skill to use this item!", &op->skill); 3363 new_draw_info_format (NDI_UNIQUE, 0, who, "You need the %s skill to use this item!", &op->skill);
3364 return 1;
3365 }
3366 else
3367 {
3368 /* While experience will be credited properly, we want to change the
3369 * skill so that the dam and wc get updated
3370 */
3371 change_skill (who, skop, 0);
3372 }
3373 }
3374
3375 if (who->type == PLAYER && op->item_power && (op->item_power + who->contr->item_power) > (settings.item_power_factor * who->level))
3376 {
3377 new_draw_info (NDI_UNIQUE, 0, who, "Equipping that combined with other items would consume your soul!");
3378 return 1;
3379 }
3380
3381
3382 /* Ok. We are now at the state where we can apply the new object.
3383 * Note that we don't have the checks for can_use_...
3384 * below - that is already taken care of by can_apply_object.
3385 */
3386
3387
3388 if (op->nrof > 1)
3389 tmp = get_split_ob (op, op->nrof - 1);
3390 else
3391 tmp = NULL;
3392
3393 if (INVOKE_OBJECT (BE_READY, op, ARG_OBJECT (who)) || INVOKE_OBJECT (READY, who, ARG_OBJECT (op)))
3394 return RESULT_INT (0);
3395
3396 switch (op->type)
3397 {
3398 case WEAPON:
3399 if (!check_weapon_power (who, op->last_eat))
3400 {
3401 new_draw_info (NDI_UNIQUE, 0, who, "That weapon is too powerful for you to use.");
3402 new_draw_info (NDI_UNIQUE, 0, who, "It would consume your soul!.");
3403 if (tmp != NULL)
3404 (void) insert_ob_in_ob (tmp, who);
3150 return 1; 3405 return 1;
3151 } else {
3152 /* While experience will be credited properly, we want to change the
3153 * skill so that the dam and wc get updated
3154 */
3155 change_skill(who, skop, 0);
3156 }
3157 }
3158
3159 if (who->type == PLAYER && op->item_power &&
3160 (op->item_power + who->contr->item_power) > (settings.item_power_factor * who->level)) {
3161 new_draw_info(NDI_UNIQUE, 0, who, "Equipping that combined with other items would consume your soul!");
3162 return 1;
3163 }
3164
3165
3166 /* Ok. We are now at the state where we can apply the new object.
3167 * Note that we don't have the checks for can_use_...
3168 * below - that is already taken care of by can_apply_object.
3169 */
3170
3171
3172 if(op->nrof > 1)
3173 tmp = get_split_ob(op,op->nrof - 1);
3174 else
3175 tmp = NULL;
3176
3177 if (INVOKE_OBJECT (BE_READY, op, ARG_OBJECT (who))
3178 || INVOKE_OBJECT (READY, who, ARG_OBJECT (op)))
3179 return RESULT_INT (0);
3180
3181 switch(op->type) {
3182 case WEAPON:
3183 if (!check_weapon_power(who, op->last_eat)) {
3184 new_draw_info(NDI_UNIQUE, 0,who,
3185 "That weapon is too powerful for you to use.");
3186 new_draw_info(NDI_UNIQUE, 0, who, "It would consume your soul!.");
3187 if(tmp!=NULL)
3188 (void) insert_ob_in_ob(tmp,who);
3189 return 1;
3190 } 3406 }
3191 if( op->level && (strncmp(op->name,who->name,strlen(who->name)))) { 3407 if (op->level && (strncmp (op->name, who->name, strlen (who->name))))
3408 {
3192 /* if the weapon does not have the name as the character, can't use it. */ 3409 /* if the weapon does not have the name as the character, can't use it. */
3193 /* (Ragnarok's sword attempted to be used by Foo: won't work) */ 3410 /* (Ragnarok's sword attempted to be used by Foo: won't work) */
3194 new_draw_info(NDI_UNIQUE, 0,who,"The weapon does not recognize you as its owner."); 3411 new_draw_info (NDI_UNIQUE, 0, who, "The weapon does not recognize you as its owner.");
3195 if(tmp!=NULL) 3412 if (tmp != NULL)
3196 (void) insert_ob_in_ob(tmp,who); 3413 (void) insert_ob_in_ob (tmp, who);
3197 return 1; 3414 return 1;
3198 } 3415 }
3199 SET_FLAG(op, FLAG_APPLIED); 3416 SET_FLAG (op, FLAG_APPLIED);
3200 3417
3418 if (skop)
3201 if (skop) change_skill(who, skop, 1); 3419 change_skill (who, skop, 1);
3202 if(!QUERY_FLAG(who,FLAG_READY_WEAPON)) 3420 if (!QUERY_FLAG (who, FLAG_READY_WEAPON))
3203 SET_FLAG(who, FLAG_READY_WEAPON); 3421 SET_FLAG (who, FLAG_READY_WEAPON);
3204 3422
3205 new_draw_info_format(NDI_UNIQUE, 0, who, "You wield %s.",query_name(op)); 3423 new_draw_info_format (NDI_UNIQUE, 0, who, "You wield %s.", query_name (op));
3206 3424
3207 (void) change_abil (who,op); 3425 (void) change_abil (who, op);
3208 break; 3426 break;
3209 3427
3210 case ARMOUR: 3428 case ARMOUR:
3211 case HELMET: 3429 case HELMET:
3212 case SHIELD: 3430 case SHIELD:
3213 case BOOTS: 3431 case BOOTS:
3214 case GLOVES: 3432 case GLOVES:
3215 case GIRDLE: 3433 case GIRDLE:
3216 case BRACERS: 3434 case BRACERS:
3217 case CLOAK: 3435 case CLOAK:
3218 case RING: 3436 case RING:
3219 case AMULET: 3437 case AMULET:
3220 SET_FLAG(op, FLAG_APPLIED); 3438 SET_FLAG (op, FLAG_APPLIED);
3221 new_draw_info_format(NDI_UNIQUE, 0, who, "You wear %s.",query_name(op)); 3439 new_draw_info_format (NDI_UNIQUE, 0, who, "You wear %s.", query_name (op));
3222 (void) change_abil (who,op); 3440 (void) change_abil (who, op);
3223 break; 3441 break;
3224 case LAMP: 3442 case LAMP:
3225 if (op->stats.food < 1) { 3443 if (op->stats.food < 1)
3444 {
3226 new_draw_info_format(NDI_UNIQUE, 0, who, "Your %s is out of" 3445 new_draw_info_format (NDI_UNIQUE, 0, who, "Your %s is out of" " fuel!", &op->name);
3227 " fuel!", &op->name);
3228 return 1; 3446 return 1;
3229 } 3447 }
3230 new_draw_info_format(NDI_UNIQUE, 0, who, "You turn on your %s.", 3448 new_draw_info_format (NDI_UNIQUE, 0, who, "You turn on your %s.", &op->name);
3231 &op->name);
3232 tmp2 = arch_to_object(op->other_arch); 3449 tmp2 = arch_to_object (op->other_arch);
3233 tmp2->stats.food = op->stats.food; 3450 tmp2->stats.food = op->stats.food;
3234 SET_FLAG(tmp2, FLAG_APPLIED); 3451 SET_FLAG (tmp2, FLAG_APPLIED);
3235 if (QUERY_FLAG(op, FLAG_INV_LOCKED)) 3452 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
3236 SET_FLAG(tmp2, FLAG_INV_LOCKED); 3453 SET_FLAG (tmp2, FLAG_INV_LOCKED);
3237 insert_ob_in_ob(tmp2, who); 3454 insert_ob_in_ob (tmp2, who);
3238 3455
3239 /* Remove the old lantern */ 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);
3240 if (who->type == PLAYER) 3466 if (who->type == PLAYER)
3241 esrv_del_item(who->contr, (tag_t)op->count);
3242 remove_ob(op);
3243 free_object(op);
3244
3245 /* insert the portion that was split off */
3246 if(tmp!=NULL) {
3247 (void) insert_ob_in_ob(tmp,who);
3248 if(who->type==PLAYER)
3249 esrv_send_item(who, tmp); 3467 esrv_send_item (who, tmp);
3250 } 3468 }
3251 fix_player(who); 3469 who->update_stats ();
3252 if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)) { 3470 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
3471 {
3253 if (who->type == PLAYER) { 3472 if (who->type == PLAYER)
3473 {
3254 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!");
3255 SET_FLAG(tmp2, FLAG_KNOWN_CURSED); 3475 SET_FLAG (tmp2, FLAG_KNOWN_CURSED);
3256 } 3476 }
3257 } 3477 }
3258 if(who->type==PLAYER) 3478 if (who->type == PLAYER)
3259 esrv_send_item(who, tmp2); 3479 esrv_send_item (who, tmp2);
3260 return 0; 3480 return 0;
3261 break; 3481 break;
3262 3482
3263 /* this part is needed for skill-tools */ 3483 /* this part is needed for skill-tools */
3264 case SKILL: 3484 case SKILL:
3265 case SKILL_TOOL: 3485 case SKILL_TOOL:
3266 if (who->chosen_skill) { 3486 if (who->chosen_skill)
3487 {
3267 LOG (llevError, "BUG: apply_special(): can't apply two skills\n"); 3488 LOG (llevError, "BUG: apply_special(): can't apply two skills\n");
3268 return 1; 3489 return 1;
3269 } 3490 }
3270 if (who->type == PLAYER) { 3491 if (who->type == PLAYER)
3492 {
3271 who->contr->shoottype = range_skill; 3493 who->contr->shoottype = range_skill;
3272 who->contr->ranges[range_skill] = op; 3494 who->contr->ranges[range_skill] = op;
3273 if ( ! op->invisible) { 3495 if (!op->invisible)
3274 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.",
3275 query_name (op));
3276 new_draw_info_format (NDI_UNIQUE, 0, who,
3277 "You can now use the skill: %s.",
3278 &op->skill);
3279 } else {
3280 new_draw_info_format (NDI_UNIQUE, 0, who, "Readied skill: %s.",
3281 op->skill ? &op->skill : &op->name);
3282 } 3496 {
3283 }
3284 SET_FLAG (op, FLAG_APPLIED);
3285 (void) change_abil (who, op);
3286 who->chosen_skill = op;
3287 SET_FLAG (who, FLAG_READY_SKILL);
3288 break;
3289
3290 case BOW:
3291 if (!check_weapon_power(who, op->last_eat)) {
3292 new_draw_info(NDI_UNIQUE, 0, who,
3293 "That item is too powerful for you to use.");
3294 new_draw_info(NDI_UNIQUE, 0, who, "It would consume your soul!.");
3295 if(tmp != NULL)
3296 (void)insert_ob_in_ob(tmp,who);
3297 return 1;
3298 }
3299 if( op->level && (strncmp(op->name,who->name,strlen(who->name)))) {
3300 new_draw_info(NDI_UNIQUE, 0, who,
3301 "The weapon does not recognize you as its owner.");
3302 if(tmp != NULL)
3303 (void)insert_ob_in_ob(tmp,who);
3304 return 1;
3305 }
3306 /*FALLTHROUGH*/
3307 case WAND:
3308 case ROD:
3309 case HORN:
3310 /* check for skill, alter player status */
3311 SET_FLAG(op, FLAG_APPLIED);
3312 if (skop) change_skill(who, skop, 0);
3313 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));
3498 new_draw_info_format (NDI_UNIQUE, 0, who, "You can now use the skill: %s.", &op->skill);
3499 }
3500 else
3501 {
3502 new_draw_info_format (NDI_UNIQUE, 0, who, "Readied skill: %s.", op->skill ? &op->skill : &op->name);
3503 }
3504 }
3505 SET_FLAG (op, FLAG_APPLIED);
3506 (void) change_abil (who, op);
3507 who->chosen_skill = op;
3508 SET_FLAG (who, FLAG_READY_SKILL);
3509 break;
3314 3510
3511 case BOW:
3512 if (!check_weapon_power (who, op->last_eat))
3513 {
3514 new_draw_info (NDI_UNIQUE, 0, who, "That item is too powerful for you to use.");
3515 new_draw_info (NDI_UNIQUE, 0, who, "It would consume your soul!.");
3516 if (tmp != NULL)
3517 (void) insert_ob_in_ob (tmp, who);
3518 return 1;
3519 }
3520 if (op->level && (strncmp (op->name, who->name, strlen (who->name))))
3521 {
3522 new_draw_info (NDI_UNIQUE, 0, who, "The weapon does not recognize you as its owner.");
3523 if (tmp != NULL)
3524 (void) insert_ob_in_ob (tmp, who);
3525 return 1;
3526 }
3527 /*FALLTHROUGH*/ case WAND:
3528 case ROD:
3529 case HORN:
3530 /* check for skill, alter player status */
3531 SET_FLAG (op, FLAG_APPLIED);
3532 if (skop)
3533 change_skill (who, skop, 0);
3534 new_draw_info_format (NDI_UNIQUE, 0, who, "You ready %s.", query_name (op));
3535
3315 if(who->type==PLAYER) { 3536 if (who->type == PLAYER)
3537 {
3316 if (op->type == BOW) { 3538 if (op->type == BOW)
3539 {
3317 (void)change_abil(who, op); 3540 (void) change_abil (who, op);
3318 new_draw_info_format (NDI_UNIQUE, 0, who, 3541 new_draw_info_format (NDI_UNIQUE, 0, who,
3319 "You will now fire %s with %s.",
3320 op->race ? &op->race : "nothing", query_name(op)); 3542 "You will now fire %s with %s.", op->race ? &op->race : "nothing", query_name (op));
3321 who->contr->shoottype = range_bow; 3543 who->contr->shoottype = range_bow;
3544 }
3322 } else { 3545 else
3546 {
3323 who->contr->shoottype = range_misc; 3547 who->contr->shoottype = range_misc;
3324 } 3548 }
3549 }
3325 } else { 3550 else
3551 {
3326 if (op->type == BOW) 3552 if (op->type == BOW)
3327 SET_FLAG (who, FLAG_READY_BOW); 3553 SET_FLAG (who, FLAG_READY_BOW);
3328 else 3554 else
3329 SET_FLAG (who, FLAG_READY_RANGE); 3555 SET_FLAG (who, FLAG_READY_RANGE);
3330 } 3556 }
3331 break; 3557 break;
3332 3558
3333 case BUILDER: 3559 case BUILDER:
3334 if ( who->contr->ranges[ range_builder ] ) 3560 if (who->contr->ranges[range_builder])
3335 unapply_special( who, who->contr->ranges[ range_builder ], 0 ); 3561 unapply_special (who, who->contr->ranges[range_builder], 0);
3336 who->contr->shoottype = range_builder; 3562 who->contr->shoottype = range_builder;
3337 who->contr->ranges[ range_builder ] = op; 3563 who->contr->ranges[range_builder] = op;
3338 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));
3339 break; 3565 break;
3340 3566
3341 default: 3567 default:
3342 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));
3343 } /* end of switch op->type */ 3569 } /* end of switch op->type */
3344 3570
3345 SET_FLAG(op, FLAG_APPLIED); 3571 SET_FLAG (op, FLAG_APPLIED);
3346 3572
3347 if(tmp!=NULL) 3573 if (tmp != NULL)
3348 tmp = insert_ob_in_ob(tmp,who); 3574 tmp = insert_ob_in_ob (tmp, who);
3349 3575
3350 fix_player(who); 3576 who->update_stats ();
3351 3577
3352 /* We exclude spell casting objects. The fire code will set the 3578 /* We exclude spell casting objects. The fire code will set the
3353 * been applied flag when they are used - until that point, 3579 * been applied flag when they are used - until that point,
3354 * you don't know anything about them. 3580 * you don't know anything about them.
3355 */ 3581 */
3356 if (who->type == PLAYER && op->type!=WAND && op->type!=HORN && 3582 if (who->type == PLAYER && op->type != WAND && op->type != HORN && op->type != ROD)
3357 op->type!=ROD)
3358 SET_FLAG(op,FLAG_BEEN_APPLIED); 3583 SET_FLAG (op, FLAG_BEEN_APPLIED);
3359 3584
3360 if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)) { 3585 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
3586 {
3361 if (who->type == PLAYER) { 3587 if (who->type == PLAYER)
3588 {
3362 new_draw_info(NDI_UNIQUE, 0,who, "Oops, it feels deadly cold!"); 3589 new_draw_info (NDI_UNIQUE, 0, who, "Oops, it feels deadly cold!");
3363 SET_FLAG(op,FLAG_KNOWN_CURSED); 3590 SET_FLAG (op, FLAG_KNOWN_CURSED);
3364 } 3591 }
3365 } 3592 }
3366 if(who->type==PLAYER) { 3593 if (who->type == PLAYER)
3594 {
3367 /* if multiple objects were applied, update both slots */ 3595 /* if multiple objects were applied, update both slots */
3368 if (tmp) 3596 if (tmp)
3369 esrv_send_item(who, tmp); 3597 esrv_send_item (who, tmp);
3370 esrv_send_item(who, op); 3598 esrv_send_item (who, op);
3371 } 3599 }
3372 return 0; 3600 return 0;
3373} 3601}
3374 3602
3375 3603
3604int
3376int monster_apply_special (object *who, object *op, int aflags) 3605monster_apply_special (object *who, object *op, int aflags)
3377{ 3606{
3378 if (QUERY_FLAG (op, FLAG_UNPAID) && ! QUERY_FLAG (op, FLAG_APPLIED)) 3607 if (QUERY_FLAG (op, FLAG_UNPAID) && !QUERY_FLAG (op, FLAG_APPLIED))
3379 return 1; 3608 return 1;
3380 return apply_special (who, op, aflags); 3609 return apply_special (who, op, aflags);
3381} 3610}
3382 3611
3383/** 3612/**
3384 * Map was just loaded, handle op's initialisation. 3613 * Map was just loaded, handle op's initialisation.
3385 * 3614 *
3386 * Generates shop floor's item, and treasures. 3615 * Generates shop floor's item, and treasures.
3387 */ 3616 */
3617int
3388int auto_apply (object *op) { 3618auto_apply (object *op)
3619{
3389 object *tmp = NULL, *tmp2; 3620 object *tmp = NULL, *tmp2;
3390 int i; 3621 int i;
3391 3622
3392 switch(op->type) { 3623 switch (op->type)
3624 {
3393 case SHOP_FLOOR: 3625 case SHOP_FLOOR:
3394 if (!HAS_RANDOM_ITEMS(op)) return 0; 3626 if (!op->has_random_items ())
3627 return 0;
3628
3629 do
3395 do { 3630 {
3396 i=10; /* let's give it 10 tries */ 3631 i = 10; /* let's give it 10 tries */
3397 while((tmp=generate_treasure(op->randomitems, 3632 while ((tmp = generate_treasure (op->randomitems,
3398 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);
3399 if(tmp==NULL) 3634 if (tmp == NULL)
3400 return 0;
3401 if(QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
3402 free_object(tmp);
3403 tmp = NULL;
3404 }
3405 } while(!tmp);
3406 tmp->x=op->x;
3407 tmp->y=op->y;
3408 SET_FLAG(tmp,FLAG_UNPAID);
3409 insert_ob_in_map(tmp,op->map,NULL,0);
3410 CLEAR_FLAG(op,FLAG_AUTO_APPLY);
3411 identify(tmp);
3412 break;
3413
3414 case TREASURE:
3415 if (QUERY_FLAG(op,FLAG_IS_A_TEMPLATE))
3416 return 0; 3635 return 0;
3636 if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
3637 {
3638 tmp->destroy ();
3639 tmp = NULL;
3640 }
3641 }
3642 while (!tmp);
3643
3644 tmp->x = op->x;
3645 tmp->y = op->y;
3646 SET_FLAG (tmp, FLAG_UNPAID);
3647 insert_ob_in_map (tmp, op->map, NULL, 0);
3648 CLEAR_FLAG (op, FLAG_AUTO_APPLY);
3649 identify (tmp);
3650 break;
3651
3652 case TREASURE:
3653 if (QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))
3654 return 0;
3655
3417 while ((op->stats.hp--)>0) 3656 while ((op->stats.hp--) > 0)
3418 create_treasure(op->randomitems, op, op->map?GT_ENVIRONMENT:0, 3657 create_treasure (op->randomitems, op, op->map ? GT_ENVIRONMENT : 0,
3419 op->stats.exp ? (int)op->stats.exp :
3420 op->map == NULL ? 14: op->map->difficulty,0); 3658 op->stats.exp ? (int) op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
3421 3659
3422 /* 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,
3423 * 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
3424 * to disappear. An example of this item is the random_* stuff 3662 * to disappear. An example of this item is the random_* stuff
3425 * that is put inside other objects. 3663 * that is put inside other objects.
3426 */ 3664 */
3427 for (tmp=op->inv; tmp; tmp=tmp2) { 3665 for (tmp = op->inv; tmp; tmp = tmp2)
3666 {
3428 tmp2 = tmp->below; 3667 tmp2 = tmp->below;
3429 remove_ob(tmp); 3668 tmp->remove ();
3669
3670 if (op->env)
3430 if (op->env) insert_ob_in_ob(tmp, op->env); 3671 insert_ob_in_ob (tmp, op->env);
3431 else free_object(tmp); 3672 else
3673 tmp->destroy ();
3432 } 3674 }
3433 remove_ob(op); 3675
3434 free_object(op); 3676 op->destroy ();
3435 break; 3677 break;
3436 } 3678 }
3437 return tmp ? 1 : 0; 3679 return tmp ? 1 : 0;
3438} 3680}
3439 3681
3440/** 3682/**
3441 * fix_auto_apply goes through the entire map (only the first time 3683 * fix_auto_apply goes through the entire map (only the first time
3442 * when an original map is loaded) and performs special actions for 3684 * when an original map is loaded) and performs special actions for
3443 * certain objects (most initialization of chests and creation of 3685 * certain objects (most initialization of chests and creation of
3444 * treasures and stuff). Calls auto_apply if appropriate. 3686 * treasures and stuff). Calls auto_apply if appropriate.
3445 */ 3687 */
3446void 3688void
3447fix_auto_apply (mapstruct * m) 3689maptile::fix_auto_apply ()
3448{ 3690{
3449 object *tmp, *above = NULL; 3691 if (!spaces)
3450 int x, y;
3451
3452 if (m == NULL)
3453 return; 3692 return;
3454 3693
3455 for (x = 0; x < MAP_WIDTH (m); x++) 3694 for (mapspace *ms = spaces + size (); ms-- > spaces; )
3456 for (y = 0; y < MAP_HEIGHT (m); y++) 3695 for (object *tmp = ms->bot; tmp; )
3457 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = above)
3458 { 3696 {
3459 above = tmp->above; 3697 object *above = tmp->above;
3460 3698
3461 if (tmp->inv) 3699 if (tmp->inv)
3462 { 3700 {
3463 object *invtmp, *invnext; 3701 object *invtmp, *invnext;
3464 3702
3465 for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext) 3703 for (invtmp = tmp->inv; invtmp != NULL; invtmp = invnext)
3466 { 3704 {
3467 invnext = invtmp->below; 3705 invnext = invtmp->below;
3468 3706
3469 if (QUERY_FLAG (invtmp, FLAG_AUTO_APPLY)) 3707 if (QUERY_FLAG (invtmp, FLAG_AUTO_APPLY))
3470 auto_apply (invtmp); 3708 auto_apply (invtmp);
3471 else if (invtmp->type == TREASURE && HAS_RANDOM_ITEMS (invtmp)) 3709 else if (invtmp->type == TREASURE && invtmp->has_random_items ())
3472 { 3710 {
3473 while ((invtmp->stats.hp--) > 0) 3711 while ((invtmp->stats.hp--) > 0)
3474 create_treasure (invtmp->randomitems, invtmp, 0, m->difficulty, 0); 3712 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0);
3475 3713
3476 invtmp->randomitems = NULL; 3714 invtmp->randomitems = NULL;
3477 } 3715 }
3478 else if (invtmp && invtmp->arch 3716 else if (invtmp && invtmp->arch
3479 && invtmp->type != TREASURE 3717 && invtmp->type != TREASURE && invtmp->type != SPELL && invtmp->type != CLASS && invtmp->has_random_items ())
3480 && invtmp->type != SPELL
3481 && invtmp->type != CLASS
3482 && HAS_RANDOM_ITEMS (invtmp))
3483 { 3718 {
3484 create_treasure (invtmp->randomitems, invtmp, 0, 3719 create_treasure (invtmp->randomitems, invtmp, 0, difficulty, 0);
3485 m->difficulty, 0);
3486 /* Need to clear this so that we never try to create 3720 /* Need to clear this so that we never try to create
3487 * treasure again for this object 3721 * treasure again for this object
3488 */ 3722 */
3489 invtmp->randomitems = NULL; 3723 invtmp->randomitems = NULL;
3490 } 3724 }
3491 } 3725 }
3492 /* This is really temporary - the code at the bottom will 3726 /* This is really temporary - the code at the bottom will
3493 * also set randomitems to null. The problem is there are bunches 3727 * also set randomitems to null. The problem is there are bunches
3494 * of maps/players already out there with items that have spells 3728 * of maps/players already out there with items that have spells
3495 * which haven't had the randomitems set to null yet. 3729 * which haven't had the randomitems set to null yet.
3496 * MSW 2004-05-13 3730 * MSW 2004-05-13
3497 * 3731 *
3498 * 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,
3499 * else you get two spells in the book ^_- 3733 * else you get two spells in the book ^_-
3500 * Ryo 2004-08-16 3734 * Ryo 2004-08-16
3501 */ 3735 */
3502 if (tmp->type == WAND || tmp->type == ROD || tmp->type == SCROLL 3736 if (tmp->type == WAND || tmp->type == ROD || tmp->type == SCROLL
3503 || tmp->type == HORN || tmp->type == FIREWALL 3737 || tmp->type == HORN || tmp->type == FIREWALL || tmp->type == POTION || tmp->type == ALTAR || tmp->type == SPELLBOOK)
3504 || tmp->type == POTION || tmp->type == ALTAR
3505 || tmp->type == SPELLBOOK)
3506 tmp->randomitems = NULL;
3507
3508 }
3509
3510 if (QUERY_FLAG (tmp, FLAG_AUTO_APPLY))
3511 auto_apply (tmp);
3512 else if ((tmp->type == TREASURE || (tmp->type == CONTAINER))
3513 && HAS_RANDOM_ITEMS (tmp))
3514 {
3515 while ((tmp->stats.hp--) > 0)
3516 create_treasure (tmp->randomitems, tmp, 0, m->difficulty, 0);
3517 tmp->randomitems = NULL; 3738 tmp->randomitems = NULL;
3739
3518 } 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 }
3519 else if (tmp->type == TIMED_GATE) 3750 else if (tmp->type == TIMED_GATE)
3520 { 3751 {
3521 object *head = tmp->head != NULL ? tmp->head : tmp; 3752 object *head = tmp->head != NULL ? tmp->head : tmp;
3753
3522 if (QUERY_FLAG (head, FLAG_IS_LINKED)) 3754 if (QUERY_FLAG (head, FLAG_IS_LINKED))
3523 {
3524 tmp->speed = 0; 3755 tmp->set_speed (0);
3525 update_ob_speed (tmp);
3526 }
3527 } 3756 }
3528 /* 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
3529 * 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
3530 * 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
3531 * 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.
3532 * 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
3533 * which say how many times to make the treasure. 3762 * which say how many times to make the treasure.
3534 */ 3763 */
3535 else if (tmp && tmp->arch && tmp->type != PLAYER 3764 else if (tmp && tmp->arch && tmp->type != PLAYER
3536 && tmp->type != TREASURE && tmp->type != SPELL 3765 && tmp->type != TREASURE && tmp->type != SPELL
3537 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS 3766 && tmp->type != PLAYER_CHANGER && tmp->type != CLASS && tmp->has_random_items ())
3538 && HAS_RANDOM_ITEMS (tmp))
3539 { 3767 {
3540 create_treasure (tmp->randomitems, tmp, GT_APPLY, 3768 create_treasure (tmp->randomitems, tmp, GT_APPLY, difficulty, 0);
3541 m->difficulty, 0);
3542 tmp->randomitems = NULL; 3769 tmp->randomitems = NULL;
3543 } 3770 }
3771
3772 tmp = above;
3544 } 3773 }
3545 3774
3546 for (x = 0; x < MAP_WIDTH (m); x++) 3775 for (mapspace *ms = spaces + size (); ms-- > spaces; )
3547 for (y = 0; y < MAP_HEIGHT (m); y++) 3776 for (object *tmp = ms->bot; tmp; tmp = tmp->above)
3548 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above)
3549 if (tmp->above &&
3550 (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL)) 3777 if (tmp->above && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
3551 check_trigger (tmp, tmp->above); 3778 check_trigger (tmp, tmp->above);
3552} 3779}
3553 3780
3554/** 3781/**
3555 * Handles player eating food that temporarily changes status (resistances, stats). 3782 * Handles player eating food that temporarily changes status (resistances, stats).
3556 * This used to call cast_change_attr(), but 3783 * This used to call cast_change_attr(), but
3557 * that doesn't work with the new spell code. Since we know what 3784 * that doesn't work with the new spell code. Since we know what
3558 * the food changes, just grab a force and use that instead. 3785 * the food changes, just grab a force and use that instead.
3559 */ 3786 */
3560 3787
3788void
3561void eat_special_food(object *who, object *food) { 3789eat_special_food (object *who, object *food)
3790{
3562 object *force; 3791 object *force;
3563 int i, did_one=0; 3792 int i, did_one = 0;
3564 sint8 k; 3793 sint8 k;
3565 3794
3566 force = get_archetype(FORCE_NAME); 3795 force = get_archetype (FORCE_NAME);
3567 3796
3568 for (i=0; i < NUM_STATS; i++) { 3797 for (i = 0; i < NUM_STATS; i++)
3798 {
3569 k = get_attr_value(&food->stats, i); 3799 k = get_attr_value (&food->stats, i);
3570 if (k) { 3800 if (k)
3801 {
3571 set_attr_value(&force->stats, i, k); 3802 set_attr_value (&force->stats, i, k);
3572 did_one = 1; 3803 did_one = 1;
3573 } 3804 }
3574 } 3805 }
3575 3806
3576 /* check if we can protect the eater */ 3807 /* check if we can protect the eater */
3577 for (i=0; i<NROFATTACKS; i++) { 3808 for (i = 0; i < NROFATTACKS; i++)
3809 {
3578 if (food->resist[i]>0) { 3810 if (food->resist[i] > 0)
3811 {
3579 force->resist[i] = food->resist[i] / 2; 3812 force->resist[i] = food->resist[i] / 2;
3580 did_one = 1; 3813 did_one = 1;
3581 } 3814 }
3582 } 3815 }
3816
3583 if (did_one) { 3817 if (did_one)
3818 {
3584 force->speed = 0.1; 3819 force->set_speed (0.1);
3585 update_ob_speed(force);
3586 /* bigger morsel of food = longer effect time */ 3820 /* bigger morsel of food = longer effect time */
3587 force->stats.food = food->stats.food / 5; 3821 force->duration = food->stats.food / 5;
3588 SET_FLAG(force, FLAG_IS_USED_UP);
3589 SET_FLAG(force, FLAG_APPLIED); 3822 SET_FLAG (force, FLAG_APPLIED);
3590 change_abil(who, force); 3823 change_abil (who, force);
3591 insert_ob_in_ob(force, who); 3824 insert_ob_in_ob (force, who);
3592 } else {
3593 free_object(force);
3594 } 3825 }
3826 else
3827 force->destroy ();
3595 3828
3596 /* check for hp, sp change */ 3829 /* check for hp, sp change */
3597 if(food->stats.hp!=0) { 3830 if (food->stats.hp != 0)
3831 {
3598 if(QUERY_FLAG(food, FLAG_CURSED)) { 3832 if (QUERY_FLAG (food, FLAG_CURSED))
3833 {
3599 strcpy(who->contr->killer,food->name); 3834 strcpy (who->contr->killer, food->name);
3600 hit_player(who, food->stats.hp, food, AT_POISON, 1); 3835 hit_player (who, food->stats.hp, food, AT_POISON, 1);
3836 new_draw_info (NDI_UNIQUE, 0, who, "Eck!...that was poisonous!");
3837 }
3838 else
3839 {
3840 if (food->stats.hp > 0)
3841 new_draw_info (NDI_UNIQUE, 0, who, "You begin to feel better.");
3842 else
3601 new_draw_info(NDI_UNIQUE, 0,who,"Eck!...that was poisonous!"); 3843 new_draw_info (NDI_UNIQUE, 0, who, "Eck!...that was poisonous!");
3602 } else {
3603 if(food->stats.hp>0)
3604 new_draw_info(NDI_UNIQUE, 0,who,"You begin to feel better.");
3605 else
3606 new_draw_info(NDI_UNIQUE, 0,who,"Eck!...that was poisonous!");
3607 who->stats.hp += food->stats.hp; 3844 who->stats.hp += food->stats.hp;
3608 } 3845 }
3609 } 3846 }
3610 if(food->stats.sp!=0) { 3847 if (food->stats.sp != 0)
3848 {
3611 if(QUERY_FLAG(food, FLAG_CURSED)) { 3849 if (QUERY_FLAG (food, FLAG_CURSED))
3850 {
3612 new_draw_info(NDI_UNIQUE, 0,who,"You are drained of mana!"); 3851 new_draw_info (NDI_UNIQUE, 0, who, "You are drained of mana!");
3613 who->stats.sp -= food->stats.sp; 3852 who->stats.sp -= food->stats.sp;
3614 if(who->stats.sp<0) who->stats.sp=0; 3853 if (who->stats.sp < 0)
3615 } else { 3854 who->stats.sp = 0;
3855 }
3856 else
3857 {
3616 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!");
3617 who->stats.sp += food->stats.sp; 3859 who->stats.sp += food->stats.sp;
3618 /* place limit on max sp from food? */ 3860 /* place limit on max sp from food? */
3619 } 3861 }
3620 } 3862 }
3621 fix_player(who); 3863 who->update_stats ();
3622} 3864}
3623
3624 3865
3625/** 3866/**
3626 * Designed primarily to light torches/lanterns/etc. 3867 * Designed primarily to light torches/lanterns/etc.
3627 * 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
3628 * the selected object to "burn". -b.t. 3869 * the selected object to "burn". -b.t.
3629 */ 3870 */
3630 3871void
3631void apply_lighter(object *who, object *lighter) { 3872apply_lighter (object *who, object *lighter)
3873{
3632 object *item; 3874 object *item;
3633 int is_player_env=0; 3875 int is_player_env = 0;
3634 uint32 nrof;
3635 tag_t count;
3636 char item_name[MAX_BUF];
3637 3876
3638 item=find_marked_object(who); 3877 item = find_marked_object (who);
3639 if(item) { 3878 if (item)
3879 {
3640 if(lighter->last_eat && lighter->stats.food) { /* lighter gets used up */ 3880 if (lighter->last_eat && lighter->stats.food)
3881 { /* lighter gets used up */
3641 /* Split multiple lighters if they're being used up. Otherwise * 3882 /* Split multiple lighters if they're being used up. Otherwise *
3642 * one charge from each would be used up. --DAMN */ 3883 * one charge from each would be used up. --DAMN */
3643 if(lighter->nrof > 1) { 3884 if (lighter->nrof > 1)
3885 {
3644 object *oneLighter = get_object(); 3886 object *oneLighter = lighter->clone ();
3645 copy_object(lighter, oneLighter); 3887
3646 lighter->nrof -= 1; 3888 lighter->nrof -= 1;
3647 oneLighter->nrof = 1; 3889 oneLighter->nrof = 1;
3648 oneLighter->stats.food--; 3890 oneLighter->stats.food--;
3649 esrv_send_item(who, lighter); 3891 esrv_send_item (who, lighter);
3650 oneLighter=insert_ob_in_ob(oneLighter, who); 3892 oneLighter = insert_ob_in_ob (oneLighter, who);
3651 esrv_send_item(who, oneLighter); 3893 esrv_send_item (who, oneLighter);
3894 }
3652 } else { 3895 else
3653 lighter->stats.food--; 3896 lighter->stats.food--;
3654 } 3897 }
3655 3898 else if (lighter->last_eat)
3656 } else if(lighter->last_eat) { /* no charges left in lighter */ 3899 { /* no charges left in lighter */
3657 new_draw_info_format(NDI_UNIQUE, 0,who, 3900 new_draw_info_format (NDI_UNIQUE, 0, who, "You attempt to light the %s with a used up %s.", &item->name, &lighter->name);
3658 "You attempt to light the %s with a used up %s.",
3659 &item->name, &lighter->name);
3660 return; 3901 return;
3661 } 3902 }
3903
3662 /* 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?
3663 * 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
3664 * objects at once. 3906 * objects at once.
3665 */ 3907 */
3666 nrof=item->nrof;
3667 count=item->count;
3668 /* If the item is destroyed, we don't have a valid pointer to the
3669 * name object, so make a copy so the message we print out makes
3670 * some sense.
3671 */
3672 strcpy(item_name, item->name);
3673 if (who == is_player_inv(item)) is_player_env=1;
3674 3908
3909 if (who == item->in_player ())
3910 is_player_env = 1;
3911
3675 save_throw_object(item,AT_FIRE,who); 3912 save_throw_object (item, AT_FIRE, who);
3676 /* Change to check count and not freed, since the object pointer 3913
3677 * may have gotten recycled 3914 if (item->destroyed ())
3678 */ 3915 {
3679 if ((nrof != item->nrof ) || (count != item->count)) { 3916 new_draw_info_format (NDI_UNIQUE, 0, who, "You light the %s with the %s.", &item->name, &lighter->name);
3680 new_draw_info_format(NDI_UNIQUE, 0,who,
3681 "You light the %s with the %s.", &item_name, &lighter->name);
3682 /* Need to update the player so that the players glow radius 3917 /* Need to update the player so that the players glow radius
3683 * gets changed. 3918 * gets changed.
3684 */ 3919 */
3685 if (is_player_env) fix_player(who); 3920 if (is_player_env)
3921 who->update_stats ();
3922 }
3686 } else { 3923 else
3687 new_draw_info_format(NDI_UNIQUE, 0,who,
3688 "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);
3689 } 3925 }
3690 3926 else /* nothing to light */
3691 } else /* nothing to light */
3692 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.");
3693 3928
3694} 3929}
3695 3930
3696/** 3931/**
3697 * op made some mistake with a scroll, this takes care of punishment. 3932 * op made some mistake with a scroll, this takes care of punishment.
3698 * scroll_failure()- hacked directly from spell_failure 3933 * scroll_failure()- hacked directly from spell_failure
3699 */ 3934 */
3935void
3700void scroll_failure(object *op, int failure, int power) 3936scroll_failure (object *op, int failure, int power)
3701{ 3937{
3702 if(abs(failure/4)>power) power=abs(failure/4); /* set minimum effect */ 3938 if (abs (failure / 4) > power)
3939 power = abs (failure / 4); /* set minimum effect */
3703 3940
3704 if(failure<= -1&&failure > -15) {/* wonder */ 3941 if (failure <= -1 && failure > -15)
3942 { /* wonder */
3705 object *tmp; 3943 object *tmp;
3706 3944
3707 new_draw_info(NDI_UNIQUE, 0,op,"Your spell warps!."); 3945 new_draw_info (NDI_UNIQUE, 0, op, "Your spell warps!.");
3708 tmp=get_archetype(SPELL_WONDER); 3946 tmp = get_archetype (SPELL_WONDER);
3709 cast_wonder(op, op, 0, tmp); 3947 cast_wonder (op, op, 0, tmp);
3710 free_object(tmp); 3948 tmp->destroy ();
3949 }
3711 } else if (failure <= -15&&failure > -35) {/* drain mana */ 3950 else if (failure <= -15 && failure > -35)
3951 { /* drain mana */
3712 new_draw_info(NDI_UNIQUE, 0,op,"Your mana is drained!."); 3952 new_draw_info (NDI_UNIQUE, 0, op, "Your mana is drained!.");
3713 op->stats.sp -= random_roll(0, power-1, op, PREFER_LOW); 3953 op->stats.sp -= random_roll (0, power - 1, op, PREFER_LOW);
3714 if(op->stats.sp<0) op->stats.sp = 0; 3954 if (op->stats.sp < 0)
3955 op->stats.sp = 0;
3956 }
3715 } else if (settings.spell_failure_effects == TRUE) { 3957 else if (settings.spell_failure_effects == TRUE)
3958 {
3716 if (failure <= -35&&failure > -60) { /* confusion */ 3959 if (failure <= -35 && failure > -60)
3960 { /* confusion */
3717 new_draw_info(NDI_UNIQUE, 0,op,"The magic recoils on you!"); 3961 new_draw_info (NDI_UNIQUE, 0, op, "The magic recoils on you!");
3718 confuse_player(op,op,power); 3962 confuse_player (op, op, power);
3963 }
3719 } else if (failure <= -60&&failure> -70) {/* paralysis */ 3964 else if (failure <= -60 && failure > -70)
3965 { /* paralysis */
3720 new_draw_info(NDI_UNIQUE, 0,op,"The magic recoils and paralyzes " 3966 new_draw_info (NDI_UNIQUE, 0, op, "The magic recoils and paralyzes " "you!");
3721 "you!");
3722 paralyze_player(op,op,power); 3967 paralyze_player (op, op, power);
3968 }
3723 } else if (failure <= -70&&failure> -80) {/* blind */ 3969 else if (failure <= -70 && failure > -80)
3970 { /* blind */
3724 new_draw_info(NDI_UNIQUE, 0,op,"The magic recoils on you!"); 3971 new_draw_info (NDI_UNIQUE, 0, op, "The magic recoils on you!");
3725 blind_player(op,op,power); 3972 blind_player (op, op, power);
3726 } else if (failure <= -80) {/* blast the immediate area */ 3973 }
3974 else if (failure <= -80)
3975 { /* blast the immediate area */
3727 object *tmp; 3976 object *tmp;
3977
3728 tmp=get_archetype(LOOSE_MANA); 3978 tmp = get_archetype (LOOSE_MANA);
3729 cast_magic_storm(op,tmp, power); 3979 cast_magic_storm (op, tmp, power);
3730 new_draw_info(NDI_UNIQUE, 0,op,"You unlease uncontrolled mana!"); 3980 new_draw_info (NDI_UNIQUE, 0, op, "You unlease uncontrolled mana!");
3731 free_object(tmp); 3981 tmp->destroy ();
3732 } 3982 }
3733 } 3983 }
3734} 3984}
3735 3985
3986void
3736void apply_changes_to_player(object *pl, object *change) { 3987apply_changes_to_player (object *pl, object *change)
3988{
3737 int excess_stat=0; /* if the stat goes over the maximum 3989 int excess_stat = 0; /* if the stat goes over the maximum
3738 for the race, put the excess stat some 3990 for the race, put the excess stat some
3739 where else. */ 3991 where else. */
3740 3992
3741 switch (change->type) { 3993 switch (change->type)
3994 {
3742 case CLASS: { 3995 case CLASS:
3996 {
3743 living *stats = &(pl->contr->orig_stats); 3997 living *stats = &(pl->contr->orig_stats);
3744 living *ns = &(change->stats); 3998 living *ns = &(change->stats);
3745 object *walk; 3999 object *walk;
3746 int flag_change_face=1; 4000 int flag_change_face = 1;
3747 4001
3748 /* the following code assigns stats up to the stat max 4002 /* the following code assigns stats up to the stat max
3749 * for the race, and if the stat max is exceeded, 4003 * for the race, and if the stat max is exceeded,
3750 * tries to randomly reassign the excess stat 4004 * tries to randomly reassign the excess stat
3751 */ 4005 */
3752 int i,j; 4006 int i, j;
4007
3753 for(i=0;i<NUM_STATS;i++) { 4008 for (i = 0; i < NUM_STATS; i++)
4009 {
3754 sint8 stat=get_attr_value(stats,i); 4010 sint8 stat = get_attr_value (stats, i);
3755 int race_bonus = get_attr_value(&(pl->arch->clone.stats),i); 4011 int race_bonus = get_attr_value (&(pl->arch->clone.stats), i);
4012
3756 stat += get_attr_value(ns,i); 4013 stat += get_attr_value (ns, i);
3757 if(stat > 20 + race_bonus) { 4014 if (stat > 20 + race_bonus)
4015 {
3758 excess_stat++; 4016 excess_stat++;
3759 stat = 20+race_bonus; 4017 stat = 20 + race_bonus;
3760 } 4018 }
3761 set_attr_value(stats,i,stat); 4019 set_attr_value (stats, i, stat);
3762 } 4020 }
3763 4021
3764 for(j=0;excess_stat >0 && j<100;j++) {/* try 100 times to assign excess stats */ 4022 for (j = 0; excess_stat > 0 && j < 100; j++)
4023 { /* try 100 times to assign excess stats */
3765 int i = rndm(0, 6); 4024 int i = rndm (0, 6);
3766 int stat=get_attr_value(stats,i); 4025 int stat = get_attr_value (stats, i);
3767 int race_bonus = get_attr_value(&(pl->arch->clone.stats),i); 4026 int race_bonus = get_attr_value (&(pl->arch->clone.stats), i);
4027
4028 if (i == CHA)
3768 if(i==CHA) continue; /* exclude cha from this */ 4029 continue; /* exclude cha from this */
3769 if( stat < 20 + race_bonus) { 4030 if (stat < 20 + race_bonus)
4031 {
3770 change_attr_value(stats,i,1); 4032 change_attr_value (stats, i, 1);
3771 excess_stat--; 4033 excess_stat--;
3772 } 4034 }
3773 } 4035 }
3774 4036
3775 /* insert the randomitems from the change's treasurelist into 4037 /* insert the randomitems from the change's treasurelist into
3776 * the player ref: player.c 4038 * the player ref: player.c
3777 */ 4039 */
3778 if(change->randomitems!=NULL) 4040 if (change->randomitems != NULL)
3779 give_initial_items(pl,change->randomitems); 4041 give_initial_items (pl, change->randomitems);
3780 4042
3781 4043
3782 /* set up the face, for some races. */ 4044 /* set up the face, for some races. */
3783 4045
3784 /* first, look for the force object banning 4046 /* first, look for the force object banning
3785 * changing the face. Certain races never change face with class. 4047 * changing the face. Certain races never change face with class.
3786 */ 4048 */
3787 for(walk=pl->inv;walk!=NULL;walk=walk->below) 4049 for (walk = pl->inv; walk != NULL; walk = walk->below)
3788 if (!strcmp(walk->name,"NOCLASSFACECHANGE")) flag_change_face=0; 4050 if (!strcmp (walk->name, "NOCLASSFACECHANGE"))
4051 flag_change_face = 0;
3789 4052
3790 if(flag_change_face) { 4053 if (flag_change_face)
4054 {
3791 pl->animation_id = GET_ANIM_ID(change); 4055 pl->animation_id = GET_ANIM_ID (change);
3792 pl->face = change->face; 4056 pl->face = change->face;
3793 4057
3794 if(QUERY_FLAG(change,FLAG_ANIMATE)) 4058 if (QUERY_FLAG (change, FLAG_ANIMATE))
3795 SET_FLAG(pl,FLAG_ANIMATE); 4059 SET_FLAG (pl, FLAG_ANIMATE);
3796 else 4060 else
3797 CLEAR_FLAG(pl,FLAG_ANIMATE); 4061 CLEAR_FLAG (pl, FLAG_ANIMATE);
3798 } 4062 }
3799 4063
3800 /* check the special case of can't use weapons */ 4064 /* check the special case of can't use weapons */
3801 /*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); */
3802 if(!strcmp(change->name,"monk")) CLEAR_FLAG(pl,FLAG_USE_WEAPON); 4066 if (!strcmp (change->name, "monk"))
4067 CLEAR_FLAG (pl, FLAG_USE_WEAPON);
3803 4068
3804 break; 4069 break;
3805 } 4070 }
3806 } 4071 }
3807} 4072}
3808 4073
3809/** 4074/**
3814 * Change information is contained in the 'slaying' field of the marked item. 4079 * Change information is contained in the 'slaying' field of the marked item.
3815 * The format is as follow: transformer:[number ]yield[;transformer:...]. 4080 * The format is as follow: transformer:[number ]yield[;transformer:...].
3816 * This way an item can be transformed in many things, and/or many objects. 4081 * This way an item can be transformed in many things, and/or many objects.
3817 * The 'slaying' field for transformer is used as verb for the action. 4082 * The 'slaying' field for transformer is used as verb for the action.
3818 */ 4083 */
4084void
3819void apply_item_transformer( object* pl, object* transformer ) 4085apply_item_transformer (object *pl, object *transformer)
3820 { 4086{
3821 object* marked; 4087 object *marked;
3822 object* new_item; 4088 object *new_item;
3823 char* find; 4089 char *find;
3824 char* separator; 4090 char *separator;
3825 int yield; 4091 int yield;
3826 char got[ MAX_BUF ]; 4092 char got[MAX_BUF];
3827 int len; 4093 int len;
3828 4094
3829 if ( !pl || !transformer ) 4095 if (!pl || !transformer)
3830 return; 4096 return;
3831 marked = find_marked_object( pl ); 4097 marked = find_marked_object (pl);
3832 if ( !marked ) 4098 if (!marked)
3833 { 4099 {
3834 new_draw_info_format( NDI_UNIQUE, 0, pl, "Use the %s with what item?", query_name( transformer ) ); 4100 new_draw_info_format (NDI_UNIQUE, 0, pl, "Use the %s with what item?", query_name (transformer));
3835 return; 4101 return;
3836 } 4102 }
3837 if ( !marked->slaying ) 4103 if (!marked->slaying)
3838 { 4104 {
3839 new_draw_info_format( NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name( transformer ), query_name( marked ) ); 4105 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name (transformer), query_name (marked));
3840 return; 4106 return;
3841 } 4107 }
3842 /* check whether they are compatible or not */ 4108 /* check whether they are compatible or not */
3843 find = strstr( marked->slaying, transformer->arch->name ); 4109 find = strstr (marked->slaying, transformer->arch->name);
3844 if ( !find || ( *( find + strlen( transformer->arch->name ) ) != ':' ) ) 4110 if (!find || (*(find + strlen (transformer->arch->name)) != ':'))
3845 { 4111 {
3846 new_draw_info_format( NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name( transformer ), query_name( marked ) ); 4112 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't use the %s with your %s!", query_name (transformer), query_name (marked));
3847 return; 4113 return;
3848 } 4114 }
3849 find += strlen( transformer->arch->name ) + 1; 4115 find += strlen (transformer->arch->name) + 1;
3850 /* Item can be used, now find how many and what it yields */ 4116 /* Item can be used, now find how many and what it yields */
3851 if ( isdigit( *( find ) ) ) 4117 if (isdigit (*(find)))
3852 { 4118 {
3853 yield = atoi( find ); 4119 yield = atoi (find);
3854 if ( yield < 1 ) 4120 if (yield < 1)
3855 { 4121 {
3856 LOG( llevDebug, "apply_item_transformer: item %s has slaying-yield %d.", query_base_name( marked, 0 ), yield ); 4122 LOG (llevDebug, "apply_item_transformer: item %s has slaying-yield %d.", query_base_name (marked, 0), yield);
3857 yield = 1; 4123 yield = 1;
3858 } 4124 }
3859 } 4125 }
3860 else 4126 else
3861 yield = 1; 4127 yield = 1;
3862 4128
3863 while ( isdigit( *find ) ) 4129 while (isdigit (*find))
3864 find++; 4130 find++;
3865 while ( *find == ' ' ) 4131 while (*find == ' ')
3866 find++; 4132 find++;
3867 memset( got, 0, MAX_BUF ); 4133 memset (got, 0, MAX_BUF);
3868 if ( (separator = strchr( find, ';' ))!=NULL) 4134 if ((separator = strchr (find, ';')) != NULL)
3869 { 4135 {
3870 len = separator - find; 4136 len = separator - find;
3871 } 4137 }
3872 else 4138 else
3873 { 4139 {
3874 len = strlen(find); 4140 len = strlen (find);
3875 } 4141 }
3876 if ( len > MAX_BUF-1) 4142 if (len > MAX_BUF - 1)
3877 len = MAX_BUF-1; 4143 len = MAX_BUF - 1;
3878 strcpy( got, find ); 4144 strcpy (got, find);
3879 got[len] = '\0'; 4145 got[len] = '\0';
3880 4146
3881 /* Now create new item, remove used ones when required. */ 4147 /* Now create new item, remove used ones when required. */
3882 new_item = get_archetype( got ); 4148 new_item = get_archetype (got);
3883 if ( !new_item ) 4149 if (!new_item)
3884 { 4150 {
3885 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));
3886 return; 4152 return;
3887 } 4153 }
4154
3888 new_item->nrof = yield; 4155 new_item->nrof = yield;
3889 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));
3890 insert_ob_in_ob( new_item, pl ); 4157 insert_ob_in_ob (new_item, pl);
3891 esrv_send_inventory( pl, pl ); 4158 esrv_send_inventory (pl, pl);
3892 /* Eat up one item */ 4159 /* Eat up one item */
3893 decrease_ob_nr( marked, 1 ); 4160 decrease_ob_nr (marked, 1);
3894 /* Eat one transformer if needed */ 4161 /* Eat one transformer if needed */
3895 if ( transformer->stats.food ) 4162 if (transformer->stats.food)
3896 if ( --transformer->stats.food == 0 ) 4163 if (--transformer->stats.food == 0)
3897 decrease_ob_nr( transformer, 1 ); 4164 decrease_ob_nr (transformer, 1);
3898 } 4165}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines