1 /* $Id$ */
2 /* File: effects.c */
3
4 /* Purpose: effects of various "objects" */
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 #include "party.h"
18
19
20 //#define IRON_TEAM_EXPERIENCE
21 /* todo before enabling: implement way to decrease party.experience again! */
22
23 /*
24 * What % of exp points will be lost when resurrecting? [40] - Jir -
25 *
26 * cf. GHOST_FADING in dungeon.c
27 */
28 #ifdef ENABLE_INSTANT_RES
29 #define GHOST_XP_LOST 35
30 #else
31 #define GHOST_XP_LOST 40
32 #endif
33
34 /*
35 * What % of exp points will be lost on instant resurrection?
36 */
37 #define INSTANT_RES_XP_LOST 50
38
39 /*
40 * Chance of an item teleporting away when player dies, in percent. [10]
41 * This is to balance death penalty after item stacking was implemented.
42 * To disable, comment it out.
43 */
44 #define DEATH_ITEM_SCATTER 0
45
46 /* Chance of an item from the player's inventory getting lost (aka deleted)
47 when player dies, in percent [20]. - C. Blue (limited to 4) */
48 #define DEATH_PACK_ITEM_LOST 15
49
50 /* Chance of an item from the player's equipment getting lost (aka deleted)
51 when player dies, in percent [10]. - C. Blue (limited to 1) */
52 #define DEATH_EQ_ITEM_LOST 10
53
54 /* Reduce chance of inventory item destruction, to balance death for
55 characters relying heavily on certain types of items? */
56 #define DEATH_PACK_ITEM_NICE
57
58 /* Loot item level is average of monster level and floor level - C. Blue
59 Note: Imho the more floor level is taken into account, the more will
60 melee chars who aim at high level weapons and armour be at a
61 disadvantage, compared to light armour dropping everywhere.
62 Also, floor level determines monster level of spawns anyway.
63 However, contra side of disabling this is cheezy high unique
64 farming on harmless floors via vaults for great loot -
65 probably only affects melee chars though.
66 Disabling this definition will cause loot to depend more on monster level. */
67 #define TRADITIONAL_LOOT_LEVEL
68
69 /* Should be defined to allow finding top-level items on non-NR floors
70 in cases where you just cannot find monsters of high enough level so
71 that averaging floor and monster level would pass the test.
72 Details:
73 Without this, if TRADITIONAL_LOOT_LEVEL is on, no loot above klevel 108
74 could drop outside of NR anymore (Star Blade being highest normal monster
75 at 90).
76 Without TRADITIONAL_LOOT_LEVEL the situation becomes worse and usually no
77 loot above klevel 102 could drop anymore (again Star Blades lv90 assumed).
78 Note: Items of klevel > 115 usually cannot drop outside of NR, even with
79 this on.
80 EXCEPTIONS to all the above stuff:
81 Note2: Objects still get an extra boost from being 'good' or 'great', of +10
82 to object_level and from GREAT_OBJ which can even be +128. - C. Blue */
83 #define RANDOMIZED_LOOT_LEVEL
84
85 /* Level 50 limit for non-kings: RECOMMENDED! */
86 #define KINGCAP_LEV
87
88 /* exp limit for non-kings (level 50..69 depending on race/class) for non-kings: */
89 /*#define KINGCAP_EXP*/ /* NOT RECOMMENDED to enable this! */
90
91 /* Does NOT have effect if KINGCAP_EXP is defined.
92 Total bonus skill points till level 50 for yeeks.
93 All other class/race combinations will get less, down to 0 for
94 max exp penalty of 472,5 %. Must be integer within 0..50. [25] */
95 #define WEAK_SKILLBONUS 0 /* NOT RECOMMENDED to set this > 0! */
96
97 /* Show real killer name even when hallucinating? */
98 #define SHOW_REALLY_DIED_FROM
99 /* In addition to above, show real killer instead of "insanity"? */
100 #ifdef SHOW_REALLY_DIED_FROM
101 #define SHOW_REALLY_DIED_FROM_INSANITY
102 #endif
103
104 /* Do player-kill messages of "Morgoth, Lord of Darkness" get some
105 special flavour? - C. Blue */
106 #define MORGOTH_FUNKY_KILL_MSGS
107
108 /*
109 * Modifier of semi-promised artifact drops, in percent.
110 * It can happen that the quickest player will gather most of those
111 * artifact; this can be used to defuse it somewhat. Won't affect '101%' chances.
112 */
113 // #define SEMI_PROMISED_ARTS_MODIFIER 50
114
115 /*
116 * If defined, a player cannot gain more than 1 level at once.
117 * It prevents so-called 'high-books cheeze'.
118 */
119 /* Prolly no longer needed, since a player cannot gain exp from books now */
120 //#define LEVEL_GAINING_LIMIT
121
122
123 /*
124 * Thresholds for scrolling. [3,8] [2,4]
125 * XXX They should be client-side numerical options. - Jir -
126 */
127 #ifndef ARCADE_SERVER
128 #define TRAD_SCROLL_MARGIN_ROW (p_ptr->wide_scroll_margin ? 5 : 2)
129 #define SCROLL_MARGIN_ROW (p_ptr->screen_hgt >= 26 ? \
130 (p_ptr->wide_scroll_margin ? p_ptr->screen_hgt / 5 : p_ptr->screen_hgt / 13) : \
131 TRAD_SCROLL_MARGIN_ROW)
132 #define SCROLL_MARGIN_COL (p_ptr->wide_scroll_margin ? p_ptr->screen_wid / 5 : p_ptr->screen_wid / 13)
133 #define TRAD_SCROLL_MARGIN_COL SCROLL_MARGIN_COL
134 #else
135 #define SCROLL_MARGIN_ROW 8
136 #define SCROLL_MARGIN_COL 20
137 #define TRAD_SCROLL_MARGIN_ROW SCROLL_MARGIN_ROW
138 #define TRAD_SCROLL_MARGIN_COL SCROLL_MARGIN_COL
139 #endif
140
141 /* death_type definitions */
142 #define DEATH_PERMA 0
143 #define DEATH_INSANITY 1
144 #define DEATH_GHOST 2
145 #define DEATH_QUIT 3 /* suicide/retirement */
146
147
148 /* If during certain events, remember his/her account ID, for handing out a reward
149 to a different character which he chooses on next login! - C. Blue
150 */
buffer_account_for_event_deed(player_type * p_ptr,int death_type)151 static void buffer_account_for_event_deed(player_type *p_ptr, int death_type) {
152 int i,j;
153 #if 0 /* why should this be enabled, hmm */
154 for (i = 0; i < MAX_CONTENDER_BUFFERS; i++)
155 if (ge_contender_buffer_ID[i] == p_ptr->account) return; /* player already has a buffer entry */
156 #endif
157 for (i = 0; i < MAX_CONTENDER_BUFFERS; i++)
158 if (ge_contender_buffer_ID[i] == 0) break;
159 if (i == MAX_CONTENDER_BUFFERS) return; /* no free buffer entries anymore, sorry! */
160 ge_contender_buffer_ID[i] = p_ptr->account;
161 for (j = 0; j < MAX_GLOBAL_EVENTS; j++)
162 switch (p_ptr->global_event_type[j]) {
163 case GE_HIGHLANDER:
164 if (p_ptr->global_event_progress[j][0] < 5) break; /* only rewarded if already in deathmatch phase! */
165 if (death_type >= DEATH_QUIT) break; /* no reward for suiciding! */
166 /* hand out the reward: */
167 ge_contender_buffer_deed[i] = SV_DEED2_HIGHLANDER;
168 return;
169 #if 1 /* since everyone can win, this is not that important */
170 case GE_DUNGEON_KEEPER:
171 if (death_type >= DEATH_QUIT) break; /* no reward for suiciding! */
172 /* hand out the reward: */
173 ge_contender_buffer_deed[i] = SV_DEED2_DUNGEONKEEPER;
174 return;
175 #endif
176 case GE_NONE:
177 default:
178 break;
179 }
180 ge_contender_buffer_ID[i] = 0; /* didn't find any event where player participated */
181 }
182
buffer_account_for_achievement_deed(player_type * p_ptr,int achievement)183 static void buffer_account_for_achievement_deed(player_type *p_ptr, int achievement) {
184 int i;
185 #if 0 /* why should this be enabled, hmm */
186 for (i = 0; i < MAX_ACHIEVEMENT_BUFFERS; i++)
187 if (achievement_buffer_ID[i] == p_ptr->account) return; /* player already has a buffer entry */
188 #endif
189 for (i = 0; i < MAX_ACHIEVEMENT_BUFFERS; i++)
190 if (achievement_buffer_ID[i] == 0) break;
191 if (i == MAX_ACHIEVEMENT_BUFFERS) return; /* no free buffer entries anymore, sorry! */
192 achievement_buffer_ID[i] = p_ptr->account;
193 switch (achievement) {
194 case ACHV_PVP_MAX:
195 achievement_buffer_deed[i] = SV_DEED_PVP_MAX;
196 break;
197 case ACHV_PVP_MID:
198 achievement_buffer_deed[i] = SV_DEED_PVP_MID;
199 break;
200 case ACHV_PVP_MASS:
201 achievement_buffer_deed[i] = SV_DEED_PVP_MASS;
202 break;
203 default:
204 break;
205 }
206 }
207
208 /*
209 * Set "p_ptr->tim_thunder", notice observable changes
210 */
set_tim_thunder(int Ind,int v,int p1,int p2)211 bool set_tim_thunder(int Ind, int v, int p1, int p2) {
212 player_type *p_ptr = Players[Ind];
213 bool notice = FALSE;
214
215 /* Hack -- Force good values */
216 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
217
218 /* Open */
219 if (v) {
220 if (!p_ptr->tim_thunder) {
221 msg_print(Ind, "The air around you charges with lightning!");
222 notice = TRUE;
223 }
224 }
225
226 /* Shut */
227 else {
228 if (p_ptr->tim_thunder) {
229 msg_print(Ind, "The air around you discharges.");
230 notice = TRUE;
231 p1 = p2 = 0;
232 }
233 }
234
235 /* Use the value */
236 p_ptr->tim_thunder = v;
237 p_ptr->tim_thunder_p1 = p1;
238 p_ptr->tim_thunder_p2 = p2;
239
240 /* Nothing to notice */
241 if (!notice) return (FALSE);
242
243 /* Disturb */
244 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
245
246 /* Recalculate boni */
247 p_ptr->update |= (PU_BONUS);
248
249 /* Update the monsters */
250 p_ptr->update |= (PU_MONSTERS);
251
252 /* Handle stuff */
253 handle_stuff(Ind);
254
255 /* Result */
256 return (TRUE);
257 }
258
259 /*
260 * Set "p_ptr->tim_regen", notice observable changes
261 */
set_tim_regen(int Ind,int v,int p)262 bool set_tim_regen(int Ind, int v, int p) {
263 player_type *p_ptr = Players[Ind];
264 bool notice = FALSE;
265
266 /* Hack -- Force good values */
267 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
268
269 /* Open */
270 if (v) {
271 if (!p_ptr->tim_regen) {
272 msg_print(Ind, "Your body regeneration abilities greatly increase!");
273 notice = TRUE;
274 }
275 }
276
277 /* Shut */
278 else {
279 if (p_ptr->tim_regen) {
280 p = 0;
281 msg_print(Ind, "Your body regeneration abilities becomes normal again.");
282 notice = TRUE;
283 }
284 }
285
286 /* Use the value */
287 p_ptr->tim_regen = v;
288 p_ptr->tim_regen_pow = p;
289
290 /* Nothing to notice */
291 if (!notice) return (FALSE);
292
293 /* Disturb */
294 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
295
296 /* Handle stuff */
297 handle_stuff(Ind);
298
299 /* Result */
300 return (TRUE);
301 }
302
303 /*
304 * Set "p_ptr->tim_ffall"
305 */
set_tim_ffall(int Ind,int v)306 bool set_tim_ffall(int Ind, int v) {
307 player_type *p_ptr = Players[Ind];
308 bool notice = FALSE;
309
310 /* Hack -- Force good values */
311 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
312
313 /* Open */
314 if (v) {
315 if (!p_ptr->tim_ffall) {
316 msg_print(Ind, "You feel very light.");
317 notice = TRUE;
318 }
319 }
320
321 /* Shut */
322 else {
323 if (p_ptr->tim_ffall) {
324 msg_print(Ind, "You are suddenly heavier.");
325 notice = TRUE;
326 }
327 }
328
329 /* Use the value */
330 p_ptr->tim_ffall = v;
331
332 /* Nothing to notice */
333 if (!notice)
334 return (FALSE);
335
336 /* Disturb */
337 if (p_ptr->disturb_state)
338 disturb(Ind, 0, 0);
339
340 /* Recalculate boni */
341 p_ptr->update |= (PU_BONUS);
342
343 /* Result */
344 return (TRUE);
345 }
346
347 /*
348 * Set "p_ptr->tim_lev"
349 */
set_tim_lev(int Ind,int v)350 bool set_tim_lev(int Ind, int v) {
351 player_type *p_ptr = Players[Ind];
352 bool notice = FALSE;
353
354 /* Hack -- Force good values */
355 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
356
357 /* Open */
358 if (v) {
359 if (!p_ptr->tim_lev) {
360 msg_print(Ind, "You feel light and your feet take off the ground.");
361 notice = TRUE;
362 }
363 }
364
365 /* Shut */
366 else {
367 if (p_ptr->tim_lev) {
368 msg_print(Ind, "You are suddenly a lot heavier.");
369 notice = TRUE;
370 }
371 }
372
373 /* Use the value */
374 p_ptr->tim_lev = v;
375
376 /* Nothing to notice */
377 if (!notice)
378 return (FALSE);
379
380 /* Disturb */
381 if (p_ptr->disturb_state)
382 disturb(Ind, 0, 0);
383
384 /* Recalculate boni */
385 p_ptr->update |= (PU_BONUS);
386
387 /* Result */
388 return (TRUE);
389 }
390
391 /*
392 * Set "p_ptr->adrenaline", notice observable changes
393 * Note the interaction with biofeedback
394 */
set_adrenaline(int Ind,int v)395 bool set_adrenaline(int Ind, int v) {
396 player_type *p_ptr = Players[Ind];
397 bool notice = FALSE;
398
399 int i;
400
401 /* Hack -- Force good values */
402 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
403
404 /* Open */
405 if (v) {
406 if (!p_ptr->adrenaline) {
407 msg_print(Ind, "Adrenaline surges through your veins!");
408 if (p_ptr->biofeedback) {
409 msg_print(Ind, "You lose control of your blood flow!");
410 i = randint(randint(v));
411 take_hit(Ind, damroll(2, i),"adrenaline poisoning", 0);
412 v = v - i + 1;
413 p_ptr->biofeedback = 0;
414 }
415
416 notice = TRUE;
417 } else {
418 /* Sudden crash */
419 if (!rand_int(500) && (p_ptr->adrenaline >= v)) {
420 msg_print(Ind, "Your adrenaline suddenly runs out!");
421 v = 0;
422 }
423 }
424
425 while (v > 30 + randint(p_ptr->lev * 5)) {
426 msg_print(Ind, "Your body can't handle that much adrenaline!");
427 i = randint(randint(v));
428 take_hit(Ind, damroll(3, i * 2),"adrenaline poisoning", 0);
429 v = v - i + 1;
430 }
431 }
432
433 /* Shut */
434 else {
435 if (p_ptr->adrenaline) {
436 if (!rand_int(5)) {
437 msg_print(Ind, "Your adrenaline runs out, leaving you tired and weak.");
438 do_dec_stat(Ind, A_CON, STAT_DEC_TEMPORARY);
439 } else {
440 msg_print(Ind, "Your heart slows down to normal.");
441 }
442 notice = TRUE;
443 }
444 }
445
446 /* Use the value */
447 p_ptr->adrenaline = v;
448
449 /* Nothing to notice */
450 if (!notice) return (FALSE);
451
452 /* Notice */
453 p_ptr->update |= (PU_BONUS | PU_HP);
454
455 /* Disturb */
456 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
457
458 /* Handle stuff */
459 handle_stuff(Ind);
460
461 /* Result */
462 return (TRUE);
463
464 }
465 /*
466 * Set "p_ptr->biofeedback", notice observable changes
467 * Note the interaction with adrenaline
468 */
set_biofeedback(int Ind,int v)469 bool set_biofeedback(int Ind, int v) {
470 player_type *p_ptr = Players[Ind];
471 bool notice = FALSE;
472
473 /* Hack -- Force good values */
474 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
475
476 /* Open */
477 if (v) {
478 if (!p_ptr->biofeedback) {
479 msg_print(Ind, "Your pulse slows and your body prepares to resist damage.");
480 if (p_ptr->adrenaline) {
481 msg_print(Ind, "The adrenaline drains out of your veins.");
482 p_ptr->adrenaline = 0;
483 if (!rand_int(8)) {
484 msg_print(Ind, "You start to tremble as your blood sugar crashes.");
485 set_slow(Ind, p_ptr->slow + rand_int(rand_int(16)));
486 if (!rand_int(5)) set_paralyzed(Ind, p_ptr->paralyzed + 1);
487 if (!rand_int(3)) set_stun(Ind, p_ptr->stun + rand_int(30));
488 }
489 }
490 notice = TRUE;
491 }
492 }
493
494 /* Shut */
495 else {
496 if (p_ptr->biofeedback) {
497 msg_print(Ind, "Your veins return to normal.");
498 notice = TRUE;
499 }
500 }
501
502 while (v > 35 + rand_int(rand_int(p_ptr->lev))) {
503 msg_print(Ind, "You speed up your pulse to avoid fainting!");
504 v -= 20;
505 }
506
507 /* Use the value */
508 p_ptr->biofeedback = v;
509
510 /* Nothing to notice */
511 if (!notice) return (FALSE);
512
513 /* Notice */
514 p_ptr->update |= (PU_BONUS | PU_HP);
515
516 /* Disturb */
517 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
518
519 /* Handle stuff */
520 handle_stuff(Ind);
521
522 /* Result */
523 return (TRUE);
524
525 }
526
527
528 /*
529 * Set "p_ptr->tim_esp", notice observable changes
530 */
set_tim_esp(int Ind,int v)531 bool set_tim_esp(int Ind, int v) {
532 player_type *p_ptr = Players[Ind];
533 bool notice = FALSE;
534
535 /* Hack -- Force good values */
536 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
537
538 /* Open */
539 if (v) {
540 if (!p_ptr->tim_esp) {
541 msg_print(Ind, "Your mind expands !");
542 notice = TRUE;
543 }
544 }
545
546 /* Shut */
547 else {
548 if (p_ptr->tim_esp) {
549 msg_print(Ind, "Your mind retracts.");
550 notice = TRUE;
551 }
552 }
553
554 /* Use the value */
555 p_ptr->tim_esp = v;
556
557 /* Nothing to notice */
558 if (!notice) return (FALSE);
559
560 /* Disturb */
561 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
562
563 /* Recalculate boni */
564 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
565
566 /* Handle stuff */
567 handle_stuff(Ind);
568
569 /* Result */
570 return (TRUE);
571 }
572
573
574 /*
575 * Set "p_ptr->st_anchor", notice observable changes
576 */
set_st_anchor(int Ind,int v)577 bool set_st_anchor(int Ind, int v) {
578 player_type *p_ptr = Players[Ind];
579 bool notice = FALSE;
580
581 /* Hack -- Force good values */
582 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
583
584 /* Open */
585 if (v) {
586 if (!p_ptr->st_anchor) {
587 //msg_print(Ind, "The Space/Time Continuum seems to solidify !");
588 msg_print(Ind, "The air feels very still.");
589 notice = TRUE;
590 }
591 }
592
593 /* Shut */
594 else {
595 if (p_ptr->st_anchor) {
596 //msg_print(Ind, "The Space/Time Continuum seems more flexible.");
597 msg_print(Ind, "The air feels fresh again.");
598 notice = TRUE;
599 }
600 }
601
602 /* Use the value */
603 p_ptr->st_anchor = v;
604
605 /* Nothing to notice */
606 if (!notice) return (FALSE);
607
608 /* Disturb */
609 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
610
611 /* Recalculate boni */
612 p_ptr->update |= (PU_BONUS);
613
614 /* Handle stuff */
615 handle_stuff(Ind);
616
617 /* Result */
618 return (TRUE);
619 }
620
621 /*
622 * Set "p_ptr->prob_travel", notice observable changes
623 */
set_prob_travel(int Ind,int v)624 bool set_prob_travel(int Ind, int v) {
625 player_type *p_ptr = Players[Ind];
626 bool notice = FALSE;
627
628 /* Hack -- Force good values */
629 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
630
631 /* Open */
632 if (v) {
633 if (!p_ptr->prob_travel) {
634 msg_print(Ind, "You feel instable !");
635 notice = TRUE;
636 }
637 }
638
639 /* Shut */
640 else {
641 if (p_ptr->prob_travel) {
642 msg_print(Ind, "You feel more stable.");
643 notice = TRUE;
644 }
645 }
646
647 /* Use the value */
648 p_ptr->prob_travel = v;
649
650 /* Nothing to notice */
651 if (!notice) return (FALSE);
652
653 /* Disturb */
654 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
655
656 /* Recalculate boni */
657 p_ptr->update |= (PU_BONUS);
658
659 /* Handle stuff */
660 handle_stuff(Ind);
661
662 /* Result */
663 return (TRUE);
664 }
665
666 /*
667 * Set "p_ptr->brand", notice observable changes
668 */
set_brand(int Ind,int v,int t,int p)669 bool set_brand(int Ind, int v, int t, int p) {
670 player_type *p_ptr = Players[Ind];
671 bool notice = FALSE, plural;
672 char weapons[20];
673
674 if (p_ptr->inventory[INVEN_WIELD].k_idx && /* dual-wield */
675 (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) {
676 strcpy(weapons, "\377wYour weapons");
677 plural = TRUE;
678 } else if (p_ptr->inventory[INVEN_WIELD].k_idx ||
679 (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) {
680 strcpy(weapons, "\377wYour weapon");
681 plural = FALSE;
682 } else {
683 if (v) msg_print(Ind, "You are not wielding any melee weapons to brand."); /* failure */
684 else { /* Shut */
685 p_ptr->brand = 0;
686 p_ptr->brand_t = 0;
687 p_ptr->brand_d = 0;
688 }
689 return FALSE; /* don't notice anything */
690 }
691
692 /* Hack -- Force good values */
693 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
694
695 /* Open */
696 if (v) {
697 if (!p_ptr->brand &&
698 (p_ptr->inventory[INVEN_WIELD].k_idx || /* dual-wield..*/
699 (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD))) {
700 switch (t) {
701 case BRAND_ELEC:
702 case BRAND_BALL_ELEC:
703 if (plural) msg_format(Ind, "%s sparkle with lightning!", weapons);
704 else msg_format(Ind, "%s sparkles with lightning!", weapons);
705 break;
706 case BRAND_BALL_COLD:
707 case BRAND_COLD:
708 if (plural) msg_format(Ind, "%s freeze!", weapons);
709 else msg_format(Ind, "%s freezes!", weapons);
710 break;
711 case BRAND_BALL_FIRE:
712 case BRAND_FIRE:
713 if (plural) msg_format(Ind, "%s burn!", weapons);
714 else msg_format(Ind, "%s burns!", weapons);
715 break;
716 case BRAND_BALL_ACID:
717 case BRAND_ACID:
718 if (plural) msg_format(Ind, "%s drip acid!", weapons);
719 else msg_format(Ind, "%s drips acid!", weapons);
720 break;
721 case BRAND_POIS:
722 if (plural) msg_format(Ind, "%s are covered with venom!", weapons);
723 else msg_format(Ind, "%s is covered with venom!", weapons);
724 break;
725 case BRAND_BASE:
726 if (plural) msg_format(Ind, "%s glow in many colours!", weapons);
727 else msg_format(Ind, "%s glows in many colours!", weapons);
728 break;
729 case BRAND_CHAO:
730 if (plural) msg_format(Ind, "%s seem to twist and warp!", weapons); //used experimentally
731 else msg_format(Ind, "%s seems to twist and warp!", weapons); //used experimentally
732 break;
733 case BRAND_VORP:
734 if (plural) msg_format(Ind, "%s sharpen!", weapons); //not used
735 else msg_format(Ind, "%s sharpens!", weapons); //not used
736 break;
737 case BRAND_BALL_SOUN:
738 if (plural) msg_format(Ind, "%s vibrate!", weapons); //not used
739 else msg_format(Ind, "%s vibrates!", weapons); //not used
740 break;
741 }
742 notice = TRUE;
743 }
744 }
745
746 /* Shut */
747 else {
748 if (p_ptr->brand) {
749 if (plural) msg_print(Ind, "\377oThe branding magic on your weapons ceases again.");
750 else msg_print(Ind, "\377oThe branding magic on your weapon ceases again.");
751 notice = TRUE;
752 t = 0;
753 p = 0;
754 }
755 }
756
757 /* Use the value */
758 p_ptr->brand = v;
759 p_ptr->brand_t = t;
760 p_ptr->brand_d = p;
761
762
763 /* Nothing to notice */
764 if (!notice) return (FALSE);
765
766 /* Disturb */
767 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
768
769 /* Recalculate boni */
770 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
771
772 /* Handle stuff */
773 handle_stuff(Ind);
774
775 /* Result */
776 return (TRUE);
777 }
778
779 /*
780 * Set "p_ptr->bow_brand_xxx", notice observable changes
781 */
set_bow_brand(int Ind,int v,int t,int p)782 bool set_bow_brand(int Ind, int v, int t, int p) {
783 player_type *p_ptr = Players[Ind];
784 bool notice = FALSE;
785
786 if (!p_ptr->inventory[INVEN_AMMO].k_idx) {
787 if (v) msg_print(Ind, "Your quiver does not hold any ammunition to brand."); /* failure */
788 else { /* Shut */
789 p_ptr->bow_brand = 0;
790 p_ptr->bow_brand_t = 0;
791 p_ptr->bow_brand_d = 0;
792 }
793 return FALSE; /* don't notice anything */
794 }
795
796 /* Hack -- Force good values */
797 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
798
799 /* Open */
800 if (v) {
801 if (!p_ptr->bow_brand) {
802 switch (t) {
803 case BRAND_ELEC:
804 case BRAND_BALL_ELEC:
805 msg_print(Ind, "\377oYour ammunition sparkles with lightnings!");
806 break;
807 case BRAND_BALL_COLD:
808 case BRAND_COLD:
809 msg_print(Ind, "\377oYour ammunition freezes!");
810 break;
811 case BRAND_BALL_FIRE:
812 case BRAND_FIRE:
813 msg_print(Ind, "\377oYour ammunition burns!");
814 break;
815 case BRAND_BALL_ACID:
816 case BRAND_ACID:
817 msg_print(Ind, "\377oYour ammunition drips acid!");
818 break;
819 case BRAND_POIS:
820 msg_print(Ind, "\377oYour ammunition is covered with venom!");
821 break;
822 case BRAND_BASE:
823 msg_print(Ind, "\377oYour ammunition glows in many colours!");
824 break;
825 case BRAND_CHAO:
826 msg_print(Ind, "\377oYour ammunition seems to twist and warp!");
827 break;
828 case BRAND_VORP:
829 msg_print(Ind, "\377oYour ammunition sharpens!");
830 break;
831 case BRAND_BALL_SOUN:
832 msg_print(Ind, "\377oYour ammunition vibrates!");
833 break;
834 }
835 notice = TRUE;
836 }
837 }
838
839 /* Shut */
840 else {
841 if (p_ptr->bow_brand) {
842 msg_print(Ind, "\377oThe branding magic on your ammunition ceases again.");
843 notice = TRUE;
844 t = 0;
845 p = 0;
846 }
847 }
848
849 /* Use the value */
850 p_ptr->bow_brand = v;
851 p_ptr->bow_brand_t = t;
852 p_ptr->bow_brand_d = p;
853
854
855 /* Nothing to notice */
856 if (!notice) return (FALSE);
857
858 /* Disturb */
859 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
860
861 /* Recalculate boni */
862 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
863
864 /* Handle stuff */
865 handle_stuff(Ind);
866
867 /* Result */
868 return (TRUE);
869 }
870
871
872 /*
873 * Set "p_ptr->tim_mimic", notice observable changes
874 */
set_mimic(int Ind,int v,int p)875 bool set_mimic(int Ind, int v, int p) {
876 player_type *p_ptr = Players[Ind];
877 bool notice = FALSE;
878
879 /* force good values */
880 if (v < 0) v = 0;
881
882 /* Open */
883 if (v) {
884 if (!p_ptr->tim_mimic) {
885 msg_print(Ind, "Your image changes!");
886 notice = TRUE;
887 } else if (p_ptr->tim_mimic > 100 && v <= 100) {
888 msg_print(Ind, "\376\377LThe magical force stabilizing your form starts to fade...");
889 }
890 }
891
892 /* Shut */
893 else {
894 if (p_ptr->tim_mimic && p_ptr->body_monster == p_ptr->tim_mimic_what) {
895 msg_print(Ind, "\376\377LYour image changes back to normality.");
896 do_mimic_change(Ind, 0, TRUE);
897 notice = TRUE;
898 }
899 }
900
901 /* Use the value */
902 p_ptr->tim_mimic = v;
903
904 #if 0 /* once you might have mimicked other classes, now we will use it for polymorph rings! */
905 /* Enforce good values */
906 if (p < 0) p = 0;
907 if (p >= MAX_CLASS) p = MAX_CLASS - 1;
908 p_ptr->tim_mimic_what = p;
909 #endif
910
911 /* Nothing to notice */
912 if (!notice) return (FALSE);
913
914 /* Disturb */
915 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
916
917 /* Recalculate boni */
918 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
919
920 /* Handle stuff */
921 handle_stuff(Ind);
922
923 /* Result */
924 return (TRUE);
925 }
926
927 /*
928 * Set "p_ptr->tim_manashield", notice observable changes
929 */
set_tim_manashield(int Ind,int v)930 bool set_tim_manashield(int Ind, int v) {
931 player_type *p_ptr = Players[Ind];
932 bool notice = FALSE;
933
934 /* Hack -- Force good values */
935 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
936
937 /* Open */
938 if (v) {
939 if (!p_ptr->tim_manashield) {
940 msg_print(Ind, "\376\377wA purple shimmering shield forms around your body!");
941 notice = TRUE;
942 } else if (p_ptr->tim_manashield > 15 && v <= 15) {
943 msg_print(Ind, "\376\377vThe disruption shield starts to flicker and fade...");
944 }
945 }
946
947 /* Shut */
948 else {
949 if (p_ptr->tim_manashield) {
950 msg_print(Ind, "\376\377vThe disruption shield fades away.");
951 notice = TRUE;
952 }
953 }
954
955 /* Use the value */
956 p_ptr->tim_manashield = v;
957
958 /* Nothing to notice */
959 if (!notice) return (FALSE);
960
961 /* Disturb */
962 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
963
964 /* Recalculate boni */
965 p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA);
966
967 /* update so everyone sees the colour animation */
968 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
969
970 /* Handle stuff */
971 handle_stuff(Ind);
972
973 /* Result */
974 return (TRUE);
975 }
976
977 /*
978 * Set "p_ptr->tim_traps", notice observable changes
979 */
set_tim_traps(int Ind,int v)980 bool set_tim_traps(int Ind, int v) {
981 player_type *p_ptr = Players[Ind];
982 bool notice = FALSE;
983
984 /* Hack -- Force good values */
985 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
986
987 /* Open */
988 if (v) {
989 if (!p_ptr->tim_traps) {
990 msg_print(Ind, "You can avoid all the traps !");
991 notice = TRUE;
992 }
993 }
994
995 /* Shut */
996 else {
997 if (p_ptr->tim_traps) {
998 msg_print(Ind, "You should worry about traps again.");
999 notice = TRUE;
1000 }
1001 }
1002
1003 /* Use the value */
1004 p_ptr->tim_traps = v;
1005
1006 /* Nothing to notice */
1007 if (!notice) return (FALSE);
1008
1009 /* Disturb */
1010 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1011
1012 /* Recalculate boni */
1013 p_ptr->update |= (PU_BONUS);
1014
1015 /* Handle stuff */
1016 handle_stuff(Ind);
1017
1018 /* Result */
1019 return (TRUE);
1020 }
1021
1022 /*
1023 * Set "p_ptr->tim_invis", notice observable changes
1024 */
set_invis(int Ind,int v,int p)1025 bool set_invis(int Ind, int v, int p) {
1026 player_type *p_ptr = Players[Ind];
1027 bool notice = FALSE;
1028
1029 /* Hack -- Force good values */
1030 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1031
1032 /* Open */
1033 if (v) {
1034 if (!p_ptr->tim_invisibility && !p_ptr->invis) {
1035 msg_format_near(Ind, "%s fades in the shadows!", p_ptr->name);
1036 msg_print(Ind, "You fade in the shadow!");
1037 notice = TRUE;
1038 }
1039 }
1040
1041 /* Shut */
1042 else {
1043 if (p_ptr->tim_invisibility && !p_ptr->invis) {
1044 msg_format_near(Ind, "The shadows enveloping %s disipate.", p_ptr->name);
1045 msg_print(Ind, "The shadows enveloping you disipate.");
1046 notice = TRUE;
1047 }
1048 p = 0;
1049 }
1050
1051 /* Use the value */
1052 p_ptr->tim_invisibility = v;
1053 p_ptr->tim_invis_power2 = p;
1054
1055 /* Nothing to notice */
1056 if (!notice) return (FALSE);
1057
1058 /* Disturb */
1059 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1060
1061 /* Recalculate boni */
1062 p_ptr->update |= (PU_BONUS | PU_MONSTERS);
1063
1064 /* Handle stuff */
1065 handle_stuff(Ind);
1066
1067 /* Result */
1068 return (TRUE);
1069 }
1070
1071 /*
1072 * Set "p_ptr->fury", notice observable changes
1073 */
set_fury(int Ind,int v)1074 bool set_fury(int Ind, int v) {
1075 player_type *p_ptr = Players[Ind];
1076 bool notice = FALSE;
1077
1078 /* Hack -- Force good values */
1079 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1080
1081 /* Open */
1082 if (v) {
1083 if (!p_ptr->fury) {
1084 msg_print(Ind, "You grow a fury!");
1085 notice = TRUE;
1086 }
1087 }
1088
1089 /* Shut */
1090 else {
1091 if (p_ptr->fury) {
1092 msg_print(Ind, "The fury stops.");
1093 notice = TRUE;
1094 }
1095 }
1096
1097 /* Use the value */
1098 p_ptr->fury = v;
1099
1100 /* Nothing to notice */
1101 if (!notice) return (FALSE);
1102
1103 /* Disturb */
1104 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1105
1106 /* Recalculate boni + hit points */
1107 p_ptr->update |= (PU_BONUS | PU_HP);
1108
1109 /* Handle stuff */
1110 handle_stuff(Ind);
1111
1112 /* Result */
1113 return (TRUE);
1114 }
1115
1116
1117 /*
1118 * Set "p_ptr->tim_meditation", notice observable changes
1119 */
set_tim_meditation(int Ind,int v)1120 bool set_tim_meditation(int Ind, int v) {
1121 player_type *p_ptr = Players[Ind];
1122 bool notice = FALSE;
1123
1124 /* Hack -- Force good values */
1125 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1126
1127 /* Open */
1128 if (v) {
1129 if (!p_ptr->tim_meditation) {
1130 msg_format_near(Ind, "%s starts a calm meditation!", p_ptr->name);
1131 msg_print(Ind, "You start a calm meditation!");
1132 notice = TRUE;
1133 }
1134 }
1135
1136 /* Shut */
1137 else {
1138 if (p_ptr->tim_meditation) {
1139 msg_format_near(Ind, "%s stops meditating.", p_ptr->name);
1140 msg_print(Ind, "You stop your meditation.");
1141 notice = TRUE;
1142 }
1143 }
1144
1145 /* Use the value */
1146 p_ptr->tim_meditation = v;
1147
1148 /* Nothing to notice */
1149 if (!notice) return (FALSE);
1150
1151 /* Disturb */
1152 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1153
1154 /* Recalculate boni */
1155 p_ptr->update |= (PU_HP | PU_MANA);
1156
1157 /* Handle stuff */
1158 handle_stuff(Ind);
1159
1160 /* Result */
1161 return (TRUE);
1162 }
1163
1164 /*
1165 * Set "p_ptr->tim_wraith", notice observable changes
1166 */
set_tim_wraith(int Ind,int v)1167 bool set_tim_wraith(int Ind, int v) {
1168 player_type *p_ptr = Players[Ind];
1169 bool notice = FALSE;
1170 cave_type **zcave;
1171 dun_level *l_ptr = getfloor(&p_ptr->wpos);
1172 if (!(zcave = getcave(&p_ptr->wpos))) return FALSE;
1173
1174 /* Hack -- Force good values */
1175 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1176
1177 /* Open */
1178 if (v) {
1179 if (!p_ptr->tim_wraith) {
1180 if ((zcave[p_ptr->py][p_ptr->px].info & CAVE_STCK) ||
1181 (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_MAGIC)))
1182 {
1183 msg_print(Ind, "You feel different for a moment");
1184 v = 0;
1185 } else {
1186 msg_format_near(Ind, "%s turns into a wraith!", p_ptr->name);
1187 msg_print(Ind, "You turn into a wraith!");
1188 notice = TRUE;
1189
1190 p_ptr->wraith_in_wall = TRUE;
1191 }
1192 }
1193 #if 0 // I can't remember what was it for..
1194 // but for sure it's wrong
1195 //it was probably for the old hack to prevent wraithing in/around town and breaking into houses that way - C. Blue
1196 else if(!p_ptr->wpos.wz && cave_floor_bold(zcave, p_ptr->py, p_ptr->px))
1197 return(FALSE);
1198 #endif // 0
1199 }
1200
1201 /* Shut */
1202 else {
1203 if (p_ptr->tim_wraith) {
1204 /* In town it only runs out if you are not on a wall
1205 * To prevent breaking into houses */
1206 /* important! check for illegal spaces */
1207 cave_type **zcave;
1208 zcave = getcave(&p_ptr->wpos);
1209
1210 if (zcave && in_bounds(p_ptr->py, p_ptr->px)) {
1211 /* if a worn item grants wraith form, don't let it run out */
1212 u32b f1, f2, f3, f4, f5, f6, esp;
1213 object_type *o_ptr;
1214 int i;
1215 /* Scan the usable inventory */
1216 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) {
1217 o_ptr = &p_ptr->inventory[i];
1218 /* Skip missing items */
1219 if (!o_ptr->k_idx) continue;
1220 /* Extract the item flags */
1221 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1222 if (f3 & (TR3_WRAITH)) {
1223 //p_ptr->wraith_form = TRUE;
1224 v = 30000;
1225 }
1226 }
1227 if (v != 30000) {
1228 msg_format_near(Ind, "%s loses %s wraith powers.", p_ptr->name, p_ptr->male ? "his":"her");
1229 msg_print(Ind, "You lose your wraith powers.");
1230 notice = TRUE;
1231
1232 /* That will hopefully prevent game hinging when loading */
1233 if (cave_floor_bold(zcave, p_ptr->py, p_ptr->px)) p_ptr->wraith_in_wall = FALSE;
1234 }
1235 }
1236 else v = 1;
1237 }
1238 }
1239
1240 /* Use the value */
1241 p_ptr->tim_wraith = v;
1242
1243 /* Nothing to notice */
1244 if (!notice) return (FALSE);
1245
1246 /* Disturb */
1247 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1248
1249 /* Recalculate boni */
1250 p_ptr->update |= (PU_BONUS);
1251
1252 /* Handle stuff */
1253 handle_stuff(Ind);
1254
1255 /* Result */
1256 return (TRUE);
1257 }
1258
1259 /*
1260 * Set "p_ptr->blind", notice observable changes
1261 *
1262 * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to
1263 * memorize any terrain features which suddenly become "visible".
1264 * Note that blindness is currently the only thing which can affect
1265 * "player_can_see_bold()".
1266 */
set_blind(int Ind,int v)1267 bool set_blind(int Ind, int v) {
1268 player_type *p_ptr = Players[Ind];
1269 bool notice = FALSE;
1270
1271 if (p_ptr->martyr && v) return FALSE;
1272
1273 /* the admin wizard can not be blinded */
1274 if (p_ptr->admin_wiz) return 1;
1275
1276 /* instead put into dungeon.c for faster recovery
1277 if (get_skill(p_ptr, SKILL_HCURING) >= 30) v /= 2;
1278 */
1279 /* Hack -- Force good values */
1280 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1281
1282 /* Open */
1283 if (v) {
1284 if (!p_ptr->blind) {
1285 disturb(Ind, 1, 0); /* stop running and searching */
1286 msg_format_near(Ind, "%s gropes around blindly!", p_ptr->name);
1287 msg_print(Ind, "You are blind!");
1288 notice = TRUE;
1289 }
1290
1291 break_shadow_running(Ind);
1292 }
1293
1294 /* Shut */
1295 else {
1296 if (p_ptr->blind) {
1297 msg_format_near(Ind, "%s can see again.", p_ptr->name);
1298 msg_print(Ind, "You can see again.");
1299 notice = TRUE;
1300 }
1301 }
1302
1303 /* Use the value */
1304 p_ptr->blind = v;
1305
1306 /* Nothing to notice */
1307 if (!notice) return (FALSE);
1308
1309 /* Disturb */
1310 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1311
1312 /* Forget stuff */
1313 p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
1314
1315 /* Update stuff */
1316 p_ptr->update |= (PU_VIEW | PU_LITE | PU_BONUS);
1317
1318 /* Update the monsters */
1319 p_ptr->update |= (PU_MONSTERS);
1320
1321 /* Redraw map */
1322 p_ptr->redraw |= (PR_MAP);
1323
1324 /* Redraw the "blind" */
1325 p_ptr->redraw |= (PR_BLIND);
1326
1327 /* Window stuff */
1328 p_ptr->window |= (PW_OVERHEAD);
1329
1330 /* Handle stuff */
1331 handle_stuff(Ind);
1332
1333 /* Result */
1334 return (TRUE);
1335 }
1336
1337
1338 /*
1339 * Set "p_ptr->confused", notice observable changes
1340 */
set_confused(int Ind,int v)1341 bool set_confused(int Ind, int v) {
1342 player_type *p_ptr = Players[Ind];
1343 bool notice = FALSE;
1344
1345 if (p_ptr->martyr && v) return FALSE;
1346
1347 /* Hack -- Force good values */
1348 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1349
1350 if (get_skill(p_ptr, SKILL_MIND) >= 30) v /= 2;
1351
1352 /* Open */
1353 if (v) {
1354 if (!p_ptr->confused) {
1355 disturb(Ind, 1, 0); /* stop running and searching */
1356 msg_format_near(Ind, "%s appears confused!", p_ptr->name);
1357 msg_print(Ind, "You are confused!");
1358 notice = TRUE;
1359 }
1360
1361 break_cloaking(Ind, 0);
1362 break_shadow_running(Ind);
1363 stop_precision(Ind);
1364 stop_shooting_till_kill(Ind);
1365 }
1366
1367 /* Shut */
1368 else {
1369 if (p_ptr->confused) {
1370 msg_format_near(Ind, "%s appears less confused now.", p_ptr->name);
1371 msg_print(Ind, "You feel less confused now.");
1372 notice = TRUE;
1373 }
1374 }
1375
1376 /* Use the value */
1377 p_ptr->confused = v;
1378
1379 /* Nothing to notice */
1380 if (!notice) return (FALSE);
1381
1382 /* Disturb */
1383 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1384
1385 /* Redraw the "confused" */
1386 p_ptr->redraw |= (PR_CONFUSED);
1387
1388 p_ptr->update |= (PU_BONUS);
1389
1390 /* Handle stuff */
1391 handle_stuff(Ind);
1392
1393 /* Result */
1394 return (TRUE);
1395 }
1396
1397 #ifdef ARCADE_SERVER
set_pushed(int Ind,int dir)1398 void set_pushed(int Ind, int dir) {
1399 player_type *p_ptr = Players[Ind];
1400 p_ptr->pushed = 20;
1401 p_ptr->pushdir = dir;
1402 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1403 handle_stuff(Ind);
1404 return;
1405 }
1406 #endif
1407
1408 /*
1409 * Set "p_ptr->poisoned", notice observable changes
1410 */
set_poisoned(int Ind,int v,int attacker)1411 bool set_poisoned(int Ind, int v, int attacker) {
1412 player_type *p_ptr = Players[Ind];
1413 bool notice = FALSE;
1414
1415 if (p_ptr->martyr && v) return FALSE;
1416
1417 /* Hack -- Force good values */
1418 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1419
1420 /* instead put into dungeon.c for faster recovery
1421 if (get_skill(p_ptr, SKILL_HCURING) >= 30) v /= 2;
1422 */
1423 /* Open */
1424 if (v) {
1425 if (!p_ptr->poisoned) {
1426 msg_print(Ind, "You are poisoned!");
1427 notice = TRUE;
1428
1429 /* Remember who did it - mikaelh */
1430 p_ptr->poisoned_attacker = attacker;
1431 }
1432 }
1433
1434 /* Shut */
1435 else {
1436 if (p_ptr->poisoned) {
1437 msg_print(Ind, "You are no longer poisoned.");
1438 notice = TRUE;
1439
1440 /* Forget who did it - mikaelh */
1441 p_ptr->poisoned_attacker = 0;
1442 }
1443 }
1444
1445 /* Use the value */
1446 p_ptr->poisoned = v;
1447
1448 /* Nothing to notice */
1449 if (!notice) return (FALSE);
1450
1451 /* Disturb */
1452 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1453
1454 /* Redraw the "poisoned" */
1455 p_ptr->redraw |= (PR_POISONED);
1456
1457 /* Handle stuff */
1458 handle_stuff(Ind);
1459
1460 /* Result */
1461 return (TRUE);
1462 }
1463
1464
1465 /*
1466 * Set "p_ptr->afraid", notice observable changes
1467 */
set_afraid(int Ind,int v)1468 bool set_afraid(int Ind, int v) {
1469 player_type *p_ptr = Players[Ind];
1470 bool notice = FALSE;
1471
1472 if (p_ptr->martyr && v) return FALSE;
1473
1474 /* Hack -- Force good values */
1475 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1476
1477 /* Open */
1478 if (v) {
1479 if (!p_ptr->afraid) {
1480 msg_format_near(Ind, "%s cowers in fear!", p_ptr->name);
1481 msg_print(Ind, "You are terrified!");
1482 notice = TRUE;
1483 }
1484 }
1485
1486 /* Shut */
1487 else {
1488 if (p_ptr->afraid) {
1489 msg_format_near(Ind, "%s appears bolder now.", p_ptr->name);
1490 msg_print(Ind, "You feel bolder now.");
1491 notice = TRUE;
1492 }
1493 }
1494
1495 /* Use the value */
1496 p_ptr->afraid = v;
1497
1498 /* Nothing to notice */
1499 if (!notice) return (FALSE);
1500
1501 /* Disturb */
1502 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1503
1504 /* Redraw the "afraid" */
1505 p_ptr->redraw |= (PR_AFRAID);
1506
1507 /* Handle stuff */
1508 handle_stuff(Ind);
1509
1510 /* Result */
1511 return (TRUE);
1512 }
1513
1514
1515 /*
1516 * Set "p_ptr->paralyzed", notice observable changes
1517 */
set_paralyzed(int Ind,int v)1518 bool set_paralyzed(int Ind, int v) {
1519 player_type *p_ptr = Players[Ind];
1520 bool notice = FALSE;
1521
1522 if (p_ptr->martyr && v) return FALSE;
1523
1524 /* Hack -- Force good values */
1525 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1526
1527 /* Open */
1528 if (v) {
1529 if (!p_ptr->paralyzed) {
1530 msg_format_near(Ind, "%s becomes rigid!", p_ptr->name);
1531 msg_print(Ind, "You are paralyzed!");
1532 notice = TRUE;
1533 s_printf("%s EFFECT: Paralyzed %s.\n", showtime(), p_ptr->name);
1534 }
1535 }
1536
1537 /* Shut */
1538 else {
1539 if (p_ptr->paralyzed) {
1540 msg_format_near(Ind, "%s can move again.", p_ptr->name);
1541 msg_print(Ind, "You can move again.");
1542 notice = TRUE;
1543 }
1544 }
1545
1546 /* Use the value */
1547 p_ptr->paralyzed = v;
1548
1549 /* Nothing to notice */
1550 if (!notice) return (FALSE);
1551
1552 /* Disturb */
1553 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1554
1555 /* Redraw the state */
1556 p_ptr->redraw |= (PR_STATE);
1557
1558 p_ptr->update |= (PU_BONUS);
1559
1560 /* Handle stuff */
1561 handle_stuff(Ind);
1562
1563 /* Result */
1564 return (TRUE);
1565 }
1566
1567
1568 /*
1569 * Set "p_ptr->image", notice observable changes
1570 *
1571 * Note that we must redraw the map when hallucination changes.
1572 */
set_image(int Ind,int v)1573 bool set_image(int Ind, int v) {
1574 player_type *p_ptr = Players[Ind];
1575 bool notice = FALSE;
1576
1577 /* Hack -- Force good values */
1578 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1579
1580 /* instead put into dungeon.c for faster recovery
1581 if (get_skill(p_ptr, SKILL_MIND) >= 30) v /= 2;
1582 if (get_skill(p_ptr, SKILL_HCURING) >= 50) v /= 2;
1583 */
1584 /* Open */
1585 if (v) {
1586 if (!p_ptr->image) {
1587 msg_format_near(Ind, "%s has been drugged.", p_ptr->name);
1588 msg_print(Ind, "You feel drugged!");
1589 notice = TRUE;
1590 }
1591 }
1592
1593 /* Shut */
1594 else {
1595 if (p_ptr->image) {
1596 msg_format_near(Ind, "%s has recovered from %s drug induced stupor.", p_ptr->name, p_ptr->male ? "his" : "her");
1597 msg_print(Ind, "You can see clearly again.");
1598 notice = TRUE;
1599 }
1600 }
1601
1602 /* Use the value */
1603 p_ptr->image = v;
1604
1605 /* Nothing to notice */
1606 if (!notice) return (FALSE);
1607
1608 /* Disturb */
1609 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1610
1611 /* Redraw map */
1612 p_ptr->redraw |= (PR_MAP);
1613
1614 /* Update monsters */
1615 p_ptr->update |= (PU_MONSTERS);
1616
1617 /* Window stuff */
1618 p_ptr->window |= (PW_OVERHEAD);
1619
1620 /* Handle stuff */
1621 handle_stuff(Ind);
1622
1623 /* Result */
1624 return (TRUE);
1625 }
1626
1627
1628 /*
1629 * Set "p_ptr->fast", notice observable changes
1630 */
set_fast(int Ind,int v,int p)1631 bool set_fast(int Ind, int v, int p) {
1632 player_type *p_ptr = Players[Ind];
1633 bool notice = FALSE;
1634
1635 if (p_ptr->mode & MODE_PVP) return(FALSE);
1636
1637 /* Hack -- Force good values */
1638 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1639
1640 /* Open */
1641 if (v) {
1642 if (!p_ptr->fast) {
1643 if (p > 0) {
1644 msg_format_near(Ind, "%s begins moving faster!", p_ptr->name);
1645 msg_print(Ind, "You feel yourself moving faster!");
1646 } else {
1647 msg_format_near(Ind, "%s moves slower!", p_ptr->name);
1648 msg_print(Ind, "You feel yourself moving slower!");
1649 }
1650 notice = TRUE;
1651 }
1652 }
1653
1654 /* Shut */
1655 else {
1656 if (p_ptr->fast) {
1657 if (p > 0) {
1658 msg_format_near(Ind, "%s slows down.", p_ptr->name);
1659 msg_print(Ind, "You feel yourself slow down.");
1660 } else {
1661 msg_format_near(Ind, "%s moves faster.", p_ptr->name);
1662 msg_print(Ind, "You feel yourself moving faster");
1663 }
1664 notice = TRUE;
1665 }
1666 }
1667
1668 /* Use the value */
1669 p_ptr->fast = v;
1670 p_ptr->fast_mod = p;
1671
1672 /* Nothing to notice */
1673 if (!notice) return (FALSE);
1674
1675 /* Disturb */
1676 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1677
1678 /* Recalculate boni */
1679 p_ptr->update |= (PU_BONUS);
1680
1681 /* Handle stuff */
1682 handle_stuff(Ind);
1683
1684 /* Result */
1685 return (TRUE);
1686 }
1687
1688
1689 /*
1690 * Set "p_ptr->slow", notice observable changes
1691 */
set_slow(int Ind,int v)1692 bool set_slow(int Ind, int v) {
1693 player_type *p_ptr = Players[Ind];
1694 bool notice = FALSE;
1695
1696 if (p_ptr->martyr && v) return FALSE;
1697
1698 /* Hack -- Force good values */
1699 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1700
1701 /* Open */
1702 if (v) {
1703 if (!p_ptr->slow) {
1704 msg_format_near(Ind, "%s begins moving slower!", p_ptr->name);
1705 msg_print(Ind, "You feel yourself moving slower!");
1706 notice = TRUE;
1707 s_printf("%s EFFECT: Slowed %s.\n", showtime(), p_ptr->name);
1708 }
1709 }
1710
1711 /* Shut */
1712 else {
1713 if (p_ptr->slow) {
1714 msg_format_near(Ind, "%s speeds up.", p_ptr->name);
1715 msg_print(Ind, "You feel yourself speed up.");
1716 notice = TRUE;
1717 }
1718 }
1719
1720 /* Use the value */
1721 p_ptr->slow = v;
1722
1723 /* Nothing to notice */
1724 if (!notice) return (FALSE);
1725
1726 /* Disturb */
1727 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1728
1729 /* Recalculate boni */
1730 p_ptr->update |= (PU_BONUS);
1731
1732 /* Handle stuff */
1733 handle_stuff(Ind);
1734
1735 /* Result */
1736 return (TRUE);
1737 }
1738
1739
1740 /*
1741 * Set "p_ptr->shield", notice observable changes
1742 */
set_shield(int Ind,int v,int p,s16b o,s16b d1,s16b d2)1743 bool set_shield(int Ind, int v, int p, s16b o, s16b d1, s16b d2) {
1744 player_type *p_ptr = Players[Ind];
1745 bool notice = FALSE;
1746
1747 /* Hack -- Force good values */
1748 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1749
1750 /* Open */
1751 if (v) {
1752 if (!p_ptr->shield) {
1753 msg_print(Ind, "A mystic shield forms around your body!");
1754 notice = TRUE;
1755 }
1756 }
1757
1758 /* Shut */
1759 else {
1760 if (p_ptr->shield) {
1761 msg_print(Ind, "Your mystic shield crumbles away.");
1762 notice = TRUE;
1763 }
1764 }
1765
1766
1767 /* Use the value */
1768 p_ptr->shield = v;
1769 if (p_ptr->shield_power != p) notice = TRUE;
1770 p_ptr->shield_power = p;
1771 p_ptr->shield_opt = o;
1772 p_ptr->shield_power_opt = d1;
1773 p_ptr->shield_power_opt2 = d2;
1774
1775 /* Nothing to notice */
1776 if (!notice) return (FALSE);
1777
1778 /* Disturb */
1779 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1780
1781 /* Recalculate boni */
1782 p_ptr->update |= (PU_BONUS);
1783
1784 /* Handle stuff */
1785 handle_stuff(Ind);
1786
1787 /* Result */
1788 return (TRUE);
1789 }
1790
1791 /*
1792 * Set "p_ptr->blessed", notice observable changes
1793 */
set_blessed(int Ind,int v)1794 bool set_blessed(int Ind, int v) {
1795 player_type *p_ptr = Players[Ind];
1796 bool notice = FALSE;
1797
1798 /* Hack -- Force good values */
1799 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1800
1801 /* Open */
1802 if (v) {
1803 if (!p_ptr->blessed) {
1804 msg_format_near(Ind, "%s has become righteous.", p_ptr->name);
1805 msg_print(Ind, "You feel righteous!");
1806 notice = TRUE;
1807 }
1808 }
1809
1810 /* Shut */
1811 else {
1812 if (p_ptr->blessed) {
1813 msg_format_near(Ind, "%s has become less righteous.", p_ptr->name);
1814 msg_print(Ind, "The prayer has expired.");
1815 notice = TRUE;
1816 p_ptr->blessed_power = 0;
1817 }
1818 }
1819
1820 /* Use the value */
1821 p_ptr->blessed = v;
1822
1823 /* Nothing to notice */
1824 if (!notice) return (FALSE);
1825
1826 /* Disturb */
1827 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1828
1829 /* Recalculate boni */
1830 p_ptr->update |= (PU_BONUS);
1831
1832 /* Handle stuff */
1833 handle_stuff(Ind);
1834
1835 /* Result */
1836 return (TRUE);
1837 }
1838
set_res_fear(int Ind,int v)1839 bool set_res_fear(int Ind, int v) {
1840 player_type *p_ptr = Players[Ind];
1841 bool notice = FALSE;
1842
1843 /* Hack -- Force good values */
1844 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1845
1846 /* Open */
1847 if (v) {
1848 if (!p_ptr->res_fear_temp) {
1849 notice = TRUE;
1850 }
1851 }
1852
1853 /* Shut */
1854 else {
1855 if (p_ptr->res_fear_temp) {
1856 notice = TRUE;
1857 }
1858 }
1859
1860 /* Use the value */
1861 p_ptr->res_fear_temp = v;
1862
1863 /* Nothing to notice */
1864 if (!notice) return (FALSE);
1865
1866 /* Disturb */
1867 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1868
1869 /* Recalculate boni */
1870 p_ptr->update |= (PU_BONUS);
1871
1872 /* Handle stuff */
1873 handle_stuff(Ind);
1874
1875 /* Result */
1876 return (TRUE);
1877 }
1878
1879 /*
1880 * Set "p_ptr->hero", notice observable changes
1881 */
set_hero(int Ind,int v)1882 bool set_hero(int Ind, int v) {
1883 player_type *p_ptr = Players[Ind];
1884 bool notice = FALSE;
1885
1886 /* Hack -- Force good values */
1887 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1888
1889 /* Open */
1890 if (v) {
1891 if (!p_ptr->hero) {
1892 msg_format_near(Ind, "%s has become a hero.", p_ptr->name);
1893 msg_print(Ind, "You feel like a hero!");
1894 notice = TRUE;
1895 }
1896 }
1897
1898 /* Shut */
1899 else {
1900 if (p_ptr->hero) {
1901 msg_format_near(Ind, "%s has become less of a hero.", p_ptr->name);
1902 msg_print(Ind, "The heroism wears off.");
1903 notice = TRUE;
1904 }
1905 }
1906
1907 /* Use the value */
1908 p_ptr->hero = v;
1909
1910 /* Nothing to notice */
1911 if (!notice) return (FALSE);
1912
1913 /* Disturb */
1914 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1915
1916 /* Recalculate boni & hit points */
1917 p_ptr->update |= (PU_BONUS | PU_HP);
1918
1919 /* Handle stuff */
1920 handle_stuff(Ind);
1921
1922 /* Result */
1923 return (TRUE);
1924 }
1925
1926
1927 /*
1928 * Set "p_ptr->shero", notice observable changes
1929 */
set_shero(int Ind,int v)1930 bool set_shero(int Ind, int v) {
1931 player_type *p_ptr = Players[Ind];
1932 bool notice = FALSE;
1933
1934 /* Hack -- Force good values */
1935 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1936
1937 /* Open */
1938 if (v) {
1939 if (!p_ptr->shero) {
1940 msg_format_near(Ind, "%s has become a killing machine.", p_ptr->name);
1941 msg_print(Ind, "You feel like a killing machine!");
1942 notice = TRUE;
1943 }
1944 }
1945
1946 /* Shut */
1947 else {
1948 if (p_ptr->shero) {
1949 msg_format_near(Ind, "%s has returned to being a wimp.", p_ptr->name);
1950 msg_print(Ind, "You feel less Berserk.");
1951 notice = TRUE;
1952 }
1953 }
1954
1955 /* Use the value */
1956 p_ptr->shero = v;
1957
1958 /* Nothing to notice */
1959 if (!notice) return (FALSE);
1960
1961 /* Disturb */
1962 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
1963
1964 /* Recalculate boni + hit points */
1965 p_ptr->update |= (PU_BONUS | PU_HP);
1966
1967 /* Handle stuff */
1968 handle_stuff(Ind);
1969
1970 /* Result */
1971 return (TRUE);
1972 }
1973
1974
set_berserk(int Ind,int v)1975 bool set_berserk(int Ind, int v) {
1976 player_type *p_ptr = Players[Ind];
1977 bool notice = FALSE;
1978
1979 /* Hack -- Force good values */
1980 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
1981
1982 /* Open */
1983 if (v) {
1984 if (!p_ptr->berserk) {
1985 msg_format_near(Ind, "%s has become a killing machine.", p_ptr->name);
1986 msg_print(Ind, "You feel like a killing machine!");
1987 notice = TRUE;
1988 }
1989 }
1990
1991 /* Shut */
1992 else {
1993 if (p_ptr->berserk) {
1994 msg_format_near(Ind, "%s has returned to being a wimp.", p_ptr->name);
1995 msg_print(Ind, "You feel less Berserk.");
1996 notice = TRUE;
1997 }
1998 }
1999
2000 /* Use the value */
2001 p_ptr->berserk = v;
2002
2003 /* Nothing to notice */
2004 if (!notice) return (FALSE);
2005
2006 /* Disturb */
2007 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2008
2009 /* Recalculate boni + hit points */
2010 p_ptr->update |= (PU_BONUS | PU_HP);
2011
2012 /* Handle stuff */
2013 handle_stuff(Ind);
2014
2015 /* Result */
2016 return (TRUE);
2017 }
2018
2019
set_melee_sprint(int Ind,int v)2020 bool set_melee_sprint(int Ind, int v) {
2021 player_type *p_ptr = Players[Ind];
2022 bool notice = FALSE;
2023
2024 /* Hack -- Force good values */
2025 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2026
2027 /* Open */
2028 if (v) {
2029 if (!p_ptr->melee_sprint) {
2030 msg_format_near(Ind, "%s starts sprinting.", p_ptr->name);
2031 msg_print(Ind, "You start sprinting!");
2032 notice = TRUE;
2033 }
2034 }
2035
2036 /* Shut */
2037 else {
2038 if (p_ptr->melee_sprint) {
2039 msg_format_near(Ind, "%s slows down.", p_ptr->name);
2040 msg_print(Ind, "You slow down.");
2041 notice = TRUE;
2042 }
2043 }
2044
2045 /* Use the value */
2046 p_ptr->melee_sprint = v;
2047
2048 /* Nothing to notice */
2049 if (!notice) return (FALSE);
2050
2051 /* Disturb */
2052 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2053
2054 /* Recalculate boni */
2055 p_ptr->update |= (PU_BONUS);
2056
2057 /* Recalculate hitpoints */
2058 p_ptr->update |= (PU_HP);
2059
2060 /* Handle stuff */
2061 handle_stuff(Ind);
2062
2063 /* Result */
2064 return (TRUE);
2065 }
2066
2067
2068 /*
2069 * Set "p_ptr->protevil", notice observable changes
2070 */
set_protevil(int Ind,int v)2071 bool set_protevil(int Ind, int v) {
2072 player_type *p_ptr = Players[Ind];
2073 bool notice = FALSE;
2074
2075 /* Hack -- Force good values */
2076 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2077
2078 /* Open */
2079 if (v) {
2080 if (!p_ptr->protevil) {
2081 msg_print(Ind, "You feel safe from evil!");
2082 notice = TRUE;
2083 }
2084 }
2085
2086 /* Shut */
2087 else {
2088 if (p_ptr->protevil) {
2089 msg_print(Ind, "You no longer feel safe from evil.");
2090 notice = TRUE;
2091 }
2092 }
2093
2094 /* Use the value */
2095 p_ptr->protevil = v;
2096
2097 /* Nothing to notice */
2098 if (!notice) return (FALSE);
2099
2100 /* Disturb */
2101 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2102
2103 /* Handle stuff */
2104 handle_stuff(Ind);
2105
2106 /* Result */
2107 return (TRUE);
2108 }
2109
2110
2111 /*
2112 * Set "p_ptr->zeal", notice observable changes
2113 */
set_zeal(int Ind,int p,int v)2114 bool set_zeal(int Ind, int p, int v) {
2115 player_type *p_ptr = Players[Ind];
2116 bool notice = FALSE;
2117
2118 /* Hack -- Force good values */
2119 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2120
2121 /* set EA */
2122 p_ptr->zeal_power = p;
2123
2124 /* Open */
2125 if (v) {
2126 if (!p_ptr->zeal) {
2127 msg_print(Ind, "You heed a holy call!");
2128 notice = TRUE;
2129 }
2130 }
2131
2132 /* Shut */
2133 else {
2134 if (p_ptr->zeal) {
2135 msg_print(Ind, "The holy call fades.");
2136 notice = TRUE;
2137 }
2138 }
2139
2140 /* Use the value */
2141 p_ptr->zeal = v;
2142
2143 /* Nothing to notice */
2144 if (!notice) return (FALSE);
2145
2146 /* Redraw the Blows/Round */
2147 p_ptr->update |= PU_BONUS;
2148
2149 /* Disturb */
2150 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2151
2152 /* Handle stuff */
2153 handle_stuff(Ind);
2154
2155 /* Result */
2156 return (TRUE);
2157 }
2158
set_martyr(int Ind,int v)2159 bool set_martyr(int Ind, int v) {
2160 player_type *p_ptr = Players[Ind];
2161 bool notice = FALSE;
2162
2163 /* Hack: Negative v means initiate martyr */
2164 if (v < 0) {
2165 v = -v;
2166 p_ptr->martyr_dur = v;
2167 }
2168
2169 /* Hack -- Force good values */
2170 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2171
2172 /* Open */
2173 if (v) {
2174 if (!p_ptr->martyr) {
2175 msg_print(Ind, "\377vYou feel the heavens grant your their powers.");
2176 hp_player_quiet(Ind, 5000, FALSE); /* fully heal */
2177 p_ptr->martyr_timeout = 1000;
2178 notice = TRUE;
2179 s_printf("MARTYRDOM: %s\n", p_ptr->name);
2180 } else {
2181 msg_print(Ind, "\377wYou burn in holy fire!");
2182 /* assumes that martyr starts at -15 turns! : */
2183 p_ptr->chp = (p_ptr->mhp * p_ptr->martyr) / p_ptr->martyr_dur;
2184 /* Update health bars */
2185 update_health(0 - Ind);
2186 /* Redraw */
2187 p_ptr->redraw |= (PR_HP);
2188
2189 /* update so everyone sees the colour animation */
2190 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
2191 }
2192 }
2193
2194 /* Shut */
2195 else {
2196 if (p_ptr->martyr) {
2197 /* Increased remaining HP (from 1), to buffer environmental influences
2198 like nether/fire hit from the ground in the Nether Realm;
2199 assumes that martyr starts at -15 turns! : */
2200 // p_ptr->chp = (p_ptr->mhp >= 30 * 15) ? 30 : p_ptr->mhp / 15;
2201 p_ptr->chp = (p_ptr->mhp <= 30 * p_ptr->martyr_dur) ? 30 : p_ptr->mhp / p_ptr->martyr_dur;
2202 /* Update health bars */
2203 update_health(0 - Ind);
2204 /* Redraw */
2205 p_ptr->redraw |= (PR_HP);
2206
2207 msg_print(Ind, "\377vYou collapse as your martyrium ends!");
2208 notice = TRUE;
2209 }
2210 }
2211
2212 /* Use the value */
2213 p_ptr->martyr = v;
2214
2215 /* Nothing to notice */
2216 if (!notice) return (FALSE);
2217
2218 /* Disturb */
2219 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2220
2221 /* update so everyone sees the colour animation */
2222 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
2223
2224 /* Handle stuff */
2225 handle_stuff(Ind);
2226
2227 /* Result */
2228 return (TRUE);
2229 }
2230
2231 /*
2232 * Set "p_ptr->invuln", notice observable changes
2233 */
set_invuln(int Ind,int v)2234 bool set_invuln(int Ind, int v) {
2235 player_type *p_ptr = Players[Ind];
2236 bool notice = FALSE;
2237
2238 /* Hack -- Force good values */
2239 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2240
2241 /* Open */
2242 if (v) {
2243 if (!p_ptr->invuln) {
2244 p_ptr->invuln_dur = v;
2245 msg_print(Ind, "\377A powerful iridescent shield forms around your body!");
2246 notice = TRUE;
2247 } else if (p_ptr->invuln > 5 && v <= 5) {
2248 msg_print(Ind, "\376\377vThe invulnerability shield starts to fade...");
2249 }
2250 }
2251
2252 /* Shut */
2253 else {
2254 if (p_ptr->invuln &&
2255 p_ptr->invuln_dur >= 5) { /* avoid spam on stair-GoI */
2256 msg_print(Ind, "\376\377vThe invulnerability shield fades away.");
2257 }
2258 notice = TRUE;
2259 }
2260
2261 /* Use the value */
2262 p_ptr->invuln = v;
2263
2264 /* Nothing to notice */
2265 if (!notice) return (FALSE);
2266
2267 /* Disturb */
2268 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2269
2270 /* Recalculate boni */
2271 p_ptr->update |= (PU_BONUS);
2272
2273 /* update so everyone sees the colour animation */
2274 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
2275
2276 /* Handle stuff */
2277 handle_stuff(Ind);
2278
2279 /* Result */
2280 return (TRUE);
2281 }
2282
2283 /*
2284 * Set "p_ptr->invuln", but not notice observable changes
2285 * It should be used to protect players from recall-instadeath. - Jir -
2286 * Note: known also as 'stair-GoI' (globe of invulnerability),
2287 * supposed to shortly protect players when they enter a new level. -C. Blue
2288 */
set_invuln_short(int Ind,int v)2289 bool set_invuln_short(int Ind, int v) {
2290 player_type *p_ptr = Players[Ind];
2291
2292 /* not cumulative */
2293 if (p_ptr->invuln > v) return (FALSE);
2294
2295 /* Hack -- Force good values */
2296 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2297
2298 /* Use the value */
2299 p_ptr->invuln = v;
2300 p_ptr->invuln_dur = v;
2301
2302 /* Recalculate boni */
2303 p_ptr->update |= (PU_BONUS);
2304
2305 /* Handle stuff */
2306 handle_stuff(Ind);
2307
2308 /* Result (never noticeable) */
2309 return (FALSE);
2310 }
2311
2312 /*
2313 * Set "p_ptr->tim_invis", notice observable changes
2314 */
set_tim_invis(int Ind,int v)2315 bool set_tim_invis(int Ind, int v) {
2316 player_type *p_ptr = Players[Ind];
2317 bool notice = FALSE;
2318
2319 /* Hack -- Force good values */
2320 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2321
2322 /* Open */
2323 if (v) {
2324 if (!p_ptr->tim_invis) {
2325 msg_print(Ind, "Your eyes feel very sensitive!");
2326 notice = TRUE;
2327 }
2328 }
2329
2330 /* Shut */
2331 else {
2332 if (p_ptr->tim_invis) {
2333 msg_print(Ind, "Your eyes feel less sensitive.");
2334 notice = TRUE;
2335 }
2336 }
2337
2338 /* Use the value */
2339 p_ptr->tim_invis = v;
2340
2341 /* Nothing to notice */
2342 if (!notice) return (FALSE);
2343
2344 /* Disturb */
2345 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2346
2347 /* Recalculate boni */
2348 p_ptr->update |= (PU_BONUS);
2349
2350 /* Update the monsters */
2351 p_ptr->update |= (PU_MONSTERS);
2352
2353 /* Handle stuff */
2354 handle_stuff(Ind);
2355
2356 /* Result */
2357 return (TRUE);
2358 }
2359
2360
2361 /*
2362 * Set "p_ptr->tim_infra", notice observable changes
2363 */
set_tim_infra(int Ind,int v)2364 bool set_tim_infra(int Ind, int v) {
2365 player_type *p_ptr = Players[Ind];
2366 bool notice = FALSE;
2367
2368 /* Hack -- Force good values */
2369 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2370
2371 /* Open */
2372 if (v) {
2373 if (!p_ptr->tim_infra) {
2374 msg_print(Ind, "Your eyes begin to tingle!");
2375 notice = TRUE;
2376 }
2377 }
2378
2379 /* Shut */
2380 else {
2381 if (p_ptr->tim_infra) {
2382 msg_print(Ind, "Your eyes stop tingling.");
2383 notice = TRUE;
2384 }
2385 }
2386
2387 /* Use the value */
2388 p_ptr->tim_infra = v;
2389
2390 /* Nothing to notice */
2391 if (!notice) return (FALSE);
2392
2393 /* Disturb */
2394 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2395
2396 /* Recalculate boni */
2397 p_ptr->update |= (PU_BONUS);
2398
2399 /* Update the monsters */
2400 p_ptr->update |= (PU_MONSTERS);
2401
2402 /* Handle stuff */
2403 handle_stuff(Ind);
2404
2405 /* Result */
2406 return (TRUE);
2407 }
2408
2409
2410 /*
2411 * Set "p_ptr->oppose_acid", notice observable changes
2412 */
set_oppose_acid(int Ind,int v)2413 bool set_oppose_acid(int Ind, int v) {
2414 player_type *p_ptr = Players[Ind];
2415 bool notice = FALSE;
2416
2417 /* Hack -- Force good values */
2418 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2419
2420 /* Open */
2421 if (v) {
2422 if (!p_ptr->oppose_acid) {
2423 msg_print(Ind, "You feel resistant to acid!");
2424 notice = TRUE;
2425 }
2426 }
2427
2428 /* Shut */
2429 else {
2430 if (p_ptr->oppose_acid) {
2431 msg_print(Ind, "\377WYou feel less resistant to \377sacid.");
2432 notice = TRUE;
2433 }
2434 }
2435
2436 /* Use the value */
2437 p_ptr->oppose_acid = v;
2438
2439 /* Nothing to notice */
2440 if (!notice) return (FALSE);
2441
2442 /* Disturb */
2443 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2444
2445 /* Handle stuff */
2446 handle_stuff(Ind);
2447
2448 /* Result */
2449 return (TRUE);
2450 }
2451
2452
2453 /*
2454 * Set "p_ptr->oppose_elec", notice observable changes
2455 */
set_oppose_elec(int Ind,int v)2456 bool set_oppose_elec(int Ind, int v) {
2457 player_type *p_ptr = Players[Ind];
2458 bool notice = FALSE;
2459
2460 /* Hack -- Force good values */
2461 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2462
2463 /* Open */
2464 if (v) {
2465 if (!p_ptr->oppose_elec) {
2466 msg_print(Ind, "You feel resistant to electricity!");
2467 notice = TRUE;
2468 }
2469 }
2470
2471 /* Shut */
2472 else {
2473 if (p_ptr->oppose_elec) {
2474 msg_print(Ind, "\377WYou feel less resistant to \377belectricity.");
2475 notice = TRUE;
2476 }
2477 }
2478
2479 /* Use the value */
2480 p_ptr->oppose_elec = v;
2481
2482 /* Nothing to notice */
2483 if (!notice) return (FALSE);
2484
2485 /* Disturb */
2486 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2487
2488 /* Handle stuff */
2489 handle_stuff(Ind);
2490
2491 /* Result */
2492 return (TRUE);
2493 }
2494
2495
2496 /*
2497 * Set "p_ptr->oppose_fire", notice observable changes
2498 */
set_oppose_fire(int Ind,int v)2499 bool set_oppose_fire(int Ind, int v) {
2500 player_type *p_ptr = Players[Ind];
2501 bool notice = FALSE;
2502
2503 /* Hack -- Force good values */
2504 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2505
2506 /* Open */
2507 if (v) {
2508 if (!p_ptr->oppose_fire) {
2509 msg_print(Ind, "You feel resistant to fire!");
2510 notice = TRUE;
2511 }
2512 }
2513
2514 /* Shut */
2515 else {
2516 if (p_ptr->oppose_fire) {
2517 msg_print(Ind, "\377WYou feel less resistant to \377rfire.");
2518 notice = TRUE;
2519 }
2520 }
2521
2522 /* Use the value */
2523 p_ptr->oppose_fire = v;
2524
2525 /* Nothing to notice */
2526 if (!notice) return (FALSE);
2527
2528 /* Disturb */
2529 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2530
2531 /* Handle stuff */
2532 handle_stuff(Ind);
2533
2534 /* Result */
2535 return (TRUE);
2536 }
2537
2538
2539 /*
2540 * Set "p_ptr->oppose_cold", notice observable changes
2541 */
set_oppose_cold(int Ind,int v)2542 bool set_oppose_cold(int Ind, int v) {
2543 player_type *p_ptr = Players[Ind];
2544 bool notice = FALSE;
2545
2546 /* Hack -- Force good values */
2547 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2548
2549 /* Open */
2550 if (v) {
2551 if (!p_ptr->oppose_cold) {
2552 msg_print(Ind, "You feel resistant to cold!");
2553 notice = TRUE;
2554 }
2555 }
2556
2557 /* Shut */
2558 else {
2559 if (p_ptr->oppose_cold) {
2560 msg_print(Ind, "\377WYou feel less resistant to \377wcold.");
2561 notice = TRUE;
2562 }
2563 }
2564
2565 /* Use the value */
2566 p_ptr->oppose_cold = v;
2567
2568 /* Nothing to notice */
2569 if (!notice) return (FALSE);
2570
2571 /* Disturb */
2572 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2573
2574 /* Handle stuff */
2575 handle_stuff(Ind);
2576
2577 /* Result */
2578 return (TRUE);
2579 }
2580
2581
2582 /*
2583 * Set "p_ptr->oppose_pois", notice observable changes
2584 */
set_oppose_pois(int Ind,int v)2585 bool set_oppose_pois(int Ind, int v) {
2586 player_type *p_ptr = Players[Ind];
2587 bool notice = FALSE;
2588
2589 /* Hack -- Force good values */
2590 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2591
2592 /* Open */
2593 if (v) {
2594 if (!p_ptr->oppose_pois) {
2595 msg_print(Ind, "You feel resistant to poison!");
2596 notice = TRUE;
2597 }
2598 }
2599
2600 /* Shut */
2601 else {
2602 if (p_ptr->oppose_pois) {
2603 msg_print(Ind, "\377WYou feel less resistant to \377gpoison.");
2604 notice = TRUE;
2605 }
2606 }
2607
2608 /* Use the value */
2609 p_ptr->oppose_pois = v;
2610
2611 /* Nothing to notice */
2612 if (!notice) return (FALSE);
2613
2614 /* Disturb */
2615 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2616
2617 /* Handle stuff */
2618 handle_stuff(Ind);
2619
2620 /* Result */
2621 return (TRUE);
2622 }
2623
2624
2625 /*
2626 * Set "p_ptr->stun", notice observable changes
2627 *
2628 * Note the special code to only notice "range" changes.
2629 */
set_stun(int Ind,int v)2630 bool set_stun(int Ind, int v) {
2631 player_type *p_ptr = Players[Ind];
2632 int old_aux, new_aux;
2633 bool notice = FALSE;
2634
2635 if (p_ptr->martyr && v) return FALSE;
2636
2637 /* hack -- the admin wizard can not be stunned */
2638 // if (p_ptr->admin_wiz) return TRUE;
2639
2640 /* Hack -- Force good values */
2641 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2642
2643 #if 0 /* decided to make it just as combat skill working in dungeon.c to accelerate recovery! */
2644 /* apply HCURING in a special way: halve the duration of highest stun level that actually gets reached */
2645 if (get_skill(p_ptr, SKILL_HCURING) >= 40) v /= 2;
2646 #endif
2647
2648 /* Knocked out */
2649 if (p_ptr->stun > 100) old_aux = 3;
2650 /* Heavy stun */
2651 else if (p_ptr->stun > 50) old_aux = 2;
2652 /* Stun */
2653 else if (p_ptr->stun > 0) old_aux = 1;
2654 /* None */
2655 else old_aux = 0;
2656
2657 /* Knocked out */
2658 if (v > 100) new_aux = 3;
2659 /* Heavy stun */
2660 else if (v > 50) new_aux = 2;
2661 /* Stun */
2662 else if (v > 0) new_aux = 1;
2663 /* None */
2664 else new_aux = 0;
2665
2666 /* Increase stun */
2667 if (new_aux > old_aux) {
2668 /* Describe the state */
2669 switch (new_aux) {
2670 /* Stun */
2671 case 1:
2672 msg_format_near(Ind, "\377o%s appears stunned.", p_ptr->name);
2673 msg_print(Ind, "\377oYou have been stunned.");
2674 break;
2675
2676 /* Heavy stun */
2677 case 2:
2678 msg_format_near(Ind, "\377o%s is heavily stunned.", p_ptr->name);
2679 msg_print(Ind, "\377oYou have been heavily stunned.");
2680 break;
2681
2682 /* Knocked out */
2683 case 3:
2684 msg_format_near(Ind, "%s has been knocked out.", p_ptr->name);
2685 msg_print(Ind, "\377rYou have been knocked out.");
2686 s_printf("%s EFFECT: Knockedout %s.\n", showtime(), p_ptr->name);
2687 p_ptr->energy = 0;/* paranoia, couldn't reproduce it so far - don't allow him a final action with his rest of energy */
2688 break;
2689 }
2690
2691 break_shadow_running(Ind);
2692
2693 /* Notice */
2694 notice = TRUE;
2695 }
2696
2697 /* Decrease cut */
2698 else if (new_aux < old_aux) {
2699 /* Describe the state */
2700 switch (new_aux) {
2701 /* None */
2702 case 0:
2703 msg_format_near(Ind, "\377o%s is no longer stunned.", p_ptr->name);
2704 msg_print(Ind, "\377yYou are no longer stunned.");
2705 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2706 break;
2707 }
2708
2709 /* Notice */
2710 notice = TRUE;
2711 }
2712
2713 /* Use the value */
2714 p_ptr->stun = v;
2715
2716 /* No change */
2717 if (!notice) return (FALSE);
2718
2719 /* Disturb */
2720 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2721
2722 /* Recalculate boni */
2723 p_ptr->update |= (PU_BONUS);
2724
2725 /* Redraw the "stun" */
2726 p_ptr->redraw |= (PR_STUN);
2727
2728 /* Handle stuff */
2729 handle_stuff(Ind);
2730
2731 /* Result */
2732 return (TRUE);
2733 }
2734
2735
2736 /*
2737 * Set "p_ptr->cut", notice observable changes
2738 *
2739 * Note the special code to only notice "range" changes.
2740 */
set_cut(int Ind,int v,int attacker)2741 bool set_cut(int Ind, int v, int attacker) {
2742 player_type *p_ptr = Players[Ind];
2743 int old_aux, new_aux;
2744 bool notice = FALSE;
2745
2746 if (p_ptr->martyr && v) return FALSE;
2747
2748 /* Hack -- Force good values */
2749 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2750
2751 /* instead put into dungeon.c for faster recovery
2752 if (get_skill(p_ptr, SKILL_HCURING) >= 40) v /= 2;
2753 */
2754
2755 /* p_ptr->no_cut? for mimic forms that cannot bleed */
2756 if (p_ptr->no_cut) v = 0;
2757
2758 /* a ghost never bleeds */
2759 if (v && p_ptr->ghost) v = 0;
2760
2761 /* Mortal wound */
2762 if (p_ptr->cut > 1000) old_aux = 7;
2763 /* Deep gash */
2764 else if (p_ptr->cut > 200) old_aux = 6;
2765 /* Severe cut */
2766 else if (p_ptr->cut > 100) old_aux = 5;
2767 /* Nasty cut */
2768 else if (p_ptr->cut > 50) old_aux = 4;
2769 /* Bad cut */
2770 else if (p_ptr->cut > 25) old_aux = 3;
2771 /* Light cut */
2772 else if (p_ptr->cut > 10) old_aux = 2;
2773 /* Graze */
2774 else if (p_ptr->cut > 0) old_aux = 1;
2775 /* None */
2776 else old_aux = 0;
2777
2778 /* Mortal wound */
2779 if (v > 1000) new_aux = 7;
2780 /* Deep gash */
2781 else if (v > 200) new_aux = 6;
2782 /* Severe cut */
2783 else if (v > 100) new_aux = 5;
2784 /* Nasty cut */
2785 else if (v > 50) new_aux = 4;
2786 /* Bad cut */
2787 else if (v > 25) new_aux = 3;
2788 /* Light cut */
2789 else if (v > 10) new_aux = 2;
2790 /* Graze */
2791 else if (v > 0) new_aux = 1;
2792 /* None */
2793 else new_aux = 0;
2794
2795 /* Increase cut */
2796 if (new_aux > old_aux) {
2797 /* Describe the state */
2798 switch (new_aux) {
2799 /* Graze */
2800 case 1:
2801 msg_print(Ind, "You have been given a graze.");
2802 break;
2803
2804 /* Light cut */
2805 case 2:
2806 msg_print(Ind, "You have been given a light cut.");
2807 break;
2808
2809 /* Bad cut */
2810 case 3:
2811 msg_print(Ind, "You have been given a bad cut.");
2812 break;
2813
2814 /* Nasty cut */
2815 case 4:
2816 msg_print(Ind, "You have been given a nasty cut.");
2817 break;
2818
2819 /* Severe cut */
2820 case 5:
2821 msg_print(Ind, "You have been given a severe cut.");
2822 break;
2823
2824 /* Deep gash */
2825 case 6:
2826 msg_print(Ind, "You have been given a deep gash.");
2827 break;
2828
2829 /* Mortal wound */
2830 case 7:
2831 msg_print(Ind, "You have been given a mortal wound.");
2832 break;
2833 }
2834
2835 /* Notice */
2836 notice = TRUE;
2837 }
2838
2839 /* Decrease cut */
2840 else if (new_aux < old_aux) {
2841 /* Describe the state */
2842 switch (new_aux) {
2843 /* None */
2844 case 0:
2845 msg_print(Ind, "You are no longer bleeding.");
2846 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2847 p_ptr->cut_attacker = 0;
2848 break;
2849 }
2850
2851 /* Notice */
2852 notice = TRUE;
2853 }
2854
2855 /* Use the value */
2856 p_ptr->cut = v;
2857
2858 /* Remember who did it - mikaelh */
2859 p_ptr->cut_attacker = attacker;
2860
2861 /* No change */
2862 if (!notice) return (FALSE);
2863
2864 /* Disturb */
2865 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2866
2867 /* Recalculate boni */
2868 p_ptr->update |= (PU_BONUS);
2869
2870 /* Redraw the "cut" */
2871 p_ptr->redraw |= (PR_CUT);
2872
2873 /* Handle stuff */
2874 handle_stuff(Ind);
2875
2876 /* Result */
2877 return (TRUE);
2878 }
2879
set_mindboost(int Ind,int p,int v)2880 bool set_mindboost(int Ind, int p, int v) {
2881 player_type *p_ptr = Players[Ind];
2882 bool notice = FALSE;
2883
2884 /* Hack -- Force good values */
2885 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2886
2887
2888 /* Redraw the Blows/Round if any */
2889 if (v && p_ptr->mindboost_power != p) p_ptr->update |= PU_BONUS;
2890
2891 /* set boni/EA */
2892 p_ptr->mindboost_power = p;
2893
2894 /* Open */
2895 if (v) {
2896 if (!p_ptr->mindboost) {
2897 msg_print(Ind, "Your mind overflows!");
2898 notice = TRUE;
2899 }
2900 }
2901
2902 /* Shut */
2903 else {
2904 if (p_ptr->mindboost) {
2905 msg_print(Ind, "The mind returns to normal.");
2906 notice = TRUE;
2907 }
2908 }
2909
2910 /* Use the value */
2911 p_ptr->mindboost = v;
2912
2913 if (set_afraid(Ind, 0)) notice = TRUE;
2914
2915 /* Nothing to notice */
2916 if (!notice) return (FALSE);
2917
2918 /* Redraw the Blows/Round if any */
2919 p_ptr->update |= PU_BONUS;
2920
2921 /* Disturb */
2922 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2923
2924 /* Handle stuff */
2925 handle_stuff(Ind);
2926
2927 /* Result */
2928 return (TRUE);
2929 }
2930
set_kinetic_shield(int Ind,int v)2931 bool set_kinetic_shield(int Ind, int v) {
2932 player_type *p_ptr = Players[Ind];
2933 bool notice = FALSE;
2934
2935 /* Hack -- Force good values */
2936 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2937
2938 /* Open */
2939 if (v) {
2940 if (!p_ptr->kinetic_shield) {
2941 msg_print(Ind, "You create a kinetic barrier.");
2942 notice = TRUE;
2943 }
2944 }
2945
2946 /* Shut */
2947 else {
2948 if (p_ptr->kinetic_shield) {
2949 msg_print(Ind, "Your kinetic barrier destabilizes.");
2950 notice = TRUE;
2951 }
2952 }
2953
2954 /* Use the value */
2955 p_ptr->kinetic_shield = v;
2956
2957 /* Nothing to notice */
2958 if (!notice) return (FALSE);
2959
2960 /* Disturb */
2961 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
2962
2963 /* Handle stuff */
2964 handle_stuff(Ind);
2965
2966 /* Result */
2967 return (TRUE);
2968 }
2969
2970 #ifdef ENABLE_MAIA
2971 /* timed hp bonus for RACE_MAIA.
2972 *fastest* path (SKILL_ASTRAL = lvl+2):
2973 +1 at lvl 39
2974 +2 at lvl 54
2975 +3 at lvl 60
2976 */
do_divine_hp(int Ind,int v,int p)2977 bool do_divine_hp(int Ind, int v, int p) {
2978 player_type *p_ptr = Players[Ind];
2979 bool notice = (FALSE);
2980
2981 /* Hack -- Force good values */
2982 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
2983
2984 /* Open */
2985 if (v) {
2986 if (!p_ptr->divine_hp) {
2987 msg_format_near(Ind, "%s prepares for aggression!", p_ptr->name);
2988 msg_print(Ind, "You feel courageous.");
2989 p_ptr->divine_hp_mod = p;
2990
2991 notice = (TRUE);
2992 }
2993 }
2994
2995 /* Shut */
2996 else { //v = 0;
2997 if (p_ptr->divine_hp) {
2998 p_ptr->divine_hp_mod = 0;
2999 msg_format_near(Ind, "%s returns to %s normal self.", p_ptr->name, (p_ptr->male? "his" : "her"));
3000 msg_print(Ind, "You no longer feel courageous.");
3001 notice = (TRUE);
3002 }
3003 }
3004
3005 p_ptr->divine_hp = v;
3006
3007 /* Nothing to notice */
3008 if (!notice) return (FALSE);
3009
3010 /* Disturb */
3011 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3012
3013 /* Recalculate boni */
3014 p_ptr->update |= (PU_BONUS|PU_HP);
3015 /* Handle stuff */
3016 handle_stuff(Ind);
3017
3018 /* Result */
3019 return (TRUE);
3020 }
3021
3022 /*
3023 timed crit bonus for RACE_MAIA.
3024 *fastest* path (SKILL_ASTRAL = lvl+2):
3025 +2 at lvl 44, +2 per 5 levels thereafter
3026 */
do_divine_crit(int Ind,int v,int p)3027 bool do_divine_crit(int Ind, int v, int p) {
3028 player_type *p_ptr = Players[Ind];
3029 bool notice = (FALSE);
3030
3031 /* Hack -- Force good values */
3032 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3033
3034 /* Open */
3035 if (v) {
3036 if (!p_ptr->divine_crit) {
3037 msg_format_near(Ind, "%s seems focussed.", p_ptr->name);
3038 msg_print(Ind, "You focus your intentions.");
3039 p_ptr->divine_crit_mod = p;
3040
3041 notice = (TRUE);
3042 }
3043 }
3044
3045 /* Shut */
3046 else { //v = 0;
3047 if (p_ptr->divine_crit) {
3048 p_ptr->divine_crit_mod = 0;
3049 msg_format_near(Ind, "%s seems less focussed", p_ptr->name);
3050 msg_print(Ind, "Your focus dissipates.");
3051 notice = (TRUE);
3052 }
3053 }
3054
3055 p_ptr->divine_crit = v;
3056
3057 /* Nothing to notice */
3058 if (!notice) return (FALSE);
3059
3060 /* Disturb */
3061 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3062
3063 /* Recalculate boni */
3064 p_ptr->update |= (PU_BONUS);
3065 /* Handle stuff */
3066 handle_stuff(Ind);
3067
3068 /* Result */
3069 return (TRUE);
3070 }
3071
3072 /*
3073 timed time and mana res bonus for RACE_MAIA.
3074 */
do_divine_xtra_res_time(int Ind,int v)3075 bool do_divine_xtra_res_time(int Ind, int v) {
3076 player_type *p_ptr = Players[Ind];
3077 bool notice = (FALSE);
3078
3079 /* Hack -- Force good values */
3080 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3081
3082 /* Open */
3083 if (v) {
3084 if (!p_ptr->divine_xtra_res_time) {
3085 msg_print(Ind, "You feel resistant to \377Btime\377w.");
3086 notice = (TRUE);
3087 }
3088 }
3089
3090 /* Shut */
3091 else { //v = 0;
3092 if (p_ptr->divine_xtra_res_time) {
3093 msg_print(Ind, "You feel less resistant to \377Btime\377w.");
3094 notice = (TRUE);
3095 }
3096 }
3097
3098 p_ptr->divine_xtra_res_time = v;
3099
3100 /* Nothing to notice */
3101 if (!notice) return (FALSE);
3102
3103 /* Disturb */
3104 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3105
3106 /* Recalculate boni */
3107 p_ptr->update |= (PU_BONUS);
3108
3109 /* Handle stuff */
3110 handle_stuff(Ind);
3111
3112 /* Result */
3113 return (TRUE);
3114 }
3115 #endif
3116
3117 /*
3118 * Set "p_ptr->tim_deflect", notice observable changes
3119 */
set_tim_deflect(int Ind,int v)3120 bool set_tim_deflect(int Ind, int v) {
3121 player_type *p_ptr = Players[Ind];
3122 bool notice = FALSE;
3123
3124 /* Hack -- Force good values */
3125 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3126
3127 /* Open */
3128 if (v) {
3129 if (!p_ptr->tim_deflect) {
3130 msg_print(Ind, "A deflective shield forms around your body!");
3131 notice = TRUE;
3132 }
3133 }
3134
3135 /* Shut */
3136 else {
3137 if (p_ptr->tim_deflect) {
3138 msg_print(Ind, "Your deflective shield crumbles away.");
3139 notice = TRUE;
3140 }
3141 }
3142
3143
3144 /* Use the value */
3145 p_ptr->tim_deflect = v;
3146
3147 /* Nothing to notice */
3148 if (!notice) return (FALSE);
3149
3150 /* Disturb */
3151 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3152
3153 /* Recalculate boni */
3154 p_ptr->update |= (PU_BONUS);
3155
3156 /* Handle stuff */
3157 handle_stuff(Ind);
3158
3159 /* Result */
3160 return (TRUE);
3161 }
3162
3163 /*
3164 * Set "p_ptr->sh_fire/cold/elec", notice observable changes
3165 */
set_sh_fire_tim(int Ind,int v)3166 bool set_sh_fire_tim(int Ind, int v) {
3167 player_type *p_ptr = Players[Ind];
3168 bool notice = FALSE;
3169
3170 /* Hack -- Force good values */
3171 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3172
3173 /* Open */
3174 if (v) {
3175 if (!p_ptr->sh_fire_tim) {
3176 if (!p_ptr->sh_fire_fix) {
3177 msg_print(Ind, "You are enveloped by scorching flames!");
3178 notice = TRUE;
3179 } else msg_print(Ind, "The scorching flames surrounding you are blazing high!");
3180 }
3181 }
3182 /* Shut */
3183 else {
3184 if (p_ptr->sh_fire_tim && !p_ptr->sh_fire_fix) {
3185 msg_print(Ind, "The scorching flames surrounding you cease.");
3186 notice = TRUE;
3187 }
3188 }
3189
3190 /* Use the value */
3191 p_ptr->sh_fire_tim = v;
3192 /* Nothing to notice */
3193 if (!notice) return (FALSE);
3194 /* Disturb */
3195 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3196 /* Recalculate boni */
3197 p_ptr->update |= (PU_BONUS);
3198 /* Handle stuff */
3199 handle_stuff(Ind);
3200 /* Result */
3201 return (TRUE);
3202 }
set_sh_cold_tim(int Ind,int v)3203 bool set_sh_cold_tim(int Ind, int v) {
3204 player_type *p_ptr = Players[Ind];
3205 bool notice = FALSE;
3206
3207 /* Hack -- Force good values */
3208 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3209
3210 /* Open */
3211 if (v) {
3212 if (!p_ptr->sh_cold_tim) {
3213 if (!p_ptr->sh_cold_fix) {
3214 msg_print(Ind, "You are enveloped by freezing cold!");
3215 notice = TRUE;
3216 } else msg_print(Ind, "The frost around you blows colder even!");
3217 }
3218 }
3219 /* Shut */
3220 else {
3221 if (p_ptr->sh_cold_tim && !p_ptr->sh_cold_fix) {
3222 msg_print(Ind, "The scorching flames surrounding you cease.");
3223 notice = TRUE;
3224 }
3225 }
3226
3227 /* Use the value */
3228 p_ptr->sh_cold_tim = v;
3229 /* Nothing to notice */
3230 if (!notice) return (FALSE);
3231 /* Disturb */
3232 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3233 /* Recalculate boni */
3234 p_ptr->update |= (PU_BONUS);
3235 /* Handle stuff */
3236 handle_stuff(Ind);
3237 /* Result */
3238 return (TRUE);
3239 }
set_sh_elec_tim(int Ind,int v)3240 bool set_sh_elec_tim(int Ind, int v) {
3241 player_type *p_ptr = Players[Ind];
3242 bool notice = FALSE;
3243
3244 /* Hack -- Force good values */
3245 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
3246
3247 /* Open */
3248 if (v) {
3249 if (!p_ptr->sh_elec_tim) {
3250 if (!p_ptr->sh_elec_fix) {
3251 msg_print(Ind, "You are enveloped by sparkling static!");
3252 notice = TRUE;
3253 } else msg_print(Ind, "Static around you surges brightly!");
3254 }
3255 }
3256 /* Shut */
3257 else {
3258 if (p_ptr->sh_elec_tim && !p_ptr->sh_elec_fix) {
3259 msg_print(Ind, "The static sparkling around you ceases.");
3260 notice = TRUE;
3261 }
3262 }
3263
3264 /* Use the value */
3265 p_ptr->sh_elec_tim = v;
3266 /* Nothing to notice */
3267 if (!notice) return (FALSE);
3268 /* Disturb */
3269 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3270 /* Recalculate boni */
3271 p_ptr->update |= (PU_BONUS);
3272 /* Handle stuff */
3273 handle_stuff(Ind);
3274 /* Result */
3275 return (TRUE);
3276 }
3277
3278
3279
3280 /*
3281 * Set "p_ptr->food", notice observable changes
3282 *
3283 * The "p_ptr->food" variable can get as large as 20000, allowing the
3284 * addition of the most "filling" item, Elvish Waybread, which adds
3285 * 7500 food units, without overflowing the 32767 maximum limit.
3286 *
3287 * Perhaps we should disturb the player with various messages,
3288 * especially messages about hunger status changes. XXX XXX XXX
3289 *
3290 * Digestion of food is handled in "dungeon.c", in which, normally,
3291 * the player digests about 20 food units per 100 game turns, more
3292 * when "fast", more when "regenerating", less with "slow digestion",
3293 * but when the player is "gorged", he digests 100 food units per 10
3294 * game turns, or a full 1000 food units per 100 game turns.
3295 *
3296 * Note that the player's speed is reduced by 10 units while gorged,
3297 * so if the player eats a single food ration (5000 food units) when
3298 * full (15000 food units), he will be gorged for (5000/100)*10 = 500
3299 * game turns, or 500/(100/5) = 25 player turns (if nothing else is
3300 * affecting the player speed).
3301 */
set_food(int Ind,int v)3302 bool set_food(int Ind, int v) {
3303 player_type *p_ptr = Players[Ind];
3304 int old_aux, new_aux;
3305 bool notice = FALSE;
3306
3307 /* True Ghosts don't starve */
3308 if ((p_ptr->ghost) || (get_skill(p_ptr, SKILL_HSUPPORT) >= 40) ||
3309 (p_ptr->prace == RACE_MAIA && p_ptr->ptrait))
3310 {
3311 p_ptr->food = PY_FOOD_FULL - 1;
3312 return (FALSE);
3313 }
3314
3315 /* Warrior does not need food badly */
3316 #ifdef ARCADE_SERVER
3317 p_ptr->food = PY_FOOD_FULL - 1;
3318 return (FALSE);
3319 #endif
3320 /* Hack -- Force good values */
3321 v = (v > 20000) ? 20000 : (v < 0) ? 0 : v;
3322
3323 /* Ents will never get gorged, but can still go hungry/thirsty */
3324 if (p_ptr->prace == RACE_ENT && v >= PY_FOOD_MAX ) {
3325 v = PY_FOOD_MAX - 1;
3326 }
3327
3328 /* Fainting / Starving */
3329 if (p_ptr->food < PY_FOOD_FAINT) old_aux = 0;
3330 /* Weak */
3331 else if (p_ptr->food < PY_FOOD_WEAK) old_aux = 1;
3332 /* Hungry */
3333 else if (p_ptr->food < PY_FOOD_ALERT) old_aux = 2;
3334 /* Normal */
3335 else if (p_ptr->food < PY_FOOD_FULL) old_aux = 3;
3336 /* Full */
3337 else if (p_ptr->food < PY_FOOD_MAX) old_aux = 4;
3338 /* Gorged */
3339 else old_aux = 5;
3340
3341 /* Fainting / Starving */
3342 if (v < PY_FOOD_FAINT) new_aux = 0;
3343 /* Weak */
3344 else if (v < PY_FOOD_WEAK) new_aux = 1;
3345 /* Hungry */
3346 else if (v < PY_FOOD_ALERT) new_aux = 2;
3347 /* Normal */
3348 else if (v < PY_FOOD_FULL) new_aux = 3;
3349 /* Full */
3350 else if (v < PY_FOOD_MAX) new_aux = 4;
3351 /* Gorged */
3352 else new_aux = 5;
3353
3354 /* Food increase */
3355 if (new_aux > old_aux) {
3356 /* Describe the state */
3357 switch (new_aux) {
3358 /* Weak */
3359 case 1:
3360 msg_print(Ind, "You are still weak.");
3361 break;
3362
3363 /* Hungry */
3364 case 2:
3365 msg_print(Ind, "You are still hungry.");
3366 break;
3367
3368 /* Normal */
3369 case 3:
3370 msg_print(Ind, "You are no longer hungry.");
3371 break;
3372
3373 /* Full */
3374 case 4:
3375 msg_print(Ind, "You are full!");
3376 break;
3377
3378 /* Bloated */
3379 case 5:
3380 msg_print(Ind, "You have gorged yourself!");
3381 break;
3382 }
3383
3384 /* Change */
3385 notice = TRUE;
3386 }
3387
3388 /* Food decrease */
3389 else if (new_aux < old_aux) {
3390 /* Describe the state */
3391 switch (new_aux) {
3392 /* Fainting / Starving */
3393 case 0:
3394 msg_print(Ind, "\377RYou are getting faint from hunger!");
3395 break;
3396
3397 /* Weak */
3398 case 1:
3399 msg_print(Ind, "You are getting weak from hunger!");
3400 if (p_ptr->warning_hungry != 2) {
3401 p_ptr->warning_hungry = 2;
3402 if (p_ptr->prace == RACE_VAMPIRE) {
3403 msg_print(Ind, "\374\377RWARNING: You are 'weak' from hunger. Drink some blood by killing monsters");
3404 msg_print(Ind, "\374\377R monsters in melee (close combat). Town monsters will work too.");
3405 } else if (p_ptr->prace == RACE_ENT) {
3406 msg_print(Ind, "\374\377RWARNING: You are 'weak' from hunger. Find something to drink or rest");
3407 msg_print(Ind, "\374\377R (\377oSHIFT+r\377R) on earth/dirt/grass/water floor tiles for a while.");
3408 } else {
3409 msg_print(Ind, "\374\377RWARNING: You are 'weak' from hunger. Press \377oSHIFT+e\377R to eat something");
3410 msg_print(Ind, "\374\377R or read a 'scroll of satisfy hunger' if you have one.");
3411 }
3412 s_printf("warning_hungry(weak): %s\n", p_ptr->name);
3413 }
3414 break;
3415
3416 /* Hungry */
3417 case 2:
3418 msg_print(Ind, "You are getting hungry.");
3419 if (p_ptr->warning_hungry == 0) {
3420 p_ptr->warning_hungry = 1;
3421 if (p_ptr->prace == RACE_VAMPIRE) {
3422 msg_print(Ind, "\374\377oWARNING: Your character is 'hungry'. Drink some blood by killing some");
3423 msg_print(Ind, "\374\377o monsters in melee (close combat). Town monsters will work too.");
3424 } else if (p_ptr->prace == RACE_ENT) {
3425 msg_print(Ind, "\374\377oWARNING: Your character is 'hungry'. Find something to drink or rest ");
3426 msg_print(Ind, "\374\377o (\377RSHIFT+r\377o) on earth/dirt/grass/water floor tiles for a while.");
3427 } else {
3428 msg_print(Ind, "\374\377oWARNING: Your character is 'hungry'. Press \377RSHIFT+e\377o to eat something");
3429 msg_print(Ind, "\374\377o or read a 'scroll of satisfy hunger' if you have one.");
3430 }
3431 s_printf("warning_hungry(hungry): %s\n", p_ptr->name);
3432 }
3433 break;
3434
3435 /* Normal */
3436 case 3:
3437 msg_print(Ind, "You are no longer full.");
3438 break;
3439
3440 /* Full */
3441 case 4:
3442 msg_print(Ind, "You are no longer gorged.");
3443 break;
3444 }
3445
3446 /* Change */
3447 notice = TRUE;
3448 }
3449
3450 /* Use the value */
3451 p_ptr->food = v;
3452
3453 /* Nothing to notice */
3454 if (!notice) return (FALSE);
3455
3456 /* Disturb */
3457 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3458
3459 /* Recalculate boni */
3460 p_ptr->update |= (PU_BONUS);
3461
3462 /* Redraw hunger */
3463 p_ptr->redraw |= (PR_HUNGER);
3464
3465 /* Handle stuff */
3466 handle_stuff(Ind);
3467
3468 /* Result */
3469 return (TRUE);
3470 }
3471
3472
3473 /*
3474 * Set "p_ptr->bless_temp_luck" - note: currently bless_temp_... aren't saved/loaded! (ie expire on logout)
3475 */
bless_temp_luck(int Ind,int pow,int dur)3476 bool bless_temp_luck(int Ind, int pow, int dur) {
3477 player_type *p_ptr = Players[Ind];
3478 bool notice = FALSE;
3479
3480 if (!p_ptr->bless_temp_luck) {
3481 msg_print(Ind, "You feel luck is on your side.");
3482 notice = TRUE;
3483 }
3484 if (!dur) {
3485 msg_print(Ind, "Your lucky streak fades.");
3486 notice = TRUE;
3487 }
3488
3489 /* Use the value */
3490 p_ptr->bless_temp_luck = dur;
3491 p_ptr->bless_temp_luck_power = pow;
3492
3493 /* Nothing to notice */
3494 if (!notice) return (FALSE);
3495
3496 /* Disturb */
3497 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
3498
3499 /* Recalculate boni */
3500 p_ptr->update |= (PU_BONUS);
3501
3502 /* Handle stuff */
3503 handle_stuff(Ind);
3504
3505 /* Result */
3506 return (TRUE);
3507 }
3508
3509 #ifdef ENABLE_MAIA
3510 /* helper function to modify Maia skills when they get a trait - C. Blue
3511 NOTE: IF THIS IS CALLED TOO MANY TIMES IN A ROW IT
3512 _MIGHT_ DISCONNET THE CLIENT WITH A 'write error'. */
do_Maia_skill(int Ind,int s,int m)3513 static void do_Maia_skill(int Ind, int s, int m) {
3514 /* Save old skill value */
3515 s32b val = Players[Ind]->s_info[s].value, tmp_val = Players[Ind]->s_info[s].mod;
3516
3517 /* Release invested points */
3518 respec_skill(Ind, s, FALSE, FALSE);
3519
3520 /* Modify skill, avoiding overflow (mod is u16b) */
3521 tmp_val = (tmp_val * m) / 10;
3522 /* Cap to 2.0 */
3523 if (tmp_val > 2000) tmp_val = 2000;
3524 Players[Ind]->s_info[s].mod = tmp_val;
3525
3526 /* Reinvest some of the points until old skill value is reached again */
3527 tmp_val = -1;
3528 #if 0
3529 while (((Players[Ind]->s_info[s].value / 1000 < val / 1000 && /* smooth: avoid "overskilling" */
3530 (Players[Ind]->s_info[s].value + Players[Ind]->s_info[s].mod) / 1000 <= val / 1000) ||
3531 Players[Ind]->s_info[s].value + Players[Ind]->s_info[s].mod <= val) /* no "underskilling" */
3532 #else
3533 while (Players[Ind]->s_info[s].value + Players[Ind]->s_info[s].mod <= val /* no "overskilling" */
3534 #endif
3535 /* avoid game maximum overflow - paranoia: */
3536 && Players[Ind]->s_info[s].value < 50000
3537 /* avoid cap overflow - extreme cases only (maxed auras): */
3538 && Players[Ind]->s_info[s].value / 1000 < Players[Ind]->max_plv + 2
3539 /* avoid getting stuck - paranoia (could waste 1 point actually if it really happened): */
3540 && Players[Ind]->s_info[s].value != tmp_val) {
3541 /* make sure we don't loop forever in case we can't go higher */
3542 tmp_val = Players[Ind]->s_info[s].value;
3543 /* invest a point */
3544 increase_skill(Ind, s, TRUE);
3545 }
3546
3547 /* Update it after the re-increasing has been finished */
3548 Send_skill_info(Ind, s, FALSE);
3549 }
3550 /* Change Maia skill chart after initiation */
shape_Maia_skills(int Ind)3551 void shape_Maia_skills(int Ind) {
3552 player_type *p_ptr = Players[Ind];
3553
3554 switch (p_ptr->ptrait) {
3555 case TRAIT_CORRUPTED:
3556 /* Doh! */
3557 p_ptr->s_info[SKILL_HOFFENSE].mod = 0;
3558 p_ptr->s_info[SKILL_HCURING].mod = 0;
3559 p_ptr->s_info[SKILL_HDEFENSE].mod = 0;
3560 p_ptr->s_info[SKILL_HSUPPORT].mod = 0;
3561
3562 /* Yay */
3563 do_Maia_skill(Ind, SKILL_AXE, 13);
3564 do_Maia_skill(Ind, SKILL_MARTIAL_ARTS, 13);
3565 do_Maia_skill(Ind, SKILL_FIRE, 17);
3566 do_Maia_skill(Ind, SKILL_AIR, 17);
3567 do_Maia_skill(Ind, SKILL_CONVEYANCE, 17);
3568 do_Maia_skill(Ind, SKILL_UDUN, 20);
3569 do_Maia_skill(Ind, SKILL_TRAUMATURGY, 30);
3570 do_Maia_skill(Ind, SKILL_NECROMANCY, 30);
3571 do_Maia_skill(Ind, SKILL_AURA_FEAR, 30);
3572 do_Maia_skill(Ind, SKILL_AURA_SHIVER, 30);
3573 do_Maia_skill(Ind, SKILL_AURA_DEATH, 30);
3574 do_Maia_skill(Ind, SKILL_R_DARK, 17);
3575 do_Maia_skill(Ind, SKILL_R_NETH, 17);
3576 break;
3577
3578 case TRAIT_ENLIGHTENED:
3579 /* Doh! */
3580 p_ptr->s_info[SKILL_TRAUMATURGY].mod = 0;
3581 p_ptr->s_info[SKILL_NECROMANCY].mod = 0;
3582 p_ptr->s_info[SKILL_AURA_DEATH].mod = 0;
3583
3584 /* Yay */
3585 do_Maia_skill(Ind, SKILL_AURA_FEAR, 30);
3586 do_Maia_skill(Ind, SKILL_AURA_SHIVER, 30);
3587 do_Maia_skill(Ind, SKILL_HOFFENSE, 21);
3588 do_Maia_skill(Ind, SKILL_HCURING, 21);
3589 do_Maia_skill(Ind, SKILL_HDEFENSE, 21);
3590 do_Maia_skill(Ind, SKILL_HSUPPORT, 21);
3591 do_Maia_skill(Ind, SKILL_DIVINATION, 17);
3592 do_Maia_skill(Ind, SKILL_SWORD, 13);
3593 do_Maia_skill(Ind, SKILL_BLUNT, 13);
3594 do_Maia_skill(Ind, SKILL_POLEARM, 13);
3595 do_Maia_skill(Ind, SKILL_R_LITE, 17);
3596 do_Maia_skill(Ind, SKILL_R_MANA, 17);
3597 break;
3598 default: ;
3599 }
3600 }
3601 #else /* shared player.pkg file */
shape_Maia_skills(int Ind)3602 void shape_Maia_skills(int Ind) { }
3603 #endif
3604
3605 /*
3606 * Try to raise stats, esp. if low. - Jir -
3607 */
check_training(int Ind)3608 static void check_training(int Ind) {
3609 player_type *p_ptr = Players[Ind];
3610 int train = get_skill_scale(p_ptr, SKILL_TRAINING, 50);
3611 int i, chance, value, value2;
3612
3613 if (train < 1) return;
3614
3615 for (i = 0; i < 6; i++) {
3616 value = p_ptr->stat_cur[i];
3617 value2 = p_ptr->stat_ind[i];
3618 chance = train;
3619
3620 value += (p_ptr->rp_ptr->r_adj[i]);
3621 value += (p_ptr->cp_ptr->c_adj[i]);
3622
3623 if (value > 12) chance /= 2;
3624 if (value > 17) chance /= 4;
3625
3626 /* Hack -- High stats, low chance */
3627 if (magik(adj_str_hold[value2]) || !magik(chance)) continue;
3628
3629 /* Hack -- if restored, not increase */
3630 if (!res_stat(Ind, i)) do_inc_stat(Ind, i);
3631 }
3632
3633 /* Also, it can give an extra skill point */
3634 if (magik(train)) p_ptr->skill_points++;
3635 }
3636
3637 /*
3638 * Advance experience levels and print experience
3639 */
check_experience(int Ind)3640 void check_experience(int Ind) {
3641 player_type *p_ptr = Players[Ind];
3642 char str[160];
3643
3644 bool newlv = FALSE, reglv = FALSE;
3645 int old_lev, i;
3646 //long int i;
3647 #ifdef LEVEL_GAINING_LIMIT
3648 int limit;
3649 #endif // LEVEL_GAINING_LIMIT
3650
3651
3652 /* paranoia -- fix the max level first */
3653 if (p_ptr->lev > p_ptr->max_plv)
3654 p_ptr->max_plv = p_ptr->lev;
3655
3656 /* Note current level */
3657 old_lev = p_ptr->lev;
3658
3659 /* Hack -- lower limit */
3660 if (p_ptr->exp < 0) p_ptr->exp = 0;
3661
3662 /* Hack -- lower limit */
3663 if (p_ptr->max_exp < 0) p_ptr->max_exp = 0;
3664
3665 #ifdef LEVEL_GAINING_LIMIT
3666 /* upper limit */
3667 #ifndef ALT_EXPRATIO
3668 limit = (s64b)((s64b)player_exp[p_ptr->max_plv] *
3669 (s64b)p_ptr->expfact / 100L) - 1;
3670 #else
3671 limit = (s64b)(player_exp[p_ptr->max_plv] - 1);
3672 #endif
3673 /* Hack -- upper limit */
3674 if (p_ptr->exp > limit) p_ptr->exp = limit;
3675 #endif // LEVEL_GAINING_LIMIT
3676
3677 /* Hack -- upper limit */
3678 if (p_ptr->exp > PY_MAX_EXP) p_ptr->exp = PY_MAX_EXP;
3679
3680 /* Hack -- upper limit */
3681 if (p_ptr->max_exp > PY_MAX_EXP) p_ptr->max_exp = PY_MAX_EXP;
3682
3683
3684 /* Hack -- maintain "max" experience */
3685 if (p_ptr->exp > p_ptr->max_exp) p_ptr->max_exp = p_ptr->exp;
3686
3687 /* Redraw experience */
3688 p_ptr->redraw |= (PR_EXP);
3689
3690
3691 /* Lose levels while possible */
3692 #ifndef ALT_EXPRATIO
3693 while ((p_ptr->lev > 1) &&
3694 (p_ptr->exp < ((s64b)((s64b)player_exp[p_ptr->lev-2] * (s64b)p_ptr->expfact / 100L))))
3695 #else
3696 while ((p_ptr->lev > 1) &&
3697 (p_ptr->exp < (s64b)player_exp[p_ptr->lev-2]))
3698 #endif
3699 {
3700 /* Lose a level */
3701 p_ptr->lev--;
3702
3703 clockin(Ind, 1); /* Set player level */
3704
3705 }
3706
3707
3708 /* Remember maximum level (the one displayed if life levels were restored right now) */
3709 #ifndef ALT_EXPRATIO
3710 while ((p_ptr->max_lev > 1) &&
3711 (p_ptr->max_exp < ((s64b)((s64b)player_exp[p_ptr->max_lev-2] * (s64b)p_ptr->expfact / 100L))))
3712 #else
3713 while ((p_ptr->max_lev > 1) &&
3714 (p_ptr->max_exp < (s64b)player_exp[p_ptr->max_lev-2]))
3715 #endif
3716 {
3717 /* Lose a level */
3718 p_ptr->max_lev--;
3719 }
3720
3721
3722 /* Gain levels while possible */
3723 #ifndef ALT_EXPRATIO
3724 while ((p_ptr->lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3725 (p_ptr->exp >= ((s64b)(((s64b)player_exp[p_ptr->lev-1] * (s64b)p_ptr->expfact) / 100L))))
3726 #else
3727 while ((p_ptr->lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3728 (p_ptr->exp >= (s64b)player_exp[p_ptr->lev-1]))
3729 #endif
3730 {
3731 if (p_ptr->inval && p_ptr->lev >= 25) {
3732 msg_print(Ind, "\377rYou cannot gain level further, wait for an admin to validate your account.");
3733 break;
3734 // return;
3735 }
3736
3737 process_hooks(HOOK_PLAYER_LEVEL, "d", Ind);
3738
3739 /* Gain a level */
3740 p_ptr->lev++;
3741
3742 clockin(Ind, 1); /* Set player level */
3743
3744 /* Save the highest level */
3745 if (p_ptr->lev > p_ptr->max_plv) {
3746 p_ptr->max_plv = p_ptr->lev;
3747
3748 /* gain skill points */
3749 #ifdef KINGCAP_EXP
3750 /* min cap level is 50. check how far this
3751 character can come with the actual exp cap of
3752 21240000 (TL Ranger level 50) and adjust skill
3753 distribution so that characters gain 250..300
3754 skill points in total (TLRanger..YeekWarrior)*/
3755 for (i = 50; i < 69; i++) {
3756 if ((((s64b)player_exp[i-1] * (s64b)p_ptr->expfact) / 100L) > 21240000) break;
3757 }
3758 i--;/* i now contains the maximum reachable level for
3759 this character, due to exp cap 21240000 */
3760 /* now calculate his skills/level ratio.
3761 It's (250+2.63*extraLevel) / personalCapLevel */
3762 i = i - 50;/* i now contains the extraLevel above 50 */
3763 i = ((250000 + (2630 * i)) / (50 + i));
3764 if (i != ((i / 1000) * 1000)) i += 10;/* +1 against rounding probs */
3765 i /= 10; /* i is now 500..4xx, containing the skills/levelup * 100 */
3766 /* Give player all of his skill points except the last one: */
3767 p_ptr->skill_points += SKILL_NB_BASE - 1;
3768 /* Eventually give him the last one, depending on his skills/levelup ratio: */
3769 if (rand_int(100) < (i - ((SKILL_NB_BASE - 1) * 100))) p_ptr->skill_points++;
3770 #endif
3771 #ifndef KINGCAP_EXP
3772 p_ptr->skill_points += SKILL_NB_BASE;
3773 if (WEAK_SKILLBONUS) {
3774 /* calculate total bonus skill points for this
3775 player at level 50, save it in xsp: */
3776 long xsp_mul = WEAK_SKILLBONUS * 1000000 / ((573000 / (100 + 35)) - 1000);
3777 long xsp = ((573000 / (100 + p_ptr->expfact)) - 1) * xsp_mul;
3778 xsp /= 1000000;
3779 /* depending on his should-have-bonus give him an extra point randomly */
3780 if (rand_int(100) < (xsp * 100 / 50)) p_ptr->skill_points++;
3781 }
3782 #endif
3783 if (is_older_than(&p_ptr->version, 4, 4, 8, 5, 0, 0)) p_ptr->redraw |= PR_STUDY;
3784 p_ptr->update |= PU_SKILL_MOD;
3785
3786 newlv = TRUE;
3787
3788 /* give some stats, using Training skill */
3789 check_training(Ind);
3790 } else {
3791 /* Player just regained a level he lost previously */
3792 reglv = TRUE;
3793 }
3794
3795 #ifdef USE_SOUND_2010
3796 /* see further below! */
3797 #else
3798 sound(Ind, SOUND_LEVEL);
3799 #endif
3800 }
3801 /* log regaining of levels */
3802 if (reglv) s_printf("%s has regained level %d.\n", p_ptr->name, p_ptr->lev);
3803
3804
3805 /* Remember maximum level (the one displayed if life levels were restored right now) */
3806 #ifndef ALT_EXPRATIO
3807 while ((p_ptr->max_lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3808 (p_ptr->max_exp >= ((s64b)(((s64b)player_exp[p_ptr->max_lev-1] * (s64b)p_ptr->expfact) / 100L))))
3809 #else
3810 while ((p_ptr->max_lev < (is_admin(p_ptr) ? PY_MAX_LEVEL : PY_MAX_PLAYER_LEVEL)) &&
3811 (p_ptr->max_exp >= (s64b)player_exp[p_ptr->max_lev-1]))
3812 #endif
3813 {
3814 /* Gain a level */
3815 p_ptr->max_lev++;
3816 }
3817
3818 /* Try to own items we previously couldn't own */
3819 if (old_lev < p_ptr->lev) {
3820 object_type *o_ptr;
3821
3822 for (i = 0; i < INVEN_PACK; i++) {
3823 o_ptr = &p_ptr->inventory[i];
3824 if (!o_ptr->k_idx) continue;
3825 if (o_ptr->owner == p_ptr->id) continue;
3826 can_use(Ind, o_ptr);
3827 }
3828 }
3829
3830 /* Redraw level-depending stuff.. */
3831 if (old_lev != p_ptr->lev) {
3832 /* Update some stuff */
3833 p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SANITY);
3834
3835 /* Redraw some stuff */
3836 p_ptr->redraw |= (PR_LEV | PR_TITLE | PR_DEPTH | PR_STATE);
3837 /* PR_STATE is only needed if player can unlearn
3838 techniques by dropping in levels */
3839
3840 /* Window stuff */
3841 p_ptr->window |= (PW_PLAYER);
3842
3843 /* Window stuff - Items might be come (un)usable depending on level! */
3844 p_ptr->window |= (PW_INVEN | PW_EQUIP);
3845 }
3846
3847 if (!newlv) {
3848 /* Handle stuff */
3849 handle_stuff(Ind);
3850
3851 return;
3852 }
3853
3854
3855 /* Message */
3856 msg_format(Ind, "\374\377GWelcome to level %d. You have %d skill points.", p_ptr->lev, p_ptr->skill_points);
3857 if (!is_admin(p_ptr)) {
3858 if (p_ptr->lev == 99) l_printf("%s \\{U*** \\{g%s has attained level 99 \\{U***\n", showdate(), p_ptr->name);
3859 else if (p_ptr->lev >= 90) l_printf("%s \\{g%s has attained level %d\n", showdate(), p_ptr->name, p_ptr->lev);
3860 else if (old_lev < 80 && p_ptr->lev >= 80) l_printf("%s \\{g%s has attained level 80\n", showdate(), p_ptr->name);
3861 else if (old_lev < 70 && p_ptr->lev >= 70) l_printf("%s \\{g%s has attained level 70\n", showdate(), p_ptr->name);
3862 else if (old_lev < 60 && p_ptr->lev >= 60) l_printf("%s \\{g%s has attained level 60\n", showdate(), p_ptr->name);
3863 }
3864 #ifdef USE_SOUND_2010
3865 sound(Ind, "levelup", NULL, SFX_TYPE_MISC, FALSE);
3866 #endif
3867
3868 snprintf(str, 160, "\374\377G%s has attained level %d.", p_ptr->name, p_ptr->lev);
3869 s_printf("%s has attained level %d.\n", p_ptr->name, p_ptr->lev);
3870 clockin(Ind, 1); /* Set player level */
3871 #ifdef TOMENET_WORLDS
3872 if (cfg.worldd_lvlup) world_msg(str);
3873 #endif
3874 msg_broadcast(Ind, str);
3875
3876
3877 /* Disable certain warnings on reaching certain levels */
3878 disable_lowlevel_warnings(p_ptr);
3879
3880 /* Give helpful msg about how to distribute skill points at first level-up */
3881 if (p_ptr->newbie_hints && (old_lev == 1 || (p_ptr->skill_points == (p_ptr->max_plv - 1) * SKILL_NB_BASE))) {
3882 // && p_ptr->inval) /* (p_ptr->warning_skills) */
3883 msg_print(Ind, "\374\377GHINT: Press \377gSHIFT+g\377G to distribute your skill points!");
3884 }
3885
3886 if (p_ptr->warning_cloak == 2 && p_ptr->lev >= 15)
3887 msg_print(Ind, "\374\377GHINT: You can press \377gSHIFT+v\377G to cloak your appearance.");
3888
3889 /* Tell player to use numpad to move diagonally */
3890 if (old_lev < 2 && p_ptr->lev >= 2 && p_ptr->warning_numpadmove == 0) {
3891 msg_print(Ind, "\374\377yHINT: Use the number pad keys to move, that way you can move \377odiagonally\377y too!");
3892 msg_print(Ind, "\374\377y (Or try using the \377orogue-like\377y key set, press \377o= 1 y\377y to enable it.)");
3893 s_printf("warning_numpadmove: %s\n", p_ptr->name);
3894 p_ptr->warning_numpadmove = 1;
3895 }
3896
3897 /* Remind how to send chat messages */
3898 if (old_lev < 3 && p_ptr->lev >= 3 && p_ptr->warning_chat == 0) {
3899 p_ptr->warning_chat = 1;
3900 msg_print(Ind, "\374\377oHINT: You can press '\377R:\377o' key to chat with other players, eg greet them!");
3901 s_printf("warning_chat: %s\n", p_ptr->name);
3902 }
3903
3904 /* Give warning message to use word-of-recall, aimed at newbies */
3905 if (old_lev < 8 && p_ptr->lev >= 8 && p_ptr->warning_wor == 0) {
3906 /* scan inventory for any potions */
3907 bool found_items = FALSE;
3908 int i;
3909 for (i = 0; i < INVEN_PACK; i++) {
3910 if (!p_ptr->inventory[i].k_idx) continue;
3911 if (!object_known_p(Ind, &p_ptr->inventory[i])) continue;
3912 if (p_ptr->inventory[i].tval == TV_SCROLL &&
3913 p_ptr->inventory[i].sval == SV_SCROLL_WORD_OF_RECALL)
3914 found_items = TRUE;
3915 }
3916 if (!found_items) {
3917 msg_print(Ind, "\374\377yHINT: You can use scrolls of \377Rword-of-recall\377y to teleport out of a dungeon");
3918 msg_print(Ind, "\374\377y or back into it, making the tedious search for stairs obsolete!");
3919 s_printf("warning_wor: %s\n", p_ptr->name);
3920 }
3921 p_ptr->warning_wor = 1;
3922 }
3923
3924 /* Give warning message to get involved with macros, aimed at newbies */
3925 if (old_lev < 10 && p_ptr->lev >= 10 && !p_ptr->warning_macros) {
3926 /* scan inventory for any macroish inscriptions */
3927 bool found_macroishness = FALSE;
3928 int i;
3929 for (i = 0; i < INVEN_PACK; i++)
3930 if (p_ptr->inventory[i].k_idx &&
3931 p_ptr->inventory[i].note &&
3932 strstr(quark_str(p_ptr->inventory[i].note), "@"))
3933 found_macroishness = TRUE;
3934 /* give a warning if it seems as if this character doesn't use any macros ;) */
3935 if (!found_macroishness) {
3936 msg_print(Ind, "\374\377oHINT: Create '\377Rmacros\377o' aka hotkeys to ensure survival in critical situations!");
3937 msg_print(Ind, "\374\377o Press '\377R%\377o' and then '\377Rz\377o' to start the macro wizard.");
3938 s_printf("warning_macros: %s\n", p_ptr->name);
3939 }
3940 }
3941
3942 /* Give warning message to stock wound curing potions, aimed at newbies */
3943 if (old_lev < 12 && p_ptr->lev >= 12 && p_ptr->warning_potions == 0) {
3944 #if 1
3945 /* scan inventory for any potions */
3946 bool found_items = FALSE;
3947 int i;
3948 for (i = 0; i < INVEN_PACK; i++) {
3949 if (!p_ptr->inventory[i].k_idx) continue;
3950 if (!object_known_p(Ind, &p_ptr->inventory[i])) continue;
3951 if (p_ptr->inventory[i].tval == TV_POTION && (
3952 // p_ptr->inventory[i].sval == SV_POTION_CURE_LIGHT ||
3953 p_ptr->inventory[i].sval == SV_POTION_CURE_SERIOUS ||
3954 p_ptr->inventory[i].sval == SV_POTION_CURE_CRITICAL))
3955 found_items = TRUE;
3956 }
3957 if (!found_items)
3958 #endif
3959 {
3960 msg_print(Ind, "\374\377oHINT: Buy potions of cure wounds from the \377Rtemple\377o in Bree. They will");
3961 msg_print(Ind, "\374\377o restore your hit points, ensuring your survival in critical situations.");
3962 msg_print(Ind, "\374\377o Ideally, create a \377Rmacro\377o for using them by a single key press!");
3963 s_printf("warning_potions: %s\n", p_ptr->name);
3964 }
3965 p_ptr->warning_potions = 1;
3966 }
3967
3968 /* Give warning message to utilize techniques */
3969 if (old_lev < 15 && p_ptr->lev >= 15) {
3970 if (p_ptr->warning_technique_melee == 0 && p_ptr->warning_technique_ranged == 0) {
3971 msg_print(Ind, "\374\377yHINT: Press '\377om\377y' to access 'Fighting Techniques' and 'Shooting Techniques'!");
3972 msg_print(Ind, "\374\377y You can also create macros for these. See the TomeNET guide for details.");
3973 s_printf("warning_techniques: %s\n", p_ptr->name);
3974 } else if (p_ptr->warning_technique_melee == 0) {
3975 msg_print(Ind, "\374\377yHINT: Press '\377om\377y' to access 'Fighting Techniques'!");
3976 msg_print(Ind, "\374\377y You can also create macros for these. See the TomeNET guide for details.");
3977 s_printf("warning_technique_melee: %s\n", p_ptr->name);
3978 } else if (p_ptr->warning_technique_ranged == 0) {
3979 msg_print(Ind, "\374\377yHINT: Press '\377om\377y' to access 'Shooting Techniques'!");
3980 msg_print(Ind, "\374\377y You can also create macros for these. See the TomeNET guide for details.");
3981 s_printf("warning_technique_ranged: %s\n", p_ptr->name);
3982 }
3983 p_ptr->warning_technique_melee = p_ptr->warning_technique_ranged = 1;
3984 }
3985
3986 /* Give warning message to get phase/tele means, aimed at newbies */
3987 if (old_lev < 18 && p_ptr->lev >= 18 && p_ptr->warning_tele == 0) {
3988 #if 1
3989 /* scan inventory for any scrolls/staves */
3990 bool found_items = FALSE;
3991 int i;
3992 for (i = 0; i < INVEN_PACK; i++) {
3993 if (!p_ptr->inventory[i].k_idx) continue;
3994 if (!object_known_p(Ind, &p_ptr->inventory[i])) continue;
3995 if (p_ptr->inventory[i].tval == TV_SCROLL && (
3996 p_ptr->inventory[i].sval == SV_SCROLL_TELEPORT))
3997 found_items = TRUE;
3998 if (p_ptr->inventory[i].tval == TV_STAFF && (
3999 p_ptr->inventory[i].sval == SV_STAFF_TELEPORTATION))
4000 found_items = TRUE;
4001 }
4002 if (!found_items)
4003 #endif
4004 {
4005 msg_print(Ind, "\374\377oHINT: Buy scrolls of teleportation from the \377RBlack Market\377o or a staff");
4006 msg_print(Ind, "\374\377o of teleportation from the \377RMagic Shop\377o to get out of trouble!");
4007 msg_print(Ind, "\374\377o Ideally, create a \377Rmacro\377o for using them by a single key press.");
4008 s_printf("warning_tele: %s\n", p_ptr->name);
4009 }
4010 p_ptr->warning_tele = 1;
4011 }
4012
4013 /* Introduce newly learned abilities (that depend on char level) */
4014 /* those that depend on a race */
4015 switch (p_ptr->prace) {
4016 case RACE_DWARF:
4017 if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn to climb mountains easily!");
4018 break;
4019 case RACE_ENT:
4020 if (old_lev < 4 && p_ptr->lev >= 4) msg_print(Ind, "\374\377GYou learn to see the invisible!");
4021 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou learn to telepathically sense animals!");
4022 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou learn to telepathically sense orcs!");
4023 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to telepathically sense trolls!");
4024 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou learn to telepathically sense giants!");
4025 if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn to telepathically sense dragons!");
4026 if (old_lev < 40 && p_ptr->lev >= 40) msg_print(Ind, "\374\377GYou learn to telepathically sense demons!");
4027 if (old_lev < 50 && p_ptr->lev >= 50) msg_print(Ind, "\374\377GYou learn to telepathically sense evil!");
4028 break;
4029 case RACE_DRACONIAN:
4030 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou learn to telepathically sense dragons!");
4031 #ifndef ENABLE_DRACONIAN_TRAITS
4032 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou become more resistant to fire!");
4033 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou become more resistant to frost!");
4034 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou become more resistant to acid!");
4035 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou become more resistant to lightning!");
4036 #else
4037 if (old_lev < 8 && p_ptr->lev >= 8) msg_print(Ind, "\374\377GYou learn how to breathe an element!");
4038 switch (p_ptr->ptrait) {
4039 case TRAIT_BLUE: /* Draconic Blue */
4040 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYour attacks are branded by lightning!");
4041 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou are enveloped in lightning!");
4042 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear electricity!");
4043 break;
4044 case TRAIT_WHITE: /* Draconic White */
4045 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou are enveloped by freezing air!");
4046 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear frost!");
4047 break;
4048 case TRAIT_RED: /* Draconic Red */
4049 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear fire!");
4050 break;
4051 case TRAIT_BLACK: /* Draconic Black */
4052 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear acid!");
4053 break;
4054 case TRAIT_GREEN: /* Draconic Green */
4055 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou no longer fear poison!");
4056 break;
4057 case TRAIT_MULTI: /* Draconic Multi-hued */
4058 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to electricity!");
4059 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to frost!");
4060 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to fire!");
4061 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou develop intrinsic resistance to acid!");
4062 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou develop intrinsic resistance to poison!");
4063 break;
4064 case TRAIT_BRONZE: /* Draconic Bronze */
4065 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to confusion!");
4066 if (old_lev < 10 && p_ptr->lev >= 10) {
4067 msg_print(Ind, "\374\377GYou develop intrinsic resistance to electricity!");
4068 msg_print(Ind, "\374\377GYou develop intrinsic resistance to paralysis!");
4069 }
4070 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4071 break;
4072 case TRAIT_SILVER: /* Draconic Silver */
4073 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to frost!");
4074 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to acid!");
4075 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to poison!");
4076 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4077 break;
4078 case TRAIT_GOLD: /* Draconic Gold */
4079 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to fire!");
4080 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to acid!");
4081 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to sound!");
4082 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4083 break;
4084 case TRAIT_LAW: /* Draconic Law */
4085 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to shards!");
4086 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to paralysis!");
4087 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to sound!");
4088 break;
4089 case TRAIT_CHAOS: /* Draconic Chaos */
4090 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to confusion!");
4091 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou develop intrinsic resistance to chaos!");
4092 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou develop intrinsic resistance to disenchantment!");
4093 break;
4094 case TRAIT_BALANCE: /* Draconic Balance */
4095 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou develop intrinsic resistance to disenchantment!");
4096 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou develop intrinsic resistance to sound!");
4097 break;
4098 case TRAIT_POWER: /* Draconic Power */
4099 if (old_lev < 5 && p_ptr->lev >= 5) msg_print(Ind, "\374\377GYou develop intrinsic resistance to blindness!");
4100 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour scales have grown metallic enough to reflect attacks!");
4101 break;
4102 }
4103 #endif
4104 if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn how to levitate!");
4105 break;
4106 case RACE_DARK_ELF:
4107 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to see the invisible!");
4108 break;
4109 case RACE_VAMPIRE:
4110 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYour vision extends.");
4111 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYour vision extends.");
4112 if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYour vision extends.");
4113 if (old_lev < 40 && p_ptr->lev >= 40) msg_print(Ind, "\374\377GYour vision extends.");
4114 if (old_lev < 50 && p_ptr->lev >= 50) msg_print(Ind, "\374\377GYour vision extends.");
4115 if (old_lev < 60 && p_ptr->lev >= 60) msg_print(Ind, "\374\377GYour vision extends.");
4116 if (old_lev < 70 && p_ptr->lev >= 70) msg_print(Ind, "\374\377GYour vision extends.");
4117 if (old_lev < 80 && p_ptr->lev >= 80) msg_print(Ind, "\374\377GYour vision extends.");
4118 if (old_lev < 90 && p_ptr->lev >= 90) msg_print(Ind, "\374\377GYour vision extends.");
4119 // if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn how to levitate!");
4120 if (old_lev < 20 && p_ptr->lev >= 20) {
4121 msg_print(Ind, "\374\377GYou are now able to turn into a vampire bat (#391)!");
4122 msg_print(Ind, "\374\377G(Press '\377gm\377G' key and choose '\377guse innate power\377G' to polymorph.)");
4123 }
4124 break;
4125 #ifdef ENABLE_MAIA
4126 case RACE_MAIA:
4127 if (p_ptr->ptrait) break; /* In case we got *bad* exp drain for some unfathomable reason ;) */
4128 if (old_lev < 12 && p_ptr->lev >= 12) msg_print(Ind, "\374\377GWe all have to pick our own path some time...");
4129 // if (old_lev < 14 && p_ptr->lev >= 14) msg_print(Ind, "\374\377GYou are thirsty for blood: be it good or evil");
4130 if (old_lev < 14 && p_ptr->lev >= 14) msg_print(Ind, "\374\377GYour soul thirsts for shaping, either enlightenment or corruption!");
4131 if (old_lev <= 19 && p_ptr->lev >= 15 && old_lev < p_ptr->lev) {
4132 /* Killed none? nothing happens except if we reached the threshold level */
4133 if (p_ptr->r_killed[RI_CANDLEBEARER] == 0
4134 && p_ptr->r_killed[RI_DARKLING] == 0) {
4135 /* Threshold level has been overstepped -> die */
4136 if (old_lev == 19) {
4137 // msg_print(Ind, "\377RYou don't deserve to live.");
4138 msg_print(Ind, "\377RYour indecision proves you aren't ready yet to stay in this realm!");
4139 strcpy(p_ptr->died_from, "indecisiveness");
4140 p_ptr->deathblow = 0;
4141 p_ptr->death = TRUE;
4142 }
4143 /* We're done here.. */
4144 break;
4145 }
4146
4147 /* Killed both? -> you die */
4148 if (p_ptr->r_killed[RI_CANDLEBEARER] != 0 &&
4149 p_ptr->r_killed[RI_DARKLING] != 0) {
4150 msg_print(Ind, "\377RYour indecision proves you aren't ready yet to stay in this realm!");
4151 strcpy(p_ptr->died_from, "indecisiveness");
4152 p_ptr->deathblow = 0;
4153 p_ptr->death = TRUE;
4154 /* End of story, next.. */
4155 break;
4156 }
4157
4158 /* Don't initiate earlier than at threshold level, it's a ceremony ^^ */
4159 if (p_ptr->lev <= 19) break;
4160
4161 /* Modify skill tree */
4162 if (p_ptr->r_killed[RI_CANDLEBEARER] != 0) {
4163 //A demon appears!
4164 msg_print(Ind, "\374\377p*** \377GYour corruption grows well within you. \377p***");
4165 p_ptr->ptrait = TRAIT_CORRUPTED;
4166 } else {
4167 //An angel appears!
4168 msg_print(Ind, "\374\377p*** \377sYou have been ordained to be order in presence of chaos. \377p***");
4169 p_ptr->ptrait = TRAIT_ENLIGHTENED;
4170 }
4171
4172 shape_Maia_skills(Ind);
4173 calc_techniques(Ind);
4174
4175 p_ptr->redraw |= PR_SKILLS | PR_MISC;
4176 p_ptr->update |= PU_SKILL_INFO | PU_SKILL_MOD;
4177 }
4178 break;
4179 #endif
4180 }
4181
4182
4183 /* those that depend on a class */
4184 switch (p_ptr->pclass) {
4185 case CLASS_ROGUE:
4186 #ifdef ENABLE_CLOAKING
4187 if (old_lev < LEARN_CLOAKING_LEVEL && p_ptr->lev >= LEARN_CLOAKING_LEVEL) {
4188 msg_print(Ind, "\374\377GYou learn how to cloak yourself to pass unnoticed (press '\377gSHIFT+v\377G').");
4189 if (!p_ptr->warning_cloak) p_ptr->warning_cloak = 2;
4190 }
4191 #endif
4192 break;
4193 case CLASS_RANGER:
4194 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou learn how to move through dense forests easily.");
4195 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou learn how to swim well, with heavy backpack even.");
4196 break;
4197 case CLASS_DRUID: /* Forms gained by Druids */
4198 /* compare mimic_druid in defines.h */
4199 if (old_lev < 5 && p_ptr->lev >= 5) {
4200 msg_print(Ind, "\374\377GYou learn how to change into a Cave Bear (#160) and Panther (#198)");
4201 msg_print(Ind, "\374\377G(Press '\377gm\377G' key and choose '\377guse innate power\377G' to polymorph.)");
4202 }
4203 if (old_lev < 10 && p_ptr->lev >= 10) {
4204 msg_print(Ind, "\374\377GYou learn how to change into a Grizzly Bear (#191) and Yeti (#154)");
4205 msg_print(Ind, "\374\377GYou learn how to walk among your brothers through deep forest.");
4206 }
4207 if (old_lev < 15 && p_ptr->lev >= 15) msg_print(Ind, "\374\377GYou learn how to change into a Griffon (#279) and Sasquatch (#343)");
4208 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn how to change into a Werebear (#414), Great Eagle (#335), Aranea (#963) and Great White Shark (#898)");
4209 if (old_lev < 25 && p_ptr->lev >= 25) msg_print(Ind, "\374\377GYou learn how to change into a Wyvern (#334) and Multi-hued Hound (#513)");
4210 if (old_lev < 30 && p_ptr->lev >= 30) msg_print(Ind, "\374\377GYou learn how to change into a 5-h-Hydra (#440), Minotaur (#641) and Giant Squid (#482)");
4211 if (old_lev < 35 && p_ptr->lev >= 35) msg_print(Ind, "\374\377GYou learn how to change into a 7-h-Hydra (#614), Elder Aranea (#964) and Plasma Hound (#726)");
4212 if (old_lev < 40 && p_ptr->lev >= 40) msg_print(Ind, "\374\377GYou learn how to change into an 11-h-Hydra (#688), Giant Roc (#640) and Lesser Kraken (#740)");
4213 if (old_lev < 45 && p_ptr->lev >= 45) msg_print(Ind, "\374\377GYou learn how to change into a Maulotaur (#723) and Winged Horror (#704)");// and Behemoth (#716)");
4214 if (old_lev < 50 && p_ptr->lev >= 50) msg_print(Ind, "\374\377GYou learn how to change into a Spectral tyrannosaur (#705), Jabberwock (#778) and Greater Kraken (775)");//Leviathan (#782)");
4215 if (old_lev < 55 && p_ptr->lev >= 55) msg_print(Ind, "\374\377GYou learn how to change into a Horned Serpent (#1131)");
4216 if (old_lev < 60 && p_ptr->lev >= 60) msg_print(Ind, "\374\377GYou learn how to change into a Firebird (#1127)");
4217 break;
4218 case CLASS_SHAMAN:
4219 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to see the invisible!");
4220 break;
4221 case CLASS_MINDCRAFTER:
4222 if (old_lev < 10 && p_ptr->lev >= 10) msg_print(Ind, "\374\377GYou learn to keep hold of your sanity!");
4223 if (old_lev < 20 && p_ptr->lev >= 20) msg_print(Ind, "\374\377GYou learn to keep strong hold of your sanity!");
4224 break;
4225 }
4226
4227 /* learn fighting techniques */
4228 if (old_lev < mtech_lev[p_ptr->pclass][0] && p_ptr->lev >= mtech_lev[p_ptr->pclass][0])
4229 msg_print(Ind, "\374\377GYou learn the fighting technique 'Sprint'! (press '\377gm\377G')");
4230 if (old_lev < mtech_lev[p_ptr->pclass][1] && p_ptr->lev >= mtech_lev[p_ptr->pclass][1])
4231 msg_print(Ind, p_ptr->pclass == CLASS_MINDCRAFTER ?
4232 "\374\377GYou learn the fighting technique 'Taunt'! (press '\377gm\377G')" :
4233 "\374\377GYou learn the fighting technique 'Taunt'!");
4234 if (old_lev < mtech_lev[p_ptr->pclass][3] && p_ptr->lev >= mtech_lev[p_ptr->pclass][3])
4235 msg_print(Ind, "\374\377GYou learn the fighting technique 'Distract'!");
4236 if (old_lev < mtech_lev[p_ptr->pclass][7] && p_ptr->lev >= mtech_lev[p_ptr->pclass][7])
4237 msg_print(Ind, "\374\377GYou learn the fighting technique 'Flash bomb'!");
4238 if (old_lev < mtech_lev[p_ptr->pclass][9] && p_ptr->lev >= mtech_lev[p_ptr->pclass][9])
4239 msg_print(Ind, "\374\377GYou learn the fighting technique 'Spin'!");
4240 #ifdef ENABLE_ASSASSINATE
4241 if (old_lev < mtech_lev[p_ptr->pclass][10] && p_ptr->lev >= mtech_lev[p_ptr->pclass][10])
4242 msg_print(Ind, "\374\377GYou learn the fighting technique 'Assasinate'!");
4243 #endif
4244 if (old_lev < mtech_lev[p_ptr->pclass][11] && p_ptr->lev >= mtech_lev[p_ptr->pclass][11])
4245 msg_print(Ind, "\374\377GYou learn the fighting technique 'Berserk'!");
4246 if (old_lev < mtech_lev[p_ptr->pclass][14] && p_ptr->lev >= mtech_lev[p_ptr->pclass][14]
4247 && p_ptr->total_winner)
4248 msg_print(Ind, "\374\377GYou learn the royal fighting technique 'Shadow run'!");
4249
4250 /* update the client's 'm' menu for fighting techniques */
4251 calc_techniques(Ind);
4252 Send_skill_info(Ind, SKILL_TECHNIQUE, TRUE);
4253
4254
4255 #ifdef ENABLE_STANCES
4256 /* increase SKILL_STANCE by +1 automatically (just for show :-p) if we actually have that skill */
4257 if (get_skill(p_ptr, SKILL_STANCE) && p_ptr->lev <= 50) {
4258 p_ptr->s_info[SKILL_STANCE].value = p_ptr->lev * 1000;
4259 /* Update the client */
4260 Send_skill_info(Ind, SKILL_STANCE, TRUE);
4261 /* give message if we learn a new stance (compare cmd6.c! keep it synchronized */
4262 msg_gained_abilities(Ind, (p_ptr-> lev - 1) * 10, SKILL_STANCE);
4263 }
4264 #endif
4265
4266 #if 0 /* Make fruit bat gain speed on levelling up, instead of starting out with full +10 speed bonus? */
4267 if (p_ptr->fruit_bat == 1 && old_lev < p_ptr->lev) {
4268 if (p_ptr->lev % 5 == 0 && p_ptr->lev <= 35) msg_print(Ind, "\374\377GYour flying abilities have improved, you have gained some speed.");
4269 }
4270 #endif
4271
4272 #ifdef KINGCAP_LEV
4273 /* Added a check that (s)he's not already a king - mikaelh */
4274 // if(p_ptr->lev == 50 && !p_ptr->total_winner) msg_print(Ind, "\374\377GYou can't gain more levels until you defeat Morgoth, Lord of Darkness!");
4275 if (p_ptr->lev == 50 && !p_ptr->total_winner) msg_print(Ind, "\374\377G* To level up further, you must defeat Morgoth, Lord of Darkness! *");
4276 #endif
4277
4278 /* pvp mode cant go higher, but receives a reward maybe */
4279 if (p_ptr->mode & MODE_PVP) {
4280 if (get_skill(p_ptr, SKILL_MIMIC) &&
4281 p_ptr->pclass != CLASS_DRUID &&
4282 p_ptr->prace != RACE_VAMPIRE) {
4283 msg_print(Ind, "\375\377GYou gain one free mimicry transformation of your choice!");
4284 p_ptr->free_mimic = 1;
4285 }
4286 if (old_lev < MID_PVP_LEVEL && p_ptr->lev >= MID_PVP_LEVEL) {
4287 msg_broadcast_format(Ind, "\374\377G* %s has raised in ranks greatly! *", p_ptr->name);
4288 msg_print(Ind, "\375\377G* You have raised quite a bit in ranks of PvP characters! *");
4289 msg_print(Ind, "\375\377G* For that, you just received a reward, and if you die you will *");
4290 msg_print(Ind, "\375\377G* also receive a deed on the next character you log in with. *");
4291 give_reward(Ind, RESF_MID, "Gladiator's reward", 1, 0);
4292 }
4293 if (p_ptr->lev == MAX_PVP_LEVEL) {
4294 msg_broadcast_format(Ind, "\374\377G* %s has reached the highest level available to PvP characters! *", p_ptr->name);
4295 msg_print(Ind, "\375\377G* You have reached the highest level available to PvP characters! *");
4296 msg_print(Ind, "\375\377G* For that, you just received a reward, and if you die you will *");
4297 msg_print(Ind, "\375\377G* also receive a deed on the next character you log in with. *");
4298 // buffer_account_for_achievement_deed(p_ptr, ACHV_PVP_MAX);
4299 give_reward(Ind, RESF_HIGH, "Gladiator's reward", 1, 0);
4300 }
4301 }
4302
4303 /* Make a new copy of the skills - mikaelh */
4304 memcpy(p_ptr->s_info_old, p_ptr->s_info, MAX_SKILLS * sizeof(skill_player));
4305 p_ptr->skill_points_old = p_ptr->skill_points;
4306
4307 /* Reskilling is now possible */
4308 p_ptr->reskill_possible = TRUE;
4309
4310 /* Re-check house permissions, to display doors in correct colour (level-based door access!) */
4311 if (!p_ptr->wpos.wz) p_ptr->redraw |= PR_MAP;
4312
4313 /* Handle stuff */
4314 handle_stuff(Ind);
4315
4316 /* Update the skill points info on the client */
4317 Send_skill_info(Ind, 0, TRUE);
4318 }
4319
4320
4321 /*
4322 * Gain experience
4323 */
gain_exp(int Ind,s64b amount)4324 void gain_exp(int Ind, s64b amount) {
4325 player_type *p_ptr = Players[Ind];//, *p_ptr2=NULL;
4326 // int Ind2 = 0;
4327
4328 if (is_admin(p_ptr) && p_ptr->lev >= 99) return;
4329
4330 /* enforce dedicated Ironman Deep Dive Challenge character slot usage */
4331 if (amount && (p_ptr->mode & MODE_DED_IDDC) && !in_irondeepdive(&p_ptr->wpos)) {
4332 #if 0 /* poof when gaining exp prematurely */
4333 msg_print(Ind, "\377RYou failed to enter the Ironman Deep Dive Challenge!");
4334 strcpy(p_ptr->died_from, "indetermination");
4335 p_ptr->deathblow = 0;
4336 p_ptr->death = TRUE;
4337 return;
4338 #else /* just don't get exp */
4339 return;
4340 #endif
4341 }
4342
4343 if (p_ptr->IDDC_logscum) {
4344 //(spammy) msg_print(Ind, "\377oThis floor has become stale, take a staircase to move on!");
4345 return;
4346 }
4347
4348 #ifdef IRON_TEAM_EXPERIENCE
4349 int iron_team_members_here = 0, iron_team_limit = 0;
4350 #endif
4351
4352 #ifdef ARCADE_SERVER
4353 return;
4354 #endif
4355
4356 if (amount <= 0) return;
4357 #ifdef ALT_EXPRATIO
4358 /* New way to gain exp: Exp ratio works no longer for determining required exp
4359 to level up, but instead to determine how much exp you gain: */
4360 amount = (amount * 100L) / ((s64b)p_ptr->expfact);
4361 if (amount < 1) amount = 1;
4362 #endif
4363
4364 /* You cant gain xp on your land */
4365 if (player_is_king(Ind)) return;
4366
4367
4368 #ifdef IRON_TEAM_EXPERIENCE
4369 /* moved here from party_gain_exp() for implementing the 'sync'-exception */
4370 /* Iron Teams only get exp if the whole team is on the same floor! - C. Blue */
4371 if (p_ptr->party && parties[p_ptr->party].mode == PA_IRONTEAM) {
4372 for (i = 1; i <= NumPlayers; i++) {
4373 if (p_ptr->conn == NOT_CONNECTED) continue;
4374
4375 /* note: this line means that iron teams must not add
4376 admins, or the members won't gain exp anymore */
4377 if (is_admin(p_ptr)) continue;
4378
4379 /* player on the same dungeon level? */
4380 if (!inarea(&p_ptr->wpos, wpos)) continue;
4381
4382 /* count party members on the same dlvl */
4383 if (player_in_party(p_ptr->party, i)) iron_team_members_here++;
4384 }
4385
4386 /* only gain exp if all members are here */
4387 if (iron_team_members_here != parties[p_ptr->party].members) {
4388 /* New: allow exception to somewhat 'sync' own exp w/ the exp of
4389 iron team member having the most exp, to avoid falling back too much.
4390 (most drastic example: death of everlasting char). - C. Blue */
4391 if (p_ptr->exp >= parties[p_ptr->party].experience) return;
4392 iron_team_limit = parties[p_ptr->party].experience;
4393 }
4394 }
4395 #endif
4396
4397
4398 /* allow own kills to be gained */
4399 if (p_ptr->ghost) amount = (amount * 2) / 4;
4400
4401 #ifdef KINGCAP_LEV
4402 /* You must defeat morgoth before being allowed level > 50
4403 otherwise stop 1 exp point before 51 */
4404 #ifndef ALT_EXPRATIO
4405 if ((!p_ptr->total_winner) && (p_ptr->exp + amount + 1 >=
4406 ((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)))) {
4407 if (p_ptr->exp + 1 >=
4408 ((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)))
4409 return;
4410 amount = ((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)) - p_ptr->exp;
4411 amount--;
4412 }
4413 #else
4414 if ((!p_ptr->total_winner) && (p_ptr->exp + amount + 1 >= ((s64b)player_exp[50 - 1]))) {
4415 if (p_ptr->exp + 1 >= ((s64b)player_exp[50 - 1]))
4416 return;
4417 amount = ((s64b)player_exp[50 - 1]) - p_ptr->exp;
4418 amount--;
4419 }
4420 #endif
4421 #endif
4422 #ifdef KINGCAP_EXP
4423 /* You must defeat morgoth before being allowed to gain more
4424 than 21,240,000 exp which is level 50 for Draconian Ranger <- might be OUTDATED */
4425 if ((!p_ptr->total_winner) && (p_ptr->exp + amount >= 21240000)) {
4426 if (p_ptr->exp >= 21240000) return;
4427 amount = 21240000 - p_ptr->exp;
4428 }
4429 #endif
4430
4431 /* PvP-mode players have a level limit */
4432 if (p_ptr->mode & MODE_PVP) {
4433 #ifndef ALT_EXPRATIO
4434 if (p_ptr->exp + amount + 1 >= ((s64b)((s64b)player_exp[MAX_PVP_LEVEL - 1] *
4435 (s64b)p_ptr->expfact / 100L))) {
4436 if (p_ptr->exp + 1 >= ((s64b)((s64b)player_exp[MAX_PVP_LEVEL - 1] *
4437 (s64b)p_ptr->expfact / 100L)))
4438 return;
4439 amount = ((s64b)((s64b)player_exp[MAX_PVP_LEVEL - 1] * (s64b)p_ptr->expfact / 100L)) - p_ptr->exp;
4440 amount--;
4441 }
4442 #else
4443 if (p_ptr->exp + amount + 1 >= ((s64b)player_exp[MAX_PVP_LEVEL - 1])) {
4444 if (p_ptr->exp + 1 >= ((s64b)player_exp[MAX_PVP_LEVEL - 1]))
4445 return;
4446 amount = ((s64b)player_exp[MAX_PVP_LEVEL - 1]) - p_ptr->exp;
4447 amount--;
4448 }
4449 #endif
4450 }
4451
4452 #ifdef IRON_TEAM_EXPERIENCE
4453 /* new: allow players to 'sync' their exp to leading player in an iron team party */
4454 if (iron_team_limit && (p_ptr->exp + amount > iron_team_limit))
4455 amount = iron_team_limit - p_ptr->exp;
4456 #endif
4457
4458 /* Gain some experience */
4459 p_ptr->exp += amount;
4460
4461 /* Slowly recover from experience drainage */
4462 if (p_ptr->exp < p_ptr->max_exp) {
4463 #ifdef KINGCAP_LEV
4464 /* You must defeat morgoth before beong allowed level > 50 */
4465 #ifndef ALT_EXPRATIO
4466 if ((!p_ptr->total_winner) && (p_ptr->max_exp + (amount/10) + 1 >= ((s64b)((s64b)player_exp[50 - 1] *
4467 (s64b)p_ptr->expfact / 100L)))) {
4468 if (p_ptr->max_exp >= ((s64b)((s64b)player_exp[50 - 1] *
4469 (s64b)p_ptr->expfact / 100L)))
4470 return;
4471 amount = (((s64b)((s64b)player_exp[50 - 1] * (s64b)p_ptr->expfact / 100L)) - p_ptr->max_exp);
4472 amount--;
4473 }
4474 #else
4475 if ((!p_ptr->total_winner) && (p_ptr->max_exp + (amount/10) + 1 >= ((s64b)player_exp[50 - 1]))) {
4476 if (p_ptr->max_exp >= ((s64b)player_exp[50 - 1]))
4477 return;
4478 amount = (((s64b)player_exp[50 - 1]) - p_ptr->max_exp);
4479 amount--;
4480 }
4481 #endif
4482 #endif
4483 #ifdef KINGCAP_EXP
4484 if ((!p_ptr->total_winner) && (p_ptr->max_exp + (amount/10) >= 21240000)) {
4485 if (p_ptr->max_exp >= 21240000) return;
4486 amount = (21240000 - p_ptr->max_exp);
4487 }
4488 #endif
4489
4490 #ifdef IRON_TEAM_EXPERIENCE
4491 /* new: allow players to 'sync' their exp to leading player in an iron team party */
4492 if (iron_team_limit && (p_ptr->max_exp + amount > iron_team_limit))
4493 amount = iron_team_limit - p_ptr->max_exp;
4494 #endif
4495
4496 /* Gain max experience (10%) */
4497 p_ptr->max_exp += amount / 10;
4498 }
4499
4500 /* Check Experience */
4501 check_experience(Ind);
4502
4503 #ifdef IRON_TEAM_EXPERIENCE
4504 /* possibly set new maximum for iron team */
4505 if (p_ptr->party && parties[p_ptr->party].mode == PA_IRONTEAM &&
4506 p_ptr->max_exp > parties[p_ptr->party].experience)
4507 parties[p_ptr->party].experience = p_ptr->max_exp;
4508 #endif
4509 }
4510
4511
4512 /*
4513 * Lose experience
4514 * (caused by GF_NETHER, GF_CHAOS, traps, exp-melee-hits, TY-curse)
4515 */
lose_exp(int Ind,s32b amount)4516 void lose_exp(int Ind, s32b amount) {
4517 player_type *p_ptr = Players[Ind];
4518
4519 /* Amulet of Immortality */
4520 if (p_ptr->admin_invuln) return;
4521
4522 if (safe_area(Ind)) return;
4523
4524 /* Amulet of Immortality */
4525 if (p_ptr->admin_invuln) return;
4526
4527 /* Paranoia */
4528 if (p_ptr->death) return;
4529
4530 /* Hack -- player is secured inside a store/house except in dungeons */
4531 if (p_ptr->store_num != -1 && !p_ptr->wpos.wz && !bypass_invuln) return;
4532
4533 #if 0
4534 if (disturb) {
4535 break_cloaking(Ind, 0);
4536 stop_precision(Ind);
4537 }
4538 #endif
4539
4540 if (p_ptr->lev == 99) {
4541 //msg_print(Ind, "You are impervious to life force drain!");
4542 return;
4543 }
4544
4545 #if 0 /* todo: get this right and all */
4546 /* Mega-Hack -- Apply "invulnerability" */
4547 if (p_ptr->invuln && (!bypass_invuln) && !p_ptr->invuln_applied) {
4548 /* Hack: Just reduce exp loss flat */
4549 amount = (amount + 1) / 2;
4550 }
4551 #endif
4552
4553 /* Never drop below zero experience */
4554 if (amount > p_ptr->exp) amount = p_ptr->exp - 1;
4555 if (!amount) return;
4556
4557 #if 1
4558 if (((p_ptr->alert_afk_dam && p_ptr->afk)
4559 #ifdef ALERT_OFFPANEL_DAM
4560 || (p_ptr->alert_offpanel_dam && (p_ptr->panel_row_old != p_ptr->panel_row || p_ptr->panel_col_old != p_ptr->panel_col))
4561 #endif
4562 )
4563 #ifdef USE_SOUND_2010
4564 ) {
4565 Send_warning_beep(Ind);
4566 //sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
4567 #else
4568 && p_ptr->paging == 0) {
4569 p_ptr->paging = 1;
4570 #endif
4571 }
4572 #endif
4573
4574 #if 1
4575 /* warn if taking (continuous) damage while inside a store! */
4576 if (p_ptr->store_num != -1) {
4577 #ifdef USE_SOUND_2010
4578 Send_warning_beep(Ind);
4579 //sound(Ind, "warning", "page", SFX_TYPE_MISC, FALSE);
4580 #else
4581 if (p_ptr->paging == 0) p_ptr->paging = 1;
4582 #endif
4583 //all places using lose_exp() already give a message..
4584 //msg_print(Ind, "\377RWarning - your experience is getting drained!");
4585 }
4586 #endif
4587
4588 /* Lose some experience */
4589 p_ptr->exp -= amount;
4590
4591 /* Check Experience */
4592 check_experience(Ind);
4593 }
4594
4595
4596 /* helper function to boost a character to a specific level (for Dungeon Keeper event) */
4597 void gain_exp_to_level(int Ind, int level) {
4598 u32b k = 0;
4599 if (level <= 1) return;
4600 k = player_exp[level - 2];
4601 if (Players[Ind]->max_exp < k)
4602 /* make up for rounding error (+99) */
4603 gain_exp(Ind, ((k - Players[Ind]->max_exp) * Players[Ind]->expfact + 99) / 100);
4604 }
4605
4606
4607
4608 /*
4609 * Hack -- Return the "automatic coin type" of a monster race
4610 * Used to allocate proper treasure when "Creeping coins" die
4611 *
4612 * XXX XXX XXX Note the use of actual "monster names"
4613 */
4614 static int get_coin_type(monster_race *r_ptr) {
4615 cptr name = (r_name + r_ptr->name);
4616
4617 /* Analyze "coin" monsters */
4618 if (r_ptr->d_char == '$') {
4619 /* Look for textual clues */
4620 if (strstr(name, " copper ")) return (1);
4621 if (strstr(name, " silver ")) return (2);
4622 if (strstr(name, " gold ")) return (10);
4623 if (strstr(name, " mithril ")) return (16);
4624 if (strstr(name, " adamantite ")) return (18);
4625
4626 /* Look for textual clues */
4627 if (strstr(name, "Copper ")) return (1);
4628 if (strstr(name, "Silver ")) return (2);
4629 if (strstr(name, "Gold ")) return (10);
4630 if (strstr(name, "Mithril ")) return (16);
4631 if (strstr(name, "Adamantite ")) return (18);
4632 }
4633
4634 /* Assume nothing */
4635 return (0);
4636 }
4637
4638
4639 /*
4640 * Handle the "death" of a monster.
4641 *
4642 * Disperse treasures centered at the monster location based on the
4643 * various flags contained in the monster flags fields.
4644 *
4645 * Check for "Quest" completion when a quest monster is killed.
4646 *
4647 * Note that only the player can induce "monster_death()" on Uniques.
4648 * Thus (for now) all Quest monsters should be Uniques.
4649 *
4650 * Note that in a few, very rare, circumstances, killing Morgoth
4651 * may result in the Iron Crown of Morgoth crushing the Lead-Filled
4652 * Mace "Grond", since the Iron Crown is more important.
4653 */
4654
4655 /* Display Zu-Aon kills in special colours:
4656 * UxU is too flashy, lcl is possible, xcx maybe best (Nether Realm floor look preserved in msg ;) */
4657 #define ZU_AON_FLASHY_MSG
4658
4659 void monster_death(int Ind, int m_idx) {
4660 player_type *p_ptr = Players[Ind];
4661 player_type *q_ptr = Players[Ind];
4662
4663 int i, j, y, x, ny, nx;
4664 int tmp_luck = p_ptr->luck;
4665
4666 // int dump_item = 0;
4667 // int dump_gold = 0;
4668
4669 int number = 0;
4670 int total = 0;
4671
4672 char buf[160], m_name[MAX_CHARS], o_name[ONAME_LEN];
4673 cptr titlebuf;
4674
4675 cave_type *c_ptr;
4676
4677 monster_type *m_ptr = &m_list[m_idx];
4678 monster_race *r_ptr = race_inf(m_ptr);
4679 bool is_Morgoth = (m_ptr->r_idx == RI_MORGOTH);
4680 bool is_Sauron = (m_ptr->r_idx == RI_SAURON);
4681 bool is_Pumpkin = (m_ptr->r_idx == RI_PUMPKIN1 || m_ptr->r_idx == RI_PUMPKIN2 || m_ptr->r_idx == RI_PUMPKIN3);
4682 int credit_idx = r_ptr->dup_idx ? r_ptr->dup_idx : m_ptr->r_idx;
4683 // bool visible = (p_ptr->mon_vis[m_idx] || (r_ptr->flags1 & RF1_UNIQUE));
4684
4685 bool good = (r_ptr->flags1 & RF1_DROP_GOOD) ? TRUE : FALSE;
4686 bool great = (r_ptr->flags1 & RF1_DROP_GREAT) ? TRUE : FALSE;
4687
4688 bool do_gold = (!(r_ptr->flags1 & RF1_ONLY_ITEM));
4689 bool do_item = (!(r_ptr->flags1 & RF1_ONLY_GOLD));
4690
4691 int force_coin = get_coin_type(r_ptr);
4692 s16b local_quark = 0;
4693 object_type forge;
4694 object_type *qq_ptr;
4695 struct worldpos *wpos;
4696 cave_type **zcave;
4697 int dlev, rlev, tol_lev;
4698
4699 int a_idx, chance, I_kind;
4700 artifact_type *a_ptr;
4701
4702 bool henc_cheezed = FALSE, pvp = ((p_ptr->mode & MODE_PVP) != 0);
4703 u32b resf_drops = make_resf(p_ptr), resf_chosen = resf_drops;
4704
4705
4706 /* experimental: Zu-Aon drops only randarts */
4707 if (m_ptr->r_idx == RI_ZU_AON || m_ptr->r_idx == RI_BAD_LUCK_BAT)
4708 resf_drops |= (RESF_FORCERANDART | RESF_NOTRUEART);
4709 /* Morgoth never drops true artifacts */
4710 if (is_Morgoth) resf_drops |= RESF_NOTRUEART;
4711
4712 /* terminate mindcrafter charm effect */
4713 if (m_ptr->charmedignore) {
4714 Players[m_ptr->charmedignore]->mcharming--;
4715 m_ptr->charmedignore = 0;
4716 }
4717
4718 #ifdef RPG_SERVER
4719 /* Pet death. Update and inform the owner -the_sandman */
4720 if (m_ptr->pet) {
4721 for (i = NumPlayers; i > 0; i--) {
4722 if (m_ptr->owner == Players[i]->id) {
4723 msg_format(i, "\374\377R%s has killed your pet!", Players[Ind]->name);
4724 msg_format(Ind, "\374\377RYou have killed %s's pet!", Players[i]->name);
4725 Players[i]->has_pet = 0;
4726 FREE(m_ptr->r_ptr, monster_race); //no drop, no exp.
4727 return;
4728 }
4729 }
4730 }
4731 #endif
4732
4733 if (cfg.henc_strictness && !p_ptr->total_winner &&
4734 /* p_ptr->lev more logical but harsh: */
4735 #if 1 /* player should always seek not too high-level party members compared to player's current real level? */
4736 m_ptr->henc - p_ptr->max_lev > MAX_PARTY_LEVEL_DIFF + 1)
4737 #else /* players may seek higher-level party members to team up with if he's died before? Weird combination so not recommended! */
4738 m_ptr->henc - p_ptr->max_plv > MAX_PARTY_LEVEL_DIFF + 1)
4739 #endif
4740 henc_cheezed = TRUE;
4741
4742 /* Get the location */
4743 y = m_ptr->fy;
4744 x = m_ptr->fx;
4745 wpos = &m_ptr->wpos;
4746 if (!(zcave = getcave(wpos))) return;
4747
4748 if (ge_special_sector && /* training tower event running? and we are there? */
4749 wpos->wx == WPOS_ARENA_X && wpos->wy == WPOS_ARENA_Y &&
4750 wpos->wz == WPOS_ARENA_Z) {
4751 monster_desc(0, m_name, m_idx, 0x00);
4752 msg_broadcast_format(0, "\376\377S** %s has defeated %s! **", p_ptr->name, m_name);
4753 s_printf("EVENT_RESULT: %s (%d) has defeated %s.\n", p_ptr->name, p_ptr->lev, m_name);
4754 }
4755
4756 /* get monster name for damage deal description */
4757 monster_desc(Ind, m_name, m_idx, 0x00);
4758
4759 process_hooks(HOOK_MONSTER_DEATH, "d", Ind);
4760
4761 if (season_halloween) {
4762 /* let everyone know, so they are prepared.. >:) */
4763 if ((m_ptr->r_idx == RI_PUMPKIN1 || m_ptr->r_idx == RI_PUMPKIN2 || m_ptr->r_idx == RI_PUMPKIN3)
4764 && !m_ptr->clone) {
4765 msg_broadcast_format(0, "\374\377L**\377o%s has defeated a tasty halloween spirit!\377L**", p_ptr->name);
4766 s_printf("HALLOWEEN: %s (%d/%d) has defeated %s.\n", p_ptr->name, p_ptr->max_plv, p_ptr->max_lev, m_name);
4767 great_pumpkin_timer = 15 + rand_int(45);
4768 //great_pumpkin_killer = p_ptr->id;
4769 strcpy(great_pumpkin_killer, p_ptr->accountname);
4770 }
4771 } else if (season_xmas) {
4772 if ((m_ptr->r_idx == RI_SANTA1 || m_ptr->r_idx == RI_SANTA2)
4773 && !m_ptr->clone) {
4774 msg_broadcast_format(0, "\374\377L**\377oSanta dropped the presents near %s!\377L**", p_ptr->name);
4775 s_printf("XMAS: %s (%d) has defeated %s.\n", p_ptr->name, p_ptr->max_plv, m_name);
4776 santa_claus_timer = 60 + rand_int(120);
4777 }
4778 }
4779
4780
4781
4782 /*
4783 * Mega^3-hack: killing a 'Warrior of the Dawn' is likely to
4784 * spawn another in the fallen one's place!
4785 */
4786 if (strstr((r_name + r_ptr->name),"the Dawn")) {
4787 if (!(randint(20) == 13)) {
4788 int wy = p_ptr->py, wx = p_ptr->px;
4789 int attempts = 100;
4790
4791 do {
4792 scatter(wpos, &wy, &wx,p_ptr->py,p_ptr->px, 20, 0);
4793 } while (!(in_bounds(wy,wx) && cave_floor_bold(zcave, wy,wx)) && --attempts);
4794
4795 if (attempts > 0) {
4796 #if 0
4797 if (is_friend(m_ptr) > 0) {
4798 if (summon_specific_friendly(wy, wx, 100, SUMMON_DAWN, FALSE)) {
4799 if (player_can_see_bold(wy, wx))
4800 msg_print ("A new warrior steps forth!");
4801 }
4802 }
4803 else
4804 #endif
4805 {
4806 if (summon_specific(wpos, wy, wx, 100, m_ptr->clone + 20, SUMMON_DAWN, 1, 0)) {
4807 if (player_can_see_bold(Ind, wy, wx))
4808 msg_print (Ind, "A new warrior steps forth!");
4809 }
4810 }
4811 }
4812 }
4813 }
4814
4815 /* One more ultra-hack: An Unmaker goes out with a big bang! */
4816 else if (strstr((r_name + r_ptr->name),"Unmaker")) {
4817 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
4818 (void)project(m_idx, 6, wpos, y, x, 150, GF_CHAOS, flg, "The Unmaker explodes for");
4819 }
4820
4821 /* Pink horrors are replaced with 2 Blue horrors */
4822 else if (strstr((r_name + r_ptr->name),"Pink horror")) {
4823 for (i = 0; i < 2; i++) {
4824 int wy = p_ptr->py, wx = p_ptr->px;
4825 int attempts = 100;
4826
4827 do {
4828 scatter(wpos, &wy, &wx, p_ptr->py, p_ptr->px, 3, 0);
4829 } while (!(in_bounds(wy,wx) && cave_floor_bold(zcave, wy,wx)) && --attempts);
4830
4831 if (attempts > 0) {
4832 summon_override_checks = SO_IDDC;
4833 if (summon_specific(wpos, wy, wx, 100, 0, SUMMON_BLUE_HORROR, 1, 0)) { /* that's _not_ 2, lol */
4834 if (player_can_see_bold(Ind, wy, wx))
4835 msg_print (Ind, "A blue horror appears!");
4836 }
4837 summon_override_checks = SO_NONE;
4838 }
4839 }
4840 }
4841
4842 /* Let monsters explode! */
4843 for (i = 0; i < 4; i++) {
4844 if (m_ptr->blow[i].method == RBM_EXPLODE) {
4845 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
4846 int typ = GF_MISSILE;
4847 int d_dice = m_ptr->blow[i].d_dice;
4848 int d_side = m_ptr->blow[i].d_side;
4849 int damage = damroll(d_dice, d_side);
4850 int base_damage = r_ptr->blow[i].d_dice * r_ptr->blow[i].d_side; /* if monster didn't gain levels */
4851
4852 switch (m_ptr->blow[i].effect) {
4853 case RBE_HURT: typ = GF_MISSILE; break;
4854 case RBE_POISON: typ = GF_POIS; break;
4855 case RBE_UN_BONUS: typ = GF_DISENCHANT; break;
4856 case RBE_UN_POWER: typ = GF_MISSILE; break; /* ToDo: Apply the correct effects */
4857 case RBE_EAT_GOLD: typ = GF_MISSILE; break;
4858 case RBE_EAT_ITEM: typ = GF_MISSILE; break;
4859 case RBE_EAT_FOOD: typ = GF_MISSILE; break;
4860 case RBE_EAT_LITE: typ = GF_MISSILE; break;
4861 case RBE_ACID: typ = GF_ACID; break;
4862 case RBE_ELEC: typ = GF_ELEC; break;
4863 case RBE_FIRE: typ = GF_FIRE; break;
4864 case RBE_COLD: typ = GF_COLD; break;
4865 case RBE_BLIND: typ = GF_BLIND; break;
4866 case RBE_LITE: typ = GF_LITE; break;
4867 // case RBE_HALLU: typ = GF_CONFUSION; break;
4868 case RBE_HALLU: typ = GF_CHAOS; break; /* CAUTION! */
4869 case RBE_CONFUSE: typ = GF_CONFUSION; break;
4870 case RBE_TERRIFY: typ = GF_MISSILE; break;
4871 case RBE_PARALYZE: typ = GF_MISSILE; break;
4872 case RBE_LOSE_STR: typ = GF_MISSILE; break;
4873 case RBE_LOSE_DEX: typ = GF_MISSILE; break;
4874 case RBE_LOSE_CON: typ = GF_MISSILE; break;
4875 case RBE_LOSE_INT: typ = GF_MISSILE; break;
4876 case RBE_LOSE_WIS: typ = GF_MISSILE; break;
4877 case RBE_LOSE_CHR: typ = GF_MISSILE; break;
4878 case RBE_LOSE_ALL: typ = GF_MISSILE; break;
4879 case RBE_PARASITE: typ = GF_MISSILE; break;
4880 case RBE_SHATTER: typ = GF_DETONATION; break;
4881 case RBE_EXP_10: typ = GF_MISSILE; break;
4882 case RBE_EXP_20: typ = GF_MISSILE; break;
4883 case RBE_EXP_40: typ = GF_MISSILE; break;
4884 case RBE_EXP_80: typ = GF_MISSILE; break;
4885 case RBE_DISEASE: typ = GF_POIS; break;
4886 case RBE_TIME: typ = GF_TIME; break;
4887 case RBE_SANITY: typ = GF_MISSILE; break;
4888 }
4889
4890 snprintf(p_ptr->attacker, sizeof(p_ptr->attacker), "%s inflicts", m_name);
4891 project(m_idx, 3, wpos, y, x, damage > base_damage ? base_damage : damage, typ, flg, p_ptr->attacker);
4892 break;
4893 }
4894 }
4895
4896 /* Log-scumming in IDDC is like fighting clones */
4897 if (p_ptr->IDDC_logscum) return;
4898 /* enforce dedicated Ironman Deep Dive Challenge character slot usage */
4899 if ((p_ptr->mode & MODE_DED_IDDC) && !in_irondeepdive(&p_ptr->wpos)
4900 && r_ptr->mexp) /* Allow kills in Bree */
4901 return;
4902 /* clones don't drop treasure or complete quests.. */
4903 if (m_ptr->clone) {
4904 /* Specialty - even for non-creditable Sauron:
4905 If Sauron is killed in Mt Doom, allow the player to recall! */
4906 if (is_Sauron) {
4907 dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
4908 if (d_ptr->type == DI_MT_DOOM) {
4909 dun_level *l_ptr = getfloor(&p_ptr->wpos);
4910 l_ptr->flags1 |= LF1_IRON_RECALL;
4911 floor_msg_format(&p_ptr->wpos, "\374\377gYou don't sense a magic barrier here!");
4912 }
4913 }
4914
4915 /* no credit/loot for clones */
4916 return;
4917 }
4918 /* ..neither do cheezed kills */
4919 if (henc_cheezed &&
4920 !is_Morgoth && /* make exception for Morgoth, so hi-lvl fallen kings can re-king */
4921 !is_Pumpkin) /* allow a mixed hunting group */
4922 return;
4923
4924 /* Check whether a quest requested this monster dead */
4925 if (p_ptr->quest_any_k_within_target) quest_check_goal_k(Ind, m_ptr);
4926
4927 dlev = getlevel(wpos);
4928 rlev = r_ptr->level;
4929
4930 /* Determine how much we can drop */
4931 if ((r_ptr->flags1 & RF1_DROP_60) && (rand_int(100) < 60)) number++;
4932 if ((r_ptr->flags1 & RF1_DROP_90) && (rand_int(100) < 90)) number++;
4933 if (r_ptr->flags0 & RF0_DROP_1) number++;
4934 if (r_ptr->flags1 & RF1_DROP_1D2) number += damroll(1, 2);
4935 if (r_ptr->flags1 & RF1_DROP_2D2) number += damroll(2, 2);
4936 if (r_ptr->flags1 & RF1_DROP_3D2) number += damroll(3, 2);
4937 if (r_ptr->flags1 & RF1_DROP_4D2) number += damroll(4, 2);
4938
4939 /* Hack -- inscribe items that a unique drops */
4940 if (r_ptr->flags1 & RF1_UNIQUE) {
4941 local_quark = quark_add(r_name + r_ptr->name);
4942 unique_quark = local_quark;
4943
4944 /* make uniques drop a bit better than normal monsters */
4945 tmp_luck += 20;
4946 /* luck caps at 40 */
4947 if (tmp_luck > 40) tmp_luck = 40;
4948 }
4949
4950 /* Questors: Usually drop no items, except if specified */
4951 if (m_ptr->questor) {
4952 if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
4953 if (!(q_info[m_ptr->quest].questor[m_ptr->questor_idx].drops & 0x1)) number = 0;
4954 } else {
4955 s_printf("QUESTOR_DEPRECATED (monster_dead)\n");
4956 number = 0;
4957 }
4958 }
4959
4960 /* Drop some objects */
4961 for (j = 0; j < number; j++) {
4962 /* Try 20 times per item, increasing range */
4963 // for (i = 0; i < 20; ++i)
4964 {
4965 #if 0
4966 int d = (i + 14) / 15;
4967
4968 /* Pick a "correct" location */
4969 scatter(wpos, &ny, &nx, y, x, d, 0);
4970 /* Must be "clean" floor grid */
4971 if (!cave_clean_bold(zcave, ny, nx)) continue;
4972
4973 /* Access the grid */
4974 c_ptr = &zcave[ny][nx];
4975 #endif // 0
4976
4977 /* Hack -- handle creeping coins */
4978 coin_type = force_coin;
4979
4980 #ifdef TRADITIONAL_LOOT_LEVEL
4981 /* Average dungeon and monster levels */
4982 object_level = (dlev + rlev) / 2;
4983 #ifdef RANDOMIZED_LOOT_LEVEL
4984 if (object_level < rlev) tol_lev = rlev - object_level;
4985 else tol_lev = dlev - object_level;
4986 if (tol_lev > 11) tol_lev = 13; /* need +12 levels of tolerance to allow depth-115 items to drop from level 80 monsters */
4987 object_level += rand_int(tol_lev);
4988 #endif
4989 #else
4990 /* Monster level is more important than floor level */
4991 object_level = (dlev + rlev * 2) / 3;
4992 #ifdef RANDOMIZED_LOOT_LEVEL
4993 if (object_level < rlev) tol_lev = rlev - object_level;
4994 else tol_lev = dlev - object_level;
4995 if (tol_lev > 21) tol_lev = 21; /* need +20 levels of tolerance to allow depth-115 items to drop from level 80 monsters */
4996 object_level += rand_int(tol_lev);
4997 #endif
4998 #endif
4999
5000 /* No easy item hunting in towns.. */
5001 if (wpos->wz == 0) object_level = rlev / 2;
5002
5003 /* Place Gold */
5004 if (do_gold && (!do_item || (rand_int(100) < 50))) {
5005 place_gold(wpos, y, x, 0);
5006 // if (player_can_see_bold(Ind, ny, nx)) dump_gold++;
5007 }
5008
5009 /* Place Object */
5010 else {
5011 place_object_restrictor = RESF_NONE;
5012
5013 /* hack to allow custom test l00t drop for admins: */
5014 if (is_admin(p_ptr)) {
5015 /* the hack works by using weapon's inscription! */
5016 char *k_tval, *k_sval;
5017 if (p_ptr->inventory[INVEN_WIELD].tval &&
5018 p_ptr->inventory[INVEN_WIELD].note &&
5019 (k_tval = strchr(quark_str(p_ptr->inventory[INVEN_WIELD].note), '%')) &&
5020 (k_sval = strchr(k_tval, ':'))
5021 ) {
5022 resf_drops |= RESF_DEBUG_ITEM;
5023 /* extract tval:sval */
5024 /* abuse luck parameter for this */
5025 tmp_luck = lookup_kind(atoi(k_tval + 1), atoi(k_sval + 1));
5026 /* catch invalid items */
5027 if (!tmp_luck) resf_drops &= ~RESF_DEBUG_ITEM;
5028 }
5029 }
5030
5031 /* generate an object and place it */
5032 place_object(wpos, y, x, good, great, FALSE, resf_drops, r_ptr->drops, tmp_luck, ITEM_REMOVAL_NORMAL);
5033
5034 // if (player_can_see_bold(Ind, ny, nx)) dump_item++;
5035 }
5036
5037 /* Reset the object level */
5038 object_level = dlev;
5039
5040 /* Reset "coin" type */
5041 coin_type = 0;
5042 }
5043 }
5044
5045 /* Forget it */
5046 unique_quark = 0;
5047
5048 /* Take note of any dropped treasure */
5049 #if 0
5050 /* XXX this doesn't work for now.. (not used anyway) */
5051 if (visible && (dump_item || dump_gold)) {
5052 /* Take notes on treasure */
5053 lore_treasure(m_idx, dump_item, dump_gold);
5054 }
5055 #endif
5056
5057 /* Get credit for unique monster kills */
5058 if (r_ptr->flags1 & RF1_UNIQUE) {
5059 /* Set unique monster to 'killed' for this player */
5060 p_ptr->r_killed[m_ptr->r_idx] = 1;
5061 Send_unique_monster(Ind, m_ptr->r_idx);
5062 /* Set unique monster to 'helped with' for all other nearby players
5063 who haven't explicitely killed it yet - C. Blue */
5064 for (i = 1; i <= NumPlayers; i++) {
5065 if (i == Ind) continue;
5066 if (is_admin(Players[i])) continue;
5067 if (Players[i]->conn == NOT_CONNECTED) continue;
5068 /* it's sufficient to just be on the same dungeon floor to get credit */
5069 if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
5070 /* must be in the same party though */
5071 if (!Players[i]->party || p_ptr->party != Players[i]->party) continue;
5072
5073 /* Hack: '2' means 'helped' instead of 'killed' */
5074 if (!Players[i]->r_killed[m_ptr->r_idx]) {
5075 Players[i]->r_killed[m_ptr->r_idx] = 2;
5076 Send_unique_monster(i, m_ptr->r_idx);
5077 }
5078 }
5079 /* Get kill credit for non-uniques (important for mimics) */
5080 //HACK: added test for m_ptr->r_idx to suppress bad msgs about 0 forms learned (exploders?)
5081 } else if (credit_idx && p_ptr->r_killed[credit_idx] < 1000 && !m_ptr->questor) {
5082 int before = p_ptr->r_killed[credit_idx];
5083 i = get_skill_scale(p_ptr, SKILL_MIMIC, 100);
5084
5085 /* get +1 bonus credit in Ironman Deep Dive Challenge */
5086 if (in_irondeepdive(wpos))
5087 #ifndef IDDC_MIMICRY_BOOST
5088 p_ptr->r_killed[credit_idx]++;
5089 #else /* give a possibly greater boost than just +1 */
5090 p_ptr->r_killed[credit_idx] += IDDC_MIMICRY_BOOST;
5091 #endif
5092
5093 #ifdef RPG_SERVER
5094 /* There is a 1 in (m_ptr->level - kill count)^2 chance of learning form straight away
5095 * to make it easier (at least statistically) getting forms in the iron server. Plus,
5096 * mimicked speed and hp are lowered already anyway. - the_sandman */
5097 if ( ( r_info[m_ptr->r_idx].level - p_ptr->r_killed[credit_idx] > 0 ) &&
5098 ( (randint((r_info[m_ptr->r_idx].level - p_ptr->r_killed[credit_idx]) *
5099 (r_info[m_ptr->r_idx].level - p_ptr->r_killed[credit_idx])) == 1))) {
5100 p_ptr->r_killed[credit_idx] = r_info[credit_idx].level;
5101 } else { /* Badluck */
5102 p_ptr->r_killed[credit_idx]++;
5103
5104 /* Shamans have a chance to learn E forms very quickly */
5105 if (p_ptr->pclass == CLASS_SHAMAN && (mimic_shaman_E(credit_idx) || r_info[credit_idx].d_char == 'X'))
5106 p_ptr->r_killed[credit_idx] += 2;
5107 }
5108 #else
5109 if (pvp) {
5110 /* PvP mode chars learn forms very quickly! */
5111 p_ptr->r_killed[credit_idx] += 3;
5112 } else {
5113 p_ptr->r_killed[credit_idx]++;
5114
5115 /* Shamans have a chance to learn E forms very quickly */
5116 if (p_ptr->pclass == CLASS_SHAMAN && (mimic_shaman_E(credit_idx) || r_info[credit_idx].d_char == 'X'))
5117 p_ptr->r_killed[credit_idx] += 2;
5118 }
5119 #endif
5120
5121 if (p_ptr->r_killed[credit_idx] > 1000)
5122 p_ptr->r_killed[credit_idx] = 1000;
5123
5124 if (i && i >= r_info[credit_idx].level &&
5125 (before == 0 || /* <- for level 0 townspeople */
5126 before < r_info[credit_idx].level) &&
5127 (p_ptr->r_killed[credit_idx] >= r_info[credit_idx].level ||
5128 /* for level 0 townspeople: */
5129 r_info[credit_idx].level == 0))
5130 {
5131 if (!((r_ptr->flags1 & RF1_UNIQUE) || (p_ptr->pclass == CLASS_DRUID) ||
5132 ((p_ptr->pclass == CLASS_SHAMAN) && !mimic_shaman(credit_idx)) ||
5133 (p_ptr->prace == RACE_VAMPIRE))) {
5134 msg_format(Ind, "\374\377UYou have learned the form of %s! (%d)",
5135 r_info[credit_idx].name + r_name, credit_idx);
5136 /* smooth transition from poly ring form to known form */
5137 if (p_ptr->body_monster == credit_idx) p_ptr->tim_mimic = p_ptr->tim_mimic_what = 0;
5138 if (!p_ptr->warning_mimic) {
5139 p_ptr->warning_mimic = 1;
5140 msg_print(Ind, "\374\377U(Press '\377ym\377U' key and choose '\377yuse innate power\377U' to polymorph.)");
5141 s_printf("warning_mimic: %s\n", p_ptr->name);
5142 }
5143 }
5144 }
5145 }
5146
5147 /* Take note of the killer */
5148 if ((r_ptr->flags1 & RF1_UNIQUE) && !pvp) {
5149 int Ind2 = 0;
5150 player_type *p_ptr2 = NULL;
5151
5152 #ifdef MUCHO_RUMOURS
5153 /*the_sandman prints a rumour */
5154 /* print the same message other players get before it - mikaelh */
5155 msg_print(Ind, "Suddenly a thought comes to your mind:");
5156 fortune(Ind, TRUE);
5157 #endif
5158
5159 /* give credit to the killer by default */
5160 if (cfg.unikill_format) {
5161 /* let's try with titles before the name :) -C. Blue */
5162 titlebuf = get_ptitle(q_ptr, FALSE);
5163
5164 if (is_Morgoth)
5165 snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by %s %s.\377v**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5166 #ifdef ZU_AON_FLASHY_MSG
5167 else if (m_ptr->r_idx == RI_ZU_AON)
5168 snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by %s %s.\377x**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5169 #endif
5170 else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5171 snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by %s %s.\377U**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5172 else
5173 snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by %s %s.\377b**", r_name_get(m_ptr), titlebuf, p_ptr->name);
5174 } else {
5175 /* for now disabled (works though) since we don't have telepath class
5176 at the moment, and party names would make the line grow too long if
5177 combined with title before the actual name :/ -C. Blue */
5178 if (!Ind2) {
5179 if (is_Morgoth)
5180 snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by %s.\377v**", r_name_get(m_ptr), p_ptr->name);
5181 #ifdef ZU_AON_FLASHY_MSG
5182 else if (m_ptr->r_idx == RI_ZU_AON)
5183 snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by %s.\377x**", r_name_get(m_ptr), p_ptr->name);
5184 #endif
5185 else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5186 snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by %s.\377U**", r_name_get(m_ptr), p_ptr->name);
5187 else
5188 snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by %s.\377b**", r_name_get(m_ptr), p_ptr->name);
5189 } else {
5190 if (is_Morgoth)
5191 snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by fusion %s-%s.\377v**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5192 #ifdef ZU_AON_FLASHY_MSG
5193 else if (m_ptr->r_idx == RI_ZU_AON)
5194 snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by fusion %s-%s.\377x**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5195 #endif
5196 else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5197 snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by fusion %s-%s.\377U**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5198 else
5199 snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by fusion %s-%s.\377b**", r_name_get(m_ptr), p_ptr->name, p_ptr2->name);
5200 }
5201
5202 /* give credit to the party if there is a teammate on the
5203 level, and the level is not 0 (the town) */
5204 if (p_ptr->party) {
5205 for (i = 1; i <= NumPlayers; i++) {
5206 if ( (Players[i]->party == p_ptr->party) && (inarea(&Players[i]->wpos, &p_ptr->wpos)) && (i != Ind) && (p_ptr->wpos.wz) )
5207 {
5208 if (is_Morgoth)
5209 snprintf(buf, sizeof(buf), "\374\377v**\377L%s was slain by %s of %s.\377v**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5210 #ifdef ZU_AON_FLASHY_MSG
5211 else if (m_ptr->r_idx == RI_ZU_AON)
5212 snprintf(buf, sizeof(buf), "\374\377x**\377c%s was slain by %s of %s.\377x**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5213 #endif
5214 else if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN))
5215 snprintf(buf, sizeof(buf), "\374\377U**\377c%s was slain by %s of %s.\377U**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5216 else
5217 snprintf(buf, sizeof(buf), "\374\377b**\377c%s was slain by %s of %s.\377b**", r_name_get(m_ptr), p_ptr->name, parties[p_ptr->party].name);
5218 break;
5219 }
5220
5221 }
5222 }
5223 }
5224
5225 if (!is_admin(p_ptr)) {
5226 #ifdef TOMENET_WORLDS
5227 if (cfg.worldd_unideath)
5228 world_msg(buf);
5229 else if (cfg.worldd_pwin && is_Morgoth)
5230 world_msg(buf);
5231 #endif
5232 /* Tell every player */
5233 msg_broadcast(-1, buf);
5234 /* Log event */
5235 s_printf("%s was slain by %s.\n", r_name_get(m_ptr), p_ptr->name);
5236
5237 }
5238 }
5239
5240 /* If the dungeon where Morgoth is killed is Ironman/Forcedown/No-Recall
5241 allow recalling on this particular floor, since player will lose all true arts.
5242 Note: If strict_etiquette is false, the player can actualy keep his arts!
5243 Originally for RPG_SERVER, but atm enabled for all. - C. Blue */
5244 if (is_Morgoth
5245 #if 1 /* hm */
5246 && cfg.strict_etiquette
5247 #endif
5248 ) {
5249 dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
5250 dun_level *l_ptr = getfloor(&p_ptr->wpos);
5251 if ((((d_ptr->flags2 & DF2_IRON || d_ptr->flags1 & DF1_FORCE_DOWN)
5252 && d_ptr->maxdepth > ABS(p_ptr->wpos.wz)) ||
5253 (d_ptr->flags1 & DF1_NO_RECALL))
5254 && !(l_ptr->flags1 & LF1_IRON_RECALL)
5255 && !(d_ptr->flags2 & DF2_NO_EXIT_WOR)) {
5256 /* Allow exceptional recalling.. */
5257 l_ptr->flags1 |= LF1_IRON_RECALL;
5258 /* ..and notify everyone on the level about it */
5259 floor_msg_format(&p_ptr->wpos, "\374\377gYou don't sense a magic barrier here!");
5260 }
5261 }
5262 else if (is_Sauron) {
5263 dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
5264
5265 /* If player killed Sauron, also mark the Shadow (formerly Necromancer) of Dol Guldur as killed!
5266 This is required since we now need a dungeon boss for Dol Guldur again =)
5267 So always kill the Shadow first, if you want his loot. - C. Blue */
5268 p_ptr->r_killed[RI_DOL_GULDUR] = 1;
5269
5270 /* If Sauron is killed in Mt Doom, allow the player to recall! */
5271 if (d_ptr->type == DI_MT_DOOM) {
5272 dun_level *l_ptr = getfloor(&p_ptr->wpos);
5273
5274 l_ptr->flags1 |= LF1_IRON_RECALL;
5275 floor_msg_format(&p_ptr->wpos, "\374\377gYou don't sense a magic barrier here!");
5276 }
5277
5278 /* for The One Ring.. */
5279 if (in_irondeepdive(wpos)) sauron_weakened_iddc = FALSE;
5280 else sauron_weakened = FALSE;
5281 }
5282
5283 /* Dungeon bosses often drop a dungeon-set true artifact (for now 1 in 3 chance) */
5284 if ((r_ptr->flags0 & RF0_FINAL_GUARDIAN)) {
5285 dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
5286
5287 msg_format(Ind, "\374\377UYou have conquered %s!", d_name + d_info[d_ptr->type].name);
5288
5289 if ((
5290 #ifdef IRONDEEPDIVE_MIXED_TYPES
5291 in_irondeepdive(wpos) ? (a_idx = d_info[iddc[ABS(wpos->wz)].type].final_artifact) :
5292 #endif
5293 (a_idx = d_info[d_ptr->type].final_artifact))
5294 /* hack: 0 rarity = always generate -- for Ring of Phasing! */
5295
5296 && (
5297 #ifdef IRONDEEPDIVE_MIXED_TYPES
5298 in_irondeepdive(wpos) || //Let's reward those brave IDDC participants?
5299 #endif
5300 (!a_info[a_idx].rarity || !rand_int(3)))
5301
5302 && !cfg.arts_disabled &&
5303 #ifdef RING_OF_PHASING_NO_TIMEOUT
5304 (
5305 #endif
5306 a_info[a_idx].cur_num == 0
5307 #ifdef RING_OF_PHASING_NO_TIMEOUT
5308 || a_idx == ART_PHASING)
5309 #endif
5310 ) {
5311 #ifdef RING_OF_PHASING_NO_TIMEOUT
5312 /* remove current ring of phasing, so it can be dropped anew */
5313 if (a_info[a_idx].cur_num) erase_artifact(a_idx);
5314 #endif
5315 s_printf("preparing FINAL_ARTIFACT %d", a_idx);
5316 a_ptr = &a_info[a_idx];
5317 qq_ptr = &forge;
5318 object_wipe(qq_ptr);
5319 I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
5320 /* Create the artifact */
5321 invcopy(qq_ptr, I_kind);
5322 qq_ptr->name1 = a_idx;
5323
5324 if (!(resf_chosen & RESF_NOTRUEART) ||
5325 ((resf_chosen & RESF_WINNER) && winner_artifact_p(qq_ptr))) {
5326 /* Extract the fields */
5327 qq_ptr->pval = a_ptr->pval;
5328 qq_ptr->ac = a_ptr->ac;
5329 qq_ptr->dd = a_ptr->dd;
5330 qq_ptr->ds = a_ptr->ds;
5331 qq_ptr->to_a = a_ptr->to_a;
5332 qq_ptr->to_h = a_ptr->to_h;
5333 qq_ptr->to_d = a_ptr->to_d;
5334 qq_ptr->weight = a_ptr->weight;
5335
5336 object_desc(Ind, o_name, qq_ptr, TRUE, 3);
5337 s_printf(" '%s'", o_name);
5338
5339 handle_art_inum(a_idx);
5340
5341 /* Hack -- acquire "cursed" flag */
5342 if (a_ptr->flags3 & (TR3_CURSED)) qq_ptr->ident |= (ID_CURSED);
5343
5344 /* Complete generation, especially level requirements check */
5345 apply_magic(wpos, qq_ptr, -2, FALSE, TRUE, FALSE, FALSE, resf_chosen);
5346
5347 qq_ptr->note = local_quark;
5348 qq_ptr->note_utag = strlen(quark_str(local_quark));
5349
5350 /* Little sanity hack for level requirements
5351 of the Ring of Phasing - would be 92 otherwise */
5352 if (a_idx == ART_PHASING) {
5353 qq_ptr->level = (60 + rand_int(6));
5354 qq_ptr->marked2 = ITEM_REMOVAL_NEVER;
5355 }
5356
5357 /* Drop the artifact from heaven */
5358 #ifdef PRE_OWN_DROP_CHOSEN
5359 else { /* ring of phasing is never 0'ed */
5360 qq_ptr->level = 0;
5361 qq_ptr->owner = p_ptr->id;
5362 qq_ptr->mode = p_ptr->mode;
5363 determine_artifact_timeout(a_idx, wpos);
5364 }
5365 #endif
5366 drop_near(qq_ptr, -1, wpos, y, x);
5367 s_printf("..dropped.\n");
5368 } else s_printf("..failed.\n");
5369 } else if (
5370 #ifdef IRONDEEPDIVE_MIXED_TYPES
5371 in_irondeepdive(wpos) ? (I_kind = d_info[iddc[ABS(wpos->wz)].type].final_object) :
5372 #endif
5373 (I_kind = d_info[d_ptr->type].final_object)) {
5374 s_printf("preparing FINAL_OBJECT %d", I_kind);
5375 qq_ptr = &forge;
5376 object_wipe(qq_ptr);
5377 /* Create the object */
5378 invcopy(qq_ptr, I_kind + 1); /* weirdness, why is it actually 1 too low? */
5379
5380 /* Complete generation, especially level requirements check */
5381 apply_magic(wpos, qq_ptr, -2, FALSE, TRUE, FALSE, FALSE, resf_chosen);
5382
5383 object_desc(Ind, o_name, qq_ptr, TRUE, 3);
5384 s_printf(" '%s'", o_name);
5385
5386 qq_ptr->note = local_quark;
5387 qq_ptr->note_utag = strlen(quark_str(local_quark));
5388
5389 /* Drop the object from heaven */
5390 #ifdef PRE_OWN_DROP_CHOSEN
5391 qq_ptr->level = 0;
5392 qq_ptr->owner = p_ptr->id;
5393 qq_ptr->mode = p_ptr->mode;
5394 if (true_artifact_p(qq_ptr)) determine_artifact_timeout(qq_ptr->name1, wpos);
5395 #endif
5396 drop_near(qq_ptr, -1, wpos, y, x);
5397 s_printf("..dropped.\n");
5398 }
5399 }
5400
5401 if (r_ptr->flags1 & (RF1_DROP_CHOSEN)) {
5402 /* Mega-Hack -- drop "winner" treasures */
5403 if (is_Morgoth && !pvp) {
5404 /* Hack -- an "object holder" */
5405 object_type prize;
5406
5407 int num = 0;
5408
5409 /* Nothing left, game over... */
5410 for (i = 1; i <= NumPlayers; i++) {
5411 q_ptr = Players[i];
5412 if (q_ptr->ghost) continue;
5413 /* Make everyone in the game in the same party on the
5414 * same level greater than or equal to level 40 total
5415 * winners.
5416 */
5417 if ((((p_ptr->party) && (q_ptr->party == p_ptr->party)) ||
5418 (q_ptr == p_ptr) ) && q_ptr->lev >= 40 && inarea(&p_ptr->wpos,&q_ptr->wpos))
5419 {
5420
5421 /* Total winner */
5422 q_ptr->total_winner = TRUE;
5423 q_ptr->once_winner = TRUE;
5424 s_printf("%s *** total_winner : %s (lev %d (%d,%d))\n", showtime(), q_ptr->name, q_ptr->lev, q_ptr->max_lev, q_ptr->max_plv);
5425
5426 s_printf("CHARACTER_WINNER: race=%s ; class=%s\n", race_info[q_ptr->prace].title, class_info[q_ptr->pclass].title);
5427
5428 /* Lose ironman champion status if this total_winner title was actually
5429 acquired after having already beaten the ironman deep dive challenge */
5430 q_ptr->iron_winner = FALSE;
5431
5432 /* Redraw the "title" */
5433 q_ptr->redraw |= (PR_TITLE);
5434
5435 /* Congratulations */
5436 msg_print(i, "\377G*** CONGRATULATIONS ***");
5437 if (q_ptr->mode & (MODE_HARD | MODE_NO_GHOST)) {
5438 msg_format(i, "\374\377GYou have won the game and are henceforth titled '%s'!", (q_ptr->male) ? "Emperor" : "Empress");
5439 msg_broadcast_format(i, "\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "Emperor" : "Empress", q_ptr->name);
5440 if (!is_admin(q_ptr)) l_printf("%s \\{v%s (%d) has been crowned %s\n", showdate(), q_ptr->name, q_ptr->lev, q_ptr->male ? "emperor" : "empress");
5441 #ifdef TOMENET_WORLDS
5442 if (cfg.worldd_pwin) world_msg(format("\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "Emperor" : "Empress", q_ptr->name));
5443 #endif
5444 } else {
5445 msg_format(i, "\374\377GYou have won the game and are henceforth titled '%s!'", (q_ptr->male) ? "King" : "Queen");
5446 msg_broadcast_format(i, "\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "King" : "Queen", q_ptr->name);
5447 if (!is_admin(q_ptr)) l_printf("%s \\{v%s (%d) has been crowned %s\n", showdate(), q_ptr->name, q_ptr->lev, q_ptr->male ? "king" : "queen");
5448 #ifdef TOMENET_WORLDS
5449 if (cfg.worldd_pwin) world_msg(format("\374\377v%s is henceforth known as %s %s", q_ptr->name, (q_ptr->male) ? "King" : "Queen", q_ptr->name));
5450 #endif
5451 }
5452 msg_print(i, "\377G(You may retire (by committing suicide) when you are ready.)");
5453
5454 num++;
5455
5456 /* Set all his artifacts to double-speed timeout */
5457 for (j = 0; j < INVEN_TOTAL; j++)
5458 if (p_ptr->inventory[j].name1 &&
5459 p_ptr->inventory[j].name1 != ART_RANDART)
5460 a_info[p_ptr->inventory[j].name1].winner = TRUE;
5461
5462 /* Set his retire_timer if neccecary */
5463 if (cfg.retire_timer >= 0) {
5464 q_ptr->retire_timer = cfg.retire_timer;
5465 msg_format(i, "Otherwise you will retire after %s minutes of tenure.", cfg.retire_timer);
5466 }
5467
5468 /* take char dump and screenshot from winning scene */
5469 if (is_newer_than(&q_ptr->version, 4, 4, 2, 0, 0, 0)) Send_chardump(i, "-victory");
5470
5471 #ifdef ENABLE_STANCES
5472 /* increase SKILL_STANCE by +1 automatically (just for show :-p) if we actually have that skill */
5473 if (get_skill(q_ptr, SKILL_STANCE) >= 45) {
5474 /* give message if we learn a new stance (compare cmd6.c! keep it synchronized */
5475 msg_print(i, "\374\377GYou learn how to enter Royal Rank combat stances.");
5476 /* automatically upgrade currently taken stance power */
5477 if (q_ptr->combat_stance) q_ptr->combat_stance_power = 3;
5478 }
5479 #endif
5480
5481 if (get_skill(q_ptr, SKILL_MARTIAL_ARTS) >= 48) {
5482 msg_print(i, "\374\377GYou learn the Royal Titan's Fist technique.");
5483 msg_print(i, "\374\377GYou learn the Royal Phoenix Claw technique.");
5484 }
5485
5486 if (q_ptr->lev >= 50 && q_ptr->pclass == CLASS_ROGUE) {
5487 msg_print(i, "\374\377GYou learn the royal fighting technique 'Shadow Run'");
5488 calc_techniques(i);
5489 Send_skill_info(i, SKILL_TECHNIQUE, TRUE);
5490 }
5491 }
5492 }
5493
5494 /* Paranoia (if a ghost killed Morgoth) ;) - C. Blue */
5495 if (num) {
5496
5497 /* Mega-Hack -- Prepare to make "Grond" */
5498 invcopy(&prize, lookup_kind(TV_BLUNT, SV_GROND));
5499 /* Mega-Hack -- Mark this item as "Grond" */
5500 prize.name1 = ART_GROND;
5501 /* Mega-Hack -- Actually create "Grond" */
5502 apply_magic(wpos, &prize, -1, TRUE, TRUE, TRUE, FALSE, resf_chosen);
5503
5504 prize.number = num;
5505 prize.level = 45;
5506 prize.note = local_quark;
5507 prize.note_utag = strlen(quark_str(local_quark));
5508
5509 /* Drop it in the dungeon */
5510 if (wpos->wz) prize.marked2 = ITEM_REMOVAL_NEVER;
5511 else prize.marked2 = ITEM_REMOVAL_DEATH_WILD;
5512 drop_near(&prize, -1, wpos, y, x);
5513
5514 /* Mega-Hack -- Prepare to make "Morgoth" */
5515 invcopy(&prize, lookup_kind(TV_CROWN, SV_MORGOTH));
5516 /* Mega-Hack -- Mark this item as "Morgoth" */
5517 prize.name1 = ART_MORGOTH;
5518 /* Mega-Hack -- Actually create "Morgoth" */
5519 apply_magic(wpos, &prize, -1, TRUE, TRUE, TRUE, FALSE, resf_chosen);
5520
5521 prize.number = num;
5522 prize.level = 45;
5523 prize.note = local_quark;
5524 prize.note_utag = strlen(quark_str(local_quark));
5525
5526 /* Drop it in the dungeon */
5527 if (wpos->wz) prize.marked2 = ITEM_REMOVAL_NEVER;
5528 else prize.marked2 = ITEM_REMOVAL_DEATH_WILD;
5529 drop_near(&prize, -1, wpos, y, x);
5530
5531
5532 /* Special reward: 1 *great* acquirement item per player. */
5533 i = object_level;
5534 object_level = 127;
5535 acquirement(wpos, y, x, num, TRUE, TRUE, RESF_WINNER | RESF_LIFE | RESF_NOTRUEART | RESF_EGOHI);
5536 object_level = i;
5537
5538 } /* Paranoia tag */
5539
5540 /* Hack -- instantly retire any new winners if neccecary */
5541 if (cfg.retire_timer == 0) {
5542 for (i = 1; i <= NumPlayers; i++) {
5543 p_ptr = Players[i];
5544 if (p_ptr->total_winner)
5545 do_cmd_suicide(i);
5546 }
5547 }
5548
5549 FREE(m_ptr->r_ptr, monster_race);
5550 return;
5551
5552 } else if (strstr((r_name + r_ptr->name),"Smeagol")) {
5553 /* Get local object */
5554 qq_ptr = &forge;
5555
5556 object_wipe(qq_ptr);
5557
5558 /* Mega-Hack -- Prepare to make a ring of invisibility */
5559 /* Sorry, =inv is too nice.. */
5560 // invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_INVIS));
5561 invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_STEALTH));
5562 qq_ptr->number = 1;
5563 qq_ptr->note = local_quark;
5564 qq_ptr->note_utag = strlen(quark_str(local_quark));
5565
5566 apply_magic(wpos, qq_ptr, -1, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5567
5568 qq_ptr->bpval = 5;
5569 /* Drop it in the dungeon */
5570 drop_near(qq_ptr, -1, wpos, y, x);
5571
5572 /* finally made Robin Hood drop a Bow ;) */
5573 } else if (strstr((r_name + r_ptr->name),"Robin Hood, the Outlaw") && magik(50)) {
5574 qq_ptr = &forge;
5575 object_wipe(qq_ptr);
5576 invcopy(qq_ptr, lookup_kind(TV_BOW, SV_LONG_BOW));
5577 qq_ptr->number = 1;
5578 qq_ptr->note = local_quark;
5579 qq_ptr->note_utag = strlen(quark_str(local_quark));
5580 apply_magic(wpos, qq_ptr, -1, TRUE, TRUE, TRUE, TRUE, resf_drops);
5581 drop_near(qq_ptr, -1, wpos, y, x);
5582
5583 } else if (r_ptr->flags7 & RF7_NAZGUL) {
5584 /* Get local object */
5585 qq_ptr = &forge;
5586
5587 object_wipe(qq_ptr);
5588
5589 /* Mega-Hack -- Prepare to make a Ring of Power */
5590 invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_SPECIAL));
5591 qq_ptr->number = 1;
5592
5593 qq_ptr->name1 = ART_RANDART;
5594
5595 /* Piece together a 32-bit random seed */
5596 qq_ptr->name3 = rand_int(0xFFFF) << 16;
5597 qq_ptr->name3 += rand_int(0xFFFF);
5598
5599 /* Check the tval is allowed */
5600 // if (randart_make(qq_ptr) != NULL)
5601
5602 apply_magic(wpos, qq_ptr, -1, FALSE, TRUE, FALSE, FALSE, RESF_NONE);
5603
5604 /* Save the inscription */
5605 /* (pfft, not so smart..) */
5606 /*qq_ptr->note = quark_add(format("#of %s", r_name + r_ptr->name));*/
5607 qq_ptr->bpval = m_ptr->r_idx;
5608
5609 /* Drop it in the dungeon */
5610 #ifdef PRE_OWN_DROP_CHOSEN
5611 qq_ptr->level = 0;
5612 qq_ptr->owner = p_ptr->id;
5613 qq_ptr->mode = p_ptr->mode;
5614 #endif
5615 drop_near(qq_ptr, -1, wpos, y, x);
5616
5617 /* Hack - the Dragonriders give some firestone */
5618 } else if (r_ptr->flags3 & RF3_DRAGONRIDER) {
5619 /* Get local object */
5620 qq_ptr = &forge;
5621
5622 /* Prepare to make some Firestone */
5623 if (magik(70)) invcopy(qq_ptr, lookup_kind(TV_FIRESTONE, SV_FIRESTONE));
5624 else invcopy(qq_ptr, lookup_kind(TV_FIRESTONE, SV_FIRE_SMALL));
5625 qq_ptr->number = (byte)rand_range(1,12);
5626
5627 /* Drop it in the dungeon */
5628 drop_near(qq_ptr, -1, wpos, y, x);
5629
5630 /* PernAngband additions */
5631 /* Mega^2-hack -- destroying the Stormbringer gives it us! */
5632 } else if (strstr((r_name + r_ptr->name),"Stormbringer")) {
5633 /* Get local object */
5634 qq_ptr = &forge;
5635
5636 /* Prepare to make the Stormbringer */
5637 invcopy(qq_ptr, lookup_kind(TV_SWORD, SV_BLADE_OF_CHAOS));
5638
5639 /* Megahack -- specify the ego */
5640 qq_ptr->name2 = EGO_STORMBRINGER;
5641
5642 /* Piece together a 32-bit random seed */
5643 qq_ptr->name3 = rand_int(0xFFFF) << 16;
5644 qq_ptr->name3 += rand_int(0xFFFF);
5645
5646 apply_magic(wpos, qq_ptr, -1, FALSE, FALSE, FALSE, FALSE, RESF_NONE);
5647 qq_ptr->level = 0;
5648
5649 qq_ptr->ident |= ID_CURSED;
5650
5651 /* hack for a good result */
5652 qq_ptr->to_h = 17 + rand_int(14);
5653 qq_ptr->to_d = 17 + rand_int(14);
5654
5655 /* Drop it in the dungeon */
5656 drop_near(qq_ptr, -1, wpos, y, x);
5657
5658 #if 0 /* currently no such book */
5659 /* Raal's Tomes of Destruction drop a Raal's Tome of Destruction */
5660 // else if ((strstr((r_name + r_ptr->name),"Raal's Tome of Destruction")) && (rand_int(100) < 20))
5661 } else if ((strstr((r_name + r_ptr->name),"Raal's Tome of Destruction")) && (magik(1))) {
5662 /* Get local object */
5663 qq_ptr = &forge;
5664
5665 /* Prepare to make a Raal's Tome of Destruction */
5666 // invcopy(qq_ptr, lookup_kind(TV_MAGIC_BOOK, 8));
5667 /* Make a Tome of the Hellflame (Udun) */
5668 invcopy(qq_ptr, lookup_kind(TV_BOOK, 11));
5669
5670 /* Drop it in the dungeon */
5671 drop_near(qq_ptr, -1, wpos, y, x);
5672 #endif
5673
5674 } else if (m_ptr->r_idx == RI_LIVING_LIGHTNING) {
5675 int tries = 100;
5676 object_type forge_bak, forge_fallback;
5677 qq_ptr = &forge;
5678 /* possible loot:
5679 skydsm,elec rod,elec ring,elec/mana rune,mage staff,tome of wind
5680 */
5681
5682 while (tries--) {
5683 object_wipe(qq_ptr);
5684 invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_ELEC));
5685 qq_ptr->number = 1;
5686 qq_ptr->note = local_quark;
5687 qq_ptr->note_utag = strlen(quark_str(local_quark));
5688 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_FORCERANDART | RESF_NOTRUEART);
5689 /* hack - ensure non-cursed item: */
5690 if (qq_ptr->to_a > 0) break;
5691 }
5692 #if 1
5693 tries = 3000;
5694 object_copy(&forge_bak, &forge);
5695 object_copy(&forge_fallback, &forge);
5696 while (qq_ptr->pval < 6 && tries--) {
5697 object_copy(&forge, &forge_bak);
5698 /* Piece together a 32-bit random seed */
5699 qq_ptr->name3 = rand_int(0xFFFF) << 16;
5700 qq_ptr->name3 += rand_int(0xFFFF);
5701 randart_make(qq_ptr);
5702 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_FORCERANDART | RESF_NOTRUEART);
5703
5704 /* no AGGR/AM items */
5705 a_ptr = randart_make(qq_ptr);
5706 if ((a_ptr->flags3 & (TR3_AGGRAVATE | TR3_NO_MAGIC))
5707 || artifact_power(a_ptr) < 90) {
5708 /* hack: don't even use these for fallback */
5709 qq_ptr->pval = 0;
5710 continue;
5711 }
5712
5713 if (qq_ptr->pval > forge_fallback.pval) object_copy(&forge_fallback, qq_ptr);
5714 }
5715 if (qq_ptr->pval < 6) object_copy(qq_ptr, &forge_fallback);
5716 #endif
5717 qq_ptr->timeout = 0;
5718 drop_near(qq_ptr, -1, wpos, y, x);
5719
5720 object_wipe(qq_ptr);
5721 invcopy(qq_ptr, lookup_kind(TV_BOOK, 2));
5722 qq_ptr->number = 1;
5723 qq_ptr->note = local_quark;
5724 qq_ptr->note_utag = strlen(quark_str(local_quark));
5725 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5726 drop_near(qq_ptr, -1, wpos, y, x);
5727
5728 object_wipe(qq_ptr);
5729 invcopy(qq_ptr, lookup_kind(TV_RUNE, 5));
5730 qq_ptr->number = 1;
5731 qq_ptr->note = local_quark;
5732 qq_ptr->note_utag = strlen(quark_str(local_quark));
5733 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5734 drop_near(qq_ptr, -1, wpos, y, x);
5735
5736 object_wipe(qq_ptr);
5737 invcopy(qq_ptr, lookup_kind(TV_RUNE, 8));
5738 qq_ptr->number = 1;
5739 qq_ptr->note = local_quark;
5740 qq_ptr->note_utag = strlen(quark_str(local_quark));
5741 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5742 drop_near(qq_ptr, -1, wpos, y, x);
5743
5744 object_wipe(qq_ptr);
5745 invcopy(qq_ptr, lookup_kind(TV_ROD, SV_ROD_ELEC_BALL));
5746 qq_ptr->number = 1;
5747 qq_ptr->note = local_quark;
5748 qq_ptr->note_utag = strlen(quark_str(local_quark));
5749 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5750 qq_ptr->name2 = EGO_RISTARI;
5751 qq_ptr->name2b = 0;
5752 drop_near(qq_ptr, -1, wpos, y, x);
5753
5754 object_wipe(qq_ptr);
5755 invcopy(qq_ptr, lookup_kind(TV_DRAG_ARMOR, SV_DRAGON_SKY));
5756 qq_ptr->number = 1;
5757 qq_ptr->note = local_quark;
5758 qq_ptr->note_utag = strlen(quark_str(local_quark));
5759 qq_ptr->name1 = ART_RANDART;
5760 tries = 500;
5761 while (tries) {
5762 /* Piece together a 32-bit random seed */
5763 qq_ptr->name3 = rand_int(0xFFFF) << 16;
5764 qq_ptr->name3 += rand_int(0xFFFF);
5765 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_FORCERANDART | RESF_NOTRUEART | RESF_LIFE);
5766
5767 a_ptr = randart_make(qq_ptr);
5768 if (artifact_power(a_ptr) >= 105 + 5 && /* at least +1 new mod gained; and +extra bonus boost */
5769 qq_ptr->to_a > 0 && /* not cursed */
5770 !(a_ptr->flags3 & (TR3_AGGRAVATE | TR3_NO_MAGIC)))
5771 break;
5772 tries--;
5773 }
5774 if (!tries) msg_format(Ind, "RI_LIVING_LIGHTNING: Re-rolling out of tries!");
5775
5776 qq_ptr->timeout = 0;
5777 drop_near(qq_ptr, -1, wpos, y, x);
5778
5779 } else if (m_ptr->r_idx == RI_HELLRAISER) {
5780 /* Get local object */
5781 qq_ptr = &forge;
5782
5783 object_wipe(qq_ptr);
5784
5785 /* Drop Scroll Of Artifact Creation along with loot */
5786 invcopy(qq_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_ARTIFACT_CREATION));
5787 qq_ptr->number = 1;
5788 qq_ptr->note = local_quark;
5789 qq_ptr->note_utag = strlen(quark_str(local_quark));
5790
5791 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5792
5793 /* Drop it in the dungeon */
5794 drop_near(qq_ptr, -1, wpos, y, x);
5795
5796 /* Prepare a second reward */
5797 object_wipe(qq_ptr);
5798
5799 /* Drop Potions Of Learning along with loot */
5800 #ifdef EXPAND_TV_POTION
5801 invcopy(qq_ptr, lookup_kind(TV_POTION, SV_POTION_LEARNING));
5802 #else
5803 invcopy(qq_ptr, lookup_kind(TV_POTION2, SV_POTION2_LEARNING));
5804 #endif
5805 qq_ptr->number = 1;
5806 qq_ptr->note = local_quark;
5807 qq_ptr->note_utag = strlen(quark_str(local_quark));
5808
5809 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5810
5811 /* Drop it in the dungeon */
5812 #ifdef PRE_OWN_DROP_CHOSEN
5813 qq_ptr->level = 0;
5814 qq_ptr->owner = p_ptr->id;
5815 qq_ptr->mode = p_ptr->mode;
5816 #endif
5817 drop_near(qq_ptr, -1, wpos, y, x);
5818
5819 } else if (m_ptr->r_idx == RI_DOR) {
5820 /* Get local object */
5821 qq_ptr = &forge;
5822
5823 #if 0
5824 /* super-charged wands of rockets */
5825 object_wipe(qq_ptr);
5826 invcopy(qq_ptr, lookup_kind(TV_WAND, SV_WAND_ROCKETS));
5827 qq_ptr->number = 2 + rand_int(2);
5828 qq_ptr->note = local_quark;
5829 qq_ptr->note_utag = strlen(quark_str(local_quark));
5830 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5831 qq_ptr->pval = qq_ptr->number * 5 + 3 + rand_int(4);
5832 drop_near(qq_ptr, -1, wpos, y, x);
5833 #endif
5834
5835 /* a rod of havoc */
5836 object_wipe(qq_ptr);
5837 invcopy(qq_ptr, lookup_kind(TV_ROD, SV_ROD_HAVOC));
5838 qq_ptr->number = 1;
5839 qq_ptr->note = local_quark;
5840 qq_ptr->note_utag = strlen(quark_str(local_quark));
5841 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, TRUE, TRUE, RESF_NONE);
5842 /* hack ego power */
5843 qq_ptr->name2 = EGO_RISTARI;
5844 qq_ptr->name2b = 0;
5845 drop_near(qq_ptr, -1, wpos, y, x);
5846
5847 /* dungeon boss, but drops multiple items */
5848 } else if (m_ptr->r_idx == RI_ZU_AON) {
5849 dun_level *l_ptr = getfloor(&p_ptr->wpos);
5850
5851 l_ptr->flags2 |= LF2_COLLAPSING;
5852 nether_realm_collapsing = TRUE;
5853 nrc_x = m_ptr->fx;
5854 nrc_y = m_ptr->fy;
5855
5856 #if 1
5857 for (i = 1; i <= NumPlayers; i++) {
5858 if (inarea(&Players[i]->wpos, &p_ptr->wpos)
5859 && !is_admin(Players[i]))
5860 l_printf("%s \\{U%s made it through the Nether Realm\n", showdate(), Players[i]->name);
5861 }
5862 #endif
5863
5864 /* Get local object */
5865 qq_ptr = &forge;
5866 object_wipe(qq_ptr);
5867 /* Drop Scroll Of Artifact Creation */
5868 invcopy(qq_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_ARTIFACT_CREATION));
5869 qq_ptr->number = 1;
5870 qq_ptr->note = local_quark;
5871 qq_ptr->note_utag = strlen(quark_str(local_quark));
5872 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5873 /* Drop it in the dungeon */
5874 drop_near(qq_ptr, -1, wpos, y, x);
5875
5876 /* Prepare a second reward */
5877 object_wipe(qq_ptr);
5878 /* Drop Potions Of Learning along with loot */
5879 #ifdef EXPAND_TV_POTION
5880 invcopy(qq_ptr, lookup_kind(TV_POTION, SV_POTION_LEARNING));
5881 #else
5882 invcopy(qq_ptr, lookup_kind(TV_POTION2, SV_POTION2_LEARNING));
5883 #endif
5884 qq_ptr->number = 1;
5885 qq_ptr->note = local_quark;
5886 qq_ptr->note_utag = strlen(quark_str(local_quark));
5887 apply_magic(wpos, qq_ptr, 150, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
5888 /* Drop it in the dungeon */
5889 #ifdef PRE_OWN_DROP_CHOSEN
5890 qq_ptr->level = 0;
5891 qq_ptr->owner = p_ptr->id;
5892 qq_ptr->mode = p_ptr->mode;
5893 #endif
5894 drop_near(qq_ptr, -1, wpos, y, x);
5895
5896 } else if (!pvp) {
5897 a_idx = 0;
5898 chance = 0;
5899 I_kind = 0;
5900
5901 if (strstr((r_name + r_ptr->name)," Mardra, rider of the Gold Loranth")) {
5902 a_idx = ART_MARDRA;
5903 chance = 55;
5904 } else if (strstr((r_name + r_ptr->name), "Saruman of Many Colours")) {
5905 a_idx = ART_ELENDIL;
5906 chance = 30;
5907 } else if (strstr((r_name + r_ptr->name), "Hagen, son of Alberich")) { /* not in the game */
5908 a_idx = ART_NIMLOTH;
5909 chance = 66;
5910 } else if (strstr((r_name + r_ptr->name), "Gothmog, the High Captain of Balrogs")) {
5911 a_idx = ART_GOTHMOG;
5912 chance = 80;
5913 } else if (strstr((r_name + r_ptr->name), "Eol, the Dark Elf")) {
5914 if (magik(25)) a_idx = ART_ANGUIREL;
5915 else a_idx = ART_EOL;
5916 chance = 65;
5917 } else if (strstr((r_name + r_ptr->name), "Kronos, Lord of the Titans")) {
5918 a_idx = ART_KRONOS;
5919 chance = 80;
5920 /* Wyrms have a chance of dropping The Amulet of Grom, the Wyrm Hunter: -C. Blue */
5921 } else if ((r_ptr->flags3 & RF3_DRAGON)) {
5922 a_idx = ART_AMUGROM;
5923 chance = 101;
5924
5925 /* only powerful wyrms may have a chance of dropping it */
5926 if ((m_ptr->maxhp < 6000) && rand_int(300)) a_idx = 0;/* strong wyrms at 6000+ */
5927 else if ((m_ptr->maxhp >= 6000) && (m_ptr->maxhp < 10000) && rand_int(150)) a_idx = 0;
5928 else if ((m_ptr->maxhp >= 10000) && rand_int(75)) a_idx = 0;/* gwop ^^ */
5929 }
5930
5931 #ifdef SEMI_PROMISED_ARTS_MODIFIER
5932 if (chance < 100 / SEMI_PROMISED_ARTS_MODIFIER) /* never turn into zero */
5933 chance = 1;
5934 else if (chance < 101) /* 101 = always drops */
5935 chance = chance * SEMI_PROMISED_ARTS_MODIFIER / 100;
5936 #endif
5937
5938 // if ((a_idx > 0) && ((randint(99)<chance) || (wizard)))
5939 if ((a_idx > 0) && magik(chance) && !cfg.arts_disabled &&
5940 (a_info[a_idx].cur_num == 0)) {
5941 a_ptr = &a_info[a_idx];
5942 /* Get local object */
5943 qq_ptr = &forge;
5944 /* Wipe the object */
5945 object_wipe(qq_ptr);
5946 /* Acquire the "kind" index */
5947 I_kind = lookup_kind(a_ptr->tval, a_ptr->sval);
5948 /* Create the artifact */
5949 invcopy(qq_ptr, I_kind);
5950 /* Save the name */
5951 qq_ptr->name1 = a_idx;
5952
5953 if (!(resf_chosen & RESF_NOTRUEART) ||
5954 ((resf_chosen & RESF_WINNER) && winner_artifact_p(qq_ptr))) {
5955 /* Extract the fields */
5956 qq_ptr->pval = a_ptr->pval;
5957 qq_ptr->ac = a_ptr->ac;
5958 qq_ptr->dd = a_ptr->dd;
5959 qq_ptr->ds = a_ptr->ds;
5960 qq_ptr->to_a = a_ptr->to_a;
5961 qq_ptr->to_h = a_ptr->to_h;
5962 qq_ptr->to_d = a_ptr->to_d;
5963 qq_ptr->weight = a_ptr->weight;
5964
5965 object_desc(Ind, o_name, qq_ptr, TRUE, 3);
5966 s_printf("DROP_CHOSEN: '%s'\n", o_name);
5967
5968 if (local_quark) {
5969 qq_ptr->note = local_quark;
5970 qq_ptr->note_utag = strlen(quark_str(local_quark));
5971 }
5972
5973 // random_artifact_resistance(qq_ptr);
5974 handle_art_inum(a_idx);
5975
5976 /* Hack -- acquire "cursed" flag */
5977 if (a_ptr->flags3 & (TR3_CURSED)) qq_ptr->ident |= (ID_CURSED);
5978
5979 /* Complete generation, especially level requirements check */
5980 apply_magic(wpos, qq_ptr, -2, FALSE, TRUE, FALSE, FALSE, resf_chosen);
5981
5982 /* Little sanity hack for level requirements
5983 of the Ring of Phasing - would be 92 otherwise */
5984 if (a_idx == ART_PHASING) {
5985 qq_ptr->level = (60 + rand_int(6));
5986 qq_ptr->marked2 = ITEM_REMOVAL_NEVER;
5987 }
5988
5989 /* Drop the artifact from heaven */
5990 #ifdef PRE_OWN_DROP_CHOSEN
5991 qq_ptr->level = 0;
5992 qq_ptr->owner = p_ptr->id;
5993 qq_ptr->mode = p_ptr->mode;
5994 determine_artifact_timeout(a_idx, wpos);
5995 #endif
5996 drop_near(qq_ptr, -1, wpos, y, x);
5997 }
5998 }
5999 }
6000 }
6001
6002 #ifdef IDDC_EASY_SPEED_RINGS
6003 #if IDDC_EASY_SPEED_RINGS > 0
6004 /* IDDC hacks: Easy speed ring obtaining */
6005 if ((p_ptr->IDDC_flags & 0x3) &&
6006 //basically wyrms+ and some especially feared uniques
6007 (m_ptr->level >= 63 || (m_ptr->level >= 59 && (r_ptr->flags1 & RF1_UNIQUE))) &&
6008 (r_ptr->flags1 & (RF1_DROP_GOOD | RF1_DROP_GREAT)) &&
6009 //not TOO easy
6010 #if IDDC_EASY_SPEED_RINGS > 1
6011 !rand_int(10)) {
6012 #else
6013 !rand_int(15)) {
6014 #endif
6015 s_printf("Player '%s' : IDDC_flags %d -> ", p_ptr->name, p_ptr->IDDC_flags);
6016 p_ptr->IDDC_flags--;
6017 s_printf("%d\n", p_ptr->IDDC_flags);
6018
6019 /* Get local object */
6020 qq_ptr = &forge;
6021 object_wipe(qq_ptr);
6022
6023 invcopy(qq_ptr, lookup_kind(TV_RING, SV_RING_SPEED));
6024 qq_ptr->number = 1;
6025 qq_ptr->note = local_quark;
6026 qq_ptr->note_utag = strlen(quark_str(local_quark));
6027 apply_magic(wpos, qq_ptr, -1, TRUE, TRUE, FALSE, FALSE, RESF_NONE);
6028
6029 qq_ptr->bpval = 7 + rand_int(4); //make it decent
6030 qq_ptr->ident &= ~ID_CURSED; //paranoia
6031
6032 drop_near(qq_ptr, -1, wpos, y, x);
6033 }
6034 #endif
6035 #endif
6036
6037 /* for when a quest giver turned non-invincible */
6038 if (m_ptr->questor) {
6039 if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
6040 /* Drop a specific item? */
6041 if (q_info[m_ptr->quest].questor[m_ptr->questor_idx].drops & 0x2)
6042 questor_drop_specific(Ind, m_ptr->quest, m_ptr->questor_idx, wpos, x, y);
6043 /* Quest progression/fail effect? */
6044 questor_death(m_ptr->quest, m_ptr->questor_idx, wpos, 0);
6045 } else {
6046 s_printf("QUESTOR DEPRECATED (monster_dead2)\n");
6047 }
6048 }
6049
6050 // if((!force_coin)&&(randint(100)<50)) place_corpse(m_ptr);
6051
6052 /* Only process "Quest Monsters" */
6053 if (!(r_ptr->flags1 & RF1_QUESTOR)) return;
6054
6055 /* Hack -- Mark quests as complete */
6056 for (i = 0; i < MAX_XO_IDX; i++)
6057 {
6058 /* Hack -- note completed quests */
6059 if (xo_list[i].level == r_ptr->level) xo_list[i].level = 0;
6060
6061 /* Count incomplete quests */
6062 if (xo_list[i].level) total++;
6063 }
6064
6065
6066 /* Need some stairs */
6067 if (total)
6068 {
6069 /* Stagger around */
6070 while (!cave_valid_bold(zcave, y, x))
6071 {
6072 int d = 1;
6073
6074 /* Pick a location */
6075 scatter(wpos, &ny, &nx, y, x, d, 0);
6076
6077 /* Stagger */
6078 y = ny; x = nx;
6079 }
6080
6081 /* Delete any old object XXX XXX XXX */
6082 delete_object(wpos, y, x, TRUE);
6083
6084 /* Explain the stairway */
6085 msg_print(Ind, "A magical stairway appears...");
6086
6087 /* Access the grid */
6088 c_ptr = &zcave[y][x];
6089
6090 /* Create stairs down */
6091 c_ptr->feat = FEAT_MORE;
6092
6093 /* Note the spot */
6094 note_spot_depth(wpos, y, x);
6095
6096 /* Draw the spot */
6097 everyone_lite_spot(wpos, y, x);
6098
6099 /* Remember to update everything */
6100 p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_MONSTERS);
6101 }
6102
6103 FREE(m_ptr->r_ptr, monster_race);
6104 }
6105
6106 /* FIXME: this function is known to be bypassable by nominally
6107 * 'party-owning'.
6108 */
6109 void kill_house_contents(house_type *h_ptr) {
6110 struct worldpos *wpos = &h_ptr->wpos;
6111 object_type *o_ptr;
6112 int i;
6113
6114 /* hack: for PLAYER_STORES actually allocate the cave temporarily,
6115 just for delete_object()->delete_object_idx() to find any offered items and log their removal. */
6116 bool must_alloc = (getcave(wpos) == NULL);
6117 if (must_alloc) {
6118 alloc_dungeon_level(wpos);
6119 generate_cave(wpos, NULL);
6120 }
6121
6122 #ifdef USE_MANG_HOUSE
6123 if (h_ptr->flags & HF_RECT) {
6124 int sy, sx, ey, ex, x, y;
6125 sy = h_ptr->y + 1;
6126 sx = h_ptr->x + 1;
6127 ey = h_ptr->y + h_ptr->coords.rect.height - 1;
6128 ex = h_ptr->x + h_ptr->coords.rect.width - 1;
6129 for (y = sy; y < ey; y++) {
6130 for (x = sx; x < ex; x++)
6131 delete_object(wpos, y, x, TRUE);
6132 }
6133
6134 /* make sure no player gets stuck by being inside while it's sold - C. Blue */
6135 for (i = 1; i <= NumPlayers; i++) {
6136 if (inarea(&Players[i]->wpos, wpos) &&
6137 Players[i]->py >= sy && Players[i]->py <= ey &&
6138 Players[i]->px >= sx && Players[i]->px <= ex)
6139 teleport_player_force(i, 1);
6140 }
6141 } else {
6142 fill_house(h_ptr, FILL_CLEAR, NULL);
6143 /* Polygonal house */
6144
6145 //todo: teleport any players inside out */
6146 }
6147 #endif // USE_MANG_HOUSE
6148
6149 #ifndef USE_MANG_HOUSE_ONLY
6150 for (i = 0; i < h_ptr->stock_num; i++) {
6151 o_ptr = &h_ptr->stock[i];
6152 if (o_ptr->k_idx && true_artifact_p(o_ptr))
6153 handle_art_d(o_ptr->name1);
6154 questitem_d(o_ptr, o_ptr->number);
6155
6156 #ifdef PLAYER_STORES
6157 /* Log removal of player store items */
6158 if (o_ptr->note && strstr(quark_str(o_ptr->note), "@S")) {
6159 char o_name[ONAME_LEN];//, p_name[NAME_LEN];
6160 object_desc(0, o_name, o_ptr, TRUE, 3);
6161 //s_printf("PLAYER_STORE_REMOVED: %s - %s (%d,%d,%d; %d,%d).\n",
6162 s_printf("PLAYER_STORE_REMOVED: %s (%d,%d,%d; %d,%d).\n",
6163 //p_name, o_name, wpos->wx, wpos->wy, wpos->wz,
6164 o_name, wpos->wx, wpos->wy, wpos->wz,
6165 o_ptr->ix, o_ptr->iy);
6166 }
6167 #endif
6168
6169 invwipe(o_ptr);
6170 }
6171 h_ptr->stock_num = 0;
6172 #endif // USE_MANG_HOUSE_ONLY
6173
6174 #ifdef HOUSE_PAINTING
6175 /* Remove house paint */
6176 h_ptr->colour = 0;
6177 fill_house(h_ptr, FILL_UNPAINT, NULL);
6178 #endif
6179
6180 /* hack: reset size/price of extendable (trad) houses */
6181 if ((h_ptr->flags & HF_TRAD)) {
6182 int area = (h_ptr->coords.rect.width - 2) * (h_ptr->coords.rect.height - 2);
6183 h_ptr->stock_size = (area >= STORE_INVEN_MAX) ? STORE_INVEN_MAX : area;
6184
6185 /* note: trad houses currently can't have sizes > 30 (compare wild.c),
6186 so it's sufficient to add term for medium houses + term for small houses,
6187 ignoring the term for large houses. */
6188 h_ptr->dna->price = initial_house_price(h_ptr);
6189 }
6190
6191 if (must_alloc) dealloc_dungeon_level(wpos);
6192 }
6193
6194 void kill_houses(int id, byte type) {
6195 int i;
6196 for (i = 0; i < num_houses; i++) {
6197 struct dna_type *dna = houses[i].dna;
6198 if (dna->owner == id && dna->owner_type == type) {
6199 dna->owner = 0L;
6200 dna->creator = 0L;
6201 dna->a_flags = ACF_NONE;
6202 kill_house_contents(&houses[i]);
6203 }
6204 }
6205 }
6206
6207 /* XXX maybe this function can delete the objects
6208 * to prevent 'house-owner char cheeze' - Jir -
6209 */
6210 void kill_objs(int id){
6211 int i;
6212 object_type *o_ptr;
6213 for (i = 0; i < o_max; i++) {
6214 o_ptr = &o_list[i];
6215 if (!o_ptr->k_idx) continue;
6216 if (o_ptr->owner == id) {
6217 o_ptr->owner = MAX_ID + 1;
6218 /* o_ptr->mode = 0; <- makes everlasting items usable! bad! */
6219 }
6220 }
6221 }
6222
6223
6224 #define QUIT_BAN_NONE 0
6225 #define QUIT_BAN_ROLLER 1
6226 #define QUIT_BAN_ALL 2
6227
6228 /* This function prevents DoS attack using suicide */
6229 /* ;) DoS... its just annoying. hehe */
6230 static void check_roller(int Ind) {
6231 player_type *p_ptr = Players[Ind];
6232 time_t now = time(&now);
6233
6234 /* This was necessary ;) */
6235 if(is_admin(p_ptr)) return;
6236
6237 if (!cfg.quit_ban_mode) return;
6238
6239 if (cfg.quit_ban_mode == QUIT_BAN_ROLLER) {
6240 /* (s)he should have played somewhat */
6241 if (p_ptr->max_exp) return;
6242
6243 /* staying for more than 60 seconds? */
6244 if (now - lookup_player_laston(p_ptr->id) > 60) return;
6245
6246 /* died to a townie?
6247 if (p_ptr->ghost) return; */
6248 }
6249
6250 /* ban her/him for 1 min */
6251 add_banlist(p_ptr->accountname, NULL, p_ptr->hostname, 1, "Suicide spam");
6252 }
6253
6254
6255 static void check_killing_reward(int Ind) {
6256 player_type *p_ptr = Players[Ind];
6257
6258 /* reward top gladiators */
6259 if (p_ptr->kills >= 10) {
6260 /* reset! */
6261 //p_ptr->kills -= 10;
6262 p_ptr->kills = 0;
6263
6264 msg_broadcast_format(Ind, "\374\377y** %s vanquished 10 opponents! **", p_ptr->name);
6265 msg_print(Ind, "\375\377G* Another 10 aggressors have fallen by your hands! *");
6266 msg_print(Ind, "\375\377G* You received a reward! *");
6267 give_reward(Ind, RESF_MID, "Gladiator's reward", 1, 0);
6268 }
6269 }
6270
6271 /* deletes a ghost-dead player, cleans up his business, and disconnects him */
6272 static void erase_player(int Ind, int death_type, bool static_floor) {
6273 player_type *p_ptr = Players[Ind];
6274 char buf[1024];
6275 int i;
6276
6277 kill_houses(p_ptr->id, OT_PLAYER);
6278 rem_xorder(p_ptr->xorder_id);
6279 kill_objs(p_ptr->id);
6280 p_ptr->death = TRUE;
6281
6282 #ifdef AUCTION_SYSTEM
6283 auction_player_death(p_ptr->id);
6284 #endif
6285
6286 /* Remove him from his party/guild */
6287 if (p_ptr->party) {
6288 /* He leaves */
6289 party_leave(Ind, FALSE);
6290 }
6291 if (p_ptr->guild) {
6292 if ((guilds[p_ptr->guild].flags & GFLG_AUTO_READD)) {
6293 acc_set_guild(p_ptr->accountname, p_ptr->guild);
6294 acc_set_guild_dna(p_ptr->accountname, p_ptr->guild_dna);
6295 }
6296 if ((p_ptr->guild_flags & PGF_ADDER))
6297 acc_set_flags(p_ptr->accountname, ACC_GUILD_ADDER, TRUE);
6298 guild_leave(Ind, FALSE);
6299 }
6300
6301 /* Ghosts dont static the lvl if under cfg_preserve_death_level ft. DEG */
6302 if (static_floor && getlevel(&p_ptr->wpos) < cfg.preserve_death_level) {
6303 struct worldpos old_wpos;
6304 /*
6305 * HACK - Change the wpos temporarily so that new_players_on_depth
6306 * won't think that the player is on the level - mikaelh
6307 */
6308 wpcopy(&old_wpos, &p_ptr->wpos);
6309 p_ptr->wpos.wz++;
6310 new_players_on_depth(&old_wpos, -1, TRUE);
6311 p_ptr->wpos.wz--;
6312 }
6313
6314 buffer_account_for_event_deed(p_ptr, death_type);
6315
6316 /* temporarily reserve his character name in case he want's to remake that character */
6317 for (i = 0; i < MAX_RESERVED_NAMES; i++) {
6318 if (reserved_name_character[i][0]) continue;
6319
6320 strcpy(reserved_name_character[i], p_ptr->name);
6321 strcpy(reserved_name_account[i], p_ptr->accountname);
6322 reserved_name_timeout[i] = 60 * 24; //minutes
6323 break;
6324 }
6325 if (i == MAX_RESERVED_NAMES)
6326 s_printf("Warning: Coudln't reserve character name '%s' for account '%s'!\n", p_ptr->name, p_ptr->accountname);
6327
6328 /* Remove him from the player name database */
6329 delete_player_name(p_ptr->name);
6330
6331 /* Put him on the high score list */
6332 if(!p_ptr->noscore && !(p_ptr->mode & (MODE_PVP | MODE_EVERLASTING)))
6333 add_high_score(Ind);
6334
6335 /* Format string for death reason */
6336 if (death_type == DEATH_QUIT) strcpy(buf, "Committed suicide");
6337 else if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
6338 snprintf(buf, sizeof(buf), "Killed by %s (%d pts)", p_ptr->really_died_from, total_points(Ind));
6339 else snprintf(buf, sizeof(buf), "Killed by %s (%d pts)", p_ptr->died_from, total_points(Ind));
6340
6341 /* Get rid of him */
6342 Destroy_connection(p_ptr->conn, buf);
6343 }
6344
6345 static void inven_death_damage(int Ind, int verbose) {
6346 player_type *p_ptr = Players[Ind];
6347 object_type *o_ptr;
6348 char o_name[ONAME_LEN];
6349 int shuffle[INVEN_PACK];
6350 int inventory_loss = 0;
6351 int i, j, k;
6352
6353 for (i = 0; i < INVEN_PACK; i++) shuffle[i] = i;
6354 intshuffle(shuffle, INVEN_PACK);
6355
6356 /* Destroy some items randomly */
6357 for (i = 0; i < INVEN_PACK; i++) {
6358 j = shuffle[i];
6359 o_ptr = &p_ptr->inventory[j];
6360 if (!o_ptr->k_idx) continue;
6361
6362 /* hack: don't discard his remaining gold - a penalty was already deducted from it */
6363 if (o_ptr->tval == TV_GOLD) continue;
6364 /* guild keys are supposedly indestructible, so whatever.. */
6365 if (o_ptr->tval == TV_KEY && o_ptr->sval == SV_GUILD_KEY) continue;
6366 #ifdef DEATH_PACK_ITEM_NICE
6367 /* don't be too nasty to magic device users */
6368 if (is_magic_device(o_ptr->tval)) {
6369 k = object_value_real(0, o_ptr);
6370 if (k >= 2000 && rand_int(2)) continue;//basic bolt rods
6371 if (k >= 30000 && rand_int(2)) continue;//anni wand (rocket,havoc)
6372 }
6373 /* ..and to rare book carriers */
6374 if (o_ptr->tval == TV_BOOK &&
6375 (o_ptr->sval == SV_CUSTOM_TOME_2 || o_ptr->sval == SV_CUSTOM_TOME_3)
6376 && rand_int(2))
6377 continue;
6378 #endif
6379
6380 if (magik(DEATH_PACK_ITEM_LOST)) {
6381 object_desc(Ind, o_name, o_ptr, TRUE, 3);
6382 s_printf("item_lost: %s (slot %d)\n", o_name, j);
6383
6384 if (verbose) {
6385 /* Message */
6386 msg_format(Ind, "\376\377oYour %s %s destroyed!", o_name,
6387 ((o_ptr->number > 1) ? "were" : "was"));
6388 }
6389
6390 if (true_artifact_p(o_ptr)) {
6391 /* set the artifact as unfound */
6392 handle_art_d(o_ptr->name1);
6393 }
6394 questitem_d(o_ptr, o_ptr->number);
6395
6396 inven_item_increase(Ind, j, -(o_ptr->number));
6397 inven_item_optimize(Ind, j);
6398 inventory_loss++;
6399
6400 if (inventory_loss >= 4) {
6401 break;
6402 }
6403 }
6404 }
6405 }
6406
6407 static void equip_death_damage(int Ind, int verbose) {
6408 player_type *p_ptr = Players[Ind];
6409 object_type *o_ptr;
6410 char o_name[ONAME_LEN];
6411 int shuffle[INVEN_TOTAL];
6412 int equipment_loss = 0;
6413 int i, j;
6414
6415 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) shuffle[i] = i;
6416 intshuffle(shuffle + INVEN_WIELD, INVEN_EQ);
6417
6418 /* Destroy some items randomly */
6419 for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) {
6420 j = shuffle[i];
6421 o_ptr = &p_ptr->inventory[j];
6422 if (!o_ptr->k_idx) continue;
6423
6424 if (magik(DEATH_EQ_ITEM_LOST)) {
6425 object_desc(Ind, o_name, o_ptr, TRUE, 3);
6426 s_printf("item_lost: %s (slot %d)\n", o_name, j);
6427
6428 if (verbose) {
6429 /* Message */
6430 msg_format(Ind, "\376\377oYour %s %s destroyed!", o_name,
6431 ((o_ptr->number > 1) ? "were" : "was"));
6432 }
6433
6434 if (true_artifact_p(o_ptr)) {
6435 /* set the artifact as unfound */
6436 handle_art_d(o_ptr->name1);
6437 }
6438 questitem_d(o_ptr, o_ptr->number);
6439
6440 inven_item_increase(Ind, j, -(o_ptr->number));
6441 inven_item_optimize(Ind, j);
6442 equipment_loss++;
6443
6444 if (equipment_loss >= 1) {
6445 break;
6446 }
6447 }
6448 }
6449 }
6450
6451 /*
6452 * Handle the death of a player and drop their stuff.
6453 */
6454
6455 /*
6456 HACKED to handle fruit bat
6457 changed so players remain in the team when killed
6458 changed so when leader ghosts perish the team is disbanded
6459 -APD-
6460 */
6461
6462 void player_death(int Ind) {
6463 player_type *p_ptr = Players[Ind], *p_ptr2 = NULL;
6464 int Ind2;
6465 object_type *o_ptr;
6466 monster_type *m_ptr;
6467 dungeon_type *d_ptr = getdungeon(&p_ptr->wpos);
6468 dun_level *l_ptr = getfloor(&p_ptr->wpos);
6469 char buf[1024], m_name_extra[MNAME_LEN], msg_layout = 'a';
6470 int i, k, j, tries = 0;
6471 #if 0
6472 int inventory_loss = 0, equipment_loss = 0;
6473 #endif
6474 // int inven_sort_map[INVEN_TOTAL];
6475 //wilderness_type *wild;
6476 bool hell = TRUE, secure = FALSE, ge_secure = FALSE, pvp = ((p_ptr->mode & MODE_PVP) != 0), erase = FALSE, insanity = streq(p_ptr->died_from, "insanity");
6477 cptr titlebuf;
6478 int death_type = -1; /* keep track of the way (s)he died, for buffer_account_for_event_deed() */
6479 bool world_broadcast = TRUE, just_fruitbat_transformation = (p_ptr->fruit_bat == -1);
6480 bool was_total_winner = p_ptr->total_winner, retire = FALSE;
6481 bool in_iddc = in_irondeepdive(&p_ptr->wpos);
6482
6483 #ifdef SHOW_REALLY_DIED_FROM
6484 if ((streq(p_ptr->died_from, "It") || p_ptr->image
6485 #ifdef SHOW_REALLY_DIED_FROM_INSANITY
6486 || insanity
6487 #endif
6488 ) && !(
6489 #ifndef SHOW_REALLY_DIED_FROM_INSANITY
6490 insanity ||
6491 #endif
6492 streq(p_ptr->died_from, "indecisiveness") ||
6493 streq(p_ptr->died_from, "indetermination"))
6494 && p_ptr->really_died_from[0]) //paranoia?
6495 strcpy(p_ptr->died_from, p_ptr->really_died_from);
6496 #endif
6497
6498 /* character-intrinsic conditions violated -> unpreventable no-ghost death */
6499 if (streq(p_ptr->died_from, "indecisiveness") ||
6500 streq(p_ptr->died_from, "indetermination"))
6501 erase = TRUE;
6502
6503 /* Amulet of immortality prevents death */
6504 if (!erase && p_ptr->admin_invuln) {
6505 if (just_fruitbat_transformation) p_ptr->fruit_bat = 0;
6506 return;
6507 }
6508
6509 /* prepare player's title */
6510 titlebuf = get_ptitle(p_ptr, FALSE);
6511
6512 break_cloaking(Ind, 0);
6513 break_shadow_running(Ind);
6514 stop_precision(Ind);
6515 stop_shooting_till_kill(Ind);
6516
6517 if (just_fruitbat_transformation) {
6518 p_ptr->death = FALSE;
6519 p_ptr->update |= (PU_BONUS);
6520 p_ptr->redraw |= (PR_HP | PR_GOLD | PR_BASIC | PR_DEPTH);
6521 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
6522 p_ptr->window |= (PW_INVEN | PW_EQUIP);
6523 p_ptr->fruit_bat = 2;
6524 calc_hitpoints(Ind);
6525
6526 /* Tell the players */
6527 snprintf(buf, sizeof(buf), "\374\377o%s was turned into a fruit bat by %s!", p_ptr->name, p_ptr->died_from);
6528 /* handle the secret_dungeon_master option */
6529 if ((!p_ptr->admin_dm) || (!cfg.secret_dungeon_master)) {
6530 #ifdef TOMENET_WORLDS
6531 if (cfg.worldd_pdeath) world_msg(buf);
6532 #endif
6533 msg_broadcast(Ind, buf);
6534 }
6535 return;
6536 }
6537
6538 #ifdef RPG_SERVER
6539 if (p_ptr->wpos.wz != 0) {
6540 for (i = m_top-1; i >= 0; i--) {
6541 monster_type *m_ptr = &m_list[i];
6542 if (m_ptr->owner == p_ptr->id && m_ptr->pet) {
6543 m_ptr->pet = 0; //default behaviour!
6544 m_ptr->owner = 0;
6545 i = -1;
6546 }
6547 }
6548 }
6549 #endif
6550
6551 /* very very rare case, but this can happen(eg. starvation) */
6552 if (p_ptr->store_num != -1) {
6553 handle_store_leave(Ind);
6554 Send_store_kick(Ind);
6555 }
6556
6557 if (d_ptr && (d_ptr->flags2 & DF2_NO_DEATH)) secure = TRUE;
6558
6559 if (in_iddc
6560 && !is_admin(p_ptr)) {
6561 for (i = 0; i < IDDC_HIGHSCORE_SIZE; i++) {
6562 if (deep_dive_level[i] >= ABS(p_ptr->wpos.wz) || deep_dive_level[i] == -1) {
6563 #ifdef IDDC_RESTRICT_ACC_CLASS /* only allow one entry of same account+class? : discard new entry */
6564 if (!strcmp(deep_dive_account[i], p_ptr->accountname) &&
6565 deep_dive_class[i] == p_ptr->pclass) {
6566 i = IDDC_HIGHSCORE_DISPLAYED;
6567 break;
6568 }
6569 #endif
6570 continue;
6571 }
6572 #ifdef IDDC_RESTRICT_ACC_CLASS /* only allow one entry of same account+class? : discard previous entry */
6573 for (j = i; j < IDDC_HIGHSCORE_SIZE - 1; j++) {
6574 if (!strcmp(deep_dive_account[j], p_ptr->accountname) &&
6575 deep_dive_class[i] == p_ptr->pclass) {
6576 int k;
6577
6578 /* pull up all succeeding entries by 1 */
6579 for (k = j; k < IDDC_HIGHSCORE_SIZE - 1; k++) {
6580 deep_dive_level[k] = deep_dive_level[k + 1];
6581 strcpy(deep_dive_name[k], deep_dive_name[k + 1]);
6582 strcpy(deep_dive_char[k], deep_dive_char[k + 1]);
6583 strcpy(deep_dive_account[k], deep_dive_account[k + 1]);
6584 deep_dive_class[k] = deep_dive_class[k + 1];
6585 }
6586 break;
6587 }
6588 }
6589 #endif
6590 /* push down all entries by 1, to make room for inserting new entry */
6591 for (j = IDDC_HIGHSCORE_SIZE - 1; j > i; j--) {
6592 deep_dive_level[j] = deep_dive_level[j - 1];
6593 strcpy(deep_dive_name[j], deep_dive_name[j - 1]);
6594 strcpy(deep_dive_char[j], deep_dive_char[j - 1]);
6595 strcpy(deep_dive_account[j], deep_dive_account[j - 1]);
6596 deep_dive_class[j] = deep_dive_class[j - 1];
6597 }
6598 deep_dive_level[i] = ABS(p_ptr->wpos.wz);
6599 //strcpy(deep_dive_name[i], p_ptr->name);
6600 #ifdef IDDC_HISCORE_SHOWS_ICON
6601 sprintf(deep_dive_name[i], "%s, %s %s (\\{%c%c\\{s/\\{%c%d\\{s),",
6602 p_ptr->name, get_prace(p_ptr), class_info[p_ptr->pclass].title, color_attr_to_char(p_ptr->cp_ptr->color), p_ptr->fruit_bat ? 'b' : '@',
6603 p_ptr->ghost ? 'r' : 's', p_ptr->max_plv);
6604 #else
6605 sprintf(deep_dive_name[i], "%s, %s %s (\\{%c%d\\{s),",
6606 p_ptr->name, get_prace(p_ptr), class_info[p_ptr->pclass].title,
6607 p_ptr->ghost ? 'r' : 's', p_ptr->max_plv);
6608 #endif
6609 strcpy(deep_dive_char[i], p_ptr->name);
6610 strcpy(deep_dive_account[i], p_ptr->accountname);
6611 deep_dive_class[i] = p_ptr->pclass;
6612 break;
6613 }
6614
6615 if (i < IDDC_HIGHSCORE_DISPLAYED) {
6616 sprintf(buf, "\374\377a%s reached floor %d in the Ironman Deep Dive challenge, placing %d%s!",
6617 p_ptr->name, ABS(p_ptr->wpos.wz), i + 1, i == 0 ? "st" : (i == 1 ? "nd" : (i == 2 ? "rd" : "th")));
6618 msg_broadcast_format(0, buf);
6619 #ifdef TOMENET_WORLDS
6620 if (cfg.worldd_events) world_msg(buf);
6621 #endif
6622 } else {
6623 sprintf(buf, "\374\377a%s reached floor %d in the Ironman Deep Dive challenge!",
6624 p_ptr->name, ABS(p_ptr->wpos.wz));
6625 msg_broadcast_format(0, buf);
6626 #ifdef TOMENET_WORLDS
6627 if (cfg.worldd_events) world_msg(buf);
6628 #endif
6629 }
6630
6631 if (ABS(p_ptr->wpos.wz) >= 30)
6632 l_printf("%s \\{s%s (%d) reached floor %d in the Ironman Deep Dive challenge\n",
6633 showdate(), p_ptr->name, p_ptr->max_plv, ABS(p_ptr->wpos.wz));
6634 else if (i < IDDC_HIGHSCORE_SIZE) { /* the score table is updated anyway, even if no l_printf() entry is created */
6635 char path[MAX_PATH_LENGTH];
6636 char path_rev[MAX_PATH_LENGTH];
6637 path_build(path, MAX_PATH_LENGTH, ANGBAND_DIR_DATA, "legends.log");
6638 path_build(path_rev, MAX_PATH_LENGTH, ANGBAND_DIR_DATA, "legends-rev.log");
6639 reverse_lines(path, path_rev);
6640 }
6641 }
6642
6643 if (ge_special_sector &&
6644 (p_ptr->wpos.wx == WPOS_ARENA_X && p_ptr->wpos.wy == WPOS_ARENA_Y &&
6645 p_ptr->wpos.wz == WPOS_ARENA_Z)) {
6646 secure = TRUE;
6647 ge_secure = TRUE; /* extra security for global events */
6648 }
6649
6650 if (pvp) {
6651 secure = FALSE;
6652 msg_layout = 'L';
6653 }
6654
6655 /* Hack -- amulet of life saving */
6656 if (p_ptr->alive && !erase && (secure ||
6657 (p_ptr->inventory[INVEN_NECK].k_idx &&
6658 p_ptr->inventory[INVEN_NECK].sval == SV_AMULET_LIFE_SAVING))) {
6659 s_printf("%s (%d) was pseudo-killed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->really_died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
6660
6661 if (!secure) {
6662 msg_print(Ind, "\377oYour amulet shatters into pieces!");
6663 inven_item_increase(Ind, INVEN_NECK, -99);
6664 //inven_item_describe(Ind, INVEN_NECK);
6665 inven_item_optimize(Ind, INVEN_NECK);
6666 }
6667
6668 /* Cure him from various maladies */
6669 // p_ptr->black_breath = FALSE;
6670 if (p_ptr->image) (void)set_image(Ind, 0);
6671 if (p_ptr->blind) (void)set_blind(Ind, 0);
6672 if (p_ptr->paralyzed) (void)set_paralyzed(Ind, 0);
6673 if (p_ptr->confused) (void)set_confused(Ind, 0);
6674 if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
6675 if (p_ptr->stun) (void)set_stun(Ind, 0);
6676 if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
6677 /* if (p_ptr->food < PY_FOOD_ALERT) */
6678 (void)set_food(Ind, PY_FOOD_FULL - 1);
6679
6680 /* Teleport him */
6681 teleport_player(Ind, 200, TRUE);
6682
6683 /* Remove the death flag */
6684 p_ptr->death = FALSE;
6685 // ptr->ghost = 0;
6686
6687 /* Give him his hit points back */
6688 p_ptr->chp = p_ptr->mhp;
6689 p_ptr->chp_frac = 0;
6690
6691 if (secure) {
6692 p_ptr->new_level_method = (p_ptr->wpos.wz > 0 ? LEVEL_RECALL_DOWN : LEVEL_RECALL_UP);
6693 p_ptr->recall_pos.wx = p_ptr->wpos.wx;
6694 p_ptr->recall_pos.wy = p_ptr->wpos.wy;
6695 p_ptr->recall_pos.wz = 0;
6696 if (ge_secure) {
6697 k = 0;
6698 /* reset the monster :D */
6699 for (i = 1; i < m_max; i++) {
6700 m_ptr = &m_list[i];
6701 if (m_ptr->wpos.wx == p_ptr->wpos.wx && m_ptr->wpos.wy == p_ptr->wpos.wy && m_ptr->wpos.wz == p_ptr->wpos.wz) {
6702 k = m_ptr->r_idx;
6703 j = m_ptr->ego;
6704 monster_desc(0, m_name_extra, i, 0x00);
6705 m_name_extra[0] = toupper(m_name_extra[0]);
6706 wipe_m_list(&p_ptr->wpos);
6707 summon_override_checks = SO_ALL & ~SO_PROTECTED;
6708 #if 1 /* GE_ARENA_ALLOW_EGO */
6709 while (!summon_detailed_one_somewhere(&p_ptr->wpos, k, j, FALSE, 101)
6710 && (++tries < 1000));
6711 #else
6712 while (!summon_specific_race_somewhere(&p_ptr->wpos, k, 100, 1)
6713 && (++tries < 1000));
6714 #endif
6715 summon_override_checks = SO_NONE;
6716 break;
6717 }
6718 }
6719 if (k) { /* usual */
6720 msg_broadcast_format(0, "\376\377A** %s has defeated %s! **", m_name_extra, p_ptr->name);
6721 s_printf("EVENT_RESULT: %s has defeated %s (%d) (%d damage).\n", m_name_extra, p_ptr->name, p_ptr->lev, p_ptr->deathblow);
6722 } else { /* can happen if monster dies first, then player dies to monster DoT */
6723 msg_broadcast_format(0, "\376\377A** %s didn't survive! **", p_ptr->name);
6724 s_printf("EVENT_RESULT: %s (%d) was defeated (%d damage).\n", p_ptr->name, p_ptr->lev, p_ptr->deathblow);
6725 }
6726 recall_player(Ind, "\377oYou die.. at least it felt like you did..!");
6727 }
6728 else recall_player(Ind, "\377oYou almost died.. but your life was secured here!");
6729
6730 p_ptr->safe_sane = TRUE;
6731 /* Apply small penalty for death */
6732 if (!ge_secure) { /* except if we were in a special event that protects */
6733 #ifndef ARCADE_SERVER
6734 p_ptr->au = p_ptr->au * 4 / 5;
6735 p_ptr->max_exp = (p_ptr->max_exp * 4 + 1) / 5; /* never drop below 1! (Highlander Tournament exploit) */
6736 p_ptr->exp = p_ptr->max_exp;
6737 #endif
6738 } else {
6739 if (p_ptr->csane <= 10) p_ptr->csane = 10; /* just something, paranoia */
6740 }
6741 check_experience(Ind);
6742
6743 /* update stats */
6744 p_ptr->update |= PU_SANITY;
6745 update_stuff(Ind);
6746 p_ptr->safe_sane = FALSE;
6747 /* Redraw */
6748 p_ptr->redraw |= (PR_BASIC);
6749 /* Update */
6750 p_ptr->update |= (PU_BONUS);
6751 } else {
6752 /* Went mad? */
6753 if (p_ptr->csane < 0) p_ptr->csane = 0;
6754 }
6755
6756 /* Wow! You may return!! */
6757 if (!ge_secure) p_ptr->soft_deaths++;
6758 return;
6759 }
6760
6761 if ((!(p_ptr->mode & MODE_NO_GHOST)) && !cfg.no_ghost && !pvp) {
6762 if(!p_ptr->wpos.wz || !(d_ptr->flags2 & (DF2_HELL | DF2_IRON)))
6763 hell = FALSE;
6764 }
6765
6766 if ((Ind2 = get_esp_link(Ind, LINKF_PAIN, &p_ptr2))) {
6767 strcpy(p_ptr2->died_from, p_ptr->died_from);
6768 if (!p_ptr2->ghost)
6769 {
6770 strcpy(p_ptr2->died_from_list, p_ptr->died_from);
6771 p_ptr2->died_from_depth = getlevel(&p_ptr2->wpos);
6772 /* Hack to remember total winning */
6773 if (p_ptr2->total_winner) strcat(p_ptr2->died_from_list, "\001");
6774 }
6775 /* new: 50-50 chance to die for linked mind */
6776 bypass_invuln = TRUE;
6777 if (p_ptr2->chp >= 30)
6778 take_hit(Ind2, p_ptr2->chp - 20 + rand_int(42), p_ptr->died_from, 0);
6779 else
6780 take_hit(Ind2, p_ptr2->chp - 2 + rand_int(6), p_ptr->died_from, 0);
6781 bypass_invuln = FALSE;
6782 }
6783
6784 if (erase) hell = TRUE;
6785
6786 /* Morgoth's level might be NO_GHOST! */
6787 if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_GHOST)) hell = TRUE;
6788
6789 /* For global events (Highlander Tournament) */
6790 /* either instakill in sector 0,0... */
6791 if (p_ptr->global_event_temp & PEVF_NOGHOST_00) hell = TRUE;
6792 /* or instead teleport them to surface */
6793 /* added wpos checks due to weirdness. -Molt */
6794 if (p_ptr->wpos.wx != WPOS_SECTOR00_X && p_ptr->wpos.wy != WPOS_SECTOR00_Y && (p_ptr->global_event_temp & PEVF_SAFEDUN_00)) {
6795 s_printf("Somethin weird with %s. GET is %d\n", p_ptr->name, p_ptr->global_event_temp);
6796 msg_broadcast(0, "Uh oh, somethin's not right here.");
6797 }
6798 if ((p_ptr->global_event_temp & PEVF_SAFEDUN_00) && (p_ptr->csane >= 0) && p_ptr->wpos.wx == WPOS_SECTOR00_X && p_ptr->wpos.wy == WPOS_SECTOR00_Y && p_ptr->wpos.wz != 0) {
6799 s_printf("DEBUG_TOURNEY: player %s revived.\n", p_ptr->name);
6800 s_printf("%s (%d) was pseudo-killed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->really_died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
6801
6802 if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
6803 if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
6804 (void)set_food(Ind, PY_FOOD_FULL - 1);
6805
6806 if (!sector00downstairs) p_ptr->global_event_temp &= ~PEVF_SAFEDUN_00; /* no longer safe from death */
6807 p_ptr->recall_pos.wx = 0;
6808 p_ptr->recall_pos.wy = 0;
6809 p_ptr->recall_pos.wz = 0;
6810 p_ptr->global_event_temp |= PEVF_PASS_00; /* pass through sector00separation */
6811 p_ptr->new_level_method = LEVEL_OUTSIDE_RAND;
6812 recall_player(Ind, "");
6813
6814 /* Allow him to find the stairs quickly for re-entering highlander dungeon */
6815 wiz_lite(Ind);
6816
6817 /* Teleport him */
6818 teleport_player(Ind, 200, TRUE);
6819 /* Remove the death flag */
6820 p_ptr->death = FALSE;
6821 // p_ptr->ghost = 0;
6822 /* Give him his hit points back */
6823 p_ptr->chp = p_ptr->mhp;
6824 p_ptr->chp_frac = 0;
6825
6826 /* Redraw */
6827 p_ptr->redraw |= (PR_BASIC);
6828 /* Update */
6829 p_ptr->update |= (PU_BONUS);
6830
6831 /* Inform him about his situation */
6832 if (!sector00downstairs) msg_print(Ind, "\377oYou were defeated too early and have to sit out the remaining time!");
6833 else msg_print(Ind, "\377oYou were defeated too early, find the staircase and re-enter the dungeon!");
6834
6835 p_ptr->soft_deaths++;
6836 return;
6837 }
6838
6839 #ifdef ENABLE_INSTANT_RES
6840 if (p_ptr->insta_res && !erase && p_ptr->alive) {
6841 char instant_res_possible = TRUE;
6842 int dlvl = getlevel(&p_ptr->wpos);
6843 int instant_res_cost = dlvl * dlvl * 10 + 10;
6844
6845 /* Only everlasters */
6846 if (!(p_ptr->mode & MODE_EVERLASTING))
6847 instant_res_possible = FALSE;
6848
6849 /* If already a ghost, get destroyed */
6850 if (p_ptr->ghost)
6851 instant_res_possible = FALSE;
6852
6853 /* Insanity is a no-ghost death */
6854 if (insanity)
6855 instant_res_possible = FALSE;
6856
6857 /* Not on NO_GHOST levels */
6858 if (hell)
6859 instant_res_possible = FALSE;
6860
6861 /* Not on suicides */
6862 if (!p_ptr->alive)
6863 instant_res_possible = FALSE;
6864
6865 #ifdef INSTANT_RES_EXCEPTION
6866 /* Not in Nether Realm */
6867 if (in_netherrealm(&p_ptr->wpos))
6868 instant_res_possible = FALSE;
6869 #endif
6870
6871 /* Divine wrath is meant to kill people */
6872 if (streq(p_ptr->died_from, "divine wrath"))
6873 instant_res_possible = FALSE;
6874
6875 /* Check that the player has enough money */
6876 if (instant_res_cost > p_ptr->au + p_ptr->balance) {
6877 msg_print(Ind, "\376\377yYou do not have sufficient funds for instant-resurrection!");
6878 instant_res_possible = FALSE;
6879 }
6880
6881 if (instant_res_possible) {
6882 int loss_factor, reduce;
6883 #ifndef FALLEN_WINNERSONLY
6884 int i;
6885 u32b dummy, f5;
6886 #endif
6887
6888 /* Log it */
6889 s_printf("INSTA_RES: %s (%d) was defeated by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
6890 if (!strcmp(p_ptr->died_from, "It") || insanity || p_ptr->image)
6891 s_printf("(%s was really defeated by %s.)\n", p_ptr->name, p_ptr->really_died_from);
6892
6893 #ifdef USE_SOUND_2010
6894 /* Play the death sound */
6895 if (p_ptr->male) sound(Ind, "death_male", "death", SFX_TYPE_MISC, TRUE);
6896 else sound(Ind, "death_female", "death", SFX_TYPE_MISC, TRUE);
6897 #else
6898 sound(Ind, SOUND_DEATH);
6899 #endif
6900
6901 /* Message to other players */
6902 if (cfg.unikill_format)
6903 snprintf(buf, sizeof(buf), "\374\377D%s %s (%d) was defeated by %s.", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
6904 else
6905 snprintf(buf, sizeof(buf), "\374\377D%s (%d) was defeated by %s.", p_ptr->name, p_ptr->lev, p_ptr->died_from);
6906
6907 msg_broadcast(Ind, buf);
6908 #ifdef TOMENET_WORLDS
6909 if (cfg.worldd_pdeath) world_msg(buf);
6910 #endif
6911
6912 /* Add to legends log if he was a winner or very high level */
6913 if (!is_admin(p_ptr)) {
6914 if (p_ptr->total_winner)
6915 l_printf("%s \\{r%s royalty %s (%d) died and was instantly resurrected\n", showdate(), p_ptr->male ? "His" : "Her", p_ptr->name, p_ptr->lev);
6916 else if (p_ptr->lev >= 50)
6917 l_printf("%s \\{r%s (%d) died and was instantly resurrected\n", showdate(), p_ptr->name, p_ptr->lev);
6918 }
6919
6920 /* Tell him what happened -- moved the messages up here so they get onto the chardump! */
6921 msg_format(Ind, "\374\377RYou were defeated by %s, but the priests have saved you.", p_ptr->died_from);
6922
6923 /* new - death dump for insta-res too! */
6924 Send_chardump(Ind, "-death");
6925
6926 /* Hm, this doesn't need to be on the char dump actually */
6927 msg_format(Ind, "\377oThey have requested a fee of %d gold pieces.", instant_res_cost);
6928
6929 /* Cure him from various maladies */
6930 if (p_ptr->image) (void)set_image(Ind, 0);
6931 if (p_ptr->blind) (void)set_blind(Ind, 0);
6932 if (p_ptr->paralyzed) (void)set_paralyzed(Ind, 0);
6933 if (p_ptr->confused) (void)set_confused(Ind, 0);
6934 if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
6935 if (p_ptr->stun) (void)set_stun(Ind, 0);
6936 if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
6937 (void)set_food(Ind, PY_FOOD_FULL - 1);
6938
6939 if (p_ptr->black_breath) {
6940 //msg_print(Ind, "The hold of the Black Breath on you is broken!");
6941 p_ptr->black_breath = FALSE;
6942 }
6943
6944 /* Remove the death flag */
6945 p_ptr->death = FALSE;
6946
6947 /* Give him his hit points back */
6948 p_ptr->chp = p_ptr->mhp;
6949 p_ptr->chp_frac = 0;
6950
6951 /* Lose inventory and equipment items as per normal death */
6952 #ifdef DEATH_PACK_ITEM_LOST
6953 inven_death_damage(Ind, TRUE);
6954 #endif
6955 #ifdef DEATH_EQ_ITEM_LOST
6956 equip_death_damage(Ind, TRUE);
6957 #endif
6958
6959 /* Extract the cost */
6960 p_ptr->au -= instant_res_cost;
6961 if (p_ptr->au < 0) {
6962 p_ptr->balance += p_ptr->au;
6963 p_ptr->au = 0;
6964 }
6965
6966 /* Also lose some cash on death */
6967 s_printf("gold_lost: carried %d, remaining ", p_ptr->au);
6968 #if 0 /* lose 0 below 50k, up to 50% up to 500k, 50% after that */
6969 if (p_ptr->au <= 50000) ;
6970 else if (p_ptr->au <= 500000) p_ptr->au = (((p_ptr->au) * 100) / (100 + ((p_ptr->au - 50000) / 4500)));
6971 else p_ptr->au /= 2;
6972 #else /* lose 5..33% */
6973 /* overflow handling */
6974 if (p_ptr->au <= 20000000) p_ptr->au = (p_ptr->au * (rand_int(29) + 67)) / 100;
6975 else p_ptr->au = (p_ptr->au / 100) * (rand_int(29) + 67);
6976 #endif
6977 s_printf("%d.\n", p_ptr->au);
6978
6979 p_ptr->safe_sane = TRUE;
6980
6981 /* Lose some experience */
6982 loss_factor = INSTANT_RES_XP_LOST;
6983 if (get_skill(p_ptr, SKILL_HCURING) >= 50) loss_factor -= 5;
6984
6985 reduce = p_ptr->max_exp;
6986 reduce = reduce > 99999 ?
6987 reduce / 100 * loss_factor : reduce * loss_factor / 100;
6988 p_ptr->max_exp -= reduce;
6989
6990 reduce = p_ptr->exp;
6991 reduce = reduce > 99999 ?
6992 reduce / 100 * loss_factor : reduce * loss_factor / 100;
6993 p_ptr->exp -= reduce;
6994
6995 check_experience(Ind);
6996
6997 /* Remove massive crown of Morgoth and Grond */
6998 if (p_ptr->inventory[INVEN_HEAD].k_idx && p_ptr->inventory[INVEN_HEAD].name1 == ART_MORGOTH) {
6999 char o_name[ONAME_LEN];
7000
7001 o_ptr = &p_ptr->inventory[INVEN_HEAD];
7002 object_desc(Ind, o_name, o_ptr, TRUE, 3);
7003 msg_format(Ind, "\376\377oYour %s was destroyed!", o_name);
7004 handle_art_d(o_ptr->name1);
7005
7006 inven_item_increase(Ind, INVEN_HEAD, -(o_ptr->number));
7007 inven_item_optimize(Ind, INVEN_HEAD);
7008 }
7009 if (p_ptr->inventory[INVEN_WIELD].k_idx && p_ptr->inventory[INVEN_WIELD].name1 == ART_GROND) {
7010 char o_name[ONAME_LEN];
7011
7012 o_ptr = &p_ptr->inventory[INVEN_WIELD];
7013 object_desc(Ind, o_name, o_ptr, TRUE, 3);
7014 msg_format(Ind, "\376\377oYour %s was destroyed!", o_name);
7015 handle_art_d(o_ptr->name1);
7016
7017 inven_item_increase(Ind, INVEN_WIELD, -(o_ptr->number));
7018 inven_item_optimize(Ind, INVEN_WIELD);
7019 }
7020
7021 /* update stats */
7022 p_ptr->update |= PU_SANITY;
7023 update_stuff(Ind);
7024 p_ptr->safe_sane = FALSE;
7025
7026 p_ptr->recall_pos.wx = p_ptr->town_x;
7027 p_ptr->recall_pos.wy = p_ptr->town_y;
7028 p_ptr->recall_pos.wz = 0;
7029 p_ptr->new_level_method = LEVEL_TO_TEMPLE;
7030 recall_player(Ind, "");
7031
7032 #if 0
7033 /* Unown land */
7034 if (p_ptr->total_winner) {
7035 #ifdef NEW_DUNGEON
7036 /* FIXME */
7037 /*
7038 msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7039 wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7040 */
7041 #else
7042 msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7043 wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7044 #endif
7045 }
7046 #endif
7047
7048 /* No longer a winner */
7049 p_ptr->total_winner = FALSE;
7050
7051 /* Set all his artifacts back to normal-speed timeout */
7052 if (was_total_winner && !cfg.fallenkings_etiquette) {
7053 for (j = 0; j < INVEN_TOTAL; j++)
7054 if (p_ptr->inventory[j].name1 &&
7055 p_ptr->inventory[j].name1 != ART_RANDART)
7056 a_info[p_ptr->inventory[j].name1].winner = FALSE;
7057 }
7058
7059 #ifndef FALLEN_WINNERSONLY
7060 /* Take off winner artifacts and winner-only items */
7061 for (i = INVEN_WIELD; i <= INVEN_TOTAL; i++) {
7062 o_ptr = &p_ptr->inventory[i];
7063 object_flags(o_ptr, &dummy, &dummy, &dummy, &dummy, &f5, &dummy, &dummy);
7064 if ((f5 & TR5_WINNERS_ONLY)) {
7065 bypass_inscrption = TRUE;
7066 inven_takeoff(Ind, i, 255, FALSE);
7067 }
7068 }
7069 #endif
7070
7071 /* Redraw */
7072 p_ptr->redraw |= (PR_BASIC);
7073 /* Update */
7074 p_ptr->update |= (PU_BONUS);
7075
7076 p_ptr->deaths++;
7077 return;
7078 }
7079 }
7080 #endif
7081
7082 /* Players of level cfg.nodrop [5] will die a no-ghost death.
7083 This should clarify the situation for newbies and avoid them
7084 getting confused and/or lacking their startup equipment.
7085 On the other hand, it's confusing to ghost-die when you know
7086 you chose everlasting +_+ */
7087 #if 0 /* disable newbies-lvl explanation msg (much below) iff this is on */
7088 if (p_ptr->max_plv < cfg.newbies_cannot_drop) hell = TRUE;
7089 #endif
7090
7091 #ifdef USE_SOUND_2010
7092 /* don't play a sfx for mere suicide */
7093 if (p_ptr->alive) {
7094 if (p_ptr->male) sound(Ind, "death_male", "death", SFX_TYPE_MISC, TRUE);
7095 else sound(Ind, "death_female", "death", SFX_TYPE_MISC, TRUE);
7096 }
7097 #else
7098 /* don't play a sfx for mere suicide */
7099 if (p_ptr->alive) sound(Ind, SOUND_DEATH);
7100 #endif
7101
7102 /* Drop gold if player has any -------------------------------------- */
7103 if (p_ptr->alive && p_ptr->au) {
7104 /* Put the player's gold in the overflow slot */
7105 invcopy(&p_ptr->inventory[INVEN_PACK], lookup_kind(TV_GOLD, 9));
7106 /* Change the mode of the gold accordingly */
7107 p_ptr->inventory[INVEN_PACK].mode = p_ptr->mode;
7108 p_ptr->inventory[INVEN_PACK].owner = p_ptr->id; /* hack */
7109
7110 /* Drop no more than 32000 gold */
7111 // if (p_ptr->au > 32000) p_ptr->au = 32000;
7112 /* (actually, this if-clause is not necessary) */
7113 s_printf("gold_lost: carried %d, remaining ", p_ptr->au);
7114 #if 0 /* lose 0 below 50k, up to 50% up to 500k, 50% after that */
7115 if (p_ptr->au <= 50000) ;
7116 else if (p_ptr->au <= 500000) p_ptr->au = (((p_ptr->au) * 100) / (100 + ((p_ptr->au - 50000) / 4500)));
7117 else p_ptr->au /= 2;
7118 #else /* lose 5..33% */
7119 p_ptr->au = (p_ptr->au * (rand_int(29) + 67)) / 100;
7120 #endif
7121
7122 if (p_ptr->max_plv >= cfg.newbies_cannot_drop) {
7123 /* Set the amount */
7124 p_ptr->inventory[INVEN_PACK].pval = p_ptr->au;
7125 /* set fitting gold 'colour' */
7126 p_ptr->inventory[INVEN_PACK].k_idx = gold_colour(p_ptr->au, FALSE, TRUE);
7127 p_ptr->inventory[INVEN_PACK].xtra1 = 1;//mark as 'compact' in case it falls on top of a normal money pile
7128 p_ptr->inventory[INVEN_PACK].sval = k_info[p_ptr->inventory[INVEN_PACK].k_idx].sval;
7129 s_printf("%d.\n", p_ptr->au);
7130 } else {
7131 invwipe(&p_ptr->inventory[INVEN_PACK]);
7132 s_printf("none.\n");
7133 }
7134
7135 /* No more gold */
7136 p_ptr->au = 0;
7137 }
7138
7139 /* Drop/lose items -------------------------------------------------- */
7140
7141 /* Don't "lose" items on suicide (they all poof anyway, except for true arts possibly) */
7142 #ifdef DEATH_PACK_ITEM_LOST
7143 if (p_ptr->alive) inven_death_damage(Ind, FALSE);
7144 #endif
7145 #ifdef DEATH_EQ_ITEM_LOST
7146 if (p_ptr->alive) equip_death_damage(Ind, FALSE);
7147 #endif
7148
7149 /* Setup the sorter */
7150 ang_sort_comp = ang_sort_comp_value;
7151 ang_sort_swap = ang_sort_swap_value;
7152 /* Remember original position before sorting */
7153 for (i = 0; i < INVEN_TOTAL; i++) p_ptr->inventory[i].inven_order = i;
7154 /* Sort the player's inventory according to value */
7155 ang_sort(Ind, p_ptr->inventory, NULL, INVEN_TOTAL);
7156
7157 /* Starting with the most valuable, drop things one by one */
7158 for (i = 0; i < INVEN_TOTAL; i++) {
7159 bool away = FALSE;
7160
7161 o_ptr = &p_ptr->inventory[i];
7162 /* Make sure we have an object */
7163 if (o_ptr->k_idx == 0) continue;
7164
7165 if (o_ptr->questor) { /* questor items cannot be 'dropped', only destroyed! */
7166 questitem_d(o_ptr, o_ptr->number);
7167 continue;
7168 }
7169
7170 /* Set all his artifacts back to normal-speed timeout */
7171 if (was_total_winner && !cfg.fallenkings_etiquette &&
7172 p_ptr->inventory[i].name1 &&
7173 p_ptr->inventory[i].name1 != ART_RANDART)
7174 a_info[p_ptr->inventory[i].name1].winner = FALSE;
7175
7176 /* If we committed suicide, only drop artifacts */
7177 // if (!p_ptr->alive && !artifact_p(o_ptr)) continue;
7178 if (!p_ptr->alive) {
7179 if (!true_artifact_p(o_ptr)) continue;
7180
7181 /* hack -- total winners do not drop artifacts when they suicide */
7182 // if (!p_ptr->alive && p_ptr->total_winner && artifact_p(&p_ptr->inventory[i]))
7183
7184 /* Artifacts cannot be dropped after all */
7185 /* Don't litter Valinor -- Ring of Phasing must be destroyed anyways */
7186 if ((cfg.anti_arts_hoard) || in_valinor(&p_ptr->wpos)) {
7187 /* set the artifact as unfound */
7188 handle_art_d(o_ptr->name1);
7189
7190 /* Don't drop the artifact */
7191 continue;
7192 }
7193 }
7194
7195 if (!is_admin(p_ptr) && !p_ptr->inval && (p_ptr->max_plv >= cfg.newbies_cannot_drop) &&
7196 /* Don't drop Morgoth's crown or Grond */
7197 !(o_ptr->name1 == ART_MORGOTH) && !(o_ptr->name1 == ART_GROND)
7198 #ifdef IDDC_NO_TRADE_CHEEZE
7199 && !(in_iddc && o_ptr->NR_tradable)
7200 #endif
7201 ) {
7202 #ifdef DEATH_ITEM_SCATTER
7203 /* Apply penalty of death */
7204 if (!artifact_p(o_ptr) && magik(DEATH_ITEM_SCATTER))
7205 away = TRUE;
7206 else
7207 #endif /* DEATH_ITEM_SCATTER */
7208 {
7209 if (p_ptr->wpos.wz) o_ptr->marked2 = ITEM_REMOVAL_NEVER;
7210 else if (istown(&p_ptr->wpos)) o_ptr->marked2 = ITEM_REMOVAL_DEATH_WILD;/* don't litter towns for long */
7211 else o_ptr->marked2 = ITEM_REMOVAL_LONG_WILD;/* don't litter wilderness eternally ^^ */
7212
7213 /* Drop this one */
7214 away = drop_near(o_ptr, 0, &p_ptr->wpos, p_ptr->py, p_ptr->px)
7215 <= 0 ? TRUE : FALSE;
7216 }
7217
7218 if (away) {
7219 int o_idx = 0, x1, y1, try = 500;
7220 cave_type **zcave;
7221 if ((zcave = getcave(&p_ptr->wpos))) /* this should never.. */
7222 while (o_idx <= 0 && try--) {
7223 x1 = rand_int(p_ptr->cur_wid);
7224 y1 = rand_int(p_ptr->cur_hgt);
7225
7226 if (!cave_clean_bold(zcave, y1, x1)) continue;
7227 if (p_ptr->wpos.wz) o_ptr->marked2 = ITEM_REMOVAL_NEVER;
7228 else if (istown(&p_ptr->wpos)) o_ptr->marked2 = ITEM_REMOVAL_DEATH_WILD;/* don't litter towns for long */
7229 else o_ptr->marked2 = ITEM_REMOVAL_LONG_WILD;/* don't litter wilderness eternally ^^ */
7230 o_idx = drop_near(o_ptr, 0, &p_ptr->wpos, y1, x1);
7231 }
7232 }
7233 } else {
7234 /* set the artifact as unfound */
7235 if (true_artifact_p(o_ptr)) handle_art_d(o_ptr->name1);
7236 questitem_d(o_ptr, o_ptr->number);
7237 }
7238
7239 /* No more item */
7240 invwipe(o_ptr);
7241 }
7242
7243 /* Get rid of him if he's a ghost or suffers a no-ghost death */
7244 if ((p_ptr->ghost || (hell && p_ptr->alive)) ||
7245 insanity ||
7246 streq(p_ptr->died_from, "indecisiveness") ||
7247 streq(p_ptr->died_from, "indetermination") ||
7248 ((p_ptr->lives == 1 + 1) && cfg.lifes && p_ptr->alive &&
7249 !(p_ptr->mode & MODE_EVERLASTING))) {
7250 /* Tell players */
7251 if (insanity) {
7252 /* Tell him */
7253 msg_print(Ind, "\374\377RYou die.");
7254 //msg_print(Ind, NULL);
7255 //todo: use 'died_from' (insanity-blinking-style):
7256 msg_format(Ind, "\374\377%c**\377rYou have been destroyed by \377oI\377Gn\377bs\377Ba\377sn\377Ri\377vt\377yy\377r.\377%c**", msg_layout, msg_layout);
7257
7258 s_printf("CHARACTER_TERMINATION: INSANITY race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7259
7260 if (cfg.unikill_format)
7261 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was destroyed by \377m%s\377r.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7262 else
7263 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was destroyed by \377m%s\377r.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7264 s_printf("%s (%d) was destroyed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7265 if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7266 s_printf("(%s was really destroyed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7267
7268 #if CHATTERBOX_LEVEL > 2
7269 if (strstr(p_ptr->died_from, "Farmer Maggot's dog") && magik(50)) {
7270 msg_broadcast(Ind, "Suddenly a thought comes to your mind:");
7271 msg_broadcast(0, "Who let the dogs out?");
7272 } else if (p_ptr->last_words) {
7273 char death_message[80];
7274
7275 (void)get_rnd_line("death.txt", 0, death_message, 80);
7276 msg_print(Ind, death_message);
7277 }
7278 #endif // CHATTERBOX_LEVEL
7279
7280 death_type = DEATH_INSANITY;
7281 if (p_ptr->ghost) {
7282 death_type = DEATH_GHOST;
7283 Send_chardump(Ind, "-ghost");
7284 } else Send_chardump(Ind, "-death");
7285 Net_output1(Ind);
7286 } else if (p_ptr->ghost) {
7287 /* Tell him */
7288 msg_format(Ind, "\374\377a**\377rYour ghost was destroyed by %s.\377a**", p_ptr->died_from);
7289
7290 s_printf("CHARACTER_TERMINATION: GHOSTKILL race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7291
7292 if (cfg.unikill_format) {
7293 if (p_ptr->name[strlen(p_ptr->name) - 1] == 's')
7294 snprintf(buf, sizeof(buf), "\374\377a**\377r%s %s' (%d) ghost was destroyed by %s.\377a**", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7295 else
7296 snprintf(buf, sizeof(buf), "\374\377a**\377r%s %s's (%d) ghost was destroyed by %s.\377a**", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7297 } else {
7298 if (p_ptr->name[strlen(p_ptr->name) - 1] == 's')
7299 snprintf(buf, sizeof(buf), "\374\377a**\377r%s' (%d) ghost was destroyed by %s.\377a**", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7300 else
7301 snprintf(buf, sizeof(buf), "\374\377a**\377r%s's (%d) ghost was destroyed by %s.\377a**", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7302 }
7303 s_printf("%s's (%d) ghost was destroyed by %s for %d damage on %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7304 if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7305 s_printf("(%s's ghost was really destroyed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7306
7307 #if CHATTERBOX_LEVEL > 2
7308 if (p_ptr->last_words) {
7309 char death_message[80];
7310
7311 (void)get_rnd_line("death.txt", 0, death_message, 80);
7312 msg_print(Ind, death_message);
7313 }
7314 #endif // CHATTERBOX_LEVEL
7315
7316 death_type = DEATH_GHOST;
7317 } else {
7318 /* Tell him */
7319 msg_print(Ind, "\374\377RYou die.");
7320 // msg_print(Ind, NULL);
7321 #ifdef MORGOTH_FUNKY_KILL_MSGS /* Might add some atmosphere? (lol) - C. Blue */
7322 if (!strcmp(p_ptr->died_from, "Morgoth, Lord of Darkness")) {
7323 char funky_msg[20];
7324 switch (randint(5)) {
7325 case 1:strcpy(funky_msg,"wasted");break;
7326 case 2:strcpy(funky_msg,"crushed");break;
7327 case 3:strcpy(funky_msg,"shredded");break;
7328 case 4:strcpy(funky_msg,"torn up");break;
7329 case 5:strcpy(funky_msg,"crushed");break; /* again :) */
7330 }
7331 msg_format(Ind, "\374\377%c**\377rYou have been %s by %s.\377%c**", msg_layout, funky_msg, p_ptr->died_from, msg_layout);
7332 if (cfg.unikill_format) {
7333 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was %s by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, funky_msg, p_ptr->died_from, msg_layout);
7334 } else {
7335 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was %s and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, funky_msg, p_ptr->died_from, msg_layout);
7336 }
7337 } else {
7338 #endif
7339 if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7340 #ifdef ENABLE_MAIA
7341 || streq(p_ptr->died_from, "indecisiveness")
7342 #endif
7343 || streq(p_ptr->died_from, "indetermination")
7344 || insanity) {
7345 msg_format(Ind, "\374\377%c**\377rYou have been killed by %s.\377%c**", msg_layout, p_ptr->died_from, msg_layout);
7346 } else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7347 msg_format(Ind, "\374\377%c**\377rYou have been annihilated by %s.\377%c**", msg_layout, p_ptr->died_from, msg_layout);
7348 } else {
7349 msg_format(Ind, "\374\377%c**\377rYou have been vaporized by %s.\377%c**", msg_layout, p_ptr->died_from, msg_layout);
7350 }
7351
7352 if (cfg.unikill_format) {
7353 if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7354 #ifdef ENABLE_MAIA
7355 || streq(p_ptr->died_from, "indecisiveness")
7356 #endif
7357 || streq(p_ptr->died_from, "indetermination")
7358 || insanity)
7359 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was killed by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7360 else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450)))
7361 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was annihilated by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7362 else
7363 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s %s (%d) was vaporized by %s.\377%c**", msg_layout, titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7364 } else {
7365 if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7366 #ifdef ENABLE_MAIA
7367 || streq(p_ptr->died_from, "indecisiveness")
7368 #endif
7369 || streq(p_ptr->died_from, "indetermination")
7370 || insanity)
7371 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was killed and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7372 else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450)))
7373 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was annihilated and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7374 else
7375 snprintf(buf, sizeof(buf), "\374\377%c**\377r%s (%d) was vaporized and destroyed by %s.\377%c**", msg_layout, p_ptr->name, p_ptr->lev, p_ptr->died_from, msg_layout);
7376 }
7377 #ifdef MORGOTH_FUNKY_KILL_MSGS
7378 }
7379 #endif
7380 s_printf("%s (%d) was killed and destroyed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7381 if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7382 s_printf("(%s was really killed and destroyed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7383
7384 s_printf("CHARACTER_TERMINATION: %s race=%s ; class=%s ; trait=%s ; %d deaths\n", pvp ? "PVP" : "NOGHOST", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7385
7386 #if CHATTERBOX_LEVEL > 2
7387 if (p_ptr->last_words) {
7388 char death_message[80];
7389 (void)get_rnd_line("death.txt", 0, death_message, 80);
7390 msg_print(Ind, death_message);
7391 }
7392 #endif // CHATTERBOX_LEVEL
7393 death_type = DEATH_PERMA;
7394 Send_chardump(Ind, "-death");
7395 Net_output1(Ind);
7396 }
7397 #ifdef TOMENET_WORLDS
7398 world_player(p_ptr->id, p_ptr->name, FALSE, TRUE);
7399 #endif
7400
7401 #if (MAX_PING_RECVS_LOGGED > 0)
7402 /* Print last ping reception times */
7403 struct timeval now;
7404 gettimeofday(&now, NULL);
7405 s_printf("PINGS_RECEIVED:");
7406 /* Starting from latest */
7407 for (i = 0; i < MAX_PING_RECVS_LOGGED; i++) {
7408 j = (p_ptr->pings_received_head - i + MAX_PING_RECVS_LOGGED) % MAX_PING_RECVS_LOGGED;
7409 if (p_ptr->pings_received[j].tv_sec) {
7410 s_printf(" %s", timediff(&p_ptr->pings_received[j], &now));
7411 }
7412 }
7413 s_printf("\n");
7414 #endif
7415
7416 if (is_admin(p_ptr)) snprintf(buf, sizeof(buf), "\376\377D%s bids farewell to this plane.", p_ptr->name);
7417
7418 if ((!p_ptr->admin_dm) || (!cfg.secret_dungeon_master)){
7419 #ifdef TOMENET_WORLDS
7420 if (cfg.worldd_pdeath) world_msg(buf);
7421 #endif
7422 msg_broadcast(Ind, buf);
7423 }
7424
7425 /* Reward the killer if it was a PvP-mode char */
7426 if (pvp) {
7427 int killer = name_lookup_quiet(Ind, p_ptr->really_died_from, FALSE, FALSE);
7428
7429 /* reward him again, making restarting easier */
7430 if (p_ptr->max_plv == MID_PVP_LEVEL)
7431 buffer_account_for_achievement_deed(p_ptr, ACHV_PVP_MID);
7432 if (p_ptr->max_plv == MAX_PVP_LEVEL)
7433 buffer_account_for_achievement_deed(p_ptr, ACHV_PVP_MAX);
7434
7435 if (killer) {
7436 if (Players[killer]->max_plv > p_ptr->max_plv) Players[killer]->kills_lower++;
7437 else if (Players[killer]->max_plv < p_ptr->max_plv) Players[killer]->kills_higher++;
7438 else Players[killer]->kills_equal++;
7439
7440 #if 0 /* only reward exp for killing same level or higher players */
7441 if (Players[killer]->max_plv <= p_ptr->max_plv) {
7442 /* note how expfact isn't multiplied, so a difference between the races remains :) */
7443 gain_exp(killer, (player_exp[Players[killer]->lev - 1] - player_exp[Players[killer]->lev - 2]) * (1 + (p_ptr->max_plv - 5) / (Players[killer]->lev - 5)));
7444 }
7445 #else /* reward exp for all player-kills, but less for killing lower level chars */
7446 if (Players[killer]->max_plv <= p_ptr->max_plv) {
7447 /* note how expfact isn't multiplied, so a difference between the races/classes remains, as usual */
7448 gain_exp(killer, (player_exp[Players[killer]->lev - 1] - player_exp[Players[killer]->lev - 2]) * (1 + (p_ptr->max_plv - 5) / (Players[killer]->lev - 5)));
7449 } else {
7450 /* get less exp if player was lower than killer, dropping rapidly */
7451 k = 2 + Players[killer]->lev - p_ptr->max_plv;//2+k; k*k+0; *12/
7452 gain_exp(killer, ((player_exp[Players[killer]->lev - 1] - player_exp[Players[killer]->lev - 2]) * 10) / ((k * k) - 2));
7453 }
7454 #endif
7455
7456 /* get victim's kills credited as own ones >:) */
7457 //wrong code: used for rewards Players[killer]->kills += p_ptr->kills;
7458 #if 0 /* disabled since it doesn't make much sense */
7459 Players[killer]->kills_lower += p_ptr->kills_lower;
7460 Players[killer]->kills_equal += p_ptr->kills_equal;
7461 Players[killer]->kills_higher += p_ptr->kills_higher;
7462 #endif
7463 Players[killer]->kills++;
7464 Players[killer]->kills_own++;
7465
7466 check_killing_reward(killer);
7467 } else { /* killed by monster/trap? still reward nearby pvp players! */
7468 int players_in_area = 0, avg_kills;
7469 for (i = 1; i <= NumPlayers; i++) {
7470 if (i == Ind) continue;
7471 if (is_admin(Players[i])) continue;
7472 if (Players[i]->conn == NOT_CONNECTED) continue;
7473 if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
7474 if (!(Players[i]->mode & MODE_PVP)) continue;
7475 players_in_area++;
7476 }
7477 if (players_in_area) {
7478 /* give everyone a 'share' of the kills */
7479 #if 0 /* round downwards */
7480 avg_kills = p_ptr->kills / players_in_area;
7481 /* at least give 1 kill if player had one */
7482 if (!avg_kills && p_ptr->kills) avg_kills = 1;
7483 #else /* round upwards! generous */
7484 avg_kills = (p_ptr->kills + players_in_area - 1) / players_in_area;
7485 #endif
7486 /* get victim's kills credited as own ones >:) */
7487 for (i = 1; i <= NumPlayers; i++) {
7488 if (i == Ind) continue;
7489 if (is_admin(Players[i])) continue;
7490 if (Players[i]->conn == NOT_CONNECTED) continue;
7491 if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
7492 if (!(Players[i]->mode & MODE_PVP)) continue;
7493 #if 0 /* wrong code (rewards) */
7494 Players[i]->kills += avg_kills;
7495 #else
7496 if (avg_kills) Players[i]->kills++;
7497 #endif
7498 check_killing_reward(i);
7499 }
7500 }
7501 }
7502 } else { /* wasn't a pvp-mode death */
7503 /* copy/paste from above pvp section, just for info */
7504 int killer = name_lookup_quiet(Ind, p_ptr->really_died_from, FALSE, FALSE);
7505 if (killer) {
7506 if (Players[killer]->max_plv > p_ptr->max_plv) Players[killer]->kills_lower++;
7507 else if (Players[killer]->max_plv < p_ptr->max_plv) Players[killer]->kills_higher++;
7508 else Players[killer]->kills_equal++;
7509 //wrong code (rewards) Players[killer]->kills += p_ptr->kills;
7510 #if 0 /* not much sense */
7511 Players[killer]->kills_lower += p_ptr->kills_lower;
7512 Players[killer]->kills_equal += p_ptr->kills_equal;
7513 Players[killer]->kills_higher += p_ptr->kills_higher;
7514 #endif
7515 Players[killer]->kills++;
7516 Players[killer]->kills_own++;
7517
7518 /* no reward outside of PvP xD */
7519 }
7520 }
7521
7522 /* Add to legends log if he was at least 50 or died vs Morgoth */
7523 if (!is_admin(p_ptr)) {
7524 if (p_ptr->total_winner)
7525 l_printf("%s \\{r%s royalty %s (%d) died\n", showdate(), p_ptr->male ? "His" : "Her", p_ptr->name, p_ptr->lev);
7526 else if (p_ptr->wpos.wz && (l_ptr->flags1 & LF1_NO_GHOST))
7527 l_printf("%s \\{r%s (%d) died facing Morgoth\n", showdate(), p_ptr->name, p_ptr->lev);
7528 #ifndef RPG_SERVER
7529 /* for non-ghost deaths, display somewhat "lower" levels (below 50) too */
7530 else if (p_ptr->lev >= 40)
7531 l_printf("%s \\{r%s (%d) died\n", showdate(), p_ptr->name, p_ptr->lev);
7532 #else /* for RPG_SERVER, also display more trivial deaths, so people know the player is up for startup-party again */
7533 else if (p_ptr->lev >= 20)
7534 l_printf("%s \\{r%s (%d) died\n", showdate(), p_ptr->name, p_ptr->lev);
7535 #endif
7536 }
7537
7538 erase_player(Ind, death_type, TRUE);
7539
7540 /* Done */
7541 return;
7542 }
7543
7544 /* --- non-noghost-death: everlasting or more lives left --- */
7545 /* Add to legends log if he was a winner */
7546 if (p_ptr->total_winner && !is_admin(p_ptr) && p_ptr->alive)
7547 l_printf("%s \\{r%s (%d) lost %s royal title by death\n", showdate(), p_ptr->name, p_ptr->lev, p_ptr->male ? "his" : "her");
7548
7549 /* Tell everyone he died */
7550 if (p_ptr->alive) {
7551 if (cfg.unikill_format) {
7552 if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7553 #ifdef ENABLE_MAIA
7554 || streq(p_ptr->died_from, "indecisiveness")
7555 #endif
7556 || streq(p_ptr->died_from, "indetermination")
7557 || insanity) {
7558 /* snprintf(buf, sizeof(buf), "\374\377r%s was killed by %s.", p_ptr->name, p_ptr->died_from); */
7559 /* Add the player lvl to the death message. the_sandman */
7560 snprintf(buf, sizeof(buf), "\374\377r%s %s (%d) was killed by %s", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7561 }
7562 else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7563 /* snprintf(buf, sizeof(buf), "\377r%s was annihilated by %s.", p_ptr->name, p_ptr->died_from); */
7564 snprintf(buf, sizeof(buf), "\374\377r%s %s (%d) was annihilated by %s", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7565 }
7566 else {
7567 snprintf(buf, sizeof(buf), "\374\377r%s %s (%d) was vaporized by %s.", titlebuf, p_ptr->name, p_ptr->lev, p_ptr->died_from);
7568 }
7569 } else {
7570 if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7571 #ifdef ENABLE_MAIA
7572 || streq(p_ptr->died_from, "indecisiveness")
7573 #endif
7574 || streq(p_ptr->died_from, "indetermination")
7575 || insanity) {
7576 /* snprintf(buf, sizeof(buf), "\374\377r%s was killed by %s.", p_ptr->name, p_ptr->died_from); */
7577 /* Add the player lvl to the death message. the_sandman */
7578 snprintf(buf, sizeof(buf), "\374\377r%s (%d) was killed by %s", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7579 }
7580 else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7581 /* snprintf(buf, sizeof(buf), "\377r%s was annihilated by %s.", p_ptr->name, p_ptr->died_from); */
7582 snprintf(buf, sizeof(buf), "\374\377r%s (%d) was annihilated by %s", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7583 }
7584 else {
7585 snprintf(buf, sizeof(buf), "\374\377r%s (%d) was vaporized by %s.", p_ptr->name, p_ptr->lev, p_ptr->died_from);
7586 }
7587 }
7588 s_printf("%s (%d) was killed by %s for %d damage at %d, %d, %d.\n", p_ptr->name, p_ptr->lev, p_ptr->died_from, p_ptr->deathblow, p_ptr->wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wz);
7589 if (!strcmp(p_ptr->died_from, "It") || !strcmp(p_ptr->died_from, "insanity") || p_ptr->image)
7590 s_printf("(%s was really killed by %s.)\n", p_ptr->name, p_ptr->really_died_from);
7591
7592 s_printf("CHARACTER_TERMINATION: NORMAL race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7593 }
7594 else if (p_ptr->iron_winner) {
7595 if (p_ptr->total_winner) {
7596 snprintf(buf, sizeof(buf), "\374\377vThe iron emperor %s has retired to a warm, sunny climate.", p_ptr->name);
7597 if (!is_admin(p_ptr)) l_printf("%s \\{v%s (%d) retired from the iron throne\n", showdate(), p_ptr->name, p_ptr->lev);
7598 } else {
7599 snprintf(buf, sizeof(buf), "\374\377sThe iron champion %s has retired to a warm, sunny climate.", p_ptr->name);
7600 if (!is_admin(p_ptr)) l_printf("%s \\{s%s (%d) retired as an iron champion\n", showdate(), p_ptr->name, p_ptr->lev);
7601 }
7602 s_printf("%s (%d) committed suicide. (Retirement)\n", p_ptr->name, p_ptr->lev);
7603 retire = TRUE;
7604 death_type = DEATH_QUIT;
7605 s_printf("CHARACTER_TERMINATION: RETIREMENT race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7606 }
7607 else if (!p_ptr->total_winner) {
7608 /* assume newb_suicide option for world broadcasts */
7609 if (p_ptr->max_plv == 1) world_broadcast = FALSE;
7610
7611 snprintf(buf, sizeof(buf), "\374\377D%s committed suicide.", p_ptr->name);
7612 s_printf("%s (%d) committed suicide.\n", p_ptr->name, p_ptr->lev);
7613 death_type = DEATH_QUIT;
7614 s_printf("CHARACTER_TERMINATION: SUICIDE race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7615 } else {
7616 if (in_valinor(&p_ptr->wpos)) {
7617 snprintf(buf, sizeof(buf), "\374\377vThe unbeatable %s has retired to the shores of valinor.", p_ptr->name);
7618 if (!is_admin(p_ptr)) l_printf("%s \\{v%s (%d) retired to the shores of valinor\n", showdate(), p_ptr->name, p_ptr->lev);
7619 } else {
7620 snprintf(buf, sizeof(buf), "\374\377vThe unbeatable %s has retired to a warm, sunny climate.", p_ptr->name);
7621 if (!is_admin(p_ptr)) l_printf("%s \\{v%s (%d) retired to a warm, sunny climate\n", showdate(), p_ptr->name, p_ptr->lev);
7622 }
7623 s_printf("%s (%d) committed suicide. (Retirement)\n", p_ptr->name, p_ptr->lev);
7624 retire = TRUE;
7625 death_type = DEATH_QUIT;
7626 s_printf("CHARACTER_TERMINATION: RETIREMENT race=%s ; class=%s ; trait=%s ; %d deaths\n", race_info[p_ptr->prace].title, class_info[p_ptr->pclass].title, trait_info[p_ptr->ptrait].title, p_ptr->deaths);
7627 }
7628
7629 if (is_admin(p_ptr)) {
7630 if (death_type == -1) snprintf(buf, sizeof(buf), "\376\377D%s enters a ghostly state.", p_ptr->name);
7631 else snprintf(buf, sizeof(buf), "\376\377D%s bids farewell to this plane.", p_ptr->name);
7632 }
7633
7634 /* Tell the players */
7635 /* handle the secret_dungeon_master option */
7636 if ((!p_ptr->admin_dm) || (!cfg.secret_dungeon_master)) {
7637 /* handle newbie suicide option by manually doing 'msg_broadcast': */
7638 if (death_type == DEATH_QUIT) {
7639 /* Tell every player */
7640 for (i = 1; i <= NumPlayers; i++) {
7641 if (Players[i]->conn == NOT_CONNECTED) continue;
7642 if (i == Ind) continue;
7643 if (!Players[i]->newb_suicide && p_ptr->max_plv == 1)
7644 msg_format(i, "%c%s", '\376', buf + 1);
7645 else
7646 msg_print(i, buf);
7647 }
7648 } else msg_broadcast(Ind, buf);
7649
7650 #ifdef TOMENET_WORLDS
7651 if (cfg.worldd_pdeath && world_broadcast) world_msg(buf);
7652 #endif
7653 }
7654
7655 #if 0
7656 /* Unown land */
7657 if (p_ptr->total_winner) {
7658 #ifdef NEW_DUNGEON
7659 /* FIXME */
7660 /*
7661 msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7662 wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7663 */
7664 #else
7665 msg_broadcast_format(Ind, "%d(%d) and %d(%d) are no more owned.", p_ptr->own1, p_ptr->own2, p_ptr->own1 * 50, p_ptr->own2 * 50);
7666 wild_info[p_ptr->own1].own = wild_info[p_ptr->own2].own = 0;
7667 #endif
7668 }
7669 #endif
7670
7671 /* No longer a winner */
7672 p_ptr->total_winner = FALSE;
7673
7674 /* Handle suicide */
7675 if (!p_ptr->alive) {
7676 #ifdef TOMENET_WORLDS
7677 world_player(p_ptr->id, p_ptr->name, FALSE, TRUE);
7678 #endif
7679
7680 /* prevent suicide spam, if set in cfg */
7681 check_roller(Ind);
7682
7683 if (!p_ptr->ghost) {
7684 if (retire) Send_chardump(Ind, "-retirement");
7685 else Send_chardump(Ind, "-death");
7686 Net_output1(Ind);
7687 }
7688
7689 erase_player(Ind, death_type, FALSE);
7690
7691 /* Done */
7692 return;
7693 }
7694
7695 /* Tell him */
7696 msg_print(Ind, "\374\377RYou die.");
7697 // msg_print(Ind, NULL);
7698 #if CHATTERBOX_LEVEL > 2
7699 if (p_ptr->last_words) {
7700 char death_message[80];
7701
7702 (void)get_rnd_line("death.txt", 0, death_message, 80);
7703 msg_print(Ind, death_message);
7704 }
7705 #endif // CHATTERBOX_LEVEL
7706
7707 /* Paranoia - ghosts getting destroyed are already caught above */
7708 if (p_ptr->ghost) Send_chardump(Ind, "-ghost"); else
7709 Send_chardump(Ind, "-death");
7710
7711 /* Polymorph back to player */
7712 if (p_ptr->body_monster) do_mimic_change(Ind, 0, TRUE);
7713
7714 /* Cure him from various maladies */
7715 p_ptr->black_breath = FALSE;
7716 if (p_ptr->image) (void)set_image(Ind, 0);
7717 if (p_ptr->blind) (void)set_blind(Ind, 0);
7718 if (p_ptr->paralyzed) (void)set_paralyzed(Ind, 0);
7719 if (p_ptr->confused) (void)set_confused(Ind, 0);
7720 if (p_ptr->poisoned) (void)set_poisoned(Ind, 0, 0);
7721 if (p_ptr->stun) (void)set_stun(Ind, 0);
7722 if (p_ptr->cut) (void)set_cut(Ind, 0, 0);
7723 /* if (p_ptr->food < PY_FOOD_FULL) */
7724 (void)set_food(Ind, PY_FOOD_FULL - 1);
7725
7726 /* Don't have 'vegetable' ghosts running around after equipment was dropped */
7727 p_ptr->safe_sane = TRUE;
7728 p_ptr->update |= PU_SANITY;
7729 update_stuff(Ind);
7730 p_ptr->safe_sane = FALSE;
7731
7732 if ((p_ptr->deathblow < 10) || ((p_ptr->deathblow < p_ptr->mhp / 4) && (p_ptr->deathblow < 100))
7733 #ifdef ENABLE_MAIA
7734 || streq(p_ptr->died_from, "indecisiveness")
7735 #endif
7736 || streq(p_ptr->died_from, "indetermination")
7737 || insanity) {
7738 msg_format(Ind, "\374\377RYou have been killed by %s.", p_ptr->died_from);
7739 }
7740 else if ((p_ptr->deathblow < 30) || ((p_ptr->deathblow < p_ptr->mhp / 2) && (p_ptr->deathblow < 450))) {
7741 msg_format(Ind, "\374\377RYou have been annihilated by %s.", p_ptr->died_from);
7742 }
7743 else {
7744 msg_format(Ind, "\374\377RYou have been vaporized by %s.", p_ptr->died_from);
7745 }
7746
7747 #if (MAX_PING_RECVS_LOGGED > 0)
7748 /* Print last ping reception times */
7749 struct timeval now;
7750 gettimeofday(&now, NULL);
7751 s_printf("PING_RECEIVED:");
7752 /* Starting from latest */
7753 for (i = 0; i < MAX_PING_RECVS_LOGGED; i++) {
7754 j = (p_ptr->pings_received_head - i + MAX_PING_RECVS_LOGGED) % MAX_PING_RECVS_LOGGED;
7755 if (p_ptr->pings_received[j].tv_sec) {
7756 s_printf(" %s", timediff(&p_ptr->pings_received[j], &now));
7757 }
7758 }
7759 s_printf("\n");
7760 #endif
7761
7762 /* Turn him into a ghost */
7763 p_ptr->ghost = 1;
7764 /* Prevent accidental floating up/downwards depending on client option. - C. Blue */
7765 if (p_ptr->safe_float) p_ptr->safe_float_turns = 5;
7766
7767 /* Hack -- drop bones :) */
7768 #ifdef ENABLE_MAIA
7769 /* hackhack: Maiar don't have a real physical body ;) */
7770 if (p_ptr->prace != RACE_MAIA)
7771 #endif
7772 for (i = 0; i < 4; i++) {
7773 object_type forge;
7774 o_ptr = &forge;
7775
7776 invcopy(o_ptr, lookup_kind(TV_SKELETON, i ? SV_BROKEN_BONE : SV_BROKEN_SKULL));
7777 object_known(o_ptr);
7778 object_aware(Ind, o_ptr);
7779 o_ptr->owner = p_ptr->id;
7780 o_ptr->mode = p_ptr->mode;
7781 o_ptr->level = 0;
7782 o_ptr->note = quark_add(format("# of %s", p_ptr->name));
7783 /* o_ptr->note = quark_add(format("#of %s", p_ptr->name));
7784 the_sandman: removed the auto-space-padding on {# inscs */
7785
7786 if (p_ptr->wpos.wz) o_ptr->marked2 = ITEM_REMOVAL_NEVER;
7787 else if (istown(&p_ptr->wpos)) o_ptr->marked2 = ITEM_REMOVAL_DEATH_WILD;/* don't litter towns for long */
7788 else o_ptr->marked2 = ITEM_REMOVAL_LONG_WILD;/* don't litter wilderness eternally ^^ */
7789 (void)drop_near(o_ptr, 0, &p_ptr->wpos, p_ptr->py, p_ptr->px);
7790 }
7791
7792 /* Give him his hit points back */
7793 p_ptr->chp = p_ptr->mhp;
7794 p_ptr->chp_frac = 0;
7795
7796 /* Teleport him */
7797 /* XXX p_ptr->death allows teleportation even when NO_TELE etc. */
7798 teleport_player(Ind, 200, TRUE);
7799
7800 /* Hack -- Give him/her the newbie death guide */
7801 // if (p_ptr->max_plv < 20) /* Now it's for everyone */
7802 {
7803 object_type forge;
7804 o_ptr = &forge;
7805
7806 invcopy(o_ptr, lookup_kind(TV_PARCHMENT, SV_PARCHMENT_DEATH));
7807 object_known(o_ptr);
7808 object_aware(Ind, o_ptr);
7809 o_ptr->owner = p_ptr->id;
7810 o_ptr->mode = p_ptr->mode;
7811 o_ptr->level = 1;
7812 (void)inven_carry(Ind, o_ptr);
7813 }
7814 /* Cancel any WOR spells */
7815 p_ptr->word_recall = 0;
7816
7817 /* He is carrying nothing */
7818 p_ptr->inven_cnt = 0;
7819
7820 p_ptr->deaths++;
7821
7822 /* Remove the death flag */
7823 p_ptr->death = FALSE;
7824
7825 /* Update bonus */
7826 p_ptr->update |= (PU_BONUS);
7827
7828 /* Redraw */
7829 p_ptr->redraw |= (PR_HP | PR_GOLD | PR_BASIC | PR_DEPTH);
7830
7831 /* Notice */
7832 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
7833
7834 /* Windows */
7835 p_ptr->window |= (PW_INVEN | PW_EQUIP);
7836
7837 #if 1 /* Enable, iff newbies-level leading to perma-death is disabled above. */
7838 if (p_ptr->max_plv < cfg.newbies_cannot_drop) {
7839 msg_format(Ind, "\374\377oYou died below level %d, which means that your items didn't drop.", cfg.newbies_cannot_drop);
7840 msg_print(Ind, "\374\377oTherefore, it's recommended to press '\377RQ\377o' to suicide and start over.");
7841 if (p_ptr->wpos.wz < 0) msg_print(Ind, "\374\377oIf you don't like to do that, use '\377R<\377o' to float back to town,");
7842 else if (p_ptr->wpos.wz > 0) msg_print(Ind, "\374\377oIf you don't like to do that, use '\377R>\377o' to float back to town,");
7843 else if (in_bree(&p_ptr->wpos)) msg_print(Ind, "\374\377oIf you don't like to do that, of course you may just continue");
7844 else msg_print(Ind, "\374\377oIf you don't like to do that, just continue by flying back to town");
7845 msg_print(Ind, "\374\377oand enter the temple (\377g4\377o) to be revived and handed some money.");
7846 } else
7847 #endif
7848 if (!p_ptr->warning_death) {
7849 /* normal warning - in dungeon */
7850 if (p_ptr->wpos.wz) {
7851 p_ptr->warning_death = 1;
7852 msg_print(Ind, "\374\377yIf you leave this floor and nobody else stays on it, it will change and");
7853 msg_print(Ind, "\374\377ytherefore all your items would be lost! You now have two choices:");
7854 if (p_ptr->wpos.wz > 0)
7855 msg_print(Ind, "\374\377ya) Float back to town with '\377o>\377y' key and revive yourself in the temple ('\377g4\377y').");
7856 else
7857 msg_print(Ind, "\374\377ya) Float back to town with '\377o<\377y' key and revive yourself in the temple ('\377g4\377y').");
7858 msg_print(Ind, "\374\377yb) Stay here as a ghost and ask someone else to come and revive you.");
7859 } else {
7860 /* specialty - on worldmap */
7861 if (in_bree(&p_ptr->wpos))
7862 msg_print(Ind, "\374\377yRevive yourself by floating over to the temple ('\377g4\377y') and entering it.");
7863 else {
7864 msg_print(Ind, "\374\377yYou now have two choices:");
7865 msg_print(Ind, "\374\377ya) Float back to town and revive yourself by entering the temple ('\377g4\377y').");
7866 msg_print(Ind, "\374\377yb) Stay here as a ghost and ask someone else to come and revive you.");
7867 }
7868 }
7869 }
7870
7871 #if 0 /* currently disabled, because replaced by warning_death */
7872 /* Possibly tell him what to do now */
7873 if (p_ptr->warning_ghost == 0) {
7874 p_ptr->warning_ghost = 1;
7875 msg_print(Ind, "\375\377RHINT: You died! You can wait for someone to revive you or use \377o<\377R or \377o>");
7876 msg_print(Ind, "\375\377R keys to float back to town and revive yourself in the temple (the \377g4\377R).");
7877 msg_print(Ind, "\375\377R If you wish to start over, press \377oSHIFT+q\377R to erase this character.");
7878 s_printf("warning_ghost: %s\n", p_ptr->name);
7879 }
7880 #endif
7881 }
7882
7883 /*
7884 * Resurrect a player
7885 */
7886
7887 /* To prevent people from ressurecting too many times, I am modifying this to give
7888 everyone 1 "freebie", and then to have a p_ptr->level % chance of failing to
7889 ressurect and have your ghost be destroyed.
7890
7891 -APD-
7892
7893 hmm, haven't gotten aroudn to doing this yet...
7894
7895 loss_reduction tells by how much % the GHOST_XP_LOST is reduced (C. Blue).
7896 */
7897 void resurrect_player(int Ind, int loss_factor) {
7898 player_type *p_ptr = Players[Ind];
7899 int reduce;
7900
7901 /* Hack -- the dungeon master can not resurrect */
7902 if (p_ptr->admin_dm) return; // TRUE;
7903
7904 /* Reset ghost flag */
7905 p_ptr->ghost = 0;
7906
7907 disturb(Ind, 1, 0);
7908
7909 /* limits - hack: '0' means use default value */
7910 if (!loss_factor) loss_factor = GHOST_XP_LOST;
7911 /* paranoia */
7912 else if (loss_factor < 0) loss_factor = GHOST_XP_LOST;
7913 else if (loss_factor > 100) loss_factor = GHOST_XP_LOST;
7914
7915 /* Lose some experience */
7916 if (get_skill(p_ptr, SKILL_HCURING) >= 50) loss_factor -= 5;
7917 if (loss_factor < 30) loss_factor = 30;//hardcoded mess
7918
7919 reduce = p_ptr->max_exp;
7920 reduce = reduce > 99999 ?
7921 reduce / 100 * loss_factor : reduce * loss_factor / 100;
7922 p_ptr->max_exp -= reduce;
7923
7924 reduce = p_ptr->exp;
7925 reduce = reduce > 99999 ?
7926 reduce / 100 * loss_factor : reduce * loss_factor / 100;
7927 p_ptr->exp -= reduce;
7928
7929 p_ptr->safe_sane = TRUE;
7930 check_experience(Ind);
7931 p_ptr->update |= PU_SANITY;
7932 update_stuff(Ind);
7933 p_ptr->safe_sane = FALSE;
7934
7935 /* Message */
7936 msg_print(Ind, "\376\377GYou feel life force return to your body!");
7937 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
7938
7939 /* (was in player_death: Take care of ghost suiciding before final resurrection (p_ptr->alive check, C. Blue)) */
7940 /*if (p_ptr->alive && ((p_ptr->lives > 0+1) && cfg.lifes)) p_ptr->lives--;*/
7941 /* Tell him his remaining lifes */
7942 if (!(p_ptr->mode & MODE_EVERLASTING)
7943 && !(p_ptr->mode & MODE_PVP)) {
7944 if (p_ptr->lives > 1+1) p_ptr->lives--;
7945 if (cfg.lifes) {
7946 if (p_ptr->lives == 1+1)
7947 msg_print(Ind, "\376\377GYou have no more resurrections left!");
7948 else
7949 msg_format(Ind, "\376\377GYou have %d resurrections left.", p_ptr->lives-1-1);
7950 }
7951 }
7952
7953 /* Bonus service: Also restore drained exp (for newbies, especially) */
7954 restore_level(Ind);
7955
7956 /* Redraw */
7957 p_ptr->redraw |= (PR_BASIC);
7958
7959 /* Update */
7960 p_ptr->update |= (PU_BONUS);
7961
7962 /* Inform him of instant resurrection option */
7963 if (p_ptr->warning_instares == 0) {
7964 p_ptr->warning_instares = 1;
7965 msg_print(Ind, "\375\377yHINT: You can turn on \377oInstant Resurrection\377y in the temple by pressing '\377or\377y'.");
7966 msg_print(Ind, "\375\377y Make sure to read up on it in the \377oguide\377y to understand pros and cons!");
7967 s_printf("warning_instares: %s\n", p_ptr->name);
7968 }
7969 }
7970
7971 void check_xorders(){
7972 int i, j;
7973 struct player_type *q_ptr;
7974 for (i = 0; i < MAX_XORDERS; i++) {
7975 if (xorders[i].active && xorders[i].id) {
7976 if ((turn - xorders[i].turn) > MAX_XORDER_TURNS) {
7977 for (j = 1; j <= NumPlayers; j++) {
7978 q_ptr = Players[j];
7979 if (q_ptr && q_ptr->xorder_id == xorders[i].id) {
7980 msg_print(j, "\376\377oYou have failed your extermination order!");
7981 q_ptr->xorder_id = 0;
7982 q_ptr->xorder_num = 0;
7983 }
7984 }
7985 xorders[i].active = 0;
7986 xorders[i].id = 0;
7987 xorders[i].type = 0;
7988 }
7989 }
7990 }
7991 }
7992
7993 void del_xorder(int id){
7994 int i;
7995 for (i = 0; i < MAX_XORDERS; i++) {
7996 if (xorders[i].id == id) {
7997 s_printf("Extermination order %d removed\n", id);
7998 xorders[i].active = 0;
7999 xorders[i].id = 0;
8000 xorders[i].type = 0;
8001 }
8002 }
8003 }
8004
8005 /* One player leave a quest (death, deletion) */
8006 void rem_xorder(u16b id){
8007 int i;
8008
8009 s_printf("Player death. Extermination order id: %d\n", id);
8010
8011 if(!id) return;
8012
8013 for (i = 0; i < MAX_XORDERS; i++) {
8014 if (xorders[i].id == id) {
8015 break;
8016 }
8017 }
8018 if (i == MAX_XORDERS) return;
8019 s_printf("Extermination order found in slot %d\n",i);
8020 if (xorders[i].active) {
8021 xorders[i].active--;
8022 s_printf("Remaining active: %d\n", xorders[i].active);
8023 if (!xorders[i].active) {
8024 process_hooks(HOOK_QUEST_FAIL, "d", id);
8025 s_printf("delete call\n");
8026 del_xorder(id);
8027 }
8028 }
8029 }
8030
8031 void kill_xorder(int Ind) {
8032 int i;
8033 u16b id, pos = 9999;
8034 player_type *p_ptr = Players[Ind], *q_ptr;
8035 char temp[160];
8036 bool great, verygreat = FALSE;
8037 u32b resf;
8038
8039 id = p_ptr->xorder_id;
8040 for (i = 0; i < MAX_XORDERS; i++) {
8041 if (xorders[i].id == id) {
8042 pos = i;
8043 break;
8044 }
8045 }
8046 // if (pos == -1) return; /* it's UNsigned :) */
8047 if (pos == 9999) return;
8048
8049 process_hooks(HOOK_QUEST_FINISH, "d", Ind);
8050
8051 if (xorders[i].flags & QUEST_RACE) {
8052 snprintf(temp, 160, "\374\377y%s has carried out a%s %s extermination order!",
8053 p_ptr->name,
8054 is_a_vowel(*(r_name + r_info[xorders[pos].type].name)) ? "n" : "",
8055 r_name + r_info[xorders[pos].type].name);
8056 msg_broadcast(Ind, temp);
8057 }
8058 if (xorders[i].flags & QUEST_GUILD) {
8059 hash_entry *temphash;
8060 snprintf(temp, 160, "\374\377y%s has carried out the %s extermination order!", p_ptr->name, r_name + r_info[xorders[pos].type].name);
8061 if ((temphash = lookup_player(xorders[i].creator)) && temphash->guild) {
8062 guild_msg(temphash->guild ,temp);
8063 if (!p_ptr->guild) {
8064 guild_msg_format(temphash->guild, "\374\377%c%s is now a guild member!", COLOUR_CHAT_GUILD, p_ptr->name);
8065 guilds[temphash->guild].members++;
8066 msg_format(Ind, "\374\377yYou've been added to '\377%c%s\377w'.", COLOUR_CHAT_GUILD, guilds[temphash->guild].name);
8067 p_ptr->guild = temphash->guild;
8068 p_ptr->guild_dna = guilds[p_ptr->guild].dna;
8069 clockin(Ind, 3); /* set in db */
8070 }
8071 else if (p_ptr->guild == temphash->guild) {
8072 guild_msg_format(temphash->guild, "\374\377%c%s has carried out the extermination order!", COLOUR_CHAT_GUILD, p_ptr->name);
8073 }
8074 }
8075 } else {
8076 object_type forge, *o_ptr = &forge;
8077 int avg;
8078
8079 msg_format(Ind, "\374\377yYou have carried out the %s extermination order!", r_name + r_info[xorders[pos].type].name);
8080 s_printf("r_info quest: %s won the %s extermination order\n", p_ptr->name, r_name + r_info[xorders[pos].type].name);
8081 strcpy(temp, r_name + r_info[xorders[pos].type].name);
8082 strcat(temp, " extermination");
8083 unique_quark = quark_add(temp);
8084
8085 /* grant verygreat rerolls for better value? */
8086 avg = ((r_info[xorders[pos].type].level * 2) + (p_ptr->lev * 4)) / 2;
8087 avg = avg > 100 ? 100 : avg;
8088 // if (great && p_ptr->lev >= 25) verygreat = magik(r_info[xorders[pos].type].level - (5 - (p_ptr->lev / 5)));
8089 // if (great) verygreat = magik(((r_info[xorders[pos].type].level * 2) + (p_ptr->lev * 4)) / 5);
8090 avg /= 2; avg = 540 / (57 - avg) + 5; /* same as exp calculation ;) phew, Heureka.. (14..75) */
8091
8092 /* boost quest rewards for the iron price */
8093 #ifndef RPG_SERVER
8094 if (in_irondeepdive(&p_ptr->wpos)) {
8095 #endif
8096 great = TRUE;
8097 verygreat = magik(avg);
8098 resf = RESF_LOW2;
8099 #ifndef RPG_SERVER
8100 } else {
8101 great = magik(50 + p_ptr->lev * 2);
8102 if (great) verygreat = magik(avg);
8103 resf = RESF_LOW;
8104 }
8105 #endif
8106
8107 #if 0 /* needs more care, otherwise acquirement could even be BETTER than create_reward, depending on RESF.. */
8108 create_reward(Ind, o_ptr, getlevel(&p_ptr->wpos), getlevel(&p_ptr->wpos), great, verygreat, resf, 3000);
8109 if (!o_ptr->note) o_ptr->note = quark_add(temp);
8110 o_ptr->note_utag = strlen(temp);
8111 inven_carry(Ind, o_ptr);
8112 #else
8113 acquirement_direct(o_ptr, &p_ptr->wpos, great, verygreat, resf);
8114 //s_printf("object rewarded %d,%d,%d\n", o_ptr->tval, o_ptr->sval, o_ptr->k_idx);
8115 inven_carry(Ind, o_ptr);
8116 #endif
8117 unique_quark = 0;
8118 }
8119
8120 for (i = 1; i <= NumPlayers; i++) {
8121 q_ptr = Players[i];
8122 if (q_ptr && q_ptr->xorder_id == id) {
8123 q_ptr->xorder_id = 0;
8124 q_ptr->xorder_num = 0;
8125 }
8126 }
8127 del_xorder(id);
8128 }
8129
8130 s16b questid = 1;
8131
8132 bool add_xorder(int Ind, int target, u16b type, u16b num, u16b flags) {
8133 int i, j;
8134 bool added = FALSE;
8135 player_type *p_ptr = Players[target], *q_ptr;
8136 if (!p_ptr) return(FALSE);
8137
8138 process_hooks(HOOK_GEN_QUEST, "d", Ind);
8139
8140 for (i = 0; i < MAX_XORDERS; i++) {
8141 if (!xorders[i].active) {
8142 xorders[i].active = 0;
8143 xorders[i].id = questid;
8144 xorders[i].type = type;
8145 xorders[i].flags = flags;
8146 xorders[i].turn = turn;
8147 added = TRUE;
8148 break;
8149 }
8150 }
8151 if (!added) {
8152 msg_print(Ind, "Sorry, no more extermination orders are available at this time.");
8153 return(FALSE);
8154 }
8155 added = 0;
8156
8157 /* give it only to the one original target player */
8158 j = target;
8159 q_ptr = Players[j];
8160 #ifndef RPG_SERVER
8161 if (q_ptr->lev < 5 && !in_irondeepdive(&q_ptr->wpos)) return(FALSE); /* level 5 is minimum to do quests */
8162 #else
8163 if (q_ptr->lev < 3) return(FALSE);
8164 #endif
8165 q_ptr->xorder_id = questid;
8166 q_ptr->xorder_num = num;
8167 clockin(j, 4); /* register that player */
8168 if ((flags & QUEST_GUILD))
8169 msg_print(j, "\374\377oYou have been given an extermination order from your guild\377y!");
8170 else
8171 msg_print(j, "\376\377oYou have been given a extermination order\377y!");
8172 // msg_format(j, "\377oFind and kill \377y%d \377g%s%s\377y!", num, r_name+r_info[type].name, flags&QUEST_GUILD?"":" \377obefore any other player");
8173 msg_format(j, "\376\377oFind and kill \377y%d \377g%s\377o (level %d)!", num, r_name + r_info[type].name, r_info[type].level);
8174 msg_format(Ind, "\376\377oThe remaining time to carry it out is \377y%d\377o minutes.", MAX_XORDER_TURNS / (cfg.fps * 60));
8175 xorders[i].active++;
8176
8177 if (!xorders[i].active) {
8178 del_xorder(questid);
8179 return(FALSE);
8180 }
8181 s_printf("Added extermination order id %d (players %d), target %d (%s): %d x %s\n",
8182 xorders[i].id, xorders[i].active, target, p_ptr != NULL ? p_ptr->name : "NULL",
8183 num, r_name + r_info[type].name);
8184 questid++;
8185 if (questid == 0) questid = 1;
8186 if (target != Ind) {
8187 if (flags & QUEST_GUILD) {
8188 guild_msg_format(Players[Ind]->guild, "\374\377%c%s has been given an extermination order!", COLOUR_CHAT_GUILD, p_ptr->name);
8189 }
8190 else msg_format(Ind, "Extermination order given to %s", p_ptr->name);
8191 xorders[i].creator = Players[Ind]->id;
8192 }
8193 return(TRUE);
8194 }
8195
8196 /* prepare some quest parameters for a standard kill quest */
8197 bool prepare_xorder(int Ind, int j, u16b flags, int *level, u16b *type, u16b *num){
8198 int r = *type, i = *num, lev = *level, k = 0;
8199
8200 if (Players[j]->xorder_id) {
8201 for (i = 0; i < MAX_XORDERS; i++) {
8202 if (xorders[i].id == Players[j]->xorder_id) {
8203 if (j == Ind)
8204 msg_format(Ind, "\376\377oYour %sorder is to exterminate \377y%d \377g%s\377o (level %d).",
8205 (xorders[i].flags & QUEST_GUILD) ? "guild's " : "", Players[Ind]->xorder_num,
8206 r_name + r_info[xorders[i].type].name, r_info[xorders[i].type].level);
8207 msg_format(Ind, "\376\377oThe remaining time to carry it out is \377y%d\377o minutes.", (MAX_XORDER_TURNS - (turn - xorders[i].turn)) / (cfg.fps * 60));
8208 return FALSE;
8209 }
8210 }
8211 }
8212
8213 /* don't start too early -C. Blue */
8214 #ifndef RPG_SERVER
8215 if (Players[j]->lev < 5 && !in_irondeepdive(&Players[j]->wpos)) {
8216 msg_print(Ind, "\377oYou need to be level 5 or higher to receive an extermination order!");
8217 #else /* for ironman there's no harm in allowing early quests */
8218 if (Players[j]->lev < 3) {
8219 msg_print(Ind, "\377oYou need to be level 3 or higher to receive an extermination order!");
8220 #endif
8221 return FALSE;
8222 }
8223
8224 /* plev 1..50 -> mlev 1..100 (!) */
8225 if (lev <= 50) lev += (lev * lev) / 83;
8226 else lev = 80 + rand_int(20);
8227
8228 get_mon_num_hook = xorder_aux;
8229 get_mon_num_prep(0, NULL);
8230 i = 2 + randint(5);
8231
8232 do {
8233 r = get_mon_num(lev, lev - 10); //reduce OoD chance slightly
8234
8235 k++;
8236 if (k > 100) lev--;
8237 } while (((lev - 5) > r_info[r].level && lev >= 5) ||
8238 (r_info[r].flags1 & RF1_UNIQUE) ||
8239 (r_info[r].flags7 & RF7_MULTIPLY) ||
8240 !r_info[r].level); /* "no town quests" ;) */
8241 // r_info[r].level <= 2); /* no Training Tower quests */
8242
8243 /* easier in Ironman environments */
8244 #ifndef RPG_SERVER
8245 if (in_irondeepdive(&Players[j]->wpos)) {
8246 #endif
8247 if (lev < 40) {
8248 if (r_info[r].flags1 & RF1_FRIENDS) i = i + 3 + randint(4);
8249 /* very easy for very low level non-friends quests */
8250 else if (lev < 20) i = (i + 1) / 2;
8251 } else {
8252 if (r_info[r].flags1 & RF1_FRIENDS) i = i + 9 + randint(5);
8253 if (i > 6) i--;
8254 if (i > 4) i--;
8255 }
8256 #ifndef RPG_SERVER
8257 /* pack monsters require a high number, so 2-3 packs must be located */
8258 } else if (r_info[r].flags1 & RF1_FRIENDS) i = i + 11 + randint(7);
8259 #endif
8260
8261 /* Hack: If (non-)FRIENDS variant exists, use the first one (usually the non-FRIENDS one) */
8262 if (r_info[r].dup_idx) r = r_info[r].dup_idx;
8263
8264 *level = lev; *type = r; *num = i;
8265 return TRUE;
8266 }
8267
8268
8269
8270 /*
8271 * Decreases monsters hit points, handling monster death.
8272 *
8273 * We return TRUE if the monster has been killed (and deleted).
8274 *
8275 * We announce monster death (using an optional "death message"
8276 * if given, and a otherwise a generic killed/destroyed message).
8277 *
8278 * Only "physical attacks" can induce the "You have slain" message.
8279 * Missile and Spell attacks will induce the "dies" message, or
8280 * various "specialized" messages. Note that "You have destroyed"
8281 * and "is destroyed" are synonyms for "You have slain" and "dies".
8282 *
8283 * Hack -- unseen monsters yield "You have killed it." message.
8284 *
8285 * Added fear (DGK) and check whether to print fear messages -CWS
8286 *
8287 * Genericized name, sex, and capitilization -BEN-
8288 *
8289 * As always, the "ghost" processing is a total hack.
8290 *
8291 * Hack -- we "delay" fear messages by passing around a "fear" flag.
8292 *
8293 * XXX XXX XXX Consider decreasing monster experience over time, say,
8294 * by using "(m_exp * m_lev * (m_lev)) / (p_lev * (m_lev + n_killed))"
8295 * instead of simply "(m_exp * m_lev) / (p_lev)", to make the first
8296 * monster worth more than subsequent monsters. This would also need
8297 * to induce changes in the monster recall code.
8298 */
8299 bool mon_take_hit(int Ind, int m_idx, int dam, bool *fear, cptr note) {
8300 player_type *p_ptr = Players[Ind];
8301
8302 monster_type *m_ptr = &m_list[m_idx];
8303 monster_race *r_ptr = race_inf(m_ptr);
8304
8305 s64b new_exp, new_exp_frac;
8306 s64b tmp_exp;
8307 long skill_trauma = get_skill(p_ptr, SKILL_TRAUMATURGY) * SKILL_STEP;
8308 long scale_trauma = 0;
8309 bool old_tacit = suppress_message;
8310
8311 // int dun_level2 = getlevel(&p_ptr->wpos);
8312 dungeon_type *dt_ptr2 = getdungeon(&p_ptr->wpos);
8313 #if 0
8314 int dun_type2;
8315 dungeon_info_type *d_ptr2 = NULL;
8316 if (p_ptr->wpos.wz) {
8317 dun_type2 = dt_ptr2->type;
8318 d_ptr2 = &d_info[dun_type2];
8319 }
8320 #endif
8321
8322 p_ptr->test_count++;
8323 p_ptr->test_dam += dam;
8324
8325 /* break charmignore */
8326 if (m_ptr->charmedignore) {
8327 Players[m_ptr->charmedignore]->mcharming--;
8328 m_ptr->charmedignore = 0;
8329 }
8330
8331 /* Redraw (later) if needed */
8332 update_health(m_idx);
8333
8334 /* Change monster's highest player encounter - mode 1+ : a player targetted this monster */
8335 if (!in_bree(&m_ptr->wpos)) { /* not in Bree, because of Halloween :) */
8336 if (m_ptr->henc < p_ptr->max_lev) m_ptr->henc = p_ptr->max_lev;
8337 if (m_ptr->henc_top < (p_ptr->max_lev + p_ptr->max_plv) / 2) m_ptr->henc_top = (p_ptr->max_lev + p_ptr->max_plv) / 2;
8338 if (m_ptr->henc < p_ptr->supp) m_ptr->henc = p_ptr->supp;
8339 if (m_ptr->henc_top < (p_ptr->max_lev + p_ptr->supp_top) / 2) m_ptr->henc_top = (p_ptr->max_lev + p_ptr->supp_top) / 2;
8340 }
8341
8342 /* Traumaturgy skill - C. Blue */
8343 if (dam && skill_trauma &&
8344 /* los(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) && */
8345 /* projectable(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx, MAX_RANGE) && */
8346 target_able(Ind, m_idx) &&
8347 (!(r_ptr->flags3 & RF3_UNDEAD)) &&
8348 (!(r_ptr->flags3 & RF3_NONLIVING)) &&
8349 (!(strchr("AEgv", r_ptr->d_char))))
8350 {
8351 /* difficult to balance, due to the different damage effects of spells- might need some changes */
8352 long gain = scale_trauma;
8353 gain = (dam/20 > gain ? gain : dam/20);//50
8354 if (gain > m_ptr->hp) gain = m_ptr->hp;
8355 if (!gain && magik(dam * 5)) gain = 1; /* no perma-supply for level 1 mana bolts for now */
8356
8357 if (gain && (p_ptr->csp < p_ptr->msp)) {
8358 msg_print(Ind, "You draw energy from the pain of your opponent.");
8359 p_ptr->csp += gain;
8360 if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;
8361 p_ptr->redraw |= (PR_MANA);
8362 }
8363 }
8364
8365 /* Some monsters are immune to death */
8366 if (r_ptr->flags7 & RF7_NO_DEATH) return FALSE;
8367
8368 /* Wake it up */
8369 m_ptr->csleep = 0;
8370
8371 /* for when a quest giver turned non-invincible */
8372 #if 0
8373 if (m_ptr->questor) {
8374 if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
8375 if (q_info[m_ptr->quest].stage[q_info[m_ptr->quest].cur_stage].questor_hostility[m_ptr->questor_idx] &&
8376 m_ptr->hp - dam <= q_info[m_ptr->quest].stage[q_info[m_ptr->quest].cur_stage].questor_hostility[m_ptr->questor_idx]->hostile_revert_hp)
8377 quest_questor_reverts(m_ptr->quest, m_ptr->questor_idx, &m_ptr->wpos);
8378 } else {
8379 s_printf("QUESTOR DEPRECATED (monster_dead3)\n");
8380 }
8381 }
8382 #else
8383 if (m_ptr->questor && m_ptr->hp - dam <= m_ptr->limit_hp) {
8384 if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx)
8385 quest_questor_reverts(m_ptr->quest, m_ptr->questor_idx, &m_ptr->wpos);
8386 else
8387 s_printf("QUESTOR DEPRECATED (monster_dead3)\n");
8388 }
8389 #endif
8390
8391 /* Hurt it */
8392 m_ptr->hp -= dam;
8393
8394 /* record the data for use in C_BLUE_AI */
8395 p_ptr->dam_turn[0] += (m_ptr->hp < dam) ? m_ptr->hp : dam;
8396
8397 /* It is dead now */
8398 if (m_ptr->hp < 0) {
8399 #ifdef ARCADE_SERVER
8400 cave_set_feat(&m_ptr->wpos, m_ptr->fy, m_ptr->fx, 172); /* drop "blood"? */
8401 if(m_ptr->hp < -1000) {
8402
8403 object_type forge, *o_ptr;
8404 o_ptr = &forge;
8405
8406 int i, head, arm, leg, part, ok;
8407 head = arm = leg = part = 0;
8408 for (i = 1; i < 5; i++) {
8409 ok = 0;
8410 while(ok == 0) {
8411 ok = 1;
8412 part = randint(4);
8413 if(part == 1 && head == 1)
8414 ok = 0;
8415 if(part == 2 && arm == 2)
8416 ok = 0;
8417 if(part == 4 && leg == 2)
8418 ok = 0;
8419 }
8420 if(part == 1)
8421 head++;
8422 if(part == 2)
8423 arm++;
8424 if(part == 4)
8425 leg++;
8426 invcopy(o_ptr, lookup_kind(TV_SKELETON, part));
8427 object_known(o_ptr);
8428 o_ptr->owner = p_ptr->id;
8429 o_ptr->mode = p_ptr->mode;
8430 o_ptr->level = 1;
8431 o_ptr->marked2 = ITEM_REMOVAL_NORMAL;
8432 (void)drop_near(o_ptr, 0, &m_ptr->wpos, m_ptr->fy, m_ptr->fx);
8433 }
8434 }
8435 #endif
8436
8437 char m_name[MNAME_LEN];
8438 dun_level *l_ptr = getfloor(&p_ptr->wpos);
8439
8440
8441 /* prepare for experience calculation further down */
8442 if (m_ptr->level == 0) tmp_exp = r_ptr->mexp;
8443 else tmp_exp = r_ptr->mexp * m_ptr->level;
8444
8445 /* for when a quest giver turned non-invincible */
8446 if (m_ptr->questor) {
8447 if (q_info[m_ptr->quest].defined && q_info[m_ptr->quest].questors > m_ptr->questor_idx) {
8448 if (q_info[m_ptr->quest].questor[m_ptr->questor_idx].exp != -1)
8449 tmp_exp = q_info[m_ptr->quest].questor[m_ptr->questor_idx].exp * m_ptr->level;
8450 } else {
8451 s_printf("QUESTOR DEPRECATED (monster_deatd2)\n");
8452 }
8453 }
8454
8455
8456 /* for obtaining statistical IDDC information: */
8457 if (l_ptr) l_ptr->monsters_killed++;
8458
8459 /* Hack -- remove possible suppress flag */
8460 suppress_message = FALSE;
8461
8462 /* Extract monster name */
8463 monster_desc(Ind, m_name, m_idx, 0);
8464
8465 #ifdef USE_SOUND_2010
8466 #else
8467 sound(Ind, SOUND_KILL);
8468 #endif
8469
8470 /* Death by Missile/Spell attack */
8471 /* DEG modified spell damage messages. */
8472 if (note) {
8473 msg_format_near(Ind, "\377y%^s%s from \377g%d \377ydamage.", m_name, note, dam);
8474 msg_format(Ind, "\377y%^s%s from \377g%d \377ydamage.", m_name, note, dam);
8475 }
8476
8477 /* Death by physical attack -- invisible monster */
8478 else if (!p_ptr->mon_vis[m_idx]) {
8479 msg_format_near(Ind, "\377y%^s has been killed from \377g%d \377ydamage by %s.", m_name, dam, p_ptr->name);
8480 msg_format(Ind, "\377yYou have killed %s.", m_name);
8481 }
8482
8483 /* Death by Physical attack -- non-living monster */
8484 else if ((r_ptr->flags3 & RF3_DEMON) ||
8485 (r_ptr->flags3 & RF3_UNDEAD) ||
8486 (r_ptr->flags2 & RF2_STUPID) ||
8487 (strchr("Evg", r_ptr->d_char))) {
8488 msg_format_near(Ind, "\377y%^s has been destroyed from \377g%d \377ydamage by %s.", m_name, dam, p_ptr->name);
8489 msg_format(Ind, "\377yYou have destroyed %s.", m_name);
8490 }
8491
8492 /* Death by Physical attack -- living monster */
8493 else {
8494 msg_format_near(Ind, "\377y%^s has been slain from \377g%d \377ydamage by %s.", m_name, dam, p_ptr->name);
8495 msg_format(Ind, "\377yYou have slain %s.", m_name);
8496 }
8497
8498 /* Check if it's cloned unique, ie "someone else's spawn" */
8499 if ((r_ptr->flags1 & RF1_UNIQUE) && p_ptr->r_killed[m_ptr->r_idx] == 1)
8500 m_ptr->clone = 90; /* still allow some experience to be gained */
8501
8502 /* Generate treasure and give kill credit */
8503 monster_death(Ind, m_idx);
8504
8505
8506 /* experience calculation: gain 2 decimal digits (for low-level exp'ing) */
8507 tmp_exp *= 100;
8508
8509 /* Award players of disadvantageous situations */
8510 if (l_ptr) {
8511 int factor = 100;
8512 if (l_ptr->flags1 & LF1_NO_MAGIC) factor += 10;
8513 if (l_ptr->flags1 & LF1_NO_MAP) factor += 15;
8514 if (l_ptr->flags1 & LF1_NO_MAGIC_MAP) factor += 10;
8515 if (l_ptr->flags1 & LF1_NO_DESTROY) factor += 5;
8516 if (l_ptr->flags1 & LF1_NO_GENO) factor += 5;
8517
8518 tmp_exp = (tmp_exp * factor) / 100;
8519 }
8520
8521 if (p_ptr->wpos.wz) {
8522 int factor = 100;
8523 if (dt_ptr2->flags1 & DF1_NO_UP) factor += 5;
8524 if (dt_ptr2->flags2 & DF2_NO_RECALL_INTO) factor += 5;
8525 if (dt_ptr2->flags1 & DF1_NO_RECALL) factor += 10;
8526 if (dt_ptr2->flags1 & DF1_FORCE_DOWN) factor += 10;
8527 if (dt_ptr2->flags2 & DF2_IRON) factor += 15;
8528 if (dt_ptr2->flags2 & DF2_HELL) factor += 10;
8529 if (dt_ptr2->flags2 & DF2_NO_DEATH) factor -= 50;
8530
8531 if (dt_ptr2->flags3 & DF3_EXP_5) factor += 5;
8532 if (dt_ptr2->flags3 & DF3_EXP_10) factor += 10;
8533 if (dt_ptr2->flags3 & DF3_EXP_20) factor += 20;
8534
8535 #ifdef DUNGEON_VISIT_BONUS
8536 if (!(dt_ptr2->flags3 & DF3_NO_DUNGEON_BONUS))
8537 switch (dungeon_bonus[dt_ptr2->id]) {
8538 case 3: factor += 20; break;
8539 case 2: factor += 13; break;
8540 case 1: factor += 7; break;
8541 }
8542 #endif
8543
8544 tmp_exp = (tmp_exp * factor) / 100;
8545 }
8546
8547 if (p_ptr->wpos.wz != 0) {
8548 /* Monsters in the Nether Realm give extra-high exp,
8549 +2% per floor! (C. Blue) */
8550 if (dt_ptr2->type == DI_NETHER_REALM)
8551 tmp_exp = ((((-p_ptr->wpos.wz) * 2) + 100) * tmp_exp) / 100;
8552 }
8553
8554 /* factor in clone state */
8555 tmp_exp = (tmp_exp * (100 - m_ptr->clone)) / 100;
8556
8557 /* Split experience if in a party */
8558 if (p_ptr->party == 0 || p_ptr->ghost) {
8559 /* Don't allow cheap support from super-high level characters */
8560 if (cfg.henc_strictness && !p_ptr->total_winner &&
8561 /* p_ptr->lev more logical but harsh: */
8562 #if 1 /* player should always seek not too high-level party members compared to player's current real level? */
8563 m_ptr->henc - p_ptr->max_lev > MAX_PARTY_LEVEL_DIFF + 1)
8564 #else /* players may seek higher-level party members to team up with if he's died before? Weird combination so not recommended! */
8565 m_ptr->henc - p_ptr->max_plv > MAX_PARTY_LEVEL_DIFF + 1)
8566 #endif
8567 tmp_exp = 0; /* zonk */
8568
8569 else {
8570 /* Higher characters who farm monsters on low levels compared to
8571 their clvl will gain less exp. */
8572 if (!in_irondeepdive(&p_ptr->wpos))
8573 tmp_exp = det_exp_level(tmp_exp, p_ptr->lev, getlevel(&p_ptr->wpos));
8574
8575 /* Give some experience, undo 2 extra digits */
8576 new_exp = tmp_exp / p_ptr->lev / 100;
8577
8578 /* Give fractional experience, undo 2 extra digits (*100L instead of *10000L) */
8579 new_exp_frac = ((tmp_exp - new_exp * p_ptr->lev * 100)
8580 * 100L) / p_ptr->lev + p_ptr->exp_frac;
8581
8582 /* Never get too much exp off a monster
8583 due to high level difference,
8584 make exception for low exp boosts like "holy jackal" */
8585 if ((new_exp > r_ptr->mexp * 4) && (new_exp > 200)) {
8586 new_exp = r_ptr->mexp * 4;
8587 new_exp_frac = 0;
8588 }
8589
8590 /* Keep track of experience */
8591 if (new_exp_frac >= 10000L) {
8592 new_exp++;
8593 p_ptr->exp_frac = new_exp_frac - 10000L;
8594 } else {
8595 p_ptr->exp_frac = new_exp_frac;
8596 p_ptr->redraw |= PR_EXP; //EXP_BAR_FINESCALE
8597 }
8598
8599 /* Gain experience */
8600 if (new_exp) {
8601 if (!(p_ptr->mode & MODE_PVP)) gain_exp(Ind, new_exp);
8602 } else if (!p_ptr->warning_fracexp && tmp_exp) {
8603 msg_print(Ind, "\374\377ySome monsters give less than 1 experience point, but you still gain a bit!");
8604 s_printf("warning_fracexp: %s\n", p_ptr->name);
8605 p_ptr->warning_fracexp = 1;
8606 }
8607 }
8608 } else {
8609 /* Give experience to that party */
8610 /* Seemingly it's severe to cloning, but maybe it's ok :) */
8611 // if (!player_is_king(Ind) && !m_ptr->clone) party_gain_exp(Ind, p_ptr->party, tmp_exp);
8612 /* Since players won't share exp if leveldiff > MAX_PARTY_LEVEL_DIFF (7)
8613 I see ne problem with kings sharing exp.
8614 Otherwise Nether Realm parties are punished.. */
8615 // if (!player_is_king(Ind)) party_gain_exp(Ind, p_ptr->party, tmp_exp);
8616 //add 2 extra digits to r_ptr->mexp too by multiplying by 100, to match tmp_exp shift
8617 if (!(p_ptr->mode & MODE_PVP)) party_gain_exp(Ind, p_ptr->party, tmp_exp, r_ptr->mexp * 100, m_ptr->henc, m_ptr->henc_top);
8618 }
8619
8620
8621 /*
8622 * Necromancy skill regenerates you
8623 * Cannot drain an undead or nonliving monster
8624 */
8625 if ((get_skill(p_ptr, SKILL_NECROMANCY)) &&
8626 (!(r_ptr->flags3 & RF3_UNDEAD)) &&
8627 (!(r_ptr->flags3 & RF3_NONLIVING)) &&
8628 target_able(Ind, m_idx) && !p_ptr->ghost) /* Target must be in LoS */
8629 {
8630 /* int gain = (r_ptr->level *
8631 get_skill_scale(p_ptr, SKILL_NECROMANCY, 100)) / 100 +
8632 get_skill(p_ptr, SKILL_NECROMANCY); */
8633 long gain, gain_sp, skill; /* let's make it more complicated - gain HP and SP now - C. Blue */
8634
8635 skill = get_skill_scale(p_ptr, SKILL_NECROMANCY, 50);
8636 gain = get_skill_scale(p_ptr, SKILL_NECROMANCY, 100);
8637
8638 gain = (m_ptr->level > gain ? gain : m_ptr->level);
8639 gain_sp = gain;
8640
8641 if (skill >= 15) gain = (2 + gain) * (2 + gain) * (2 + gain) / 327;
8642 else gain = ((3 + skill) * (3 + skill) - 9) / 21;
8643
8644 if (!gain) gain = 1; /* level 0 monsters (and super-low skill) give some energy too */
8645
8646 #if 0 /* strange values I guess */
8647 if (gain_sp >= 60) gain_sp = (gain_sp - 60) * 20 + 100;
8648 else if (gain_sp >= 40) gain_sp = (gain_sp - 40) * 4 + 20;
8649 else if (gain_sp >= 30) gain_sp = (gain_sp - 30) + 7;
8650 else if (gain_sp >= 20) gain_sp = (gain_sp - 20) / 2 + 2;
8651 else gain_sp /= 10;
8652 if (!gain_sp && magik(25)) gain_sp = 1; /* level 0 monsters have chance to give energy too */
8653 #else
8654 gain_sp = ((gain_sp + 1) * (gain_sp + 1)) / 50;
8655 if (!gain_sp) gain_sp = 1; /* level 0 monsters give energy */
8656 #endif
8657
8658 if ((p_ptr->chp < p_ptr->mhp) || (p_ptr->csp < p_ptr->msp)) {
8659 msg_print(Ind, "You absorb the energy of the dying soul.");
8660 hp_player_quiet(Ind, gain, TRUE);
8661 p_ptr->csp += gain_sp;
8662 if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp;
8663 p_ptr->redraw |= (PR_MANA);
8664 }
8665 }
8666
8667 /* RANGED ATTACKS ONLY vampire feeding! */
8668 /* Vampires feed off the life force! (if any) */
8669 // mimic forms for vampires/bats: 432, 520, 521, 623, 989
8670 if (p_ptr->vamp_fed_midx == m_idx) p_ptr->vamp_fed_midx = 0;
8671 else if (p_ptr->prace == RACE_VAMPIRE &&
8672 !((r_ptr->flags3 & RF3_UNDEAD) ||
8673 //(r_ptr->flags3 & RF3_DEMON) ||
8674 (r_ptr->flags3 & RF3_NONLIVING) ||
8675 (strchr("Egv", r_ptr->d_char)))
8676 /* not too far away? */
8677 && (ABS(m_ptr->fx - p_ptr->px) <= 1 && ABS(m_ptr->fy - p_ptr->py) <= 1)) {
8678 int feed = m_ptr->maxhp + 100;
8679 feed = (6 - (300 / feed)) * 100;//300..600
8680 if (r_ptr->flags3 & RF3_DEMON) feed /= 2;
8681 if (r_ptr->d_char == 'A') feed /= 3;
8682 /* Never get gorged */
8683 feed += p_ptr->food;
8684 if (feed >= PY_FOOD_MAX) feed = PY_FOOD_MAX - 1;
8685 set_food(Ind, feed);
8686 }
8687
8688 /* Kill credit for quest */
8689 if (!m_ptr->clone) {
8690 int i, credit_idx = r_ptr->dup_idx ? r_ptr->dup_idx : m_ptr->r_idx;
8691 for (i = 0; i < MAX_XORDERS; i++) {
8692 if (p_ptr->xorder_id && xorders[i].id == p_ptr->xorder_id) {
8693 if (credit_idx == xorders[i].type) {
8694 p_ptr->xorder_num--;
8695 if (p_ptr->xorder_num <= 0) { //there's a panic save bug after verygreat apply magic, q_n = -1 after
8696 kill_xorder(Ind);
8697 } else
8698 msg_format(Ind, "%d more to go!", p_ptr->xorder_num);
8699 }
8700 break;
8701 }
8702 }
8703 }
8704
8705 #ifdef MONSTER_INVENTORY
8706 monster_drop_carried_objects(m_ptr);
8707 #endif // MONSTER_INVENTORY
8708
8709
8710 /* When the player kills a Unique, it stays dead */
8711 /* No more, this is handled byt p_ptr->r_killed -- DG */
8712 // if (r_ptr->flags1 & RF1_UNIQUE) r_ptr->max_num = 0;
8713 // p_ptr->r_killed[m_ptr->r_idx] = TRUE;
8714
8715 /* Recall even invisible uniques or winners */
8716 if (p_ptr->mon_vis[m_idx] || (r_ptr->flags1 & RF1_UNIQUE)) {
8717 /* Count kills in all lives */
8718 if (!is_admin(p_ptr)) r_ptr->r_tkills++;
8719
8720 /* Hack -- Auto-recall */
8721 recent_track(m_ptr->r_idx);
8722 }
8723
8724 /* Delete the monster */
8725 delete_monster_idx(m_idx, FALSE);
8726
8727 /* Not afraid */
8728 (*fear) = FALSE;
8729
8730 suppress_message = old_tacit;
8731
8732 /* Monster is dead */
8733 return (TRUE);
8734 }
8735
8736
8737 #ifdef ALLOW_FEAR
8738
8739 /* Mega-Hack -- Pain cancels fear */
8740 if (m_ptr->monfear && (dam > 0)) {
8741 int tmp = randint(dam);
8742
8743 /* Cure a little fear */
8744 if (tmp < m_ptr->monfear) {
8745 /* Reduce fear */
8746 m_ptr->monfear -= tmp;
8747 }
8748
8749 /* Cure all the fear */
8750 else {
8751 /* Cure fear */
8752 m_ptr->monfear = 0;
8753
8754 /* No more fear */
8755 (*fear) = FALSE;
8756 }
8757 }
8758
8759 /* Sometimes a monster gets scared by damage */
8760 else if (!m_ptr->monfear && !(r_ptr->flags3 & RF3_NO_FEAR)) {
8761 int percentage;
8762
8763 /* prevent crash bug that happened in line 8237 (mon_take_hit),
8764 apparently maxhp can extremely rarely be 0 - C. Blue */
8765 if (m_ptr->maxhp == 0) {
8766 s_printf("DBG_MAXHP_1 %d,%d\n", m_ptr->r_idx, m_ptr->ego);
8767 return FALSE;
8768 }
8769
8770 /* Percentage of fully healthy */
8771 percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
8772
8773 /*
8774 * Run (sometimes) if at 10% or less of max hit points,
8775 * or (usually) when hit for half its current hit points
8776 */
8777 if (((percentage <= 10) && (rand_int(10) < percentage)) ||
8778 ((dam >= m_ptr->hp) && (rand_int(100) < 80)))
8779 {
8780 /* Hack -- note fear */
8781 (*fear) = TRUE;
8782
8783 /* XXX XXX XXX Hack -- Add some timed fear */
8784 m_ptr->monfear = (randint(10) +
8785 (((dam >= m_ptr->hp) && (percentage > 7)) ?
8786 20 : ((11 - percentage) * 5)));
8787 m_ptr->monfear_gone = 0;
8788 }
8789 }
8790
8791 #endif
8792
8793 /* Not dead yet */
8794 return (FALSE);
8795 }
8796
8797 void monster_death_mon(int am_idx, int m_idx)
8798 {
8799 int i, j, y, x, ny, nx;
8800 int number = 0;
8801 cave_type *c_ptr;
8802
8803 monster_type *m_ptr = &m_list[m_idx];
8804 monster_race *r_ptr = race_inf(m_ptr);
8805
8806 bool good = (r_ptr->flags1 & RF1_DROP_GOOD) ? TRUE : FALSE;
8807 bool great = (r_ptr->flags1 & RF1_DROP_GREAT) ? TRUE : FALSE;
8808
8809 bool do_gold = (!(r_ptr->flags1 & RF1_ONLY_ITEM));
8810 bool do_item = (!(r_ptr->flags1 & RF1_ONLY_GOLD));
8811
8812 int force_coin = get_coin_type(r_ptr);
8813 struct worldpos *wpos;
8814 cave_type **zcave;
8815
8816 /* Get the location */
8817 y = m_ptr->fy;
8818 x = m_ptr->fx;
8819 wpos = &m_ptr->wpos;
8820 if (!(zcave = getcave(wpos))) return;
8821
8822 /* Determine how much we can drop */
8823 if ((r_ptr->flags1 & RF1_DROP_60) && (rand_int(100) < 60)) number++;
8824 if ((r_ptr->flags1 & RF1_DROP_90) && (rand_int(100) < 90)) number++;
8825 if (r_ptr->flags0 & RF0_DROP_1) number++;
8826 if (r_ptr->flags1 & RF1_DROP_1D2) number += damroll(1, 2);
8827 if (r_ptr->flags1 & RF1_DROP_2D2) number += damroll(2, 2);
8828 if (r_ptr->flags1 & RF1_DROP_3D2) number += damroll(3, 2);
8829 if (r_ptr->flags1 & RF1_DROP_4D2) number += damroll(4, 2);
8830
8831 /* Drop some objects */
8832 for (j = 0; j < number; j++) {
8833 /* Try 20 times per item, increasing range */
8834 for (i = 0; i < 20; ++i) {
8835 int d = (i + 14) / 15;
8836
8837 /* Pick a "correct" location */
8838 scatter(wpos, &ny, &nx, y, x, d, 0);
8839
8840 /* Must be "clean" floor grid */
8841 if (!cave_clean_bold(zcave, ny, nx)) continue;
8842
8843 /* Access the grid */
8844 c_ptr = &zcave[ny][nx];
8845
8846 /* Hack -- handle creeping coins */
8847 coin_type = force_coin;
8848
8849 /* Average dungeon and monster levels */
8850 object_level = (getlevel(wpos) + r_ptr->level) / 2;
8851
8852 /* No easy item hunting in towns.. */
8853 if (wpos->wz == 0) object_level = r_ptr->level / 2;
8854
8855 /* Place Gold */
8856 if (do_gold && (!do_item || (rand_int(100) < 50))) {
8857 place_gold(wpos, ny, nx, 0);
8858 }
8859 /* Place Object */
8860 else {
8861 place_object_restrictor = RESF_NONE;
8862 place_object(wpos, ny, nx, good, great, FALSE, RESF_LOW, default_obj_theme, 0, ITEM_REMOVAL_NORMAL);
8863 }
8864
8865 /* Reset the object level */
8866 object_level = getlevel(wpos);
8867
8868 /* Reset "coin" type */
8869 coin_type = 0;
8870
8871 /* Notice */
8872 note_spot_depth(wpos, ny, nx);
8873
8874 /* Display */
8875 everyone_lite_spot(wpos, ny, nx);
8876
8877 /* Under a player */
8878 if (c_ptr->m_idx < 0) {
8879 msg_print(0 - c_ptr->m_idx, "You feel something roll beneath your feet.");
8880 }
8881
8882 break;
8883 }
8884 }
8885
8886 FREE(m_ptr->r_ptr, monster_race);
8887 }
8888
8889 bool mon_take_hit_mon(int am_idx, int m_idx, int dam, bool *fear, cptr note)
8890 {
8891 monster_type *am_ptr = &m_list[am_idx];
8892 monster_type *m_ptr = &m_list[m_idx];
8893 monster_race *r_ptr = race_inf(m_ptr);
8894 s64b new_exp;
8895
8896 /* Redraw (later) if needed */
8897 update_health(m_idx);
8898
8899 /* Wake it up */
8900 m_ptr->csleep = 0;
8901
8902 /* Hurt it */
8903 m_ptr->hp -= dam;
8904
8905 /* Cannot kill uniques */
8906 if ((r_ptr->flags1 & RF1_UNIQUE) && (m_ptr->hp < 1)) m_ptr->hp = 1;
8907
8908 /* It is dead now */
8909 if (m_ptr->hp < 0) {
8910 /* Give some experience */
8911 // new_exp = ((long)r_ptr->mexp * r_ptr->level) / am_ptr->level;
8912 /* Division by zero occurs here when a pet attacks a townie (level 0) - mikaelh */
8913 /* Only gain exp when target monster level > 0 */
8914 if (am_ptr->level > 0) {
8915 new_exp = ((long)r_ptr->mexp * m_ptr->level) / am_ptr->level;
8916
8917 /* Gain experience */
8918 if((new_exp*(100-m_ptr->clone))/100)
8919 /* disabled for golems for now, till attack-bug (9k damage) has been solved */
8920 if (!m_ptr->special && !m_ptr->owner)
8921 monster_gain_exp(am_idx, (new_exp*(100-m_ptr->clone))/100, TRUE);
8922 }
8923 /*
8924 switch (m_ptr->r_idx - 1) {
8925 case SV_GOLEM_WOOD:
8926 case SV_GOLEM_COPPER:
8927 case SV_GOLEM_IRON:
8928 case SV_GOLEM_ALUM:
8929 case SV_GOLEM_SILVER:
8930 case SV_GOLEM_GOLD:
8931 case SV_GOLEM_MITHRIL:
8932 case SV_GOLEM_ADAM:
8933 } */
8934
8935 /* Generate treasure */
8936 if (!m_ptr->clone) monster_death_mon(am_idx, m_idx);
8937
8938 /* Delete the monster */
8939 delete_monster_idx(m_idx, TRUE);
8940
8941 /* Not afraid */
8942 (*fear) = FALSE;
8943
8944 /* Monster is dead */
8945 return (TRUE);
8946 }
8947
8948
8949 #ifdef ALLOW_FEAR
8950
8951 /* Mega-Hack -- Pain cancels fear */
8952 if (m_ptr->monfear && (dam > 0)) {
8953 int tmp = randint(dam);
8954
8955 /* Cure a little fear */
8956 if (tmp < m_ptr->monfear) {
8957 /* Reduce fear */
8958 m_ptr->monfear -= tmp;
8959 }
8960 /* Cure all the fear */
8961 else {
8962 /* Cure fear */
8963 m_ptr->monfear = 0;
8964
8965 /* No more fear */
8966 (*fear) = FALSE;
8967 }
8968 }
8969
8970 /* Sometimes a monster gets scared by damage */
8971 else if (!m_ptr->monfear && !(r_ptr->flags3 & RF3_NO_FEAR)) {
8972 int percentage;
8973
8974 /* prevent crash bug that happened in line 8237 (mon_take_hit),
8975 apparently maxhp can extremely rarely be 0 - C. Blue */
8976 if (m_ptr->maxhp == 0) {
8977 s_printf("DBG_MAXHP_2 %d,%d\n", m_ptr->r_idx, m_ptr->ego);
8978 return FALSE;
8979 }
8980
8981 /* Percentage of fully healthy */
8982 percentage = (100L * m_ptr->hp) / m_ptr->maxhp;
8983
8984 /*
8985 * Run (sometimes) if at 10% or less of max hit points,
8986 * or (usually) when hit for half its current hit points
8987 */
8988 if (((percentage <= 10) && (rand_int(10) < percentage)) ||
8989 ((dam >= m_ptr->hp) && (rand_int(100) < 80))) {
8990 /* Hack -- note fear */
8991 (*fear) = TRUE;
8992
8993 /* XXX XXX XXX Hack -- Add some timed fear */
8994 m_ptr->monfear = (randint(10) +
8995 (((dam >= m_ptr->hp) && (percentage > 7)) ?
8996 20 : ((11 - percentage) * 5)));
8997 m_ptr->monfear_gone = 0;
8998 }
8999 }
9000
9001 #endif
9002
9003 /* Not dead yet */
9004 return (FALSE);
9005 }
9006
9007 /* Initialises the panel, when newly entering a level */
9008 void panel_calculate(Ind) {
9009 player_type *p_ptr = Players[Ind];
9010
9011 p_ptr->panel_row = ((p_ptr->py - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
9012 if (p_ptr->panel_row > p_ptr->max_panel_rows) p_ptr->panel_row = p_ptr->max_panel_rows;
9013 else if (p_ptr->panel_row < 0) p_ptr->panel_row = 0;
9014
9015 p_ptr->panel_col = ((p_ptr->px - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
9016 if (p_ptr->panel_col > p_ptr->max_panel_cols) p_ptr->panel_col = p_ptr->max_panel_cols;
9017 else if (p_ptr->panel_col < 0) p_ptr->panel_col = 0;
9018
9019 #ifdef ALERT_OFFPANEL_DAM
9020 /* For alert-beeps on damage: Reset remembered panel */
9021 p_ptr->panel_row_old = p_ptr->panel_row;
9022 p_ptr->panel_col_old = p_ptr->panel_col;
9023 #endif
9024
9025 panel_bounds(Ind);
9026
9027 tradpanel_calculate(Ind);
9028 }
9029 /* for functions of fixed size of effect that therefore require the
9030 'traditional' panel dimensions, such as Magic Mapping: */
9031 void tradpanel_calculate(Ind) {
9032 player_type *p_ptr = Players[Ind];
9033
9034 p_ptr->tradpanel_row = ((p_ptr->py - SCREEN_HGT / 4) / (SCREEN_HGT / 2));
9035 if (p_ptr->tradpanel_row > p_ptr->max_tradpanel_rows) p_ptr->tradpanel_row = p_ptr->max_tradpanel_rows;
9036 else if (p_ptr->tradpanel_row < 0) p_ptr->tradpanel_row = 0;
9037
9038 p_ptr->tradpanel_col = ((p_ptr->px - SCREEN_WID / 4) / (SCREEN_WID / 2));
9039 if (p_ptr->tradpanel_col > p_ptr->max_tradpanel_cols) p_ptr->tradpanel_col = p_ptr->max_tradpanel_cols;
9040 else if (p_ptr->tradpanel_col < 0) p_ptr->tradpanel_col = 0;
9041
9042 #ifdef ALERT_OFFPANEL_DAM
9043 /* For alert-beeps on damage: Reset remembered panel */
9044 p_ptr->panel_row_old = p_ptr->panel_row;
9045 p_ptr->panel_col_old = p_ptr->panel_col;
9046 #endif
9047
9048 tradpanel_bounds(Ind);
9049 }
9050
9051 /*
9052 * Calculates current boundaries
9053 * Called below and from "do_cmd_locate()".
9054 */
9055 void panel_bounds(int Ind)
9056 {
9057 player_type *p_ptr = Players[Ind];
9058
9059 p_ptr->panel_row_min = p_ptr->panel_row * (p_ptr->screen_hgt / 2);
9060 p_ptr->panel_row_max = p_ptr->panel_row_min + p_ptr->screen_hgt - 1;
9061 p_ptr->panel_row_prt = p_ptr->panel_row_min - SCREEN_PAD_TOP;
9062 p_ptr->panel_col_min = p_ptr->panel_col * (p_ptr->screen_wid / 2);
9063 p_ptr->panel_col_max = p_ptr->panel_col_min + p_ptr->screen_wid - 1;
9064 p_ptr->panel_col_prt = p_ptr->panel_col_min - SCREEN_PAD_LEFT;
9065 }
9066 void tradpanel_bounds(int Ind)
9067 {
9068 player_type *p_ptr = Players[Ind];
9069
9070 /* for stuff such as magic mapping that relies on traditional panel size */
9071 p_ptr->tradpanel_row_min = p_ptr->tradpanel_row * (SCREEN_HGT / 2);
9072 p_ptr->tradpanel_row_max = p_ptr->tradpanel_row_min + SCREEN_HGT - 1;
9073 p_ptr->tradpanel_col_min = p_ptr->tradpanel_col * (SCREEN_WID / 2);
9074 p_ptr->tradpanel_col_max = p_ptr->tradpanel_col_min + SCREEN_WID - 1;
9075 }
9076
9077
9078
9079 /*
9080 * Given an row (y) and col (x), this routine detects when a move
9081 * off the screen has occurred and figures new borders. -RAK-
9082 *
9083 * "Update" forces a "full update" to take place.
9084 *
9085 * The map is reprinted if necessary, and "TRUE" is returned.
9086 */
9087 void verify_panel(int Ind)
9088 {
9089 player_type *p_ptr = Players[Ind];
9090
9091 int y = p_ptr->py;
9092 int x = p_ptr->px;
9093
9094 int prow = p_ptr->panel_row;
9095 int pcol = p_ptr->panel_col;
9096
9097
9098 /* Also update (virtual) traditional panel */
9099 verify_tradpanel(Ind);
9100
9101
9102 /* Scroll screen when 2 grids from top/bottom edge */
9103 if ((y < p_ptr->panel_row_min + SCROLL_MARGIN_ROW) || (y > p_ptr->panel_row_max - SCROLL_MARGIN_ROW)) {
9104 prow = ((y - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
9105 if (prow > p_ptr->max_panel_rows) prow = p_ptr->max_panel_rows;
9106 else if (prow < 0) prow = 0;
9107 }
9108
9109 /* Scroll screen when 4 grids from left/right edge */
9110 if ((x < p_ptr->panel_col_min + SCROLL_MARGIN_COL) || (x > p_ptr->panel_col_max - SCROLL_MARGIN_COL)) {
9111 pcol = ((x - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
9112 if (pcol > p_ptr->max_panel_cols) pcol = p_ptr->max_panel_cols;
9113 else if (pcol < 0) pcol = 0;
9114 }
9115
9116 /* Check for "no change" */
9117 if ((prow == p_ptr->panel_row) && (pcol == p_ptr->panel_col)) return;
9118
9119 /* Hack -- optional disturb on "panel change" */
9120 if (p_ptr->disturb_panel) disturb(Ind, 0, 0);
9121
9122 /* Save the new panel info */
9123 p_ptr->panel_row = prow;
9124 p_ptr->panel_col = pcol;
9125
9126 /* Recalculate the boundaries */
9127 panel_bounds(Ind);
9128
9129 #ifdef ALERT_OFFPANEL_DAM
9130 /* For alert-beeps on damage: Reset remembered panel */
9131 p_ptr->panel_row_old = p_ptr->panel_row;
9132 p_ptr->panel_col_old = p_ptr->panel_col;
9133 #endif
9134
9135 /* client-side weather stuff */
9136 p_ptr->panel_changed = TRUE;
9137
9138 /* Update stuff */
9139 p_ptr->update |= (PU_MONSTERS);
9140
9141 /* Redraw map */
9142 p_ptr->redraw |= (PR_MAP);
9143
9144 /* Window stuff */
9145 p_ptr->window |= (PW_OVERHEAD);
9146 }
9147 void verify_tradpanel(int Ind)
9148 {
9149 player_type *p_ptr = Players[Ind];
9150
9151 int y = p_ptr->py;
9152 int x = p_ptr->px;
9153
9154 int prow = p_ptr->tradpanel_row;
9155 int pcol = p_ptr->tradpanel_col;
9156
9157 /* Scroll screen when 2 grids from top/bottom edge */
9158 if ((y < p_ptr->tradpanel_row_min + TRAD_SCROLL_MARGIN_ROW) || (y > p_ptr->tradpanel_row_max - TRAD_SCROLL_MARGIN_ROW)) {
9159 prow = ((y - SCREEN_HGT / 4) / (SCREEN_HGT / 2));
9160 if (prow > p_ptr->max_tradpanel_rows) prow = p_ptr->max_tradpanel_rows;
9161 else if (prow < 0) prow = 0;
9162 }
9163
9164 /* Scroll screen when 4 grids from left/right edge */
9165 if ((x < p_ptr->tradpanel_col_min + TRAD_SCROLL_MARGIN_COL) || (x > p_ptr->tradpanel_col_max - TRAD_SCROLL_MARGIN_COL)) {
9166 pcol = ((x - SCREEN_WID / 4) / (SCREEN_WID / 2));
9167 if (pcol > p_ptr->max_tradpanel_cols) pcol = p_ptr->max_tradpanel_cols;
9168 else if (pcol < 0) pcol = 0;
9169 }
9170
9171 /* Check for "no change" */
9172 if ((prow == p_ptr->tradpanel_row) && (pcol == p_ptr->tradpanel_col)) return;
9173
9174 #if 0 /* only in 'real' verify_panel() */
9175 /* Hack -- optional disturb on "panel change" */
9176 if (p_ptr->disturb_panel) disturb(Ind, 0, 0);
9177 #endif
9178
9179 /* Save the new panel info */
9180 p_ptr->tradpanel_row = prow;
9181 p_ptr->tradpanel_col = pcol;
9182
9183 /* Recalculate the boundaries */
9184 tradpanel_bounds(Ind);
9185
9186 #if 0 /* only in 'real' verify_panel() */
9187 /* client-side weather stuff */
9188 p_ptr->panel_changed = TRUE;
9189
9190 /* Update stuff */
9191 p_ptr->update |= (PU_MONSTERS);
9192
9193 /* Redraw map */
9194 p_ptr->redraw |= (PR_MAP);
9195
9196 /* Window stuff */
9197 p_ptr->window |= (PW_OVERHEAD);
9198 #endif
9199 }
9200
9201 /* Test whether the player is currently looking at his local surroundings (default)
9202 as opposed to some far off panel (done by cmd_locate()).
9203 Purpose: Prevent detection magic from working on remote areas. */
9204 bool local_panel(int Ind) {
9205 player_type *p_ptr = Players[Ind];
9206
9207 int y = p_ptr->py;
9208 int x = p_ptr->px;
9209
9210 int prow = p_ptr->panel_row;
9211 int pcol = p_ptr->panel_col;
9212
9213
9214 #if 0
9215 /* Also check (virtual) traditional panel */
9216 if (!local_tradpanel(Ind)) return FALSE;
9217 #endif
9218
9219
9220 /* Scroll screen when 2 grids from top/bottom edge */
9221 if ((y < p_ptr->panel_row_min + SCROLL_MARGIN_ROW) || (y > p_ptr->panel_row_max - SCROLL_MARGIN_ROW)) {
9222 prow = ((y - p_ptr->screen_hgt / 4) / (p_ptr->screen_hgt / 2));
9223 if (prow > p_ptr->max_panel_rows) prow = p_ptr->max_panel_rows;
9224 else if (prow < 0) prow = 0;
9225 }
9226
9227 /* Scroll screen when 4 grids from left/right edge */
9228 if ((x < p_ptr->panel_col_min + SCROLL_MARGIN_COL) || (x > p_ptr->panel_col_max - SCROLL_MARGIN_COL)) {
9229 pcol = ((x - p_ptr->screen_wid / 4) / (p_ptr->screen_wid / 2));
9230 if (pcol > p_ptr->max_panel_cols) pcol = p_ptr->max_panel_cols;
9231 else if (pcol < 0) pcol = 0;
9232 }
9233
9234 /* Check for "no change" */
9235 if ((prow == p_ptr->panel_row) && (pcol == p_ptr->panel_col)) return TRUE;
9236 return FALSE;
9237 }
9238 #if 0
9239 bool local_tradpanel(int Ind) {
9240 player_type *p_ptr = Players[Ind];
9241
9242 int y = p_ptr->py;
9243 int x = p_ptr->px;
9244
9245 int prow = p_ptr->tradpanel_row;
9246 int pcol = p_ptr->tradpanel_col;
9247
9248 /* Scroll screen when 2 grids from top/bottom edge */
9249 if ((y < p_ptr->tradpanel_row_min + TRAD_SCROLL_MARGIN_ROW) || (y > p_ptr->tradpanel_row_max - TRAD_SCROLL_MARGIN_ROW)) {
9250 prow = ((y - SCREEN_HGT / 4) / (SCREEN_HGT / 2));
9251 if (prow > p_ptr->max_tradpanel_rows) prow = p_ptr->max_tradpanel_rows;
9252 else if (prow < 0) prow = 0;
9253 }
9254
9255 /* Scroll screen when 4 grids from left/right edge */
9256 if ((x < p_ptr->tradpanel_col_min + TRAD_SCROLL_MARGIN_COL) || (x > p_ptr->tradpanel_col_max - TRAD_SCROLL_MARGIN_COL)) {
9257 pcol = ((x - SCREEN_WID / 4) / (SCREEN_WID / 2));
9258 if (pcol > p_ptr->max_tradpanel_cols) pcol = p_ptr->max_tradpanel_cols;
9259 else if (pcol < 0) pcol = 0;
9260 }
9261
9262 /* Check for "no change" */
9263 if ((prow == p_ptr->tradpanel_row) && (pcol == p_ptr->tradpanel_col)) return TRUE;
9264 return FALSE;
9265 }
9266 #endif
9267
9268
9269 /*
9270 * Monster health description
9271 */
9272 cptr look_mon_desc(int m_idx)
9273 {
9274 monster_type *m_ptr = &m_list[m_idx];
9275 monster_race *r_ptr = race_inf(m_ptr);
9276
9277 bool living = TRUE;
9278 int perc;
9279
9280
9281 /* Determine if the monster is "living" (vs "undead") */
9282 if (r_ptr->flags3 & RF3_UNDEAD) living = FALSE;
9283 if (r_ptr->flags3 & RF3_DEMON) living = FALSE;
9284 if (strchr("Egv", r_ptr->d_char)) living = FALSE;
9285
9286
9287 /* Healthy monsters */
9288 if (m_ptr->hp >= m_ptr->maxhp) {
9289 /* asleep even? */
9290 if (m_ptr->csleep) return("asleep");
9291 /* albeit stunned? */
9292 if (m_ptr->stunned > 100) return("knocked out");
9293 if (m_ptr->stunned > 50) return("heavily dazed");
9294 if (m_ptr->stunned) return("dazed");
9295 /* No damage (and no other effect either) */
9296 return (living ? "unhurt" : "undamaged");
9297 }
9298
9299
9300 /* prevent crash bug that happened in line 8237 (mon_take_hit),
9301 apparently maxhp can extremely rarely be 0 - C. Blue */
9302 if (m_ptr->maxhp == 0) {
9303 s_printf("DBG_MAXHP_3 %d,%d\n", m_ptr->r_idx, m_ptr->ego);
9304 return "awake"; /* some excuse string ;) */
9305 }
9306
9307 /* Calculate a health "percentage" */
9308 perc = 100L * m_ptr->hp / m_ptr->maxhp;
9309
9310 if (perc >= 60)
9311 return (living ? "somewhat wounded" : "somewhat damaged");
9312
9313 if (perc >= 25)
9314 return (living ? "wounded" : "damaged");
9315
9316 if (perc >= 10)
9317 return (living ? "badly wounded" : "badly damaged");
9318
9319 return (living ? "almost dead" : "almost destroyed");
9320 }
9321
9322
9323
9324 /*
9325 * Angband sorting algorithm -- quick sort in place
9326 *
9327 * Note that the details of the data we are sorting is hidden,
9328 * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
9329 * function hooks to interact with the data, which is given as
9330 * two pointers, and which may have any user-defined form.
9331 */
9332 void ang_sort_aux(int Ind, vptr u, vptr v, int p, int q)
9333 {
9334 int z, a, b;
9335
9336 /* Done sort */
9337 if (p >= q) return;
9338
9339 /* Pivot */
9340 z = p;
9341
9342 /* Begin */
9343 a = p;
9344 b = q;
9345
9346 /* Partition */
9347 while (TRUE) {
9348 /* Slide i2 */
9349 while (!(*ang_sort_comp)(Ind, u, v, b, z)) b--;
9350
9351 /* Slide i1 */
9352 while (!(*ang_sort_comp)(Ind, u, v, z, a)) a++;
9353
9354 /* Done partition */
9355 if (a >= b) break;
9356
9357 /* Swap */
9358 (*ang_sort_swap)(Ind, u, v, a, b);
9359
9360 /* Advance */
9361 a++, b--;
9362 }
9363
9364 /* Recurse left side */
9365 ang_sort_aux(Ind, u, v, p, b);
9366
9367 /* Recurse right side */
9368 ang_sort_aux(Ind, u, v, b+1, q);
9369 }
9370
9371 void ang_sort_extra_aux(int Ind, vptr u, vptr v, vptr w, int p, int q)
9372 {
9373 int z, a, b;
9374
9375 /* Done sort */
9376 if (p >= q) return;
9377
9378 /* Pivot */
9379 z = p;
9380
9381 /* Begin */
9382 a = p;
9383 b = q;
9384
9385 /* Partition */
9386 while (TRUE) {
9387 /* Slide i2 */
9388 while (!(*ang_sort_extra_comp)(Ind, u, v, w, b, z)) b--;
9389
9390 /* Slide i1 */
9391 while (!(*ang_sort_extra_comp)(Ind, u, v, w, z, a)) a++;
9392
9393 /* Done partition */
9394 if (a >= b) break;
9395
9396 /* Swap */
9397 (*ang_sort_extra_swap)(Ind, u, v, w, a, b);
9398
9399 /* Advance */
9400 a++, b--;
9401 }
9402
9403 /* Recurse left side */
9404 ang_sort_extra_aux(Ind, u, v, w, p, b);
9405
9406 /* Recurse right side */
9407 ang_sort_extra_aux(Ind, u, v, w, b+1, q);
9408 }
9409
9410
9411 /*
9412 * Angband sorting algorithm -- quick sort in place
9413 *
9414 * Note that the details of the data we are sorting is hidden,
9415 * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
9416 * function hooks to interact with the data, which is given as
9417 * two pointers, and which may have any user-defined form.
9418 */
9419 void ang_sort(int Ind, vptr u, vptr v, int n)
9420 {
9421 /* Sort the array */
9422 ang_sort_aux(Ind, u, v, 0, n-1);
9423 }
9424
9425 /* Added this for further sorting the all monsters that are *closest* to
9426 the player by their sleep state: Target awake monsters first, before
9427 waking up sleeping ones. Suggested by Caine/Ifrit - C. Blue */
9428 void ang_sort_extra(int Ind, vptr u, vptr v, vptr w, int n)
9429 {
9430 /* Sort the array */
9431 ang_sort_extra_aux(Ind, u, v, w, 0, n-1);
9432 }
9433
9434 /* returns our max times 100 divided by our current...*/
9435 static int player_wounded(s16b ind)
9436 {
9437 player_type *p_ptr = Players[ind];
9438 int wounded = (p_ptr->mhp * 100) / p_ptr->chp;
9439
9440 /* allow targetting healed up players that suffer from status ailments
9441 curable by Cure Wounds spell - C. Blue */
9442 if (wounded == 100 &&
9443 (p_ptr->cut || p_ptr->blind || p_ptr->confused || p_ptr->stun))
9444 wounded = 101;
9445
9446 return wounded;
9447 }
9448
9449 /* this should probably be somewhere more logical, but I should probably be
9450 sleeping right now.....
9451 Selects the most wounded target.
9452
9453 Hmm, I am sure there are faster sort algorithms out there... oh well, I don't
9454 think it really matters... this one goes out to you Mr. Munroe.
9455 -ADA-
9456 */
9457
9458 static void wounded_player_target_sort(int Ind, vptr sx, vptr sy, vptr id, int n)
9459 {
9460 int c,num;
9461 s16b swp;
9462 s16b * idx = (s16b *) id;
9463 byte * x = (byte *) sx;
9464 byte * y = (byte *) sy;
9465 byte swpb;
9466
9467 /* num equals our max index */
9468 num = n-1;
9469
9470 while (num > 0) {
9471 for (c = 0; c < num; c++) {
9472 if (player_wounded(idx[c+1]) > player_wounded(idx[c])) {
9473 swp = idx[c];
9474 idx[c] = idx[c+1];
9475 idx[c+1] = swp;
9476
9477 swpb = x[c];
9478 x[c] = x[c+1];
9479 x[c+1] = swpb;
9480
9481 swpb = y[c];
9482 y[c] = y[c+1];
9483 y[c+1] = swpb;
9484 }
9485 }
9486 num--;
9487 }
9488 }
9489
9490
9491
9492 /*
9493 * Sorting hook -- comp function -- by "distance to player"
9494 *
9495 * We use "u" and "v" to point to arrays of "x" and "y" positions,
9496 * and sort the arrays by double-distance to the player.
9497 */
9498 bool ang_sort_comp_distance(int Ind, vptr u, vptr v, int a, int b)
9499 {
9500 player_type *p_ptr = Players[Ind];
9501
9502 byte *x = (byte*)(u);
9503 byte *y = (byte*)(v);
9504
9505 int da, db, kx, ky;
9506
9507 /* Absolute distance components */
9508 kx = x[a]; kx -= p_ptr->px; kx = ABS(kx);
9509 ky = y[a]; ky -= p_ptr->py; ky = ABS(ky);
9510
9511 /* Approximate Double Distance to the first point */
9512 da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9513
9514 /* Absolute distance components */
9515 kx = x[b]; kx -= p_ptr->px; kx = ABS(kx);
9516 ky = y[b]; ky -= p_ptr->py; ky = ABS(ky);
9517
9518 /* Approximate Double Distance to the first point */
9519 db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9520
9521 /* Compare the distances */
9522 return (da <= db);
9523 }
9524
9525
9526 /*
9527 * Sorting hook -- swap function -- by "distance to player"
9528 *
9529 * We use "u" and "v" to point to arrays of "x" and "y" positions,
9530 * and sort the arrays by distance to the player.
9531 */
9532 void ang_sort_swap_distance(int Ind, vptr u, vptr v, int a, int b)
9533 {
9534 byte *x = (byte*)(u);
9535 byte *y = (byte*)(v);
9536
9537 byte temp;
9538
9539 /* Swap "x" */
9540 temp = x[a];
9541 x[a] = x[b];
9542 x[b] = temp;
9543
9544 /* Swap "y" */
9545 temp = y[a];
9546 y[a] = y[b];
9547 y[b] = temp;
9548 }
9549
9550
9551 bool ang_sort_extra_comp_distance(int Ind, vptr u, vptr v, vptr w, int a, int b)
9552 {
9553 player_type *p_ptr = Players[Ind];
9554
9555 byte *x = (byte*)(u);
9556 byte *y = (byte*)(v);
9557 byte *z = (byte*)(w);
9558
9559 int da, db, kx, ky;
9560
9561 /* Absolute distance components */
9562 kx = x[a]; kx -= p_ptr->px; kx = ABS(kx);
9563 ky = y[a]; ky -= p_ptr->py; ky = ABS(ky);
9564
9565 /* Approximate Double Distance to the first point */
9566 da = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9567
9568 /* Absolute distance components */
9569 kx = x[b]; kx -= p_ptr->px; kx = ABS(kx);
9570 ky = y[b]; ky -= p_ptr->py; ky = ABS(ky);
9571
9572 /* Approximate Double Distance to the first point */
9573 db = ((kx > ky) ? (kx + kx + ky) : (ky + ky + kx));
9574
9575 /* Compare the distances -- if equal, prefer the target that is not asleep, default to 'a'. */
9576 return ((da == db) ? (z[b] || !z[a]) : (da <= db));
9577 }
9578
9579 void ang_sort_extra_swap_distance(int Ind, vptr u, vptr v, vptr w, int a, int b)
9580 {
9581 byte *x = (byte*)(u);
9582 byte *y = (byte*)(v);
9583 byte *z = (byte*)(w);
9584
9585 byte temp;
9586
9587 /* Swap "x" */
9588 temp = x[a];
9589 x[a] = x[b];
9590 x[b] = temp;
9591
9592 /* Swap "y" */
9593 temp = y[a];
9594 y[a] = y[b];
9595 y[b] = temp;
9596
9597 /* Swap "z" */
9598 temp = z[a];
9599 z[a] = z[b];
9600 z[b] = temp;
9601 }
9602
9603
9604
9605 /*
9606 * Compare the values of two objects.
9607 *
9608 * Pointer "v" should not point to anything (it isn't used, anyway).
9609 */
9610 bool ang_sort_comp_value(int Ind, vptr u, vptr v, int a, int b)
9611 {
9612 object_type *inven = (object_type *)u;
9613 s64b va, vb;
9614
9615 if (inven[a].tval && inven[b].tval) {
9616 va = object_value(Ind, &inven[a]);
9617 vb = object_value(Ind, &inven[b]);
9618
9619 return (va >= vb);
9620 }
9621
9622 if (inven[a].tval) return FALSE;
9623 return TRUE;
9624 }
9625
9626
9627 void ang_sort_swap_value(int Ind, vptr u, vptr v, int a, int b)
9628 {
9629 object_type *x = (object_type *)u;
9630 object_type temp;
9631
9632 temp = x[a];
9633 x[a] = x[b];
9634 x[b] = temp;
9635 }
9636
9637
9638 /*
9639 * Sort a list of r_idx by level(depth). - Jir -
9640 *
9641 * Pointer "v" should not point to anything (it isn't used, anyway).
9642 */
9643 bool ang_sort_comp_mon_lev(int Ind, vptr u, vptr v, int a, int b)
9644 {
9645 s16b *r_idx = (s16b*)u;
9646 s32b va, vb;
9647 monster_race *ra_ptr = &r_info[r_idx[a]];
9648 monster_race *rb_ptr = &r_info[r_idx[b]];
9649
9650 if (ra_ptr->name && rb_ptr->name) {
9651 va = ra_ptr->level * 3000 + r_idx[a];
9652 vb = rb_ptr->level * 3000 + r_idx[b];
9653
9654 return (va >= vb);
9655 }
9656
9657 if (ra_ptr->name) return FALSE;
9658 return TRUE;
9659 }
9660
9661
9662 /* namely. */
9663 void ang_sort_swap_s16b(int Ind, vptr u, vptr v, int a, int b)
9664 {
9665 s16b *x = (s16b*)u;
9666 s16b temp;
9667
9668 temp = x[a];
9669 x[a] = x[b];
9670 x[b] = temp;
9671 }
9672
9673 /*
9674 * Sort a list of k_idx by tval and sval. - Jir -
9675 *
9676 * Pointer "v" should not point to anything (it isn't used, anyway).
9677 */
9678 bool ang_sort_comp_tval(int Ind, vptr u, vptr v, int a, int b)
9679 {
9680 s16b *k_idx = (s16b*)u;
9681 s32b va, vb;
9682 object_kind *ka_ptr = &k_info[k_idx[a]];
9683 object_kind *kb_ptr = &k_info[k_idx[b]];
9684
9685 if (ka_ptr->tval && kb_ptr->tval) {
9686 va = ka_ptr->tval * 256 + ka_ptr->sval;
9687 vb = kb_ptr->tval * 256 + kb_ptr->sval;
9688
9689 return (va >= vb);
9690 }
9691
9692 if (ka_ptr->tval) return FALSE;
9693 return TRUE;
9694 }
9695
9696
9697
9698 /*** Targetting Code ***/
9699
9700
9701 /*
9702 * Determine is a monster makes a reasonable target
9703 *
9704 * The concept of "targetting" was stolen from "Morgul" (?)
9705 *
9706 * The player can target any location, or any "target-able" monster.
9707 *
9708 * Currently, a monster is "target_able" if it is visible, and if
9709 * the player can hit it with a projection, and the player is not
9710 * hallucinating. This allows use of "use closest target" macros.
9711 *
9712 * Future versions may restrict the ability to target "trappers"
9713 * and "mimics", but the semantics is a little bit weird.
9714 */
9715 /* Allow auto-retaliation to not get 'disabled' by a Sparrow next to the player?
9716 Also see EXPENSIVE_NO_TARGET_TEST. */
9717 //#define CHEAP_NO_TARGET_TEST
9718 bool target_able(int Ind, int m_idx)
9719 {
9720 player_type *p_ptr = Players[Ind], *q_ptr;
9721 monster_type *m_ptr;
9722
9723 if (!p_ptr) return FALSE;
9724
9725 /* Hack -- no targeting hallucinations */
9726 if (p_ptr->image) return (FALSE);
9727
9728 /* Check for OK monster */
9729 if (m_idx > 0) {
9730 monster_race *r_ptr;
9731
9732 /* Acquire pointer */
9733 m_ptr = &m_list[m_idx];
9734 r_ptr = race_inf(m_ptr);
9735
9736 /* Monster must be visible */
9737 if (!p_ptr->mon_vis[m_idx]) return (FALSE);
9738
9739 /* Monster must not be owned */
9740 if (p_ptr->id == m_ptr->owner) return (FALSE);
9741
9742 /* Distance to target too great?
9743 Use distance() to form a 'natural' circle shaped radius instead of a square shaped radius,
9744 monsters do this too */
9745 if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) > MAX_RANGE) return (FALSE);
9746
9747 /* Monster must be projectable */
9748 #ifdef PY_PROJ_WALL
9749 if (!projectable_wall(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx, MAX_RANGE)) return (FALSE);
9750 #else
9751 if (!projectable(&p_ptr->wpos, p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx, MAX_RANGE)) return (FALSE);
9752 #endif
9753
9754 if(m_ptr->owner == p_ptr->id) return(FALSE);
9755
9756 /* XXX XXX XXX Hack -- Never target trappers */
9757 /* if (CLEAR_ATTR && CLEAR_CHAR) return (FALSE); */
9758
9759 /* Cannot be targeted */
9760 #ifdef CHEAP_NO_TARGET_TEST
9761 /* Allow targetting if it's next to player? */
9762 if (!(ABS(p_ptr->px - m_ptr->fx) <= 1 && ABS(p_ptr->py - m_ptr->fy) <= 1))
9763 #endif
9764 if (r_ptr->flags7 & RF7_NO_TARGET) return (FALSE);
9765
9766 /* Assume okay */
9767 return (TRUE);
9768 }
9769
9770 /* Check for OK player */
9771 if (m_idx < 0) {
9772 /* Don't target oneself */
9773 if (Ind == 0 - m_idx) return(FALSE);
9774
9775 /* Acquire pointer */
9776 q_ptr = Players[0 - m_idx];
9777
9778 if ((0 - m_idx) > NumPlayers) q_ptr = NULL;
9779
9780 /* Paranoia check -- require a valid player */
9781 if (!q_ptr || q_ptr->conn == NOT_CONNECTED){
9782 p_ptr->target_who = 0;
9783 return (FALSE);
9784 }
9785
9786 /* Players must be on same depth */
9787 if (!inarea(&p_ptr->wpos, &q_ptr->wpos)) return (FALSE);
9788
9789 /* Player must be visible */
9790 if (!p_ptr->play_vis[-m_idx]) return (FALSE);
9791
9792 /* Player must be in FoV */
9793 if (!player_can_see_bold(Ind, q_ptr->py, q_ptr->px)) return (FALSE);
9794
9795 /* Distance to target too great?
9796 Use distance() to form a 'natural' circle shaped radius instead of a square shaped radius,
9797 monsters do this too */
9798 if (distance(p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px) > MAX_RANGE) return (FALSE);
9799
9800 /* Player must be projectable */
9801 #ifdef PY_PROJ_WALL
9802 if (!projectable_wall(&p_ptr->wpos, p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px, MAX_RANGE)) return (FALSE);
9803 #else
9804 if (!projectable(&p_ptr->wpos, p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px, MAX_RANGE)) return (FALSE);
9805 #endif
9806
9807 /* Assume okay */
9808 return (TRUE);
9809 }
9810
9811 /* Assume no target */
9812 return (FALSE);
9813 }
9814
9815
9816
9817
9818 /*
9819 * Update (if necessary) and verify (if possible) the target.
9820 *
9821 * We return TRUE if the target is "okay" and FALSE otherwise.
9822 */
9823 bool target_okay(int Ind)
9824 {
9825 player_type *p_ptr = Players[Ind];
9826
9827 /* Accept stationary targets */
9828 // if (p_ptr->target_who > MAX_M_IDX) return (TRUE);
9829 if (p_ptr->target_who < 0 - MAX_PLAYERS) return (TRUE);
9830
9831 /* Check moving monsters */
9832 if (p_ptr->target_who > 0) {
9833 /* Accept reasonable targets */
9834 if (target_able(Ind, p_ptr->target_who)) {
9835 monster_type *m_ptr = &m_list[p_ptr->target_who];
9836
9837 /* Acquire monster location */
9838 p_ptr->target_row = m_ptr->fy;
9839 p_ptr->target_col = m_ptr->fx;
9840
9841 /* Good target */
9842 return (TRUE);
9843 }
9844 }
9845
9846 /* Check moving players */
9847 if (p_ptr->target_who < 0) {
9848 /* Accept reasonable targets */
9849 if (target_able(Ind, p_ptr->target_who)) {
9850 player_type *q_ptr = Players[0 - p_ptr->target_who];
9851
9852 /* Acquire player location */
9853 p_ptr->target_row = q_ptr->py;
9854 p_ptr->target_col = q_ptr->px;
9855
9856 /* Good target */
9857 return (TRUE);
9858 }
9859 }
9860
9861 /* Assume no target */
9862 return (FALSE);
9863 }
9864
9865
9866
9867 /*
9868 * Hack -- help "select" a location (see below)
9869 */
9870 s16b target_pick(int Ind, int y1, int x1, int dy, int dx)
9871 {
9872 player_type *p_ptr = Players[Ind];
9873 int i, v;
9874 int x2, y2, x3, y3, x4, y4;
9875 int b_i = -1, b_v = 9999;
9876
9877 /* Scan the locations */
9878 for (i = 0; i < p_ptr->target_n; i++) {
9879 /* Point 2 */
9880 x2 = p_ptr->target_x[i];
9881 y2 = p_ptr->target_y[i];
9882
9883 /* Directed distance */
9884 x3 = (x2 - x1);
9885 y3 = (y2 - y1);
9886
9887 /* Verify quadrant */
9888 if (dx && (x3 * dx <= 0)) continue;
9889 if (dy && (y3 * dy <= 0)) continue;
9890
9891 /* Absolute distance */
9892 x4 = ABS(x3);
9893 y4 = ABS(y3);
9894
9895 /* Verify quadrant */
9896 if (dy && !dx && (x4 > y4)) continue;
9897 if (dx && !dy && (y4 > x4)) continue;
9898
9899 /* Approximate Double Distance */
9900 v = ((x4 > y4) ? (x4 + x4 + y4) : (y4 + y4 + x4));
9901
9902 /* XXX XXX XXX Penalize location */
9903
9904 /* Track best */
9905 if ((b_i >= 0) && (v >= b_v)) continue;
9906
9907 /* Track best */
9908 b_i = i; b_v = v;
9909 }
9910
9911 /* Result */
9912 return (b_i);
9913 }
9914
9915
9916 /*
9917 * Set a new target. This code can be called from "get_aim_dir()"
9918 *
9919 * The target must be on the current panel. Consider the use of
9920 * "panel_bounds()" to allow "off-panel" targets, perhaps by using
9921 * some form of "scrolling" the map around the cursor. XXX XXX XXX
9922 *
9923 * That is, consider the possibility of "auto-scrolling" the screen
9924 * while the cursor moves around. This may require changes in the
9925 * "update_mon()" code to allow "visibility" even if off panel.
9926 *
9927 * Hack -- targetting an "outer border grid" may be dangerous,
9928 * so this is not currently allowed.
9929 *
9930 * You can now use the direction keys to move among legal monsters,
9931 * just like the new "look" function allows the use of direction
9932 * keys to move amongst interesting locations.
9933 */
9934 static bool autotarget = FALSE;
9935 bool target_set(int Ind, int dir)
9936 {
9937 player_type *p_ptr = Players[Ind], *q_ptr;
9938 struct worldpos *wpos = &p_ptr->wpos;
9939 int i, m, idx;
9940 int y;
9941 int x;
9942 // bool flag = TRUE;
9943 bool flag = autotarget;
9944 char out_val[160];
9945 cave_type *c_ptr;
9946 monster_type *m_ptr;
9947 cave_type **zcave;
9948 if (!(zcave = getcave(wpos))) return(FALSE);
9949
9950
9951 if (!dir) {
9952 x = p_ptr->px;
9953 y = p_ptr->py;
9954
9955 /* Go ahead and turn off target mode */
9956 p_ptr->target_who = 0;
9957
9958 /* Turn off health tracking */
9959 health_track(Ind, 0);
9960
9961
9962 /* Reset "target" array */
9963 p_ptr->target_n = 0;
9964
9965 /* Collect "target-able" monsters */
9966 for (i = 1; i < m_max; i++) {
9967 monster_type *m_ptr = &m_list[i];
9968
9969 /* Skip "dead" monsters */
9970 if (!m_ptr->r_idx) continue;
9971
9972 /* Skip monsters not on this depth */
9973 if (!inarea(&m_ptr->wpos, wpos)) continue;
9974
9975 /* Ignore "unreasonable" monsters */
9976 if (!target_able(Ind, i)) continue;
9977
9978 /* Save this monster index */
9979 p_ptr->target_x[p_ptr->target_n] = m_ptr->fx;
9980 p_ptr->target_y[p_ptr->target_n] = m_ptr->fy;
9981 p_ptr->target_state[p_ptr->target_n] = m_ptr->csleep ? 1 : 0;
9982 p_ptr->target_n++;
9983 }
9984
9985 /* Collect "target-able" players */
9986 for (i = 1; i <= NumPlayers; i++) {
9987 /* Acquire pointer */
9988 q_ptr = Players[i];
9989
9990 /* Don't target yourself */
9991 if (i == Ind) continue;
9992
9993 /* Skip unconnected players */
9994 if (q_ptr->conn == NOT_CONNECTED) continue;
9995
9996 /* Ignore players we aren't hostile to */
9997 if (!check_hostile(Ind, i)) {
9998 continue;
9999 }
10000 /* Ignore "unreasonable" players */
10001 if (!target_able(Ind, 0 - i)) continue;
10002
10003 /* Save the player index */
10004 p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10005 p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10006 p_ptr->target_state[p_ptr->target_n] = q_ptr->afk ? 1 : 0; /* AFK players count as 'asleep' ;) */
10007 p_ptr->target_n++;
10008 }
10009
10010 /* Set the sort hooks */
10011 ang_sort_extra_comp = ang_sort_extra_comp_distance;
10012 ang_sort_extra_swap = ang_sort_extra_swap_distance;
10013
10014 /* Sort the positions */
10015 ang_sort_extra(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_state, p_ptr->target_n);
10016
10017 /* Collect indices */
10018 for (i = 0; i < p_ptr->target_n; i++) {
10019 c_ptr = &zcave[p_ptr->target_y[i]][p_ptr->target_x[i]];
10020 p_ptr->target_idx[i] = c_ptr->m_idx;
10021 }
10022
10023 /* Start near the player */
10024 m = 0;
10025 } else if (dir >= 128) {
10026 /* Initialize if needed */
10027 if (dir == 128) {
10028 p_ptr->target_col = p_ptr->px;
10029 p_ptr->target_row = p_ptr->py;
10030 } else {
10031 y = p_ptr->target_row + ddy[dir - 128];
10032 x = p_ptr->target_col + ddx[dir - 128];
10033 if (!in_bounds(y, x)) return FALSE; /* paranoia (won't harm, but seems weird) */
10034 p_ptr->target_row = y;
10035 p_ptr->target_col = x;
10036 }
10037
10038 /* Info */
10039 strcpy(out_val, "[<dir>, t, q] ");
10040
10041 /* Tell the client */
10042 Send_target_info(Ind, p_ptr->target_col - p_ptr->panel_col_prt, p_ptr->target_row - p_ptr->panel_row_prt, out_val);
10043
10044 /* Check for completion */
10045 if (dir == 128 + 5) {
10046 p_ptr->target_who = MAX_M_IDX + 1;
10047 return TRUE;
10048 }
10049
10050 /* Done */
10051 return FALSE;
10052 } else {
10053 /* Start where we last left off */
10054 m = p_ptr->look_index;
10055
10056 /* Reset the locations */
10057 for (i = 0; i < p_ptr->target_n; i++) {
10058 if (p_ptr->target_idx[i] > 0) {
10059 m_ptr = &m_list[p_ptr->target_idx[i]];
10060
10061 p_ptr->target_y[i] = m_ptr->fy;
10062 p_ptr->target_x[i] = m_ptr->fx;
10063 } else if (p_ptr->target_idx[i] < 0) {
10064 q_ptr = Players[0 - p_ptr->target_idx[i]];
10065
10066 p_ptr->target_y[i] = q_ptr->py;
10067 p_ptr->target_x[i] = q_ptr->px;
10068 }
10069 }
10070
10071 /* Find a new monster */
10072 i = target_pick(Ind, p_ptr->target_y[m], p_ptr->target_x[m], ddy[dir], ddx[dir]);
10073
10074 /* Use that monster */
10075 if (i > 0) {
10076 m = i;
10077
10078 #if 0 /* enable when this targetting method is fixed: */
10079 /* Currently you cannot select any available target, even though you can look at it,
10080 probably a problem in target_pick(). */
10081 /* Also make 'l'ooking at a monster target it, probably. (p_ptr->look_index vs p_ptr->target_who) */
10082 if (p_ptr->target_idx[i] > 0) {
10083 m_ptr = &m_list[p_ptr->target_idx[i]];
10084 snprintf(out_val, sizeof(out_val), "%s%s (Lv %d, %s%s)",
10085 ((r_info[m_ptr->r_idx].flags1 & RF1_UNIQUE) && p_ptr->r_killed[m_ptr->r_idx] == 1) ? "\377D" : "",
10086 r_name_get(&m_list[p_ptr->target_idx[m]]),
10087 m_ptr->level, look_mon_desc(p_ptr->target_idx[m]),
10088 m_ptr->clone ? ", clone" : "");
10089 } else if (p_ptr->target_idx[i] < 0) {
10090 q_ptr = Players[0 - p_ptr->target_idx[i]];
10091 if (q_ptr->body_monster) {
10092 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));
10093 } else {
10094 snprintf(out_val, sizeof(out_val), "%s the %s %s", q_ptr->name, get_prace(q_ptr), get_ptitle(q_ptr, FALSE));
10095 }
10096 }
10097 // strcpy(out_val, "[<dir>, t, q] ");
10098 Send_target_info(Ind, p_ptr->target_x[m] - p_ptr->panel_col_prt, p_ptr->target_y[m] - p_ptr->panel_row_prt, out_val);
10099 #endif
10100 }
10101 }
10102
10103 /* Target monsters */
10104 if (flag && p_ptr->target_n && p_ptr->target_idx[m] > 0) {
10105 y = p_ptr->target_y[m];
10106 x = p_ptr->target_x[m];
10107 idx = p_ptr->target_idx[m];
10108
10109 m_ptr = &m_list[idx];
10110
10111 /* Hack -- Track that monster race */
10112 recent_track(m_ptr->r_idx);
10113
10114 /* Hack -- Track that monster */
10115 health_track(Ind, idx);
10116
10117 /* Hack -- handle stuff */
10118 handle_stuff(Ind);
10119
10120 /* Describe, prompt for recall */
10121 snprintf(out_val, sizeof(out_val),
10122 "%s{%d} (%s) [<dir>, q, t] ",
10123 r_name_get(m_ptr),
10124 m_ptr->level,
10125 look_mon_desc(idx));
10126
10127 /* Tell the client about it */
10128 Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10129 } else if (flag && p_ptr->target_n && p_ptr->target_idx[m] < 0) {
10130 y = p_ptr->target_y[m];
10131 x = p_ptr->target_x[m];
10132 idx = p_ptr->target_idx[m];
10133
10134 q_ptr = Players[0 - idx];
10135
10136 /* Hack -- Track that player */
10137 health_track(Ind, idx);
10138
10139 /* Hack -- handle stuff */
10140 handle_stuff(Ind);
10141
10142 /* Describe */
10143 snprintf(out_val, sizeof(out_val), "%s [<dir>, q, t] ", q_ptr->name);
10144
10145 /* Tell the client about it */
10146 Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10147 }
10148
10149 /* Remember current index */
10150 p_ptr->look_index = m;
10151
10152 /* Set target */
10153 if (dir == 5 || autotarget) {
10154 p_ptr->target_who = p_ptr->target_idx[m];
10155 p_ptr->target_col = p_ptr->target_x[m];
10156 p_ptr->target_row = p_ptr->target_y[m];
10157
10158 /* Track */
10159 if (p_ptr->target_who) health_track(Ind, p_ptr->target_who);
10160 }
10161
10162 /* Failure */
10163 if (!p_ptr->target_who) return (FALSE);
10164
10165 /* Clear target info */
10166 p_ptr->target_n = 0;
10167
10168 /* Success */
10169 return (TRUE);
10170 }
10171
10172
10173 #if 0 /* not functional atm, replaced by target-closest strategy */
10174
10175 /* targets the most wounded teammate. should be useful for stuff like
10176 * heal other and teleport macros. -ADA-
10177 *
10178 * Now this function can take 3rd arg which specifies which player to
10179 * set the target.
10180 * This part was written by Asclep(DEG); thx for his courtesy!
10181 * */
10182
10183 bool target_set_friendly(int Ind, int dir, ...)
10184 {
10185 va_list ap;
10186 player_type *p_ptr = Players[Ind], *q_ptr;
10187 struct worldpos *wpos = &p_ptr->wpos;
10188 cave_type **zcave;
10189 int i, m, castplayer, idx;
10190 int y;
10191 int x;
10192 char out_val[160];
10193 cave_type *c_ptr;
10194
10195 if (!(zcave = getcave(wpos))) return(FALSE);
10196
10197 va_start(ap,dir);
10198 castplayer = va_arg(ap,int);
10199 va_end(ap);
10200
10201 x = p_ptr->px;
10202 y = p_ptr->py;
10203
10204 /* Go ahead and turn off target mode */
10205 p_ptr->target_who = 0;
10206
10207 /* Turn off health tracking */
10208 health_track(Ind, 0);
10209
10210
10211 /* Reset "target" array */
10212 p_ptr->target_n = 0;
10213
10214 // if (!((castplayer > 0) && (castplayer < 20)))
10215 if (!((0 < castplayer) && (castplayer <= NumPlayers))) {
10216 /* Collect "target-able" players */
10217 for (i = 1; i <= NumPlayers; i++) {
10218 /* Acquire pointer */
10219 q_ptr = Players[i];
10220
10221 /* Don't target yourself */
10222 if (i == Ind) continue;
10223
10224 /* Skip unconnected players */
10225 if (q_ptr->conn == NOT_CONNECTED) continue;
10226
10227 /* Ignore players we aren't friends with */
10228 if (check_hostile(Ind, i)) continue;
10229
10230 /* if we are in party, only help members */
10231 if (p_ptr->party && (!player_in_party(p_ptr->party, i))) continue;
10232
10233 /* Ignore "unreasonable" players */
10234 if (!target_able(Ind, 0 - i)) continue;
10235
10236 /* Save the player index */
10237 p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10238 p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10239 p_ptr->target_idx[p_ptr->target_n] = i;
10240 p_ptr->target_n++;
10241 }
10242 } else {
10243 /* Acquire pointer */
10244 q_ptr = Players[castplayer];
10245
10246 /* Skip unconnected players */
10247 if (q_ptr->conn == NOT_CONNECTED) return FALSE;
10248
10249 /* Ignore "unreasonable" players */
10250 if (!target_able(Ind, 0 - castplayer)) return FALSE;
10251
10252 /* Save the player index */
10253 p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10254 p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10255 p_ptr->target_idx[p_ptr->target_n] = castplayer;
10256 p_ptr->target_n++;
10257 }
10258
10259
10260 /* Set the sort hooks */
10261 ang_sort_comp = ang_sort_comp_distance;
10262 ang_sort_swap = ang_sort_swap_distance;
10263
10264 /* Sort the positions */
10265 wounded_player_target_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_idx, p_ptr->target_n);
10266
10267 m = 0;
10268
10269 /* too lazy to handle dirs right now */
10270
10271 /* handle player target.... */
10272 if (p_ptr->target_n) {
10273 y = p_ptr->target_y[m];
10274 x = p_ptr->target_x[m];
10275 idx = p_ptr->target_idx[m];
10276
10277 c_ptr = &zcave[y][x];
10278
10279 q_ptr = Players[idx];
10280
10281 /* Hack -- Track that player */
10282 health_track(Ind, 0 - idx);
10283
10284 /* Hack -- handle stuff */
10285 handle_stuff(Ind);
10286
10287 /* Describe */
10288 snprintf(out_val, sizeof(out_val), "%s targetted.", q_ptr->name);
10289
10290 /* Tell the client about it */
10291 Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10292 }
10293
10294 /* Remember current index */
10295 p_ptr->look_index = m;
10296
10297 p_ptr->target_who = 0 - p_ptr->target_idx[m];
10298 p_ptr->target_col = p_ptr->target_x[m];
10299 p_ptr->target_row = p_ptr->target_y[m];
10300
10301 /* Failure */
10302 if (!p_ptr->target_who) return (FALSE);
10303
10304 /* Clear target info */
10305 p_ptr->target_n = 0;
10306
10307 /* Success */
10308 return (TRUE);
10309 }
10310
10311 #else
10312
10313 /* targets closest player */
10314 bool target_set_friendly(int Ind, int dir)
10315 {
10316 player_type *p_ptr = Players[Ind], *q_ptr;
10317 struct worldpos *wpos = &p_ptr->wpos;
10318 cave_type **zcave;
10319 int i, m, idx;
10320 int y;
10321 int x;
10322 char out_val[160];
10323
10324 if (!(zcave = getcave(wpos))) return(FALSE);
10325
10326 x = p_ptr->px;
10327 y = p_ptr->py;
10328
10329 /* Go ahead and turn off target mode */
10330 p_ptr->target_who = 0;
10331
10332 /* Turn off health tracking */
10333 health_track(Ind, 0);
10334
10335
10336 /* Reset "target" array */
10337 p_ptr->target_n = 0;
10338
10339 for (i = 1; i <= NumPlayers; i++) {
10340 q_ptr = Players[i];
10341
10342 /* Don't target yourself */
10343 if (i == Ind) continue;
10344
10345 /* Skip unconnected players */
10346 if (q_ptr->conn == NOT_CONNECTED) continue;
10347
10348 /* Ignore players we aren't friends with */
10349 if (check_hostile(Ind, i)) continue;
10350
10351 /* if we are in party, only help members */
10352 if (p_ptr->party && (!player_in_party(p_ptr->party, i))) continue;
10353
10354 /* Ignore "unreasonable" players */
10355 if (!target_able(Ind, 0 - i)) continue;
10356
10357 /* Save the player index */
10358 p_ptr->target_x[p_ptr->target_n] = q_ptr->px;
10359 p_ptr->target_y[p_ptr->target_n] = q_ptr->py;
10360 p_ptr->target_idx[p_ptr->target_n] = i;
10361 p_ptr->target_n++;
10362 }
10363
10364 #if 1
10365 /* Sort the positions */
10366 wounded_player_target_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_idx, p_ptr->target_n);
10367 #else //TODO
10368 /* Set the sort hooks */
10369 ang_sort_comp = ang_sort_comp_distance;
10370 ang_sort_swap = ang_sort_swap_distance;
10371
10372 /* Sort the positions */
10373 ang_sort(Ind, p_ptr->target_x, p_ptr->target_y, p_ptr->target_n);
10374 #endif
10375
10376 m = 0;
10377
10378 /* handle player target.... */
10379 if (p_ptr->target_n) {
10380 y = p_ptr->target_y[m];
10381 x = p_ptr->target_x[m];
10382 idx = p_ptr->target_idx[m];
10383
10384 /* Hack -- Track that player */
10385 health_track(Ind, 0 - idx);
10386
10387 /* Hack -- handle stuff */
10388 handle_stuff(Ind);
10389
10390 /* Describe */
10391 snprintf(out_val, sizeof(out_val), "%s targetted.", Players[idx]->name);
10392
10393 /* Tell the client about it */
10394 Send_target_info(Ind, x - p_ptr->panel_col_prt, y - p_ptr->panel_row_prt, out_val);
10395 }
10396
10397 /* Remember current index */
10398 p_ptr->look_index = m;
10399
10400 p_ptr->target_who = 0 - p_ptr->target_idx[m];
10401 p_ptr->target_col = p_ptr->target_x[m];
10402 p_ptr->target_row = p_ptr->target_y[m];
10403
10404 /* Failure */
10405 if (!p_ptr->target_who) return (FALSE);
10406
10407 /* Clear target info */
10408 p_ptr->target_n = 0;
10409
10410 /* Success */
10411 return (TRUE);
10412 }
10413
10414 #endif
10415
10416
10417
10418 /*
10419 * Get an "aiming direction" from the user.
10420 *
10421 * The "dir" is loaded with 1,2,3,4,6,7,8,9 for "actual direction", and
10422 * "0" for "current target", and "-1" for "entry aborted".
10423 *
10424 * Note that "Force Target", if set, will pre-empt user interaction,
10425 * if there is a usable target already set.
10426 *
10427 * Note that confusion over-rides any (explicit?) user choice.
10428 *
10429 * We just ask the client to send us a direction, unless we are confused --KLJ--
10430 */
10431 bool get_aim_dir(int Ind)
10432 {
10433 int dir;
10434 player_type *p_ptr = Players[Ind];
10435
10436 if (p_ptr->auto_target) {
10437 autotarget = TRUE;
10438 target_set(Ind, 0);
10439 autotarget = FALSE;
10440 }
10441
10442 /* Hack -- auto-target if requested */
10443 if (p_ptr->use_old_target && target_okay(Ind)) {
10444 dir = 5;
10445
10446 /* XXX XXX Pretend we read this direction from the network */
10447 Handle_direction(Ind, dir);
10448 return (TRUE);
10449 }
10450
10451 Send_direction(Ind);
10452
10453 return (TRUE);
10454 }
10455
10456
10457 bool get_item(int Ind, signed char tester_hook) { //paranoia @ 'signed' char =-p
10458 Send_item_request(Ind, tester_hook);
10459
10460 return (TRUE);
10461 }
10462
10463 /*
10464 * Allows to travel both vertical/horizontal using Recall;
10465 * probably wilderness(horizontal) travel will be made by other means
10466 * in the future.
10467 *
10468 * Also, player_type doesn't contain the max.depth for each dungeon...
10469 * Currently, this function uses getlevel() to determine the max.depth
10470 * for each dungeon, but this should be replaced by actual depths
10471 * a player has ever been. - Jir -
10472 */
10473 void set_recall_depth(player_type * p_ptr, object_type * o_ptr) {
10474 // int recall_depth = 0;
10475 // worldpos goal;
10476
10477 unsigned char * inscription = (unsigned char *) quark_str(o_ptr->note);
10478
10479 /* default to the players maximum depth */
10480 p_ptr->recall_pos.wx = p_ptr->wpos.wx;
10481 p_ptr->recall_pos.wy = p_ptr->wpos.wy;
10482 #ifdef SEPARATE_RECALL_DEPTHS
10483 p_ptr->recall_pos.wz = (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags &
10484 WILD_F_DOWN) ? 0 - get_recall_depth(&p_ptr->wpos, p_ptr) : get_recall_depth(&p_ptr->wpos, p_ptr);
10485 #else
10486 p_ptr->recall_pos.wz = (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags &
10487 WILD_F_DOWN) ? 0 - p_ptr->max_dlv : p_ptr->max_dlv;
10488 #endif
10489
10490 #if 0
10491 p_ptr->recall_pos.wz = (wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags &
10492 WILD_F_DOWN) ? 0 - p_ptr->max_dlv :
10493 ((wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags & WILD_F_UP) ?
10494 p_ptr->max_dlv : 0);
10495
10496 goal.wx = p_ptr->wpos.wx;
10497 goal.wy = p_ptr->wpos.wy;
10498 // goal.wz = 0 - p_ptr->max_dlv; // hack -- default to 'dungeon'
10499 #endif // 0
10500
10501 /* check for a valid inscription */
10502 if (inscription == NULL) return;
10503
10504 /* scan the inscription for @R */
10505 while (*inscription != '\0') {
10506 if (*inscription == '@') {
10507 inscription++;
10508
10509 /* a valid @R has been located */
10510 if (*inscription == 'R') {
10511 inscription++;
10512 /* @RW for World(Wilderness) travel */
10513 /* It would be also amusing to limit the distance.. */
10514 if ((*inscription == 'W') || (*inscription == 'X')) {
10515 unsigned char * next;
10516 inscription++;
10517 p_ptr->recall_pos.wx = atoi((char *)inscription) % MAX_WILD_X;
10518 p_ptr->recall_pos.wz = 0;
10519 next = (unsigned char *)strchr((char *)inscription,',');
10520 if (next) {
10521 if (++next) p_ptr->recall_pos.wy = atoi((char*)next) % MAX_WILD_Y;
10522 }
10523 }
10524 else if (*inscription == 'Y') {
10525 inscription++;
10526 p_ptr->recall_pos.wy = atoi((char*)inscription) % MAX_WILD_Y;
10527 p_ptr->recall_pos.wz = 0;
10528 }
10529 #if 1
10530 /* @RT for inter-Town travels (not fully implemented yet) */
10531 else if (*inscription == 'T') {
10532 inscription++;
10533 p_ptr->recall_pos.wx = p_ptr->town_x;
10534 p_ptr->recall_pos.wy = p_ptr->town_y;
10535 p_ptr->recall_pos.wz = 0;
10536 }
10537 #endif
10538 else {
10539 int tmp = 0;
10540 if (*inscription == 'Z') inscription++;
10541
10542 /* convert the inscription into a level index */
10543 if ((tmp = atoi((char*)inscription) /
10544 (p_ptr->depth_in_feet ? 50 : 1)))
10545 p_ptr->recall_pos.wz = tmp;
10546
10547 /* catch user mistake: missing W in @RWx,y */
10548 while (*inscription != '\0') {
10549 if (*inscription == ',') {
10550 p_ptr->recall_pos.wz = 0;
10551 return;
10552 }
10553 inscription++;
10554 }
10555 }
10556 }
10557 }
10558 inscription++;
10559 }
10560
10561 /* sanity check or crash */
10562 if (p_ptr->recall_pos.wx < 0) p_ptr->recall_pos.wx = 0;
10563 if (p_ptr->recall_pos.wy < 0) p_ptr->recall_pos.wy = 0;
10564 }
10565
10566 bool set_recall_timer(int Ind, int v) {
10567 player_type *p_ptr = Players[Ind];
10568 bool notice = FALSE;
10569
10570 /* don't accidentally recall players in Ironman Deep Dive Challenge
10571 by some effect (spell/Morgoth) */
10572 if (!is_admin(p_ptr) &&
10573 in_irondeepdive(&p_ptr->wpos) && (p_ptr->mode & MODE_DED_IDDC) && !irondeepdive_bottom(&p_ptr->wpos)) {
10574 msg_print(Ind, "\377oThere is some static discharge in the air around you, but nothing happens.");
10575 return FALSE;
10576 }
10577
10578 /* Hack -- Force good values */
10579 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
10580
10581 /* Open */
10582 if (v) {
10583 if (!p_ptr->word_recall) {
10584 msg_print(Ind, "\377oThe air about you becomes charged...");
10585 notice = TRUE;
10586 }
10587 }
10588 /* Shut */
10589 else {
10590 if (p_ptr->word_recall) {
10591 msg_print(Ind, "\377oA tension leaves the air around you...");
10592 notice = TRUE;
10593 }
10594 }
10595
10596 /* Use the value */
10597 p_ptr->word_recall = v;
10598
10599 /* Nothing to notice */
10600 if (!notice) return (FALSE);
10601
10602 /* Disturb */
10603 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
10604
10605 /* Redraw the depth(colour) */
10606 p_ptr->redraw |= (PR_DEPTH);
10607
10608 /* Handle stuff */
10609 handle_stuff(Ind);
10610
10611 /* Result */
10612 return (TRUE);
10613 }
10614
10615 bool set_recall(int Ind, int v, object_type * o_ptr) {
10616 player_type *p_ptr = Players[Ind];
10617
10618 /* don't accidentally recall players in Ironman Deep Dive Challenge
10619 by some effect (spell/Morgoth) */
10620 if (!is_admin(p_ptr) &&
10621 in_irondeepdive(&p_ptr->wpos) && (p_ptr->mode & MODE_DED_IDDC) && !irondeepdive_bottom(&p_ptr->wpos)) {
10622 msg_print(Ind, "\377oThere is some static discharge in the air around you, but nothing happens.");
10623 return FALSE;
10624 }
10625
10626 if (!p_ptr->word_recall) {
10627 set_recall_depth(p_ptr, o_ptr);
10628 return (set_recall_timer(Ind, v));
10629 } else {
10630 return (set_recall_timer(Ind, 0));
10631 }
10632
10633 }
10634
10635 void telekinesis_aux(int Ind, int item) {
10636 player_type *p_ptr = Players[Ind], *p2_ptr;
10637 object_type *q_ptr, *o_ptr = p_ptr->current_telekinesis;
10638 int Ind2;
10639 char *inscription, *scan;
10640 #ifdef TELEKINESIS_GETITEM_SERVERSIDE
10641 int max_weight = p_ptr->current_telekinesis_mw;
10642 #endif
10643
10644 p_ptr->current_telekinesis = NULL;
10645
10646 /* Get the item (in the pack) */
10647 if (item >= 0) {
10648 q_ptr = &p_ptr->inventory[item];
10649 } else { /* Get the item (on the floor) */
10650 msg_print(Ind, "You must carry the object to teleport it.");
10651 return;
10652 }
10653
10654 Ind2 = get_player(Ind, o_ptr);
10655 if (!Ind2) return;
10656 p2_ptr = Players[Ind2];
10657
10658 #ifdef TELEKINESIS_GETITEM_SERVERSIDE
10659 if (q_ptr->weight * q_ptr->number > max_weight) {
10660 msg_format(Ind, "The item%s too heavy.", q_ptr->number > 1 ? "s are" : " is");
10661 return;
10662 }
10663 #endif
10664
10665 if (p2_ptr->ghost && !is_admin(p_ptr)) {
10666 msg_print(Ind, "You cannot send items to ghosts!");
10667 return;
10668 }
10669
10670 if (compat_pmode(Ind, Ind2, FALSE) && !is_admin(p_ptr)) {
10671 msg_format(Ind, "You cannot contact %s beings!", compat_pmode(Ind, Ind2, FALSE));
10672 return;
10673 }
10674
10675 /* prevent winners picking up true arts accidentally */
10676 if (true_artifact_p(q_ptr) && !winner_artifact_p(q_ptr) &&
10677 p2_ptr->total_winner && cfg.kings_etiquette) {
10678 msg_print(Ind, "Royalties may not own true artifacts!");
10679 if (!is_admin(p2_ptr)) return;
10680 }
10681
10682 /* the_sandman: item lvl restrictions are disabled in rpg */
10683 #ifndef RPG_SERVER
10684 if ((q_ptr->owner) && (q_ptr->owner != p2_ptr->id) &&
10685 (q_ptr->level > p2_ptr->lev || q_ptr->level == 0)) {
10686 if (cfg.anti_cheeze_telekinesis) {
10687 msg_print(Ind, "The target isn't powerful enough yet to receive that item!");
10688 if (!is_admin(p_ptr)) return;
10689 }
10690 if (true_artifact_p(q_ptr) && cfg.anti_arts_pickup)
10691 // if (artifact_p(q_ptr) && cfg.anti_arts_pickup)
10692 {
10693 msg_print(Ind, "The target isn't powerful enough yet to receive that artifact!");
10694 if (!is_admin(p_ptr)) return;
10695 }
10696 }
10697 #endif
10698 if ((k_info[q_ptr->k_idx].flags5 & TR5_WINNERS_ONLY) &&
10699 #ifdef FALLEN_WINNERSONLY
10700 !p_ptr->once_winner
10701 #else
10702 !p_ptr->total_winner
10703 #endif
10704 ) {
10705 msg_print(Ind, "Only royalties are powerful enough to receive that item!");
10706 if (!is_admin(p_ptr)) return;
10707 }
10708
10709 if (cfg.anti_arts_send && artifact_p(q_ptr) && !is_admin(p_ptr)) {
10710 msg_print(Ind, "The artifact resists telekinesis!");
10711 return;
10712 }
10713
10714 /* questor items cannot be 'dropped', only destroyed! */
10715 if (q_ptr->questor) {
10716 msg_print(Ind, "This item cannot be sent by telekinesis!");
10717 return;
10718 }
10719
10720 /* Add a check for full inventory of target player - mikaelh */
10721 if (!inven_carry_okay(Ind2, q_ptr, 0x0)) {
10722 msg_print(Ind, "Item doesn't fit into the target player's inventory.");
10723 return;
10724 }
10725
10726 /* Check that the target player isn't shopping - mikaelh */
10727 if (p2_ptr->store_num != -1) {
10728 msg_print(Ind, "Target player is currently shopping.");
10729 return;
10730 }
10731
10732 /* You cannot send artifact */
10733 if ((cfg.anti_arts_hoard || p_ptr->total_winner) && true_artifact_p(q_ptr) && !is_admin(p_ptr)) {
10734 msg_print(Ind, "You have an acute feeling of loss!");
10735 handle_art_d(q_ptr->name1);
10736 } else {
10737 char o_name[ONAME_LEN];
10738 /* If they're not within the same dungeon level,
10739 they cannot reach each other if
10740 one is in an IRON or NO_RECALL dungeon/tower */
10741 if (!inarea(&p_ptr->wpos, &p2_ptr->wpos) && !is_admin(p_ptr)) {
10742 dungeon_type *d_ptr;
10743 d_ptr = getdungeon(&p_ptr->wpos);
10744 if(d_ptr && ((d_ptr->flags2 & (DF2_IRON | DF2_NO_RECALL_INTO)) || (d_ptr->flags1 & DF1_NO_RECALL))){
10745 msg_print(Ind, "You are unable to contact that player");
10746 return;
10747 }
10748 d_ptr = getdungeon(&p2_ptr->wpos);
10749 if(d_ptr && ((d_ptr->flags2 & (DF2_IRON | DF2_NO_RECALL_INTO)) || (d_ptr->flags1 & DF1_NO_RECALL))){
10750 msg_print(Ind, "You are unable to contact that player");
10751 return;
10752 }
10753 }
10754
10755 if (!(p2_ptr->esp_link_flags & LINKF_TELEKIN)) {
10756 msg_print(Ind, "That player isn't concentrating on telekinesis at the moment.");
10757 if (!is_admin(p_ptr)) return;
10758 }
10759
10760 /* Log it - mikaelh */
10761 object_desc_store(Ind, o_name, q_ptr, TRUE, 3);
10762 s_printf("(Tele) Item transaction from %s(%d) to %s(%d):\n %s\n", p_ptr->name, p_ptr->lev, Players[Ind2]->name, Players[Ind2]->lev, o_name);
10763
10764 if (true_artifact_p(q_ptr)) a_info[q_ptr->name1].carrier = p_ptr->id;
10765
10766 /* Highlander Tournament: Don't allow transactions before it begins */
10767 if (!p2_ptr->max_exp) {
10768 msg_print(Ind2, "You gain a tiny bit of experience from receiving an item via telekinesis.");
10769 gain_exp(Ind2, 1);
10770 }
10771
10772 /* Remove dangerous inscriptions - mikaelh */
10773 if (q_ptr->note && p2_ptr->clear_inscr) {
10774 scan = inscription = strdup(quark_str(q_ptr->note));
10775
10776 while (*scan != '\0') {
10777 if (*scan == '@') {
10778 /* Replace @ with space */
10779 *scan = ' ';
10780 }
10781 scan++;
10782 }
10783
10784 q_ptr->note = quark_add(inscription);
10785 free(inscription);
10786 }
10787
10788 /* Actually teleport the object to the player inventory */
10789 can_use(Ind2, q_ptr); /* change owner */
10790 inven_carry(Ind2, q_ptr);
10791
10792 /* Combine the pack */
10793 p2_ptr->notice |= (PN_COMBINE);
10794
10795 /* Window stuff */
10796 p2_ptr->window |= (PW_INVEN | PW_EQUIP);
10797
10798 msg_format(Ind2, "You are hit by a powerful magic wave from %s.", p_ptr->name);
10799 }
10800
10801 #ifdef USE_SOUND_2010
10802 sound_item(Ind, q_ptr->tval, q_ptr->sval, "pickup_");
10803 #endif
10804
10805 /* Wipe it */
10806 inven_item_increase(Ind, item, -99);
10807 inven_item_describe(Ind, item);
10808 inven_item_optimize(Ind, item);
10809
10810 /* Combine the pack */
10811 p_ptr->notice |= (PN_COMBINE);
10812
10813 /* Window stuff */
10814 p_ptr->window |= (PW_INVEN | PW_EQUIP);
10815
10816 }
10817
10818 int get_player(int Ind, object_type *o_ptr) {
10819 bool ok = FALSE;
10820 int Ind2 = 0;
10821 unsigned char * inscription = (unsigned char *) quark_str(o_ptr->note);
10822 char ins2[80];
10823
10824 /* check for a valid inscription */
10825 if (inscription == NULL) {
10826 // msg_print(Ind, "Nobody to use the power with.");
10827 msg_print(Ind, "\377yNo target player specified.");
10828 return 0;
10829 }
10830
10831 /* scan the inscription for @P */
10832 while ((*inscription != '\0') && !ok) {
10833 if (*inscription == '@') {
10834 inscription++;
10835
10836 /* a valid @P has been located */
10837 if (*inscription == 'P') {
10838 inscription++;
10839
10840 /* stop at '#' symbol, to allow more inscription
10841 variety without disturbing player name parsing */
10842 strcpy(ins2, (cptr)inscription);
10843 if (strchr(ins2, '#')) *(strchr(ins2, '#')) = '\0';
10844
10845 // Ind2 = find_player_name(inscription);
10846 // Ind2 = name_lookup_loose(Ind, (cptr)inscription,< FALSE, FALSE);
10847 Ind2 = name_lookup_loose(Ind, ins2, FALSE, FALSE);
10848 if (Ind2) ok = TRUE;
10849 }
10850 }
10851 inscription++;
10852 }
10853
10854 if (!ok) {
10855 msg_print(Ind, "\377yCouldn't find the target.");
10856 return 0;
10857 }
10858
10859 if (Ind == Ind2) {
10860 msg_print(Ind, "\377yYou cannot do that on yourself.");
10861 return 0;
10862 }
10863
10864 return Ind2;
10865 }
10866
10867 int get_monster(int Ind, object_type *o_ptr) {
10868 bool ok1 = TRUE, ok2 = TRUE;
10869 int r_idx = 0;
10870
10871 unsigned char * inscription = (unsigned char *) quark_str(o_ptr->note);
10872
10873 /* check for a valid inscription */
10874 if (inscription == NULL) {
10875 msg_print(Ind, "No monster specified.");
10876 return 0;
10877 }
10878
10879 /* scan the inscription for @M */
10880 while ((*inscription != '\0') && ok1 && ok2) {
10881 if (*inscription == '@') {
10882 inscription++;
10883
10884 /* a valid @M has been located */
10885 if (*inscription == 'M') {
10886 inscription++;
10887
10888 r_idx = atoi((cptr)inscription);
10889 if (r_idx < 1 || r_idx > MAX_R_IDX - 1) ok1 = FALSE;
10890 else if (!r_info[r_idx].name) ok1 = FALSE;
10891 else if (!Players[Ind]->r_killed[r_idx]) ok2 = FALSE;
10892 }
10893 }
10894 inscription++;
10895 }
10896
10897 if (!ok1) {
10898 msg_print(Ind, "That monster does not exist.");
10899 return 0;
10900 }
10901
10902 if (!ok2) {
10903 msg_print(Ind, "You haven't killed one of these monsters yet.");
10904 return 0;
10905 }
10906
10907 return r_idx;
10908 }
10909
10910 void blood_bond(int Ind, object_type *o_ptr) {
10911 player_type *p_ptr = Players[Ind], *p2_ptr;
10912 // bool ok = FALSE;
10913 int Ind2;
10914 player_list_type *pl_ptr;
10915 cave_type **zcave;
10916 cave_type *c_ptr;
10917
10918 if (p_ptr->pvpexception == 3) {
10919 msg_print(Ind, "Sorry, you're *not* allowed to attack other players.");
10920 return; /* otherwise, blood bond will result in insta-death */
10921 }
10922
10923 Ind2 = get_player(Ind, o_ptr);
10924 if (!Ind2) {
10925 msg_print(Ind, "\377oCouldn't blood bond because that player wasn't found.");
10926 return;
10927 }
10928 p2_ptr = Players[Ind2];
10929
10930 /* not during pvp-only or something (Highlander Tournament) */
10931 if (sector00separation &&
10932 ((p_ptr->wpos.wx == WPOS_SECTOR00_X && p_ptr->wpos.wy == WPOS_SECTOR00_Y) ||
10933 (p2_ptr->wpos.wx == WPOS_SECTOR00_X && p2_ptr->wpos.wy == WPOS_SECTOR00_Y))) {
10934 msg_print(Ind, "You cannot blood bond right now.");
10935 return;
10936 }
10937
10938 if (check_blood_bond(Ind, Ind2)) {
10939 msg_format(Ind, "You are already blood bonded with %s.", p2_ptr->name);
10940 return;
10941 }
10942
10943 /* To prevent an AFK player being teleported around: */
10944 if (p2_ptr->afk) {
10945 msg_print(Ind, "That player is currently AFK.");
10946 return;
10947 }
10948
10949 /* protect players in inns */
10950 if ((zcave = getcave(&p2_ptr->wpos))) {
10951 c_ptr = &zcave[p2_ptr->py][p2_ptr->px];
10952 if (f_info[c_ptr->feat].flags1 & FF1_PROTECTED) {
10953 msg_print(Ind, "That player currently dwells on protected grounds.");
10954 return;
10955 }
10956 }
10957
10958 MAKE(pl_ptr, player_list_type);
10959 pl_ptr->id = p2_ptr->id;
10960 if (p_ptr->blood_bond) {
10961 pl_ptr->next = p_ptr->blood_bond;
10962 } else {
10963 pl_ptr->next = NULL;
10964 }
10965 p_ptr->blood_bond = pl_ptr;
10966
10967 MAKE(pl_ptr, player_list_type);
10968 pl_ptr->id = p_ptr->id;
10969 if (p_ptr->blood_bond) {
10970 pl_ptr->next = p2_ptr->blood_bond;
10971 } else {
10972 pl_ptr->next = NULL;
10973 }
10974 p2_ptr->blood_bond = pl_ptr;
10975
10976 s_printf("BLOOD_BOND: %s blood bonds with %s\n", p_ptr->name, p2_ptr->name);
10977 msg_format(Ind, "\374\377cYou blood bond with %s.", p2_ptr->name);
10978 msg_format(Ind2, "\374%s blood bonds with you.", p_ptr->name);
10979 msg_broadcast_format(Ind, "\374\377c%s blood bonds with %s.", p_ptr->name, p2_ptr->name);
10980
10981 /* new: auto-hostile, circumventing town peace zone functionality: */
10982 add_hostility(Ind, p2_ptr->name, TRUE);
10983 add_hostility(Ind2, p_ptr->name, FALSE);
10984
10985 p_ptr->update |= PU_BONUS;
10986 p2_ptr->update |= PU_BONUS;
10987 }
10988
10989 bool check_blood_bond(int Ind, int Ind2)
10990 {
10991 player_type *p_ptr, *p2_ptr;
10992 player_list_type *pl_ptr;
10993
10994 p_ptr = Players[Ind];
10995 p2_ptr = Players[Ind2];
10996 if (!p2_ptr) return FALSE;
10997
10998 pl_ptr = p_ptr->blood_bond;
10999 while (pl_ptr) {
11000 if (pl_ptr->id == p2_ptr->id) return TRUE;
11001 pl_ptr = pl_ptr->next;
11002 }
11003 return FALSE;
11004 }
11005
11006 void remove_blood_bond(int Ind, int Ind2)
11007 {
11008 player_type *p_ptr, *p2_ptr;
11009 player_list_type *pl_ptr, *ppl_ptr;
11010
11011 p_ptr = Players[Ind];
11012 p2_ptr = Players[Ind2];
11013 if (!p2_ptr) return;
11014
11015 ppl_ptr = NULL;
11016 pl_ptr = p_ptr->blood_bond;
11017 while (pl_ptr)
11018 {
11019 if (pl_ptr->id == p2_ptr->id)
11020 {
11021 if (ppl_ptr)
11022 {
11023 ppl_ptr->next = pl_ptr->next;
11024 }
11025 else
11026 {
11027 /* First in the list */
11028 p_ptr->blood_bond = pl_ptr->next;
11029 }
11030 KILL(pl_ptr, player_list_type);
11031 return;
11032 }
11033 ppl_ptr = pl_ptr;
11034 pl_ptr = pl_ptr->next;
11035 }
11036 }
11037 #ifdef TELEKINESIS_GETITEM_SERVERSIDE
11038 bool telekinesis(int Ind, object_type *o_ptr, int max_weight) {
11039 player_type *p_ptr = Players[Ind];
11040
11041 get_item(Ind, ITH_MAX_WEIGHT + max_weight);
11042
11043 /* Clear any other pending actions */
11044 clear_current(Ind);
11045
11046 p_ptr->current_telekinesis = o_ptr;
11047 p_ptr->current_telekinesis_mw = max_weight;
11048
11049 return TRUE;
11050 }
11051 #endif
11052
11053 /* this has finally earned its own function, to make it easy for restoration to do this also */
11054 bool do_scroll_life(int Ind)
11055 {
11056 int x,y;
11057
11058 player_type * p_ptr = Players[Ind], *q_ptr;
11059 cave_type * c_ptr;
11060 cave_type **zcave;
11061 zcave = getcave(&p_ptr->wpos);
11062 if (!zcave) return(FALSE);
11063
11064 for (y = -1; y <= 1; y++) {
11065 for (x = -1; x <= 1; x++) {
11066 c_ptr = &zcave[p_ptr->py+y][p_ptr->px+x];
11067 if (c_ptr->m_idx < 0) {
11068 q_ptr = Players[0 - c_ptr->m_idx];
11069 if (q_ptr->ghost) {
11070 if (cave_floor_bold(zcave, p_ptr->py + y, p_ptr->px + x) &&
11071 !(c_ptr->info & CAVE_ICKY))
11072 {
11073 resurrect_player(0 - c_ptr->m_idx, 0);
11074 /* if player is not in town and resurrected on *TRUE* death level
11075 then this is a GOOD action. Reward the player */
11076 if (!istown(&p_ptr->wpos) && getlevel(&p_ptr->wpos) == q_ptr->died_from_depth) {
11077 u16b dal = 1 + ((2 * q_ptr->lev) / p_ptr->lev);
11078 if (p_ptr->align_good > dal)
11079 p_ptr->align_good -= dal;
11080 else p_ptr->align_good = 0;
11081 }
11082 return TRUE;
11083 } else {
11084 msg_print(Ind, "The scroll fails here!");
11085 }
11086 }
11087 }
11088 }
11089 }
11090 /* we did nore ressurect anyone */
11091 return FALSE;
11092 }
11093
11094
11095 /* modified above function to instead restore XP... used in priest spell rememberence */
11096 bool do_restoreXP_other(int Ind)
11097 {
11098 int x,y;
11099
11100 player_type * p_ptr = Players[Ind];
11101 cave_type * c_ptr;
11102 cave_type **zcave;
11103 if (!(zcave = getcave(&p_ptr->wpos))) return(FALSE);
11104
11105 for (y = -1; y <= 1; y++) {
11106 for (x = -1; x <= 1; x++) {
11107 c_ptr = &zcave[p_ptr->py+y][p_ptr->px+x];
11108
11109 if (c_ptr->m_idx < 0) {
11110 if (Players[0 - c_ptr->m_idx]->exp < Players[0 - c_ptr->m_idx]->max_exp) {
11111 restore_level(0 - c_ptr->m_idx);
11112 return TRUE;
11113 }
11114 }
11115 }
11116 }
11117 /* we did nore ressurect anyone */
11118 return FALSE;
11119 }
11120
11121
11122 /* Hack -- since the framerate has been boosted by five times since version
11123 * 0.6.0 to make game movement more smooth, we return the old level speed
11124 * times five to keep the same movement rate.
11125 */
11126
11127 void unstatic_level(struct worldpos *wpos){
11128 int i;
11129
11130 for (i = 1; i <= NumPlayers; i++) {
11131 if (Players[i]->conn == NOT_CONNECTED) continue;
11132 if (Players[i]->st_anchor) {
11133 Players[i]->st_anchor = 0;
11134 msg_print(GetInd[Players[i]->id], "Your space/time anchor breaks");
11135 }
11136 }
11137 for (i = 1; i <= NumPlayers; i++){
11138 if (Players[i]->conn == NOT_CONNECTED) continue;
11139 if (inarea(&Players[i]->wpos, wpos)) {
11140 teleport_player_level(i, TRUE);
11141 }
11142 }
11143 new_players_on_depth(wpos,0,FALSE);
11144 }
11145
11146 /* these Dungeon Master commands should probably be added somewhere else, but I am
11147 * hacking them together here to start.
11148 */
11149
11150 /* static or unstatic a level */
11151 bool master_level(int Ind, char * parms) {
11152 int i;
11153 /* get the player pointer */
11154 player_type *p_ptr = Players[Ind];
11155
11156 if (!is_admin(p_ptr)) return FALSE;
11157
11158 switch (parms[0]) {
11159 /* unstatic the level */
11160 case 'u':
11161 {
11162 struct worldpos twpos;
11163 wpcopy(&twpos,&p_ptr->wpos);
11164 unstatic_level(&twpos);
11165 /* additionally unstale it, simply by poofing it completely. - C. Blue */
11166 if (getcave(&twpos)) dealloc_dungeon_level(&twpos);
11167 msg_format(Ind, "The level %s has been unstaticed.", wpos_format(Ind, &twpos));
11168 break;
11169 }
11170
11171 /* static the level */
11172 case 's':
11173 {
11174 /* Increase the number of players on the dungeon
11175 * masters level by one. */
11176 new_players_on_depth(&p_ptr->wpos,1,TRUE);
11177 msg_format(Ind, "The level %s has been staticed.", wpos_format(Ind, &p_ptr->wpos));
11178 break;
11179 }
11180 /* add dungeon stairs here */
11181 case 'D':
11182 {
11183 cave_type **zcave;
11184 u32b f1 = 0x0, f2 = 0x0, f3 = 0x0;
11185 if(!parms[1] || !parms[2] || p_ptr->wpos.wz) return FALSE;
11186 if(istown(&p_ptr->wpos)){
11187 msg_print(Ind,"Even you may not create dungeons in the town!");
11188 return FALSE;
11189 }
11190 /* extract flags (note that 0x01 are reservd hacks to prevent zero byte) */
11191 if (parms[4] & 0x02) f1 |= DF1_FORGET;
11192 if (parms[4] & 0x04) f3 |= (DF3_HIDDENLIB | DF3_DEEPSUPPLY);
11193 if (parms[4] & 0x08) f3 |= DF3_NO_SIMPLE_STORES;
11194 if (parms[5] & 0x02) f2 |= DF2_RANDOM;
11195 if (parms[5] & 0x04) f2 |= DF2_HELL;
11196 if (parms[5] & 0x08) f2 |= DF2_NO_MAGIC_MAP;
11197 if (parms[5] & 0x10) f2 |= DF2_IRON;
11198 if (parms[5] & 0x20) f2 |= DF2_TOWNS_IRONRECALL;
11199 if (parms[5] & 0x40) f2 |= DF2_TOWNS_RND;
11200 if (parms[5] & 0x80) f2 |= DF2_TOWNS_FIX;
11201 if (parms[6] & 0x04) f2 |= DF2_MISC_STORES;
11202 if (parms[6] & 0x08) {
11203 if (parms[6] & 0x10) f2 |= DF2_IRONRND1;
11204 if (parms[6] & 0x20) f2 |= DF2_IRONRND2;
11205 if (parms[6] & 0x40) f2 |= DF2_IRONRND3;
11206 if (parms[6] & 0x80) f2 |= DF2_IRONRND4;
11207 } else {
11208 if (parms[6] & 0x10) f2 |= DF2_IRONFIX1;
11209 if (parms[6] & 0x20) f2 |= DF2_IRONFIX2;
11210 if (parms[6] & 0x40) f2 |= DF2_IRONFIX3;
11211 if (parms[6] & 0x80) f2 |= DF2_IRONFIX4;
11212 }
11213 /* create tower or dungeon */
11214 if(parms[3] == 't' && !(wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags & WILD_F_UP)){
11215 printf("tower: flags %x,%x\n", f1, f2);
11216 if((zcave = getcave(&p_ptr->wpos))) {
11217 zcave[p_ptr->py][p_ptr->px].feat = FEAT_LESS;
11218 if (zcave[p_ptr->py][p_ptr->px].info & CAVE_JAIL) f3 |= DF3_JAIL_DUNGEON;
11219 }
11220 add_dungeon(&p_ptr->wpos, parms[1], parms[2], f1, f2, f3, TRUE, 0, parms[7], 0, 0);
11221 new_level_down_y(&p_ptr->wpos, p_ptr->py);
11222 new_level_down_x(&p_ptr->wpos, p_ptr->px);
11223 }
11224 if(parms[3] == 'd' && !(wild_info[p_ptr->wpos.wy][p_ptr->wpos.wx].flags & WILD_F_DOWN)){
11225 printf("dungeon: flags %x,%x\n", f1, f2);
11226 if((zcave = getcave(&p_ptr->wpos))) {
11227 zcave[p_ptr->py][p_ptr->px].feat = FEAT_MORE;
11228 if (zcave[p_ptr->py][p_ptr->px].info & CAVE_JAIL) f3 |= DF3_JAIL_DUNGEON;
11229 }
11230 add_dungeon(&p_ptr->wpos, parms[1], parms[2], f1, f2, f3, FALSE, 0, parms[7], 0, 0);
11231 new_level_up_y(&p_ptr->wpos, p_ptr->py);
11232 new_level_up_x(&p_ptr->wpos, p_ptr->px);
11233 }
11234 break;
11235 }
11236 case 'R':
11237 {
11238 /* Remove dungeon (here) if it exists */
11239 cave_type **zcave;
11240 if(!(zcave = getcave(&p_ptr->wpos))) break;
11241
11242 /* either remove the dungeon we're currently in */
11243 if (p_ptr->wpos.wz) {
11244 if (p_ptr->wpos.wz < 0) {
11245 p_ptr->recall_pos.wx = p_ptr->wpos.wx;
11246 p_ptr->recall_pos.wy = p_ptr->wpos.wy;
11247 p_ptr->recall_pos.wz = 0;
11248 recall_player(Ind, "");
11249 rem_dungeon(&p_ptr->wpos, FALSE);
11250 } else {
11251 p_ptr->recall_pos.wx = p_ptr->wpos.wx;
11252 p_ptr->recall_pos.wy = p_ptr->wpos.wy;
11253 p_ptr->recall_pos.wz = 0;
11254 recall_player(Ind, "");
11255 rem_dungeon(&p_ptr->wpos, TRUE);
11256 }
11257 } else { /* or the one whose entrance staircase we're standing on */
11258 switch(zcave[p_ptr->py][p_ptr->px].feat){
11259 case FEAT_MORE:
11260 rem_dungeon(&p_ptr->wpos, FALSE);
11261 zcave[p_ptr->py][p_ptr->px].feat = FEAT_GRASS;
11262 break;
11263 case FEAT_LESS:
11264 rem_dungeon(&p_ptr->wpos, TRUE);
11265 zcave[p_ptr->py][p_ptr->px].feat = FEAT_GRASS;
11266 break;
11267 default:
11268 msg_print(Ind, "There is no dungeon here");
11269 }
11270 }
11271 break;
11272 }
11273 case 'T':
11274 {
11275 struct worldpos twpos;
11276 if(!parms[1] || p_ptr->wpos.wz) return FALSE;
11277 if(istown(&p_ptr->wpos)){
11278 msg_print(Ind, "There is already a town here!");
11279 return FALSE;
11280 }
11281 wpcopy(&twpos,&p_ptr->wpos);
11282
11283 /* clean level first! */
11284 wipe_m_list(&p_ptr->wpos);
11285 wipe_o_list(&p_ptr->wpos);
11286 // wipe_t_list(&p_ptr->wpos);
11287
11288 /* dont do this where there are houses! */
11289 for (i = 0; i < num_houses; i++) {
11290 if (inarea(&p_ptr->wpos, &houses[i].wpos)) {
11291 houses[i].flags |= HF_DELETED;
11292 }
11293 }
11294 addtown(p_ptr->wpos.wy, p_ptr->wpos.wx, parms[1], 0, TOWN_VANILLA);
11295 unstatic_level(&twpos);
11296 if(getcave(&twpos))
11297 dealloc_dungeon_level(&twpos);
11298
11299 break;
11300 }
11301 /* default -- do nothing. */
11302 default: break;
11303 }
11304 return TRUE;
11305 }
11306
11307 /* static or unstatic a level (from chat-line command) */
11308 bool master_level_specific(int Ind, struct worldpos *wpos, char * parms)
11309 {
11310 /* get the player pointer */
11311 player_type *p_ptr = Players[Ind];
11312
11313 // if (strcmp(p_ptr->name, cfg_dungeon_master)) return FALSE;
11314 if (!is_admin(p_ptr)) return FALSE;
11315
11316 switch (parms[0])
11317 {
11318 /* unstatic the level */
11319 case 'u':
11320 {
11321 unstatic_level(wpos);
11322 /* additionally unstale it, simply by poofing it completely. - C. Blue */
11323 dealloc_dungeon_level(wpos);
11324 // msg_format(Ind, "The level (%d,%d) %dft has been unstaticed.", wpos->wx, wpos->wy, wpos->wz * 50);
11325 msg_format(Ind, "The level %s has been unstaticed.", wpos_format(Ind, wpos));
11326 break;
11327 }
11328
11329 /* static the level */
11330 case 's':
11331 {
11332 /* Increase the number of players on the dungeon
11333 * masters level by one. */
11334 new_players_on_depth(&p_ptr->wpos,1,TRUE);
11335 msg_print(Ind, "The level has been staticed.");
11336 break;
11337 }
11338 /* default -- do nothing. */
11339 default: break;
11340 }
11341 return TRUE;
11342 }
11343
11344
11345 /*
11346 *
11347 * Guild build access
11348 * Must be owner inside guild hall
11349 *
11350 */
11351 //static bool guild_build(int Ind){
11352 bool guild_build(int Ind){
11353 player_type *p_ptr = Players[Ind];
11354 int i;
11355
11356 for (i = 0; i < num_houses; i++) {
11357 if (inarea(&houses[i].wpos, &p_ptr->wpos)) {
11358 if (fill_house(&houses[i], FILL_PLAYER, p_ptr)) {
11359 if (access_door(Ind, houses[i].dna, FALSE) || admin_p(Ind)) {
11360 if (houses[i].dna->owner_type == OT_GUILD &&
11361 p_ptr->guild == houses[i].dna->owner &&
11362 guilds[p_ptr->guild].master == p_ptr->id) {
11363 if (p_ptr->au > 1000) {
11364 p_ptr->au -= 1000;
11365 p_ptr->redraw |= PR_GOLD;
11366 return(TRUE);
11367 }
11368 }
11369 }
11370 break;
11371 }
11372 }
11373 }
11374 return(FALSE);
11375 }
11376
11377 /* Build walls and such. This should probably be improved, I am just hacking
11378 * it together right now for Halloween. -APD
11379 */
11380 bool master_build(int Ind, char * parms)
11381 {
11382 player_type * p_ptr = Players[Ind];
11383 cave_type * c_ptr;
11384 struct c_special *cs_ptr;
11385 static unsigned char new_feat = FEAT_WALL_EXTRA;
11386 cave_type **zcave;
11387
11388 if (!(zcave = getcave(&p_ptr->wpos))) return(FALSE);
11389
11390 if (!is_admin(p_ptr) && (!player_is_king(Ind)) && (!guild_build(Ind))) return FALSE;
11391
11392 /* extract arguments, otherwise build a wall of type new_feat */
11393 if (parms) {
11394 /* Hack -- the first character specifies the type of wall */
11395 new_feat = parms[0];
11396 /* Hack -- toggle auto-build on/off */
11397 switch (parms[1]) {
11398 case 'T': p_ptr->master_move_hook = master_build; break;
11399 case 'F': p_ptr->master_move_hook = NULL; return FALSE;
11400 default : break;
11401 }
11402 }
11403
11404 c_ptr = &zcave[p_ptr->py][p_ptr->px];
11405
11406 /* Never destroy real house doors! Work on this later */
11407 if ((cs_ptr = GetCS(c_ptr, CS_DNADOOR))) return(FALSE);
11408
11409 /* This part to be rewritten for stacked CS */
11410 c_ptr->feat = new_feat;
11411 if (c_ptr->feat == FEAT_HOME) {
11412 struct c_special *cs_ptr;
11413 /* new special door creation (with keys) */
11414 struct key_type *key;
11415 object_type newkey;
11416 int id;
11417 MAKE(key, struct key_type);
11418 sscanf(&parms[2],"%d",&id);
11419 key->id = id;
11420 invcopy(&newkey, lookup_kind(TV_KEY, SV_HOUSE_KEY ));
11421 newkey.pval = key->id;
11422 newkey.marked2 = ITEM_REMOVAL_NEVER;
11423 drop_near(&newkey, -1, &p_ptr->wpos, p_ptr->py, p_ptr->px);
11424 cs_ptr = ReplaceCS(c_ptr, CS_KEYDOOR);
11425 if (cs_ptr) cs_ptr->sc.ptr = key;
11426 else KILL(key, struct key_type);
11427 p_ptr->master_move_hook = NULL; /*buggers up if not*/
11428 }
11429 if (c_ptr->feat == FEAT_SIGN) {
11430 struct c_special *cs_ptr;
11431 struct floor_insc *sign;
11432 MAKE(sign, struct floor_insc);
11433 strcpy(sign->text, &parms[2]);
11434 cs_ptr = ReplaceCS(c_ptr, CS_INSCRIP);
11435 if (cs_ptr) cs_ptr->sc.ptr = sign;
11436 else KILL(sign, struct floor_insc);
11437 p_ptr->master_move_hook = NULL; /*buggers up if not*/
11438 }
11439
11440 return TRUE;
11441 }
11442
11443 static char master_specific_race_char = 'a';
11444
11445 static bool master_summon_specific_aux(int r_idx)
11446 {
11447 monster_race *r_ptr = &r_info[r_idx];
11448
11449 /* no uniques */
11450 if (r_ptr->flags1 & RF1_UNIQUE) return FALSE;
11451
11452 /* if we look like what we are looking for */
11453 if (r_ptr->d_char == master_specific_race_char) return TRUE;
11454 return FALSE;
11455 }
11456
11457 /* Auxillary function to master_summon, determine the exact type of monster
11458 * to summon from a more general description.
11459 */
11460 static u16b master_summon_aux_monster_type(int Ind, char monster_type, char * monster_parms)
11461 {
11462 player_type *p_ptr = Players[Ind];
11463 int tmp, lev;
11464
11465 /* handle each category of monster types */
11466 switch (monster_type)
11467 {
11468 /* specific monster specified */
11469 case 's':
11470 {
11471 /* allows specification by monster No. */
11472 tmp = atoi(monster_parms);
11473 if (tmp > 0) return tmp;
11474
11475 /* if the name was specified, summon this exact race */
11476 if (strlen(monster_parms) > 1) return race_index(monster_parms);
11477 /* otherwise, summon a monster that looks like us */
11478 else
11479 {
11480 master_specific_race_char = monster_parms[0];
11481 get_mon_num_hook = master_summon_specific_aux;
11482 get_mon_num_prep(0, NULL);
11483 // tmp = get_mon_num(rand_int(100) + 10);
11484 lev = (monster_parms[0] == 't') ? 0 : rand_int(100) + 10;
11485 tmp = get_mon_num(lev, lev);
11486
11487 /* restore monster generator */
11488 get_mon_num_hook = dungeon_aux;
11489
11490 /* return our monster */
11491 return tmp;
11492 }
11493 }
11494 /* orc specified */
11495 case 'o':
11496 {
11497 /* if not random, assume specific orc specified */
11498 if (strcmp(monster_parms, "random")) return race_index(monster_parms);
11499 /* random orc */
11500 else switch(rand_int(6))
11501 {
11502 case 0: return race_index("Snaga");
11503 case 1: return race_index("Cave orc");
11504 case 2: return race_index("Hill orc");
11505 case 3: return race_index("Dark orc");
11506 case 4: return race_index("Half-orc");
11507 case 5: return race_index("Uruk");
11508 }
11509 break;
11510 }
11511 /* low undead specified */
11512 case 'u':
11513 {
11514 /* if not random, assume specific high undead specified */
11515 if (strcmp(monster_parms, "random")) return race_index(monster_parms);
11516 /* random low undead */
11517 else switch(rand_int(11))
11518 {
11519 case 0: return race_index("Poltergeist");
11520 case 1: return race_index("Green glutton ghost");
11521 case 2: return race_index("Lost soul");
11522 case 3: return race_index("Skeleton kobold");
11523 case 4: return race_index("Skeleton orc");
11524 case 5: return race_index("Skeleton human");
11525 case 6: return race_index("Zombified orc");
11526 case 7: return race_index("Zombified human");
11527 case 8: return race_index("Mummified orc");
11528 case 9: return race_index("Moaning spirit");
11529 case 10: return race_index("Vampire bat");
11530 }
11531 break;
11532 }
11533
11534 /* high undead specified */
11535 case 'U':
11536 {
11537 /* if not random, assume specific high undead specified */
11538 if (strcmp(monster_parms, "random")) return race_index(monster_parms);
11539 /* random low undead */
11540 else switch(rand_int(13))
11541 {
11542 case 0: return race_index("Vampire");
11543 case 1: return race_index("Giant skeleton troll");
11544 case 2: return race_index("Lich");
11545 case 3: return race_index("Master vampire");
11546 case 4: return race_index("Dread");
11547 case 5: return race_index("Nether wraith");
11548 case 6: return race_index("Night mare");
11549 case 7: return race_index("Vampire lord");
11550 case 8: return race_index("Archpriest");
11551 case 9: return race_index("Undead beholder");
11552 case 10: return race_index("Dreadmaster");
11553 case 11: return race_index("Nightwing");
11554 case 12: return race_index("Nightcrawler");
11555 }
11556 break;
11557 }
11558
11559 /* specific depth specified */
11560 case 'd':
11561 {
11562 get_mon_num_hook = dungeon_aux;
11563
11564 /* Wilderness-specific hook */
11565 if (!p_ptr->wpos.wz) set_mon_num_hook_wild(&p_ptr->wpos);
11566
11567 get_mon_num_prep(0, NULL);
11568 return get_mon_num(monster_parms[0], monster_parms[0] - 20); //reduce OoD if we summon depth-specificly
11569 }
11570
11571 default : break;
11572 }
11573
11574 /* failure */
11575 return 0;
11576
11577 }
11578
11579 /* Temporary debugging hack, to test the new excellents.
11580 */
11581 bool master_acquire(int Ind, char * parms)
11582 {
11583 player_type * p_ptr = Players[Ind];
11584
11585 if (!is_admin(p_ptr)) return FALSE;
11586 acquirement(&p_ptr->wpos, p_ptr->py, p_ptr->px, 1, TRUE, TRUE, make_resf(p_ptr));
11587 return TRUE;
11588 }
11589
11590 /* Monster summoning options. More documentation on this later. */
11591 bool master_summon(int Ind, char * parms)
11592 {
11593 int c;
11594 player_type * p_ptr = Players[Ind];
11595
11596 static char monster_type = 0; /* What type of monster we are -- specific, random orc, etc */
11597 static char monster_parms[80];
11598 static char summon_type = 0; /* what kind to summon -- x right here, group at random location, etc */
11599 static char summon_parms = 0; /* arguments to previous byte */
11600 static u16b r_idx = 0; /* which monser to actually summon, from previous variables */
11601 unsigned char size = 0; /* how many monsters to actually summon */
11602
11603 if (!is_admin(p_ptr) && (!player_is_king(Ind))) return FALSE;
11604
11605 summon_override_checks = SO_ALL; /* set admin summoning flag for overriding all validity checks */
11606
11607 /* extract arguments. If none are found, summon previous type. */
11608 if (parms)
11609 {
11610 /* the first character specifies the type of monster */
11611 summon_type = parms[0];
11612 summon_parms = parms[1];
11613 monster_type = parms[2];
11614 /* Hack -- since monster_parms is a string, throw it on the end */
11615 strcpy(monster_parms, &parms[3]);
11616 }
11617
11618 switch (summon_type)
11619 {
11620 /* summon x here */
11621 case 'x':
11622 {
11623 /* for each monster we are summoning */
11624 for (c = 0; c < summon_parms; c++)
11625 {
11626 /* figure out who to summon */
11627 r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11628
11629 /* summon the monster, if we have a valid one */
11630 if (r_idx)
11631 summon_specific_race(&p_ptr->wpos, p_ptr->py, p_ptr->px, r_idx, 0, 1);
11632 }
11633 break;
11634 }
11635
11636 /* summon x at random locations */
11637 case 'X':
11638 {
11639 for (c = 0; c < summon_parms; c++)
11640 {
11641 /* figure out who to summon */
11642 r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11643
11644 /* summon the monster at a random location */
11645 if (r_idx)
11646 summon_specific_race_somewhere(&p_ptr->wpos,r_idx, 0, 1);
11647 }
11648 break;
11649 }
11650
11651 /* summon group of random size here */
11652 case 'g':
11653 {
11654 /* figure out how many to summon */
11655 size = rand_int(rand_int(50)) + 2;
11656
11657 /* figure out who to summon */
11658 r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11659
11660 /* summon the group here */
11661 summon_specific_race(&p_ptr->wpos, p_ptr->py, p_ptr->px, r_idx, 0, size);
11662 break;
11663 }
11664 /* summon group of random size at random location */
11665 case 'G':
11666 {
11667 /* figure out how many to summon */
11668 size = rand_int(rand_int(50)) + 2;
11669
11670 /* figure out who to summon */
11671 r_idx = master_summon_aux_monster_type(Ind, monster_type, monster_parms);
11672
11673 /* someone the group at a random location */
11674 summon_specific_race_somewhere(&p_ptr->wpos, r_idx, 0, size);
11675 break;
11676 }
11677 /* summon mode on (use with discretion... lets not be TOO mean ;-) )*/
11678 case 'T':
11679 {
11680 summon_type = 'x';
11681 summon_parms = 1;
11682
11683 p_ptr->master_move_hook = master_summon;
11684 break;
11685 }
11686
11687 /* summon mode off */
11688 case 'F':
11689 {
11690 p_ptr->master_move_hook = NULL;
11691 break;
11692 }
11693 }
11694
11695 summon_override_checks = SO_NONE; /* clear all override flags */
11696 return TRUE;
11697 }
11698
11699 #define FIND_CLOSEST_JAIL
11700 bool imprison(int Ind, u16b time, char *reason) {
11701 int id, i, j;
11702 #ifdef FIND_CLOSEST_JAIL
11703 int dist = 999, tmp, picked = -1;
11704 #endif
11705 struct dna_type *dna;
11706 player_type *p_ptr = Players[Ind];
11707 char string[160];
11708 cave_type **zcave, **nzcave;
11709 struct worldpos old_wpos;
11710
11711 if (!jails_enabled) {
11712 p_ptr->tim_susp = 0;
11713 s_printf("IMPRISON: %s DISABLED.\n", p_ptr->name);
11714 return FALSE;
11715 }
11716
11717 if (!(zcave = getcave(&p_ptr->wpos))) return (FALSE);
11718
11719 s_printf("IMPRISON: %s ", p_ptr->name);
11720
11721 if (!p_ptr || !(id = lookup_player_id("Jailer"))) {
11722 s_printf("JAILER\n");
11723 return (FALSE);
11724 }
11725
11726 if (p_ptr->wpos.wz) {
11727 p_ptr->tim_susp += time;
11728 s_printf("TIM_SUSP.\n");
11729 return (TRUE);
11730 }
11731
11732 #ifdef JAIL_TOWN_AREA /* only imprison when within town area? */
11733 if (!istownarea(&p_ptr->wpos, MAX_TOWNAREA)) {
11734 p_ptr->tim_susp += time;
11735 s_printf("NO_TOWN.\n");
11736 return (TRUE);
11737 }
11738 #endif
11739
11740 if (p_ptr->tim_jail) {
11741 p_ptr->tim_jail += time;
11742 s_printf("TIM_JAIL.\n");
11743 return (TRUE);
11744 }
11745
11746 /* get appropriate prison house */
11747 for (i = 0; i < num_houses; i++) {
11748 if (!(houses[i].flags & HF_JAIL)) continue;
11749 if ((houses[i].flags & HF_DELETED)) continue;
11750 dna = houses[i].dna;
11751 if (dna->owner == id && dna->owner_type == OT_PLAYER) {
11752 #ifndef FIND_CLOSEST_JAIL /* get first prison we find? */
11753 break;
11754 #else /* get closest prison we find? */
11755 tmp = distance(houses[i].wpos.wy, houses[i].wpos.wx, p_ptr->wpos.wy, p_ptr->wpos.wx);
11756 if (tmp < dist) {
11757 dist = tmp;
11758 picked = i;
11759 }
11760 #endif
11761 }
11762 }
11763 #ifndef FIND_CLOSEST_JAIL
11764 if (i == num_houses) {
11765 p_ptr->tim_susp = 0;
11766 s_printf("FAILED.\n");
11767 return (FALSE);
11768 }
11769 #else
11770 if (picked == -1) {
11771 p_ptr->tim_susp = 0;
11772 s_printf("FAILED.\n");
11773 return (FALSE);
11774 }
11775 i = picked;
11776 #endif
11777
11778 /* lazy, single prison system */
11779 /* hopefully no overcrowding! */
11780 if (!(nzcave = getcave(&houses[i].wpos))){
11781 alloc_dungeon_level(&houses[i].wpos);
11782 generate_cave(&houses[i].wpos, p_ptr);
11783
11784 #if 1
11785 /* generate some vermin randomly, for flavour */
11786 nzcave = getcave(&houses[i].wpos);
11787 if (rand_int(2)) for (j = randint(2); j; j--) {
11788 int x, y;
11789 //abuse 'id'
11790 id = 10;
11791 while (id--) {
11792 if (rand_int(2)) x = houses[i].x - 15 + rand_int(13);
11793 else x = houses[i].x + 15 - rand_int(13);
11794 if (rand_int(2)) y = houses[i].y - 15 + rand_int(13);
11795 else y = houses[i].y + 15 - rand_int(13);
11796
11797 if (!in_bounds(y, x)) continue;
11798 if (!(nzcave[y][x].info & CAVE_STCK)) continue;
11799
11800 break;
11801 }
11802 if (id) place_monster_one(&houses[i].wpos,
11803 y, x,
11804 1, 0, 0, rand_int(2) ? TRUE : FALSE, 0, 0);
11805 }
11806 #endif
11807 }
11808
11809 store_exit(Ind);
11810
11811 zcave[p_ptr->py][p_ptr->px].m_idx = 0;
11812 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
11813 forget_lite(Ind);
11814 forget_view(Ind);
11815 wpcopy(&old_wpos, &p_ptr->wpos);
11816 wpcopy(&p_ptr->wpos, &houses[i].wpos);
11817 new_players_on_depth(&old_wpos, -1, TRUE);
11818
11819 p_ptr->py = houses[i].y;
11820 p_ptr->px = houses[i].x;
11821
11822 /* that messes it up */
11823 /* nzcave[p_ptr->py][p_ptr->px].m_idx = (0-Ind); */
11824 new_players_on_depth(&p_ptr->wpos, 1, TRUE);
11825
11826 p_ptr->new_level_flag = TRUE;
11827 p_ptr->new_level_method = LEVEL_HOUSE;
11828
11829 #ifdef JAILER_KILLS_WOR
11830 /* eat his WoR scrolls as suggested? */
11831 id = FALSE; //abuse 'id' and 'i'
11832 i = TRUE;
11833 for (j = 0; j < INVEN_WIELD; j++) {
11834 object_type *j_ptr;
11835 if (!p_ptr->inventory[j].k_idx) continue;
11836 j_ptr = &p_ptr->inventory[j];
11837 if ((j_ptr->tval == TV_SCROLL) && (j_ptr->sval == SV_SCROLL_WORD_OF_RECALL)) {
11838 if (id) i = FALSE;
11839 if (j_ptr->number > 1) i = FALSE;
11840 inven_item_increase(Ind, j, -j_ptr->number);
11841 inven_item_optimize(Ind, j);
11842 combine_pack(Ind);
11843 reorder_pack(Ind);
11844 id = TRUE;
11845 }
11846 }
11847 if (id) msg_format(Ind, "\376\377oThe jailer confiscates your word-of-recall scroll%s.", i ? "" : "s");
11848 #endif
11849
11850 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
11851 snprintf(string, sizeof(string), "\374\377o%s was jailed for %s.", p_ptr->name, reason);
11852 msg_broadcast(Ind, string);
11853 msg_format(Ind, "\374\377oYou have been jailed for %s.", reason);
11854 p_ptr->tim_jail = time + p_ptr->tim_susp;
11855 p_ptr->tim_susp = 0;
11856
11857 s_printf("DONE.\n");
11858 return (TRUE);
11859 }
11860
11861 static void player_edit(char *name){
11862
11863 }
11864
11865 bool master_player(int Ind, char *parms){
11866 player_type *p_ptr = Players[Ind];
11867 player_type *q_ptr;
11868 int Ind2 = 0;
11869 int i;
11870 struct account *d_acc;
11871 int *id_list, n;
11872 char buf[MSG_LEN];
11873
11874 if (!is_admin(p_ptr)) {
11875 msg_print(Ind,"You need to be the dungeon master to use this command.");
11876 return FALSE;
11877 }
11878 switch (parms[0]) {
11879 case 'E': /* offline editor */
11880 for (i = 1; i <= NumPlayers; i++){
11881 if (!strcmp(Players[i]->name, &parms[1])){
11882 msg_format(Ind,"%s is currently playing",&parms[1]);
11883 return(FALSE);
11884 }
11885 }
11886 player_edit(&parms[1]);
11887
11888 break;
11889 case 'A': /* acquirement */
11890 Ind2 = name_lookup(Ind, &parms[1], FALSE, FALSE);
11891 if(Ind2)
11892 {
11893 player_type *p_ptr2 = Players[Ind2];
11894 acquirement(&p_ptr2->wpos, p_ptr2->py, p_ptr2->px, 1, TRUE, TRUE, make_resf(p_ptr2));
11895 msg_format(Ind, "%s is granted an item.", p_ptr2->name);
11896 msg_print(Ind2, "You feel a divine favor!");
11897 return(FALSE);
11898 }
11899 // msg_print(Ind, "That player is not in the game.");
11900 break;
11901 case 'k': /* admin wrath (preceed name with '!' for no-ghost kill */
11902 i = 1;
11903 if (parms[1] == '!') i = 2;
11904 Ind2 = name_lookup(Ind, &parms[i], FALSE, FALSE);
11905 if (Ind2) {
11906 q_ptr = Players[Ind2];
11907 msg_print(Ind2, "\377rYou are hit by a bolt from the blue!");
11908 strcpy(q_ptr->died_from,"divine wrath");
11909 if (i == 2) q_ptr->global_event_temp |= PEVF_NOGHOST_00; //hack: no-ghost death
11910 q_ptr->deathblow = 0;
11911 player_death(Ind2);
11912 return(TRUE);
11913 }
11914 // msg_print(Ind, "That player is not in the game.");
11915
11916 break;
11917 case 'S': /* Static a regular */
11918 stat_player(&parms[1], TRUE);
11919 break;
11920 case 'U': /* Unstatic him */
11921 stat_player(&parms[1], FALSE);
11922 break;
11923 case 't': /* DM telekinesis */
11924 /* I needed this before - it is useful */
11925 /* Unfortunately the current telekinesis */
11926 /* is not compatible with it, and I do not */
11927 /* want to combine it while there is a */
11928 /* potential bug. */
11929 break;
11930 case 'B':
11931 /* This could be fun - be wise dungeon master */
11932 sprintf(buf, "\375\377r[\377%c%s\377r]\377%c %s", 'b', p_ptr->name, COLOUR_CHAT, &parms[1]); /* admin colour 'b' */
11933 censor_length = 0;
11934 msg_broadcast_format(0, buf);
11935 #ifdef TOMENET_WORLDS
11936 if (cfg.worldd_broadcast) world_chat(0, buf);
11937 #endif
11938 break;
11939 case 'r': /* FULL ACCOUNT SCAN + RM */
11940 /* Delete a player from the database/savefile */
11941 d_acc = GetAccount(&parms[1], NULL, FALSE);
11942 if (d_acc != (struct account*)NULL) {
11943 char name[80];
11944 n = player_id_list(&id_list, d_acc->id);
11945 for(i = 0; i < n; i++) {
11946 strcpy(name, lookup_player_name(id_list[i]));
11947 msg_format(Ind, "\377oDeleting %s", name);
11948 delete_player_id(id_list[i]);
11949 sf_delete(name);
11950 }
11951 if (n) C_KILL(id_list, n, int);
11952 d_acc->flags |= ACC_DELD;
11953 /* stamp in the deleted account */
11954 WriteAccount(d_acc, FALSE);
11955 KILL(d_acc, struct account);
11956 }
11957 else
11958 msg_print(Ind, "\377rCould not find account");
11959 break;
11960 }
11961 return(FALSE);
11962 }
11963
11964 static vault_type *get_vault(char *name)
11965 {
11966 int i;
11967
11968 for (i = 0; i < MAX_V_IDX; i++) {
11969 if (strstr(v_name + v_info[i].name, name))
11970 return &v_info[i];
11971 }
11972
11973 return NULL;
11974 }
11975
11976 /* Generate something */
11977 bool master_generate(int Ind, char * parms)
11978 {
11979 /* get the player pointer */
11980 player_type *p_ptr = Players[Ind];
11981
11982 if (!is_admin(p_ptr)) return FALSE;
11983
11984 switch (parms[0])
11985 {
11986 /* generate a vault */
11987 case 'v':
11988 {
11989 vault_type *v_ptr = NULL;
11990
11991 switch(parms[1])
11992 {
11993 case '#':
11994 v_ptr = &v_info[parms[2] + 127];
11995 break;
11996 case 'n':
11997 v_ptr = get_vault(&parms[2]);
11998 }
11999
12000 if(!v_ptr || !v_ptr->wid) return FALSE;
12001
12002 // build_vault(&p_ptr->wpos, p_ptr->py, p_ptr->px, v_ptr->hgt, v_ptr->wid, v_text + v_ptr->text);
12003 build_vault(&p_ptr->wpos, p_ptr->py, p_ptr->px, v_ptr, p_ptr);
12004
12005 break;
12006 }
12007 }
12008 return TRUE;
12009 }
12010
12011 #if 0 /* some new esp link stuff - mikaelh */
12012 bool establish_esp_link(int Ind, int Ind2, byte type, u16b flags, u16b end)
12013 {
12014 player_type *p_ptr, *p2_ptr;
12015 esp_link_type *esp_ptr;
12016
12017 p_ptr = Players[Ind];
12018 p2_ptr = Players[Ind2];
12019 if (!p2_ptr) return;
12020
12021 esp_ptr = check_esp_link(Ind, Ind2);
12022 if (esp_ptr) {
12023 if (esp_ptr->type == type) {
12024 /* compatible ESP link already exists, add flags */
12025 esp_ptr->flags |= flags;
12026 esp_ptr->end = end;
12027 }
12028 else return FALSE;
12029 }
12030 else {
12031 MAKE(esp_ptr, esp_link_type);
12032
12033 esp_ptr->id = p2_ptr->id;
12034 esp_ptr->type = type;
12035 esp_ptr->flags = flags;
12036 esp_ptr->end = end;
12037
12038 if (!(esp_ptr->flags & LINKF_HIDDEN))
12039 {
12040 msg_format(Ind, "\377oYou establish a mind link with %s.", p2_ptr->name);
12041 msg_format(Ind, "\377o%s has established a mind link with you.", p_ptr->name);
12042 }
12043
12044 esp_ptr->next = p_ptr->esp_link;
12045 p_ptr->esp_link = esp_ptr;
12046 }
12047
12048 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12049 p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12050 p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12051 p2_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12052 p2_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12053 p2_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12054
12055 return TRUE;
12056 }
12057
12058 void break_esp_link(int Ind, int Ind2)
12059 {
12060 player_type *p_ptr, *p2_ptr;
12061 esp_link_type *esp_ptr, *pest_link;
12062
12063 p_ptr = Players[Ind];
12064 p2_ptr = Players[Ind2];
12065 if (!p2_ptr) return;
12066
12067 pesp_ptr = NULL;
12068 esp_ptr = p_ptr->esp_link;
12069 while (esp_ptr)
12070 {
12071 if (esp_ptr->id == p2_ptr->id)
12072 {
12073 if (!(esp_ptr->flags & LINKF_HIDDEN)) {
12074 msg_format(Ind, "\377RYou break the mind link with %s.", p2_ptr->name);
12075 msg_format(Ind2, "\377R%s breaks the mind link with you.", p_ptr->name);
12076 }
12077
12078 if (pesp_ptr)
12079 {
12080 pest_ptr->next = esp_ptr->next;
12081 }
12082 else
12083 {
12084 p_ptr->esp_link = esp_ptr->next;
12085 }
12086 KILL(esp_ptr, esp_link_type);
12087
12088 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12089 p_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12090 p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12091 p2_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
12092 p2_ptr->update |= (PU_BONUS | PU_VIEW | PU_MANA | PU_HP);
12093 p2_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP);
12094 }
12095 pesp_ptr = esp_ptr;
12096 esp_ptr = esp_ptr->next;
12097 }
12098 }
12099
12100 esp_link_type *check_esp_link(ind Ind, int Ind2)
12101 {
12102 player_type *p_ptr, *p2_ptr;
12103 esp_link_type *esp_ptr;
12104
12105 p_ptr = Players[Ind];
12106 p2_ptr = Players[Ind2];
12107 if (!p2_ptr) return NULL;
12108
12109 esp_ptr = p_ptr->esp_link;
12110 while (esp_ptr)
12111 {
12112 if (esp_ptr->id == p2_ptr->id) return esp_ptr;
12113 esp_ptr = esp_ptr->next;
12114 }
12115 return NULL;
12116 }
12117
12118 bool check_esp_link_type(int Ind, int Ind2, u16b flags)
12119 {
12120 esp_link_type* esp_ptr;
12121 esp_ptr = check_esp_link(Ind, Ind2);
12122
12123 if (esp_ptr && esp_ptr->flags & flags) return TRUE;
12124 else return FALSE;
12125 }
12126 #endif
12127
12128 void toggle_aura(int Ind, int aura) {
12129 char buf[80];
12130 Players[Ind]->aura[aura] = !Players[Ind]->aura[aura];
12131 strcpy(buf, "\377sYour ");
12132 switch (aura) { /* up to MAX_AURAS */
12133 case 0: strcat(buf, "aura of fear"); break;
12134 case 1: strcat(buf, "shivering aura"); break;
12135 case 2: strcat(buf, "aura of death"); break;
12136 }
12137 strcat(buf, " is now ");
12138 if (Players[Ind]->aura[aura]) strcat(buf, "unleashed"); else strcat(buf, "suppressed");
12139 strcat(buf, "!");
12140 msg_print(Ind, buf);
12141 }
12142
12143 void check_aura(int Ind, int aura) {
12144 char buf[80];
12145 strcpy(buf, "\377sYour ");
12146 switch (aura) { /* up to MAX_AURAS */
12147 case 0: strcat(buf, "aura of fear"); break;
12148 case 1: strcat(buf, "shivering aura"); break;
12149 case 2: strcat(buf, "aura of death"); break;
12150 }
12151 strcat(buf, " is currently ");
12152 if (Players[Ind]->aura[aura]) strcat(buf, "unleashed"); else strcat(buf, "suppressed");
12153 strcat(buf, ".");
12154 msg_print(Ind, buf);
12155 }
12156
12157 /* determine minimum dungeon level required for a player of a particular
12158 character level to obtain optimum experience. */
12159 int det_req_level(int plev) {
12160 if (plev < 20) return (0);
12161 else if (plev < 30) return (375 / (45 - plev));
12162 else if (plev < 50) return (650 / (56 - plev));
12163 else if (plev < 65) return (plev * 2);
12164 else if (plev < 75) return ((plev - 65) * 4 + 130);
12165 else return ((plev - 75) + 170);
12166 }
12167 /* calculate actual experience gain based on det_req_level */
12168 s64b det_exp_level(s64b exp, int plev, int dlev) {
12169 int req_dlvl = det_req_level(plev);
12170
12171 if (dlev < req_dlvl - 5) return 0; /* actually give zero exp for 'grey' levels? */
12172 if (dlev < req_dlvl) return ((exp * 2) / (2 + req_dlvl - dlev)); /* give reduced exp for 'yellow' levels */
12173 return (exp); /* normal exp */
12174 }
12175