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.4 by elmex, Tue Aug 15 16:19:55 2006 UTC vs.
Revision 1.43 by root, Tue Dec 19 05:12:52 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines