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.18 by root, Sun Sep 3 00:18:42 2006 UTC vs.
Revision 1.38 by root, Tue Dec 12 22:37:05 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines