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.7 by elmex, Thu Aug 24 05:04:46 2006 UTC vs.
Revision 1.59 by pippijn, Sat Jan 6 14:42:30 2007 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines