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.21 by pippijn, Thu Sep 7 10:01:57 2006 UTC vs.
Revision 1.51 by root, Fri Dec 22 16:34:00 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines