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.9 by root, Fri Aug 25 17:11:53 2006 UTC vs.
Revision 1.39 by root, Wed Dec 13 00:42:04 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines