1 /* $Id$ */
2 /* File: cmd3.c */
3
4 /* Purpose: Inventory commands */
5
6 /*
7 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
8 *
9 * This software may be copied and distributed for educational, research, and
10 * not for profit purposes provided that this copyright and statement are
11 * included in all such copies.
12 */
13
14 #define SERVER
15
16 #include "angband.h"
17
18
19 /* Allow fruit bats to wear body armour? [experimental, disabled] */
20 #define BATS_ALLOW_BODY
21
22
23 bool bypass_inscrption = FALSE;
24 /*
25 * Move an item from equipment list to pack
26 * Note that only one item at a time can be wielded per slot.
27 * Note that taking off an item when "full" will cause that item
28 * to fall to the ground.
29 */
inven_takeoff(int Ind,int item,int amt,bool called_from_wield)30 void inven_takeoff(int Ind, int item, int amt, bool called_from_wield) {
31 player_type *p_ptr = Players[Ind];
32 int posn; //, j;
33 object_type *o_ptr;
34 object_type tmp_obj;
35 cptr act;
36 char o_name[ONAME_LEN];
37
38
39 /* Get the item to take off */
40 o_ptr = &(p_ptr->inventory[item]);
41
42 /* Paranoia */
43 if (amt <= 0) return;
44
45 if ((!bypass_inscrption) && check_guard_inscription( o_ptr->note, 't' )) {
46 msg_print(Ind, "The item's inscription prevents it.");
47 return;
48 }
49 bypass_inscrption = FALSE;
50
51 /* Sigil (reset it) */
52 if (o_ptr->sigil) {
53 msg_print(Ind, "The sigil fades away.");
54 o_ptr->sigil = 0;
55 o_ptr->sseed = 0;
56 }
57
58 if (p_ptr->bow_brand && item == INVEN_AMMO) set_bow_brand(Ind, 0, 0, 0);
59 /* for now, if one of dual-wielded weapons is stashed away the brand fades for both..
60 could use o_ptr->xtraX to mark them specifically maybe, but also requires distinct messages, maybe too much. */
61 else if (p_ptr->brand && (item == INVEN_WIELD || /* dual-wield */
62 (item == INVEN_ARM && o_ptr->tval != TV_SHIELD))) set_brand(Ind, 0, 0, 0);
63
64 /* Verify */
65 if (amt > o_ptr->number) amt = o_ptr->number;
66
67 /* Make a copy to carry */
68 tmp_obj = *o_ptr;
69 tmp_obj.number = amt;
70
71 /* What are we "doing" with the object */
72 if (amt < o_ptr->number)
73 act = "Took off";
74 else if (item == INVEN_WIELD)
75 act = "You were wielding";
76 else if (item == INVEN_ARM)
77 act = "You were wielding";
78 else if (item == INVEN_BOW)
79 act = "You were shooting with";
80 else if (item == INVEN_LITE)
81 act = "Light source was";
82 /* Took off ammo */
83 else if (item == INVEN_AMMO)
84 act = "You were carrying in your quiver";
85 /* Took off tool */
86 else if (item == INVEN_TOOL)
87 act = "You were using";
88 else
89 act = "You were wearing";
90
91 #ifdef USE_SOUND_2010
92 sound_item(Ind, o_ptr->tval, o_ptr->sval, "takeoff_");
93 #endif
94
95 #if 0 //DSMs don't poly anymore due to cheeziness. They breathe instead.
96 /* Polymorph back */
97 /* XXX this can cause strange things for players with mimicry skill.. */
98 if ((item == INVEN_BODY) && (o_ptr->tval == TV_DRAG_ARMOR))
99 {
100 /* Well, so we gotta check if the player, in case he is a
101 mimic, is using a form that can _only_ come from the armor */
102 //if (p_ptr->pclass == CLASS_MIMIC) //Adventurers can also have mimic skill
103 //{
104 switch (o_ptr->sval)
105 {
106 case SV_DRAGON_BLACK:
107 j = race_index("Ancient black dragon"); break;
108 case SV_DRAGON_BLUE:
109 j = race_index("Ancient blue dragon"); break;
110 case SV_DRAGON_WHITE:
111 j = race_index("Ancient white dragon"); break;
112 case SV_DRAGON_RED:
113 j = race_index("Ancient red dragon"); break;
114 case SV_DRAGON_GREEN:
115 j = race_index("Ancient green dragon"); break;
116 case SV_DRAGON_MULTIHUED:
117 j = race_index("Ancient multi-hued dragon"); break;
118 case SV_DRAGON_PSEUDO:
119 j = race_index("Ethereal drake"); break;
120 //j = race_index("Pseudo dragon"); break;
121 case SV_DRAGON_SHINING:
122 j = race_index("Ethereal dragon"); break;
123 case SV_DRAGON_LAW:
124 j = race_index("Great Wyrm of Law"); break;
125 case SV_DRAGON_BRONZE:
126 j = race_index("Ancient bronze dragon"); break;
127 case SV_DRAGON_GOLD:
128 j = race_index("Ancient gold dragon"); break;
129 case SV_DRAGON_CHAOS:
130 j = race_index("Great Wyrm of Chaos"); break;
131 case SV_DRAGON_BALANCE:
132 j = race_index("Great Wyrm of Balance"); break;
133 case SV_DRAGON_POWER:
134 j = race_index("Great Wyrm of Power"); break;
135 }
136 if((p_ptr->body_monster == j) &&
137 ((p_ptr->r_killed[j] < r_info[j].level) ||
138 (r_info[j].level > get_skill_scale(p_ptr, SKILL_MIMIC, 100))))
139 do_mimic_change(Ind, 0, TRUE);
140 /*}
141 else
142 {
143 do_mimic_change(Ind, 0, TRUE);
144 }*/
145 }
146 #endif
147
148 #if POLY_RING_METHOD == 0
149 /* Polymorph back */
150 /* XXX this can cause strange things for players with mimicry skill.. */
151 if ((item == INVEN_LEFT || item == INVEN_RIGHT) && (o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_POLYMORPH))
152 {
153 if ((p_ptr->body_monster == o_ptr->pval) &&
154 ((p_ptr->r_killed[p_ptr->body_monster] < r_info[p_ptr->body_monster].level) ||
155 (get_skill_scale(p_ptr, SKILL_MIMIC, 100) < r_info[p_ptr->body_monster].level)))
156 {
157 /* If player hasn't got high enough kill count anymore now, poly back to player form! */
158 msg_print(Ind, "You polymorph back to your normal form.");
159 do_mimic_change(Ind, 0, TRUE);
160 }
161 }
162 #endif
163
164 /* Check if item gave WRAITH form */
165 if((k_info[o_ptr->k_idx].flags3 & TR3_WRAITH) && p_ptr->tim_wraith)
166 p_ptr->tim_wraith = 1;
167
168 /* Sigil (reset it) */
169 if (o_ptr->sigil) {
170 msg_print(Ind, "The sigil fades away.");
171 o_ptr->sigil = 0;
172 o_ptr->sseed = 0;
173 }
174
175 /* Artifacts */
176 if (o_ptr->name1)
177 {
178 artifact_type *a_ptr;
179 /* Obtain the artifact info */
180 if (o_ptr->name1 == ART_RANDART)
181 a_ptr = randart_make(o_ptr);
182 else
183 a_ptr = &a_info[o_ptr->name1];
184
185 if ((a_ptr->flags3 & TR3_WRAITH) && p_ptr->tim_wraith) p_ptr->tim_wraith = 1;
186 }
187
188 /* Carry the object, saving the slot it went in */
189 posn = inven_carry(Ind, &tmp_obj);
190
191 /* Handles overflow */
192 pack_overflow(Ind);
193
194
195 /* Describe the result */
196 if (amt < o_ptr->number)
197 object_desc(Ind, o_name, &tmp_obj, TRUE, 3);
198 else
199 object_desc(Ind, o_name, o_ptr, TRUE, 3);
200 msg_format(Ind, "%^s %s (%c).", act, o_name, index_to_label(posn));
201
202 if (!called_from_wield && p_ptr->prace == RACE_HOBBIT && o_ptr->tval == TV_BOOTS)
203 msg_print(Ind, "\377gYou feel more dextrous now, being barefeet.");
204
205 /* Delete (part of) it */
206 inven_item_increase(Ind, item, -amt);
207 inven_item_optimize(Ind, item);
208
209 #ifdef ENABLE_STANCES
210 /* take care of combat stances */
211 #ifndef ALLOW_SHIELDLESS_DEFENSIVE_STANCE
212 if ((item == INVEN_ARM && p_ptr->combat_stance == 1) ||
213 (item == INVEN_WIELD && p_ptr->combat_stance == 2)) {
214 #else
215 if (p_ptr->combat_stance &&
216 ((item == INVEN_ARM && !p_ptr->inventory[INVEN_WIELD].k_idx) ||
217 (item == INVEN_WIELD && (
218 !p_ptr->inventory[INVEN_ARM].k_idx || p_ptr->combat_stance == 2)))) {
219 #endif
220 msg_print(Ind, "\377sYou return to balanced combat stance.");
221 p_ptr->combat_stance = 0;
222 p_ptr->redraw |= PR_STATE;
223 }
224 #endif
225
226 /* Recalculate bonuses */
227 p_ptr->update |= (PU_BONUS);
228
229 /* Recalculate torch */
230 p_ptr->update |= (PU_TORCH);
231
232 /* Recalculate mana */
233 p_ptr->update |= (PU_MANA | PU_HP | PU_SANITY);
234
235 /* Redraw */
236 p_ptr->redraw |= (PR_PLUSSES);
237
238 /* Window stuff */
239 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
240 }
241
242
243
244
245 /*
246 * Drops (some of) an item from inventory to "near" the current location
247 */
248 void inven_drop(int Ind, int item, int amt) {
249 player_type *p_ptr = Players[Ind];
250
251 object_type *o_ptr;
252 object_type tmp_obj;
253
254 cptr act;
255 int o_idx;
256 char o_name[ONAME_LEN];
257
258 quest_info *q_ptr;
259
260 /* Access the slot to be dropped */
261 o_ptr = &(p_ptr->inventory[item]);
262
263 /* Error check */
264 if (amt <= 0) return;
265
266 /* Not too many */
267 if (amt > o_ptr->number) amt = o_ptr->number;
268
269 /* Nothing done? */
270 if (amt <= 0) return;
271
272 /* check for !d or !* in inscriptions */
273
274 if (!bypass_inscrption && check_guard_inscription(o_ptr->note, 'd')) {
275 msg_print(Ind, "The item's inscription prevents it.");
276 return;
277 }
278 bypass_inscrption = FALSE;
279
280 #ifdef USE_SOUND_2010
281 sound_item(Ind, o_ptr->tval, o_ptr->sval, "drop_");
282 #endif
283
284 /* Make a "fake" object */
285 tmp_obj = *o_ptr;
286 tmp_obj.number = amt;
287
288 /*
289 * Hack -- If rods or wands are dropped, the total maximum timeout or
290 * charges need to be allocated between the two stacks. If all the items
291 * are being dropped, it makes for a neater message to leave the original
292 * stack's pval alone. -LM-
293 */
294 if (o_ptr->tval == TV_WAND) tmp_obj.pval = divide_charged_item(o_ptr, amt);
295
296 /* What are we "doing" with the object */
297 if (amt < o_ptr->number)
298 act = "Dropped";
299 else if (item == INVEN_WIELD)
300 act = "Was wielding";
301 else if (item == INVEN_ARM)
302 act = "Was wielding";
303 else if (item == INVEN_BOW)
304 act = "Was shooting with";
305 else if (item == INVEN_LITE)
306 act = "Light source was";
307 else if (item >= INVEN_WIELD)
308 act = "Was wearing";
309 else
310 act = "Dropped";
311
312 /* Message */
313 object_desc(Ind, o_name, &tmp_obj, TRUE, 3);
314
315 #if 0 //DSMs don't poly anymore due to cheeziness. They breathe instead.
316 /* Polymorph back */
317 if ((item == INVEN_BODY) && (o_ptr->tval == TV_DRAG_ARMOR)) {
318 /* Well, so we gotta check if the player, in case he is a
319 mimic, is using a form that can _only_ come from the armor */
320 //if (p_ptr->pclass == CLASS_MIMIC) //Adventurers can also have mimic skill
321 //{
322 switch (o_ptr->sval) {
323 case SV_DRAGON_BLACK:
324 j = race_index("Ancient black dragon"); break;
325 case SV_DRAGON_BLUE:
326 j = race_index("Ancient blue dragon"); break;
327 case SV_DRAGON_WHITE:
328 j = race_index("Ancient white dragon"); break;
329 case SV_DRAGON_RED:
330 j = race_index("Ancient red dragon"); break;
331 case SV_DRAGON_GREEN:
332 j = race_index("Ancient green dragon"); break;
333 case SV_DRAGON_MULTIHUED:
334 j = race_index("Ancient multi-hued dragon"); break;
335 case SV_DRAGON_PSEUDO:
336 j = race_index("Ethereal drake"); break;
337 //j = race_index("Pseudo dragon"); break;
338 case SV_DRAGON_SHINING:
339 j = race_index("Ethereal dragon"); break;
340 case SV_DRAGON_LAW:
341 j = race_index("Great Wyrm of Law"); break;
342 case SV_DRAGON_BRONZE:
343 j = race_index("Ancient bronze dragon"); break;
344 case SV_DRAGON_GOLD:
345 j = race_index("Ancient gold dragon"); break;
346 case SV_DRAGON_CHAOS:
347 j = race_index("Great Wyrm of Chaos"); break;
348 case SV_DRAGON_BALANCE:
349 j = race_index("Great Wyrm of Balance"); break;
350 case SV_DRAGON_POWER:
351 j = race_index("Great Wyrm of Power"); break;
352 }
353 if ((p_ptr->body_monster == j) &&
354 ((p_ptr->r_killed[j] < r_info[j].level) ||
355 (r_info[j].level > get_skill_scale(p_ptr, SKILL_MIMIC, 100))))
356 do_mimic_change(Ind, 0, TRUE);
357 /*}
358 else
359 {
360 do_mimic_change(Ind, 0, TRUE);
361 }*/
362 }
363 #endif
364
365 #if POLY_RING_METHOD == 0
366 /* Polymorph back */
367 /* XXX this can cause strange things for players with mimicry skill.. */
368 if ((item == INVEN_LEFT || item == INVEN_RIGHT) &&
369 (o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_POLYMORPH)) {
370 if ((p_ptr->body_monster == o_ptr->pval) &&
371 ((p_ptr->r_killed[p_ptr->body_monster] < r_info[p_ptr->body_monster].level) ||
372 (get_skill_scale(p_ptr, SKILL_MIMIC, 100) < r_info[p_ptr->body_monster].level)))
373 {
374 /* If player hasn't got high enough kill count anymore now, poly back to player form! */
375 #if 1
376 msg_print(Ind, "You polymorph back to your normal form.");
377 do_mimic_change(Ind, 0, TRUE);
378 #endif
379 s_printf("DROP_EXPLOIT (poly): %s dropped %s\n", p_ptr->name, o_name);
380 }
381 }
382 #endif
383
384 /* Check if item gave WRAITH form */
385 if ((k_info[o_ptr->k_idx].flags3 & TR3_WRAITH) && p_ptr->tim_wraith) {
386 s_printf("DROP_EXPLOIT (wraith): %s dropped %s\n", p_ptr->name, o_name);
387 #if 1
388 p_ptr->tim_wraith = 1;
389 #endif
390 }
391
392 /* Artifacts */
393 if (o_ptr->name1) {
394 artifact_type *a_ptr;
395 /* Obtain the artifact info */
396 if (o_ptr->name1 == ART_RANDART)
397 a_ptr = randart_make(o_ptr);
398 else
399 a_ptr = &a_info[o_ptr->name1];
400
401 if ((a_ptr->flags3 & TR3_WRAITH) && p_ptr->tim_wraith) {
402 #if 1
403 p_ptr->tim_wraith = 1;
404 #endif
405 s_printf("DROP_EXPLOIT (wraith, art): %s dropped %s\n", p_ptr->name, o_name);
406 }
407 }
408
409 #ifdef ENABLE_STANCES
410 /* take care of combat stances */
411 #ifndef ALLOW_SHIELDLESS_DEFENSIVE_STANCE
412 if ((item == INVEN_ARM && p_ptr->combat_stance == 1) ||
413 (item == INVEN_WIELD && p_ptr->combat_stance == 2)) {
414 #else
415 if (p_ptr->combat_stance &&
416 ((item == INVEN_ARM && !p_ptr->inventory[INVEN_WIELD].k_idx) ||
417 (item == INVEN_WIELD && (
418 !p_ptr->inventory[INVEN_ARM].k_idx || p_ptr->combat_stance == 2)))) {
419 #endif
420 msg_print(Ind, "\377sYou return to balanced combat stance.");
421 p_ptr->combat_stance = 0;
422 p_ptr->redraw |= PR_STATE;
423 }
424 #endif
425
426 /* Message */
427 msg_format(Ind, "%^s %s (%c).", act, o_name, index_to_label(item));
428
429 /* Drop it (carefully) near the player */
430 o_idx = drop_near_severe(Ind, &tmp_obj, 0, &p_ptr->wpos, p_ptr->py, p_ptr->px);
431
432 #ifdef PLAYER_STORES
433 o_ptr = &o_list[o_idx];
434 if (o_idx > 0 && o_ptr->note && strstr(quark_str(o_ptr->note), "@S") && !o_ptr->questor
435 && inside_house(&p_ptr->wpos, o_ptr->ix, o_ptr->iy)) {
436 object_desc(0, o_name, o_ptr, TRUE, 3);
437 s_printf("PLAYER_STORE_OFFER: %s - %s (%d,%d,%d; %d,%d).\n",
438 p_ptr->name, o_name, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz,
439 o_ptr->ix, o_ptr->iy);
440 }
441 #endif
442
443 /* Reattach questors to quest */
444 if (o_ptr->questor) {
445 q_ptr = &q_info[o_ptr->quest - 1];
446 if (!q_ptr->defined || /* this quest no longer exists in q_info.txt? */
447 !q_ptr->active || /* or it's not supposed to be enabled atm? */
448 q_ptr->questors <= o_ptr->questor_idx) { /* ew */
449 s_printf("QUESTOR DEPRECATED (on drop) o_idx %d, q_idx %d.\n", o_idx, o_ptr->quest - 1);
450 o_ptr->questor = FALSE;
451 /* delete him too, maybe? */
452 } else q_ptr->questor[o_ptr->questor_idx].mo_idx = o_idx;
453 }
454
455 /* Decrease the item, optimize. */
456 inven_item_increase(Ind, item, -amt);
457 inven_item_describe(Ind, item);
458 inven_item_optimize(Ind, item);
459
460 break_cloaking(Ind, 5);
461 break_shadow_running(Ind);
462 stop_precision(Ind);
463 stop_shooting_till_kill(Ind);
464 }
465
466 /*
467 * The "wearable" tester
468 */
469 #if 1 /* new way: 'fruit bat body' is checked first: it's restrictions will be inherited by all other forms */
470 bool item_tester_hook_wear(int Ind, int slot) {
471 player_type *p_ptr = Players[Ind];
472 monster_race *r_ptr = NULL;
473 bool fishy = FALSE;
474 if (p_ptr->body_monster) {
475 r_ptr = &r_info[p_ptr->body_monster];
476 if (r_ptr->d_char == '~') fishy = TRUE;
477 }
478
479 if (p_ptr->fruit_bat) {
480 switch(slot) {
481 case INVEN_RIGHT:
482 case INVEN_LEFT:
483 case INVEN_NECK:
484 case INVEN_HEAD:
485 case INVEN_LITE:
486 #ifdef BATS_ALLOW_BODY
487 case INVEN_BODY: //allow this mayyyybe?
488 #endif
489 case INVEN_OUTER:
490 case INVEN_ARM:
491 case INVEN_TOOL: //allow them to wear, say, picks and shovels - the_sandman
492 break; //fine
493 default:
494 return FALSE; //not fine
495 }
496 }
497
498 if (p_ptr->body_monster &&
499 (p_ptr->pclass != CLASS_DRUID) &&
500 ((p_ptr->pclass != CLASS_SHAMAN) || !mimic_shaman_fulleq(r_ptr->d_char)) &&
501 (p_ptr->prace != RACE_VAMPIRE)
502 ) {
503 switch(slot) {
504 case INVEN_WIELD:
505 case INVEN_BOW:
506 if (r_ptr->body_parts[BODY_WEAPON]) return (TRUE);
507 break;
508 case INVEN_LEFT:
509 if (r_ptr->body_parts[BODY_FINGER] > 1) return (TRUE);
510 break;
511 case INVEN_RIGHT:
512 if (r_ptr->body_parts[BODY_FINGER]) return (TRUE);
513 break;
514 case INVEN_NECK:
515 case INVEN_HEAD:
516 if (r_ptr->body_parts[BODY_HEAD]) return (TRUE);
517 break;
518 case INVEN_LITE:
519 /* Always allow to carry light source? :/ */
520 /* return (TRUE); break; */
521 if (r_ptr->body_parts[BODY_WEAPON]) return (TRUE);
522 if (r_ptr->body_parts[BODY_FINGER]) return (TRUE);
523 if (r_ptr->body_parts[BODY_HEAD]) return (TRUE);
524 if (r_ptr->body_parts[BODY_ARMS]) return (TRUE);
525 break;
526 case INVEN_BODY:
527 #ifdef BATS_ALLOW_BODY
528 /* note: this check is redundant, because bats actually DO have a torso atm!
529 funnily, native fruit bat players do NOT have one without this option o_O. */
530 switch (p_ptr->body_monster) {
531 case 37: case 114: case 187: case 235: case 351:
532 case 377: case 391: case 406: case 484: case 968:
533 return TRUE;
534 }
535 #endif
536 case INVEN_OUTER:
537 case INVEN_AMMO:
538 if (r_ptr->body_parts[BODY_TORSO]) return (TRUE);
539 break;
540 case INVEN_ARM:
541 if (r_ptr->body_parts[BODY_ARMS]) return (TRUE);
542 break;
543 case INVEN_TOOL:
544 /* make a difference :) - C. Blue */
545 if (r_ptr->body_parts[BODY_ARMS] ||
546 // r_ptr->body_parts[BODY_FINGER] ||
547 r_ptr->body_parts[BODY_WEAPON]) return (TRUE);
548 break;
549 case INVEN_HANDS:
550 if (fishy) return FALSE;
551 // if (r_ptr->body_parts[BODY_FINGER]) return (TRUE); too silyl (and powerful)
552 // if (r_ptr->body_parts[BODY_ARMS]) return (TRUE); was standard, but now:
553 if (r_ptr->body_parts[BODY_FINGER] && r_ptr->body_parts[BODY_ARMS]) return (TRUE);
554 break;
555 case INVEN_FEET:
556 if (r_ptr->body_parts[BODY_LEGS]) return (TRUE);
557 break;
558 }
559 }
560
561 /* Check for a usable slot */
562 else if (slot >= INVEN_WIELD) return (TRUE);
563
564 /* Assume not wearable */
565 return (FALSE);
566 }
567
568 #else // old way, deprecated
569
570 bool item_tester_hook_wear(int Ind, int slot) {
571 player_type *p_ptr = Players[Ind];
572 monster_race *r_ptr = NULL;
573 bool fishy = FALSE;
574 if (p_ptr->body_monster) {
575 r_ptr = &r_info[p_ptr->body_monster];
576 if (r_ptr->d_char == '~') fishy = TRUE;
577 }
578
579 /*
580 * Hack -- restrictions by forms
581 * I'm not quite sure if wielding 6 rings and 3 weps should be allowed..
582 * Shapechanging Druids do not get penalized...
583
584 * Another hack for shamans (very experimental):
585 * They can use their full equipment in E and G (spirit/elemental/ghost) form.
586 *
587 * Druid bats can't wear full eq.
588 */
589 #if 0
590 if (p_ptr->body_monster &&
591 ((p_ptr->pclass != CLASS_DRUID) || p_ptr->fruit_bat) &&
592 ((p_ptr->pclass != CLASS_SHAMAN) || !mimic_shaman_fulleq(r_ptr->d_char)) &&
593 ((p_ptr->prace != RACE_VAMPIRE) || p_ptr->fruit_bat)
594 )
595 #else
596 if (p_ptr->body_monster &&
597 (p_ptr->pclass != CLASS_DRUID) &&
598 ((p_ptr->pclass != CLASS_SHAMAN) || !mimic_shaman_fulleq(r_ptr->d_char)) &&
599 (p_ptr->prace != RACE_VAMPIRE)
600 )
601 #endif
602 {
603 switch(slot) {
604 case INVEN_WIELD:
605 case INVEN_BOW:
606 if (r_ptr->body_parts[BODY_WEAPON]) return (TRUE);
607 break;
608 case INVEN_LEFT:
609 if (r_ptr->body_parts[BODY_FINGER] > 1) return (TRUE);
610 break;
611 case INVEN_RIGHT:
612 if (r_ptr->body_parts[BODY_FINGER]) return (TRUE);
613 break;
614 case INVEN_NECK:
615 case INVEN_HEAD:
616 if (r_ptr->body_parts[BODY_HEAD]) return (TRUE);
617 break;
618 case INVEN_LITE:
619 /* Always allow to carry light source? :/ */
620 /* return (TRUE); break; */
621 if (r_ptr->body_parts[BODY_WEAPON]) return (TRUE);
622 if (r_ptr->body_parts[BODY_FINGER]) return (TRUE);
623 if (r_ptr->body_parts[BODY_HEAD]) return (TRUE);
624 if (r_ptr->body_parts[BODY_ARMS]) return (TRUE);
625 break;
626 case INVEN_BODY:
627 #ifdef BATS_ALLOW_BODY
628 /* note: this check is redundant, because bats actually DO have a torso atm!
629 funnily, native fruit bat players do NOT have one without this option o_O. */
630 switch (p_ptr->body_monster) {
631 case 37: case 114: case 187: case 235: case 351:
632 case 377: case 391: case 406: case 484: case 968:
633 return TRUE;
634 }
635 #endif
636 case INVEN_OUTER:
637 case INVEN_AMMO:
638 if (r_ptr->body_parts[BODY_TORSO]) return (TRUE);
639 break;
640 case INVEN_ARM:
641 if (r_ptr->body_parts[BODY_ARMS]) return (TRUE);
642 break;
643 case INVEN_TOOL:
644 /* make a difference :) - C. Blue */
645 if (r_ptr->body_parts[BODY_ARMS] ||
646 // r_ptr->body_parts[BODY_FINGER] ||
647 r_ptr->body_parts[BODY_WEAPON]) return (TRUE);
648 break;
649 case INVEN_HANDS:
650 if (fishy) return FALSE;
651 // if (r_ptr->body_parts[BODY_FINGER]) return (TRUE); too silyl (and powerful)
652 // if (r_ptr->body_parts[BODY_ARMS]) return (TRUE); was standard, but now:
653 if (r_ptr->body_parts[BODY_FINGER] && r_ptr->body_parts[BODY_ARMS]) return (TRUE);
654 break;
655 case INVEN_FEET:
656 if (r_ptr->body_parts[BODY_LEGS]) return (TRUE);
657 break;
658 }
659 }
660 /* Restrict fruit bats */
661 #if 0
662 else if (p_ptr->fruit_bat && !p_ptr->body_monster)
663 #else
664 else if (p_ptr->fruit_bat && (
665 !p_ptr->body_monster ||
666 p_ptr->pclass == CLASS_DRUID ||
667 (p_ptr->pclass == CLASS_SHAMAN && !mimic_shaman_fulleq(r_ptr->d_char)) ||
668 p_ptr->prace != RACE_VAMPIRE
669 ))
670 #endif
671 {
672 switch(slot) {
673 case INVEN_RIGHT:
674 case INVEN_LEFT:
675 case INVEN_NECK:
676 case INVEN_HEAD:
677 case INVEN_LITE:
678 #ifdef BATS_ALLOW_BODY
679 case INVEN_BODY: //allow this mayyyybe?
680 #endif
681 case INVEN_OUTER:
682 case INVEN_ARM:
683 case INVEN_TOOL: //allow them to wear, say, picks and shovels - the_sandman
684 return TRUE;
685 }
686 }
687 #if 0
688 else if (r_info[p_ptr->body_monster].flags3 & RF3_DRAGON) {
689 switch(slot) {
690 case INVEN_WIELD:
691 case INVEN_RIGHT:
692 case INVEN_LEFT:
693 case INVEN_HEAD:
694 case INVEN_BODY:
695 case INVEN_LITE:
696 case INVEN_FEET:
697 return TRUE;
698 }
699 }
700 #endif
701 /* non-fruit bats */
702 else {
703 /* Check for a usable slot */
704 if (slot >= INVEN_WIELD) {
705 #if 0
706 /* use of shield is banned in do_cmd_wield if with 2H weapon.
707 * 3 slots are too severe.. thoughts? - Jir -
708 */
709 if (slot == INVEN_BOW && p_ptr->inventory[INVEN_WIELD].k_idx) {
710 u32b f1, f2, f3, f4, f5, f6, esp;
711 object_flags(&p_ptr->inventory[INVEN_WIELD], &f1, &f2, &f3, &f4, &f5, &f6, &esp);
712 if (f4 & TR4_MUST2H) return(FALSE);
713 }
714 #endif // 0
715 return (TRUE);
716 }
717 }
718
719 /* Assume not wearable */
720 return (FALSE);
721 }
722 #endif
723
724 /* Take off things that are no more wearable */
725 void do_takeoff_impossible(int Ind) {
726 int k;
727 player_type *p_ptr = Players[Ind];
728 object_type *o_ptr;
729 u32b f1, f2, f3, f4, f5, f6, esp;
730
731
732 bypass_inscrption = TRUE;
733 for (k = INVEN_WIELD; k < INVEN_TOTAL; k++) {
734 o_ptr = &p_ptr->inventory[k];
735 if ((o_ptr->k_idx) && /* following is a hack for dual-wield.. */
736 (!item_tester_hook_wear(Ind, (k == INVEN_ARM && o_ptr->tval != TV_SHIELD) ? INVEN_WIELD : k)))
737 {
738 /* Extract the flags */
739 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
740
741 /* Morgie crown and The One Ring resists! */
742 if (f3 & TR3_PERMA_CURSE) continue;
743
744 /* Ahah TAKE IT OFF ! */
745 inven_takeoff(Ind, k, 255, FALSE);
746 }
747 /* new: also redisplay empty slots as '(unavailable)' after a form change, if they are */
748 if (!o_ptr->k_idx) Send_equip_availability(Ind, k);
749 }
750 bypass_inscrption = FALSE;
751 }
752
753 /*
754 * Wield or wear a single item from the pack or floor
755 * Added alt_slots to specify an alternative slot when an item fits in
756 * two places - C. Blue
757 * 0 = equip in first free slot that fits, if none is free, replace item in first slot (standard/traditional behaviour)
758 * 1 = equip in first slot that fits, replacing the item if any
759 * 2 = equip in second slot that fits, replacing the item if any
760 * 4 = don't equip if slot is already occupied (ie don't replace by taking off an item)
761 * Note: Rings make an exception in 4: First ring always goes in second ring slot.
762 */
763 void do_cmd_wield(int Ind, int item, u16b alt_slots) {
764 player_type *p_ptr = Players[Ind];
765
766 int slot, num = 1;
767 bool item_fits_dual = FALSE, equip_fits_dual = TRUE, all_cursed = FALSE;
768 bool slot1 = (p_ptr->inventory[INVEN_WIELD].k_idx != 0);
769 bool slot2 = (p_ptr->inventory[INVEN_ARM].k_idx != 0);
770 bool alt = ((alt_slots & 0x2) != 0);
771
772 bool ma_warning_weapon = FALSE, ma_warning_shield = FALSE, hobbit_warning = FALSE;
773
774 object_type tmp_obj;
775 object_type *o_ptr;
776 object_type *x_ptr;
777
778 cptr act;
779
780 char o_name[ONAME_LEN];
781 u32b f1 = 0 , f2 = 0 , f3 = 0, f4 = 0, f5, f6 = 0, esp = 0;
782 bool highlander = FALSE, warn_takeoff = FALSE;
783
784
785 /* Restrict the choices */
786 /*item_tester_hook = item_tester_hook_wear;*/
787
788
789 /* Get the item (in the pack) */
790 if (item >= 0) {
791 o_ptr = &(p_ptr->inventory[item]);
792 } else { /* Get the item (on the floor) */
793 if (-item >= o_max)
794 return; /* item doesn't exist */
795
796 o_ptr = &o_list[0 - item];
797 }
798
799 /* erase any interrupting inscriptions on Highlander amulets */
800 if (o_ptr->tval == TV_AMULET &&
801 (o_ptr->sval == SV_AMULET_HIGHLANDS || o_ptr->sval == SV_AMULET_HIGHLANDS2)) {
802 o_ptr->note = 0;
803 highlander = TRUE;
804 }
805
806 if (check_guard_inscription(o_ptr->note, 'w')) {
807 msg_print(Ind, "The item's inscription prevents it.");
808 return;
809 }
810
811 /* Check the slot */
812 slot = wield_slot(Ind, o_ptr);
813
814 if (!item_tester_hook_wear(Ind, slot)) {
815 msg_print(Ind, "You may not wield that item.");
816 return;
817 }
818
819 if (!can_use_verbose(Ind, o_ptr)) return;
820
821 /* Costumes allowed during halloween and xmas */
822 if (!season_halloween && !season_xmas) {
823 if ((o_ptr->tval == TV_SOFT_ARMOR) && (o_ptr->sval == SV_COSTUME)) {
824 msg_print(Ind, "It's not that time of the year anymore.");
825 return;
826 }
827 }
828
829 /* Extract the flags */
830 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
831
832 /* check whether the item to wield is fit for dual-wielding */
833 if ((o_ptr->weight <= DUAL_MAX_WEIGHT) &&
834 !(f4 & (TR4_MUST2H | TR4_SHOULD2H))) item_fits_dual = TRUE;
835 /* check whether our current equipment allows a dual-wield setup with the new item */
836 if (slot1 && (k_info[p_ptr->inventory[INVEN_WIELD].k_idx].flags4 & (TR4_MUST2H | TR4_SHOULD2H)))
837 equip_fits_dual = FALSE;
838
839 /* Do we have dual-wield and are trying to equip a weapon?.. */
840 if (get_skill(p_ptr, SKILL_DUAL) && slot == INVEN_WIELD) {
841 #if 0
842 /* Equip in arm slot if weapon slot alreay occupied but arm slot still empty */
843 if ((p_ptr->inventory[INVEN_WIELD].k_idx || (alt_slots & 0x2))
844 && (!p_ptr->inventory[INVEN_ARM].k_idx || (alt_slots & 0x2))
845 && !(alt_slots & 0x1)
846 /* If to-wield weapon is 2h or 1.5h, choose normal INVEN_WIELD slot instead */
847 && item_fits_dual
848 /* If main-hand weapon is 2h or 1.5h, choose normal INVEN_WIELD slot instead */
849 && equip_fits_dual)
850 slot = INVEN_ARM;
851 #else /* fix: allow 'W' to replace main hand if second hand is empty */
852 /* Equip in arm slot if weapon slot alreay occupied but arm slot still empty */
853 if (((!slot1 && alt) || (slot2 && alt) || (slot1 && !slot2 && !alt)) &&
854 !(alt_slots & 0x1) &&
855 /* If to-wield weapon is 2h or 1.5h, choose normal INVEN_WIELD slot instead */
856 item_fits_dual &&
857 /* If main-hand weapon is 2h or 1.5h, choose normal INVEN_WIELD slot instead */
858 equip_fits_dual)
859 slot = INVEN_ARM;
860 #endif
861 }
862
863 /* to allow only right ring -> only right ring: */
864 if (slot == INVEN_LEFT && (alt_slots & 0x2)) slot = INVEN_RIGHT;
865 /* to allow no rings -> left ring: */
866 else if (slot == INVEN_RIGHT && (alt_slots & 0x2)) slot = INVEN_LEFT;
867
868 /* use the first fitting slot found? (unused) */
869 if (slot == INVEN_RIGHT && (alt_slots & 0x1)) slot = INVEN_LEFT;
870
871 if ((alt_slots & 0x4) && p_ptr->inventory[slot].k_idx) {
872 object_desc(Ind, o_name, &(p_ptr->inventory[slot]), FALSE, 0);
873 msg_format(Ind, "Take off your %s first.", o_name);
874 return;
875 }
876
877 /* Prevent wielding into a cursed slot */
878 /* Try alternative slots if one is cursed and item can go in multiple places */
879 if (cursed_p(&p_ptr->inventory[slot]) && !(alt_slots & 0x3)) {
880 switch (slot) {
881 case INVEN_LEFT: slot = INVEN_RIGHT; all_cursed = TRUE; break;
882 case INVEN_RIGHT: slot = INVEN_LEFT; all_cursed = TRUE; break;
883 case INVEN_WIELD: if (get_skill(p_ptr, SKILL_DUAL) && item_fits_dual && equip_fits_dual) { slot = INVEN_ARM; all_cursed = TRUE; break; }
884 }
885 }
886 if (cursed_p(&(p_ptr->inventory[slot]))) {
887 /* Describe it */
888 object_desc(Ind, o_name, &(p_ptr->inventory[slot]), FALSE, 0);
889
890 /* Message */
891 if (all_cursed)
892 msg_format(Ind, "The items you are already %s both appear to be cursed.", describe_use(Ind, slot));
893 else
894 msg_format(Ind, "The %s you are %s appears to be cursed.", o_name, describe_use(Ind, slot));
895
896 /* Cancel the command */
897 return;
898 }
899
900 /* Two handed weapons can't be wielded with a shield */
901 /* TODO: move to item_tester_hook_wear? */
902 #if 0
903 if ((is_slot_ok(slot - INVEN_WIELD + INVEN_ARM)) &&
904 (f4 & TR4_MUST2H) &&
905 (inventory[slot - INVEN_WIELD + INVEN_ARM].k_idx != 0))
906 #endif // 0
907
908 if ((f4 & TR4_MUST2H) &&
909 (p_ptr->inventory[INVEN_ARM].k_idx != 0))
910 {
911 #if 1 /* a) either give error msg, or.. */
912 object_desc(Ind, o_name, o_ptr, FALSE, 0);
913 if (get_skill(p_ptr, SKILL_DUAL))
914 msg_format(Ind, "You cannot wield your %s with a shield or a secondary weapon.", o_name);
915 else
916 msg_format(Ind, "You cannot wield your %s with a shield.", o_name);
917 return;
918 #else /* b) take off the left-hand item too */
919 /* important note: can't enable this like this, because it's NOT FINISHED:
920 after taking off the shield/2nd weapon, item letters in inventory will
921 CHANGE and the WRONG item will be equipped. - C. Blue */
922 return;
923 if (check_guard_inscription(p_ptr->inventory[INVEN_ARM].note, 't' )) {
924 msg_print(Ind, "Your second wielded item's inscription prevents taking it off.");
925 return;
926 };
927 if (cursed_p(&p_ptr->inventory[INVEN_ARM]) && !is_admin(p_ptr)) {
928 msg_print(Ind, "Hmmm, the second item you're wielding seems to be cursed.");
929 return;
930 }
931 inven_takeoff(Ind, INVEN_ARM, 255, TRUE);
932 #endif
933 }
934 if ((f4 & TR4_SHOULD2H) &&
935 (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) /* dual-wield not with 1.5h */
936 {
937 object_desc(Ind, o_name, o_ptr, FALSE, 0);
938 msg_format(Ind, "You cannot wield your %s with a secondary weapon.", o_name);
939 return;
940 }
941
942 // if (is_slot_ok(slot - INVEN_ARM + INVEN_WIELD)) {
943 // i_ptr = &inventory[slot - INVEN_ARM + INVEN_WIELD];
944 if (o_ptr->tval == TV_SHIELD && (x_ptr = &p_ptr->inventory[INVEN_WIELD])) {
945 /* Extract the flags */
946 object_flags(x_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
947
948 /* Prevent shield from being put on if wielding 2H */
949 if ((f4 & TR4_MUST2H) && (x_ptr->k_idx) )
950 // (p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM))
951 {
952 object_desc(Ind, o_name, o_ptr, FALSE, 0);
953 msg_format(Ind, "You cannot wield your %s with a two-handed weapon.", o_name);
954 return;
955 }
956 }
957
958
959 x_ptr = &(p_ptr->inventory[slot]);
960
961 if (x_ptr->tval != TV_AMULET ||
962 (x_ptr->sval != SV_AMULET_HIGHLANDS && x_ptr->sval != SV_AMULET_HIGHLANDS2))
963 highlander = FALSE;
964
965 if (check_guard_inscription(x_ptr->note, 't') && !highlander) {
966 msg_print(Ind, "The inscription of your equipped item prevents it.");
967 return;
968 };
969
970
971 #if 0
972 /* Verify potential overflow */
973 if ((p_ptr->inven_cnt >= INVEN_PACK) &&
974 ((item < 0) || (o_ptr->number > 1)))
975 {
976 /* Verify with the player */
977 if (other_query_flag &&
978 !get_check(Ind, "Your pack may overflow. Continue? ")) return;
979 }
980 #endif
981
982 #ifdef USE_SOUND_2010
983 sound_item(Ind, o_ptr->tval, o_ptr->sval, "wearwield_");
984 #endif
985
986 /* Mega-hack -- prevent anyone but total winners from wielding the Massive Iron
987 * Crown of Morgoth or the Mighty Hammer 'Grond'.
988 */
989 if (!(p_ptr->total_winner || is_admin(p_ptr))) {
990 /* Attempting to wear the crown if you are not a winner is a very, very bad thing
991 * to do.
992 */
993 if (o_ptr->name1 == ART_MORGOTH) {
994 msg_print(Ind, "You are blasted by the Crown's power!");
995 /* This should pierce invulnerability */
996 bypass_invuln = TRUE;
997 take_hit(Ind, 10000, "the Massive Iron Crown of Morgoth", 0);
998 bypass_invuln = FALSE;
999 return;
1000 }
1001 /* Attempting to wield Grond isn't so bad. */
1002 if (o_ptr->name1 == ART_GROND) {
1003 msg_print(Ind, "You are far too weak to wield the mighty Grond.");
1004 return;
1005 }
1006 }
1007
1008 /* display some warnings if the item will severely conflict with Martial Arts skill */
1009 if (get_skill(p_ptr, SKILL_MARTIAL_ARTS)) {
1010 if ((is_weapon(o_ptr->tval) ||
1011 #ifndef ENABLE_MA_BOOMERANG
1012 o_ptr->tval == TV_BOOMERANG ||
1013 #endif
1014 o_ptr->tval == TV_BOW)
1015 #ifndef ENABLE_MA_BOOMERANG
1016 && !p_ptr->inventory[INVEN_BOW].k_idx
1017 #else
1018 && p_ptr->inventory[INVEN_BOW].tval != TV_BOW
1019 #endif
1020 && !p_ptr->inventory[INVEN_WIELD].k_idx
1021 && (!p_ptr->inventory[INVEN_ARM].k_idx || p_ptr->inventory[INVEN_ARM].tval == TV_SHIELD)) /* for dual-wielders */
1022 ma_warning_weapon = TRUE;
1023 else if (o_ptr->tval == TV_SHIELD &&
1024 (!p_ptr->inventory[INVEN_ARM].k_idx || p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) /* for dual-wielders */
1025 ma_warning_shield = TRUE;
1026 }
1027
1028 process_hooks(HOOK_WIELD, "d", Ind);
1029
1030 /* Let's not end afk for this - C. Blue */
1031 /* un_afk_idle(Ind); */
1032
1033 /* Take a turn */
1034 p_ptr->energy -= level_speed(&p_ptr->wpos);
1035
1036 /* for Hobbits wearing boots -> give message */
1037 if (p_ptr->prace == RACE_HOBBIT &&
1038 o_ptr->tval == TV_BOOTS && !p_ptr->inventory[slot].k_idx) {
1039 hobbit_warning = TRUE;
1040 }
1041
1042 /* Get a copy of the object to wield */
1043 tmp_obj = *o_ptr;
1044
1045 if (slot == INVEN_AMMO) num = o_ptr->number;
1046 tmp_obj.number = num;
1047
1048 /* Decrease the item (from the pack) */
1049 if (item >= 0) {
1050 inven_item_increase(Ind, item, -num);
1051 inven_item_optimize(Ind, item);
1052 }
1053 /* Decrease the item (from the floor) */
1054 else {
1055 floor_item_increase(0 - item, -num);
1056 floor_item_optimize(0 - item);
1057 }
1058
1059 /* Access the wield slot */
1060 o_ptr = &(p_ptr->inventory[slot]);
1061
1062 /*** Could make procedure "inven_wield()" ***/
1063 //no need to try to combine the non esp HL amulet?
1064 if (highlander) {
1065 o_ptr->to_h += tmp_obj.to_h;
1066 o_ptr->to_d += tmp_obj.to_d;
1067 o_ptr->to_a += tmp_obj.to_a;
1068 o_ptr->bpval += tmp_obj.bpval; /* this is normal, when it is generated via invcopy() */
1069 o_ptr->pval += tmp_obj.pval; /* unused, except if it was wished for */
1070 msg_print(Ind, "\377GThe amulets merge into one!");
1071 } else {
1072
1073 #if 0
1074 /* Take off the "entire" item if one is there */
1075 if (p_ptr->inventory[slot].k_idx) inven_takeoff(Ind, slot, 255, TRUE);
1076 #else // 0
1077 /* Take off existing item */
1078 if (slot != INVEN_AMMO) {
1079 if (o_ptr->k_idx) {
1080 /* Take off existing item */
1081 (void)inven_takeoff(Ind, slot, 255, TRUE);
1082 }
1083 } else {
1084 if (o_ptr->k_idx) {
1085 /* !M inscription tolerates different +hit / +dam enchantments,
1086 which will be merged and averaged in object_absorb.
1087 However, this doesn't work for cursed items or artefacts. - C. Blue */
1088 if (!object_similar(Ind, o_ptr, &tmp_obj, 0x1)) {
1089 /* Take off existing item */
1090 (void)inven_takeoff(Ind, slot, 255, TRUE);
1091 } else {
1092 // tmp_obj.number += o_ptr->number;
1093 object_absorb(Ind, &tmp_obj, o_ptr);
1094 }
1095 }
1096 }
1097 #endif // 0
1098
1099 /* Wear the new stuff */
1100 *o_ptr = tmp_obj;
1101
1102 /* Increase the weight */
1103 p_ptr->total_weight += o_ptr->weight * num;
1104
1105 /* Increment the equip counter by hand */
1106 p_ptr->equip_cnt++;
1107
1108 /* Where is the item now */
1109 switch (slot) {
1110 case INVEN_WIELD:
1111 act = "You are wielding";
1112 if (p_ptr->brand) set_brand(Ind, 0, 0, 0); /* actually only applies for dual-wield */
1113 break;
1114 case INVEN_ARM:
1115 act = "You are wielding";
1116 if (p_ptr->brand && o_ptr->tval != TV_SHIELD) set_brand(Ind, 0, 0, 0); /* dual-wield */
1117 break;
1118 case INVEN_BOW: act = "You are shooting with"; break;
1119 case INVEN_LITE: act = "Your light source is"; break;
1120 case INVEN_AMMO: act = "In your quiver you have"; break;
1121 case INVEN_TOOL: act = "You are using"; break;
1122 default: act = "You are wearing";
1123 }
1124
1125 /* Describe the result */
1126 object_desc(Ind, o_name, o_ptr, TRUE, 3);
1127
1128 /* Message */
1129 msg_format(Ind, "%^s %s (%c).", act, o_name, index_to_label(slot));
1130
1131 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1132
1133 /* Auto Curse */
1134 if (f3 & TR3_AUTO_CURSE) {
1135 /* The object recurse itself ! */
1136 o_ptr->ident |= ID_CURSED;
1137 }
1138
1139 /* Cursed! */
1140 if (cursed_p(o_ptr)) {
1141 /* Warn the player */
1142 msg_print(Ind, "Oops! It feels deathly cold!");
1143
1144 /* Note the curse */
1145 o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
1146
1147 note_toggle_cursed(o_ptr, TRUE);
1148 }
1149
1150 }
1151
1152 /* already done elsewhere */
1153 //if (slot == INVEN_WIELD && o_ptr->k_idx && (k_info[o_ptr->k_idx].flags4 & TR4_MUST2H)) Send_equip_availability(Ind, INVEN_ARM);
1154
1155 #ifdef ENABLE_STANCES
1156 /* take care of combat stances */
1157 if (slot == INVEN_ARM && p_ptr->combat_stance == 2) {
1158 msg_print(Ind, "\377sYou return to balanced combat stance.");
1159 p_ptr->combat_stance = 0;
1160 p_ptr->redraw |= PR_STATE;
1161 }
1162 #endif
1163
1164 /* Only warn about wrong ammo type at the very beginning (for archers, who carry one of each type) */
1165 if (!p_ptr->warning_ammotype && slot == INVEN_AMMO
1166 && p_ptr->inventory[INVEN_BOW].tval == TV_BOW) {
1167 switch (o_ptr->tval) {
1168 case TV_SHOT:
1169 if (p_ptr->inventory[INVEN_BOW].sval != SV_SLING)
1170 msg_print(Ind, "\377yYou need a sling to fire pebbles or shots.");
1171 break;
1172 case TV_ARROW:
1173 if (p_ptr->inventory[INVEN_BOW].sval != SV_SHORT_BOW &&
1174 p_ptr->inventory[INVEN_BOW].sval != SV_LONG_BOW)
1175 msg_print(Ind, "\377yYou need a bow to fire arrows.");
1176 break;
1177 case TV_BOLT:
1178 if (p_ptr->inventory[INVEN_BOW].sval != SV_LIGHT_XBOW &&
1179 p_ptr->inventory[INVEN_BOW].sval != SV_HEAVY_XBOW)
1180 msg_print(Ind, "\377yYou need a crossbow to fire bolts.");
1181 break;
1182 }
1183 }
1184
1185 /* Give additional warning messages if item prevents a certain ability */
1186 if (o_ptr->tval == TV_SHIELD) {
1187 if (get_skill(p_ptr, SKILL_DODGE))
1188 msg_print(Ind, "\377yYou cannot dodge attacks while wielding a shield.");
1189 if (get_skill(p_ptr, SKILL_MARTIAL_ARTS))
1190 msg_print(Ind, "\377yYou cannot use special martial art styles with a shield.");
1191 /* cannot use ranged techniques with a shield equipped */
1192 if (p_ptr->ranged_flare) {
1193 p_ptr->ranged_flare = 0;
1194 msg_print(Ind, "You dispose of the flare missile.");
1195 }
1196 if (p_ptr->ranged_precision) {
1197 p_ptr->ranged_precision = 0;
1198 msg_print(Ind, "You stop aiming overly precisely.");
1199 }
1200 if (p_ptr->ranged_double) {
1201 p_ptr->ranged_double = 0;
1202 msg_print(Ind, "You stop using double-shots.");
1203 }
1204 if (p_ptr->ranged_barrage) {
1205 p_ptr->ranged_barrage = 0;
1206 msg_print(Ind, "You stop preparations for barrage.");
1207 }
1208 }
1209
1210 /* display warnings, possibly */
1211 if (ma_warning_weapon && p_ptr->warning_ma_weapon == 0) {
1212 #ifndef ENABLE_MA_BOOMERANG
1213 msg_print(Ind, "\374\377RWarning: Using any sort of weapon renders Martial Arts skill effectless.");
1214 #else
1215 msg_print(Ind, "\374\377RWarning: Using any melee weapon or bow renders Martial Arts skill effectless.");
1216 #endif
1217 // s_printf("warning_ma_weapon: %s\n", p_ptr->name);
1218 warn_takeoff = TRUE;
1219
1220 /* might find esp-weapon at non-low levels, so stop spamming this warning then */
1221 if (p_ptr->lev >= 15) p_ptr->warning_ma_weapon = 1;
1222 }
1223 if (ma_warning_shield && p_ptr->warning_ma_shield == 0) {
1224 msg_print(Ind, "\374\377RWarning: Using a shield will prevent Martial Arts combat styles.");
1225 // s_printf("warning_ma_shield: %s\n", p_ptr->name);
1226 warn_takeoff = TRUE;
1227
1228 /* might find esp-shield at non-low levels, so stop spamming this warning then */
1229 if (p_ptr->lev >= 15) p_ptr->warning_ma_shield = 1;
1230 }
1231 if (warn_takeoff) msg_print(Ind, "\374\377R Press 't' key to take off your weapons or shield.");
1232
1233 if (hobbit_warning) msg_print(Ind, "\377yYou feel somewhat less dextrous than when barefeet.");
1234
1235 /* Recalculate bonuses */
1236 p_ptr->update |= (PU_BONUS);
1237
1238 /* Recalculate torch */
1239 p_ptr->update |= (PU_TORCH);
1240
1241 /* Recalculate mana */
1242 p_ptr->update |= (PU_MANA | PU_HP | PU_SANITY);
1243
1244 /* Redraw */
1245 p_ptr->redraw |= (PR_PLUSSES | PR_ARMOR);
1246
1247 /* Window stuff */
1248 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
1249
1250 /* warning messages, mostly for newbies */
1251 if (p_ptr->warning_bpr3 == 0 && slot == INVEN_WIELD)
1252 p_ptr->warning_bpr3 = 2;
1253 }
1254
1255
1256
1257 /*
1258 * Take off an item
1259 */
1260 void do_cmd_takeoff(int Ind, int item, int amt) {
1261 player_type *p_ptr = Players[Ind];
1262 object_type *o_ptr;
1263
1264 if (amt <= 0) return;
1265
1266 #if 0
1267 /* Verify potential overflow */
1268 if (p_ptr->inven_cnt >= INVEN_PACK) {
1269 /* Verify with the player */
1270 if (other_query_flag &&
1271 !get_check(Ind, "Your pack may overflow. Continue? ")) return;
1272 }
1273 #endif
1274
1275
1276 /* Get the item (in the pack) */
1277 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
1278 /* Get the item (on the floor) */
1279 else {
1280 if (-item >= o_max) return; /* item doesn't exist */
1281 o_ptr = &o_list[0 - item];
1282 }
1283
1284 if (check_guard_inscription( o_ptr->note, 'T' )) {
1285 msg_print(Ind, "The item's inscription prevents it.");
1286 return;
1287 }
1288
1289 /* Item is cursed */
1290 if (cursed_p(o_ptr) && !is_admin(p_ptr)) {
1291 /* Oops */
1292 msg_print(Ind, "Hmmm, it seems to be cursed.");
1293 /* Nope */
1294 return;
1295 }
1296
1297 /* Let's not end afk for this - C. Blue */
1298 /* un_afk_idle(Ind); */
1299
1300 /* Take a partial turn */
1301 p_ptr->energy -= level_speed(&p_ptr->wpos) / 2;
1302
1303 /* Take off the item */
1304 inven_takeoff(Ind, item, amt, FALSE);
1305 }
1306
1307
1308 /*
1309 * Drop an item
1310 */
1311 void do_cmd_drop(int Ind, int item, int quantity) {
1312 player_type *p_ptr = Players[Ind];
1313
1314 object_type *o_ptr;
1315 u32b f1, f2, f3, f4, f5, f6, esp;
1316
1317 /* Get the item (in the pack) */
1318 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
1319 /* Get the item (on the floor) */
1320 else {
1321 if (-item >= o_max) return; /* item doesn't exist */
1322 o_ptr = &o_list[0 - item];
1323 }
1324
1325 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1326
1327 #ifdef IDDC_NO_TRADE_CHEEZE /* new anti-cheeze hack: abuse NR_tradable for this */
1328 if (in_irondeepdive(&p_ptr->wpos) && o_ptr->NR_tradable) {
1329 msg_format(Ind, "\377yYou may not drop items you brought from outside this dungeon until you reach at least floor %d.", IDDC_NO_TRADE_CHEEZE);
1330 return;
1331 }
1332 #endif
1333
1334 /* Handle the newbies_cannot_drop option */
1335 #if (STARTEQ_TREATMENT == 1)
1336 if (p_ptr->max_plv < cfg.newbies_cannot_drop && !is_admin(p_ptr) &&
1337 o_ptr->tval != TV_GAME && o_ptr->tval != TV_KEY && o_ptr->tval != TV_SPECIAL) {
1338 if (p_ptr->rogue_like_commands)
1339 msg_print(Ind, "\377yYou are not experienced enough to drop items. (Destroy it with '\377oCTRL+d\377y' or sell it instead.)");
1340 else
1341 msg_print(Ind, "\377yYou are not experienced enough to drop items. (Destroy it with '\377ok\377y' or sell it instead.)");
1342 return;
1343 }
1344 #endif
1345
1346 if (check_guard_inscription(o_ptr->note, 'd')) {
1347 msg_print(Ind, "The item's inscription prevents it.");
1348 return;
1349 };
1350
1351 /* Cannot remove cursed items */
1352 if (cursed_p(o_ptr) && !is_admin(p_ptr)) { /* Hack -- DM can */
1353 if ((item >= INVEN_WIELD) ) {
1354 /* Oops */
1355 msg_print(Ind, "Hmmm, it seems to be cursed.");
1356 /* Nope */
1357 return;
1358 } else if (f4 & TR4_CURSE_NO_DROP) {
1359 /* Oops */
1360 msg_print(Ind, "Hmmm, you seem to be unable to drop it.");
1361 /* Nope */
1362 return;
1363 }
1364 }
1365 if (o_ptr->questor) {
1366 if (p_ptr->rogue_like_commands)
1367 msg_print(Ind, "\377yYou can't drop this item. Use '\377oCTRL+d\377y' to destroy it. (Might abandon the quest!)");
1368 else
1369 msg_print(Ind, "\377yYou cannot drop this item. Use '\377ok\377y' to destroy it. (Might abandon the quest!)");
1370 return;
1371 }
1372
1373 if (p_ptr->inval) {
1374 if (p_ptr->rogue_like_commands)
1375 msg_print(Ind, "\377yYou may not drop items, wait for an admin to validate your account. (Destroy it with '\377oCTRL+d\377y' or sell it instead.)");
1376 else
1377 msg_print(Ind, "\377yYou may not drop items, wait for an admin to validate your account. (Destroy it with '\377ok\377y' or sell it instead.)");
1378 return;
1379 }
1380
1381 #if 0
1382 /* Mega-Hack -- verify "dangerous" drops */
1383 if (cave[p_ptr->dun_depth][p_ptr->py][p_ptr->px].o_idx) {
1384 /* XXX XXX Verify with the player */
1385 if (other_query_flag &&
1386 !get_check(Ind, "The item may disappear. Continue? ")) return;
1387 }
1388 #endif
1389
1390 if (object_known_p(Ind, o_ptr)) {
1391 #if 0 /* would prevent ppl from getting rid of unsellable artifacts */
1392 if (true_artifact_p(o_ptr) && !is_admin(p_ptr) &&
1393 ((cfg.anti_arts_hoard && undepositable_artifact_p(o_ptr)) || (p_ptr->total_winner && !winner_artifact_p(o_ptr) && cfg.kings_etiquette))) {
1394 msg_print(Ind, "\377yThis item is a true artifact and cannot be dropped!");
1395 return;
1396 }
1397 #endif
1398 if (p_ptr->wpos.wz == 0 && /* Assume houses are always on surface */
1399 undepositable_artifact_p(o_ptr)) {
1400 if (inside_house(&p_ptr->wpos, p_ptr->px, p_ptr->py)) {
1401 if (cfg.anti_arts_house) {
1402 msg_print(Ind, "\377yThis item is a true artifact and cannot be dropped in a house!");
1403 return;
1404 }
1405 } else //if (!istown(&p_ptr->wpos))
1406 msg_print(Ind, "\377RWarning! If you leave this map sector, the artifact will likely disappear!");
1407 }
1408 }
1409
1410 /* stop littering inns */
1411 if (o_ptr->level == 0 && o_ptr->owner == p_ptr->id && istown(&p_ptr->wpos) &&
1412 !exceptionally_shareable_item(o_ptr) && o_ptr->tval != TV_GAME &&
1413 !(o_ptr->tval == TV_PARCHMENT && (o_ptr->sval == SV_DEED_HIGHLANDER || o_ptr->sval == SV_DEED_DUNGEONKEEPER))) {
1414 msg_print(Ind, "\377yPlease don't litter the town with level 0 items which are unusable");
1415 if (p_ptr->rogue_like_commands)
1416 msg_print(Ind, "\377y by other players. Use '\377oCTRL+d\377y' to destroy an item instead.");
1417 else
1418 msg_print(Ind, "\377y by other players. Use '\377ok\377y' to destroy an item instead.");
1419 if (!is_admin(p_ptr)) return;
1420 }
1421
1422 /* Let's not end afk for this - C. Blue */
1423 /* un_afk_idle(Ind); */
1424
1425 #if (STARTEQ_TREATMENT > 1)
1426 #ifndef RPG_SERVER
1427 if (o_ptr->owner == p_ptr->id && p_ptr->max_plv < cfg.newbies_cannot_drop && !is_admin(p_ptr) &&
1428 o_ptr->tval != TV_GAME && o_ptr->tval != TV_KEY && o_ptr->tval != TV_SPECIAL)
1429 o_ptr->level = 0;
1430 #else
1431 if (o_ptr->owner == p_ptr->id && p_ptr->max_plv < 2 && !is_admin(p_ptr) &&
1432 o_ptr->tval != TV_GAME && o_ptr->tval != TV_KEY && o_ptr->tval != TV_SPECIAL)
1433 o_ptr->level = 0;
1434 #endif
1435 #endif
1436
1437 /* Take a partial turn */
1438 p_ptr->energy -= level_speed(&p_ptr->wpos) / 2;
1439
1440 /* Drop (some of) the item */
1441 inven_drop(Ind, item, quantity);
1442 }
1443
1444
1445 /*
1446 * Drop some gold
1447 */
1448 void do_cmd_drop_gold(int Ind, s32b amt) {
1449 player_type *p_ptr = Players[Ind];
1450
1451 object_type tmp_obj;
1452
1453 /* Handle the newbies_cannot_drop option */
1454 if ((p_ptr->max_plv < cfg.newbies_cannot_drop) && !is_admin(p_ptr)) {
1455 msg_print(Ind, "You are not experienced enough to drop gold.");
1456 return;
1457 }
1458
1459 if (p_ptr->inval) {
1460 msg_print(Ind, "You may not drop gold, wait for an admin to validate your account.");
1461 return;
1462 }
1463
1464 /* Error checks */
1465 if (amt > p_ptr->au) {
1466 amt = p_ptr->au;
1467 /* msg_print(Ind, "You do not have that much gold.");
1468 return;
1469 */
1470 }
1471 if (amt <= 0) return;
1472
1473 /* Setup the object */
1474 /* XXX Use "gold" object kind */
1475 // invcopy(&tmp_obj, 488);
1476
1477 /* hack: player-dropped piles are bigger at same value, than normal money drops ;) */
1478 invcopy(&tmp_obj, gold_colour(amt, FALSE, TRUE));
1479
1480 /* Setup the "worth" */
1481 tmp_obj.pval = amt;
1482 tmp_obj.xtra1 = 1; //mark as 'compact' gold pile
1483
1484 /* Hack -- 'own' the gold */
1485 tmp_obj.owner = p_ptr->id;
1486
1487 /* Non-everlasting can't take money from everlasting
1488 and vice versa, depending on server cfg. */
1489 tmp_obj.mode = p_ptr->mode;
1490
1491 /* Drop it */
1492 drop_near(&tmp_obj, 0, &p_ptr->wpos, p_ptr->py, p_ptr->px);
1493
1494 /* Subtract from the player's gold */
1495 p_ptr->au -= amt;
1496
1497 /* Let's not end afk for this - C. Blue */
1498 /* un_afk_idle(Ind); */
1499
1500 /* Message */
1501 // msg_format(Ind, "You drop %d pieces of gold.", amt);
1502 msg_format(Ind, "You drop %d pieces of %s.", amt, k_name + k_info[tmp_obj.k_idx].name);
1503
1504 #ifdef USE_SOUND_2010
1505 sound(Ind, "drop_gold", NULL, SFX_TYPE_COMMAND, FALSE);
1506 #endif
1507
1508 /* #if DEBUG_LEVEL > 3 */
1509 // if (amt >= 10000) {
1510 p_ptr->last_gold_drop += amt;
1511 if (turn - p_ptr->last_gold_drop_timer >= cfg.fps * 2) {
1512 s_printf("Gold dropped (%d by %s at %d,%d,%d).\n", p_ptr->last_gold_drop, p_ptr->name, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
1513 p_ptr->last_gold_drop = 0;
1514 p_ptr->last_gold_drop_timer = turn;
1515 }
1516 // }
1517
1518 break_cloaking(Ind, 5);
1519 break_shadow_running(Ind);
1520 stop_precision(Ind);
1521 stop_shooting_till_kill(Ind);
1522
1523 /* Redraw gold */
1524 p_ptr->redraw |= (PR_GOLD);
1525
1526 /* Window stuff */
1527 p_ptr->window |= (PW_PLAYER);
1528
1529 /* Take a turn */
1530 p_ptr->energy -= level_speed(&p_ptr->wpos);
1531 }
1532
1533
1534 /*
1535 * Destroy an item
1536 */
1537 void do_cmd_destroy(int Ind, int item, int quantity) {
1538 player_type *p_ptr = Players[Ind];
1539 int old_number;
1540 //bool force = FALSE;
1541 object_type *o_ptr;
1542 char o_name[ONAME_LEN];
1543 u32b f1, f2, f3, f4, f5, f6, esp;
1544
1545 /* Get the item (in the pack) */
1546 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
1547 /* Get the item (on the floor) */
1548 else {
1549 if (-item >= o_max) return; /* item doesn't exist */
1550 o_ptr = &o_list[0 - item];
1551 }
1552
1553 /* Describe the object */
1554 old_number = o_ptr->number;
1555 o_ptr->number = quantity;
1556 object_desc(Ind, o_name, o_ptr, TRUE, 3);
1557 o_ptr->number = old_number;
1558
1559 if (check_guard_inscription( o_ptr->note, 'k')) {
1560 msg_print(Ind, "The item's inscription prevents it.");
1561 return;
1562 };
1563 #if 0
1564 /* Verify if needed */
1565 if (!force || other_query_flag) {
1566 /* Make a verification */
1567 snprintf(out_val, sizeof(out_val), "Really destroy %s? ", o_name);
1568 if (!get_check(Ind, out_val)) return;
1569 }
1570 #endif
1571
1572 /* Let's not end afk for this - C. Blue */
1573 /* un_afk_idle(Ind); */
1574
1575 /* Take a turn */
1576 p_ptr->energy -= level_speed(&p_ptr->wpos);
1577
1578 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1579
1580 if ((((f4 & TR4_CURSE_NO_DROP) && cursed_p(o_ptr)) ||
1581 (o_ptr->questor && o_ptr->questor_invincible))
1582 && !is_admin(p_ptr)) {
1583 /* Oops */
1584 msg_print(Ind, "Hmmm, you seem to be unable to destroy it.");
1585
1586 /* Nope */
1587 return;
1588 }
1589 #ifndef FUN_SERVER /* while server is being hacked, allow this (while /wish is also allowed) - C. Blue */
1590 /* Artifacts cannot be destroyed */
1591 if (like_artifact_p(o_ptr) && !is_admin(p_ptr)) {
1592 cptr feel = "special";
1593
1594 /* Message */
1595 msg_format(Ind, "You cannot destroy %s.", o_name);
1596
1597 /* Hack -- Handle icky artifacts */
1598 if (cursed_p(o_ptr) || broken_p(o_ptr)) feel = "terrible";
1599
1600 /* Hack -- inscribe the artifact */
1601 o_ptr->note = quark_add(feel);
1602
1603 /* We have "felt" it (again) */
1604 o_ptr->ident |= (ID_SENSE | ID_SENSED_ONCE | ID_SENSE_HEAVY);
1605
1606 /* Combine the pack */
1607 p_ptr->notice |= (PN_COMBINE);
1608
1609 /* Window stuff */
1610 p_ptr->window |= (PW_INVEN | PW_EQUIP);
1611
1612 /* Done */
1613 return;
1614 }
1615 #endif
1616 /* Keys cannot be destroyed */
1617 if (o_ptr->tval == TV_KEY && !is_admin(p_ptr)) {
1618 /* Message */
1619 msg_format(Ind, "You cannot destroy %s.", o_name);
1620
1621 /* Done */
1622 return;
1623 }
1624
1625 /* Cursed, equipped items cannot be destroyed */
1626 if (item >= INVEN_WIELD && cursed_p(o_ptr) && !is_admin(p_ptr)) {
1627 /* Message */
1628 msg_print(Ind, "Hmm, that seems to be cursed.");
1629
1630 /* Done */
1631 return;
1632 }
1633
1634 /* Polymorph back */
1635 /* XXX this can cause strange things for players with mimicry skill.. */
1636 if ((item == INVEN_LEFT || item == INVEN_RIGHT) && (o_ptr->tval == TV_RING) && (o_ptr->sval == SV_RING_POLYMORPH)) {
1637 if ((p_ptr->body_monster == o_ptr->pval) &&
1638 ((p_ptr->r_killed[p_ptr->body_monster] < r_info[p_ptr->body_monster].level) ||
1639 (get_skill_scale(p_ptr, SKILL_MIMIC, 100) < r_info[p_ptr->body_monster].level)))
1640 {
1641 /* If player hasn't got high enough kill count anymore now, poly back to player form! */
1642 #if 1
1643 msg_print(Ind, "You polymorph back to your normal form.");
1644 do_mimic_change(Ind, 0, TRUE);
1645 #endif
1646 s_printf("DESTROY_EXPLOIT (poly): %s destroyed %s\n", p_ptr->name, o_name);
1647 }
1648 }
1649
1650 /* Check if item gave WRAITH form */
1651 if((k_info[o_ptr->k_idx].flags3 & TR3_WRAITH) && p_ptr->tim_wraith) {
1652 s_printf("DESTROY_EXPLOIT (wraith): %s destroyed %s\n", p_ptr->name, o_name);
1653 #if 1
1654 p_ptr->tim_wraith = 1;
1655 #endif
1656 }
1657
1658 /* Message */
1659 msg_format(Ind, "You destroy %s.", o_name);
1660
1661 #ifdef USE_SOUND_2010
1662 // sound_item(Ind, o_ptr->tval, o_ptr->sval, "kill_");
1663 #endif
1664
1665 if (true_artifact_p(o_ptr)) handle_art_d(o_ptr->name1);
1666 questitem_d(o_ptr, quantity);
1667
1668 if (o_ptr->tval == TV_WAND) (void)divide_charged_item(o_ptr, quantity);
1669
1670 /* Eliminate the item (from the pack) */
1671 if (item >= 0) {
1672 inven_item_increase(Ind, item, -quantity);
1673 inven_item_describe(Ind, item);
1674 inven_item_optimize(Ind, item);
1675 }
1676 /* Eliminate the item (from the floor) */
1677 else {
1678 floor_item_increase(0 - item, -quantity);
1679 floor_item_describe(0 - item);
1680 floor_item_optimize(0 - item);
1681 }
1682
1683 break_cloaking(Ind, 5);
1684 break_shadow_running(Ind);
1685 stop_precision(Ind);
1686 stop_shooting_till_kill(Ind);
1687 }
1688
1689
1690 /*
1691 * Observe an item which has been *identify*-ed
1692 */
1693 void do_cmd_observe(int Ind, int item) {
1694 player_type *p_ptr = Players[Ind];
1695 object_type *o_ptr;
1696
1697 /* Get the item (in the pack) */
1698 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
1699 /* Get the item (on the floor) */
1700 else {
1701 if (-item >= o_max) return; /* item doesn't exist */
1702 o_ptr = &o_list[0 - item];
1703 }
1704
1705 /* Require full knowledge */
1706 if (!(o_ptr->ident & ID_MENTAL) && !is_admin(p_ptr)) observe_aux(Ind, o_ptr);
1707 /* Describe it fully */
1708 else if (!identify_fully_aux(Ind, o_ptr, FALSE)) msg_print(Ind, "You see nothing special.");
1709 }
1710
1711
1712
1713 /*
1714 * Remove the inscription from an object
1715 * XXX Mention item (when done)?
1716 */
1717 void do_cmd_uninscribe(int Ind, int item)
1718 {
1719 player_type *p_ptr = Players[Ind];
1720 object_type *o_ptr;
1721
1722
1723 /* Get the item (in the pack) */
1724 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
1725 /* Get the item (on the floor) */
1726 else {
1727 if (-item >= o_max)
1728 return; /* item doesn't exist */
1729
1730 o_ptr = &o_list[0 - item];
1731 }
1732
1733 /* Nothing to remove */
1734 if (!o_ptr->note) {
1735 msg_print(Ind, "That item had no inscription to remove.");
1736 return;
1737 }
1738
1739 /* small hack, make shirt logos permanent */
1740 if (o_ptr->tval == TV_SOFT_ARMOR && o_ptr->sval == SV_SHIRT && !is_admin(p_ptr)) {
1741 msg_print(Ind, "Cannot uninscribe shirts.");
1742 return;
1743 }
1744 if ((o_ptr->tval == TV_SPECIAL ||
1745 (o_ptr->tval == TV_SCROLL && o_ptr->sval == SV_SCROLL_CHEQUE)
1746 ) && !is_admin(p_ptr)) {
1747 msg_print(Ind, "Cannot uninscribe this item.");
1748 return;
1749 }
1750
1751 /* Message */
1752 msg_print(Ind, "Inscription removed.");
1753
1754 /* Remove the incription */
1755 o_ptr->note = 0;
1756 o_ptr->note_utag = 0;
1757
1758 /* Combine the pack */
1759 p_ptr->notice |= (PN_COMBINE);
1760
1761 /* Window stuff */
1762 p_ptr->window |= (PW_INVEN | PW_EQUIP);
1763 }
1764
1765
1766 /*
1767 * Inscribe an object with a comment
1768 */
1769 void do_cmd_inscribe(int Ind, int item, cptr inscription) {
1770 player_type *p_ptr = Players[Ind];
1771 object_type *o_ptr;
1772 char o_name[ONAME_LEN], modins[MAX_CHARS];
1773 const char *qins;
1774 char *c;
1775
1776
1777 /* Get the item (in the pack) */
1778 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
1779 /* Get the item (on the floor) */
1780 else {
1781 if (-item >= o_max)
1782 return; /* item doesn't exist */
1783
1784 o_ptr = &o_list[0 - item];
1785 }
1786
1787 /* small hack, make shirt logos permanent */
1788 if (o_ptr->tval == TV_SOFT_ARMOR && o_ptr->sval == SV_SHIRT && !is_admin(p_ptr)) {
1789 msg_print(Ind, "Cannot inscribe shirts.");
1790 return;
1791 }
1792 if ((o_ptr->tval == TV_SPECIAL ||
1793 (o_ptr->tval == TV_SCROLL && o_ptr->sval == SV_SCROLL_CHEQUE)
1794 ) && !is_admin(p_ptr)) {
1795 msg_print(Ind, "Cannot inscribe this item.");
1796 return;
1797 }
1798
1799 /* Describe the activity */
1800 object_desc(Ind, o_name, o_ptr, TRUE, 3);
1801
1802 /* Message */
1803 msg_format(Ind, "Inscribing %s.", o_name);
1804 msg_print(Ind, NULL);
1805
1806 /* small hack to prevent using colour codes in inscriptions:
1807 convert \{ to just {, compare nserver.c:Send_special_line()!
1808 Note: Colour codes in inscriptions/item names aren't implemented anyway. */
1809 if (!is_admin(p_ptr)) while ((c = strstr(inscription, "\\{")))
1810 c[0] = '{';
1811
1812 /* hack to fix auto-inscriptions: convert empty inscription to a #-type inscription */
1813 if (inscription[0] == '\0') inscription = "#";
1814
1815 /* Comfort hack for reinscribing items:
1816 Trigger with '\' as first character.
1817 Then replace the part starting on first letter, until an usual delimiter char is found.
1818 '\@@' or '\!!' will erase the corresponding tag from the inscription. */
1819 /* catch empty item inscription */
1820 if (!o_ptr->note && inscription[0] == '\\') {
1821 /* cannot delete anything in an empty inscription */
1822 if ((inscription[1] == '@' || inscription[1] == '!' || inscription [1] == '#')
1823 && inscription[2] == inscription[1])
1824 return;
1825 /* clear '\' special feature trigger */
1826 while (inscription[0] == '\\') inscription++;
1827 }
1828 if (inscription[0] == '\\') {
1829 bool append = TRUE;
1830 char modsrc[3];
1831
1832 qins = quark_str(o_ptr->note);
1833 strcpy(modins, qins);
1834
1835 modsrc[0] = inscription[1];
1836 /* search for specific @-tag to replace? */
1837 if (inscription[1] == '@') {
1838 /* duplicate tag, aka "delete!" ? */
1839 if (inscription[2] == '@') modsrc[1] = inscription[3];
1840 /* normal tag (replace or append) */
1841 else modsrc[1] = inscription[2];
1842 modsrc[2] = 0;
1843 }
1844 /* search for first !-tag to replace? */
1845 else modsrc[1] = 0;
1846
1847 /* append or replace a @/!/# part? */
1848 if (inscription[1] == '@' || inscription[1] == '!' || inscription [1] == '#') {
1849 char *start = strstr(modins, modsrc);
1850 bool delete = FALSE;
1851
1852 /* delete? */
1853 if (inscription[2] == inscription[1]) {
1854 delete = TRUE;
1855 /* definitely don't append: in case tag does not exist yet */
1856 append = FALSE;
1857 }
1858
1859 /* replace? (or delete) */
1860 if (start) {
1861 const char *delimiter;
1862 const char *deltmp;
1863
1864 append = FALSE;
1865
1866 /* after '#' the line is always completely replaced;
1867 same for @P because player names can contain spaces. */
1868 if (inscription[1] != '#' &&
1869 !(inscription[1] == '@' && inscription[2] == 'P')) {
1870 deltmp = qins + (start - modins) + strlen(modsrc);
1871 while (*deltmp) {
1872 delimiter = strchr(" @!#", *deltmp);
1873 if (delimiter) break;
1874 deltmp++;
1875 }
1876 //if (!delimiter) delimiter = qins + strlen(qins); //point to zero terminator char
1877 } else deltmp = qins + strlen(qins);
1878 //delimiter = qins + strlen(qins); //point to zero terminator char
1879
1880 if (delete) strcpy(start, deltmp);
1881 else { /* try to replace */
1882 //if ((start - modins) + strlen(inscription + 1) + strlen(delimiter) > MAX_CHARS) {
1883 if ((start - modins) + strlen(inscription + 1) + strlen(deltmp) > MAX_CHARS) {
1884 msg_print(Ind, "Inscription would become too long.");
1885 return;
1886 }
1887
1888 /* replace */
1889 strcpy(start, inscription + 1);
1890 //strcat(start, delimiter);
1891 strcat(start, deltmp);
1892 }
1893 }
1894
1895 /* new: trim trailing spaces, if anything was deleted */
1896 if (delete) while (modins[strlen(modins) - 1] == ' ') modins[strlen(modins) - 1] = 0;
1897 }
1898 /* append? */
1899 if (append) {
1900 if (strlen(modins) + strlen(inscription) > MAX_CHARS) {
1901 msg_print(Ind, "Inscription would become too long.");
1902 return;
1903 }
1904 strcat(modins, inscription + 1);
1905 }
1906 inscription = modins;
1907 }
1908
1909 /* Save the inscription */
1910 o_ptr->note = quark_add(inscription);
1911 o_ptr->note_utag = 0;
1912
1913 /* Combine the pack */
1914 p_ptr->notice |= (PN_COMBINE);
1915
1916 /* Window stuff */
1917 p_ptr->window |= (PW_INVEN | PW_EQUIP);
1918 }
1919
1920
1921 /*
1922 * Steal an object from a monster
1923 */
1924 /*
1925 * This is quite abusable.. you can rob Wormie, leave the floor, and
1926 * you'll meet him again and again... so I stop implementing this.
1927 * - Jir -
1928 */
1929 void do_cmd_steal_from_monster(int Ind, int dir)
1930 {
1931 #if 0
1932 player_type *p_ptr = Players[Ind], *q_ptr;
1933 cave_type **zcave;
1934 int x, y, dir = 0, item = -1, k = -1;
1935 cave_type *c_ptr;
1936 monster_type *m_ptr;
1937 object_type *o_ptr, forge;
1938 byte num = 0;
1939 bool done = FALSE;
1940 int monst_list[23];
1941
1942 if(!(zcave = getcave(&p_ptr->wpos))) return;
1943
1944 /* Ghosts cannot steal ; not in WRAITHFORM */
1945 if (p_ptr->ghost || p_ptr->tim_wraith) {
1946 msg_print(Ind, "You cannot steal things!");
1947 return;
1948 }
1949
1950
1951 /* Only works on adjacent monsters */
1952 if (!get_rep_dir(&dir)) return;
1953 y = py + ddy[dir];
1954 x = px + ddx[dir];
1955 c_ptr = &cave[y][x];
1956
1957 if (!(c_ptr->m_idx)) {
1958 msg_print("There is no monster there!");
1959 return;
1960 }
1961
1962 m_ptr = &m_list[c_ptr->m_idx];
1963
1964 break_shadow_running(Ind);
1965 stop_precision(Ind);
1966 stop_shooting_till_kill(Ind);
1967
1968 /* There were no non-gold items */
1969 if (!m_ptr->hold_o_idx) {
1970 msg_print("That monster has no objects!");
1971 return;
1972 }
1973
1974 #if 0
1975 /* not in WRAITHFORM */
1976 if (p_ptr->tim_wraith) {
1977 msg_print("You can't grab anything!");
1978 return;
1979 }
1980
1981 /* The monster is immune */
1982 if (r_info[m_ptr->r_idx].flags7 & (RF7_NO_THEFT)) {
1983 msg_print("The monster is guarding the treasures.");
1984 return;
1985 }
1986
1987 screen_save();
1988
1989 num = show_monster_inven(c_ptr->m_idx, monst_list);
1990
1991 /* Repeat until done */
1992 while (!done) {
1993 char tmp_val[80];
1994 char which = ' ';
1995
1996 /* Build the prompt */
1997 strnfmt(tmp_val, MAX_CHARS, "Choose an item to steal (a-%c) or ESC:",
1998 'a' - 1 + num);
1999
2000 /* Show the prompt */
2001 prt(tmp_val, 0, 0);
2002
2003 /* Get a key */
2004 which = inkey();
2005
2006 /* Parse it */
2007 switch (which) {
2008 case ESCAPE:
2009 done = TRUE;
2010 break;
2011
2012 default:
2013 int ver;
2014
2015 /* Extract "query" setting */
2016 ver = isupper(which);
2017 which = tolower(which);
2018
2019 k = islower(which) ? A2I(which) : -1;
2020 if (k < 0 || k >= num) {
2021 bell();
2022 break;
2023 }
2024
2025 /* Verify the item */
2026 if (ver && !verify("Try", 0 - monst_list[k])) {
2027 done = TRUE;
2028 break;
2029 }
2030
2031 /* Accept that choice */
2032 item = monst_list[k];
2033 done = TRUE;
2034
2035 break;
2036 }
2037 }
2038 #endif // 0
2039
2040 /* S(he) is no longer afk */
2041 un_afk_idle(Ind);
2042
2043 if (item != -1) {
2044 int chance;
2045
2046 chance = 40 - p_ptr->stat_ind[A_DEX];
2047 chance +=
2048 o_list[item].weight / (get_skill_scale(SKILL_STEALING, 19) + 1);
2049 chance += get_skill_scale(SKILL_STEALING, 29) + 1;
2050 chance -= (m_ptr->csleep) ? 10 : 0;
2051 chance += m_ptr->level;
2052
2053 /* Failure check */
2054 if (rand_int(chance) > 1 + get_skill_scale(SKILL_STEALING, 25)) {
2055 /* Take a turn */
2056 energy_use = 100;
2057
2058 /* Wake up */
2059 m_ptr->csleep = 0;
2060
2061 /* Speed up because monsters are ANGRY when you try to thief them */
2062 if (m_ptr->mspeed < m_ptr->speed + 15)
2063 m_ptr->mspeed += 5; m_ptr->speed += 5;
2064 screen_load();
2065 break_cloaking(Ind, 0);
2066 msg_print("Oops ! The monster is now really *ANGRY*.");
2067 return;
2068 }
2069
2070 /* Reconnect the objects list */
2071 if (num == 1) m_ptr->hold_o_idx = 0;
2072 else {
2073 if (k > 0) o_list[monst_list[k - 1]].next_o_idx = monst_list[k + 1];
2074 if (k + 1 >= num) o_list[monst_list[k - 1]].next_o_idx = 0;
2075 if (k == 0) m_ptr->hold_o_idx = monst_list[k + 1];
2076 }
2077
2078 /* Rogues gain some xp */
2079 if (PRACE_FLAGS(PR1_EASE_STEAL)) {
2080 s32b max_point;
2081
2082 /* Max XP gained from stealing */
2083 max_point = (o_list[item].weight / 2) + (m_ptr->level * 10);
2084
2085 /* Randomise it a bit, with half a max guaranteed */
2086 if (!(p_ptr->mode & MODE_PVP)) gain_exp((max_point / 2) + (randint(max_point) / 2));
2087
2088 /* Allow escape */
2089 if (get_check("Phase door?")) teleport_player(Ind, 10, TRUE);
2090 }
2091
2092 /* Get the item */
2093 o_ptr = &forge;
2094
2095 /* Special handling for gold */
2096 if (o_list[item].tval == TV_GOLD) {
2097 gain_au(Ind, o_ptr->pval, FALSE, FALSE);
2098 p_ptr->window |= (PW_PLAYER);
2099 } else {
2100 object_copy(o_ptr, &o_list[item]);
2101 inven_carry(o_ptr, FALSE);
2102 }
2103
2104 /* Delete it */
2105 invwipe(&o_list[item]);
2106 }
2107
2108 screen_load();
2109
2110 /* Take a turn */
2111 energy_use = 100;
2112 #endif // 0
2113 }
2114
2115
2116 /*
2117 * Attempt to steal from another player
2118 */
2119 /* TODO: Make it possible to steal from monsters.. */
2120 void do_cmd_steal(int Ind, int dir) {
2121 player_type *p_ptr = Players[Ind], *q_ptr;
2122 cave_type *c_ptr;
2123
2124 int success, notice;
2125 bool caught = FALSE;
2126 cave_type **zcave;
2127 u16b dal;
2128 bool etiquette;
2129
2130 if (!(zcave = getcave(&p_ptr->wpos))) return;
2131
2132 /* May not steal from yourself */
2133 if (!dir || dir == 5) return;
2134
2135 /* Ghosts cannot steal */
2136 /* not in WRAITHFORM either */
2137 if (p_ptr->ghost || p_ptr->tim_wraith) {
2138 msg_print(Ind, "You cannot steal things!");
2139 return;
2140 }
2141
2142 /* Make sure we have enough room */
2143 if (p_ptr->inven_cnt >= INVEN_PACK) {
2144 msg_print(Ind, "You have no room to steal anything.");
2145 return;
2146 }
2147
2148 /* Examine target grid */
2149 c_ptr = &zcave[p_ptr->py + ddy[dir]][p_ptr->px + ddx[dir]];
2150
2151 /* May only steal from players */
2152 if (c_ptr->m_idx >= 0) {
2153 msg_print(Ind, "You see nothing there to steal from.");
2154 return;
2155 }
2156 else if (c_ptr->m_idx > 0) {
2157 do_cmd_steal_from_monster(Ind, dir);
2158 return;
2159 }
2160
2161 /* IDDC - don't get exp */
2162 if ((p_ptr->mode & MODE_DED_IDDC) && !in_irondeepdive(&p_ptr->wpos)) {
2163 msg_print(Ind, "You cannot steal from someone or your life would be forfeit.");
2164 return;
2165 }
2166
2167 if (p_ptr->inval) {
2168 msg_print(Ind, "You cannot steal from other players without a valid account.");
2169 return;
2170 }
2171
2172 if (p_ptr->max_plv < cfg.newbies_cannot_drop) {
2173 msg_format(Ind, "You cannot steal from other players until you are level %d.", cfg.newbies_cannot_drop);
2174 return;
2175 }
2176
2177 /* Examine target */
2178 q_ptr = Players[0 - c_ptr->m_idx];
2179 etiquette =
2180 ((cfg.fallenkings_etiquette && q_ptr->once_winner && !q_ptr->total_winner) ||
2181 (cfg.kings_etiquette && q_ptr->total_winner)) ||
2182 ((cfg.fallenkings_etiquette && p_ptr->once_winner && !p_ptr->total_winner) ||
2183 (cfg.kings_etiquette && p_ptr->total_winner));
2184
2185 /* No transactions from different mode */
2186 if (compat_pmode(Ind, 0 - c_ptr->m_idx, FALSE)) {
2187 msg_format(Ind, "You cannot steal from %s players.", compat_pmode(Ind, 0 - c_ptr->m_idx, FALSE));
2188 return;
2189 }
2190
2191 /* Small delay to prevent crazy steal-spam */
2192 if (p_ptr->pstealing) {
2193 msg_print(Ind, "You're still not calm enough to steal again..");
2194 return;
2195 }
2196
2197 #ifdef TOWN_NO_STEALING
2198 /* no stealing in town since town-pvp is diabled */
2199 if (istown(&p_ptr->wpos)) {
2200 msg_print(Ind, "\377oYou may not steal in town.");
2201 return;
2202 }
2203 #endif
2204 #ifdef PROTECTED_NO_STEALING
2205 if ((c_ptr->info & CAVE_PROT) || (f_info[c_ptr->feat].flags1 & FF1_PROTECTED)) {
2206 msg_print(Ind, "\377oThis location is protected and does not allow stealing.");
2207 return;
2208 }
2209 #endif
2210
2211 /* May not steal from AFK players, sportsmanship ;) - C. Blue */
2212 if (q_ptr->afk) {
2213 msg_print(Ind, "You may not steal from players who are AFK.");
2214 return;
2215 }
2216
2217 if (is_admin(q_ptr)) {
2218 msg_print(Ind, "Really? You should not steal from admins.");
2219 return;
2220 }
2221
2222 /* S(he) is no longer afk */
2223 un_afk_idle(Ind);
2224
2225 /* May not steal from hostile players */
2226 /* I doubt if it's reasonable..dunno - Jir - */
2227 #if 0 /* turned off now */
2228 if (check_hostile(0 - c_ptr->m_idx, Ind)) {
2229 /* Message */
2230 msg_format(Ind, "%^s is on guard against you.", q_ptr->name);
2231 return;
2232 }
2233 #endif
2234 dal = (p_ptr->lev > q_ptr->lev ? p_ptr->lev - q_ptr->lev : 1);
2235
2236 /* affect alignment on attempt (after hostile check) */
2237 /* evil thief! stealing from newbies */
2238 if (q_ptr->lev + 5 < p_ptr->lev){
2239 if((p_ptr->align_good) < (0xffff - dal))
2240 p_ptr->align_good += dal;
2241 else p_ptr->align_good = 0xffff; /* very evil */
2242 }
2243 /* non lawful action in town :) */
2244 if (istown(&p_ptr->wpos) && (p_ptr->align_law) < (0xffff - dal))
2245 p_ptr->align_law += dal;
2246 else p_ptr->align_law = 0xffff;
2247
2248 break_shadow_running(Ind);
2249 stop_precision(Ind);
2250 stop_shooting_till_kill(Ind);
2251
2252 #if 1 /* maybe rework this */
2253 /* Compute chance of success */
2254 success = 3 * (adj_dex_safe[p_ptr->stat_ind[A_DEX]] - adj_dex_safe[q_ptr->stat_ind[A_DEX]]);
2255 success += 2 * (UNAWARENESS(q_ptr) - UNAWARENESS(p_ptr));
2256
2257 /* Compute base chance of being noticed */
2258 notice = 5 * (adj_mag_stat[q_ptr->stat_ind[A_INT]] - p_ptr->skill_stl);
2259
2260 /* Reversed this as suggested by Potter - mikaelh */
2261 notice -= 1 * (UNAWARENESS(q_ptr) - UNAWARENESS(p_ptr));
2262
2263 // notice -= q_ptr->skill_fos; /* perception */
2264
2265 /* Hack -- Rogues get bonuses to chances */
2266 if (get_skill(p_ptr, SKILL_STEALING)) {
2267 /* Increase chance by level */
2268 success += get_skill_scale(p_ptr, SKILL_STEALING, 150);
2269 notice -= get_skill_scale(p_ptr, SKILL_STEALING, 150);
2270 }
2271 /* Similar Hack -- Robber is hard to be robbed */
2272 if (get_skill(q_ptr, SKILL_STEALING)) {
2273 /* Increase chance by level */
2274 success -= get_skill_scale(p_ptr, SKILL_STEALING, 100);
2275 notice += get_skill_scale(p_ptr, SKILL_STEALING, 100);
2276 }
2277
2278 /* Always small chance to fail */
2279 if (success > 95) success = 95;
2280 // if (notice < 5) notice = 5;
2281
2282 /* Hack -- Always small chance to succeed */
2283 if (success < 2) success = 2;
2284 #else
2285 #endif
2286
2287 /* Check for success */
2288 if (rand_int(100) < success) {
2289 /* Steal gold 25% of the time */
2290 if (rand_int(100) < 25) {
2291 int amt = q_ptr->au / 10;
2292
2293 if (TOOL_EQUIPPED(q_ptr) == SV_TOOL_MONEY_BELT && magik (70)) {
2294 /* Saving throw message */
2295 msg_print(Ind, "You couldn't find any money!");
2296 amt = 0;
2297 s_printf("StealingPvP: %s fails to steal %d gold from %s (chance %d%%): money belt.\n", p_ptr->name, amt, q_ptr->name, success);
2298 }
2299
2300 /* Transfer gold */
2301 if (amt) {
2302 /* Move from target to thief */
2303 q_ptr->au -= amt;
2304 gain_au(Ind, amt, FALSE, FALSE);
2305 /* Redraw */
2306 q_ptr->redraw |= (PR_GOLD);
2307
2308 /* Tell thief */
2309 msg_format(Ind, "You steal %d gold.", amt);
2310 s_printf("StealingPvP: %s steals %d gold from %s (chance %d%%).\n", p_ptr->name, amt, q_ptr->name, success);
2311 }
2312
2313 /* Always small chance to be noticed */
2314 if (notice < 5) notice = 5;
2315
2316 /* Check for target noticing */
2317 if (rand_int(100) < notice) {
2318 /* Message */
2319 msg_format(0 - c_ptr->m_idx, "\377rYou notice %s stealing %d gold!",
2320 p_ptr->name, amt);
2321 caught = TRUE;
2322 }
2323 } else {
2324 int item;
2325 object_type *o_ptr, forge;
2326 char o_name[ONAME_LEN];
2327
2328 /* Steal an item */
2329 item = rand_int(q_ptr->inven_cnt);
2330
2331 /* Get object */
2332 o_ptr = &q_ptr->inventory[item];
2333 forge = *o_ptr;
2334
2335 if (TOOL_EQUIPPED(q_ptr) == SV_TOOL_THEFT_PREVENTION && magik (80)) {
2336 /* Saving throw message */
2337 msg_print(Ind, "Your attempt to steal was interfered with by a strange device!");
2338 notice += 50;
2339 s_printf("StealingPvP: %s fails to steal from %s (chance %d%%): theft prevention.\n", p_ptr->name, q_ptr->name, success);
2340 }
2341 /* artifacts are HARD to steal. Cannot steal quest items or guild keys. */
2342 else if ((o_ptr->name1 && (rand_int(500) > success || etiquette)) ||
2343 o_ptr->questor || o_ptr->quest || (o_ptr->tval == TV_KEY && o_ptr->sval == SV_GUILD_KEY)) {
2344 msg_print(Ind, "The object itself seems to evade your hand!");
2345 s_printf("StealingPvP: %s fails to steal from %s (chance %d%%): restricted item (1).\n", p_ptr->name, q_ptr->name, success);
2346 }
2347 else if (((k_info[o_ptr->k_idx].flags5 & TR5_WINNERS_ONLY) &&
2348 #ifdef FALLEN_WINNERSONLY
2349 !p_ptr->once_winner
2350 #else
2351 !p_ptr->total_winner
2352 #endif
2353 )
2354 /* prevent winners picking up true arts accidentally */
2355 || (true_artifact_p(o_ptr) && !winner_artifact_p(o_ptr) &&
2356 p_ptr->total_winner && cfg.kings_etiquette)
2357 #ifndef RPG_SERVER
2358 || ((o_ptr->level > p_ptr->lev || o_ptr->level == 0) &&
2359 !in_irondeepdive(&p_ptr->wpos) &&
2360 (cfg.anti_cheeze_pickup || (true_artifact_p(o_ptr) && cfg.anti_arts_pickup)))
2361 #endif
2362 ) {
2363 msg_print(Ind, "The object itself seems to evade your hand!");
2364 s_printf("StealingPvP: %s fails to steal from %s (chance %d%%): restricted item (2).\n", p_ptr->name, q_ptr->name, success);
2365 } else {
2366 /* Turn level 0 food into level 1 food - mikaelh */
2367 if (o_ptr->level == 0 && shareable_starter_item(o_ptr)) {
2368 o_ptr->level = 1;
2369 o_ptr->discount = 100;
2370 }
2371
2372 /* Give one item to thief */
2373 if (o_ptr->tval == TV_WAND) forge.pval = divide_charged_item(o_ptr, 1);
2374 forge.number = 1;
2375 inven_carry(Ind, &forge);
2376
2377 /* Take one from target */
2378 inven_item_increase(0 - c_ptr->m_idx, item, -1);
2379 inven_item_optimize(0 - c_ptr->m_idx, item);
2380
2381 /* Tell thief what he got */
2382 object_desc(0, o_name, &forge, TRUE, 3);
2383 s_printf("StealingPvP: %s steals item %s from %s (chance %d%%).\n", p_ptr->name, o_name, q_ptr->name, success);
2384 object_desc(Ind, o_name, &forge, TRUE, 3);
2385 msg_format(Ind, "You stole %s.", o_name);
2386
2387 if (true_artifact_p(o_ptr)) a_info[o_ptr->name1].carrier = p_ptr->id;
2388
2389 /* Some events don't allow transactions before they begin */
2390 if (!p_ptr->max_exp) {
2391 msg_print(Ind, "You gain a tiny bit of experience from trading an item.");
2392 gain_exp(Ind, 1);
2393 }
2394
2395 can_use(Ind, o_ptr);
2396 /* for Ironman Deep Dive Challenge cross-trading */
2397 o_ptr->mode = p_ptr->mode;
2398
2399 /* Check whether this item was requested by an item-retrieval quest */
2400 if (p_ptr->quest_any_r_within_target) quest_check_goal_r(Ind, o_ptr);
2401 }
2402
2403 /* Easier to notice heavier objects */
2404 notice += forge.weight;
2405 // / (get_skill_scale(SKILL_STEALING, 19) + 1);
2406
2407 /* Always small chance to be noticed */
2408 if (notice < 5) notice = 5;
2409
2410 /* Check for target noticing */
2411 if (rand_int(100) < notice) {
2412 /* Message */
2413 msg_format(0 - c_ptr->m_idx, "\377rYou notice %s stealing %s!",
2414 p_ptr->name, o_name);
2415 caught = TRUE;
2416 }
2417 }
2418 } else {
2419 msg_print(Ind, "You fail to steal anything.");
2420 s_printf("StealingPvP: %s fails to steal from %s.\n", p_ptr->name, q_ptr->name);
2421
2422 /* Always small chance to be noticed */
2423 if (notice < 5) notice = 5;
2424
2425 /* Easier to notice a failed attempt */
2426 if (rand_int(100) < notice + 50) {
2427 msg_format(0 - c_ptr->m_idx, "\377rYou notice %s try to steal from you!", p_ptr->name);
2428 caught = TRUE;
2429 }
2430 }
2431
2432 if (caught) break_cloaking(Ind, 0);
2433
2434 #if 0 /* now turned off */
2435 /* Counter blow! */
2436 if (caught) {
2437 int i, j;
2438 object_type *o_ptr;
2439
2440 /* Purge this traitor */
2441 if (player_in_party(q_ptr->party, Ind)) {
2442 int party = p_ptr->party;
2443
2444 /* Temporary leave for the message */
2445 p_ptr->party = 0;
2446
2447 /* Messages */
2448 msg_print(Ind, "You have been purged from your party.");
2449 party_msg_format(q_ptr->party, "%s has betrayed your party!", p_ptr->name);
2450
2451 p_ptr->party = party;
2452 party_leave(Ind, FALSE);
2453
2454 }
2455
2456 /* Make target hostile */
2457 if (q_ptr->exp > p_ptr->exp / 2 - 200) {
2458 if (Players[0 - c_ptr->m_idx]->pvpexception < 2)
2459 add_hostility(0 - c_ptr->m_idx, p_ptr->name, FALSE);
2460 }
2461
2462 /* Message */
2463 msg_format(Ind, "\377r%s gave you an unexpected blow!",
2464 q_ptr->name);
2465
2466 set_stun(Ind, p_ptr->stun + randint(50));
2467 set_confused(Ind, p_ptr->confused + rand_int(20) + 10);
2468 if (cfg.use_pk_rules == PK_RULES_DECLARE)
2469 p_ptr->pkill |= PKILL_KILLABLE;
2470
2471 /* Thief drops some items from the shock of blow */
2472 if (cfg.newbies_cannot_drop <= p_ptr->lev && !p_ptr->inval) {
2473 for(i = rand_int(5); i < 5 ; i++ ) {
2474 j = rand_int(INVEN_TOTAL);
2475 o_ptr = &(p_ptr->inventory[j]);
2476
2477 if (!o_ptr->tval) continue;
2478
2479 /* He never drops body-armour this way */
2480 if (j == INVEN_BODY) continue;
2481
2482 /* An artifact 'resists' */
2483 if (true_artifact_p(o_ptr) && rand_int(100) > 2)
2484 continue;
2485 inven_drop(Ind, j, randint(o_ptr->number * 2));
2486 }
2487 }
2488
2489 /* The target gets angry */
2490 set_fury(0 - c_ptr->m_idx, q_ptr->fury + 15 + randint(15));
2491
2492 }
2493 #else
2494 /* set timeout before attempting to pvp-steal again */
2495 p_ptr->pstealing = 15; /* 15 turns aka ~10 seconds */
2496 #endif
2497
2498 /* Take a turn */
2499 p_ptr->energy -= level_speed(&p_ptr->wpos);
2500 }
2501
2502
2503
2504
2505
2506
2507
2508 /*
2509 * An "item_tester_hook" for refilling lanterns
2510 */
2511 static bool item_tester_refill_lantern(object_type *o_ptr)
2512 {
2513 /* (Rand)arts are not usable for refilling */
2514 if (o_ptr->name1) return (FALSE);
2515
2516 /* Flasks of oil are okay */
2517 if (o_ptr->tval == TV_FLASK) return (TRUE);
2518
2519 /* Other lanterns are okay */
2520 if ((o_ptr->tval == TV_LITE) &&
2521 (o_ptr->sval == SV_LITE_LANTERN) &&
2522 o_ptr->timeout)
2523 return (TRUE);
2524
2525 /* Assume not okay */
2526 return (FALSE);
2527 }
2528
2529
2530 /*
2531 * Refill the players lamp (from the pack or floor)
2532 */
2533 static void do_cmd_refill_lamp(int Ind, int item)
2534 {
2535 player_type *p_ptr = Players[Ind];
2536
2537 object_type *o_ptr;
2538 object_type *j_ptr;
2539
2540 long int used_fuel = 0, spilled_fuel = 0, available_fuel = 0;
2541
2542
2543 /* Restrict the choices */
2544 item_tester_hook = item_tester_refill_lantern;
2545
2546 /* Get the item (in the pack) */
2547 if (item >= 0) o_ptr = &(p_ptr->inventory[item]);
2548 /* Get the item (on the floor) */
2549 else {
2550 if (-item >= o_max) return; /* item doesn't exist */
2551 o_ptr = &o_list[0 - item];
2552 }
2553
2554 if (!item_tester_hook(o_ptr)) {
2555 msg_print(Ind, "You cannot refill with that!");
2556 return;
2557 }
2558
2559 if (check_guard_inscription(o_ptr->note, 'F')) {
2560 msg_print(Ind, "The item's incription prevents it.");
2561 return;
2562 }
2563
2564 /* Too kind? :) */
2565 if (artifact_p(o_ptr)) {
2566 msg_print(Ind, "Your light seems to resist!");
2567 return;
2568 }
2569
2570 if (o_ptr->tval != TV_FLASK && o_ptr->timeout == 0) {
2571 msg_print(Ind, "That item has no fuel left!");
2572 return;
2573 }
2574
2575 /* Let's not end afk for this. - C. Blue */
2576 /* un_afk_idle(Ind); */
2577
2578 /* Take a partial turn */
2579 p_ptr->energy -= level_speed(&p_ptr->wpos) / 2;
2580
2581 /* Access the lantern */
2582 j_ptr = &(p_ptr->inventory[INVEN_LITE]);
2583
2584 /* Refuel */
2585 used_fuel = j_ptr->timeout;
2586 if (o_ptr->tval == TV_FLASK) {
2587 j_ptr->timeout += o_ptr->pval;
2588 } else {
2589 spilled_fuel = (o_ptr->timeout * (randint(5) + (130 - adj_dex_th_mul[p_ptr->stat_ind[A_DEX]]) / 2)) / 100; /* spill some */
2590 available_fuel = o_ptr->timeout - spilled_fuel;
2591 j_ptr->timeout += available_fuel;
2592 }
2593
2594 /* Message */
2595 msg_print(Ind, "You fuel your lamp.");
2596
2597 /* Comment */
2598 if (j_ptr->timeout >= FUEL_LAMP) {
2599 j_ptr->timeout = FUEL_LAMP;
2600 msg_print(Ind, "Your lamp is full.");
2601 }
2602 used_fuel = j_ptr->timeout - used_fuel;
2603
2604 if (o_ptr->tval == TV_FLASK || item <= 0) { /* just dispose of for now, if it was from the ground */
2605 /* Decrease the item (from the pack) */
2606 if (item >= 0) {
2607 inven_item_increase(Ind, item, -1);
2608 inven_item_describe(Ind, item);
2609 inven_item_optimize(Ind, item);
2610 }
2611
2612 /* Decrease the item (from the floor) */
2613 else {
2614 floor_item_increase(0 - item, -1);
2615 floor_item_describe(0 - item);
2616 floor_item_optimize(0 - item);
2617 }
2618 } else { /* TV_LITE && SV_LITE_LANTERN */
2619 /* unstack lanterns if we used one of them for refilling */
2620 if ((item >= 0) && (o_ptr->number > 1)) {
2621 /* Make a fake item */
2622 object_type tmp_obj;
2623 tmp_obj = *o_ptr;
2624 tmp_obj.number = 1;
2625
2626 /* drain its fuel */
2627 /* big numbers (*1000) to fix rounding errors: */
2628 tmp_obj.timeout -= ((used_fuel * 100000) / (100000 - ((100000 * spilled_fuel) / tmp_obj.timeout)));
2629 /* quick hack to hopefully fix rounding errors: */
2630 if (tmp_obj.timeout == 1) tmp_obj.timeout = 0;
2631
2632 /* Unstack the used item */
2633 o_ptr->number--;
2634 p_ptr->total_weight -= tmp_obj.weight;
2635 item = inven_carry(Ind, &tmp_obj);
2636
2637 /* Message */
2638 msg_print(Ind, "You unstack your lanterns.");
2639 } else {
2640 /* big numbers (*1000) to fix rounding errors: */
2641 o_ptr->timeout -= ((used_fuel * 100000) / (100000 - ((100000 * spilled_fuel) / o_ptr->timeout)));
2642 /* quick hack to hopefully fix rounding errors: */
2643 if (o_ptr->timeout == 1) o_ptr->timeout = 0;
2644 // inven_item_describe(Ind, item);
2645 }
2646 }
2647
2648 /* Recalculate torch */
2649 p_ptr->update |= (PU_TORCH | PU_LITE);
2650 p_ptr->window |= (PW_INVEN | PW_EQUIP);
2651 /* If multiple lanterns are now 0 turns, they can be combined */
2652 p_ptr->notice |= (PN_COMBINE);
2653 }
2654
2655
2656
2657 /*
2658 * An "item_tester_hook" for refilling torches
2659 */
2660 static bool item_tester_refill_torch(object_type *o_ptr)
2661 {
2662 /* (Rand)arts are not usable for refilling */
2663 if (o_ptr->name1) return (FALSE);
2664
2665 /* Torches are okay */
2666 if ((o_ptr->tval == TV_LITE) &&
2667 (o_ptr->sval == SV_LITE_TORCH) &&
2668 o_ptr->timeout)
2669 return (TRUE);
2670
2671 /* Assume not okay */
2672 return (FALSE);
2673 }
2674
2675
2676 /*
2677 * Refuel the players torch (from the pack or floor)
2678 */
2679 static void do_cmd_refill_torch(int Ind, int item)
2680 {
2681 player_type *p_ptr = Players[Ind];
2682
2683 object_type *o_ptr;
2684 object_type *j_ptr;
2685
2686
2687 /* Restrict the choices */
2688 item_tester_hook = item_tester_refill_torch;
2689
2690 if (item > INVEN_TOTAL) return;
2691
2692 /* Get the item (in the pack) */
2693 if (item >= 0) {
2694 o_ptr = &(p_ptr->inventory[item]);
2695 }
2696
2697 /* Get the item (on the floor) */
2698 else {
2699 if (-item >= o_max)
2700 return; /* item doesn't exist */
2701
2702 o_ptr = &o_list[0 - item];
2703 }
2704
2705 if (!item_tester_hook(o_ptr)) {
2706 msg_print(Ind, "You cannot refill with that!");
2707 return;
2708 }
2709
2710 if (check_guard_inscription(o_ptr->note, 'F')) {
2711 msg_print(Ind, "The item's incription prevents it.");
2712 return;
2713 }
2714
2715 /* Too kind? :) */
2716 if (artifact_p(o_ptr)) {
2717 msg_print(Ind, "Your light seems to resist!");
2718 return;
2719 }
2720
2721 /* Let's not end afk for this. - C. Blue */
2722 /* un_afk_idle(Ind); */
2723
2724 /* Take a partial turn */
2725 p_ptr->energy -= level_speed(&p_ptr->wpos) / 2;
2726
2727 /* Access the primary torch */
2728 j_ptr = &(p_ptr->inventory[INVEN_LITE]);
2729
2730 /* Refuel */
2731 j_ptr->timeout += o_ptr->timeout;
2732 /* Lose very slightly sometimes */
2733 if (o_ptr->timeout >= 10) j_ptr->timeout -= rand_int(5);
2734 else j_ptr->timeout -= o_ptr->timeout / (2 + rand_int(5));
2735
2736 /* Message */
2737 msg_print(Ind, "You combine the torches.");
2738
2739 /* Over-fuel message */
2740 if (j_ptr->timeout >= FUEL_TORCH) {
2741 j_ptr->timeout = FUEL_TORCH;
2742 msg_print(Ind, "Your torch is fully fueled.");
2743 }
2744
2745 /* Refuel message */
2746 else {
2747 msg_print(Ind, "Your torch glows more brightly.");
2748 }
2749
2750 /* Decrease the item (from the pack) */
2751 if (item >= 0) {
2752 inven_item_increase(Ind, item, -1);
2753 inven_item_describe(Ind, item);
2754 inven_item_optimize(Ind, item);
2755 }
2756
2757 /* Decrease the item (from the floor) */
2758 else {
2759 floor_item_increase(0 - item, -1);
2760 floor_item_describe(0 - item);
2761 floor_item_optimize(0 - item);
2762 }
2763
2764 /* Recalculate torch */
2765 p_ptr->update |= (PU_TORCH);
2766 p_ptr->window |= (PW_INVEN | PW_EQUIP);
2767 }
2768
2769
2770
2771
2772 /*
2773 * Refill the players lamp, or restock his torches
2774 */
2775 void do_cmd_refill(int Ind, int item)
2776 {
2777 player_type *p_ptr = Players[Ind];
2778
2779 object_type *o_ptr;
2780 u32b f1, f2, f3, f4, f5, f6, esp;
2781
2782 /* Get the light */
2783 o_ptr = &(p_ptr->inventory[INVEN_LITE]);
2784
2785 /* It is nothing */
2786 if (o_ptr->tval != TV_LITE || !o_ptr->k_idx) {
2787 msg_print(Ind, "You are not wielding a light.");
2788 return;
2789 }
2790
2791 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2792
2793 if (!(f4 & TR4_FUEL_LITE)) {
2794 msg_print(Ind, "Your light cannot be refilled.");
2795 return;
2796 }
2797
2798 /* It's a lamp */
2799 else if (o_ptr->sval == SV_LITE_LANTERN) {
2800 do_cmd_refill_lamp(Ind, item);
2801 }
2802
2803 /* It's a torch */
2804 else if (o_ptr->sval == SV_LITE_TORCH) {
2805 do_cmd_refill_torch(Ind, item);
2806 }
2807
2808 /* No torch to refill */
2809 else {
2810 msg_print(Ind, "Your light cannot be refilled.");
2811 }
2812 }
2813
2814 /*
2815 * Refill the players lamp, or restock his torches automatically. - Jir -
2816 */
2817 bool do_auto_refill(int Ind)
2818 {
2819 player_type *p_ptr = Players[Ind];
2820
2821 object_type *o_ptr;
2822 object_type *j_ptr = NULL;
2823
2824 int i;
2825 u32b f1, f2, f3, f4, f5, f6, esp;
2826
2827 /* Get the light */
2828 o_ptr = &(p_ptr->inventory[INVEN_LITE]);
2829
2830 if( check_guard_inscription( o_ptr->note, 'F' )) {
2831 //msg_print(Ind, "The item's incription prevents it.");
2832 return (FALSE);
2833 }
2834
2835 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
2836
2837 /* It's a lamp */
2838 if (o_ptr->sval == SV_LITE_LANTERN) {
2839 /* Restrict the choices */
2840 item_tester_hook = item_tester_refill_lantern;
2841
2842 for(i = 0; i < INVEN_PACK; i++) {
2843 j_ptr = &(p_ptr->inventory[i]);
2844 if (!item_tester_hook(j_ptr)) continue;
2845 if (artifact_p(j_ptr) || ego_item_p(j_ptr)) continue;
2846 if (check_guard_inscription(j_ptr->note, 'F')) continue;
2847
2848 do_cmd_refill_lamp(Ind, i);
2849 return (TRUE);
2850 }
2851 }
2852
2853 /* It's a torch */
2854 else if (o_ptr->sval == SV_LITE_TORCH) {
2855 /* Restrict the choices */
2856 item_tester_hook = item_tester_refill_torch;
2857
2858 for(i = 0; i < INVEN_PACK; i++) {
2859 j_ptr = &(p_ptr->inventory[i]);
2860 if (!item_tester_hook(j_ptr)) continue;
2861 if (artifact_p(j_ptr) || ego_item_p(j_ptr)) continue;
2862 if (check_guard_inscription(j_ptr->note, 'F')) continue;
2863
2864 do_cmd_refill_torch(Ind, i);
2865 return (TRUE);
2866 }
2867 }
2868
2869 /* Assume false */
2870 return (FALSE);
2871 }
2872
2873
2874
2875
2876
2877 /*
2878 * Target command
2879 */
2880 void do_cmd_target(int Ind, int dir)
2881 {
2882 player_type *p_ptr = Players[Ind];
2883
2884 /* Set the target */
2885 if (target_set(Ind, dir) && !p_ptr->taciturn_messages) {
2886 // msg_print(Ind, "Target Selected.");
2887 } else {
2888 /*msg_print(Ind, "Target Aborted.");*/
2889 }
2890 }
2891
2892 void do_cmd_target_friendly(int Ind, int dir)
2893 {
2894 player_type *p_ptr = Players[Ind];
2895
2896 /* Set the target */
2897 if (target_set_friendly(Ind, dir) && !p_ptr->taciturn_messages) {
2898 // msg_print(Ind, "Target Selected.");
2899 } else {
2900 /*msg_print(Ind, "Target Aborted.");*/
2901 }
2902 }
2903
2904
2905 /*
2906 * Hack -- determine if a given location is "interesting" to a player
2907 */
2908 static bool do_cmd_look_accept(int Ind, int y, int x) {
2909 player_type *p_ptr = Players[Ind];
2910 struct worldpos *wpos = &p_ptr->wpos;
2911 cave_type **zcave;
2912
2913 cave_type *c_ptr;
2914 byte *w_ptr;
2915 struct c_special *cs_ptr;
2916
2917 if (!(zcave = getcave(wpos))) return(FALSE);
2918
2919 /* Examine the grid */
2920 c_ptr = &zcave[y][x];
2921 w_ptr = &p_ptr->cave_flag[y][x];
2922
2923 /* Player grids */
2924 if (c_ptr->m_idx < 0 && p_ptr->play_vis[0-c_ptr->m_idx]) {
2925 player_type *q_ptr = Players[0-c_ptr->m_idx];
2926 if ((!q_ptr->admin_dm || player_sees_dm(Ind)) &&
2927 (player_has_los_bold(Ind, y, x) || p_ptr->telepathy))
2928 return (TRUE);
2929 }
2930
2931 /* Visible monsters */
2932 if (c_ptr->m_idx > 0 && p_ptr->mon_vis[c_ptr->m_idx]) {
2933 /* Visible monsters */
2934 if (p_ptr->mon_vis[c_ptr->m_idx]) return (TRUE);
2935 }
2936
2937 /* Objects */
2938 if (c_ptr->o_idx) {
2939 /* Memorized object */
2940 if (p_ptr->obj_vis[c_ptr->o_idx] || p_ptr->admin_dm) return (TRUE); /* finally, poor dm - C. Blue */
2941 }
2942
2943 /* Traps */
2944 if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
2945 /* Revealed trap */
2946 if (cs_ptr->sc.trap.found) return (TRUE);
2947 }
2948
2949 /* Monster Traps */
2950 if (GetCS(c_ptr, CS_MON_TRAP)) {
2951 return (TRUE);
2952 }
2953
2954 /* Interesting memorized features */
2955 if (*w_ptr & CAVE_MARK) {
2956 #if 0 // wow!
2957 /* Notice glyphs */
2958 if (c_ptr->feat == FEAT_GLYPH) return (TRUE);
2959 if (c_ptr->feat == FEAT_RUNE) return (TRUE);
2960
2961 /* Notice doors */
2962 if (c_ptr->feat == FEAT_OPEN) return (TRUE);
2963 if (c_ptr->feat == FEAT_BROKEN) return (TRUE);
2964
2965 /* Notice stairs */
2966 if (c_ptr->feat == FEAT_LESS) return (TRUE);
2967 if (c_ptr->feat == FEAT_MORE) return (TRUE);
2968
2969 /* Notice shops */
2970 if (c_ptr->feat == FEAT_SHOP) return (TRUE);
2971 #if 0
2972 if ((c_ptr->feat >= FEAT_SHOP_HEAD) &&
2973 (c_ptr->feat <= FEAT_SHOP_TAIL)) return (TRUE);
2974 #endif // 0
2975
2976 /* Notice doors */
2977 if ((c_ptr->feat >= FEAT_DOOR_HEAD) &&
2978 (c_ptr->feat <= FEAT_DOOR_TAIL)) return (TRUE);
2979
2980 /* Notice rubble */
2981 if (c_ptr->feat == FEAT_RUBBLE) return (TRUE);
2982
2983 /* Notice veins with treasure */
2984 if (c_ptr->feat == FEAT_MAGMA_K) return (TRUE);
2985 if (c_ptr->feat == FEAT_QUARTZ_K) return (TRUE);
2986 if (c_ptr->feat == FEAT_SANDWALL_K) return (TRUE);
2987 #endif // 0
2988
2989 /* Accept 'naturally' interesting features */
2990 if (f_info[c_ptr->feat].flags1 & FF1_NOTICE) return (TRUE);
2991 }
2992
2993 /* Nope */
2994 return (FALSE);
2995 }
2996
2997
2998
2999 /*
3000 * A new "look" command, similar to the "target" command.
3001 *
3002 * The "player grid" is always included in the "look" array, so
3003 * that this command will normally never "fail".
3004 *
3005 * XXX XXX XXX Allow "target" inside the "look" command (?)
3006 */
3007 void do_cmd_look(int Ind, int dir) {
3008 player_type *p_ptr = Players[Ind];
3009 player_type *q_ptr;
3010 struct worldpos *wpos = &p_ptr->wpos;
3011 cave_type **zcave;
3012 int y, x, i;
3013
3014 cave_type *c_ptr;
3015 monster_type *m_ptr;
3016 object_type *o_ptr;
3017
3018 cptr p1 = "A ", p2 = "", info = "";
3019 struct c_special *cs_ptr;
3020
3021 char o_name[ONAME_LEN];
3022 char out_val[ONAME_LEN], tmp_val[ONAME_LEN];
3023
3024 if(!(zcave = getcave(wpos))) return;
3025
3026 /* Blind */
3027 if (p_ptr->blind) {
3028 msg_print(Ind, "You can't see a damn thing!");
3029 return;
3030 }
3031
3032 /* Hallucinating */
3033 if (p_ptr->image) {
3034 msg_print(Ind, "You can't believe what you are seeing!");
3035 return;
3036 }
3037
3038
3039 /* Reset "temp" array */
3040 /* Only if this is the first time, or if we've been asked to reset */
3041 if (!dir) {
3042 p_ptr->target_n = 0;
3043
3044 /* Scan the current panel */
3045 for (y = p_ptr->panel_row_min; y <= p_ptr->panel_row_max; y++) {
3046 for (x = p_ptr->panel_col_min; x <= p_ptr->panel_col_max; x++) {
3047 /* Require line of sight, unless "look" is "expanded" */
3048 if (!player_has_los_bold(Ind, y, x)) continue;
3049
3050 /* Require interesting contents */
3051 if (!do_cmd_look_accept(Ind, y, x)) continue;
3052
3053 /* Save the location */
3054 p_ptr->target_x[p_ptr->target_n] = x;
3055 p_ptr->target_y[p_ptr->target_n] = y;
3056 p_ptr->target_n++;
3057 }
3058 }
3059
3060 /* Start near the player */
3061 p_ptr->look_index = 0;
3062
3063 /* Paranoia */
3064 if (!p_ptr->target_n) {
3065 msg_print(Ind, "You see nothing special. [<dir>, p, q]");
3066 return;
3067 }
3068
3069
3070 /* Set the sort hooks */
3071 ang_sort_comp = ang_sort_comp_distance;
3072 ang_sort_swap = ang_sort_swap_distance;
3073
3074 /* Sort the positions */
3075 ang_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_n);
3076
3077 /* Collect monster and player indices */
3078 for (i = 0; i < p_ptr->target_n; i++) {
3079 c_ptr = &zcave[p_ptr->target_y[i]][p_ptr->target_x[i]];
3080
3081 if (c_ptr->m_idx != 0)
3082 p_ptr->target_idx[i] = c_ptr->m_idx;
3083 else p_ptr->target_idx[i] = 0;
3084 }
3085
3086 } else if (dir >= 128) {
3087 /* Initialize if needed */
3088 if (dir == 128) {
3089 x = p_ptr->target_col = p_ptr->px;
3090 y = p_ptr->target_row = p_ptr->py;
3091 } else {
3092 x = p_ptr->target_col + ddx[dir - 128];
3093 if (!player_has_los_bold(Ind, p_ptr->target_row, x) && !is_admin(p_ptr)) x = p_ptr->target_col;
3094 y = p_ptr->target_row + ddy[dir - 128];
3095 if (!player_has_los_bold(Ind, y, p_ptr->target_col) && !is_admin(p_ptr)) y = p_ptr->target_row;
3096
3097 if (!in_bounds(y, x)) return;
3098
3099 p_ptr->target_col = x;
3100 p_ptr->target_row = y;
3101 }
3102
3103 /* Check for confirmation to actually look at this grid */
3104 if (dir == 128 + 5) {
3105 p_ptr->look_index = 0;
3106 p_ptr->target_x[0] = p_ptr->target_col;
3107 p_ptr->target_y[0] = p_ptr->target_row;
3108 }
3109 /* Just manually ground-targetting - do not spam look-info for each single grid */
3110 else {
3111 /* Info */
3112 strcpy(out_val, "[<dir>, l, p, q] ");
3113
3114 /* Tell the client */
3115 Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
3116
3117 return;
3118 }
3119 }
3120
3121 /* Motion */
3122 else {
3123 /* Reset the locations */
3124 for (i = 0; i < p_ptr->target_n; i++) {
3125 if (p_ptr->target_idx[i] > 0) {
3126 m_ptr = &m_list[p_ptr->target_idx[i]];
3127
3128 p_ptr->target_y[i] = m_ptr->fy;
3129 p_ptr->target_x[i] = m_ptr->fx;
3130 } else if (p_ptr->target_idx[i] < 0) {
3131 q_ptr = Players[0 - p_ptr->target_idx[i]];
3132
3133 /* Check for player leaving */
3134 if (((0 - p_ptr->target_idx[i]) > NumPlayers) ||
3135 (!inarea(&q_ptr->wpos, &p_ptr->wpos))) {
3136 p_ptr->target_y[i] = 0;
3137 p_ptr->target_x[i] = 0;
3138 } else {
3139 p_ptr->target_y[i] = q_ptr->py;
3140 p_ptr->target_x[i] = q_ptr->px;
3141 }
3142 }
3143 }
3144
3145 /* Find a new grid if possible */
3146 i = target_pick(Ind, p_ptr->target_y[p_ptr->look_index], p_ptr->target_x[p_ptr->look_index], ddy[dir], ddx[dir]);
3147
3148 /* Use that grid */
3149 if (i >= 0) p_ptr->look_index = i;
3150 }
3151
3152 /* Describe */
3153 y = p_ptr->target_y[p_ptr->look_index];
3154 x = p_ptr->target_x[p_ptr->look_index];
3155
3156 /* Paranoia */
3157 /* thats extreme paranoia */
3158 if (!(zcave = getcave(wpos))) return;
3159 c_ptr = &zcave[y][x];
3160
3161 if (c_ptr->m_idx < 0 && p_ptr->play_vis[0-c_ptr->m_idx] &&
3162 (!Players[0-c_ptr->m_idx]->admin_dm || player_sees_dm(Ind))) {
3163 q_ptr = Players[0 - c_ptr->m_idx];
3164
3165 /* Track health */
3166 health_track(Ind, c_ptr->m_idx);
3167
3168 /* Format string */
3169 if ((q_ptr->inventory[INVEN_BODY].tval == TV_SOFT_ARMOR) && (q_ptr->inventory[INVEN_BODY].sval == SV_COSTUME)) {
3170 snprintf(out_val, sizeof(out_val), "%s the %s (%s)", q_ptr->name, r_name + r_info[q_ptr->inventory[INVEN_BODY].bpval].name, get_ptitle(q_ptr, FALSE));
3171 } else if (q_ptr->body_monster) {
3172 snprintf(out_val, sizeof(out_val), "%s the %s (%s)", q_ptr->name, r_name + r_info[q_ptr->body_monster].name, get_ptitle(q_ptr, FALSE));
3173 } else {
3174 #if 0 /* use normal race_info.title */
3175 snprintf(out_val, sizeof(out_val), "%s the %s %s", q_ptr->name, race_info[q_ptr->prace].title, get_ptitle(q_ptr, FALSE));
3176 //, class_info[q_ptr->pclass].title
3177 #else /* use special_prace_lookup */
3178 snprintf(out_val, sizeof(out_val), "%s the %s %s", q_ptr->name, get_prace(q_ptr), get_ptitle(q_ptr, FALSE));
3179 #endif
3180 }
3181 } else if (c_ptr->m_idx > 0 && p_ptr->mon_vis[c_ptr->m_idx]) { /* TODO: handle monster mimics */
3182 bool done_unique;
3183 m_ptr = &m_list[c_ptr->m_idx];
3184
3185 /* a unique which the looker already killed? */
3186 if ((r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) &&
3187 p_ptr->r_killed[m_ptr->r_idx] == 1)
3188 done_unique = TRUE;
3189 else done_unique = FALSE;
3190
3191 /* Track health */
3192 health_track(Ind, c_ptr->m_idx);
3193
3194 /* Format string */
3195 if (m_ptr->questor)
3196 snprintf(out_val, sizeof(out_val), "\377%c%s (Lv %d, %s)",
3197 m_ptr->questor_invincible ? 'G' : ((m_ptr->questor_hostile & 0x1) ? 'R' : 'G'),
3198 r_name_get(&m_list[c_ptr->m_idx]),
3199 m_ptr->level, look_mon_desc(c_ptr->m_idx));
3200 else
3201 #if 0 /* attach 'slain' for uniques we already killed */
3202 // snprintf(out_val, sizeof(out_val), "%s (%s)", r_name_get(&m_list[c_ptr->m_idx]), look_mon_desc(c_ptr->m_idx));
3203 snprintf(out_val, sizeof(out_val), "%s (Lv %d, %s%s)", r_name_get(&m_list[c_ptr->m_idx]),
3204 m_ptr->level, look_mon_desc(c_ptr->m_idx),
3205 m_ptr->clone ? ", clone" : (done_unique ? ", slain" : ""));
3206 #else /* use different colour for uniques we already killed */
3207 snprintf(out_val, sizeof(out_val), "%s%s (Lv %d, %s%s)",
3208 done_unique ? "\377D" : "",
3209 r_name_get(&m_list[c_ptr->m_idx]),
3210 m_ptr->level, look_mon_desc(c_ptr->m_idx),
3211 m_ptr->clone ? ", clone" : "");
3212 #endif
3213 } else if (c_ptr->o_idx) {
3214 o_ptr = &o_list[c_ptr->o_idx];
3215
3216 /* Format string */
3217 if (o_ptr->questor) {
3218 #if 0
3219 snprintf(out_val, sizeof(out_val), "\377%c%sYou see %s%s",
3220 o_ptr->questor_invincible ? 'G' : 'G', compat_pomode(Ind, o_ptr) ? "\377D" : "",
3221 q_info[o_ptr->quest - 1].questor[o_ptr->questor_idx].name, o_ptr->next_o_idx ? " on a pile" : "");
3222 #else
3223 object_desc(Ind, o_name, o_ptr, TRUE, 3);
3224 snprintf(out_val, sizeof(out_val), "\377%c%sYou see %s%s",
3225 o_ptr->questor_invincible ? 'G' : 'G', compat_pomode(Ind, o_ptr) ? "\377D" : "",
3226 o_name, o_ptr->next_o_idx ? " on a pile" : "");
3227 #endif
3228 } else {
3229 /* Obtain an object description */
3230 object_desc(Ind, o_name, o_ptr, TRUE, 3);
3231
3232 snprintf(out_val, sizeof(out_val), "%sYou see %s%s",
3233 compat_pomode(Ind, o_ptr) ? "\377D" : "", o_name, o_ptr->next_o_idx ? " on a pile" : "");
3234 }
3235
3236 /* Check if the object is on a detected trap */
3237 if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
3238 int t_idx = cs_ptr->sc.trap.t_idx;
3239 if (cs_ptr->sc.trap.found) {
3240 if (p_ptr->trap_ident[t_idx])
3241 p1 = t_name + t_info[t_idx].name;
3242 else
3243 p1 = "trapped";
3244
3245 /* Add trap description at the end */
3246 strcat(out_val, " {");
3247 strcat(out_val, p1);
3248 strcat(out_val, "}");
3249 /* Also add a ^ at the beginning of the line
3250 in case it's too long to read its end */
3251 strcpy(tmp_val, "^ ");
3252 strcat(tmp_val, out_val);
3253 strcpy(out_val, tmp_val);
3254 }
3255 }
3256
3257 } else {
3258 int feat = f_info[c_ptr->feat].mimic;
3259 cptr name = f_name + f_info[feat].name;
3260
3261 if (f_info[c_ptr->feat].flags2 & FF2_NO_ARTICLE) p1 = "";
3262 else if (is_a_vowel(name[0])) p1 = "An ";
3263
3264 /* Hack -- add trap description */
3265 if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
3266 int t_idx = cs_ptr->sc.trap.t_idx;
3267 if (cs_ptr->sc.trap.found) {
3268 if (p_ptr->trap_ident[t_idx])
3269 p1 = t_name + t_info[t_idx].name;
3270 else
3271 p1 = "A trap";
3272
3273 p2 = " on ";
3274 }
3275 }
3276
3277 /* Hack -- special description for store doors */
3278 // if ((feat >= FEAT_SHOP_HEAD) && (feat <= FEAT_SHOP_TAIL))
3279 if (feat == FEAT_SHOP) {
3280 p1 = "The entrance to ";
3281
3282 /* TODO: store name! */
3283 if ((cs_ptr = GetCS(c_ptr, CS_SHOP))) {
3284 name = st_name + st_info[cs_ptr->sc.omni].name;
3285 }
3286
3287 }
3288
3289 if ((feat == FEAT_FOUNTAIN) &&
3290 (cs_ptr = GetCS(c_ptr, CS_FOUNTAIN)) &&
3291 cs_ptr->sc.fountain.known) {
3292 object_kind *k_ptr;
3293 int tval, sval;
3294
3295 if (cs_ptr->sc.fountain.type <= SV_POTION_LAST) {
3296 tval = TV_POTION;
3297 sval = cs_ptr->sc.fountain.type;
3298 } else {
3299 tval = TV_POTION2;
3300 sval = cs_ptr->sc.fountain.type - SV_POTION_LAST;
3301 }
3302
3303 k_ptr = &k_info[lookup_kind(tval, sval)];
3304 info = k_name + k_ptr->name;
3305 }
3306
3307 if (feat == FEAT_SIGN) /* give instructions how to actually read it ;) */
3308 name = "signpost \377D(bump to read)\377w";
3309
3310 /* Message */
3311 if (strlen(info)) snprintf(out_val, sizeof(out_val), "%s%s%s (%s)", p1, p2, name, info);
3312 else snprintf(out_val, sizeof(out_val), "%s%s%s", p1, p2, name);
3313
3314 if (f_info[c_ptr->feat].flags2 & FF2_NO_ARTICLE) out_val[0] = toupper(out_val[0]);
3315 }
3316
3317 if (is_admin(p_ptr)) strcat(out_val, format(" (%d)", c_ptr->feat));
3318
3319 /* Append a little info */
3320 strcat(out_val, " [<dir>, p, q]");
3321
3322 /* Tell the client */
3323 Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
3324 }
3325
3326
3327
3328
3329 /*
3330 * Allow the player to examine other sectors on the map
3331 */
3332 void do_cmd_locate(int Ind, int dir) {
3333 player_type *p_ptr = Players[Ind];
3334
3335 int y1, x1, y2, x2;
3336 int prow = p_ptr->panel_row;
3337 int pcol = p_ptr->panel_col;
3338 char tmp_val[MAX_CHARS];
3339 char out_val[MAX_CHARS_WIDE];
3340 char trad_val[23];
3341
3342
3343 /* No direction, recenter */
3344 if (!dir) {
3345 /* Recenter map around the player */
3346 verify_panel(Ind);
3347
3348 /* Any change? otherwise no need to redraw */
3349 if ((prow != p_ptr->panel_row) || (pcol != p_ptr->panel_col)) {
3350 /* Update stuff */
3351 p_ptr->update |= (PU_MONSTERS);
3352
3353 /* Redraw map */
3354 p_ptr->redraw |= (PR_MAP);
3355
3356 /* Window stuff */
3357 p_ptr->window |= (PW_OVERHEAD);
3358
3359 /* Handle stuff */
3360 handle_stuff(Ind);
3361 }
3362
3363 #ifdef ALERT_OFFPANEL_DAM
3364 /* For alert-beeps on damage: Reset remembered panel */
3365 p_ptr->panel_row_old = p_ptr->panel_row;
3366 p_ptr->panel_col_old = p_ptr->panel_col;
3367 #endif
3368
3369 return;
3370 }
3371
3372 /* Initialize */
3373 if (dir == 5) {
3374 /* Remember current panel */
3375 p_ptr->panel_row_old = p_ptr->panel_row;
3376 p_ptr->panel_col_old = p_ptr->panel_col;
3377 }
3378
3379 /* Start at current panel */
3380 y2 = p_ptr->panel_row;
3381 x2 = p_ptr->panel_col;
3382
3383 /* Initial panel */
3384 y1 = p_ptr->panel_row_old;
3385 x1 = p_ptr->panel_col_old;
3386
3387 /* Apply the motion */
3388 y2 += ddy[dir];
3389 x2 += ddx[dir];
3390
3391 /* Verify the row */
3392 if (y2 > p_ptr->max_panel_rows) y2 = p_ptr->max_panel_rows;
3393 else if (y2 < 0) y2 = 0;
3394
3395 /* Verify the col */
3396 if (x2 > p_ptr->max_panel_cols) x2 = p_ptr->max_panel_cols;
3397 else if (x2 < 0) x2 = 0;
3398
3399 /* Describe the location */
3400 if ((y2 == y1) && (x2 == x1)) {
3401 tmp_val[0] = '\0';
3402
3403 /* For BIG_MAP users, also display the traditional sector they are located in,
3404 to make communication about dungeon entrances etc easier. */
3405 if (p_ptr->screen_wid == SCREEN_WID && p_ptr->screen_hgt == SCREEN_HGT)
3406 trad_val[0] = 0;
3407 else
3408 sprintf(trad_val, ", traditionally [%d,%d]", p_ptr->tradpanel_row, p_ptr->tradpanel_col);
3409 } else {
3410 sprintf(tmp_val, "%s%s of",
3411 ((y2 < y1) ? " North" : (y2 > y1) ? " South" : ""),
3412 ((x2 < x1) ? " West" : (x2 > x1) ? " East" : ""));
3413 trad_val[0] = 0;
3414 }
3415
3416 /* Prepare to ask which way to look */
3417 sprintf(out_val,
3418 "Map sector [%d,%d], which is%s your sector%s. Direction (or ESC)?",
3419 y2, x2, tmp_val, trad_val);
3420
3421 msg_print(Ind, out_val);
3422
3423 /* Set the panel location */
3424 p_ptr->panel_row = y2;
3425 p_ptr->panel_col = x2;
3426
3427 /* Recalculate the boundaries */
3428 panel_bounds(Ind);
3429
3430 /* any change? otherwise no need to redraw everything */
3431 if ((prow != p_ptr->panel_row) || (pcol != p_ptr->panel_col)) {
3432 /* client-side weather stuff */
3433 p_ptr->panel_changed = TRUE;
3434
3435 /* Redraw map */
3436 p_ptr->redraw |= (PR_MAP);
3437
3438 /* Update stuff */
3439 p_ptr->update |= (PU_MONSTERS);
3440
3441 /* Window stuff */
3442 p_ptr->window |= (PW_OVERHEAD);
3443 }
3444
3445 /* Handle stuff */
3446 handle_stuff(Ind);
3447 }
3448
3449
3450
3451 /* Not fully implemented - mikaelh */
3452 #if 0
3453
3454 /*
3455 * The table of "symbol info" -- each entry is a string of the form
3456 * "X:desc" where "X" is the trigger, and "desc" is the "info".
3457 */
3458 static cptr ident_info[] =
3459 {
3460 " :A dark grid",
3461 "!:A potion (or oil)",
3462 "\":An amulet (or necklace)",
3463 "#:A wall (or secret door)",
3464 "$:Treasure (gold or gems)",
3465 "%:A vein (magma or quartz)",
3466 /* "&:unused", */
3467 "':An open door",
3468 "(:Soft armour",
3469 "):A shield",
3470 "*:A vein with treasure",
3471 "+:A closed door",
3472 ",:Food (or mushroom patch)",
3473 "-:A wand (or rod)",
3474 ".:Floor",
3475 "/:A polearm (Axe/Pike/etc)",
3476 /* "0:unused", */
3477 "1:Entrance to General Store",
3478 "2:Entrance to Armory",
3479 "3:Entrance to Weaponsmith",
3480 "4:Entrance to Temple",
3481 "5:Entrance to Alchemy shop",
3482 "6:Entrance to Magic store",
3483 "7:Entrance to Black Market",
3484 "8:Entrance to Tavern",
3485 /* "9:unused", */
3486 "::Rubble",
3487 ";:A glyph of warding",
3488 "<:An up staircase",
3489 "=:A ring",
3490 ">:A down staircase",
3491 "?:A scroll",
3492 "@:You",
3493 "A:Angel",
3494 "B:Bird",
3495 "C:Canine",
3496 "D:Ancient Dragon/Wyrm",
3497 "E:Elemental",
3498 "F:Dragon Fly",
3499 "G:Ghost",
3500 "H:Hybrid",
3501 "I:Insect",
3502 "J:Snake",
3503 "K:Killer Beetle",
3504 "L:Lich",
3505 "M:Multi-Headed Reptile",
3506 /* "N:unused", */
3507 "O:Ogre",
3508 "P:Giant Humanoid",
3509 "Q:Quylthulg (Pulsing Flesh Mound)",
3510 "R:Reptile/Amphibian",
3511 "S:Spider/Scorpion/Tick",
3512 "T:Troll",
3513 "U:Major Demon",
3514 "V:Vampire",
3515 "W:Wight/Wraith/etc",
3516 "X:Xorn/Xaren/etc",
3517 "Y:Yeti",
3518 "Z:Zephyr Hound",
3519 "[:Hard armour",
3520 "\\:A blunt weapon (mace/whip/etc)",
3521 "]:Misc. armour",
3522 "^:A trap",
3523 "_:A staff",
3524 /* "`:unused", */
3525 "a:Ant",
3526 "b:Bat",
3527 "c:Centipede",
3528 "d:Dragon",
3529 "e:Floating Eye",
3530 "f:Feline",
3531 "g:Golem",
3532 "h:Hobbit/Elf/Dwarf",
3533 "i:Icky Thing",
3534 "j:Jelly",
3535 "k:Kobold",
3536 "l:Louse",
3537 "m:Mold",
3538 "n:Naga",
3539 "o:Orc",
3540 "p:Person/Human",
3541 "q:Quadruped",
3542 "r:Rodent",
3543 "s:Skeleton",
3544 "t:Townsperson",
3545 "u:Minor Demon",
3546 "v:Vortex",
3547 "w:Worm/Worm-Mass",
3548 /* "x:unused", */
3549 "y:Yeek",
3550 "z:Zombie/Mummy",
3551 "{:A missile (arrow/bolt/shot)",
3552 "|:An edged weapon (sword/dagger/etc)",
3553 "}:A launcher (bow/crossbow/sling)",
3554 "~:A tool (or miscellaneous item)",
3555 NULL
3556 };
3557
3558
3559 /*
3560 * Identify a character
3561 *
3562 * Note that the player ghosts are ignored. XXX XXX XXX
3563 */
3564 void do_cmd_query_symbol(int Ind, char sym)
3565 {
3566 int i;
3567 char buf[128];
3568
3569
3570 /* If no symbol, abort --KLJ-- */
3571 if (!sym)
3572 return;
3573
3574 /* Find that character info, and describe it */
3575 for (i = 0; ident_info[i]; ++i)
3576 {
3577 if (sym == ident_info[i][0]) break;
3578 }
3579
3580 /* Describe */
3581 if (ident_info[i])
3582 {
3583 sprintf(buf, "%c - %s.", sym, ident_info[i] + 2);
3584 }
3585 else
3586 {
3587 sprintf(buf, "%c - %s.", sym, "Unknown Symbol");
3588 }
3589
3590 /* Display the result */
3591 msg_print(Ind, buf);
3592 }
3593
3594 #endif // 0
3595