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.8 by root, Fri Aug 25 15:21:57 2006 UTC vs.
Revision 1.38 by root, Tue Dec 12 22:37:05 2006 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines