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.14 by root, Tue Aug 29 08:01:37 2006 UTC vs.
Revision 1.43 by root, Tue Dec 19 05:12:52 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines