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.15 by elmex, Tue Aug 29 10:51:43 2006 UTC vs.
Revision 1.31 by root, Sun Dec 3 20:26:35 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines