1 /* $Id$ */
2 /* File: spells2.c */
3
4 /* Purpose: Spell code (part 2) */
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 #include "angband.h"
16
17 /*
18 * A warlock could easily beat the game by scumming & genociding vaults;
19 * Here're some codes against this method. - Jir -
20 *
21 * Note also that some vaults/quests will be genocide-resistant.
22 */
23 /*
24 * (Mass) Genocide spell being way too powerful, the caster's HP is halved
25 * if this option is set.
26 */
27 #define SEVERE_GENO
28 /*
29 * Geno won't work if inside a vault(icky).
30 * Strongly recommended.
31 */
32 #define NO_GENO_ON_ICKY
33 /*
34 * Each monster has (level) in RESIST_GENO chance of surviving this.
35 */
36 #define RESIST_GENO 250
37
38 /*
39 * 'Trap detection' is way too powerful traps and 'searching' ability
40 * are almost meanless; if this flag is defined, the spell can only
41 * detect some of the traps depending on the player level.
42 */
43 //#define TRAP_DETECTION_FAILURE /* appearently unused */
44
45 /* for PVP mode diminishing healing calc - C. Blue */
46 //#define PVP_DIMINISHING_HEALING_CAP(p) (3 * ((p)->mhp + (p)->lev * 6)) /* unfair for non-mimics */
47 #define PVP_DIMINISHING_HEALING_CAP(p) (((p)->lev + 5) * ((p)->lev + 5)) /* 10: 225, 20: 625, 30: 1225 */
48
49 /* Give 'absence' messages for detection magic?
50 This would need magic devices causing these to get identified, since we
51 can read what they supposedly do. */
52 //#define DETECT_ABSENCE
53
54 /* Helper function to educe spell damage by 50% while in wraithform.
55 * Some spells must be excempt, because their 'dam'
56 * actually stores their functionality. - C. Blue
57 */
proj_dam_wraith(int typ,int * dam)58 static void proj_dam_wraith(int typ, int *dam) {
59
60 switch (typ) {
61 case GF_RECALL_PLAYER: /* <- dam is timeout! */
62 case GF_RESTORE_PLAYER:
63 case GF_CURE_PLAYER:
64 case GF_CURING:
65 return;
66 case GF_HEAL_PLAYER:
67 *dam = (*dam & 0x3C00) + (*dam & 0x03FF) / 2;
68 return;
69 case GF_OLD_DRAIN:
70 /* - sorry, 9999 is the priest spell hack :P */
71 if (*dam == 9999) return;
72 default:
73 *dam /= 2;
74 }
75 }
76
77 #ifdef ENABLE_MAIA
78 /*
79 * For angelic beings, this spell will gather any party
80 * members on the same level to him/herself. This also
81 * tele_to's all monsters in LOS.
82 * For demonic beings, do a dispel on LOS.
83 */
divine_vengeance(int Ind,int power)84 void divine_vengeance(int Ind, int power) {
85 player_type *p_ptr = Players[Ind];
86 bool summon = !istownarea(&p_ptr->wpos, MAX_TOWNAREA);
87
88 if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
89 int i;
90 /* players TELE_TO */
91 if (p_ptr->party == 0) {
92 msg_print(Ind, "You can only teleport to party members.");
93 } else {
94 fire_ball(Ind, GF_KILL_GLYPH, 0, 0, 2, "");
95 for (i = 1; i <= NumPlayers; i++) {
96 /* Skip self */
97 if (i == Ind) continue;
98
99 player_type *q_ptr = Players[i];
100
101 /* Skip disconnected players */
102 if (q_ptr->conn == NOT_CONNECTED) continue;
103
104 /* Skip players not on this depth */
105 if (!inarea(&q_ptr->wpos, &p_ptr->wpos)) continue;
106
107 /* Skip DM if not DM himself */
108 if (q_ptr->admin_dm && !p_ptr->admin_dm) continue;
109
110 /* Skip players who haven't opened their mind */
111 if (!(q_ptr->esp_link_flags & LINKF_OPEN)) continue;
112
113 /* Skip players not in the same party */
114 if (q_ptr->party == 0 || p_ptr->party == 0) continue;
115 if (p_ptr->party != q_ptr->party) continue;
116
117 /* Have a present from the nether world for each player you teleport! */
118 if (summon) summon_specific(&p_ptr->wpos, p_ptr->py, p_ptr->px, getlevel(&p_ptr->wpos), 100, SUMMON_MONSTER, 0, cfg.clone_summoning);
119
120 teleport_player_to(i, p_ptr->py, p_ptr->px);
121 }
122 }
123 /* monsters TELE_TO */
124 project_los(Ind, GF_TELE_TO, 0, " commands return");
125 } else if (p_ptr->ptrait == TRAIT_CORRUPTED) {
126 dispel_monsters(Ind, power);
127 // project_los(Ind, GF_DISP_ALL, power, " commands leave");
128 }
129 }
130
131 /* A: fury
132 * D: +hp (does not stack with +LIFE)
133 */
divine_empowerment(int Ind,int level)134 void divine_empowerment(int Ind, int level) {
135 player_type *p_ptr = Players[Ind];
136 if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
137 set_fury(Ind, 20 + level / 10);
138 } else if (p_ptr->ptrait == TRAIT_CORRUPTED) {
139 int bonus = 0;
140 if (level >= 55) {
141 bonus = 3;
142 } else if (level >= 52) {
143 bonus = 2;
144 } else if (level >= 40) {
145 bonus = 1;
146 }
147 (void)do_divine_hp(Ind, (level * 3) / 2, bonus);
148 }
149 return;
150 }
151
152 /* A: aoe slow, time/mana res
153 * D: +crit
154 */
divine_intensify(int Ind,int level)155 void divine_intensify(int Ind, int level) {
156 player_type *p_ptr = Players[Ind];
157 if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
158 //aoe divine_xtra_res_time
159 project_los(Ind, GF_OLD_SLOW, level * 3, "");
160 (void)do_divine_xtra_res_time(Ind, (level * 3) / 2);
161 return;
162 } else if (p_ptr->ptrait == TRAIT_CORRUPTED) {
163 int bonus = 2 + ((level - 45) / 5) * 2;
164 (void)do_divine_crit(Ind, (level * 3) / 2, bonus);
165 }
166 }
167
py_create_gateway(int Ind)168 int py_create_gateway(int Ind) {
169 player_type *p_ptr = Players[Ind];
170 struct worldpos *wpos = &(p_ptr->wpos);
171 cave_type **zcave;
172 struct dun_level *l_ptr = getfloor(wpos);
173
174 if (!wpos->wz || !(zcave = getcave(wpos)) || !cave_clean_bold(zcave, p_ptr->py, p_ptr->px)) {
175 msg_format(Ind, "\377wThis spell has no effect here.");
176 return 0;
177 }
178
179 if ((l_ptr->flags1 & LF1_CUSTOM_GATEWAY)) {
180 msg_print(Ind, "\377yThe presence of another active gateway spell is disturbing your attempt.");
181 return 0;
182 }
183
184 if (p_ptr->voidx && p_ptr->voidy) {
185 if (place_between_targetted(wpos, p_ptr->py, p_ptr->px, p_ptr->voidy, p_ptr->voidx)) {
186 //TODO: jumpgate limit? Using level flag for this here:
187 l_ptr->flags1 |= LF1_CUSTOM_GATEWAY;
188
189 //When successfull, we clear state, so we can create more.
190 p_ptr->voidx = 0;
191 p_ptr->voidy = 0;
192
193 p_ptr->redraw |= (PR_MAP);
194 msg_format(Ind, "\377vYou successfully create a gateway between the two points!");
195 msg_format_near(Ind, "\377v%s has successfully created a gateway!", p_ptr->name);
196 }
197 /* completed the spell successfully */
198 return 2;
199 }
200
201 // Let's not have this in towns/houses; OK everywhere else
202 if (!allow_terraforming(wpos, FEAT_TREE)) return 0;
203
204 msg_format(Ind, "\377vYou set your mind to create a gateway here.");
205
206 p_ptr->voidx = p_ptr->px;
207 p_ptr->voidy = p_ptr->py;
208
209 place_between_dummy(wpos, p_ptr->py, p_ptr->px);
210 return 1;
211 }
212 /* A: instant wor for every party member on level. INCLUDING town recalls?
213 * /rec 32 32 -> will attempt to teleport party members to Bree.
214 * further note: hm, this could fatally disturb idle party members. also dangerous if all party teleports into a D pit!!. make this only active if player (and therefore interested party members) are not in town.
215 * D: void jumpgate creation
216 */
divine_gateway(int Ind)217 void divine_gateway(int Ind) {
218 player_type *p_ptr = Players[Ind];
219 if (p_ptr->ptrait == TRAIT_ENLIGHTENED) {
220
221 //XXX call set_recall ?
222 if (istown(&p_ptr->wpos) || !p_ptr->wpos.wz) {
223 msg_format(Ind, "\377wThis spell has no effect here.");
224 return;
225 }
226
227 // Send some audio feedback
228 Send_beep(Ind);
229
230 set_recall_timer(Ind, 1);
231
232 int i;
233 for (i = 1; i <= NumPlayers; i++) {
234 if (i == Ind) continue;
235 if (Players[i]->conn == NOT_CONNECTED) continue;
236
237 /* on the same dungeon floor */
238 if (!inarea(&p_ptr->wpos, &Players[i]->wpos)) continue;
239
240 /* must be in the same party */
241 if (!Players[i]->party || p_ptr->party != Players[i]->party) continue;
242
243 set_recall_timer(i, 1);
244 }
245 } else if (p_ptr->ptrait == TRAIT_CORRUPTED)
246 (void)py_create_gateway(Ind);
247 }
248
249 #else /*lol, shared .pkg*/
divine_vengeance(int Ind,int power)250 void divine_vengeance(int Ind, int power) {
251 return;
252 }
divine_empowerment(int Ind,int power)253 void divine_empowerment(int Ind, int power) {
254 return;
255 }
divine_intensify(int Ind,int power)256 void divine_intensify(int Ind, int power) {
257 return;
258 }
divine_gateway(int Ind)259 void divine_gateway(int Ind) {
260 return;
261 }
262 #endif
263
264
265 /* for mindcrafters: teleport to friendly player with open mind - C. Blue */
do_autokinesis_to(int Ind,int dis)266 void do_autokinesis_to(int Ind, int dis) {
267 player_type *p_ptr = Players[Ind], *q_ptr;
268 int i;
269
270 if (p_ptr->party == 0) {
271 msg_print(Ind, "You can only teleport to party members.");
272 return;
273 }
274
275 for (i = 1; i <= NumPlayers; i++) {
276 /* Skip self */
277 if (i == Ind) continue;
278 q_ptr = Players[i];
279 /* Skip disconnected players */
280 if (q_ptr->conn == NOT_CONNECTED) continue;
281 /* Skip DM if not DM himself */
282 if (q_ptr->admin_dm && !p_ptr->admin_dm) continue;
283 /* Skip ghosts */
284 if (q_ptr->ghost && !q_ptr->admin_dm) continue;
285 /* Skip players not on this depth */
286 if (!inarea(&q_ptr->wpos, &p_ptr->wpos)) continue;
287 /* Skip players not in the same party */
288 if (q_ptr->party == 0 || p_ptr->party != q_ptr->party) continue;
289 /* Skip players who haven't opened their mind */
290 if (!(q_ptr->esp_link_flags & LINKF_OPEN)) continue;
291 /* Skip targets too far away */
292 if (distance(p_ptr->py, p_ptr->px, q_ptr->py, q_ptr->px) > dis) continue;
293
294 /* success */
295 msg_print(Ind, "You reach an allied mind!");
296 teleport_player_to(Ind, q_ptr->py, q_ptr->px);
297 return;
298 }
299
300 /* fail */
301 msg_print(Ind, "You couldn't make out any destination within your mental reach.");
302 }
303
304 /*
305 * Grow trees
306 */
grow_trees(int Ind,int rad)307 void grow_trees(int Ind, int rad)
308 {
309 player_type *p_ptr = Players[Ind];
310 int a, i, j;
311
312 if (!allow_terraforming(&p_ptr->wpos, FEAT_TREE)) return;
313
314 #ifdef USE_SOUND_2010
315 sound(Ind, "grow_trees", NULL, SFX_TYPE_COMMAND, FALSE);
316 #endif
317
318 for (a = 0; a < rad * rad + 11; a++) {
319 cave_type **zcave = getcave(&p_ptr->wpos);
320
321 i = (rand_int((rad * 2) + 1) - rad + rand_int((rad * 2) + 1) - rad) / 2;
322 j = (rand_int((rad * 2) + 1) - rad + rand_int((rad * 2) + 1) - rad) / 2;
323
324 if (!in_bounds2(&p_ptr->wpos, p_ptr->py + j, p_ptr->px + i)) continue;
325 if (distance(p_ptr->py, p_ptr->px, p_ptr->py + j, p_ptr->px + i) > rad) continue;
326
327 if (cave_naked_bold(zcave, p_ptr->py + j, p_ptr->px + i) &&
328 (zcave[p_ptr->py + j][p_ptr->px + i].feat != FEAT_HOME_OPEN)) /* HACK - not on open house door - mikaelh */
329 {
330 cave_set_feat_live(&p_ptr->wpos, p_ptr->py + j, p_ptr->px + i, magik(50)?FEAT_TREE:FEAT_BUSH);
331 }
332 }
333 }
334
335 /*
336 * Garden of the Gods handler :-)
337 * Basically go through each wall tile in dungeon. For each one, there is a chance% of it
338 * getting turned into a tree. - the_sandman
339 */
create_garden(int Ind,int chance)340 bool create_garden(int Ind, int chance) {
341 int y, x;
342 player_type *p_ptr; //Who(and where)?
343 cave_type *c_ptr;
344 p_ptr = Players[Ind];
345
346 struct c_special *cs_ptr; /* for special key doors */
347 struct worldpos *wpos = &(p_ptr->wpos);
348
349 cave_type **zcave;
350 if(!(zcave = getcave(wpos))) return (FALSE);
351
352 if (!allow_terraforming(wpos, FEAT_TREE)) return(FALSE);
353
354 for (y = 0; y < MAX_HGT; y++) {
355 for (x = 0; x < MAX_WID; x++) {
356 if (!in_bounds(y, x)) continue;
357
358 c_ptr = &zcave[y][x];
359
360 /*
361 * Never transform vaults (altough it would create some potentially
362 * nasty effects >;) Imagine all those Z seeping out to get you...
363 */
364 if (c_ptr->info & CAVE_ICKY) continue;
365
366 if((cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) continue;
367
368 if (cave_valid_bold(zcave, y, x) && ( /* <- destroyable, no art on grid, not FF1_PERMANENT */
369 // (c_ptr->feat == FEAT_QUARTZ) ||
370 // (c_ptr->feat == FEAT_MAGMA) ||
371 // (c_ptr->feat == FEAT_QUARTZ_H) ||
372 // (c_ptr->feat == FEAT_QUARTZ_K) ||
373 // (c_ptr->feat == FEAT_MAGMA_K) ||
374 // (c_ptr->feat == FEAT_SAND_WALL) ||
375 // (c_ptr->feat == FEAT_SAND_WALL_H) ||
376 // (c_ptr->feat == FEAT_SAND_WALL_K) ||
377 // (c_ptr->feat == FEAT_ICE_WALL) ||
378 // (c_ptr->feat == FEAT_GLASS_WALL) ||
379 // (c_ptr->feat == FEAT_ILLUS_WALL) ||
380 (c_ptr->feat == FEAT_WALL_EXTRA) || /* granite walls: */
381 (c_ptr->feat == FEAT_WALL_INNER) ||
382 (c_ptr->feat == FEAT_WALL_OUTER) ||
383 (c_ptr->feat == FEAT_WALL_SOLID))
384 // && !cave_floor_bold(zcave, y, x) /* don't convert empty floor! */
385 // && !(f_info[c_ptr->feat].flags1 & FF1_PERMANENT)
386 )
387 {
388 if (randint(100) < chance) {
389 /* Delete the object (if any) */
390 delete_object(wpos, y, x, TRUE);
391 cave_set_feat_live(&p_ptr->wpos, y, x, magik(50)?FEAT_TREE:FEAT_BUSH);
392 //c_ptr->feat = feat;
393 }
394 }
395 } //width
396 } //height
397
398 /* Message */
399 msg_print(Ind, "You see raw power escaping from the rocks!");
400 msg_print_near(Ind, "You see raw power escaping from the rocks!");
401 return (TRUE);
402 }//garden
403
404 /*
405 * this will now add to both melee and ranged toHit instead at a rate of
406 * spell_lvl/2
407 * Yep. More druidry. - the_sandman
408 */
do_focus_shot(int Ind,int v,int p)409 bool do_focus_shot(int Ind, int v, int p) {
410 player_type *p_ptr = Players[Ind];
411 bool notice = FALSE;
412
413 /* Hack -- Force good values */
414 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
415
416 /* Open */
417 if (v)
418 {
419 if (!p_ptr->focus_time)
420 {
421 msg_format_near(Ind, "%s's arm movements turn blurry!", p_ptr->name);
422 msg_print(Ind, "Your arms feel... dexterous!");
423 notice = TRUE;
424 }
425 p_ptr->focus_time = v;
426 p_ptr->focus_val = p;
427 calc_boni(Ind);
428 }
429
430 /* Shut */
431 else
432 {
433 if (p_ptr->focus_time)
434 {
435 msg_format_near(Ind, "You can see %s's arms again.", p_ptr->name);
436 msg_print(Ind, "Your feel your arms turn into lead.");
437 notice = TRUE;
438 p_ptr->focus_time = 0;
439 }
440 p_ptr->focus_val = 0;
441 }
442
443 #if 0
444 //Buggy with another set_fast
445 /* Decrease speed */
446 if (p_ptr->focus_time != 0) set_fast(Ind, v, -(p/5));
447 #endif
448
449 /* Nothing to notice */
450 if (!notice) return (FALSE);
451
452 /* Disturb */
453 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
454
455 /* Recalculate bonuses */
456 p_ptr->update |= (PU_BONUS);
457
458 /* Handle stuff */
459 handle_stuff(Ind);
460
461 /* Result */
462 return (TRUE);
463 }//focus shot
464
465 /*
466 * Extra stats! By how much depends on the player's level.
467 * At the moment it is +1 for every 7.
468 * Druidry. - the_sandman
469 */
do_xtra_stats(int Ind,int v,int p)470 bool do_xtra_stats(int Ind, int v, int p) {
471 player_type *p_ptr = Players[Ind];
472 bool notice = (FALSE);
473
474 /* Hack -- Force good values */
475 v = (v > cfg.spell_stack_limit) ? cfg.spell_stack_limit : (v < 0) ? 0 : v;
476
477 /* Open */
478 if (v) {
479 if (!p_ptr->xtrastat || p_ptr->statval < p) {
480 msg_format_near(Ind, "%s seems to be more powerful!", p_ptr->name);
481 msg_print(Ind, "You feel... powerful!");
482
483 p_ptr->xstr = 0;
484 p_ptr->xint = 0;
485 p_ptr->xdex = 0;
486 p_ptr->xcon = 0;
487
488 p_ptr->statval = p;
489 p = (p / 10) + 2;
490 switch (p_ptr->statval / 5) {
491 default: p_ptr->xint = p;
492 case 3:
493 case 2: p_ptr->xcon = p;
494 case 1: p_ptr->xdex = p;
495 case 0: p_ptr->xstr = p;
496 }
497
498 notice = TRUE;
499 }
500 }
501
502 /* Shut */
503 else { //v = 0;
504 if (p_ptr->xtrastat) {
505 msg_format_near(Ind, "%s returns to %s normal self.", p_ptr->name, (p_ptr->male? "his" : "her"));
506 msg_print(Ind, "You somehow feel weak.");
507
508 p_ptr->xtrastat = 0;
509 p_ptr->statval = 0;
510
511 notice = TRUE;
512 }
513 }
514
515 p_ptr->xtrastat = v;
516
517 /* Nothing to notice */
518 if (!notice) return (FALSE);
519
520 /* Disturb */
521 if (p_ptr->disturb_state) disturb(Ind, 0, 0);
522
523 /* Recalculate bonuses */
524 p_ptr->update |= (PU_BONUS);
525
526 /* Handle stuff */
527 handle_stuff(Ind);
528
529 /* Result */
530 return (TRUE);
531 }//xtra stats
532
533 /*
534 * The last spell to be added for tonight!
535 * "Banish" animals... Killing them, really. - the_sandman
536 */
do_banish_animals(int Ind,int chance)537 bool do_banish_animals(int Ind, int chance) {
538 int i, j = 0, c;
539 player_type *p_ptr;
540 p_ptr = Players[Ind];
541 cave_type **zcave;
542 dun_level *l_ptr;
543 struct worldpos *wpos = &p_ptr->wpos;
544
545 if (Ind < 0 || chance <= 0) return (FALSE);
546 if (!(zcave = getcave(wpos))) return(FALSE);
547 if ((l_ptr = getfloor(wpos)) && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
548
549 for (i = 1; i < m_max; i++) {
550 monster_type *m_ptr = &m_list[i];
551 monster_race *r_ptr = race_inf(m_ptr);
552 if ((r_ptr->flags1 & RF1_UNIQUE)) continue;
553 if (!(r_ptr->flags3 & RF3_ANIMAL)) continue;
554 if ((r_ptr->flags9 & RF9_IM_TELE)) continue;
555 //if ((r_ptr->flags3 & RF3_RES_TELE) && magik(50)) continue;
556 if (!inarea(&m_ptr->wpos, wpos)) continue;
557
558 /* Taken from genocide_aux(): Not valid inside a vault */
559 if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
560
561 c = chance - r_ptr->level;
562 if (c <= 0) continue;
563 if (c > rand_int(100)) {
564 //off with you!
565 delete_monster_idx(i, TRUE);
566 j++;
567 }
568 }
569 if (j < 5) {
570 msg_print(Ind, "\337gA few here long for their gardens.");
571 msg_format_near(Ind, "\337g%s tries hard but alas can only convert a few animals.", p_ptr->name);
572 } else if (j < 10) {
573 msg_print(Ind, "\337gA handful here longs for their gardens.");
574 msg_format_near(Ind, "\337g%s tries hard but alas can only convert a handful of animals.", p_ptr->name);
575 } else if (j < 20) {
576 msg_print(Ind, "\337gA pack here abandoned evil to retire in their gardens.");
577 msg_format_near(Ind, "\337g%s tries hard and you notice animals going away.", p_ptr->name);
578 } else if (j < 50) {
579 msg_print(Ind, "\337gIt's a near-miracle!");
580 msg_format_near(Ind, "\337g%s banishes animals with conviction.", p_ptr->name);
581 } else {
582 msg_print(Ind, "\337gThe Day of Returning is here!.");
583 /* lol */
584 msg_format_near(Ind, "\337gYou see %s's tears of joy at the number of returning animals.", p_ptr->name);
585 }
586 return (TRUE);
587 }
588
589 /* For Dawn activation - C. Blue
590 (note: highest non-unique undead is Black Reaver: level 74) */
do_banish_undead(int Ind,int chance)591 bool do_banish_undead(int Ind, int chance) {
592 int i, j = 0, c;
593 player_type *p_ptr;
594 p_ptr = Players[Ind];
595 cave_type **zcave;
596 dun_level *l_ptr;
597 struct worldpos *wpos = &p_ptr->wpos;
598
599 if (Ind < 0 || chance <= 0) return (FALSE);
600 if (!(zcave = getcave(wpos))) return(FALSE);
601 if ((l_ptr = getfloor(wpos)) && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
602
603 for (i = 1; i < m_max; i++) {
604 monster_type *m_ptr = &m_list[i];
605 monster_race *r_ptr = race_inf(m_ptr);
606 if ((r_ptr->flags1 & RF1_UNIQUE)) continue;
607 if (!(r_ptr->flags3 & RF3_UNDEAD)) continue;
608 if ((r_ptr->flags9 & RF9_IM_TELE)) continue;
609 //if ((r_ptr->flags3 & RF3_RES_TELE) && magik(50)) continue;
610 if (!inarea(&m_ptr->wpos, wpos)) continue;
611
612 /* Taken from genocide_aux(): Not valid inside a vault */
613 if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
614
615 c = chance - r_ptr->level;
616 if (c <= 0) continue;
617 if (c > rand_int(100)) {
618 //off with you!
619 delete_monster_idx(i, TRUE);
620 j++;
621 }
622 }
623 /* (no time for tears of joy dealing with undead) */
624 return (TRUE);
625 }
626
627 /* For Mardra activation - C. Blue
628 (note: highest non-unique D is GWoP: level 85) */
do_banish_dragons(int Ind,int chance)629 bool do_banish_dragons(int Ind, int chance) {
630 int i, j = 0, c;
631 player_type *p_ptr;
632 p_ptr = Players[Ind];
633 cave_type **zcave;
634 dun_level *l_ptr;
635 struct worldpos *wpos = &p_ptr->wpos;
636
637 if (Ind < 0 || chance <= 0) return (FALSE);
638 if (!(zcave = getcave(wpos))) return(FALSE);
639 if ((l_ptr = getfloor(wpos)) && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
640
641 for (i = 1; i < m_max; i++) {
642 monster_type *m_ptr = &m_list[i];
643 monster_race *r_ptr = race_inf(m_ptr);
644 if ((r_ptr->flags1 & RF1_UNIQUE)) continue;
645 if (!(r_ptr->flags3 & RF3_DRAGON)) continue;
646 if ((r_ptr->flags9 & RF9_IM_TELE)) continue;
647 //if ((r_ptr->flags3 & RF3_RES_TELE) && magik(50)) continue;
648 if (!inarea(&m_ptr->wpos, wpos)) continue;
649
650 /* Taken from genocide_aux(): Not valid inside a vault */
651 if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
652
653 c = chance - r_ptr->level;
654 if (c <= 0) continue;
655 if (c > rand_int(100)) {
656 //off with you!
657 delete_monster_idx(i, TRUE);
658 j++;
659 }
660 }
661 /* (no time for tears of joy dealing with undead) */
662 return (TRUE);
663 }
664
665 /*
666 * Increase players hit points, notice effects, and tell the player about it.
667 */
hp_player(int Ind,int num)668 bool hp_player(int Ind, int num) {
669 player_type *p_ptr = Players[Ind];
670
671 // The "number" that the character is displayed as before healing
672 int old_num, new_num;
673 long eff_num; /* actual amount of HP gain */
674 long e = PVP_DIMINISHING_HEALING_CAP(p_ptr);
675
676 if (p_ptr->no_heal) return FALSE;
677
678 p_ptr->test_heal += num;
679
680 // The "number" that the character is displayed as before healing
681 old_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
682 if (old_num >= 7) old_num = 10;
683
684 /* player can't be healed while burning in the holy fire of martyrium */
685 if (p_ptr->martyr && !bypass_invuln) return(FALSE);
686
687 /* Hell mode is .. hard */
688 if ((p_ptr->mode & MODE_HARD) && (num > 3)) num = num * 3 / 4;
689
690 eff_num = (p_ptr->mhp - p_ptr->chp < num) ? (p_ptr->mhp - p_ptr->chp) : num;
691
692 /* PVP mode uses diminishing healing - C. Blue */
693 if (p_ptr->mode & MODE_PVP) {
694 eff_num = eff_num * (p_ptr->heal_effect < e ? 100 :
695 ((e * 100) / ((p_ptr->heal_effect - (e * 2) / 3) * 3)));
696 eff_num /= 100;
697 }
698
699 if (!eff_num) return(FALSE);
700
701 if (p_ptr->chp < p_ptr->mhp) {
702 /* data collection for PVP mode: weaken continous healing over time to prevent silliness (who stacks more pots) - C. Blue */
703 p_ptr->heal_effect += eff_num;
704
705 /* data collection for C_BLUE_AI: add up healing happening during current turn */
706 p_ptr->heal_turn[0] += eff_num;
707
708 /* refill HP, note that we can't use eff_num here due to chp_frac check */
709 num = eff_num;
710 p_ptr->chp += num;
711 if (p_ptr->chp > p_ptr->mhp) {
712 p_ptr->chp = p_ptr->mhp;
713 p_ptr->chp_frac = 0;
714 }
715
716 /* Update health bars */
717 update_health(0 - Ind);
718
719 /* Redraw */
720 p_ptr->redraw |= (PR_HP);
721
722 /* Figure out of if the player's "number" has changed */
723 new_num = (p_ptr->chp * 95) / (p_ptr->mhp * 10);
724 if (new_num >= 7) new_num = 10;
725
726 /* If so then refresh everyone's view of this player */
727 if (new_num != old_num)
728 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
729
730 /* Window stuff */
731 p_ptr->window |= (PW_PLAYER);
732
733 num = num / 5;
734 if (num < 3) {
735 if (num == 0) {
736 msg_print(Ind, "You feel a little better.");
737 } else {
738 msg_print(Ind, "You feel better.");
739 }
740 } else {
741 if (num < 7) {
742 msg_print(Ind, "You feel much better.");
743 } else {
744 msg_print(Ind, "You feel very good.");
745 }
746 }
747
748 return (TRUE);
749 }
750
751 return (FALSE);
752 }
753
754 /*
755 * Increase players hit points, notice effects, and don't tell the player it.
756 * 'autoeffect' stands for non-'intended' healing, that applies automatically,
757 * such as necromancy, vampiric items, standard body regeneration;
758 * set 'autoeffect' to TRUE if you want to do forced healing without any
759 * implications.
760 */
hp_player_quiet(int Ind,int num,bool autoeffect)761 bool hp_player_quiet(int Ind, int num, bool autoeffect) {
762 player_type *p_ptr = Players[Ind];
763
764 // The "number" that the character is displayed as before healing
765 int old_num, new_num;
766 long eff_num; /* actual amount of HP gain */
767 long e = PVP_DIMINISHING_HEALING_CAP(p_ptr);
768
769 if (p_ptr->no_heal && !autoeffect) return FALSE;
770
771 p_ptr->test_heal += num;
772
773 old_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
774 if (old_num >= 7) old_num = 10;
775
776 /* player can't be healed while burning in the holy fire of martyrium */
777 if (p_ptr->martyr && !bypass_invuln) return(FALSE);
778
779 /* Hell mode is .. hard */
780 if ((p_ptr->mode & MODE_HARD) && (num > 3)) num = num * 3 / 4;
781
782 eff_num = (p_ptr->mhp - p_ptr->chp < num) ? (p_ptr->mhp - p_ptr->chp) : num;
783
784 /* PVP mode uses diminishing healing - C. Blue */
785 if (!autoeffect && (p_ptr->mode & MODE_PVP)) {
786 eff_num = eff_num * (p_ptr->heal_effect < e ? 100 :
787 ((e * 100) / ((p_ptr->heal_effect - (e * 2) / 3) * 3)));
788 eff_num /= 100;
789 }
790
791 if (!eff_num) return(FALSE);
792
793 if (p_ptr->chp < p_ptr->mhp) {
794 if (!autoeffect) {
795 /* data collection for PVP mode: weaken continous healing over time to prevent silliness (who stacks more pots) - C. Blue */
796 p_ptr->heal_effect += eff_num;
797 }
798 /* data collection for C_BLUE_AI: add up healing happening during current turn */
799 p_ptr->heal_turn[0] += eff_num;
800
801 /* refill HP, note that we can't use eff_num here due to chp_frac check */
802 num = eff_num;
803 p_ptr->chp += num;
804 if (p_ptr->chp > p_ptr->mhp) {
805 p_ptr->chp = p_ptr->mhp;
806 p_ptr->chp_frac = 0;
807 }
808
809 /* Update health bars */
810 update_health(0 - Ind);
811
812 /* Redraw */
813 p_ptr->redraw |= (PR_HP);
814
815 /* Figure out of if the player's "number" has changed */
816 new_num = (p_ptr->chp * 95) / (p_ptr->mhp*10);
817 if (new_num >= 7) new_num = 10;
818
819 /* If so then refresh everyone's view of this player */
820 if (new_num != old_num)
821 everyone_lite_spot(&p_ptr->wpos, p_ptr->py, p_ptr->px);
822
823 /* Window stuff */
824 p_ptr->window |= (PW_PLAYER);
825
826 return (TRUE);
827 }
828
829 return (FALSE);
830 }
831
832
flash_bomb(int Ind)833 void flash_bomb(int Ind)
834 {
835 player_type *p_ptr = Players[Ind];
836 msg_print(Ind, "You throw down a blinding flash bomb!");
837 msg_format_near(Ind, "%s throws a blinding flash bomb!", p_ptr->name);
838
839 #ifdef USE_SOUND_2010
840 sound(Ind, "flash_bomb", NULL, SFX_TYPE_COMMAND, TRUE);
841 #endif
842
843 // project_los(Ind, GF_BLIND, (p_ptr->lev / 10) + 4, "");
844 project_los(Ind, GF_BLIND, (p_ptr->lev / 10) + 8, "");
845 }
846
847
848 /*
849 * Leave a "glyph of warding" which prevents monster movement
850 */
warding_glyph(int Ind)851 void warding_glyph(int Ind)
852 {
853 player_type *p_ptr = Players[Ind];
854
855 cave_type **zcave;
856 if (!(zcave = getcave(&p_ptr->wpos))) return;
857
858 if (!allow_terraforming(&p_ptr->wpos, FEAT_GLYPH) && !is_admin(p_ptr)) return;
859
860 cave_set_feat_live(&p_ptr->wpos, p_ptr->py, p_ptr->px, FEAT_GLYPH);
861 }
862
863
864 /*
865 * Array of stat "descriptions"
866 */
867 static cptr desc_stat_pos[] =
868 {
869 "strong",
870 "smart",
871 "wise",
872 "dextrous",
873 "healthy",
874 "cute"
875 };
876
877 #if 0 // second set for future use
878 {
879 "mighty",
880 "intelligent",
881 "sagacious",
882 "agile",
883 "sturdy",
884 "charming"
885 }
886 #endif // 0
887
888
889 /*
890 * Array of stat "descriptions"
891 */
892 static cptr desc_stat_neg[] =
893 {
894 "weak",
895 "stupid",
896 "naive",
897 "clumsy",
898 "sickly",
899 "ugly"
900 };
901
902 static cptr desc_stat_neg2[] =
903 {
904 "strong",
905 "bright",
906 "wise",
907 "agile",
908 "hale",
909 "beautiful"
910 };
911
912 #if 0
913 {
914 "feeble",
915 "dull",
916 "foolish",
917 "awkward",
918 "fragile",
919 "indecent"
920 },
921 #endif // 0
922
923
924 /*
925 * Lose a "point"
926 */
do_dec_stat(int Ind,int stat,int mode)927 bool do_dec_stat(int Ind, int stat, int mode)
928 {
929 player_type *p_ptr = Players[Ind];
930
931 bool sust = FALSE;
932
933 /* Access the "sustain" */
934 switch (stat)
935 {
936 case A_STR: if (p_ptr->sustain_str) sust = TRUE; break;
937 case A_INT: if (p_ptr->sustain_int) sust = TRUE; break;
938 case A_WIS: if (p_ptr->sustain_wis) sust = TRUE; break;
939 case A_DEX: if (p_ptr->sustain_dex) sust = TRUE; break;
940 case A_CON: if (p_ptr->sustain_con) sust = TRUE; break;
941 case A_CHR: if (p_ptr->sustain_chr) sust = TRUE; break;
942 }
943
944 /* Sustain */
945 if (sust || safe_area(Ind))
946 {
947 /* Message */
948 msg_format(Ind, "You feel %s for a moment, but the feeling passes.",
949 desc_stat_neg[stat]);
950
951 /* Notice effect */
952 return (TRUE);
953 }
954
955 /* Attempt to reduce the stat */
956 if (dec_stat(Ind, stat, 10, mode))
957 {
958 /* Message */
959 msg_format(Ind, "You feel very %s.", desc_stat_neg[stat]);
960
961 /* Notice effect */
962 return (TRUE);
963 }
964
965 /* Nothing obvious */
966 return (FALSE);
967 }
968
969
970 /*
971 * Lose a "point" by a TIME attack (or Black Breath)
972 */
do_dec_stat_time(int Ind,int stat,int mode,int sust_chance,int reduction_mode,bool msg)973 bool do_dec_stat_time(int Ind, int stat, int mode, int sust_chance, int reduction_mode, bool msg)
974 {
975 player_type *p_ptr = Players[Ind];
976
977 bool sust = FALSE;
978
979 /* Access the "sustain" */
980 switch (stat)
981 {
982 case A_STR: if (p_ptr->sustain_str) sust = TRUE; break;
983 case A_INT: if (p_ptr->sustain_int) sust = TRUE; break;
984 case A_WIS: if (p_ptr->sustain_wis) sust = TRUE; break;
985 case A_DEX: if (p_ptr->sustain_dex) sust = TRUE; break;
986 case A_CON: if (p_ptr->sustain_con) sust = TRUE; break;
987 case A_CHR: if (p_ptr->sustain_chr) sust = TRUE; break;
988 }
989
990 if (p_ptr->stat_cur[stat] <= 3) return(FALSE);
991
992 /* Sustain */
993 if ((sust && magik(sust_chance)) || safe_area(Ind)) {
994 /* Message */
995 msg_format(Ind, "You don't feel as %s as you used to be, but the feeling passes",
996 desc_stat_neg2[stat]);
997
998 /* Notice effect */
999 return (TRUE);
1000 }
1001
1002 /* Message */
1003 if (msg) msg_format(Ind, "You're not as %s as you used to be.", desc_stat_neg2[stat]);
1004
1005 /* Attempt to reduce the stat */
1006 switch (reduction_mode) {
1007 case 0:
1008 if (dec_stat(Ind, stat, 10, mode))
1009 {
1010 /* Notice effect */
1011 return (TRUE);
1012 }
1013 break;
1014 case 1:
1015 p_ptr->stat_cur[stat] = (p_ptr->stat_cur[stat] * 3) / 4;
1016 break;
1017 case 2:
1018 p_ptr->stat_cur[stat] = (p_ptr->stat_cur[stat] * 6) / 7;
1019 break;
1020 case 3:
1021 p_ptr->stat_cur[stat] = (p_ptr->stat_cur[stat] * 7) / 8;
1022 break;
1023 }
1024 if (p_ptr->stat_cur[stat] < 3) p_ptr->stat_cur[stat] = 3;
1025
1026 if (mode == STAT_DEC_PERMANENT) p_ptr->stat_max[stat] = p_ptr->stat_cur[stat];
1027
1028 p_ptr->update |= (PU_BONUS | PU_MANA | PU_HP | PU_SANITY);
1029
1030 /* Nothing obvious */
1031 return (TRUE);
1032 }
1033
1034
1035 /*
1036 * Restore lost "points" in a stat
1037 */
do_res_stat(int Ind,int stat)1038 bool do_res_stat(int Ind, int stat)
1039 {
1040 /* Attempt to increase */
1041 if (res_stat(Ind, stat))
1042 {
1043 /* Message */
1044 msg_format(Ind, "You feel less %s.", desc_stat_neg[stat]);
1045
1046 /* Notice */
1047 return (TRUE);
1048 }
1049
1050 /* Nothing obvious */
1051 return (FALSE);
1052 }
1053
1054 /*
1055 * Restore temporary-lost "points" in a stat
1056 */
do_res_stat_temp(int Ind,int stat)1057 bool do_res_stat_temp(int Ind, int stat)
1058 {
1059 player_type *p_ptr = Players[Ind];
1060
1061 /* Restore if needed */
1062 if (p_ptr->stat_cur[stat] != p_ptr->stat_max[stat])
1063 {
1064 /* Restore */
1065 p_ptr->stat_cur[stat] += p_ptr->stat_los[stat];
1066
1067 if (p_ptr->stat_cur[stat] > p_ptr->stat_max[stat])
1068 p_ptr->stat_cur[stat] = p_ptr->stat_max[stat];
1069
1070 p_ptr->stat_los[stat] = 0;
1071 p_ptr->stat_cnt[stat] = 0;
1072
1073 /* Recalculate bonuses */
1074 p_ptr->update |= (PU_BONUS);
1075
1076 /* Message */
1077 msg_format(Ind, "You feel less %s.", desc_stat_neg[stat]);
1078 /* Success */
1079 return (TRUE);
1080 }
1081
1082 /* Nothing to restore */
1083 return (FALSE);
1084 }
1085
1086 /*
1087 * Gain a "point" in a stat
1088 */
do_inc_stat(int Ind,int stat)1089 bool do_inc_stat(int Ind, int stat)
1090 {
1091 bool res;
1092
1093 /* Restore strength */
1094 res = res_stat(Ind, stat);
1095
1096 /* Attempt to increase */
1097 if (inc_stat(Ind, stat))
1098 {
1099 /* Message */
1100 msg_format(Ind, "Wow! You feel very %s!", desc_stat_pos[stat]);
1101
1102 /* Notice */
1103 return (TRUE);
1104 }
1105
1106 /* Restoration worked */
1107 if (res)
1108 {
1109 /* Message */
1110 msg_format(Ind, "You feel less %s.", desc_stat_neg[stat]);
1111
1112 /* Notice */
1113 return (TRUE);
1114 }
1115
1116 /* Nothing obvious */
1117 return (FALSE);
1118 }
1119
1120
1121
1122 /*
1123 * Identify everything being carried.
1124 * Done by a potion of "self knowledge".
1125 */
identify_pack(int Ind)1126 void identify_pack(int Ind) {
1127 player_type *p_ptr = Players[Ind];
1128
1129 int i;
1130 object_type *o_ptr;
1131 bool inven_unchanged[INVEN_TOTAL];
1132
1133 /* Simply identify and know every item */
1134 for (i = 0; i < INVEN_TOTAL; i++) {
1135 inven_unchanged[i] = TRUE;
1136 o_ptr = &p_ptr->inventory[i];
1137
1138 if (o_ptr->k_idx) {
1139 if (object_known_p(Ind, o_ptr) && object_aware_p(Ind, o_ptr)) continue;
1140
1141 object_aware(Ind, o_ptr);
1142 object_known(o_ptr);
1143 inven_unchanged[i] = FALSE;
1144 }
1145 }
1146
1147 /* Recalculate bonuses */
1148 p_ptr->update |= (PU_BONUS);
1149
1150 /* Combine / Reorder the pack (later) */
1151 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
1152
1153 /* Window stuff */
1154 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
1155
1156 /* Handle stuff */
1157 handle_stuff(Ind);
1158
1159 #if 0 /* moved to client-side, clean! */
1160 /* hack: trigger client-side auto-inscriptions for convenience,
1161 if it isn't due anyway. */
1162 if (!p_ptr->inventory_changes) Send_inventory_revision(Ind);
1163 #endif
1164 /* well, instead: */
1165 for (i = 0; i < INVEN_TOTAL; i++) {
1166 if (inven_unchanged[i]) continue;
1167 Send_apply_auto_insc(Ind, i);
1168 }
1169 }
1170
1171
1172
1173
1174
1175
1176 /*
1177 * Used by the "enchant" function (chance of failure)
1178 */
1179 static int enchant_table[16] =
1180 {
1181 0, 10, 50, 100, 200,
1182 300, 400, 500, 700, 875,
1183 960, 980, 990, 996, 999,
1184 1000
1185 };
1186
1187 /*
1188 * Lock a door. Currently range of one only.. Maybe a beam
1189 * would be better?
1190 */
wizard_lock(int Ind,int dir)1191 void wizard_lock(int Ind, int dir){
1192 player_type *p_ptr;
1193 cave_type **zcave, *c_ptr;
1194 int dy, dx;
1195
1196 p_ptr = Players[Ind];
1197 if (!p_ptr) return;
1198 zcave = getcave(&p_ptr->wpos);
1199 if (!zcave) return;
1200
1201 /* anti-cheeze: exp'ing with doors */
1202 if (!p_ptr->wpos.wz) return;
1203
1204 dx = p_ptr->px + ddx[dir];
1205 dy = p_ptr->py + ddy[dir];
1206
1207 c_ptr = &zcave[dy][dx];
1208 if (c_ptr->feat >= FEAT_DOOR_HEAD && c_ptr->feat < (FEAT_DOOR_HEAD + 7)) {
1209 if (c_ptr->feat == FEAT_DOOR_HEAD) {
1210 msg_print(Ind, "The door locks!");
1211 c_ptr->info |= CAVE_MAGELOCK;
1212 } else msg_print(Ind, "The door appears stronger!");
1213 c_ptr->feat++;
1214 } else if (c_ptr->feat != (FEAT_DOOR_HEAD + 7))
1215 msg_print(Ind, "You see no lockable door there");
1216 else
1217 msg_print(Ind, "The door is locked fast already!");
1218 }
1219
1220 /*
1221 * Removes curses from items in inventory
1222 *
1223 * Note that Items which are "Perma-Cursed" (The One Ring,
1224 * The Crown of Morgoth) can NEVER be uncursed.
1225 *
1226 * Note that if "all" is FALSE, then Items which are
1227 * "Heavy-Cursed" (Mormegil, Calris, and Weapons of Morgul)
1228 * will not be uncursed.
1229 */
1230 /*
1231 * 0x01 - all
1232 * 0x02 - limit to one item (added for projectable spell)
1233 */
remove_curse_aux(int Ind,int all,int pInd)1234 int remove_curse_aux(int Ind, int all, int pInd) {
1235 player_type *p_ptr = Players[Ind];
1236 object_type *o_ptr;
1237 #ifdef NEW_REMOVE_CURSE
1238 char o_name[ONAME_LEN];
1239 #endif
1240
1241 int i, j, cnt = 0;
1242 u32b f1, f2, f3, f4, f5, f6, esp;
1243
1244 #ifdef NEW_REMOVE_CURSE
1245 if (pInd) msg_format(Ind, "%s recites some holy words..", Players[pInd]->name);
1246 #endif
1247
1248 for (j = 0; j < INVEN_TOTAL; j++) {
1249 i = (j + INVEN_WIELD) % INVEN_TOTAL;
1250 o_ptr = &p_ptr->inventory[i];
1251
1252 /* Uncursed already */
1253 if (!cursed_p(o_ptr)) continue;
1254
1255 /* Extract the flags */
1256 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
1257
1258 /* Heavily Cursed Items need a special spell */
1259 if (!(all & 0x01) && (f3 & TR3_HEAVY_CURSE)) continue;
1260
1261 /* Perma-Cursed Items can NEVER be uncursed */
1262 if ((f3 & TR3_PERMA_CURSE) && !is_admin(p_ptr)) continue;
1263
1264 #ifdef NEW_REMOVE_CURSE
1265 /* Allow rc to fail sometimes */
1266 if ((!(all & 0x01) || (f3 & TR3_HEAVY_CURSE)) && magik(o_ptr->level)) {
1267 object_desc(Ind, o_name, o_ptr, FALSE, 3);
1268 msg_format(Ind, "Your %s shimmer%s purple for a moment..", o_name, o_ptr->number == 1 ? "s" : "");
1269 continue;
1270 }
1271
1272 object_desc(Ind, o_name, o_ptr, FALSE, 3);
1273 msg_format(Ind, "Your %s flash%s blue!", o_name, o_ptr->number == 1 ? "es" : "");
1274 #endif
1275
1276 /* Uncurse it */
1277 o_ptr->ident &= ~ID_CURSED;
1278
1279 /* Hack -- Assume felt */
1280 o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
1281
1282 /* Take note */
1283 note_toggle_cursed(o_ptr, FALSE);
1284
1285 /* Recalculate the bonuses */
1286 p_ptr->update |= (PU_BONUS);
1287
1288 /* Window stuff */
1289 p_ptr->window |= (PW_INVEN | PW_EQUIP);
1290
1291 /* Count the uncursings */
1292 cnt++;
1293
1294 /* Not everything at once. */
1295 #ifdef NEW_REMOVE_CURSE
1296 if ((all & 0x02) ||
1297 #else
1298 if (
1299 #endif
1300 (!(all & 0x01) && magik(50)))
1301 break;
1302 }
1303
1304 /* Return "something uncursed" */
1305 return (cnt);
1306 }
1307
1308
1309 /* well, erm... */
1310 /*
1311 * Remove most curses
1312 */
remove_curse(int Ind)1313 bool remove_curse(int Ind) {
1314 #ifndef NEW_REMOVE_CURSE
1315 return (remove_curse_aux(Ind, 0x0, 0));
1316 #else
1317 /* assume we're called _only_ as the projectable holy school spell */
1318 int i, p, r = 0;
1319 cave_type **zcave;
1320 player_type *p_ptr = Players[Ind];
1321
1322 /* remove our own curse(s) first - can't remove other player's curses while we're not cleansed ;) */
1323 i = remove_curse_aux(Ind, 0x0, 0);
1324 if (i) return i;
1325
1326 /* remove someone else's curse */
1327 if ((zcave = getcave(&p_ptr->wpos))) {
1328 /* check grids around the player, first one we find possibly gets a curse fixed */
1329 for (i = 7; i >= 0; i--) {
1330 if ((p = zcave[p_ptr->py + ddy_ddd[i]][p_ptr->px + ddx_ddd[i]].m_idx >= 0)) continue;
1331 r = remove_curse_aux(-p, 0x0 + 0x2, Ind);
1332 break;
1333 }
1334 }
1335
1336 /* remove our own curse(s) */
1337 return r;
1338 #endif
1339 }
1340
1341 /*
1342 * Remove all curses
1343 */
remove_all_curse(int Ind)1344 bool remove_all_curse(int Ind) {
1345 #ifndef NEW_REMOVE_CURSE
1346 return (remove_curse_aux(Ind, 0x1, 0));
1347 #else
1348 /* assume we're called _only_ as the projectable holy school spell */
1349 int i, p, r = 0;
1350 cave_type **zcave;
1351 player_type *p_ptr = Players[Ind];
1352
1353 /* remove our own curse(s) first - can't remove other player's curses while we're not cleansed ;) */
1354 i = remove_curse_aux(Ind, 0x1, 0);
1355 if (i) return i;
1356
1357 /* remove someone else's curse */
1358 if ((zcave = getcave(&p_ptr->wpos))) {
1359 /* check grids around the player, first one we find possibly gets a curse fixed */
1360 for (i = 7; i >= 0; i--) {
1361 if ((p = zcave[p_ptr->py + ddy_ddd[i]][p_ptr->px + ddx_ddd[i]].m_idx >= 0)) continue;
1362 r = remove_curse_aux(-p, 0x1 + 0x2, Ind);
1363 break;
1364 }
1365 }
1366 return r;
1367 #endif
1368 }
1369
1370 /*
1371 * Restores any drained experience
1372 */
restore_level(int Ind)1373 bool restore_level(int Ind)
1374 {
1375 player_type *p_ptr = Players[Ind];
1376
1377 /* Restore experience */
1378 if (p_ptr->exp < p_ptr->max_exp) {
1379 /* Message */
1380 msg_print(Ind, "You feel your life energies returning.");
1381
1382 /* Restore the experience */
1383 p_ptr->exp = p_ptr->max_exp;
1384
1385 /* Check the experience */
1386 check_experience(Ind);
1387
1388 /* Did something */
1389 return (TRUE);
1390 }
1391
1392 /* No effect */
1393 return (FALSE);
1394 }
1395
1396
1397 /*
1398 * self-knowledge... idea from nethack. Useful for determining powers and
1399 * resistences of items. It saves the screen, clears it, then starts listing
1400 * attributes, a screenful at a time. (There are a LOT of attributes to
1401 * list. It will probably take 2 or 3 screens for a powerful character whose
1402 * using several artifacts...) -CFT
1403 *
1404 * It is now a lot more efficient. -BEN-
1405 *
1406 * See also "identify_fully()".
1407 *
1408 * XXX XXX XXX Use the "show_file()" method, perhaps.
1409 */
self_knowledge(int Ind)1410 void self_knowledge(int Ind) {
1411 player_type *p_ptr = Players[Ind];
1412 int k;
1413 u32b f1 = 0L, f2 = 0L, f3 = 0L, f4 = 0L, f5 = 0L, f6 = 0L; //, esp = 0L;
1414 object_type *o_ptr;
1415 // cptr *info = p_ptr->info;
1416 bool life = FALSE;
1417 FILE *fff;
1418 #if 0
1419 char file_name[MAX_PATH_LENGTH];
1420
1421 /* Temporary file */
1422 if (path_temp(file_name, MAX_PATH_LENGTH)) return;
1423 strcpy(p_ptr->infofile, file_name);
1424 #endif // 0
1425 /* Open a new file */
1426 fff = my_fopen(p_ptr->infofile, "wb");
1427 /* Current file viewing */
1428 strcpy(p_ptr->cur_file, p_ptr->infofile);
1429
1430 /* Output color byte */
1431 // fprintf(fff, "%c", 'w');
1432
1433 /* Let the player scroll through the info */
1434 p_ptr->special_file_type = TRUE;
1435
1436 /* Acquire item flags from equipment */
1437 for (k = INVEN_WIELD; k < INVEN_TOTAL; k++) {
1438 u32b t1, t2, t3, t4, t5, t6, tesp;
1439 o_ptr = &p_ptr->inventory[k];
1440 /* Skip empty items */
1441 if (!o_ptr->k_idx) continue;
1442 /* Extract the flags */
1443 object_flags(o_ptr, &t1, &t2, &t3, &t4, &t5, &t6, &tesp);
1444
1445 /* Extract flags */
1446 f1 |= t1;
1447 f2 |= t2;
1448 f3 |= t3;
1449 f4 |= t4;
1450 f5 |= t5;
1451 f6 |= t6;
1452
1453 /* Mega Hack^3 -- check the amulet of life saving */
1454 if (o_ptr->tval == TV_AMULET &&
1455 o_ptr->sval == SV_AMULET_LIFE_SAVING)
1456 life = TRUE;
1457 }
1458
1459 /* Mega Hack^3 -- describe the amulet of life saving */
1460 if (life) fprintf(fff, "Your life will be saved from perilous scene once.\n");
1461
1462 #if 0
1463 k = 100 - p_ptr->csane * 100 / p_ptr->msane;
1464 if (k < 100) {
1465 // sprintf(info[i++], "%d%% of your mind is under your control.", k);
1466 fprintf(fff, "%d%% of your mind is under your control.\n", k);
1467 }
1468 #else
1469 /* Insanity warning (better message needed!) */
1470 if (p_ptr->csane < p_ptr->msane / 8) {
1471 fprintf(fff, "You are next to mad.\n");
1472 } else if (p_ptr->csane < p_ptr->msane / 4) {
1473 fprintf(fff, "Your mind is filled with insane thoughts.\n");
1474 } else if (p_ptr->csane < p_ptr->msane / 2) {
1475 fprintf(fff, "You have a seed of insanity in your mind.\n");
1476 }
1477 #endif
1478
1479 if (p_ptr->blind) fprintf(fff, "You cannot see.\n");
1480 if (p_ptr->confused) fprintf(fff, "You are confused.\n");
1481 if (p_ptr->afraid) fprintf(fff, "You are terrified.\n");
1482 if (p_ptr->cut) fprintf(fff, "\377rYou are bleeding.\n");
1483 if (p_ptr->stun) fprintf(fff, "\377oYou are stunned.\n");
1484 if (p_ptr->poisoned) fprintf(fff, "\377GYou are poisoned.\n");
1485 if (p_ptr->image) fprintf(fff, "You are hallucinating.\n");
1486
1487 if (p_ptr->aggravate) fprintf(fff, "You aggravate monsters.\n");
1488 if (p_ptr->teleport) fprintf(fff, "Your position is very uncertain.\n");
1489
1490 if (p_ptr->blessed) fprintf(fff, "You feel rightous.\n");
1491 if (p_ptr->hero) fprintf(fff, "You feel heroic.\n");
1492 if (p_ptr->shero) fprintf(fff, "You are in a battle rage.\n");
1493 if (p_ptr->fury) fprintf(fff, "You are in a wild fury.\n");
1494 if (p_ptr->berserk) fprintf(fff, "You are going berserk.\n");
1495 if (p_ptr->protevil) fprintf(fff, "You are protected from evil.\n");
1496 #if 0
1497 if (p_ptr->protgood) fprintf(fff, "You are protected from good.\n");
1498 #endif // 0
1499 if (p_ptr->shield) fprintf(fff, "You are protected by a mystic shield.\n");
1500 if (p_ptr->invuln) fprintf(fff, "You are temporarily invulnerable.\n");
1501 if (p_ptr->confusing) fprintf(fff, "Your hands are glowing dull red.\n");
1502 if (p_ptr->stunning) fprintf(fff, "Your hands are very heavy.\n");
1503 if (p_ptr->searching) fprintf(fff, "You are looking around very carefully.\n");
1504 #if 0
1505 if (p_ptr->new_spells) fprintf(fff, "You can learn some more spells.\n");
1506 #endif
1507 if (p_ptr->word_recall) fprintf(fff, "You will soon be recalled.\n");
1508 if (p_ptr->see_infra) fprintf(fff, "Your eyes are sensitive to infrared light.\n");
1509 if (p_ptr->invis) fprintf(fff, "You are invisible.\n");
1510 #if 0 /* really not required to tell the player this stuff, it'd be just spam */
1511 if (p_ptr->cloaked) fprintf(fff, "You are cloaked.\n");
1512 if (p_ptr->shadow_running) fprintf(fff, "You are shadow_running.\n");
1513 #endif
1514 if (p_ptr->see_inv) fprintf(fff, "You can see invisible creatures.\n");
1515 if (p_ptr->feather_fall) fprintf(fff, "You land gently.\n");
1516 #if 1
1517 if (p_ptr->climb) fprintf(fff, "You can climb high mountains.\n");
1518 if (p_ptr->levitate) fprintf(fff, "You can levitate.\n");
1519 if (p_ptr->can_swim) fprintf(fff, "You can swim easily.\n");
1520 #endif // 0
1521 if (p_ptr->free_act) fprintf(fff, "You have free action.\n");
1522 if (p_ptr->regenerate) fprintf(fff, "You regenerate quickly.\n");
1523 if (p_ptr->resist_time) fprintf(fff, "You are resistant to time.\n");
1524 if (p_ptr->resist_mana) fprintf(fff, "You are resistant to magical energy.\n");
1525 if (p_ptr->immune_water) fprintf(fff, "You are completely protected from unleashed water.\n");
1526 else if (p_ptr->resist_water) fprintf(fff, "You are resistant to unleashed water.\n");
1527 if (p_ptr->regen_mana) fprintf(fff, "You accumulate mana quickly.\n");
1528
1529 if (p_ptr->prace == RACE_MAIA && p_ptr->ptrait) fprintf(fff, "You have no need for worldly food.\n");
1530 else if (get_skill(p_ptr, SKILL_HSUPPORT) >= 40) fprintf(fff, "You have no need for worldly food.\n");
1531 else if (p_ptr->ghost) fprintf(fff, "You have no need for worldly food.\n");
1532 else if (p_ptr->prace == RACE_VAMPIRE && p_ptr->total_winner) fprintf(fff, "Your appetite is small.\n");
1533 else if (p_ptr->slow_digest) fprintf(fff, "Your appetite is small.\n");
1534
1535 if (p_ptr->telepathy) {
1536 // fprintf(fff, "You have ESP.\n");
1537 if (p_ptr->telepathy & ESP_ALL) fprintf(fff, "You have ESP.\n");
1538 else {
1539 if (p_ptr->telepathy & ESP_ORC) fprintf(fff, "You can sense the presence of orcs.\n");
1540 if (p_ptr->telepathy & ESP_TROLL) fprintf(fff, "You can sense the presence of trolls.\n");
1541 if (p_ptr->telepathy & ESP_DRAGON) fprintf(fff, "You can sense the presence of dragons.\n");
1542 if (p_ptr->telepathy & ESP_SPIDER) fprintf(fff, "You can sense the presence of spiders.\n");
1543 if (p_ptr->telepathy & ESP_GIANT) fprintf(fff, "You can sense the presence of giants.\n");
1544 if (p_ptr->telepathy & ESP_DEMON) fprintf(fff, "You can sense the presence of demons.\n");
1545 if (p_ptr->telepathy & ESP_UNDEAD) fprintf(fff, "You can sense presence of undead.\n");
1546 if (p_ptr->telepathy & ESP_EVIL) fprintf(fff, "You can sense the presence of evil beings.\n");
1547 if (p_ptr->telepathy & ESP_ANIMAL) fprintf(fff, "You can sense the presence of animals.\n");
1548 if (p_ptr->telepathy & ESP_DRAGONRIDER) fprintf(fff, "You can sense the presence of dragonriders.\n");
1549 if (p_ptr->telepathy & ESP_GOOD) fprintf(fff, "You can sense the presence of good beings.\n");
1550 if (p_ptr->telepathy & ESP_NONLIVING) fprintf(fff, "You can sense the presence of non-living things.\n");
1551 if (p_ptr->telepathy & ESP_UNIQUE) fprintf(fff, "You can sense the presence of unique beings.\n");
1552 }
1553 }
1554 if (p_ptr->antimagic) // older (percent)
1555 {
1556 // fprintf(fff, "You are surrounded by an anti-magic field.\n");
1557 if (p_ptr->antimagic >= ANTIMAGIC_CAP) /* AM cap */
1558 fprintf(fff, "You are surrounded by a complete anti-magic field.\n");
1559 else if (p_ptr->antimagic >= ANTIMAGIC_CAP - 10)
1560 fprintf(fff, "You are surrounded by a mighty anti-magic field.\n");
1561 else if (p_ptr->antimagic >= ANTIMAGIC_CAP - 20)
1562 fprintf(fff, "You are surrounded by a strong anti-magic field.\n");
1563 else if (p_ptr->antimagic >= 50)
1564 fprintf(fff, "You are surrounded by an anti-magic field.\n");
1565 else if (p_ptr->antimagic >= 30)
1566 fprintf(fff, "You are surrounded by a weaker anti-magic field.\n");
1567 else fprintf(fff, "You are surrounded by a feeble anti-magic field.\n");
1568
1569 }
1570 #if 1
1571 if (p_ptr->anti_magic) // newer (saving-throw boost)
1572 fprintf(fff, "You are surrounded by an anti-magic shell.\n");
1573 #endif // 0
1574 if (p_ptr->hold_life) fprintf(fff, "You have a firm hold on your life force.\n");
1575 #if 1 // somewhat hacky
1576 if (p_ptr->lite) fprintf(fff, "You are carrying a permanent light.\n");
1577 #endif // 0
1578 if (p_ptr->auto_id) fprintf(fff, "You can sense magic.\n");
1579 #if 1
1580 if (p_ptr->reflect) fprintf(fff, "You reflect arrows and bolts.\n");
1581 if (p_ptr->no_cut) fprintf(fff, "You cannot be cut.\n");
1582
1583 if (p_ptr->reduce_insanity > 0) {
1584 fprintf(fff, "Your mind is somewhat resistant against insanity.\n");
1585 }
1586 if (p_ptr->suscep_fire) fprintf(fff, "You are susceptible to fire.\n");
1587 if (p_ptr->suscep_cold) fprintf(fff, "You are susceptible to cold.\n");
1588 if (p_ptr->suscep_acid) fprintf(fff, "You are susceptible to acid.\n");
1589 if (p_ptr->suscep_elec) fprintf(fff, "You are susceptible to electricity.\n");
1590 if (p_ptr->suscep_pois) fprintf(fff, "You are susceptible to poison.\n");
1591 if (p_ptr->suscep_lite) fprintf(fff, "You are susceptible to light.\n");
1592 if (p_ptr->suscep_good) fprintf(fff, "You are susceptible to evil-vanquishing effects.\n");
1593 if (p_ptr->suscep_evil) fprintf(fff, "You are susceptible to good-vanquishing effects.\n");
1594 if (p_ptr->suscep_life) fprintf(fff, "You are susceptible to undead-vanquishing effects.\n");
1595
1596 if (p_ptr->sh_fire) fprintf(fff, "You are surrounded with a fiery aura.\n");
1597 if (p_ptr->sh_elec) fprintf(fff, "You are surrounded with electricity.\n");
1598 if (p_ptr->sh_cold) fprintf(fff, "You are surrounded with a freezing aura.\n");
1599
1600 if (p_ptr->resist_continuum) fprintf(fff, "The space-time continuum cannot be disrupted near you.\n");
1601 if (p_ptr->anti_tele) fprintf(fff, "You are surrounded by an anti-teleportation field.\n");
1602 if (p_ptr->res_tele) fprintf(fff, "You resist incoming teleportation effects.\n");
1603 #endif // 0
1604
1605 if (p_ptr->immune_acid) fprintf(fff, "You are completely immune to acid.\n");
1606 else if ((p_ptr->resist_acid) && (p_ptr->oppose_acid))
1607 fprintf(fff, "You resist acid exceptionally well.\n");
1608 else if ((p_ptr->resist_acid) || (p_ptr->oppose_acid))
1609 fprintf(fff, "You are resistant to acid.\n");
1610
1611 if (p_ptr->immune_elec) fprintf(fff, "You are completely immune to lightning.\n");
1612 else if ((p_ptr->resist_elec) && (p_ptr->oppose_elec))
1613 fprintf(fff, "You resist lightning exceptionally well.\n");
1614 else if ((p_ptr->resist_elec) || (p_ptr->oppose_elec))
1615 fprintf(fff, "You are resistant to lightning.\n");
1616
1617 if (p_ptr->immune_fire) fprintf(fff, "You are completely immune to fire.\n");
1618 else if ((p_ptr->resist_fire) && (p_ptr->oppose_fire))
1619 fprintf(fff, "You resist fire exceptionally well.\n");
1620 else if ((p_ptr->resist_fire) || (p_ptr->oppose_fire))
1621 fprintf(fff, "You are resistant to fire.\n");
1622
1623 if (p_ptr->immune_cold) fprintf(fff, "You are completely immune to cold.\n");
1624 else if ((p_ptr->resist_cold) && (p_ptr->oppose_cold))
1625 fprintf(fff, "You resist cold exceptionally well.\n");
1626 else if ((p_ptr->resist_cold) || (p_ptr->oppose_cold))
1627 fprintf(fff, "You are resistant to cold.\n");
1628
1629 if (p_ptr->immune_poison) fprintf(fff, "You are completely immune to poison.\n");
1630 else if ((p_ptr->resist_pois) && (p_ptr->oppose_pois))
1631 fprintf(fff, "You resist poison exceptionally well.\n");
1632 else if ((p_ptr->resist_pois) || (p_ptr->oppose_pois))
1633 fprintf(fff, "You are resistant to poison.\n");
1634
1635 if (p_ptr->resist_lite) fprintf(fff, "You are resistant to bright light.\n");
1636 if (p_ptr->resist_dark) fprintf(fff, "You are resistant to darkness.\n");
1637 if (p_ptr->resist_conf) fprintf(fff, "You are resistant to confusion.\n");
1638 if (p_ptr->resist_sound) fprintf(fff, "You are resistant to sonic attacks.\n");
1639 if (p_ptr->resist_disen) fprintf(fff, "You are resistant to disenchantment.\n");
1640 if (p_ptr->resist_chaos) fprintf(fff, "You are resistant to chaos.\n");
1641 if (p_ptr->resist_shard) fprintf(fff, "You are resistant to blasts of shards.\n");
1642 if (p_ptr->resist_nexus) fprintf(fff, "You are resistant to nexus attacks.\n");
1643 if (p_ptr->immune_neth) fprintf(fff, "You are immune to nether forces.\n");
1644 else if (p_ptr->resist_neth) fprintf(fff, "You are resistant to nether forces.\n");
1645 if (p_ptr->resist_fear) fprintf(fff, "You are completely fearless.\n");
1646 if (p_ptr->resist_blind) fprintf(fff, "Your eyes are resistant to blindness.\n");
1647
1648 if (p_ptr->sustain_str) fprintf(fff, "Your strength is sustained.\n");
1649 if (p_ptr->sustain_int) fprintf(fff, "Your intelligence is sustained.\n");
1650 if (p_ptr->sustain_wis) fprintf(fff, "Your wisdom is sustained.\n");
1651 if (p_ptr->sustain_con) fprintf(fff, "Your constitution is sustained.\n");
1652 if (p_ptr->sustain_dex) fprintf(fff, "Your dexterity is sustained.\n");
1653 if (p_ptr->sustain_chr) fprintf(fff, "Your charisma is sustained.\n");
1654 if (p_ptr->black_breath || p_ptr->black_breath_tmp)
1655 fprintf(fff, "You suffer from Black Breath.\n");
1656
1657 if (f1 & TR1_STR) fprintf(fff, "Your strength is affected by your equipment.\n");
1658 if (f1 & TR1_INT) fprintf(fff, "Your intelligence is affected by your equipment.\n");
1659 if (f1 & TR1_WIS) fprintf(fff, "Your wisdom is affected by your equipment.\n");
1660 if (f1 & TR1_DEX) fprintf(fff, "Your dexterity is affected by your equipment.\n");
1661 if (f1 & TR1_CON) fprintf(fff, "Your constitution is affected by your equipment.\n");
1662 if (f1 & TR1_CHR) fprintf(fff, "Your charisma is affected by your equipment.\n");
1663
1664 if (f1 & TR1_STEALTH) fprintf(fff, "Your stealth is affected by your equipment.\n");
1665 if (f1 & TR1_SEARCH) fprintf(fff, "Your searching ability is affected by your equipment.\n");
1666 if (f5 & TR5_DISARM) fprintf(fff, "Your disarming ability is affected by your equipment.\n");
1667 if (f1 & TR1_INFRA) fprintf(fff, "Your infravision is affected by your equipment.\n");
1668 if (f1 & TR1_TUNNEL) fprintf(fff, "Your digging ability is affected by your equipment.\n");
1669 if (f1 & TR1_SPEED) fprintf(fff, "Your speed is affected by your equipment.\n");
1670 if (f1 & TR1_BLOWS) fprintf(fff, "Your attack speed is affected by your equipment.\n");
1671 if (f5 & TR5_CRIT) fprintf(fff, "Your ability to score critical hits is affected by your equipment.\n");
1672
1673 if (p_ptr->luck == 40)
1674 fprintf(fff, "You are ultimatively lucky!\n");
1675 else if (p_ptr->luck >= 30)
1676 fprintf(fff, "You are lucky very frequently!\n");
1677 else if (p_ptr->luck >= 20)
1678 fprintf(fff, "You are lucky often.\n");
1679 else if (p_ptr->luck >= 10)
1680 fprintf(fff, "You are lucky here and there.\n");
1681 else if (p_ptr->luck > 0)
1682 fprintf(fff, "You are lucky sometimes.\n");
1683
1684 /* Analyze the weapon */
1685 if (p_ptr->inventory[INVEN_WIELD].k_idx ||
1686 (p_ptr->inventory[INVEN_ARM].k_idx && p_ptr->inventory[INVEN_ARM].tval != TV_SHIELD)) /* dual-wield */
1687 {
1688 /* Indicate Blessing */
1689 if (f3 & TR3_BLESSED) fprintf(fff, "Your weapon has been blessed by the gods.\n");
1690 if (f5 & TR5_CHAOTIC) fprintf(fff, "Your weapon is branded with the Sign of Chaos.\n");
1691 /* Hack */
1692 if (f5 & TR5_IMPACT) fprintf(fff, "The impact of your weapon can cause earthquakes.\n");
1693 if (f5 & TR5_VORPAL) fprintf(fff, "Your weapon is very sharp.\n");
1694 if (f1 & TR1_VAMPIRIC) fprintf(fff, "Your weapon drains life from your foes.\n");
1695
1696 /* Special "Attack Bonuses" */
1697 if (f1 & TR1_BRAND_ACID) fprintf(fff, "Your weapon melts your foes.\n");
1698 if (f1 & TR1_BRAND_ELEC) fprintf(fff, "Your weapon shocks your foes.\n");
1699 if (f1 & TR1_BRAND_FIRE) fprintf(fff, "Your weapon burns your foes.\n");
1700 if (f1 & TR1_BRAND_COLD) fprintf(fff, "Your weapon freezes your foes.\n");
1701 if (f1 & TR1_BRAND_POIS) fprintf(fff, "Your weapon poisons your foes.\n");
1702
1703 /* Special "slay" flags */
1704 if (f1 & TR1_SLAY_ORC) fprintf(fff, "Your weapon is especially deadly against orcs.\n");
1705 if (f1 & TR1_SLAY_TROLL) fprintf(fff, "Your weapon is especially deadly against trolls.\n");
1706 if (f1 & TR1_SLAY_GIANT) fprintf(fff, "Your weapon is especially deadly against giants.\n");
1707 if (f1 & TR1_SLAY_ANIMAL) fprintf(fff, "Your weapon strikes at animals with extra force.\n");
1708 if (f1 & TR1_KILL_UNDEAD) fprintf(fff, "Your weapon is a great bane of undead.\n");
1709 else if (f1 & TR1_SLAY_UNDEAD) fprintf(fff, "Your weapon strikes at undead with holy wrath.\n");
1710 if (f1 & TR1_KILL_DEMON) fprintf(fff, "Your weapon is a great bane of demons.\n");
1711 else if (f1 & TR1_SLAY_DEMON) fprintf(fff, "Your weapon strikes at demons with holy wrath.\n");
1712 if (f1 & TR1_KILL_DRAGON) fprintf(fff, "Your weapon is a great bane of dragons.\n");
1713 else if (f1 & TR1_SLAY_DRAGON) fprintf(fff, "Your weapon is especially deadly against dragons.\n");
1714 if (f1 & TR1_SLAY_EVIL) fprintf(fff, "Your weapon strikes at evil with extra force.\n");
1715 }
1716 // info[i] = NULL;
1717
1718 /* Close the file */
1719 my_fclose(fff);
1720
1721 /* Let the client know to expect some info */
1722 strcpy(p_ptr->cur_file_title, "Knowledge of Yourself");
1723 Send_special_other(Ind);
1724 }
1725
1726
1727 /*
1728 * Forget everything
1729 */
lose_all_info(int Ind)1730 bool lose_all_info(int Ind) {
1731 player_type *p_ptr = Players[Ind];
1732 int i;
1733 char note2[80], noteid[10];
1734
1735 if (safe_area(Ind)) return TRUE;
1736 if (p_ptr->auto_id) return FALSE;
1737
1738 /* Forget info about objects */
1739 for (i = 0; i < INVEN_TOTAL; i++) {
1740 object_type *o_ptr = &p_ptr->inventory[i];
1741
1742 /* Skip non-items */
1743 if (!o_ptr->k_idx) continue;
1744
1745 /* Allow "protection" by the MENTAL flag */
1746 if (o_ptr->ident & ID_MENTAL) continue;
1747
1748 /* Remove "default inscriptions" */
1749 if (o_ptr->note && (o_ptr->ident & ID_SENSE)) {
1750 #if 0
1751 /* Access the inscription */
1752 cptr q = quark_str(o_ptr->note);
1753
1754 /* Hack -- Remove auto-inscriptions */
1755 if ((streq(q, "cursed")) ||
1756 //"uncursed"?
1757 (streq(q, "broken")) ||
1758 (streq(q, "good")) ||
1759 (streq(q, "average")) ||
1760 (streq(q, "excellent")) ||
1761 (streq(q, "worthless")) ||
1762 (streq(q, "special")) ||
1763 (streq(q, "terrible"))) {
1764 /* Forget the inscription */
1765 o_ptr->note = 0;
1766 }
1767 #else
1768 note_crop_pseudoid(note2, noteid, quark_str(o_ptr->note));
1769 if (!note2[0]) o_ptr->note = o_ptr->note_utag = 0;//utag is paranoia
1770 else o_ptr->note = quark_add(note2);
1771 #endif
1772 }
1773
1774 /* Hack -- Clear the "empty" flag */
1775 o_ptr->ident &= ~ID_EMPTY;
1776
1777 /* Hack -- Clear the "known" flag */
1778 o_ptr->ident &= ~ID_KNOWN;
1779
1780 /* Hack -- Clear the "felt" flag */
1781 o_ptr->ident &= ~(ID_SENSE | ID_SENSE_HEAVY);
1782 }
1783
1784 /* Recalculate bonuses */
1785 p_ptr->update |= (PU_BONUS);
1786
1787 /* Combine / Reorder the pack (later) */
1788 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
1789
1790 /* Window stuff */
1791 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
1792
1793 /* Mega-Hack -- Forget the map */
1794 wiz_dark(Ind);
1795
1796 /* It worked */
1797 return (TRUE);
1798 }
1799
1800
1801 /*
1802 * Detect any treasure on the current panel -RAK-
1803 *
1804 * We do not yet create any "hidden gold" features XXX XXX XXX
1805 */
1806 /*
1807 * TODO:
1808 * 1. allow to display gold carried by monsters
1809 * 2. make this a ranged spell
1810 */
detect_treasure(int Ind,int rad)1811 bool detect_treasure(int Ind, int rad) {
1812 player_type *p_ptr = Players[Ind];
1813 struct worldpos *wpos = &p_ptr->wpos;
1814 dun_level *l_ptr;
1815 int py = p_ptr->py, px = p_ptr->px;
1816
1817 int y, x;
1818 bool detect = FALSE;
1819
1820 cave_type *c_ptr;
1821 byte *w_ptr;
1822 object_type *o_ptr;
1823 cave_type **zcave;
1824
1825 /* anti-exploit */
1826 if (!local_panel(Ind)) return FALSE;
1827
1828 if (!(zcave = getcave(wpos))) return(FALSE);
1829 l_ptr = getfloor(wpos);
1830
1831 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
1832 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
1833
1834 /* Scan the current panel */
1835 // for (y = p_ptr->panel_row_min; y <= p_ptr->panel_row_max; y++)
1836 for (y = py - rad; y <= py + rad; y++) {
1837 // for (x = p_ptr->panel_col_min; x <= p_ptr->panel_col_max; x++)
1838 for (x = px - rad; x <= px + rad; x++) {
1839 /* Reject locations outside of dungeon */
1840 if (!in_bounds4(l_ptr, y, x)) continue;
1841
1842 /* Reject those out of radius */
1843 if (distance(py, px, y, x) > rad) continue;
1844
1845 c_ptr = &zcave[y][x];
1846 w_ptr = &p_ptr->cave_flag[y][x];
1847
1848 o_ptr = &o_list[c_ptr->o_idx];
1849
1850 /* Magma/Quartz + Known Gold */
1851 if ((c_ptr->feat == FEAT_MAGMA_K) ||
1852 (c_ptr->feat == FEAT_QUARTZ_K) ||
1853 (c_ptr->feat == FEAT_SANDWALL_K))
1854 {
1855 /* Notice detected gold */
1856 if (!(*w_ptr & CAVE_MARK)) {
1857 /* Detect */
1858 detect = TRUE;
1859
1860 /* Hack -- memorize the feature */
1861 *w_ptr |= CAVE_MARK;
1862
1863 /* Redraw */
1864 lite_spot(Ind, y, x);
1865 }
1866 }
1867
1868 /* Notice embedded gold */
1869 if ((c_ptr->feat == FEAT_MAGMA_H) ||
1870 (c_ptr->feat == FEAT_QUARTZ_H) ||
1871 (c_ptr->feat == FEAT_SANDWALL_H))
1872 {
1873 /* Expose the gold */
1874 c_ptr->feat += 0x02;
1875
1876 /* Detect */
1877 detect = TRUE;
1878
1879 /* Hack -- memorize the item */
1880 *w_ptr |= CAVE_MARK;
1881
1882 /* Redraw */
1883 lite_spot(Ind, y, x);
1884 }
1885
1886 /* Notice gold */
1887 if (o_ptr->tval == TV_GOLD) {
1888 /* Notice new items */
1889 if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
1890 /* Detect */
1891 detect = TRUE;
1892
1893 /* Hack -- memorize the item */
1894 p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
1895
1896 /* Redraw */
1897 lite_spot(Ind, y, x);
1898 }
1899 }
1900 }
1901 }
1902
1903 return (detect);
1904 }
1905 /* detect treasures level-wide, for DIGGING skill */
floor_detect_treasure(int Ind)1906 bool floor_detect_treasure(int Ind) {
1907 player_type *p_ptr = Players[Ind];
1908 struct worldpos *wpos = &p_ptr->wpos;
1909 dun_level *l_ptr;
1910 int y, x;
1911 bool detect = FALSE;
1912 cave_type *c_ptr;
1913 byte *w_ptr;
1914 object_type *o_ptr;
1915 cave_type **zcave;
1916
1917 if (!(zcave = getcave(wpos))) return(FALSE);
1918 if (!(l_ptr = getfloor(wpos))) return(FALSE); /* doesn't work on surface levels (wpos.wz == 0) */
1919
1920 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
1921 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
1922
1923 /* Scan the whole level */
1924 for (y = 0; y < l_ptr->hgt; y++) {
1925 for (x = 0; x < l_ptr->wid; x++) {
1926 /* Reject locations outside of dungeon */
1927 if (!in_bounds4(l_ptr, y, x)) continue;
1928
1929 c_ptr = &zcave[y][x];
1930 w_ptr = &p_ptr->cave_flag[y][x];
1931 o_ptr = &o_list[c_ptr->o_idx];
1932
1933 /* Magma/Quartz + Known Gold */
1934 if ((c_ptr->feat == FEAT_MAGMA_K) ||
1935 (c_ptr->feat == FEAT_QUARTZ_K) ||
1936 (c_ptr->feat == FEAT_SANDWALL_K)) {
1937 /* Notice detected gold */
1938 if (!(*w_ptr & CAVE_MARK)) {
1939 /* Detect */
1940 detect = TRUE;
1941 /* Hack -- memorize the feature */
1942 *w_ptr |= CAVE_MARK;
1943 /* Redraw */
1944 lite_spot(Ind, y, x);
1945 }
1946 }
1947
1948 /* Notice embedded gold */
1949 if ((c_ptr->feat == FEAT_MAGMA_H) ||
1950 (c_ptr->feat == FEAT_QUARTZ_H) ||
1951 (c_ptr->feat == FEAT_SANDWALL_H)) {
1952 /* Expose the gold */
1953 c_ptr->feat += 0x02;
1954 /* Detect */
1955 detect = TRUE;
1956 /* Hack -- memorize the item */
1957 *w_ptr |= CAVE_MARK;
1958 /* Redraw */
1959 lite_spot(Ind, y, x);
1960 }
1961
1962 /* Notice gold */
1963 if (o_ptr->tval == TV_GOLD) {
1964 /* Notice new items */
1965 if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
1966 /* Detect */
1967 detect = TRUE;
1968 /* Hack -- memorize the item */
1969 p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
1970 /* Redraw */
1971 lite_spot(Ind, y, x);
1972 }
1973 }
1974 }
1975 }
1976 return (detect);
1977 }
1978
1979
1980
1981 /*
1982 * Detect magic items.
1983 *
1984 * This will light up all spaces with "magic" items, including artifacts,
1985 * ego-items, potions, scrolls, books, rods, wands, staves, amulets, rings,
1986 * and "enchanted" items of the "good" variety.
1987 *
1988 * It can probably be argued that this function is now too powerful.
1989 */
detect_magic(int Ind,int rad)1990 bool detect_magic(int Ind, int rad) {
1991 player_type *p_ptr = Players[Ind];
1992
1993 struct worldpos *wpos = &p_ptr->wpos;
1994 dun_level *l_ptr;
1995 // int py = p_ptr->py, px = p_ptr->px;
1996
1997 int i, j, tv;
1998 bool detect = FALSE;
1999
2000 cave_type *c_ptr;
2001 object_type *o_ptr;
2002
2003 cave_type **zcave;
2004
2005 /* anti-exploit */
2006 if (!local_panel(Ind)) return FALSE;
2007
2008 if (!(zcave = getcave(wpos))) return(FALSE);
2009 l_ptr = getfloor(wpos);
2010
2011 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2012 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2013
2014 /* Scan the current panel */
2015 // for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2016 for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2017 // for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2018 for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2019 /* Reject locations outside of dungeon */
2020 if (!in_bounds4(l_ptr, i, j)) continue;
2021
2022 /* Reject those out of radius */
2023 if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2024
2025 /* Access the grid and object */
2026 c_ptr = &zcave[i][j];
2027 o_ptr = &o_list[c_ptr->o_idx];
2028
2029 /* Nothing there */
2030 if (!(c_ptr->o_idx)) continue;
2031
2032 /* Examine the tval */
2033 tv = o_ptr->tval;
2034
2035 /* Artifacts, misc magic items, or enchanted wearables */
2036 if (artifact_p(o_ptr) || ego_item_p(o_ptr) ||
2037 (tv == TV_AMULET) || (tv == TV_RING) ||
2038 is_magic_device(tv) ||
2039 (tv == TV_SCROLL) || (tv == TV_POTION) ||
2040 ((o_ptr->to_a > 0) || (o_ptr->to_h + o_ptr->to_d > 0)))
2041 {
2042 /* Note new items */
2043 if (!(p_ptr->obj_vis[c_ptr->o_idx]))
2044 {
2045 /* Detect */
2046 detect = TRUE;
2047
2048 /* Memorize the item */
2049 p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
2050
2051 /* Redraw */
2052 lite_spot(Ind, i, j);
2053 }
2054 }
2055 }
2056 }
2057
2058 /* Return result */
2059 return (detect);
2060 }
2061
2062
2063
2064
2065 /*
2066 * A "generic" detect monsters routine, tagged to flags3
2067 */
2068 //bool detect_monsters_xxx(u32b match_flag, int rad)
detect_monsters_xxx(int Ind,u32b match_flag)2069 bool detect_monsters_xxx(int Ind, u32b match_flag) {
2070 player_type *p_ptr = Players[Ind];
2071 int i, y, x;
2072 bool flag = FALSE;
2073 cptr desc_monsters = "weird monsters";
2074
2075 dun_level *l_ptr = getfloor(&p_ptr->wpos);
2076
2077 /* anti-exploit */
2078 if (!local_panel(Ind)) return FALSE;
2079
2080 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2081 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2082
2083 /* Clear previously detected stuff */
2084 clear_ovl(Ind);
2085
2086 /* Scan monsters */
2087 for (i = 1; i < m_max; i++) {
2088 monster_type *m_ptr = &m_list[i];
2089 monster_race *r_ptr = race_inf(m_ptr);
2090
2091 /* Skip dead monsters */
2092 if (!m_ptr->r_idx) continue;
2093
2094 /* Skip visible monsters */
2095 if (p_ptr->mon_vis[i]) continue;
2096
2097 /* Skip monsters not on this depth */
2098 if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2099
2100 /* Location */
2101 y = m_ptr->fy;
2102 x = m_ptr->fx;
2103
2104 /* Only detect nearby monsters */
2105 // if (m_ptr->cdis > rad) continue;
2106
2107 /* Detect evil monsters */
2108 if (!panel_contains(y, x)) continue;
2109
2110 /* Detect evil monsters */
2111 if (r_ptr->flags3 & (match_flag)) {
2112 byte a;
2113 char c;
2114
2115 /* Hack - Temporarily visible */
2116 p_ptr->mon_vis[i] = TRUE;
2117
2118 /* Get the look of the monster */
2119 map_info(Ind, y, x, &a, &c);
2120
2121 /* No longer visible */
2122 p_ptr->mon_vis[i] = FALSE;
2123
2124 /* Draw the monster on the screen */
2125 draw_spot_ovl(Ind, y, x, a, c);
2126
2127 flag = TRUE;
2128 }
2129 }
2130
2131 switch (match_flag) {
2132 case RF3_EVIL:
2133 desc_monsters = "evil";
2134 break;
2135 case RF3_DEMON:
2136 desc_monsters = "demons";
2137 break;
2138 case RF3_UNDEAD:
2139 desc_monsters = "the undead";
2140 break;
2141 case RF3_GOOD:
2142 desc_monsters = "good";
2143 break;
2144 case RF3_ORC:
2145 desc_monsters = "orcs";
2146 break;
2147 /* TODO: ...you know :) */
2148 }
2149
2150 /* Describe */
2151 if (flag) {
2152 /* Describe result */
2153 msg_format(Ind, "You sense the presence of %s!", desc_monsters);
2154 //msg_print(NULL);
2155
2156 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2157 /* Wait */
2158 Send_pause(Ind);
2159
2160 /* Mega-Hack -- Fix the monsters */
2161 update_monsters(FALSE);
2162 #endif
2163 } else {
2164 #ifdef DETECT_ABSENCE
2165 /* Describe result */
2166 msg_format(Ind, "You sense the absence of %s.", desc_monsters);
2167 #endif
2168 }
2169
2170 /* Result */
2171 return (flag);
2172 }
2173
2174
2175
2176 /*
2177 * Locates and displays all invisible creatures on current panel -RAK-
2178 */
detect_invisible(int Ind)2179 bool detect_invisible(int Ind) {
2180 player_type *p_ptr = Players[Ind];
2181
2182 int i;
2183 bool flag = FALSE;
2184
2185 dun_level *l_ptr = getfloor(&p_ptr->wpos);
2186
2187 /* anti-exploit */
2188 if (!local_panel(Ind)) return FALSE;
2189
2190 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2191 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2192
2193 /* Clear previously detected stuff */
2194 clear_ovl(Ind);
2195
2196 /* Detect all invisible monsters */
2197 for (i = 1; i < m_max; i++) {
2198 monster_type *m_ptr = &m_list[i];
2199 monster_race *r_ptr = race_inf(m_ptr);
2200
2201 int fy = m_ptr->fy;
2202 int fx = m_ptr->fx;
2203
2204 /* Paranoia -- Skip dead monsters */
2205 if (!m_ptr->r_idx) continue;
2206
2207 /* Skip visible monsters */
2208 if (p_ptr->mon_vis[i]) continue;
2209
2210 /* Skip monsters not on this depth */
2211 if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2212
2213 /* Detect all invisible monsters */
2214 if (panel_contains(fy, fx) && (r_ptr->flags2 & RF2_INVISIBLE)) {
2215 byte a;
2216 char c;
2217
2218 #ifdef OLD_MONSTER_LORE
2219 /* Take note that they are invisible */
2220 r_ptr->r_flags2 |= RF2_INVISIBLE;
2221 #endif
2222
2223 /* Hack - Temporarily visible */
2224 p_ptr->mon_vis[i] = TRUE;
2225
2226 /* Get the look of the monster */
2227 map_info(Ind, fy, fx, &a, &c);
2228
2229 /* No longer visible */
2230 p_ptr->mon_vis[i] = FALSE;
2231
2232 /* Draw the monster on the screen */
2233 draw_spot_ovl(Ind, fy, fx, a, c);
2234
2235 flag = TRUE;
2236 }
2237 }
2238
2239 /* Detect all invisible players */
2240 for (i = 1; i <= NumPlayers; i++) {
2241 player_type *q_ptr = Players[i];
2242
2243 int py = q_ptr->py;
2244 int px = q_ptr->px;
2245
2246 /* Skip disconnected players */
2247 if (q_ptr->conn == NOT_CONNECTED) continue;
2248
2249 /* Skip oneself */
2250 if (i == Ind) continue;
2251
2252 /* Skip visible players */
2253 if (!inarea(&p_ptr->wpos, &q_ptr->wpos)) continue;
2254
2255 /* Skip the dungeon master */
2256 if (q_ptr->admin_dm && !player_sees_dm(Ind)) continue;
2257
2258 /* Detect all invisible players but not the dungeon master */
2259 if (panel_contains(py, px) && q_ptr->ghost) {
2260 byte a;
2261 char c;
2262
2263 /* Hack - Temporarily visible */
2264 p_ptr->play_vis[i] = TRUE;
2265
2266 /* Get the look of the player */
2267 map_info(Ind, py, px, &a, &c);
2268
2269 /* No longer visible */
2270 p_ptr->mon_vis[i] = FALSE;
2271
2272 /* Draw the player on the screen */
2273 draw_spot_ovl(Ind, py, px, a, c);
2274
2275 flag = TRUE;
2276 }
2277 }
2278
2279 /* Describe result, and clean up */
2280 if (flag) {
2281 /* Describe, and wait for acknowledgement */
2282 msg_print(Ind, "You sense the presence of invisible creatures!");
2283 msg_print(Ind, NULL);
2284
2285 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2286 /* Wait */
2287 Send_pause(Ind);
2288
2289 /* Mega-Hack -- Fix the monsters and players */
2290 update_monsters(FALSE);
2291 update_players();
2292 #endif
2293 } else {
2294 #ifdef DETECT_ABSENCE
2295 msg_print(Ind, "You sense the absence of invisible creatures.");
2296 msg_print(Ind, NULL);
2297 #endif
2298 }
2299
2300 /* Result */
2301 return (flag);
2302 }
2303
2304
2305
2306 /*
2307 * Display evil creatures on current panel -RAK-
2308 */
2309 #if 0
2310 bool detect_evil(int Ind) {
2311 player_type *p_ptr = Players[Ind];
2312
2313 int i;
2314 bool flag = FALSE;
2315
2316 dun_level *l_ptr = getfloor(&p_ptr->wpos);
2317
2318 /* anti-exploit */
2319 if (!local_panel(Ind)) return FALSE;
2320
2321 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2322 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2323
2324 /* Clear previously detected stuff */
2325 clear_ovl(Ind);
2326
2327 /* Display all the evil monsters */
2328 for (i = 1; i < m_max; i++) {
2329 monster_type *m_ptr = &m_list[i];
2330 monster_race *r_ptr = race_inf(m_ptr);
2331
2332 int fy = m_ptr->fy;
2333 int fx = m_ptr->fx;
2334
2335 /* Paranoia -- Skip dead monsters */
2336 if (!m_ptr->r_idx) continue;
2337
2338 /* Skip visible monsters */
2339 if (p_ptr->mon_vis[i]) continue;
2340
2341 /* Skip monsters not on this depth */
2342 if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2343
2344 /* Detect evil monsters */
2345 if (panel_contains(fy, fx) && (r_ptr->flags3 & RF3_EVIL)) {
2346 byte a;
2347 char c;
2348
2349 /* Hack - Temporarily visible */
2350 p_ptr->mon_vis[i] = TRUE;
2351
2352 /* Get the look of the monster */
2353 map_info(Ind, fy, fx, &a, &c);
2354
2355 /* No longer visible */
2356 p_ptr->mon_vis[i] = FALSE;
2357
2358 /* Draw the monster on the screen */
2359 draw_spot_ovl(Ind, fy, fx, a, c);
2360
2361 flag = TRUE;
2362 }
2363 }
2364
2365 /* Note effects and clean up */
2366 if (flag) {
2367 /* Describe, and wait for acknowledgement */
2368 msg_print(Ind, "You sense the presence of evil!");
2369 msg_print(Ind, NULL);
2370
2371 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2372 /* Wait */
2373 Send_pause(Ind);
2374
2375 /* Mega-Hack -- Fix the monsters */
2376 update_monsters(FALSE);
2377 #endif
2378 }
2379 else {
2380 #ifdef DETECT_ABSENCE
2381 msg_print(Ind, "You sense the absence of evil.");
2382 msg_print(Ind, NULL);
2383 #endif
2384 }
2385
2386 /* Result */
2387 return (flag);
2388 }
2389 #else
detect_evil(int Ind)2390 bool detect_evil(int Ind) {
2391 return(detect_monsters_xxx(Ind, RF3_EVIL));
2392 }
2393 #endif // 0
2394
2395
2396
2397 /*
2398 * Display all non-invisible monsters/players on the current panel
2399 */
detect_creatures(int Ind)2400 bool detect_creatures(int Ind) {
2401 player_type *p_ptr = Players[Ind];
2402
2403 int i;
2404 bool flag = FALSE;
2405
2406 dun_level *l_ptr = getfloor(&p_ptr->wpos);
2407
2408 /* anti-exploit */
2409 if (!local_panel(Ind)) return FALSE;
2410
2411 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2412 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2413
2414 /* Clear previously detected stuff */
2415 clear_ovl(Ind);
2416
2417 /* Detect non-invisible monsters */
2418 for (i = 1; i < m_max; i++) {
2419 monster_type *m_ptr = &m_list[i];
2420 monster_race *r_ptr = race_inf(m_ptr);
2421
2422 int fy = m_ptr->fy;
2423 int fx = m_ptr->fx;
2424
2425 /* Paranoia -- Skip dead monsters */
2426 if (!m_ptr->r_idx) continue;
2427
2428 /* Skip visible monsters */
2429 if (p_ptr->mon_vis[i]) continue;
2430
2431 /* Skip monsters not on this depth */
2432 if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2433
2434 /* Detect all non-invisible monsters */
2435 if (panel_contains(fy, fx) && (!(r_ptr->flags2 & RF2_INVISIBLE))) {
2436 byte a;
2437 char c;
2438
2439 /* Hack - Temporarily visible */
2440 p_ptr->mon_vis[i] = TRUE;
2441
2442 /* Get the look of the monster */
2443 map_info(Ind, fy, fx, &a, &c);
2444
2445 /* No longer visible */
2446 p_ptr->mon_vis[i] = FALSE;
2447
2448 /* Draw the monster on the screen */
2449 draw_spot_ovl(Ind, fy, fx, a, c);
2450
2451 flag = TRUE;
2452 }
2453 }
2454
2455 /* Detect non-invisible players */
2456 for (i = 1; i <= NumPlayers; i++) {
2457 player_type *q_ptr = Players[i];
2458
2459 int py = q_ptr->py;
2460 int px = q_ptr->px;
2461
2462 /* Skip disconnected players */
2463 if (q_ptr->conn == NOT_CONNECTED) continue;
2464
2465 /* Never detect the dungeon master! */
2466 if (q_ptr->admin_dm && !player_sees_dm(Ind)) continue;
2467
2468 /* Skip visible players */
2469 if (p_ptr->play_vis[i]) continue;
2470
2471 /* Skip players not on this depth */
2472 if (!inarea(&p_ptr->wpos, &q_ptr->wpos)) continue;
2473
2474 /* Skip ourself */
2475 if (i == Ind) continue;
2476
2477 /* Detect all non-invisible players */
2478 if (panel_contains(py, px) && !q_ptr->ghost) {
2479 byte a;
2480 char c;
2481
2482 /* Hack - Temporarily visible */
2483 p_ptr->play_vis[i] = TRUE;
2484
2485 /* Get the look of the player */
2486 map_info(Ind, py, px, &a, &c);
2487
2488 /* No longer visible */
2489 p_ptr->play_vis[i] = FALSE;
2490
2491 /* Draw the player on the screen */
2492 draw_spot_ovl(Ind, py, px, a, c);
2493
2494 flag = TRUE;
2495 }
2496 }
2497
2498 /* Describe and clean up */
2499 if (flag) {
2500 /* Describe, and wait for acknowledgement */
2501 msg_print(Ind, "You sense the presence of creatures!");
2502 msg_print(Ind, NULL);
2503
2504 #if 0 /* this is #if 0'd to produce old behaviour w/o the pause - mikaelh */
2505 /* Wait */
2506 Send_pause(Ind);
2507
2508 /* Mega-Hack -- Fix the monsters and players */
2509 update_monsters(FALSE);
2510 update_players();
2511 #endif
2512 } else {
2513 #ifdef DETECT_ABSENCE
2514 msg_print(Ind, "You sense the absence of creatures.");
2515 msg_print(Ind, NULL);
2516 #endif
2517 }
2518
2519 /* Result */
2520 return (flag);
2521 }
2522
2523 /*
2524 * Display all monsters on the current panel
2525 */
detect_monsters_forced(int Ind)2526 void detect_monsters_forced(int Ind) {
2527 player_type *p_ptr = Players[Ind];
2528 int i;
2529
2530 dun_level *l_ptr = getfloor(&p_ptr->wpos);
2531
2532 /* anti-exploit */
2533 if (!local_panel(Ind)) return;
2534
2535 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return;
2536 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return;
2537
2538 /* Clear previously detected stuff */
2539 clear_ovl(Ind);
2540
2541 for (i = 1; i < m_max; i++) {
2542 monster_type *m_ptr = &m_list[i];
2543 // monster_race *r_ptr = race_inf(m_ptr);
2544
2545 int fy = m_ptr->fy;
2546 int fx = m_ptr->fx;
2547
2548 byte a;
2549 char c;
2550
2551 /* Paranoia -- Skip dead monsters */
2552 if (!m_ptr->r_idx) continue;
2553
2554 /* Skip visible monsters */
2555 if (p_ptr->mon_vis[i]) continue;
2556
2557 /* Skip monsters not on this depth */
2558 if (!inarea(&m_ptr->wpos, &p_ptr->wpos)) continue;
2559
2560 /* Hack - Temporarily visible */
2561 p_ptr->mon_vis[i] = TRUE;
2562
2563 /* Get the look of the monster */
2564 map_info(Ind, fy, fx, &a, &c);
2565
2566 /* No longer visible */
2567 p_ptr->mon_vis[i] = FALSE;
2568
2569 /* Draw the monster on the screen */
2570 draw_spot_ovl(Ind, fy, fx, a, c);
2571 }
2572 }
2573
2574
2575 /*
2576 * Detect everything
2577 */
detection(int Ind,int rad)2578 bool detection(int Ind, int rad) {
2579 bool detect = FALSE;
2580
2581 /* Detect the easy things */
2582 if (detect_treasure(Ind, rad)) detect = TRUE;
2583 if (detect_object(Ind, rad)) detect = TRUE;
2584 if (detect_trap(Ind, rad)) detect = TRUE;
2585 if (detect_sdoor(Ind, rad)) detect = TRUE;
2586 if (detect_creatures(Ind)) detect = TRUE; /* not radius-ed for now */
2587
2588 /* Result */
2589 return (detect);
2590 }
2591
2592 #if 1
2593 /*
2594 * Detect bounty, a rogue's skill
2595 */
detect_bounty(int Ind,int rad)2596 bool detect_bounty(int Ind, int rad) {
2597 player_type *p_ptr = Players[Ind];
2598
2599 // 10 ... 60 % of auto-detecting "stuff"
2600 int chance = (p_ptr->lev) + 10;
2601
2602 struct worldpos *wpos = &p_ptr->wpos;
2603 dun_level *l_ptr;
2604
2605 int i, j, t_idx = 0;
2606
2607 bool detect = FALSE;
2608 bool detect_trap = FALSE;
2609
2610 cave_type *c_ptr;
2611 byte *w_ptr;
2612 cave_type **zcave;
2613 struct c_special *cs_ptr;
2614
2615 object_type *o_ptr;
2616
2617 /* anti-exploit */
2618 if (!local_panel(Ind)) return FALSE;
2619
2620 if (!(zcave = getcave(wpos))) return(FALSE);
2621
2622 l_ptr = getfloor(wpos);
2623 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2624 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2625
2626
2627 /* Scan the current panel */
2628 for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2629 for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2630 /* Reject locations outside of dungeon */
2631 if (!in_bounds4(l_ptr, i, j)) continue;
2632
2633 /* Reject those out of radius */
2634 if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2635
2636 /* Access the grid */
2637 c_ptr = &zcave[i][j];
2638 w_ptr = &p_ptr->cave_flag[i][j];
2639
2640 o_ptr = &o_list[c_ptr->o_idx];
2641
2642 detect_trap = FALSE;
2643
2644 /* Detect traps on chests */
2645 if ((c_ptr->o_idx) && (o_ptr->tval == TV_CHEST)
2646 && p_ptr->obj_vis[c_ptr->o_idx] && (o_ptr->pval)
2647 && !object_known_p(Ind, o_ptr) && magik(chance)) {
2648 /* Message =-p */
2649 msg_print(Ind, "You have discovered a trap on the chest!");
2650 /* Know the trap */
2651 object_known(o_ptr);
2652 /* Notice it */
2653 // disturb(Ind, 0, 0);
2654 detect = TRUE;
2655 }
2656
2657 /* Detect invisible traps */
2658 if ((cs_ptr = GetCS(c_ptr, CS_TRAPS)) && magik(chance)) {
2659 t_idx = cs_ptr->sc.trap.t_idx;
2660
2661 if (!cs_ptr->sc.trap.found) {
2662 /* Pick a trap */
2663 pick_trap(wpos, i, j);
2664 }
2665
2666 /* Hack -- memorize it */
2667 *w_ptr |= CAVE_MARK;
2668
2669 /* Obvious */
2670 detect = TRUE;
2671 detect_trap = TRUE;
2672 }
2673
2674 /* Detect secret doors */
2675 if (c_ptr->feat == FEAT_SECRET && magik(chance)) {
2676 struct c_special *cs_ptr;
2677
2678 /* Clear mimic feature */
2679 if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
2680 cs_erase(c_ptr, cs_ptr);
2681
2682 /* Find the door XXX XXX XXX */
2683 c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
2684
2685 /* Memorize the door */
2686 *w_ptr |= CAVE_MARK;
2687
2688 /* Obvious */
2689 detect = TRUE;
2690 }
2691
2692 // You feel a gust of air from nearby ...
2693 if (((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_MORE) ||
2694 (c_ptr->feat == FEAT_WAY_LESS) || (c_ptr->feat == FEAT_WAY_MORE))
2695 && magik(chance)) {
2696
2697 /* Memorize the stairs */
2698 *w_ptr |= CAVE_MARK;
2699
2700 /* Obvious */
2701 detect = TRUE;
2702 }
2703
2704 // You hear a jingle of coins nearby ...
2705 if (c_ptr->feat == FEAT_SHOP && magik(chance)) {
2706 /* Memorize the stairs */
2707 *w_ptr |= CAVE_MARK;
2708
2709 /* Obvious */
2710 detect = TRUE;
2711 }
2712 if (detect) lite_spot(Ind, i, j);
2713 if (detect_trap) {
2714 if (c_ptr->o_idx && !c_ptr->m_idx) {
2715 byte a = get_trap_color(Ind, t_idx, c_ptr->feat);
2716
2717 /* Hack - Always show traps under items when detecting - mikaelh */
2718 draw_spot_ovl(Ind, i, j, a, '^');
2719 } else {
2720 /* Normal redraw */
2721 lite_spot(Ind, i, j);
2722 }
2723 }
2724 }
2725 }
2726 return (detect);
2727 }
2728 #endif
2729
2730 /*
2731 * Detect all objects on the current panel -RAK-
2732 */
detect_object(int Ind,int rad)2733 bool detect_object(int Ind, int rad) {
2734 player_type *p_ptr = Players[Ind];
2735
2736 struct worldpos *wpos = &p_ptr->wpos;
2737 dun_level *l_ptr;
2738 //int py = p_ptr->py, px = p_ptr->px;
2739
2740 int i, j;
2741 bool detect = FALSE;
2742
2743 cave_type *c_ptr;
2744 object_type *o_ptr;
2745 cave_type **zcave;
2746
2747
2748 /* anti-exploit */
2749 if (!local_panel(Ind)) return FALSE;
2750
2751 if (!(zcave = getcave(wpos))) return(FALSE);
2752 l_ptr = getfloor(wpos);
2753
2754 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2755 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2756
2757 /* Scan the current panel */
2758 // for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2759 for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2760 // for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2761 for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2762 /* Reject locations outside of dungeon */
2763 if (!in_bounds4(l_ptr, i, j)) continue;
2764
2765 /* Reject those out of radius */
2766 if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2767
2768 c_ptr = &zcave[i][j];
2769
2770 o_ptr = &o_list[c_ptr->o_idx];
2771
2772 /* Nothing here */
2773 if (!(c_ptr->o_idx)) continue;
2774
2775 /* Do not detect "gold" */
2776 if (o_ptr->tval == TV_GOLD) continue;
2777
2778 /* Note new objects */
2779 if (!(p_ptr->obj_vis[c_ptr->o_idx])) {
2780 /* Detect */
2781 detect = TRUE;
2782
2783 /* Hack -- memorize it */
2784 p_ptr->obj_vis[c_ptr->o_idx] = TRUE;
2785
2786 /* Redraw */
2787 lite_spot(Ind, i, j);
2788 }
2789 }
2790 }
2791
2792 return (detect);
2793 }
2794
2795
2796 /*
2797 * Locates and displays traps on current panel
2798 */
2799 //bool detect_trap(int Ind)
detect_trap(int Ind,int rad)2800 bool detect_trap(int Ind, int rad) {
2801 player_type *p_ptr = Players[Ind];
2802
2803 struct worldpos *wpos = &p_ptr->wpos;
2804 dun_level *l_ptr;
2805 // int py = p_ptr->py, px = p_ptr->px;
2806
2807 int i, j, t_idx;
2808 bool detect = FALSE;
2809
2810 cave_type *c_ptr;
2811 byte *w_ptr;
2812 cave_type **zcave;
2813 struct c_special *cs_ptr;
2814
2815 object_type *o_ptr;
2816
2817
2818 /* anti-exploit */
2819 if (!local_panel(Ind)) return FALSE;
2820
2821 if (!(zcave = getcave(wpos))) return(FALSE);
2822 l_ptr = getfloor(wpos);
2823
2824 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2825 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2826
2827 /* Clear previously detected stuff */
2828 clear_ovl(Ind);
2829
2830 /* Scan the current panel */
2831 // for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2832 for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2833 // for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2834 for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2835 /* Reject locations outside of dungeon */
2836 if (!in_bounds4(l_ptr, i, j)) continue;
2837
2838 /* Reject those out of radius */
2839 if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2840
2841 /* Access the grid */
2842 c_ptr = &zcave[i][j];
2843 w_ptr = &p_ptr->cave_flag[i][j];
2844
2845 /* Hack - traps on undetected doors cannot be found */
2846 /* if (c_ptr->feat == FEAT_DOOR_TAIL + 1) continue; --hmm why not */
2847
2848 /* Detect traps on chests */
2849 o_ptr = &o_list[c_ptr->o_idx];
2850 if ((c_ptr->o_idx) && (o_ptr->tval == TV_CHEST) && (o_ptr->pval) && (!object_known_p(Ind, o_ptr))) {
2851 object_known(o_ptr);
2852
2853 /* New trap detected */
2854 detect = TRUE;
2855 }
2856
2857 /* Detect invisible traps */
2858 // if (c_ptr->feat == FEAT_INVIS)
2859 if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
2860 t_idx = cs_ptr->sc.trap.t_idx;
2861
2862 if (!cs_ptr->sc.trap.found) {
2863 /* Pick a trap */
2864 pick_trap(wpos, i, j);
2865
2866 /* New trap detected */
2867 detect = TRUE;
2868 }
2869
2870 /* Hack -- memorize it */
2871 *w_ptr |= CAVE_MARK;
2872
2873 /* Redraw */
2874 lite_spot(Ind, i, j);
2875
2876 if (c_ptr->o_idx && !c_ptr->m_idx) {
2877 byte a = get_trap_color(Ind, t_idx, c_ptr->feat);
2878
2879 /* Hack - Always show traps under items when detecting - mikaelh */
2880 draw_spot_ovl(Ind, i, j, a, '^');
2881 } else {
2882 /* Normal redraw */
2883 lite_spot(Ind, i, j);
2884 }
2885
2886 #if 0
2887 /* Already seen traps */
2888 else if (c_ptr->feat >= FEAT_TRAP_HEAD && c_ptr->feat <= FEAT_TRAP_TAIL) {
2889 /* Memorize it */
2890 *w_ptr |= CAVE_MARK;
2891
2892 /* Redraw */
2893 lite_spot(Ind, i, j);
2894
2895 /* Obvious */
2896 detect = TRUE;
2897 }
2898 #endif // 0
2899 }
2900 }
2901 }
2902
2903 if (detect) {
2904 msg_print(Ind, "You have detected new traps.");
2905 } else {
2906 #ifdef DETECT_ABSENCE
2907 msg_print(Ind, "You have detected no new traps.");
2908 #endif
2909 }
2910
2911 return (detect);
2912 }
2913
2914
2915
2916 /*
2917 * Locates and displays all stairs and secret doors on current panel -RAK-
2918 */
detect_sdoor(int Ind,int rad)2919 bool detect_sdoor(int Ind, int rad) {
2920 player_type *p_ptr = Players[Ind];
2921
2922 struct worldpos *wpos = &p_ptr->wpos;
2923 dun_level *l_ptr;
2924 //int py = p_ptr->py, px = p_ptr->px;
2925
2926 int i, j;
2927 bool detect = FALSE;
2928
2929 cave_type *c_ptr;
2930 byte *w_ptr;
2931 cave_type **zcave;
2932
2933 /* anti-exploit */
2934 if (!local_panel(Ind)) return FALSE;
2935
2936 if (!(zcave = getcave(wpos))) return(FALSE);
2937 l_ptr = getfloor(wpos);
2938
2939 if (l_ptr && (l_ptr->flags2 & LF2_NO_DETECT)) return FALSE;
2940 if (in_sector00(&p_ptr->wpos) && (sector00flags2 & LF2_NO_DETECT)) return FALSE;
2941
2942 /* Scan the panel */
2943 // for (i = p_ptr->panel_row_min; i <= p_ptr->panel_row_max; i++)
2944 for (i = p_ptr->py - rad; i <= p_ptr->py + rad; i++) {
2945 // for (j = p_ptr->panel_col_min; j <= p_ptr->panel_col_max; j++)
2946 for (j = p_ptr->px - rad; j <= p_ptr->px + rad; j++) {
2947 /* Reject locations outside of dungeon */
2948 if (!in_bounds4(l_ptr, i, j)) continue;
2949
2950 /* Reject those out of radius */
2951 if (distance(p_ptr->py, p_ptr->px, i, j) > rad) continue;
2952
2953 /* Access the grid and object */
2954 c_ptr = &zcave[i][j];
2955 w_ptr = &p_ptr->cave_flag[i][j];
2956
2957 /* Hack -- detect secret doors */
2958 if (c_ptr->feat == FEAT_SECRET) {
2959 struct c_special *cs_ptr;
2960
2961 /* Clear mimic feature */
2962 if ((cs_ptr = GetCS(c_ptr, CS_MIMIC)))
2963 cs_erase(c_ptr, cs_ptr);
2964
2965 /* Find the door XXX XXX XXX */
2966 c_ptr->feat = FEAT_DOOR_HEAD + 0x00;
2967
2968 /* Memorize the door */
2969 *w_ptr |= CAVE_MARK;
2970
2971 /* Redraw */
2972 lite_spot(Ind, i, j);
2973
2974 /* Obvious */
2975 detect = TRUE;
2976 }
2977
2978 /* Ignore known grids */
2979 if (*w_ptr & CAVE_MARK) continue;
2980
2981 /* Hack -- detect stairs */
2982 if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_MORE) ||
2983 (c_ptr->feat == FEAT_WAY_LESS) || (c_ptr->feat == FEAT_WAY_MORE))
2984 {
2985 /* Memorize the stairs */
2986 *w_ptr |= CAVE_MARK;
2987
2988 /* Redraw */
2989 lite_spot(Ind, i, j);
2990
2991 /* Obvious */
2992 detect = TRUE;
2993 }
2994
2995 /* Hack -- detect dungeon shops */
2996 if (c_ptr->feat == FEAT_SHOP) {
2997 /* Memorize the stairs */
2998 *w_ptr |= CAVE_MARK;
2999
3000 /* Redraw */
3001 lite_spot(Ind, i, j);
3002
3003 /* Obvious */
3004 detect = TRUE;
3005 }
3006 }
3007 }
3008
3009 return (detect);
3010 }
3011
3012
3013 /*
3014 * Create stairs at the player location
3015 */
stair_creation(int Ind)3016 void stair_creation(int Ind) {
3017 player_type *p_ptr = Players[Ind];
3018
3019 /* Access the grid */
3020 cave_type *c_ptr;
3021
3022 struct worldpos *wpos = &p_ptr->wpos;
3023 cave_type **zcave;
3024 if (!(zcave = getcave(wpos))) return;
3025
3026 /* Access the player grid */
3027 c_ptr = &zcave[p_ptr->py][p_ptr->px];
3028
3029 /* XXX XXX XXX */
3030 if (!cave_valid_bold(zcave, p_ptr->py, p_ptr->px)) {
3031 msg_print(Ind, "The object resists the spell.");
3032 return;
3033 }
3034
3035 /* Hack -- Delete old contents */
3036 delete_object(wpos, p_ptr->py, p_ptr->px, TRUE);
3037
3038 /* Create a staircase */
3039 if (!can_go_down(wpos, 0x1) && !can_go_up(wpos, 0x1)) {
3040 /* special..? */
3041 } else if (can_go_down(wpos, 0x1) && !can_go_up(wpos, 0x1)) {
3042 c_ptr->feat = FEAT_MORE;
3043 } else if(can_go_up(wpos, 0x1) && !can_go_down(wpos, 0x1)) {
3044 c_ptr->feat = FEAT_LESS;
3045 } else if (rand_int(100) < 50) {
3046 c_ptr->feat = FEAT_MORE;
3047 } else {
3048 c_ptr->feat = FEAT_LESS;
3049 }
3050
3051 /* Notice */
3052 note_spot(Ind, p_ptr->py, p_ptr->px);
3053
3054 /* Redraw */
3055 everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
3056 }
3057
3058
3059
3060
3061 /*
3062 * Hook to specify "weapon"
3063 */
item_tester_hook_weapon(object_type * o_ptr)3064 static bool item_tester_hook_weapon(object_type *o_ptr) {
3065 switch (o_ptr->tval) {
3066 /* and now new.. :) */
3067 case TV_TRAPKIT:
3068 if (!is_firearm_trapkit(o_ptr->sval)) return FALSE;
3069 case TV_SWORD:
3070 case TV_BLUNT:
3071 case TV_POLEARM:
3072 case TV_DIGGING:
3073 case TV_BOW:
3074 case TV_BOLT:
3075 case TV_ARROW:
3076 case TV_SHOT:
3077 case TV_MSTAFF:
3078 case TV_BOOMERANG:
3079 case TV_AXE:
3080 return (TRUE);
3081 }
3082
3083 return (FALSE);
3084 }
3085
3086
3087 /*
3088 * Hook to specify "armour"
3089 */
item_tester_hook_armour(object_type * o_ptr)3090 static bool item_tester_hook_armour(object_type *o_ptr) {
3091 switch (o_ptr->tval) {
3092 case TV_DRAG_ARMOR:
3093 case TV_HARD_ARMOR:
3094 case TV_SOFT_ARMOR:
3095 case TV_SHIELD:
3096 case TV_CLOAK:
3097 case TV_CROWN:
3098 case TV_HELM:
3099 case TV_BOOTS:
3100 case TV_GLOVES:
3101 /* and now new.. :) */
3102 //nope, not enchantable -- case TV_TRAPKIT:
3103 return (TRUE);
3104 }
3105
3106 return (FALSE);
3107 }
3108
3109
3110
3111 /*
3112 * Enchants a plus onto an item. -RAK-
3113 *
3114 * Revamped! Now takes item pointer, number of times to try enchanting,
3115 * and a flag of what to try enchanting. Artifacts resist enchantment
3116 * some of the time, and successful enchantment to at least +0 might
3117 * break a curse on the item. -CFT
3118 *
3119 * Note that an item can technically be enchanted all the way to +15 if
3120 * you wait a very, very, long time. Going from +9 to +10 only works
3121 * about 5% of the time, and from +10 to +11 only about 1% of the time.
3122 *
3123 * Note that this function can now be used on "piles" of items, and
3124 * the larger the pile, the lower the chance of success.
3125 */
enchant(int Ind,object_type * o_ptr,int n,int eflag)3126 bool enchant(int Ind, object_type *o_ptr, int n, int eflag) {
3127 player_type *p_ptr = Players[Ind];
3128 int i, chance, prob;
3129 bool res = FALSE;
3130 bool a = like_artifact_p(o_ptr);
3131 u32b f1, f2, f3, f4, f5, f6, esp;
3132 bool did_tohit = FALSE, did_todam = FALSE, did_toac = FALSE;
3133
3134 /* Extract the flags */
3135 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
3136
3137 /* Unenchantable items always fail */
3138 if (!is_enchantable(o_ptr)) return FALSE;
3139 if (f5 & TR5_NO_ENCHANT) return (FALSE);
3140 /* Artifacts cannot be enchanted. */
3141 if (a) return (FALSE);
3142
3143 /* Large piles resist enchantment */
3144 prob = o_ptr->number * 100;
3145
3146 /* Missiles are easy to enchant */
3147 if (is_ammo(o_ptr->tval)) {
3148 prob = prob / 20;
3149 }
3150
3151 /* Try "n" times */
3152 for (i = 0; i < n; i++) {
3153 /* Hack -- Roll for pile resistance */
3154 if (rand_int(prob) >= 100) continue;
3155
3156 /* Enchant to hit, but not that easily multiple times over 9 */
3157 if ((eflag & ENCH_TOHIT) && (magik(30) || !(did_tohit && o_ptr->to_h > 9)))
3158 {
3159 if (o_ptr->to_h < 0) chance = 0;
3160 else if (o_ptr->to_h > 14) chance = 1000;
3161 else {
3162 chance = enchant_table[o_ptr->to_h];
3163 /* *Enchant Weapon* scrolls are better! */
3164 if (n > 1) chance = ((chance * 1) / 3);
3165 }
3166
3167 if ((randint(1000) > chance) && (!a || (rand_int(100) < 50)))
3168 {
3169 o_ptr->to_h++;
3170 res = TRUE;
3171 did_tohit = TRUE;
3172
3173 /* only when you get it above -1 -CFT */
3174 if (cursed_p(o_ptr) &&
3175 (!(f3 & TR3_PERMA_CURSE)) &&
3176 // (o_ptr->to_h >= 0) && (rand_int(100) < 25))
3177 (rand_int(100) < 10 + 10 * o_ptr->to_h))
3178 {
3179 msg_print(Ind, "The curse is broken!");
3180 o_ptr->ident &= ~ID_CURSED;
3181 o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
3182 note_toggle_cursed(o_ptr, FALSE);
3183 }
3184 }
3185 }
3186
3187 /* Enchant to damage, but not that easily multiple times over 9 */
3188 if ((eflag & ENCH_TODAM) && (magik(30) || !(did_todam && o_ptr->to_d > 9))) {
3189 if (o_ptr->to_d < 0) chance = 0;
3190 else if (o_ptr->to_d > 14) chance = 1000;
3191 else {
3192 chance = enchant_table[o_ptr->to_d];
3193 /* *Enchant Weapon* scrolls are better! */
3194 if (n > 1) chance = ((chance * 1) / 3);
3195 }
3196
3197 if ((randint(1000) > chance) && (!a || (rand_int(100) < 50))) {
3198 o_ptr->to_d++;
3199 res = TRUE;
3200 did_todam = TRUE;
3201
3202 /* only when you get it above -1 -CFT */
3203 if (cursed_p(o_ptr) &&
3204 (!(f3 & TR3_PERMA_CURSE)) &&
3205 // (o_ptr->to_d >= 0) && (rand_int(100) < 25))
3206 (rand_int(100) < 10 + 10 * o_ptr->to_d))
3207 {
3208 msg_print(Ind, "The curse is broken!");
3209 o_ptr->ident &= ~ID_CURSED;
3210 o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
3211 note_toggle_cursed(o_ptr, FALSE);
3212 }
3213 }
3214 }
3215
3216 /* Enchant to armor class, but not that easily multiple times over 9 */
3217 if ((eflag & ENCH_TOAC) && (magik(30) || !(did_toac && o_ptr->to_a > 9))) {
3218 if (o_ptr->to_a < 0) chance = 0;
3219 else if (o_ptr->to_a > 14) chance = 1000;
3220 else {
3221 chance = enchant_table[o_ptr->to_a];
3222 /* *Enchant Armour* scrolls are better! */
3223 if (n > 1) chance = ((chance * 1) / 3);
3224 }
3225
3226 if ((randint(1000) > chance) && (!a || (rand_int(100) < 50))) {
3227 o_ptr->to_a++;
3228 res = TRUE;
3229 did_toac = TRUE;
3230
3231 /* only when you get it above -1 -CFT */
3232 if (cursed_p(o_ptr) &&
3233 (!(f3 & TR3_PERMA_CURSE)) &&
3234 (o_ptr->to_a >= 0) && (rand_int(100) < 25)) {
3235 msg_print(Ind, "The curse is broken!");
3236 o_ptr->ident &= ~ID_CURSED;
3237 o_ptr->ident |= ID_SENSE | ID_SENSED_ONCE;
3238 note_toggle_cursed(o_ptr, FALSE);
3239 }
3240 }
3241 }
3242 }
3243
3244 /* Failure */
3245 if (!res) return (FALSE);
3246
3247 /* Recalculate bonuses */
3248 p_ptr->update |= (PU_BONUS);
3249
3250 /* Combine / Reorder the pack (later) */
3251 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3252
3253 /* Window stuff */
3254 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3255
3256 /* Resend plusses */
3257 p_ptr->redraw |= (PR_PLUSSES);
3258
3259 /* Success */
3260 return (TRUE);
3261 }
3262
create_artifact(int Ind,bool nolife)3263 bool create_artifact(int Ind, bool nolife) {
3264 player_type *p_ptr = Players[Ind];
3265
3266 /* just in case */
3267 s_printf("(%s) Player %s initiates Artifact Creation (nolife=%d).\n", showtime(), p_ptr->name, nolife);
3268
3269 clear_current(Ind);
3270
3271 p_ptr->current_artifact = TRUE;
3272 p_ptr->current_artifact_nolife = nolife;
3273 get_item(Ind, ITH_NONE);
3274
3275 return TRUE;
3276 }
3277
create_artifact_aux(int Ind,int item)3278 bool create_artifact_aux(int Ind, int item) {
3279 player_type *p_ptr = Players[Ind];
3280 object_type *o_ptr;
3281 artifact_type *a_ptr;
3282 int tries = 0;
3283 char o_name[ONAME_LEN];
3284 s32b old_owner;/* anti-cheeze :) */
3285 u32b resf = make_resf(p_ptr);
3286
3287 /* Get the item (in the pack) */
3288 if (item >= 0) o_ptr = &p_ptr->inventory[item];
3289 /* Get the item (on the floor) */
3290 else o_ptr = &o_list[0 - item];
3291
3292 old_owner = o_ptr->owner;
3293
3294 /* Description */
3295 object_desc(Ind, o_name, o_ptr, FALSE, 0);
3296 s_printf("ART_CREATION by player %s: %s\n", p_ptr->name, o_name);
3297
3298 if (((o_ptr->tval == TV_SOFT_ARMOR && o_ptr->sval == SV_SHIRT) ||
3299 (o_ptr->tval == TV_SPECIAL)) /* <- must be checked here, not in randart_make() due to seals, see randart_make(). */
3300 && !is_admin(p_ptr)) {
3301 msg_print(Ind, "\376\377yThe item appears unchanged!");
3302 return FALSE;
3303 }
3304 if (o_ptr->name1) {
3305 msg_print(Ind, "\376\377yThe creation fails due to the powerful magic of the target object!");
3306 return FALSE;
3307 }
3308 if (o_ptr->name2 || o_ptr->name2b) {
3309 msg_print(Ind, "\376\377yThe creation fails due to the strong magic of the target object!");
3310 return FALSE;
3311 o_ptr->name2 = 0;
3312 o_ptr->name2b = 0;
3313 msg_print(Ind, "The strong magic of that object dissolves!");
3314 }
3315 if (o_ptr->number > 1) {
3316 /* msg_print(Ind, "The creation fails because the magic is split to multiple targets!");
3317 return FALSE;*/
3318 o_ptr->number = 1;
3319 msg_print(Ind, "The stack of objects magically dissolves, leaving only a single item!");
3320 }
3321
3322 /* Describe */
3323 msg_format(Ind, "%s %s glow%s *brightly*!",
3324 ((item >= 0) ? "Your" : "The"), o_name,
3325 ((o_ptr->number > 1) ? "" : "s"));
3326
3327 o_ptr->name1 = ART_RANDART;
3328
3329 /* NOTE: MAKE SURE THE FOLLOWING CODE IS CONSISTENT WITH make_artifact() IN object2.c! */
3330
3331 /* Randart loop. Try until an allowed randart was made */
3332 while (tries < 10) {
3333 tries++;
3334
3335 /* Piece together a 32-bit random seed */
3336 o_ptr->name3 = rand_int(0xFFFF) << 16;
3337 o_ptr->name3 += rand_int(0xFFFF);
3338
3339 /* Check the tval is allowed */
3340 if (randart_make(o_ptr) == NULL) {
3341 /* If not, wipe seed. No randart today */
3342 o_ptr->name1 = 0;
3343 o_ptr->name3 = 0L;
3344
3345 msg_print(Ind, "The item appears unchanged!");
3346 return FALSE;
3347 }
3348
3349 /* If the resulting randart is allowed, leave the loop */
3350 a_ptr = randart_make(o_ptr);
3351 if (((resf & RESF_LIFE) && !p_ptr->current_artifact_nolife) || !(a_ptr->flags1 & TR1_LIFE)) break;
3352 }
3353
3354 /* apply magic (which resets owner) and manually restore ownership again afterwards;
3355 apply_magic() is used to set level requirements, and copy the a_ptr to o_ptr. */
3356 apply_magic(&p_ptr->wpos, o_ptr, 50, FALSE, FALSE, FALSE, FALSE, RESF_NONE);
3357 o_ptr->owner = old_owner;
3358
3359 /* Hack - lose discount on item, looks bad/silly */
3360 o_ptr->discount = 0;
3361 o_ptr->note = 0;
3362
3363 /* Recalculate bonuses */
3364 p_ptr->update |= (PU_BONUS);
3365
3366 /* Combine / Reorder the pack (later) */
3367 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3368
3369 /* Window stuff */
3370 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3371
3372 /* Art creation finished */
3373 p_ptr->current_artifact = FALSE;
3374 p_ptr->current_artifact_nolife = FALSE;
3375
3376 /* Log it (security) */
3377 /* Description */
3378 object_desc(Ind, o_name, o_ptr, FALSE, 3);
3379 s_printf("ART_CREATION succeeded: %s\n", o_name);
3380
3381 /* Did we use up an item? (minus 1 art scroll) */
3382 if (p_ptr->using_up_item >= 0) {
3383 inven_item_describe(Ind, p_ptr->using_up_item);
3384 inven_item_optimize(Ind, p_ptr->using_up_item);
3385 p_ptr->using_up_item = -1;
3386 }
3387
3388 return TRUE;
3389 }
3390
curse_spell(int Ind)3391 bool curse_spell(int Ind) { // could be void
3392 player_type *p_ptr = Players[Ind];
3393 clear_current(Ind);
3394 get_item(Ind, ITH_NONE);
3395 p_ptr->current_curse = TRUE; /* This is awful. I intend to change it */
3396 return TRUE;
3397 }
3398
curse_spell_aux(int Ind,int item)3399 bool curse_spell_aux(int Ind, int item)
3400 {
3401 player_type *p_ptr = Players[Ind];
3402 object_type *o_ptr = &p_ptr->inventory[item];
3403 char o_name[ONAME_LEN];
3404
3405 p_ptr->current_curse = FALSE;
3406 object_desc(Ind, o_name, o_ptr, FALSE, 0);
3407
3408
3409 if (artifact_p(o_ptr) && (randint(10) < 8)) {
3410 msg_print(Ind,"The artifact resists your attempts.");
3411 return(FALSE);
3412 }
3413
3414 if (item_tester_hook_weapon(o_ptr)) {
3415 o_ptr->to_h = 0 - (randint(10) + 1);
3416 o_ptr->to_d = 0 - (randint(10) + 1);
3417 } else if (item_tester_hook_armour(o_ptr)) {
3418 o_ptr->to_a = 0 - (randint(10) + 1);
3419 } else {
3420 switch (o_ptr->tval) {
3421 case TV_RING:
3422 default:
3423 msg_print(Ind,"You cannot curse that item!");
3424 return(FALSE);
3425 }
3426 }
3427
3428 msg_format(Ind,"\376\377yA terrible black aura surrounds your %s",
3429 o_name, o_ptr->number > 1 ? "" : "s");
3430 /* except it doesnt actually get cursed properly yet. */
3431 o_ptr->name1 = 0;
3432 o_ptr->name3 = 0;
3433 o_ptr->ident |= ID_CURSED;
3434 o_ptr->ident &= ~(ID_KNOWN | ID_SENSE); /* without this, the spell is pointless */
3435
3436 if (o_ptr->name2) o_ptr->pval = 0 - (randint(10) + 1); /* nasty */
3437
3438 /* Did we use up an item? */
3439 if (p_ptr->using_up_item >= 0) {
3440 inven_item_describe(Ind, p_ptr->using_up_item);
3441 inven_item_optimize(Ind, p_ptr->using_up_item);
3442 p_ptr->using_up_item = -1;
3443 }
3444
3445 /* Recalculate the bonuses - if stupid enough to curse worn item ;) */
3446 p_ptr->update |= (PU_BONUS);
3447
3448 /* Window stuff */
3449 p_ptr->window |= (PW_INVEN | PW_EQUIP);
3450
3451 return(TRUE);
3452 }
3453
enchant_spell(int Ind,int num_hit,int num_dam,int num_ac,int flags)3454 bool enchant_spell(int Ind, int num_hit, int num_dam, int num_ac, int flags) {
3455 player_type *p_ptr = Players[Ind];
3456
3457 #ifndef NEW_SHIELDS_NO_AC
3458 get_item(Ind, num_ac ? ITH_ENCH_AC : ITH_ENCH_WEAP);
3459 #else
3460 get_item(Ind, num_ac ? ITH_ENCH_AC_NO_SHIELD : ITH_ENCH_WEAP);
3461 #endif
3462
3463 /* Clear any other pending actions - mikaelh */
3464 clear_current(Ind);
3465
3466 p_ptr->current_enchant_h = num_hit;
3467 p_ptr->current_enchant_d = num_dam;
3468 p_ptr->current_enchant_a = num_ac;
3469 p_ptr->current_enchant_flag = flags;
3470
3471 return (TRUE);
3472 }
3473
3474 /*
3475 * Enchant an item (in the inventory or on the floor)
3476 * Note that "num_ac" requires armour, else weapon
3477 * Returns TRUE if attempted, FALSE if cancelled
3478 */
3479 /*
3480 * //deprecated//For now, 'flags' is the chance of the item getting 'discounted'
3481 * in the process.
3482 */
enchant_spell_aux(int Ind,int item,int num_hit,int num_dam,int num_ac,int flags)3483 bool enchant_spell_aux(int Ind, int item, int num_hit, int num_dam, int num_ac, int flags) {
3484 player_type *p_ptr = Players[Ind];
3485 bool okay = FALSE;
3486 object_type *o_ptr;
3487 char o_name[ONAME_LEN];
3488
3489 /* Assume enchant weapon */
3490 item_tester_hook = item_tester_hook_weapon;
3491
3492 /* Enchant armor if requested */
3493 if (num_ac) item_tester_hook = item_tester_hook_armour;
3494
3495 /* Get the item (in the pack) */
3496 if (item >= 0) o_ptr = &p_ptr->inventory[item];
3497 /* Get the item (on the floor) */
3498 else o_ptr = &o_list[0 - item];
3499
3500
3501 if (!item_tester_hook(o_ptr) || !is_enchantable(o_ptr)) {
3502 msg_print(Ind, "Sorry, you cannot enchant that item.");
3503 #ifndef NEW_SHIELDS_NO_AC
3504 get_item(Ind, num_ac ? ITH_ENCH_AC : ITH_ENCH_WEAP);
3505 #else
3506 get_item(Ind, num_ac ? ITH_ENCH_AC_NO_SHIELD : ITH_ENCH_WEAP);
3507 #endif
3508 return (FALSE);
3509 }
3510
3511 /* Description */
3512 object_desc(Ind, o_name, o_ptr, FALSE, 0);
3513
3514 /* Describe */
3515 msg_format(Ind, "%s %s glow%s brightly!",
3516 ((item >= 0) ? "Your" : "The"), o_name,
3517 ((o_ptr->number > 1) ? "" : "s"));
3518
3519 /* Enchant */
3520 if (enchant(Ind, o_ptr, num_hit, ENCH_TOHIT)) okay = TRUE;
3521 if (enchant(Ind, o_ptr, num_dam, ENCH_TODAM)) okay = TRUE;
3522 if (enchant(Ind, o_ptr, num_ac, ENCH_TOAC)) okay = TRUE;
3523
3524 /* Artifacts cannot be enchanted. */
3525 //if (artifact_p(o_ptr)) msg_format(Ind,"Your %s %s unaffected.",o_name,((o_ptr->number != 1) ? "are" : "is"));
3526
3527 /* Failure */
3528 if (!okay) {
3529 /* Message */
3530 msg_print(Ind, "The enchantment failed.");
3531 }
3532
3533 #if 0
3534 /* Anti-cheeze */
3535 if (okay && !artifact_p(o_ptr) && !ego_item_p(o_ptr) && magik(flags)) {
3536 int discount = (100 - o_ptr->discount) / 2;
3537 if (discount > 0) {
3538 o_ptr->discount += discount;
3539
3540 /* Message */
3541 msg_format(Ind, "It spoiled the appearence of %s %s somewhat!",
3542 ((item >= 0) ? "your" : "the"), o_name);
3543 }
3544 }
3545 #else
3546 /* Anti-cheeze: Prevent stealers from making infinite money in IDDC towns.
3547 It doesn't matter that much in other places, since there are usually
3548 better/equal ways to make money.
3549 For items probably >= 12k it doesn't matter anymore though. */
3550 if (okay && (flags & ENCH_STOLEN) &&
3551 object_value_real(0, o_ptr) < 15000 && o_ptr->discount != 100 &&
3552 isdungeontown(&p_ptr->wpos) && in_irondeepdive(&p_ptr->wpos)) {
3553 msg_format(Ind, "The stolen enchantment scroll spoiled the appearence of %s %s!",
3554 ((item >= 0) ? "your" : "the"), o_name);
3555 o_ptr->discount = 100;
3556 if (!o_ptr->note) o_ptr->note = quark_add("devalued");
3557 }
3558 #endif
3559
3560 /* Did we use up an item? */
3561 if (p_ptr->using_up_item >= 0) {
3562 inven_item_describe(Ind, p_ptr->using_up_item);
3563 inven_item_optimize(Ind, p_ptr->using_up_item);
3564 p_ptr->using_up_item = -1;
3565 }
3566
3567 p_ptr->current_enchant_h = -1;
3568 p_ptr->current_enchant_d = -1;
3569 p_ptr->current_enchant_a = -1;
3570 p_ptr->current_enchant_flag = -1;
3571
3572 /* Window stuff */
3573 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3574
3575 /* Something happened */
3576 return (TRUE);
3577 }
3578
3579
ident_spell(int Ind)3580 bool ident_spell(int Ind) {
3581 player_type *p_ptr = Players[Ind];
3582
3583 #ifdef ENABLE_XID_SPELL
3584 /* special hack for !X on ID spells */
3585 if (p_ptr->current_item < -1) {
3586 clear_current(Ind);
3587 #ifndef XID_SPELL_AFTER_PICKUP
3588 ident_spell_aux(Ind, p_ptr->current_item + 1);
3589 #else
3590 ident_spell_aux(Ind, -p_ptr->current_item - 1);
3591 #endif
3592 return TRUE;
3593 }
3594 #endif
3595
3596 get_item(Ind, ITH_NONE);
3597
3598 /* Clear any other pending actions - mikaelh */
3599 clear_current(Ind);
3600
3601 p_ptr->current_identify = 1;
3602
3603 return TRUE;
3604 }
3605
3606 /*
3607 * Identify an object in the inventory (or on the floor)
3608 * This routine does *not* automatically combine objects.
3609 * Returns TRUE if something was identified, else FALSE.
3610 */
ident_spell_aux(int Ind,int item)3611 bool ident_spell_aux(int Ind, int item) {
3612 player_type *p_ptr = Players[Ind];
3613 object_type *o_ptr;
3614 char o_name[ONAME_LEN];
3615
3616 #ifdef ENABLE_XID_SPELL
3617 /* clean up special hack for !X on ID spells */
3618 p_ptr->current_item = -1;
3619 #endif
3620
3621 /* Get the item (in the pack) */
3622 if (item >= 0) o_ptr = &p_ptr->inventory[item];
3623 /* Get the item (on the floor) */
3624 else o_ptr = &o_list[0 - item];
3625
3626
3627 /* Identify it fully */
3628 object_aware(Ind, o_ptr);
3629 object_known(o_ptr);
3630
3631 /* Recalculate bonuses */
3632 p_ptr->update |= (PU_BONUS);
3633
3634 /* redraw to-hit/to-dam */
3635 p_ptr->redraw |= (PR_PLUSSES);
3636
3637 /* Combine / Reorder the pack (later) */
3638 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3639
3640 /* Window stuff */
3641 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3642
3643 /* Description */
3644 object_desc(Ind, o_name, o_ptr, TRUE, 3);
3645
3646 /* Describe */
3647 if (item >= INVEN_WIELD) {
3648 msg_format(Ind, "%^s: %s (%c).",
3649 describe_use(Ind, item), o_name, index_to_label(item));
3650 } else if (item >= 0) {
3651 msg_format(Ind, "In your pack: %s (%c).",
3652 o_name, index_to_label(item));
3653 } else {
3654 msg_format(Ind, "On the ground: %s.",
3655 o_name);
3656 }
3657
3658 /* Did we use up an item? */
3659 if (p_ptr->using_up_item >= 0) {
3660 // inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not when IDing */
3661 inven_item_optimize(Ind, p_ptr->using_up_item);
3662 p_ptr->using_up_item = -1;
3663 }
3664
3665 p_ptr->current_identify = 0;
3666
3667 if (item >= 0) p_ptr->inventory[item].auto_insc = TRUE;
3668
3669 /* Something happened */
3670 return (TRUE);
3671 }
3672
3673
identify_fully(int Ind)3674 bool identify_fully(int Ind) {
3675 player_type *p_ptr = Players[Ind];
3676
3677 #ifdef ENABLE_XID_SPELL
3678 /* special hack for !X on ID spells */
3679 if (p_ptr->current_item < -1) {
3680 clear_current(Ind);
3681 #ifndef XID_SPELL_AFTER_PICKUP
3682 identify_fully_item(Ind, p_ptr->current_item + 1);
3683 #else
3684 identify_fully_item(Ind, -p_ptr->current_item - 1);
3685 #endif
3686 return TRUE;
3687 }
3688 #endif
3689
3690 get_item(Ind, ITH_NONE);
3691
3692 /* Clear any other pending actions - mikaelh */
3693 clear_current(Ind);
3694
3695 p_ptr->current_star_identify = 1;
3696
3697 return TRUE;
3698 }
3699
3700
3701 /*
3702 * Fully "identify" an object in the inventory -BEN-
3703 * This routine returns TRUE if an item was identified.
3704 */
identify_fully_item(int Ind,int item)3705 bool identify_fully_item(int Ind, int item) {
3706 player_type *p_ptr = Players[Ind];
3707 object_type *o_ptr;
3708 char o_name[ONAME_LEN];
3709
3710 #ifdef ENABLE_XID_SPELL
3711 /* clean up special hack for !X on ID spells */
3712 p_ptr->current_item = -1;
3713 #endif
3714
3715 /* Get the item (in the pack) */
3716 if (item >= 0)
3717 o_ptr = &p_ptr->inventory[item];
3718 /* Get the item (on the floor) */
3719 else
3720 o_ptr = &o_list[0 - item];
3721
3722
3723 /* Identify it fully */
3724 object_aware(Ind, o_ptr);
3725 object_known(o_ptr);
3726
3727 /* Mark the item as fully known */
3728 o_ptr->ident |= (ID_MENTAL);
3729
3730 /* Recalculate bonuses */
3731 p_ptr->update |= (PU_BONUS);
3732
3733 /* Combine / Reorder the pack (later) */
3734 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3735
3736 /* Window stuff */
3737 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3738
3739 /* Handle stuff */
3740 handle_stuff(Ind);
3741
3742 /* Description */
3743 object_desc(Ind, o_name, o_ptr, TRUE, 3);
3744
3745 /* Describe */
3746 if (item >= INVEN_WIELD)
3747 msg_format(Ind, "%^s: %s (%c).",
3748 describe_use(Ind, item), o_name, index_to_label(item));
3749 else if (item >= 0)
3750 msg_format(Ind, "In your pack: %s (%c).",
3751 o_name, index_to_label(item));
3752 else
3753 msg_format(Ind, "On the ground: %s.",
3754 o_name);
3755
3756 /* Describe it fully */
3757 (void)identify_fully_aux(Ind, o_ptr, FALSE);
3758
3759 /* Did we use up an item? */
3760 if (p_ptr->using_up_item >= 0) {
3761 // inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not for *ID* */
3762 inven_item_optimize(Ind, p_ptr->using_up_item);
3763 p_ptr->using_up_item = -1;
3764
3765 p_ptr->window |= PW_INVEN;
3766 }
3767
3768 /* We no longer have a *identify* in progress */
3769 p_ptr->current_star_identify = 0;
3770
3771 /* extra: in case the item wasn't normally identified yet but right away *id*ed, apply this too.. */
3772 if (item >= 0) p_ptr->inventory[item].auto_insc = TRUE;
3773
3774 /* Success */
3775 return (TRUE);
3776 }
3777
3778 /* silent version of identify_fully_item() that doesn't display anything - C. Blue */
identify_fully_item_quiet(int Ind,int item)3779 bool identify_fully_item_quiet(int Ind, int item) {
3780 player_type *p_ptr = Players[Ind];
3781 object_type *o_ptr;
3782
3783 /* Get the item (in the pack) */
3784 if (item >= 0) o_ptr = &p_ptr->inventory[item];
3785 /* Get the item (on the floor) */
3786 else o_ptr = &o_list[0 - item];
3787
3788 /* Identify it fully */
3789 object_aware(Ind, o_ptr);
3790 object_known(o_ptr);
3791
3792 /* Mark the item as fully known */
3793 o_ptr->ident |= (ID_MENTAL);
3794 /* Recalculate bonuses */
3795 p_ptr->update |= (PU_BONUS);
3796 /* Combine / Reorder the pack (later) */
3797 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
3798 /* Window stuff */
3799 p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER);
3800
3801 /* Did we use up an item? */
3802 if (p_ptr->using_up_item >= 0) {
3803 // inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not for *ID* */
3804 inven_item_optimize(Ind, p_ptr->using_up_item);
3805 p_ptr->using_up_item = -1;
3806
3807 p_ptr->window |= PW_INVEN;
3808 }
3809
3810 /* Handle stuff */
3811 handle_stuff(Ind);
3812
3813 /* We no longer have a *identify* in progress */
3814 p_ptr->current_star_identify = 0;
3815
3816 /* Success */
3817 return (TRUE);
3818 }
3819
3820 /* variant of identify_fully_item_quiet that doesn't use player inventory,
3821 added for !X on Iron Helm of Knowledge, which probably doesn't make much
3822 sense though - C. Blue */
identify_fully_object_quiet(int Ind,object_type * o_ptr)3823 bool identify_fully_object_quiet(int Ind, object_type *o_ptr) {
3824 player_type *p_ptr = Players[Ind];
3825
3826 /* Identify it fully */
3827 object_aware(Ind, o_ptr);
3828 object_known(o_ptr);
3829
3830 /* Mark the item as fully known */
3831 o_ptr->ident |= (ID_MENTAL);
3832
3833 /* Did we use up an item? */
3834 if (p_ptr->using_up_item >= 0) {
3835 // inven_item_describe(Ind, p_ptr->using_up_item); /* maybe not for *ID* */
3836 inven_item_optimize(Ind, p_ptr->using_up_item);
3837 p_ptr->using_up_item = -1;
3838
3839 p_ptr->window |= PW_INVEN;
3840 }
3841
3842 /* Handle stuff */
3843 handle_stuff(Ind);
3844
3845 /* We no longer have a *identify* in progress */
3846 p_ptr->current_star_identify = 0;
3847
3848 /* Success */
3849 return (TRUE);
3850 }
3851
3852 /*
3853 * Hook for "get_item()". Determine if something is rechargable.
3854 */
3855 //static bool item_tester_hook_recharge(object_type *o_ptr)
item_tester_hook_recharge(object_type * o_ptr)3856 bool item_tester_hook_recharge(object_type *o_ptr) {
3857 u32b f1, f2, f3, f4, f5, f6, esp;
3858
3859 /* Extract the flags */
3860 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
3861
3862 /* Some objects cannot be recharged */
3863 if (f4 & TR4_NO_RECHARGE) return (FALSE);
3864
3865 /* Recharge staffs/wands/rods */
3866 if (is_magic_device(o_ptr->tval)) return (TRUE);
3867
3868 /* Nope */
3869 return (FALSE);
3870 }
3871
3872
recharge(int Ind,int num)3873 bool recharge(int Ind, int num) {
3874 player_type *p_ptr = Players[Ind];
3875
3876 get_item(Ind, ITH_RECHARGE);
3877
3878 /* Clear any other pending actions - mikaelh */
3879 clear_current(Ind);
3880
3881 p_ptr->current_recharge = num;
3882
3883 return TRUE;
3884 }
3885
3886
3887 /*
3888 * Recharge a wand/staff/rod from the pack or on the floor.
3889 *
3890 * Mage -- Recharge I --> recharge(5)
3891 * Mage -- Recharge II --> recharge(40)
3892 * Mage -- Recharge III --> recharge(100)
3893 *
3894 * Priest -- Recharge --> recharge(15)
3895 *
3896 * Scroll of recharging --> recharge(60)
3897 *
3898 * recharge(20) = 1/6 failure for empty 10th level wand
3899 * recharge(60) = 1/10 failure for empty 10th level wand
3900 *
3901 * It is harder to recharge high level, and highly charged wands.
3902 *
3903 * XXX XXX XXX Beware of "sliding index errors".
3904 *
3905 * Should probably not "destroy" over-charged items, unless we
3906 * "replace" them by, say, a broken stick or some such. The only
3907 * reason this is okay is because "scrolls of recharging" appear
3908 * BEFORE all staffs/wands/rods in the inventory. Note that the
3909 * new "auto_sort_pack" option would correctly handle replacing
3910 * the "broken" wand with any other item (i.e. a broken stick).
3911 *
3912 * XXX XXX XXX Perhaps we should auto-unstack recharging stacks.
3913 */
recharge_aux(int Ind,int item,int pow)3914 bool recharge_aux(int Ind, int item, int pow) {
3915 player_type *p_ptr = Players[Ind];
3916 int i, t, lev, dr;
3917 object_type *o_ptr;
3918
3919
3920 /* Only accept legal items */
3921 item_tester_hook = item_tester_hook_recharge;
3922
3923 /* Get the item (in the pack) */
3924 if (item >= 0) o_ptr = &p_ptr->inventory[item];
3925 /* Get the item (on the floor) */
3926 else o_ptr = &o_list[0 - item];
3927
3928 if (!item_tester_hook(o_ptr)) {
3929 msg_print(Ind, "You cannot recharge that item.");
3930 get_item(Ind, ITH_RECHARGE);
3931 return (FALSE);
3932 }
3933
3934 /* Extract the object "level" */
3935 lev = k_info[o_ptr->k_idx].level;
3936
3937 /* Recharge a rod */
3938 if (o_ptr->tval == TV_ROD) {
3939 /* Extract a recharge power */
3940 i = (100 - lev + pow) / 5;
3941
3942 /* Paranoia -- prevent crashes */
3943 if (i < 1) i = 1;
3944
3945 /* Back-fire */
3946 if (rand_int(i) == 0) {
3947 /* Hack -- backfire */
3948 //msg_print(Ind, "The recharge backfires, draining the rod further!");
3949 msg_print(Ind, "There is a static discharge.");
3950
3951 /* Hack -- decharge the rod */
3952 if (o_ptr->pval < 10000) o_ptr->pval = (o_ptr->pval + 100) * 2;
3953 }
3954
3955 /* Recharge */
3956 else {
3957 /* Rechange amount */
3958 t = (pow * damroll(2, 4));
3959
3960 /* Recharge by that amount */
3961 if (o_ptr->pval > t) o_ptr->pval -= t;
3962 /* Fully recharged */
3963 else o_ptr->pval = 0;
3964 }
3965 }
3966
3967 /* Recharge wand/staff */
3968 else {
3969 /* Recharge power */
3970 i = (pow + 100 - lev - (10 * o_ptr->pval)) / 15;
3971
3972 /* Paranoia -- prevent crashes */
3973 if (i < 1) i = 1;
3974
3975 /* Back-fire XXX XXX XXX */
3976 if (rand_int(i) == 0) {
3977 /* a chance to just discharge it instead of destroying it */
3978 if (!rand_int(2)) {
3979 msg_print(Ind, "There is a static discharge.");
3980 o_ptr->pval = 0;
3981 o_ptr->ident |= ID_EMPTY;
3982 } else {
3983 /* Dangerous Hack -- Destroy the item */
3984 msg_print(Ind, "There is a bright flash of light.");
3985
3986 /* Reduce and describe inventory */
3987 if (item >= 0) {
3988 inven_item_increase(Ind, item, -999);
3989 inven_item_describe(Ind, item);
3990 inven_item_optimize(Ind, item);
3991 }
3992 /* Reduce and describe floor item */
3993 else {
3994 floor_item_increase(0 - item, -999);
3995 floor_item_describe(0 - item);
3996 floor_item_optimize(0 - item);
3997 }
3998 }
3999 }
4000
4001 /* Hack: No controlled mass-summoning in ironman deep dive challenge */
4002 else if (in_irondeepdive(&p_ptr->wpos) &&
4003 ((o_ptr->tval == TV_STAFF && o_ptr->sval == SV_STAFF_SUMMONING) ||
4004 (o_ptr->tval == TV_WAND && o_ptr->sval == SV_WAND_POLYMORPH))) {
4005 msg_print(Ind, "There is a static discharge.");
4006 o_ptr->pval = 0;
4007 o_ptr->ident |= ID_EMPTY;
4008 }
4009
4010 /* Recharge */
4011 else {
4012 /* Extract a "power" */
4013 t = (pow / (lev + 2)) + 1;
4014
4015 /* Hack -- ego */
4016 if (o_ptr->name2 == EGO_PLENTY) t <<= 1;
4017
4018 #if 0 /* old way */
4019 /* Recharge based on the power */
4020 if (t > 0) o_ptr->pval += 2 + randint(t);
4021 #else /* new way: correct wand stacking, added stack size dr */
4022 /* Wands stack, so recharging must multiply the power.
4023 Add small 'laziness' diminishing returns malus. */
4024 if (o_ptr->tval == TV_WAND) {
4025 /* Recharge based on the power */
4026 //if (t > 0) o_ptr->pval += (2 * o_ptr->number) + rand_int(t * o_ptr->number);
4027
4028 /* allow dr to factor in more: */
4029 //Diminishing returns start at number=10: ' * (1050 / (10 + 1000 / (o_ptr->number + 4)) - 4) '
4030 //Diminishing returns start at number=3~: ' * (450 / (10 + 400 / (o_ptr->number + 3)) - 3) '
4031 dr = 4500 / (10 + 400 / (o_ptr->number + 3)) - 30;
4032 if (t > 0) o_ptr->pval += (3 * dr) / 10 + rand_int(t * dr) / 10;
4033 } else {
4034 /* Recharge based on the power */
4035 //if (t > 0) o_ptr->pval += 2 + randint(t);
4036
4037 /* allow dr to factor in more: */
4038 dr = 4500 / (10 + 400 / (o_ptr->number + 3)) - 30;
4039 if (t > 0) o_ptr->pval += 1 + (rand_int((t + 2) * dr) / o_ptr->number) / 10;
4040 }
4041 #endif
4042
4043 /* Hack -- we no longer "know" the item */
4044 o_ptr->ident &= ~ID_KNOWN;
4045
4046 /* Hack -- we no longer think the item is empty */
4047 o_ptr->ident &= ~ID_EMPTY;
4048 }
4049 }
4050
4051 /* Did we use up an item? */
4052 if (p_ptr->using_up_item >= 0) {
4053 inven_item_describe(Ind, p_ptr->using_up_item);
4054 inven_item_optimize(Ind, p_ptr->using_up_item);
4055 p_ptr->using_up_item = -1;
4056 }
4057
4058 /* Combine / Reorder the pack (later) */
4059 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
4060
4061 /* Window stuff */
4062 p_ptr->window |= (PW_INVEN | PW_EQUIP);
4063
4064 /* We no longer have a recharge in progress */
4065 p_ptr->current_recharge = 0;
4066
4067 /* Something was done */
4068 return (TRUE);
4069 }
4070
4071
4072
4073
4074
4075
4076
4077
4078 /*
4079 * Apply a "project()" directly to all viewable monsters
4080 */
project_los(int Ind,int typ,int dam,char * attacker)4081 bool project_los(int Ind, int typ, int dam, char *attacker) {
4082 player_type *p_ptr = Players[Ind];
4083 struct worldpos *wpos = &p_ptr->wpos;
4084 int i, x, y;
4085 int flg = PROJECT_NORF | PROJECT_JUMP | PROJECT_KILL | PROJECT_HIDE;
4086 bool obvious = FALSE;
4087 char pattacker[80];
4088
4089 if (Ind) snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
4090 else snprintf(pattacker, 80, "Something%s", attacker);
4091
4092 /* Affect all (nearby) monsters */
4093 for (i = 1; i < m_max; i++) {
4094 monster_type *m_ptr = &m_list[i];
4095
4096 /* Paranoia -- Skip dead monsters */
4097 if (!m_ptr->r_idx) continue;
4098
4099 /* Skip monsters not on this depth */
4100 if(!inarea(wpos, &m_ptr->wpos)) continue;
4101
4102 /* Location */
4103 y = m_ptr->fy;
4104 x = m_ptr->fx;
4105
4106 /* Require line of sight */
4107 if (!player_has_los_bold(Ind, y, x)) continue;
4108
4109 /* Don't exceed max range (which may be < sight range)! */
4110 if (distance(p_ptr->py, p_ptr->px, y, x) > MAX_RANGE) continue;
4111 /* Maybe also check for BLOCK_LOS/BLOCK_CONTACT grids? (glass walls..) */
4112 if (!projectable_wall(wpos, p_ptr->py, p_ptr->px, y, x, MAX_RANGE)) continue;
4113
4114 /* Jump directly to the target monster */
4115 if (project(0 - Ind, 0, wpos, y, x, dam, typ, flg, pattacker)) obvious = TRUE;
4116 }
4117
4118 #if 1 //this would require to differ between project_los calls that are meant
4119 //to work on players and those that are meant to work on monsters only
4120 //like GF_OLD_SPEED, GF_OLD_HEAL, etc. If this is done, an attacker string
4121 //should be added as well, however.
4122
4123 /* Affect all (nearby) non-partied players */
4124 for (i = 1; i < NumPlayers + 1; i++) {
4125 /* If he's not playing, skip him */
4126 if (Players[i]->conn == NOT_CONNECTED)
4127 continue;
4128
4129 /* If he's not here, skip him */
4130 if (!inarea(wpos, &Players[i]->wpos))
4131 continue;
4132
4133 /* Ignore players we aren't hostile to */
4134 // if (!check_hostile(Ind, i)) continue;
4135
4136 /* if we are in the same party, don't affect target player */
4137 if (p_ptr->party && (player_in_party(p_ptr->party, i)))
4138 continue;
4139
4140 /* Location */
4141 y = Players[i]->py;
4142 x = Players[i]->px;
4143
4144 /* Require line of sight */
4145 if (!player_has_los_bold(Ind, y, x)) continue;
4146
4147 /* Jump directly to the target player */
4148 if (project(0 - Ind, 0, wpos, y, x, dam, typ, flg, pattacker)) obvious = TRUE;
4149 }
4150 #endif
4151
4152 /* Result */
4153 return (obvious);
4154 }
4155
4156
4157 /* Speed monsters */
speed_monsters(int Ind)4158 bool speed_monsters(int Ind) {
4159 player_type *p_ptr = Players[Ind];
4160 return (project_los(Ind, GF_OLD_SPEED, p_ptr->lev, ""));
4161 }
4162 /* Slow monsters */
slow_monsters(int Ind,int pow)4163 bool slow_monsters(int Ind, int pow) {
4164 return (project_los(Ind, GF_OLD_SLOW, pow, ""));
4165 }
4166 /* Sleep monsters */
sleep_monsters(int Ind,int pow)4167 bool sleep_monsters(int Ind, int pow) {
4168 return (project_los(Ind, GF_OLD_SLEEP, pow, ""));
4169 }
4170 /* Fear monsters */
fear_monsters(int Ind,int pow)4171 bool fear_monsters(int Ind, int pow) {
4172 return (project_los(Ind, GF_TURN_ALL, pow, ""));
4173 }
4174 /* Stun monsters */
stun_monsters(int Ind,int pow)4175 bool stun_monsters(int Ind, int pow) {
4176 return (project_los(Ind, GF_STUN, pow, ""));
4177 }
4178
4179
4180 /* Banish evil monsters */
away_evil(int Ind,int dist)4181 bool away_evil(int Ind, int dist) {
4182 return (project_los(Ind, GF_AWAY_EVIL, dist, " banishes all evil"));
4183 }
4184
4185
4186 /* Turn undead */
turn_undead(int Ind)4187 bool turn_undead(int Ind) {
4188 player_type *p_ptr = Players[Ind];
4189 return (project_los(Ind, GF_TURN_UNDEAD, p_ptr->lev, " calls against all undead"));
4190 }
4191 /* Turn everyone */
turn_monsters(int Ind,int dam)4192 bool turn_monsters(int Ind, int dam) {
4193 return (project_los(Ind, GF_TURN_ALL, dam, " calls against all monsters"));
4194 }
4195
4196
4197 /* Dispel undead monsters */
dispel_undead(int Ind,int dam)4198 bool dispel_undead(int Ind, int dam) {
4199 return (project_los(Ind, GF_DISP_UNDEAD, dam, " banishes all undead"));
4200 }
4201 /* Dispel evil monsters */
dispel_evil(int Ind,int dam)4202 bool dispel_evil(int Ind, int dam) {
4203 return (project_los(Ind, GF_DISP_EVIL, dam, " banishes all evil"));
4204 }
4205 /* Dispel demons */
dispel_demons(int Ind,int dam)4206 bool dispel_demons(int Ind, int dam) {
4207 return (project_los(Ind, GF_DISP_DEMON, dam, " banishes all demons"));
4208 }
4209 /* Dispel all monsters */
dispel_monsters(int Ind,int dam)4210 bool dispel_monsters(int Ind, int dam) {
4211 return (project_los(Ind, GF_DISP_ALL, dam, " banishes all monsters"));
4212 }
4213
4214
4215 /*
4216 * Wake up all monsters, and speed up "los" monsters.
4217 */
aggravate_monsters(int Ind,int who)4218 void aggravate_monsters(int Ind, int who) {
4219 player_type *p_ptr = Players[Ind];
4220 monster_type * m_ptr;
4221 monster_race *r_ptr;
4222
4223 int i;
4224
4225 bool sleep = FALSE;
4226 bool speed = FALSE;
4227
4228 /* Aggravate everyone nearby */
4229 for (i = 1; i < m_max; i++) {
4230 m_ptr = &m_list[i];
4231 r_ptr = race_inf(m_ptr);
4232
4233 /* Paranoia -- Skip dead monsters */
4234 if (!m_ptr->r_idx) continue;
4235
4236 /* Skip monsters not on this depth */
4237 if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4238
4239 /* Skip aggravating monster (or player) */
4240 if (i == who) continue;
4241
4242 /* Wake up nearby sleeping monsters */
4243 if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4244 #if 0
4245 if (m_ptr->cdis < MAX_SIGHT * 2)
4246 #endif
4247 {
4248 /* Wake up */
4249 if (m_ptr->csleep) {
4250 /* Wake up */
4251 m_ptr->csleep = 0;
4252 sleep = TRUE;
4253 }
4254 }
4255
4256 /* Don't speed up undead/nonliving monsters */
4257 if ((r_ptr->flags3 & RF3_NONLIVING) || (r_ptr->flags2 & RF2_EMPTY_MIND)) continue;
4258
4259 /* Speed up monsters in line of sight */
4260 if (player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) {
4261 /* Speed up (instantly) to racial base + 10 */
4262 if (m_ptr->mspeed < m_ptr->speed + 10) {
4263 /* Speed up */
4264 m_ptr->mspeed = m_ptr->speed + 10;
4265 speed = TRUE;
4266 }
4267 }
4268 }
4269
4270 /* Messages */
4271 /* the_sandman: added _near so other players can hear too */
4272 if (speed) {
4273 msg_print(Ind, "You feel a sudden stirring nearby!");
4274 msg_print_near(Ind, "You feel a sudden stirring nearby!");
4275 } else if (sleep) {
4276 msg_print(Ind, "You hear a sudden stirring in the distance!");
4277 msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4278 }
4279 }
4280
4281 /*
4282 * Wake up all monsters
4283 */
wakeup_monsters(int Ind,int who)4284 void wakeup_monsters(int Ind, int who) {
4285 player_type *p_ptr = Players[Ind];
4286 int i;
4287 bool sleep = FALSE;
4288
4289 /* Aggravate everyone nearby */
4290 for (i = 1; i < m_max; i++) {
4291 monster_type *m_ptr = &m_list[i];
4292
4293 /* Paranoia -- Skip dead monsters */
4294 if (!m_ptr->r_idx) continue;
4295
4296 /* Skip monsters not on this depth */
4297 if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4298
4299 /* Skip aggravating monster (or player) */
4300 if (i == who) continue;
4301
4302 /* Wake up nearby sleeping monsters */
4303 if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4304 #if 0
4305 if (m_ptr->cdis < MAX_SIGHT * 2)
4306 #endif
4307 {
4308 /* Wake up */
4309 if (m_ptr->csleep) {
4310 /* Wake up */
4311 m_ptr->csleep = 0;
4312 sleep = TRUE;
4313 }
4314 }
4315 }
4316
4317 /* Messages */
4318 /* the_sandman: added _near so other players can hear too */
4319 if (sleep) {
4320 msg_print(Ind, "You hear a sudden stirring in the distance!");
4321 msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4322 }
4323 }
4324
wakeup_monsters_somewhat(int Ind,int who)4325 void wakeup_monsters_somewhat(int Ind, int who) {
4326 player_type *p_ptr = Players[Ind];
4327 int i;
4328 bool sleep = FALSE;
4329
4330 /* Aggravate everyone nearby */
4331 for (i = 1; i < m_max; i++) {
4332 monster_type *m_ptr = &m_list[i];
4333
4334 /* Paranoia -- Skip dead monsters */
4335 if (!m_ptr->r_idx) continue;
4336
4337 /* Skip monsters not on this depth */
4338 if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4339
4340 /* Skip aggravating monster (or player) */
4341 if (i == who) continue;
4342
4343 /* Wake up nearby sleeping monsters */
4344 if (distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4345 #if 0
4346 if (m_ptr->cdis < MAX_SIGHT * 2)
4347 #endif
4348 {
4349 /* Disturb sleep somewhat */
4350 if (m_ptr->csleep) {
4351 m_ptr->csleep = (m_ptr->csleep * 3) / 5;
4352 m_ptr->csleep -= 10 + rand_int(6); //10
4353 if (m_ptr->csleep <= 0) {
4354 m_ptr->csleep = 0;
4355 sleep = TRUE;
4356 }
4357 }
4358 }
4359 }
4360
4361 #if 1 /* better style, not to display a msg maybe? */
4362 /* Messages */
4363 /* the_sandman: added _near so other players can hear too */
4364 if (sleep) {
4365 msg_print(Ind, "You hear a sudden stirring in the distance!");
4366 msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4367 }
4368 #endif
4369 }
4370
distract_monsters(int Ind)4371 void distract_monsters(int Ind) {
4372 player_type *p_ptr = Players[Ind];
4373 monster_type *m_ptr;
4374 monster_race *r_ptr;
4375
4376 int i;
4377 bool tauntable;
4378
4379 msg_print(Ind, "You make yourself look less threatening than your team mates.");
4380 msg_format_near(Ind, "%s pretends you're more threatening than him.", p_ptr->name);
4381 break_cloaking(Ind, 0);
4382 break_shadow_running(Ind);
4383 stop_precision(Ind);
4384 stop_shooting_till_kill(Ind);
4385
4386 for (i = 1; i < m_max; i++) {
4387 m_ptr = &m_list[i];
4388 r_ptr = race_inf(m_ptr);
4389
4390 /* Paranoia -- Skip dead monsters */
4391 if (!m_ptr->r_idx) continue;
4392 if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4393
4394 if ((r_ptr->flags3 & (RF3_ORC | RF3_TROLL | RF3_GIANT | RF3_DEMON)) ||
4395 (strchr("hHkptn", r_ptr->d_char))) tauntable = TRUE;
4396 else tauntable = FALSE;
4397
4398 if (r_ptr->level >= 98) tauntable = FALSE; /* end-game specialties are exempt */
4399 if (r_ptr->flags1 & RF1_UNIQUE) {
4400 #if 0 /* still distractable, hence if 0'ed */
4401 if (r_ptr->flags2 & RF2_POWERFUL) {
4402 if (magik(75)) tauntable = FALSE; /* powerful unique monsters prefer to stay alive */
4403 } else
4404 #endif
4405 {
4406 if (magik(50)) tauntable = FALSE; /* unique monsters resist more often */
4407 }
4408 }
4409 else if (magik(25)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4410 // else if (magik(r_ptr->level / 3)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4411
4412 #if 0 /*actually, being POWERFUL doesn't really protect.. */
4413 if (r_ptr->flags2 & RF2_POWERFUL) tauntable = FALSE;
4414 #endif
4415 #if 0 /* shamans -_- and not only that, way too many monsters are SMART, so commented out for now */
4416 if (r_ptr->flags2 & RF2_SMART) tauntable = FALSE; /* smart monsters don't fall for taunts */
4417 #endif
4418 if (r_ptr->flags3 & RF3_NONLIVING) tauntable = FALSE; /* nonliving monsters can't perceive taunts */
4419 if (r_ptr->flags2 & RF2_EMPTY_MIND) tauntable = FALSE; /* empty-minded monsters can't perceive taunts */
4420 if ((r_ptr->flags2 & RF2_WEIRD_MIND) && magik(50)) tauntable = FALSE; /* weird-minded monsters are hard to predict */
4421 /* RF2_CAN_SPEAK ?? */
4422
4423 if (!tauntable) continue;
4424
4425 /* monster stands right next to this player? */
4426 if (ABS(m_ptr->fy - p_ptr->py) <= 1 && ABS(m_ptr->fx - p_ptr->px) <= 1 &&
4427 m_ptr->last_target_melee == Ind) {
4428 /* set another (adjacent) player as target */
4429 m_ptr->switch_target = Ind;
4430 }
4431 }
4432 }
4433
4434 /* attempts to make certain types of AI_ANNOY monsters approach the player for a while */
taunt_monsters(int Ind)4435 void taunt_monsters(int Ind)
4436 {
4437 player_type *p_ptr = Players[Ind];
4438 monster_type *m_ptr;
4439 monster_race *r_ptr;
4440
4441 int i;
4442 bool sleep = FALSE, tauntable;
4443
4444 msg_print(Ind, "You call out a taunt!");
4445 msg_format_near(Ind, "%s calls out a taunt!", p_ptr->name);
4446 break_cloaking(Ind, 0);
4447 stop_precision(Ind);
4448
4449 for (i = 1; i < m_max; i++) {
4450 m_ptr = &m_list[i];
4451 r_ptr = race_inf(m_ptr);
4452
4453 /* Paranoia -- Skip dead monsters */
4454 if (!m_ptr->r_idx) continue;
4455 if(!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4456
4457 if ((r_ptr->flags3 & (RF3_ORC | RF3_TROLL | RF3_GIANT | RF3_DEMON)) ||
4458 (strchr("hHkptn", r_ptr->d_char))) tauntable = TRUE;
4459 else tauntable = FALSE;
4460
4461 if (r_ptr->level >= 98) tauntable = FALSE; /* end-game specialties are exempt */
4462 if (r_ptr->flags1 & RF1_UNIQUE) {
4463 if (r_ptr->flags2 & RF2_POWERFUL) {
4464 if (magik(75)) tauntable = FALSE; /* powerful unique monsters prefer to stay alive */
4465 } else {
4466 if (magik(50)) tauntable = FALSE; /* unique monsters resist more often */
4467 }
4468 }
4469 else if (magik(20)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4470 // else if (magik(r_ptr->level / 3)) tauntable = FALSE; /* all monsters sometimes resist taunt */
4471
4472 #if 0 /*actually, being POWERFUL doesn't really protect.. */
4473 if (r_ptr->flags2 & RF2_POWERFUL) tauntable = FALSE;
4474 #endif
4475 #if 0 /* shamans -_- and not only that, way too many monsters are SMART, so commented out for now */
4476 if (r_ptr->flags2 & RF2_SMART) tauntable = FALSE; /* smart monsters don't fall for taunts */
4477 #endif
4478 if (r_ptr->flags3 & RF3_NONLIVING) tauntable = FALSE; /* nonliving monsters can't perceive taunts */
4479 if (r_ptr->flags2 & RF2_EMPTY_MIND) tauntable = FALSE; /* empty-minded monsters can't perceive taunts */
4480 if ((r_ptr->flags2 & RF2_WEIRD_MIND) && magik(50)) tauntable = FALSE; /* weird-minded monsters are hard to predict */
4481 /* RF2_CAN_SPEAK ?? */
4482
4483 /* some egos aren't tauntable possibly */
4484 switch(m_ptr->ego) {
4485 case 10: case 13: case 23: /* archers */
4486 case 9: case 30: /* mages */
4487 tauntable = FALSE;
4488 break;
4489 default: ;
4490 }
4491
4492 /* some monsters (hard-coded ;() aren't tauntable */
4493 switch(m_ptr->r_idx) {
4494 case 46: case 93: case 240: case 449: case 638: case 738: /* p mages */
4495 case 178: case 281: case 375: case 657: /* h mages */
4496 case 539: /* h archers */
4497 tauntable = FALSE;
4498 break;
4499 default: ;
4500 }
4501
4502 if (!tauntable) continue;
4503
4504 if (player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) {
4505 #if 0
4506 /* wake up */
4507 if (m_ptr->csleep) {
4508 m_ptr->csleep = 0;
4509 sleep = TRUE;
4510 }
4511 #endif
4512
4513 /* taunt */
4514 m_ptr->monfear = 0;
4515 m_ptr->taunted = 7; /* number of monster moves staying taunted */
4516 //was 5
4517 }
4518
4519 /* monster stands right next to this player? */
4520 if (ABS(m_ptr->fy - p_ptr->py) <= 1 && ABS(m_ptr->fx - p_ptr->px) <= 1)
4521 m_ptr->last_target_melee = Ind;
4522 }
4523
4524 if (sleep) {
4525 msg_print(Ind, "You hear a sudden stirring in the distance!");
4526 msg_print_near(Ind, "You hear a sudden stirring in the distance!");
4527 }
4528 }
4529
4530 /* Need it for detonation pots in potion_smash_effect - C. Blue */
aggravate_monsters_floorpos(worldpos * wpos,int x,int y)4531 void aggravate_monsters_floorpos(worldpos *wpos, int x, int y) {
4532 int i;
4533
4534 /* Aggravate everyone nearby */
4535 for (i = 1; i < m_max; i++) {
4536 monster_type *m_ptr = &m_list[i];
4537
4538 /* Paranoia -- Skip dead monsters */
4539 if (!m_ptr->r_idx) continue;
4540
4541 /* Skip monsters not on this depth */
4542 if (!inarea(wpos, &m_ptr->wpos)) continue;
4543
4544 /* Wake up nearby sleeping monsters */
4545 if (distance(y, x, m_ptr->fy, m_ptr->fx) < MAX_SIGHT * 2)
4546 #if 0
4547 if (m_ptr->cdis < MAX_SIGHT * 2)
4548 #endif
4549 {
4550 /* Wake up */
4551 if (m_ptr->csleep) {
4552 /* Wake up */
4553 m_ptr->csleep = 0;
4554 }
4555 }
4556 }
4557 }
4558
4559
4560 /*
4561 * Wake up minions (escorts/friends). May be used by a pack monster or unique.
4562 * As soon as a monster is hit by a player or has a LOS to him. - C. Blue
4563 */
wake_minions(int Ind,int who)4564 void wake_minions(int Ind, int who) {
4565 player_type *p_ptr = Players[Ind];
4566
4567 monster_type *mw_ptr = &m_list[who], *m_ptr = NULL;
4568 monster_race *rw_ptr = race_inf(m_ptr), *r_ptr = NULL;
4569 char mw_name[MNAME_LEN];
4570
4571 int i;
4572
4573 bool sleep = FALSE;
4574 // bool speed = FALSE;
4575
4576
4577 monster_desc(Ind, mw_name, who, 0x00);
4578
4579 /* Aggravate everyone nearby */
4580 for (i = 1; i < m_max; i++) {
4581 m_ptr = &m_list[i];
4582 r_ptr = race_inf(m_ptr);
4583
4584 /* Paranoia -- Skip dead monsters */
4585 if (!m_ptr->r_idx) continue;
4586
4587 /* Skip monsters not on this depth */
4588 if (!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4589
4590 /* Skip aggravating monster (or player) */
4591 if (i == who) continue;
4592
4593 /* wake_minions used by a FRIENDS monster? */
4594 if (rw_ptr->flags1 & (RF1_FRIEND | RF1_FRIENDS)) {
4595 /* Skip monsters who aren't its friends */
4596 if (m_ptr->r_idx != mw_ptr->r_idx) continue;
4597 }
4598
4599 /* wake_minions used by a UNIQUE monster? */
4600 if (rw_ptr->flags1 & RF1_UNIQUE) {
4601 /* Skip monsters who don't belong to its escort */
4602
4603 /* Paranoia -- Skip identical monsters */
4604 if (m_ptr->r_idx == mw_ptr->r_idx) continue;
4605 /* Require similar "race" */
4606 if (r_ptr->d_char != rw_ptr->d_char) continue;
4607 /* Skip more advanced monsters */
4608 if (r_ptr->level > rw_ptr->level) continue;
4609 /* Skip unique monsters */
4610 if (r_ptr->flags1 & RF1_UNIQUE) continue;
4611 /* Skip non-escorting monsters */
4612 // if (m_ptr->escorting != who) continue;
4613 }
4614
4615 /* wake_minions used by an escorting monster? */
4616 #if 0 /* m_ptr->escorting = m_idx not yet implemented */
4617 if (mw_ptr->escorting) {
4618 /* Wake up his leader, which always is unique */
4619 if (m_ptr->r_idx != mw_ptr->escorting) continue;
4620 /* Leader wakes the pack */
4621 wake_minions(Ind, i);
4622 }
4623 #endif
4624
4625 /* Wake up nearby sleeping monsters */
4626 if (distance(mw_ptr->fy, mw_ptr->fx, m_ptr->fy, m_ptr->fx) > rw_ptr->aaf) continue;
4627 #if 0
4628 if (m_ptr->cdis < MAX_SIGHT * 2)
4629 #endif
4630 {
4631 /* Wake up */
4632 if (m_ptr->csleep) {
4633 /* Wake up */
4634 m_ptr->csleep = 0;
4635 sleep = TRUE;
4636 }
4637 }
4638 #if 0
4639 /* Speed up monsters in line of sight */
4640 if (player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) {
4641 /* Speed up (instantly) to racial base + 10 */
4642 if (m_ptr->mspeed < m_ptr->speed + 10) {
4643 /* Speed up */
4644 m_ptr->mspeed = m_ptr->speed + 10;
4645 speed = TRUE;
4646 }
4647 }
4648 #endif
4649 }
4650
4651 /* Messages */
4652 if (!sleep) return;
4653 // if (speed) msg_print(Ind, "You feel a sudden stirring nearby!");
4654 // else if (sleep) msg_print(Ind, "You hear a sudden stirring in the distance!");
4655 if ((r_ptr->flags2 & RF2_EMPTY_MIND) || (r_ptr->flags3 & RF3_NONLIVING)) ;
4656 else if (r_ptr->flags3 & RF3_DRAGON) msg_format(Ind, "%s roars loudly!", mw_name);
4657 else if (r_ptr->flags3 & RF3_UNDEAD) msg_format(Ind, "%s moans loudly!", mw_name);
4658 else if (r_ptr->flags3 & RF3_ANIMAL) msg_format(Ind, "%s makes an alerting sound!", mw_name);
4659 else if ((r_ptr->flags3 & (RF3_ORC | RF3_TROLL | RF3_GIANT | RF3_DEMON | RF3_DRAGONRIDER)) ||
4660 (strchr("AhHJkpPty", r_ptr->d_char))) {
4661 msg_format(Ind, "%s shouts a command!", mw_name);
4662 msg_format_near(Ind, "%s shouts a command!", mw_name);
4663 }
4664 }
4665
4666
4667 /*
4668 * If Ind <=0, no one takes the damage. - Jir -OA
4669 */
genocide_aux(int Ind,worldpos * wpos,char typ)4670 bool genocide_aux(int Ind, worldpos *wpos, char typ) {
4671 player_type *p_ptr = Players[Ind];
4672 int i;
4673 bool result = FALSE;
4674 int tmp; // , d = 999;
4675
4676 dun_level *l_ptr = getfloor(wpos);
4677 cave_type **zcave;
4678
4679 if (!(zcave = getcave(wpos))) return(FALSE);
4680 if(l_ptr && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
4681
4682 bypass_invuln = TRUE;
4683
4684 /* Delete the monsters of that "type" */
4685 for (i = 1; i < m_max; i++) {
4686 monster_type *m_ptr = &m_list[i];
4687 monster_race *r_ptr = race_inf(m_ptr);
4688
4689 /* Paranoia -- Skip dead monsters */
4690 if (!m_ptr->r_idx) continue;
4691
4692 /* Hack -- Skip Unique Monsters */
4693 if (r_ptr->flags1 & RF1_UNIQUE) continue;
4694
4695 /* Skip "wrong" monsters */
4696 if (r_ptr->d_char != typ) continue;
4697
4698 /* Skip monsters not on this depth */
4699 if(!inarea(wpos, &m_ptr->wpos)) continue;
4700
4701 /* Skip those immune */
4702 if (r_ptr->flags9 & RF9_IM_TELE) continue;
4703
4704 /* Roll for resistance */
4705 tmp = r_ptr->level;
4706 #ifdef RESIST_GENO
4707 if (randint(RESIST_GENO) < tmp) continue;
4708 #endif // RESIST_GENO
4709
4710 #ifdef NO_GENO_ON_ICKY
4711 /* Not valid inside a vault */
4712 if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY) continue;
4713 #endif // NO_GENO_ON_ICKY
4714
4715 /* Delete the monster */
4716 delete_monster_idx(i, TRUE);
4717
4718 /* Take damage */
4719 if (Ind > 0)
4720 {
4721 if (!p_ptr->admin_dm)
4722 take_hit(Ind, randint(4 + (tmp >> 3)), "the strain of casting Genocide", 0);
4723
4724 /* Redraw */
4725 p_ptr->redraw |= (PR_HP);
4726
4727 /* Window stuff */
4728 /* p_ptr->window |= (PW_PLAYER); */
4729
4730 /* Handle */
4731 handle_stuff(Ind);
4732
4733 /* Delay */
4734 // Send_flush(Ind); /* I don't think a delay is really necessary - mikaelh */
4735 }
4736
4737 /* Take note */
4738 result = TRUE;
4739 }
4740
4741 if (Ind > 0) {
4742 #ifdef SEVERE_GENO
4743 if (!p_ptr->death && result && !p_ptr->admin_dm)
4744 take_hit(Ind, p_ptr->chp >> 1, "the strain of casting Genocide", 0);
4745
4746 /* Redraw */
4747 p_ptr->redraw |= (PR_HP);
4748 #endif // SEVERE_GENO
4749
4750 /* Window stuff */
4751 p_ptr->window |= (PW_PLAYER);
4752
4753 /* Handle */
4754 handle_stuff(Ind);
4755 }
4756
4757 bypass_invuln = FALSE;
4758
4759 return (result);
4760 }
4761
4762 /*
4763 * Delete all non-unique monsters of a given "type" from the level
4764 *
4765 * This is different from normal Angband now -- the closest non-unique
4766 * monster is chosen as the designed character to genocide.
4767 */
genocide(int Ind)4768 bool genocide(int Ind) {
4769 player_type *p_ptr = Players[Ind];
4770 int i;
4771 char typ = -1;
4772 int d = 999, tmp;
4773
4774 worldpos *wpos = &p_ptr->wpos;
4775 dun_level *l_ptr = getfloor(wpos);
4776 cave_type **zcave;
4777
4778 if (!(zcave = getcave(wpos))) return(FALSE);
4779 if(l_ptr && l_ptr->flags1 & LF1_NO_GENO) return(FALSE); // double check..
4780
4781 /* Search all monsters and find the closest */
4782 for (i = 1; i < m_max; i++) {
4783 monster_type *m_ptr = &m_list[i];
4784 monster_race *r_ptr = race_inf(m_ptr);
4785
4786 /* Paranoia -- Skip dead monsters */
4787 if (!m_ptr->r_idx) continue;
4788
4789 /* Hack -- Skip Unique Monsters */
4790 if (r_ptr->flags1 & RF1_UNIQUE) continue;
4791
4792 /* Skip monsters not on this depth */
4793 if(!inarea(&p_ptr->wpos, &m_ptr->wpos)) continue;
4794
4795 /* Check distance */
4796 if ((tmp = distance(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx)) < d) {
4797 /* Set closest distance */
4798 d = tmp;
4799
4800 /* Set char */
4801 typ = r_ptr->d_char;
4802 }
4803 }
4804
4805 /* Check to make sure we found a monster */
4806 if (d == 999) return FALSE;
4807
4808 return (genocide_aux(Ind, wpos, typ));
4809 }
4810
4811
4812 /*
4813 * Delete all nearby (non-unique) monsters
4814 * Either Ind must be a player's index for use by a player,
4815 * or Ind must be -m_idx for use by a monster trap.
4816 */
obliteration(int who)4817 bool obliteration(int who) {
4818 player_type *p_ptr;
4819 int i, tmp, rad, x, y;
4820 bool result = FALSE;
4821
4822 worldpos *wpos;
4823 dun_level *l_ptr;
4824 cave_type **zcave;
4825
4826 /* monster hit a monster trap? */
4827 if (who < 0) {
4828 rad = 1;
4829 p_ptr = NULL;
4830 wpos = &m_list[-who].wpos;
4831 x = m_list[-who].fx;
4832 y = m_list[-who].fy;
4833 }
4834 /* player cast it */
4835 else {
4836 rad = MAX_SIGHT;
4837 p_ptr = Players[who];
4838 wpos = &p_ptr->wpos;
4839 x = p_ptr->px;
4840 y = p_ptr->py;
4841 }
4842
4843 if (!(zcave = getcave(wpos))) return(FALSE);
4844 l_ptr = getfloor(wpos);
4845 if (l_ptr && l_ptr->flags1 & LF1_NO_GENO) return(FALSE);
4846
4847 bypass_invuln = TRUE;
4848
4849 /* Delete the (nearby) monsters */
4850 for (i = 1; i < m_max; i++) {
4851 monster_type *m_ptr = &m_list[i];
4852 monster_race *r_ptr = race_inf(m_ptr);
4853
4854 /* Paranoia -- Skip dead monsters */
4855 if (!m_ptr->r_idx) continue;
4856
4857 /* Skip monsters not on this depth */
4858 if (!inarea(wpos, &m_ptr->wpos)) continue;
4859
4860 /* Hack -- Skip unique monsters */
4861 if (r_ptr->flags1 & RF1_UNIQUE) continue;
4862
4863 /* Skip distant monsters */
4864 if (distance(y, x, m_ptr->fy, m_ptr->fx) > rad)
4865 #if 0
4866 if (m_ptr->cdis > MAX_SIGHT)
4867 #endif
4868 continue;
4869
4870 /* Skip those immune */
4871 if (r_ptr->flags9 & RF9_IM_TELE) continue;
4872
4873 /* Roll for resistance */
4874 tmp = r_ptr->level;
4875 #ifdef RESIST_GENO
4876 if (randint(RESIST_GENO) < tmp) continue;
4877 #endif // RESIST_GENO
4878
4879 #ifdef NO_GENO_ON_ICKY
4880 /* Not valid inside a vault */
4881 if (zcave[m_ptr->fy][m_ptr->fx].info & CAVE_ICKY && p_ptr && !p_ptr->admin_dm)
4882 continue;
4883 #endif // NO_GENO_ON_ICKY
4884
4885 /* Delete the monster */
4886 delete_monster_idx(i, TRUE);
4887
4888 /* Hack -- visual feedback */
4889 /* does not effect the dungeon master, because it disturbs his movement
4890 */
4891 if (p_ptr && !p_ptr->admin_dm) {
4892 take_hit(who, randint(3 + (tmp >> 3)), "the strain of casting Genocide", 0);
4893
4894 /* Redraw */
4895 p_ptr->redraw |= (PR_HP);
4896
4897 /* Window stuff */
4898 /* p_ptr->window |= (PW_PLAYER); */
4899
4900 /* Handle */
4901 handle_stuff(who);
4902
4903 /* Delay */
4904 //Send_flush(who); /* I don't think a delay is really necessary - mikaelh */
4905 }
4906
4907 /* Note effect */
4908 result = TRUE;
4909 }
4910
4911 if (p_ptr) {
4912 #ifdef SEVERE_GENO
4913 if (!p_ptr->death && result && !p_ptr->admin_dm) {
4914 take_hit(who, p_ptr->chp >> 1, "the strain of casting Genocide", 0);
4915
4916 /* Redraw */
4917 p_ptr->redraw |= (PR_HP);
4918 }
4919 #endif
4920
4921 /* Window stuff */
4922 p_ptr->window |= (PW_PLAYER);
4923
4924 /* Handle */
4925 handle_stuff(who);
4926 }
4927
4928 bypass_invuln = FALSE;
4929
4930 return (result);
4931 }
4932
4933
4934
4935 /*
4936 * Probe nearby monsters
4937 */
probing(int Ind)4938 bool probing(int Ind) {
4939 monster_type *m_ptr;
4940 monster_race *r_ptr;
4941 int i;
4942 player_type *p_ptr = Players[Ind];
4943 struct worldpos *wpos = &p_ptr->wpos;
4944 bool probe = FALSE;
4945
4946 /* Probe all (nearby) monsters */
4947 for (i = 1; i < m_max; i++) {
4948 m_ptr = &m_list[i];
4949 r_ptr = race_inf(m_ptr);
4950
4951 /* Paranoia -- Skip dead monsters */
4952 if (!m_ptr->r_idx) continue;
4953
4954 /* Skip monsters not on this depth */
4955 if (!inarea(&m_ptr->wpos, wpos)) continue;
4956
4957 /* Require line of sight */
4958 if (!player_has_los_bold(Ind, m_ptr->fy, m_ptr->fx)) continue;
4959
4960 /* Probe visible monsters */
4961 if (p_ptr->mon_vis[i]) {
4962 char m_name[MNAME_LEN];
4963 char buf[80];
4964 int j;
4965
4966 /* Start the message */
4967 if (!probe) msg_print(Ind, "Probing...");
4968
4969 /* Get "the monster" or "something" */
4970 monster_desc(Ind, m_name, i, 0x04);
4971 sprintf(buf, "blows");
4972
4973 for (j = 0; j < 4; j++)
4974 if (m_ptr->blow[j].d_dice) strcat(buf, format(" %dd%d", m_ptr->blow[j].d_dice, m_ptr->blow[j].d_side));
4975
4976 /* Describe the monster */
4977 if (r_ptr->flags7 & RF7_NO_DEATH)
4978 msg_format(Ind, "%^s (%d) has unknown hp, %d ac, %d speed.", m_name, m_ptr->level, m_ptr->ac, m_ptr->mspeed - 110);
4979 else
4980 msg_format(Ind, "%^s (%d) has %d hp, %d ac, %d speed.", m_name, m_ptr->level, m_ptr->hp, m_ptr->ac, m_ptr->mspeed - 110);
4981 /* include m_idx for admins */
4982 if (is_admin(p_ptr)) msg_format(Ind, "%^s (Lv%d,%d) %s.", m_name, m_ptr->level, i, buf);
4983 else msg_format(Ind, "%^s (Lv%d) %s.", m_name, m_ptr->level, buf);
4984
4985 /* Learn all of the non-spell, non-treasure flags */
4986 lore_do_probe(i);
4987
4988 /* Probe worked */
4989 probe = TRUE;
4990 }
4991 }
4992
4993 /* Done */
4994 if (probe) msg_print(Ind, "That's all.");
4995
4996 /* Result */
4997 return (probe);
4998 }
4999
5000
5001
5002 /*
5003 * The spell of destruction
5004 *
5005 * This spell "deletes" monsters (instead of "killing" them).
5006 *
5007 * Later we may use one function for both "destruction" and
5008 * "earthquake" by using the "full" to select "destruction".
5009 */
destroy_area(struct worldpos * wpos,int y1,int x1,int r,bool full,byte feat,int stun)5010 void destroy_area(struct worldpos *wpos, int y1, int x1, int r, bool full, byte feat, int stun) {
5011 int y, x, k, t, Ind;
5012 player_type *p_ptr;
5013 cave_type *c_ptr;
5014 /*bool flag = FALSE;*/
5015
5016 dun_level *l_ptr = getfloor(wpos);
5017 struct c_special *cs_ptr; /* for special key doors */
5018 cave_type **zcave;
5019
5020 if (!(zcave = getcave(wpos))) return;
5021 if(l_ptr && l_ptr->flags1 & LF1_NO_DESTROY) return;
5022
5023 /* among others, make sure town areas aren't affected.. */
5024 if (!allow_terraforming(wpos, FEAT_WALL_EXTRA)) return;
5025
5026 /* XXX XXX */
5027 full = full ? full : 0;
5028
5029 /* Set to default */
5030 feat = feat ? feat : FEAT_FLOOR;
5031
5032 /* Can't trigger within Vault? - note: this prevents exploit as well as death-_trap_ at once :) */
5033 if (zcave[y1][x1].info & CAVE_ICKY) return;
5034
5035 /* Big area of affect */
5036 for (y = (y1 - r); y <= (y1 + r); y++) {
5037 for (x = (x1 - r); x <= (x1 + r); x++) {
5038 /* Skip illegal grids */
5039 if (!in_bounds(y, x)) continue;
5040
5041 /* Extract the distance */
5042 k = distance(y1, x1, y, x);
5043
5044 /* Stay in the circle of death */
5045 if (k > r) continue;
5046
5047 /* Access the grid */
5048 c_ptr = &zcave[y][x];
5049
5050 /* Vault is protected */
5051 if (c_ptr->info & CAVE_ICKY) continue;
5052
5053 /* Special key doors are protected -C. Blue */
5054 if ((cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) continue;
5055
5056 /* Lose room and nest */
5057 /* Hack -- don't do this to houses/rooms outside the dungeon,
5058 * this will protect hosues outside town.
5059 */
5060 if(wpos->wz) {
5061 /* Lose room and nest */
5062 c_ptr->info &= ~(CAVE_ROOM | CAVE_NEST_PIT);
5063 }
5064
5065 /* Lose light and knowledge */
5066 c_ptr->info &= ~(CAVE_GLOW);
5067 everyone_forget_spot(wpos, y, x);
5068
5069 /* Hack -- Notice player affect */
5070 if (c_ptr->m_idx < 0) {
5071 Ind = 0 - c_ptr->m_idx;
5072 p_ptr = Players[Ind];
5073
5074 /* Message */
5075 msg_print(Ind, "\377oThere is a searing blast of light and a terrible shockwave!");
5076 #ifdef USE_SOUND_2010
5077 sound(Ind, "destruction", NULL, SFX_TYPE_MISC, FALSE);
5078 #endif
5079
5080 /* Blind the player */
5081 if (!p_ptr->resist_blind && !p_ptr->resist_lite) {
5082 /* Become blind */
5083 (void)set_blind(Ind, p_ptr->blind + 20 + randint(10));
5084 }
5085 (void)set_stun(Ind, stun); /* ~20s in NR, depends tho */
5086
5087 /* Mega-Hack -- Forget the view and lite */
5088 p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
5089
5090 /* Update stuff */
5091 p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW);
5092
5093 /* Update the monsters */
5094 p_ptr->update |= (PU_MONSTERS);
5095
5096 /* Redraw map */
5097 p_ptr->redraw |= (PR_MAP);
5098
5099 /* Window stuff */
5100 p_ptr->window |= (PW_OVERHEAD);
5101
5102 /* Do not hurt this grid */
5103 continue;
5104 }
5105
5106 /* Hack -- Skip the epicenter */
5107 if ((y == y1) && (x == x1)) continue;
5108
5109 /* Delete the monster (if any) */
5110 if (c_ptr->m_idx > 0) {
5111 monster_race *r_ptr = race_inf(&m_list[c_ptr->m_idx]);
5112 if (!(r_ptr->flags9 & RF9_IM_TELE)) delete_monster(wpos, y, x, TRUE);
5113 else continue;
5114 }
5115
5116 /* Destroy "valid" grids */
5117 // if ((cave_valid_bold(zcave, y, x)) && !(c_ptr->info&CAVE_ICKY))
5118 if (cave_valid_bold(zcave, y, x)) {
5119 struct c_special *cs_ptr;
5120 /* Delete the object (if any) */
5121 delete_object(wpos, y, x, TRUE);
5122
5123 /* Wall (or floor) type */
5124 t = rand_int(200);
5125
5126 if ((cs_ptr = GetCS(c_ptr, CS_TRAPS))) {
5127 /* Destroy the trap */
5128 if (t < 100) cs_erase(c_ptr, cs_ptr);
5129 else cs_ptr->sc.trap.found = FALSE;
5130
5131 /* Redraw */
5132 // everyone_lite_spot(wpos, y, x);
5133 }
5134
5135 /* Granite */
5136 if (t < 20) {
5137 /* Create granite wall */
5138 cave_set_feat_live(wpos, y, x, FEAT_WALL_EXTRA);
5139 }
5140
5141 /* Quartz */
5142 else if (t < 70) {
5143 /* Create quartz vein */
5144 cave_set_feat_live(wpos, y, x, FEAT_QUARTZ);
5145 }
5146
5147 /* Magma */
5148 else if (t < 100) {
5149 /* Create magma vein */
5150 cave_set_feat_live(wpos, y, x, FEAT_MAGMA);
5151 }
5152
5153 /* Floor */
5154 else {
5155 /* Create floor or whatever specified */
5156 cave_set_feat_live(wpos, y, x, feat);
5157 }
5158 }
5159 }
5160 }
5161 for (k = 1; k <= NumPlayers; k++) {
5162 if (inarea(wpos, &Players[k]->wpos) &&
5163 Players[k]->stun < stun) {
5164 msg_print(k, "\377oYou are hit by a terrible shockwave!");
5165 (void)set_stun(k, stun - (distance(Players[k]->py, Players[k]->px, y1, x1) - r) / 3);
5166 }
5167 }
5168 }
5169
5170
5171 /*
5172 * Induce an "earthquake" of the given radius at the given location.
5173 *
5174 * This will turn some walls into floors and some floors into walls.
5175 *
5176 * The player will take damage and "jump" into a safe grid if possible,
5177 * otherwise, he will "tunnel" through the rubble instantaneously.
5178 *
5179 * Monsters will take damage, and "jump" into a safe grid if possible,
5180 * otherwise they will be "buried" in the rubble, disappearing from
5181 * the level in the same way that they do when genocided.
5182 *
5183 * Note that thus the player and monsters (except eaters of walls and
5184 * passers through walls) will never occupy the same grid as a wall.
5185 * Note that as of now (2.7.8) no monster may occupy a "wall" grid, even
5186 * for a single turn, unless that monster can pass_walls or kill_walls.
5187 * This has allowed massive simplification of the "monster" code.
5188 */
earthquake(struct worldpos * wpos,int cy,int cx,int r)5189 void earthquake(struct worldpos *wpos, int cy, int cx, int r) {
5190 int i, t, y, x, yy, xx, dy, dx, oy, ox;
5191 int damage = 0;
5192 int sn = 0, sy = 0, sx = 0;
5193 int Ind;
5194 player_type *p_ptr;
5195 /*bool hurt = FALSE;*/
5196 cave_type *c_ptr;
5197 bool map[32][32];
5198 dun_level *l_ptr = getfloor(wpos);
5199 struct c_special *cs_ptr; /* for special key doors */
5200 cave_type **zcave;
5201
5202 if (!(zcave = getcave(wpos))) return;
5203 if(l_ptr && (l_ptr->flags1 & LF1_NO_DESTROY) && !override_LF1_NO_DESTROY) return;
5204 override_LF1_NO_DESTROY = FALSE;
5205
5206 /* among others, make sure town areas aren't affected.. */
5207 if (!allow_terraforming(wpos, FEAT_WALL_EXTRA)) return;
5208
5209 /* Paranoia -- Dnforce maximum range */
5210 if (r > 12) r = 12;
5211
5212 /* Clear the "maximal blast" area */
5213 for (y = 0; y < 32; y++) {
5214 for (x = 0; x < 32; x++) {
5215 map[y][x] = FALSE;
5216 }
5217 }
5218
5219 /* No one has taken any damage from this earthquake yet - mikaelh */
5220 for (Ind = 1; Ind <= NumPlayers; Ind++)
5221 Players[Ind]->total_damage = 0;
5222
5223 /* Check around the epicenter */
5224 for (dy = -r; dy <= r; dy++) {
5225 for (dx = -r; dx <= r; dx++) {
5226 /* Extract the location */
5227 yy = cy + dy;
5228 xx = cx + dx;
5229
5230 /* Skip illegal grids */
5231 if (!in_bounds(yy, xx)) continue;
5232
5233 /* Skip distant grids */
5234 if (distance(cy, cx, yy, xx) > r) continue;
5235
5236 /* Access the grid */
5237 c_ptr = &zcave[yy][xx];
5238
5239 /* Hack -- ICKY spaces are protected outside of the dungeon */
5240 if ((!wpos->wz) && (c_ptr->info & CAVE_ICKY)) continue;
5241
5242 /* Special key doors are protected -C. Blue */
5243 if ((cs_ptr = GetCS(c_ptr, CS_KEYDOOR))) continue;
5244
5245 #if 0 /* noticed this at 10.jan 2009, if'0ed it, and added below else branch,
5246 since it allows teleportation within vaults! - C. Blue */
5247 /* note: this miiiight be ok for non-no_tele vaults, or if no_tele is also removed, and if
5248 additionally the vault wasn't build from perma-walls, so the walls actually got quaked away too;
5249 for that, also check 'cave_valid_bold' check used to actually destroy grids (further below). */
5250
5251 /* Lose room and vault and nest */
5252 c_ptr->info &= ~(CAVE_ROOM | CAVE_NEST_PIT | CAVE_ICKY | CAVE_STCK);
5253
5254 #else /* keep preventing teleport from targetting a space inside the (quaked) vault */
5255 /* Lose room and nest */
5256 c_ptr->info &= ~(CAVE_ROOM | CAVE_NEST_PIT);
5257
5258 #if 0 /* addition mentioned above, but maybe bad idea? */
5259 if (!(c_ptr->info & (CAVE_ICKY_PERMA | CAVE_STCK))) c_ptr->info &= ~CAVE_ICKY;
5260 #endif
5261 #endif
5262
5263 /* Lose light */
5264 c_ptr->info &= ~(CAVE_GLOW);
5265
5266 /* This can be really annoying and frustrating - mikaelh */
5267 // everyone_forget_spot(wpos, y, x);
5268 everyone_lite_spot(wpos, y, x);
5269
5270 #ifdef USE_SOUND_2010
5271 if (c_ptr->m_idx < 0) sound(-c_ptr->m_idx, "earthquake", NULL, SFX_TYPE_NO_OVERLAP, FALSE);
5272 #endif
5273
5274 /* Skip the epicenter */
5275 if ((!dx && !dy) && r) continue;
5276
5277 /* Skip most grids */
5278 if (rand_int(100) < 85) continue;
5279
5280 /* Damage this grid */
5281 map[16 + yy - cy][16 + xx - cx] = TRUE;
5282
5283 /* Hack -- Take note of player damage */
5284 if (c_ptr->m_idx < 0) {
5285 Ind = 0 - c_ptr->m_idx;
5286 p_ptr = Players[Ind];
5287 store_exit(Ind);
5288
5289 sn = 0;
5290
5291 /* Check around the player */
5292 for (i = 0; i < 8; i++) {
5293 /* Access the location */
5294 y = p_ptr->py + ddy[i];
5295 x = p_ptr->px + ddx[i];
5296
5297 /* Skip non-empty grids */
5298 if (!cave_empty_bold(zcave, y, x)) continue;
5299
5300 /* Important -- Skip "quake" grids */
5301 if (map[16+y-cy][16+x-cx]) continue;
5302
5303 /* Count "safe" grids */
5304 sn++;
5305
5306 /* Randomize choice */
5307 if (rand_int(sn) > 0) continue;
5308
5309 /* Save the safe location */
5310 sy = y; sx = x;
5311 }
5312
5313 /* Random message */
5314 switch (randint(3)) {
5315 case 1:
5316 msg_print(Ind, "The cave ceiling collapses!");
5317 break;
5318 case 2:
5319 msg_print(Ind, "The cave floor twists in an unnatural way!");
5320 break;
5321 default:
5322 msg_print(Ind, "The cave quakes! You are pummeled with debris!");
5323 break;
5324 }
5325
5326 /* Hurt the player a lot */
5327 if (!sn) {
5328 /* Message and damage */
5329 damage = 300;
5330 if (get_skill(p_ptr, SKILL_EARTH) >= 45) damage /= 2;
5331 /* Cap the damage - mikaelh */
5332 if (damage + p_ptr->total_damage > 300) {
5333 damage = 300 - p_ptr->total_damage;
5334 }
5335 if (damage) msg_format(Ind, "You are severely crushed for \377o%d\377w damage!", damage);
5336
5337 /* Stun only once - mikaelh */
5338 if (p_ptr->total_damage == 0) {
5339 (void)set_stun(Ind, p_ptr->stun + randint(40));
5340 }
5341 }
5342
5343 /* Destroy the grid, and push the player to safety */
5344 else {
5345 /* Calculate results */
5346 switch (randint(3) - (magik((p_ptr->dodge_level * 3) / 4) ? 1 : 0) - (p_ptr->shadow_running ? 1 : 0)) {
5347 case -1:
5348 case 0:
5349 case 1:
5350 damage = 0;
5351 msg_format(Ind, "\377%cYou nimbly dodge the blast and take no damage!", COLOUR_DODGE_GOOD);
5352 break;
5353 case 2:
5354 damage = damroll(10, 4);
5355 if (get_skill(p_ptr, SKILL_EARTH) >= 45) damage /= 2;
5356 /* Cap the damage - mikaelh */
5357 if (damage + p_ptr->total_damage > 300)
5358 damage = 300 - p_ptr->total_damage;
5359 if (damage)
5360 msg_format(Ind, "You are bashed by rubble for \377o%d\377w damage!", damage);
5361
5362 /* Stun only once - mikaelh */
5363 if (p_ptr->total_damage == 0) {
5364 (void)set_stun(Ind, p_ptr->stun + randint(33));
5365 }
5366 break;
5367 case 3:
5368 damage = damroll(30, 4);
5369 if (get_skill(p_ptr, SKILL_EARTH) >= 45) damage /= 2;
5370 /* Cap the damage - mikaelh */
5371 if (damage + p_ptr->total_damage > 300)
5372 damage = 300 - p_ptr->total_damage;
5373 if (damage)
5374 msg_format(Ind, "You are crushed between the floor and ceiling for \377o%d\377w damage!", damage);
5375
5376 /* Stun only once - mikaelh */
5377 if (p_ptr->total_damage == 0)
5378 (void)set_stun(Ind, p_ptr->stun + randint(33));
5379 break;
5380 }
5381
5382 /* Save the old location */
5383 oy = p_ptr->py;
5384 ox = p_ptr->px;
5385
5386 /* Move the player to the safe location */
5387 p_ptr->py = sy;
5388 p_ptr->px = sx;
5389
5390 /* Update the cave player indices */
5391 zcave[oy][ox].m_idx = 0;
5392 zcave[sy][sx].m_idx = 0 - Ind;
5393 cave_midx_debug(wpos, sy, sx, -Ind);
5394
5395 /* Redraw the old spot */
5396 everyone_lite_spot(wpos, oy, ox);
5397
5398 /* Redraw the new spot */
5399 everyone_lite_spot(wpos, p_ptr->py, p_ptr->px);
5400
5401 /* Check for new panel */
5402 verify_panel(Ind);
5403 }
5404
5405 /* Important -- no wall on player */
5406 map[16 + p_ptr->py - cy][16 + p_ptr->px - cx] = FALSE;
5407
5408 /* Take some damage */
5409 if (damage) {
5410 take_hit(Ind, damage, "an earthquake", 0);
5411
5412 /* Add it tot the total damage taken - mikaelh */
5413 p_ptr->total_damage += damage;
5414 }
5415
5416 /* Mega-Hack -- Forget the view and lite */
5417 p_ptr->update |= (PU_UN_VIEW | PU_UN_LITE);
5418
5419 /* Update stuff */
5420 p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW);
5421
5422 /* Update the monsters */
5423 p_ptr->update |= (PU_DISTANCE);
5424
5425 /* Update the health bar */
5426 p_ptr->redraw |= (PR_HEALTH);
5427
5428 /* Redraw map */
5429 p_ptr->redraw |= (PR_MAP);
5430
5431 /* Window stuff */
5432 p_ptr->window |= (PW_OVERHEAD);
5433 }
5434 }
5435 }
5436
5437
5438 /* Examine the quaked region */
5439 for (dy = -r; dy <= r; dy++) {
5440 for (dx = -r; dx <= r; dx++) {
5441 /* Extract the location */
5442 yy = cy + dy;
5443 xx = cx + dx;
5444
5445 /* Skip unaffected grids */
5446 if (!map[16 + yy - cy][16 + xx - cx]) continue;
5447
5448 /* Access the grid */
5449 c_ptr = &zcave[yy][xx];
5450
5451 /* Process monsters */
5452 if (c_ptr->m_idx > 0) {
5453 monster_type *m_ptr = &m_list[c_ptr->m_idx];
5454 monster_race *r_ptr = race_inf(m_ptr);
5455
5456 /* Most monsters cannot co-exist with rock */
5457 if (!(r_ptr->flags2 & RF2_KILL_WALL) &&
5458 !(r_ptr->flags2 & RF2_PASS_WALL)) {
5459 /* Assume not safe */
5460 sn = 0;
5461
5462 /* Monster can move to escape the wall */
5463 if (!(r_ptr->flags1 & RF1_NEVER_MOVE)) {
5464 /* Look for safety */
5465 for (i = 0; i < 8; i++) {
5466 /* Access the grid */
5467 y = yy + ddy[i];
5468 x = xx + ddx[i];
5469
5470 /* Skip non-empty grids */
5471 if (!cave_empty_bold(zcave, y, x)) continue;
5472
5473 /* Hack -- no safety on glyph of warding */
5474 if (zcave[y][x].feat == FEAT_GLYPH) continue;
5475 if (zcave[y][x].feat == FEAT_RUNE) continue;
5476
5477 /* Important -- Skip "quake" grids */
5478 if (map[16 + y - cy][16 + x - cx]) continue;
5479
5480 /* Count "safe" grids */
5481 sn++;
5482
5483 /* Randomize choice */
5484 if (rand_int(sn) > 0) continue;
5485
5486 /* Save the safe grid */
5487 sy = y; sx = x;
5488 }
5489 }
5490
5491 /* Describe the monster */
5492 /*monster_desc(Ind, m_name, c_ptr->m_idx, 0);*/
5493
5494 /* Scream in pain */
5495 /*msg_format("%^s wails out in pain!", m_name);*/
5496
5497 /* Take damage from the quake */
5498 damage = (sn ? damroll(4, 8) : 200);
5499
5500 /* Monster is certainly awake */
5501 m_ptr->csleep = 0;
5502
5503 /* Apply damage directly */
5504 m_ptr->hp -= damage;
5505
5506 /* Delete (not kill) "dead" monsters */
5507 if (m_ptr->hp < 0) {
5508 /* Message */
5509 /*msg_format("%^s is embedded in the rock!", m_name);*/
5510
5511 /* Delete the monster */
5512 delete_monster(wpos, yy, xx, TRUE);
5513
5514 /* No longer safe */
5515 sn = 0;
5516 }
5517
5518 /* Hack -- Escape from the rock */
5519 if (sn) {
5520 int m_idx = zcave[yy][xx].m_idx;
5521
5522 /* Update the new location */
5523 zcave[sy][sx].m_idx = m_idx;
5524
5525 /* Update the old location */
5526 zcave[yy][xx].m_idx = 0;
5527
5528 /* Move the monster */
5529 m_ptr->fy = sy;
5530 m_ptr->fx = sx;
5531
5532 /* Update the monster (new location) */
5533 update_mon(m_idx, TRUE);
5534
5535 /* Redraw the new grid */
5536 everyone_lite_spot(wpos, yy, xx);
5537
5538 /* Redraw the new grid */
5539 everyone_lite_spot(wpos, sy, sx);
5540 }
5541 }
5542 }
5543 }
5544 }
5545
5546
5547 /* Examine the quaked region */
5548 for (dy = -r; dy <= r; dy++) {
5549 for (dx = -r; dx <= r; dx++) {
5550 /* Extract the location */
5551 yy = cy + dy;
5552 xx = cx + dx;
5553
5554 /* Skip unaffected grids */
5555 if (!map[16+yy-cy][16+xx-cx]) continue;
5556
5557 /* Access the cave grid */
5558 c_ptr = &zcave[yy][xx];
5559
5560 /* Paranoia -- never affect player */
5561 if (c_ptr->m_idx < 0) continue;
5562
5563 /* Destroy location (if valid) */
5564 if (cave_valid_bold(zcave, yy, xx)) {
5565 bool floor = cave_floor_bold(zcave, yy, xx);
5566
5567 /* Delete any object that is still there */
5568 delete_object(wpos, yy, xx, TRUE);
5569
5570 /* Wall (or floor) type */
5571 t = (floor ? rand_int(100) : 200);
5572
5573 /* Granite */
5574 if (t < 20)
5575 /* Create granite wall */
5576 cave_set_feat_live(wpos, yy, xx, FEAT_WALL_EXTRA);
5577
5578 /* Quartz */
5579 else if (t < 70)
5580 /* Create quartz vein */
5581 cave_set_feat_live(wpos, yy, xx, FEAT_QUARTZ);
5582
5583 /* Magma */
5584 else if (t < 100)
5585 /* Create magma vein */
5586 cave_set_feat_live(wpos, yy, xx, FEAT_MAGMA);
5587
5588 /* Floor */
5589 else
5590 /* Create floor */
5591 //uses static array set in generate.c, fix! place_floor_live(wpos, yy, xx);
5592 cave_set_feat_live(wpos, yy, xx, FEAT_FLOOR);
5593 }
5594 }
5595 }
5596 }
5597
5598 /* Wipe everything */
wipe_spell(struct worldpos * wpos,int cy,int cx,int r)5599 void wipe_spell(struct worldpos *wpos, int cy, int cx, int r) {
5600 int yy, xx, dy, dx;
5601 cave_type *c_ptr;
5602
5603 cave_type **zcave;
5604 if(!(zcave = getcave(wpos))) return;
5605 /* Don't hurt town or surrounding areas */
5606 if(istownarea(wpos, MAX_TOWNAREA)) return;
5607
5608 /* Paranoia -- Dnforce maximum range */
5609 if (r > 12) r = 12;
5610
5611 /* Check around the epicenter */
5612 for (dy = -r; dy <= r; dy++) {
5613 for (dx = -r; dx <= r; dx++) {
5614 /* Extract the location */
5615 yy = cy + dy;
5616 xx = cx + dx;
5617
5618 /* Skip illegal grids */
5619 if (!in_bounds(yy, xx)) continue;
5620
5621 /* Skip distant grids */
5622 if (distance(cy, cx, yy, xx) > r) continue;
5623
5624 /* Access the grid */
5625 c_ptr = &zcave[yy][xx];
5626
5627 /* Hack -- ICKY spaces are protected outside of the dungeon */
5628 if (c_ptr->info & CAVE_ICKY) continue;
5629
5630 /* Lose room and vault */
5631 c_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_NEST_PIT | CAVE_STCK | CAVE_ICKY_PERMA);
5632
5633 /* Turn into basic floor */
5634 cave_set_feat(wpos, yy, xx, FEAT_FLOOR);
5635
5636 /* Delete monsters */
5637 if (c_ptr->m_idx > 0) {
5638 monster_race *r_ptr = race_inf(&m_list[c_ptr->m_idx]);
5639 if (!(r_ptr->flags9 & RF9_IM_TELE)) delete_monster(wpos, yy, xx, TRUE);
5640 else continue;
5641 }
5642
5643 /* Delete objects */
5644 delete_object(wpos, yy, xx, TRUE);
5645
5646 everyone_lite_spot(wpos, yy, xx);
5647 }
5648 }
5649 }
5650
5651
5652 /*
5653 * This routine clears the entire "temp" set.
5654 *
5655 * This routine will Perma-Lite all "temp" grids.
5656 *
5657 * This routine is used (only) by "lite_room()"
5658 *
5659 * Dark grids are illuminated.
5660 *
5661 * Also, process all affected monsters.
5662 *
5663 * SMART monsters always wake up when illuminated
5664 * NORMAL monsters wake up 1/4 the time when illuminated
5665 * STUPID monsters wake up 1/10 the time when illuminated
5666 */
cave_temp_room_lite(int Ind)5667 static void cave_temp_room_lite(int Ind)
5668 {
5669 player_type *p_ptr = Players[Ind];
5670 int i;
5671 struct worldpos *wpos = &p_ptr->wpos;
5672 cave_type **zcave;
5673 if (!(zcave = getcave(wpos))) return;
5674
5675 /* Clear them all */
5676 for (i = 0; i < p_ptr->temp_n; i++)
5677 {
5678 int y = p_ptr->temp_y[i];
5679 int x = p_ptr->temp_x[i];
5680
5681 cave_type *c_ptr = &zcave[y][x];
5682
5683 /* No longer in the array */
5684 c_ptr->info &= ~CAVE_TEMP;
5685
5686 /* Update only non-CAVE_GLOW grids */
5687 /* if (c_ptr->info & CAVE_GLOW) continue; */
5688
5689 /* Perma-Lite */
5690 c_ptr->info |= CAVE_GLOW;
5691
5692 /* Process affected monsters */
5693 if (c_ptr->m_idx > 0)
5694 {
5695 int chance = 25;
5696
5697 monster_type *m_ptr = &m_list[c_ptr->m_idx];
5698
5699 monster_race *r_ptr = race_inf(m_ptr);
5700
5701 /* Update the monster */
5702 update_mon(c_ptr->m_idx, FALSE);
5703
5704 /* Stupid monsters rarely wake up */
5705 if (r_ptr->flags2 & RF2_STUPID) chance = 10;
5706
5707 /* Smart monsters always wake up */
5708 if (r_ptr->flags2 & RF2_SMART) chance = 100;
5709
5710 /* Sometimes monsters wake up */
5711 if (m_ptr->csleep && (rand_int(100) < chance))
5712 {
5713 /* Wake up! */
5714 m_ptr->csleep = 0;
5715
5716 /* Notice the "waking up" */
5717 if (p_ptr->mon_vis[c_ptr->m_idx])
5718 {
5719 char m_name[MNAME_LEN];
5720
5721 /* Acquire the monster name */
5722 monster_desc(Ind, m_name, c_ptr->m_idx, 0);
5723
5724 /* Dump a message */
5725 msg_format(Ind, "%^s wakes up.", m_name);
5726 }
5727 }
5728 }
5729
5730 /* Note */
5731 note_spot_depth(wpos, y, x);
5732
5733 /* Redraw */
5734 everyone_lite_spot(wpos, y, x);
5735 }
5736
5737 /* None left */
5738 p_ptr->temp_n = 0;
5739 }
5740
5741
5742
5743 /*
5744 * This routine clears the entire "temp" set.
5745 *
5746 * This routine will "darken" all "temp" grids.
5747 *
5748 * In addition, some of these grids will be "unmarked".
5749 *
5750 * This routine is used (only) by "unlite_room()"
5751 *
5752 * Also, process all affected monsters
5753 */
cave_temp_room_unlite(int Ind)5754 static void cave_temp_room_unlite(int Ind)
5755 {
5756 player_type *p_ptr = Players[Ind];
5757 int i;
5758 struct worldpos *wpos = &p_ptr->wpos;
5759 cave_type **zcave;
5760 if (!(zcave = getcave(wpos))) return;
5761
5762 /* Clear them all */
5763 for (i = 0; i < p_ptr->temp_n; i++)
5764 {
5765 int y = p_ptr->temp_y[i];
5766 int x = p_ptr->temp_x[i];
5767
5768 cave_type *c_ptr = &zcave[y][x];
5769
5770 /* No longer in the array */
5771 c_ptr->info &= ~CAVE_TEMP;
5772
5773 /* Darken the grid */
5774 c_ptr->info &= ~CAVE_GLOW;
5775
5776 /* Hack -- Forget "boring" grids */
5777 // if (c_ptr->feat <= FEAT_INVIS)
5778 if (cave_plain_floor_grid(c_ptr))
5779 {
5780 /* Forget the grid */
5781 p_ptr->cave_flag[y][x] &= ~CAVE_MARK;
5782
5783 /* Notice */
5784 note_spot_depth(wpos, y, x);
5785 }
5786
5787 /* Process affected monsters */
5788 if (c_ptr->m_idx > 0)
5789 {
5790 /* Update the monster */
5791 update_mon(c_ptr->m_idx, FALSE);
5792 }
5793
5794 /* Redraw */
5795 everyone_lite_spot(wpos, y, x);
5796 }
5797
5798 /* None left */
5799 p_ptr->temp_n = 0;
5800 }
5801
5802
5803
5804
5805 /*
5806 * Aux function -- see below
5807 */
cave_temp_room_aux(int Ind,struct worldpos * wpos,int y,int x)5808 static void cave_temp_room_aux(int Ind, struct worldpos *wpos, int y, int x)
5809 {
5810 player_type *p_ptr = Players[Ind];
5811
5812 cave_type *c_ptr;
5813 cave_type **zcave;
5814 if (!(zcave = getcave(wpos))) return;
5815 c_ptr = &zcave[y][x];
5816
5817 /* Avoid infinite recursion */
5818 if (c_ptr->info & CAVE_TEMP) return;
5819
5820 /* Do not "leave" the current room */
5821 if (!(c_ptr->info & CAVE_ROOM)) return;
5822
5823 /* Paranoia -- verify space */
5824 if (p_ptr->temp_n == TEMP_MAX) return;
5825
5826 /* Mark the grid as "seen" */
5827 c_ptr->info |= CAVE_TEMP;
5828
5829 /* Add it to the "seen" set */
5830 p_ptr->temp_y[p_ptr->temp_n] = y;
5831 p_ptr->temp_x[p_ptr->temp_n] = x;
5832 p_ptr->temp_n++;
5833 }
5834
5835
5836
5837
5838 /*
5839 * Illuminate any room containing the given location.
5840 */
lite_room(int Ind,struct worldpos * wpos,int y1,int x1)5841 void lite_room(int Ind, struct worldpos *wpos, int y1, int x1)
5842 {
5843 player_type *p_ptr = Players[Ind];
5844
5845 int i, x, y;
5846
5847 cave_type **zcave;
5848 if (!(zcave = getcave(wpos))) return;
5849
5850 /* Add the initial grid */
5851 cave_temp_room_aux(Ind, wpos, y1, x1);
5852
5853 /* While grids are in the queue, add their neighbors */
5854 for (i = 0; i < p_ptr->temp_n; i++)
5855 {
5856 x = p_ptr->temp_x[i], y = p_ptr->temp_y[i];
5857
5858 /* Walls get lit, but stop light */
5859 if (!cave_floor_bold(zcave, y, x)) continue;
5860
5861 /* Spread adjacent */
5862 cave_temp_room_aux(Ind, wpos, y + 1, x);
5863 cave_temp_room_aux(Ind, wpos, y - 1, x);
5864 cave_temp_room_aux(Ind, wpos, y, x + 1);
5865 cave_temp_room_aux(Ind, wpos, y, x - 1);
5866
5867 /* Spread diagonal */
5868 cave_temp_room_aux(Ind, wpos, y + 1, x + 1);
5869 cave_temp_room_aux(Ind, wpos, y - 1, x - 1);
5870 cave_temp_room_aux(Ind, wpos, y - 1, x + 1);
5871 cave_temp_room_aux(Ind, wpos, y + 1, x - 1);
5872 }
5873
5874 /* Now, lite them all up at once */
5875 cave_temp_room_lite(Ind);
5876 }
5877
5878
5879 /*
5880 * Darken all rooms containing the given location
5881 */
unlite_room(int Ind,struct worldpos * wpos,int y1,int x1)5882 void unlite_room(int Ind, struct worldpos *wpos, int y1, int x1)
5883 {
5884 player_type *p_ptr = Players[Ind];
5885
5886 int i, x, y;
5887
5888 cave_type **zcave;
5889 if (!(zcave = getcave(wpos))) return;
5890
5891 /* Add the initial grid */
5892 cave_temp_room_aux(Ind, wpos, y1, x1);
5893
5894 /* Spread, breadth first */
5895 for (i = 0; i < p_ptr->temp_n; i++)
5896 {
5897 x = p_ptr->temp_x[i], y = p_ptr->temp_y[i];
5898
5899 /* Walls get dark, but stop darkness */
5900 if (!cave_floor_bold(zcave, y, x)) continue;
5901
5902 /* Spread adjacent */
5903 cave_temp_room_aux(Ind, wpos, y + 1, x);
5904 cave_temp_room_aux(Ind, wpos, y - 1, x);
5905 cave_temp_room_aux(Ind, wpos, y, x + 1);
5906 cave_temp_room_aux(Ind, wpos, y, x - 1);
5907
5908 /* Spread diagonal */
5909 cave_temp_room_aux(Ind, wpos, y + 1, x + 1);
5910 cave_temp_room_aux(Ind, wpos, y - 1, x - 1);
5911 cave_temp_room_aux(Ind, wpos, y - 1, x + 1);
5912 cave_temp_room_aux(Ind, wpos, y + 1, x - 1);
5913 }
5914
5915 /* Now, darken them all at once */
5916 cave_temp_room_unlite(Ind);
5917 }
5918
5919
5920
5921 /*
5922 * Hack -- call light around the player
5923 * Affect all monsters in the projection radius
5924 */
lite_area(int Ind,int dam,int rad)5925 bool lite_area(int Ind, int dam, int rad) {
5926 player_type *p_ptr = Players[Ind];
5927
5928 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_KILL | PROJECT_NODO | PROJECT_NODF;
5929
5930 /* WRAITHFORM reduces damage/effect! */
5931 if (p_ptr->tim_wraith) proj_dam_wraith(GF_LITE_WEAK, &dam);
5932
5933 /* Hack -- Message */
5934 if (!p_ptr->blind)
5935 msg_print(Ind, "You are surrounded by a white light.");
5936
5937 /* Hook into the "project()" function */
5938 (void)project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, dam, GF_LITE_WEAK, flg, "");
5939
5940 /* Lite up the room */
5941 lite_room(Ind, &p_ptr->wpos, p_ptr->py, p_ptr->px);
5942
5943 /* Assume seen */
5944 return (TRUE);
5945 }
5946
5947
5948 /*
5949 * Hack -- call darkness around the player
5950 * Affect all monsters in the projection radius
5951 */
unlite_area(int Ind,int dam,int rad)5952 bool unlite_area(int Ind, int dam, int rad)
5953 {
5954 player_type *p_ptr = Players[Ind];
5955
5956 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_KILL | PROJECT_NODO | PROJECT_NODF;
5957
5958 /* WRAITHFORM reduces damage/effect! */
5959 if (p_ptr->tim_wraith) proj_dam_wraith(GF_DARK_WEAK, &dam);
5960
5961 /* Hack -- Message */
5962 if (!p_ptr->blind)
5963 {
5964 msg_print(Ind, "Darkness surrounds you.");
5965 }
5966
5967 /* Hook into the "project()" function */
5968 (void)project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, dam, GF_DARK_WEAK, flg, "");
5969
5970 /* Lite up the room */
5971 unlite_room(Ind, &p_ptr->wpos, p_ptr->py, p_ptr->px);
5972
5973 /* Assume seen */
5974 return (TRUE);
5975 }
5976
5977
5978
5979 /*
5980 * Cast a ball spell
5981 * Stop if we hit a monster, act as a "ball"
5982 * Allow "target" mode to pass over monsters
5983 * Affect grids, objects, and monsters
5984 */
fire_ball(int Ind,int typ,int dir,int dam,int rad,char * attacker)5985 bool fire_ball(int Ind, int typ, int dir, int dam, int rad, char *attacker)
5986 {
5987 player_type *p_ptr = Players[Ind];
5988 char pattacker[80];
5989 int tx, ty;
5990
5991 int flg = PROJECT_NORF | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_NODO;
5992
5993 /* WRAITHFORM reduces damage/effect */
5994 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
5995
5996 /* Use the given direction */
5997 tx = p_ptr->px + 99 * ddx[dir];
5998 ty = p_ptr->py + 99 * ddy[dir];
5999
6000 /* Hack -- Use an actual "target" */
6001 if ((dir == 5) && target_okay(Ind)) {
6002 flg &= ~PROJECT_STOP;
6003 tx = p_ptr->target_col;
6004 ty = p_ptr->target_row;
6005 }
6006 #if 1
6007 #ifdef USE_SOUND_2010
6008 if (typ == GF_ROCKET) sound(Ind, "rocket", NULL, SFX_TYPE_COMMAND, FALSE);
6009 else if (typ == GF_DETONATION) sound(Ind, "detonation", NULL, SFX_TYPE_COMMAND, FALSE);
6010 else if (typ == GF_STONE_WALL) sound(Ind, "stone_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6011 else {
6012 /* The 'cast_ball' sound is only for attack spells */
6013 if ((typ != GF_HEAL_PLAYER) && (typ != GF_AWAY_ALL) &&
6014 (typ != GF_WRAITH_PLAYER) && (typ != GF_SPEED_PLAYER) &&
6015 (typ != GF_SHIELD_PLAYER) && (typ != GF_RECALL_PLAYER) &&
6016 (typ != GF_BLESS_PLAYER) && (typ != GF_REMFEAR_PLAYER) &&
6017 (typ != GF_REMCONF_PLAYER) && (typ != GF_REMIMAGE_PLAYER) &&
6018 (typ != GF_SATHUNGER_PLAYER) && (typ != GF_RESFIRE_PLAYER) &&
6019 (typ != GF_RESCOLD_PLAYER) && (typ != GF_CUREPOISON_PLAYER) &&
6020 (typ != GF_SEEINVIS_PLAYER) && (typ != GF_SEEMAP_PLAYER) &&
6021 (typ != GF_CURECUT_PLAYER) && (typ != GF_CURESTUN_PLAYER) &&
6022 (typ != GF_DETECTCREATURE_PLAYER) && (typ != GF_DETECTDOOR_PLAYER) &&
6023 (typ != GF_DETECTTRAP_PLAYER) && (typ != GF_TELEPORTLVL_PLAYER) &&
6024 (typ != GF_RESPOIS_PLAYER) && (typ != GF_RESELEC_PLAYER) &&
6025 (typ != GF_RESACID_PLAYER) && (typ != GF_HPINCREASE_PLAYER) &&
6026 (typ != GF_HERO_PLAYER) && (typ != GF_SHERO_PLAYER) &&
6027 (typ != GF_TELEPORT_PLAYER) && (typ != GF_ZEAL_PLAYER) &&
6028 (typ != GF_RESTORE_PLAYER) && (typ != GF_REMCURSE_PLAYER) &&
6029 (typ != GF_CURE_PLAYER) && (typ != GF_RESURRECT_PLAYER) &&
6030 (typ != GF_SANITY_PLAYER) && (typ != GF_SOULCURE_PLAYER) &&
6031 (typ != GF_OLD_HEAL) && (typ != GF_OLD_SPEED) && (typ != GF_PUSH) &&
6032 (typ != GF_HEALINGCLOUD) && /* Also not a hostile spell */
6033 (typ != GF_MINDBOOST_PLAYER) && (typ != GF_IDENTIFY) &&
6034 (typ != GF_SLOWPOISON_PLAYER) && (typ != GF_CURING) &&
6035 (typ != GF_OLD_POLY)) /* Non-hostile players may polymorph each other */
6036 if (p_ptr->sfx_magicattack) sound(Ind, "cast_ball", NULL, SFX_TYPE_COMMAND, TRUE);
6037 }
6038 #endif
6039 #endif
6040 /* Analyze the "dir" and the "target". Hurt items on floor. */
6041 snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6042
6043 /* affect self + players + monsters AND give credit on kill */
6044 flg = mod_ball_spell_flags(typ, flg);
6045 return (project(0 - Ind, rad, &p_ptr->wpos, ty, tx, dam, typ, flg, pattacker));
6046 }
6047
6048 /*
6049 * Cast a full ball spell
6050 * Stop if we hit a monster, act as a "ball"
6051 * Allow "target" mode to pass over monsters
6052 * Affect grids, objects, and monsters
6053 */
fire_full_ball(int Ind,int typ,int dir,int dam,int rad,char * attacker)6054 bool fire_full_ball(int Ind, int typ, int dir, int dam, int rad, char *attacker) {
6055 player_type *p_ptr = Players[Ind];
6056 char pattacker[80];
6057 int tx, ty;
6058
6059 int flg = PROJECT_NORF | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_FULL | PROJECT_NODO;
6060
6061
6062 /* WRAITHFORM reduces damage/effect! */
6063 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6064
6065 /* Use the given direction */
6066 tx = p_ptr->px + 99 * ddx[dir];
6067 ty = p_ptr->py + 99 * ddy[dir];
6068
6069 /* Hack -- Use an actual "target" */
6070 if ((dir == 5) && target_okay(Ind)) {
6071 flg &= ~(PROJECT_STOP);
6072 tx = p_ptr->target_col;
6073 ty = p_ptr->target_row;
6074 }
6075 #if 1
6076 #ifdef USE_SOUND_2010
6077 if (typ == GF_ROCKET) sound(Ind, "rocket", NULL, SFX_TYPE_COMMAND, FALSE);
6078 else if (typ == GF_DETONATION) sound(Ind, "detonation", NULL, SFX_TYPE_COMMAND, FALSE);
6079 else if (typ == GF_STONE_WALL) sound(Ind, "stone_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6080 else {
6081 /* The 'cast_ball' sound is only for attack spells */
6082 if ((typ != GF_HEAL_PLAYER) && (typ != GF_AWAY_ALL) &&
6083 (typ != GF_WRAITH_PLAYER) && (typ != GF_SPEED_PLAYER) &&
6084 (typ != GF_SHIELD_PLAYER) && (typ != GF_RECALL_PLAYER) &&
6085 (typ != GF_BLESS_PLAYER) && (typ != GF_REMFEAR_PLAYER) &&
6086 (typ != GF_REMCONF_PLAYER) && (typ != GF_REMIMAGE_PLAYER) &&
6087 (typ != GF_SATHUNGER_PLAYER) && (typ != GF_RESFIRE_PLAYER) &&
6088 (typ != GF_RESCOLD_PLAYER) && (typ != GF_CUREPOISON_PLAYER) &&
6089 (typ != GF_SEEINVIS_PLAYER) && (typ != GF_SEEMAP_PLAYER) &&
6090 (typ != GF_CURECUT_PLAYER) && (typ != GF_CURESTUN_PLAYER) &&
6091 (typ != GF_DETECTCREATURE_PLAYER) && (typ != GF_DETECTDOOR_PLAYER) &&
6092 (typ != GF_DETECTTRAP_PLAYER) && (typ != GF_TELEPORTLVL_PLAYER) &&
6093 (typ != GF_RESPOIS_PLAYER) && (typ != GF_RESELEC_PLAYER) &&
6094 (typ != GF_RESACID_PLAYER) && (typ != GF_HPINCREASE_PLAYER) &&
6095 (typ != GF_HERO_PLAYER) && (typ != GF_SHERO_PLAYER) &&
6096 (typ != GF_TELEPORT_PLAYER) && (typ != GF_ZEAL_PLAYER) &&
6097 (typ != GF_RESTORE_PLAYER) && (typ != GF_REMCURSE_PLAYER) &&
6098 (typ != GF_CURE_PLAYER) && (typ != GF_RESURRECT_PLAYER) &&
6099 (typ != GF_SANITY_PLAYER) && (typ != GF_SOULCURE_PLAYER) &&
6100 (typ != GF_OLD_HEAL) && (typ != GF_OLD_SPEED) && (typ != GF_PUSH) &&
6101 (typ != GF_HEALINGCLOUD) && /* Also not a hostile spell */
6102 (typ != GF_MINDBOOST_PLAYER) && (typ != GF_IDENTIFY) &&
6103 (typ != GF_SLOWPOISON_PLAYER) && (typ != GF_CURING) &&
6104 (typ != GF_OLD_POLY)) /* Non-hostile players may polymorph each other */
6105 if (p_ptr->sfx_magicattack) sound(Ind, "cast_ball", NULL, SFX_TYPE_COMMAND, TRUE);
6106 }
6107 #endif
6108 #endif
6109 /* Analyze the "dir" and the "target". Hurt items on floor. */
6110 snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6111
6112 /* affect self + players + monsters AND give credit on kill */
6113 flg = mod_ball_spell_flags(typ, flg);
6114 return (project(0 - Ind, rad, &p_ptr->wpos, ty, tx, dam, typ, flg, pattacker));
6115 }
6116
6117 /*
6118 * Cast a cloud spell
6119 * Stop if we hit a monster, act as a "ball"
6120 * Allow "target" mode to pass over monsters
6121 * Affect grids, objects, and monsters
6122 */
fire_cloud(int Ind,int typ,int dir,int dam,int rad,int time,int interval,char * attacker)6123 bool fire_cloud(int Ind, int typ, int dir, int dam, int rad, int time, int interval, char *attacker) {
6124 player_type *p_ptr = Players[Ind];
6125 int tx, ty;
6126
6127 int flg = PROJECT_NORF | PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_STAY | PROJECT_NODF | PROJECT_NODO;
6128
6129 char pattacker[80];
6130
6131 /* WRAITHFORM reduces damage/effect! */
6132 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6133
6134 /* Use the given direction */
6135 tx = p_ptr->px + 99 * ddx[dir];
6136 ty = p_ptr->py + 99 * ddy[dir];
6137
6138 /* Hack -- Use an actual "target" */
6139 if ((dir == 5) && target_okay(Ind))
6140 {
6141 flg &= ~(PROJECT_STOP);
6142 tx = p_ptr->target_col;
6143 ty = p_ptr->target_row;
6144 }
6145 project_interval = interval;
6146 project_time = time;
6147
6148 if (snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker) < 0) return (FALSE);
6149
6150 /* Analyze the "dir" and the "target". Hurt items on floor. */
6151
6152 #ifdef USE_SOUND_2010
6153 /* paranoia, aka this won't exist as "clouds".. */
6154 if (typ == GF_ROCKET) sound(Ind, "rocket", NULL, SFX_TYPE_COMMAND, FALSE);
6155 else if (typ == GF_DETONATION) sound(Ind, "detonation", NULL, SFX_TYPE_COMMAND, FALSE);
6156 else if (typ == GF_STONE_WALL) sound(Ind, "stone_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6157 /* only this one needed really */
6158 else if (p_ptr->sfx_magicattack) sound(Ind, "cast_cloud", NULL, SFX_TYPE_COMMAND, FALSE);
6159 #endif
6160
6161 flg = mod_ball_spell_flags(typ, flg);
6162 return (project(0 - Ind, (rad > 16) ? 16 : rad, &p_ptr->wpos, ty, tx, dam, typ, flg, pattacker));
6163 }
6164
6165 /*
6166 * Cast a wave spell
6167 * Stop if we hit a monster, act as a "ball"
6168 * Allow "target" mode to pass over monsters
6169 * Affect grids, objects, and monsters
6170 */
fire_wave(int Ind,int typ,int dir,int dam,int rad,int time,int interval,s32b eff,char * attacker)6171 bool fire_wave(int Ind, int typ, int dir, int dam, int rad, int time, int interval, s32b eff, char *attacker)
6172 {
6173 char pattacker[80];
6174
6175 project_time_effect = eff;
6176 snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
6177 return (fire_cloud(Ind, typ, dir, dam, rad, time, interval, pattacker));
6178 }
6179
6180 /*
6181 * Singing in the rain :-o
6182 */
cast_raindrop(worldpos * wpos,int x)6183 bool cast_raindrop(worldpos *wpos, int x) {
6184 char pattacker[80];
6185 strcpy(pattacker, "");
6186 int pseudo_y_start;
6187
6188 int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6189
6190 project_time_effect = EFF_RAINING;
6191 project_interval = 3;
6192 /* let more drops appear at top line, simulating that they were
6193 created 'above' the screen, so we don't get quite empty top lines */
6194 pseudo_y_start = rand_int(66 - 1 + 20) - 20;
6195 project_time = pseudo_y_start < 0 ? 20 + pseudo_y_start : 20;
6196 if (pseudo_y_start < 0) pseudo_y_start = 0;
6197 return (project(PROJECTOR_EFFECT, 0, wpos, pseudo_y_start, x, 0, GF_RAINDROP, flg, pattacker));
6198
6199 // project_time = 20;//1 + randint(66 - 3);
6200 // return (project(PROJECTOR_EFFECT, 0, wpos, 1 + randint(66 - 3), x, 0, GF_RAINDROP, flg, pattacker));
6201 }
6202
6203 /*
6204 * Let it snow, let it snow, let it snow... (WINTER_SEASON)
6205 * 'interval' is movement speed
6206 */
cast_snowflake(worldpos * wpos,int x,int interval)6207 bool cast_snowflake(worldpos *wpos, int x, int interval) {
6208 char pattacker[80];
6209 strcpy(pattacker, "");
6210
6211 int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6212
6213 project_time_effect = EFF_SNOWING;
6214 project_interval = interval;
6215 project_time = 100; /* just any value long enough to traverse the screen */
6216
6217 return (project(PROJECTOR_EFFECT, 0, wpos, 0, x, 0, GF_SNOWFLAKE, flg, pattacker));
6218 }
6219
6220 /*
6221 * Fireworks! (NEW_YEARS_EVE)
6222 */
cast_fireworks(worldpos * wpos,int x,int y)6223 bool cast_fireworks(worldpos *wpos, int x, int y) {
6224 char pattacker[80];
6225 strcpy(pattacker, "");
6226
6227 int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6228
6229 int typ = rand_int(7 * 3); /* colour & style */
6230
6231 if (typ < 7) project_time_effect = EFF_FIREWORKS1;
6232 else if (typ < 7 * 2) {
6233 project_time_effect = EFF_FIREWORKS2;
6234 typ -= 7;
6235 } else {
6236 project_time_effect = EFF_FIREWORKS3;
6237 typ -= 7 * 2;
6238 }
6239
6240 switch(typ) {
6241 case 0: typ = GF_FW_FIRE; break;
6242 case 1: typ = GF_FW_ELEC; break;
6243 case 2: typ = GF_FW_POIS; break;
6244 case 3: typ = GF_FW_LITE; break;
6245 case 4: typ = GF_FW_SHDI; break;
6246 case 5: typ = GF_FW_SHDM; break;
6247 case 6: typ = GF_FW_MULT; break;
6248 }
6249
6250 #if 0
6251 project_interval = 4;
6252 project_time = 5 + 5; /* X units to rise into the air, X units to explode */
6253 #else
6254 /* Adjustments - mikaelh */
6255 project_interval = 5;
6256 project_time = 8 + 8; /* X units to rise into the air, X units to explode */
6257 //if (project_time_effect == EFF_FIREWORKS3) project_time += 2 + 2;
6258 #endif
6259
6260 return (project(PROJECTOR_EFFECT, 0, wpos, y, x, 0, typ, flg, pattacker)); /* typ -> colour */
6261 }
6262
cast_lightning(worldpos * wpos,int x,int y)6263 bool cast_lightning(worldpos *wpos, int x, int y) {
6264 char pattacker[80];
6265 int flg = PROJECT_DUMY | PROJECT_GRID | PROJECT_STAY;
6266 int typ = rand_int(3 * 2); /* style / mirrored direction? */
6267
6268 strcpy(pattacker, "");
6269
6270 if (typ < 2) {
6271 project_time_effect = EFF_LIGHTNING1;
6272 project_time = 14;
6273 } else if (typ < 2 * 2) {
6274 project_time_effect = EFF_LIGHTNING2;
6275 project_time = 8;
6276 typ -= 2;
6277 } else {
6278 project_time_effect = EFF_LIGHTNING3;
6279 project_time = 10;
6280 typ -= 2 * 2;
6281 }
6282
6283 project_interval = 1;
6284 project_time += 10; /* afterglow */
6285
6286 #ifdef USE_SOUND_2010
6287 sound_floor_vol(wpos, "thunder", NULL, SFX_TYPE_AMBIENT, 100);
6288 #endif
6289
6290 return (project(PROJECTOR_EFFECT, 0, wpos, y, x, typ, GF_SHOW_LIGHTNING, flg, pattacker));
6291 }
6292
6293
6294 /*
6295 * Player swaps position with whatever in (lty, ltx)
6296 * usually used for 'Void Jumpgate' - Jir -
6297 */
6298 /*
6299 * Fixed monster swapping bug which caused many
6300 * unfair deaths and weirdness.
6301 * (evileye)
6302 */
swap_position(int Ind,int lty,int ltx)6303 bool swap_position(int Ind, int lty, int ltx){
6304 player_type *p_ptr;
6305 worldpos *wpos;
6306 int tx, ty;
6307 cave_type *c_ptr;
6308 cave_type **zcave;
6309 #ifdef ENABLE_SELF_FLASHING
6310 bool panel;
6311 #endif
6312
6313 p_ptr = Players[Ind];
6314 if (!p_ptr) return FALSE;
6315
6316 wpos = &p_ptr->wpos;
6317 if (!(zcave = getcave(wpos))) return FALSE;
6318
6319 store_exit(Ind);
6320
6321 c_ptr = &zcave[lty][ltx];
6322
6323 /* Keep track of the old location */
6324 tx = p_ptr->px;
6325 ty = p_ptr->py;
6326
6327 /* Move the player */
6328 p_ptr->px = ltx;
6329 p_ptr->py = lty;
6330
6331 if (!c_ptr->m_idx) {
6332 /* Free space */
6333 /* Update the old location */
6334 zcave[ty][tx].m_idx = 0;
6335 c_ptr->m_idx = 0 - Ind;
6336 cave_midx_debug(wpos, lty, ltx, -Ind);
6337
6338 /* Redraw/remember old location */
6339 note_spot_depth(wpos, ty, tx);
6340 everyone_lite_spot(wpos, ty, tx);
6341
6342 /* Redraw new grid */
6343 everyone_lite_spot(wpos, lty, ltx);
6344 } else if (c_ptr->m_idx > 0) {
6345 /* Monster */
6346 monster_type *m_ptr = &m_list[c_ptr->m_idx];
6347 zcave[ty][tx].m_idx = c_ptr->m_idx;
6348
6349 /* Move the monster */
6350 m_ptr->fy = ty;
6351 m_ptr->fx = tx;
6352
6353 /* Update the new location */
6354 c_ptr->m_idx = 0 - Ind;
6355 cave_midx_debug(wpos, lty, ltx, -Ind);
6356
6357 /* Update monster (new location) */
6358 update_mon(zcave[ty][tx].m_idx, TRUE);
6359
6360 /* Redraw/remember old location */
6361 note_spot_depth(wpos, ty, tx);
6362 everyone_lite_spot(wpos, ty, tx);
6363
6364 /* Redraw new grid */
6365 everyone_lite_spot(wpos, lty, ltx);
6366 } else {//if (c_ptr->m_idx < 0) {
6367 /* Other player */
6368 int Ind2 = 0 - c_ptr->m_idx;
6369 player_type *q_ptr = NULL;
6370 if (Ind2) q_ptr = Players[Ind2];
6371
6372 /* Shift them if they are real */
6373 if (q_ptr) {
6374 store_exit(Ind2);
6375
6376 q_ptr->py = ty;
6377 q_ptr->px = tx;
6378 #ifdef ARCADE_SERVER
6379 if (p_ptr->game == 3) {
6380 p_ptr->arc_c = q_ptr->arc_c = 1;
6381 p_ptr->arc_d = Ind2; }
6382 #endif
6383 }
6384
6385 p_ptr->px = ltx;
6386 p_ptr->py = lty;
6387
6388 /* Update old player location */
6389 c_ptr->m_idx = 0 - Ind;
6390 cave_midx_debug(wpos, lty, ltx, -Ind);
6391 zcave[ty][tx].m_idx = 0 - Ind2;
6392 cave_midx_debug(wpos, ty, tx, -Ind2);
6393
6394 /* Redraw/remember old location */
6395 note_spot_depth(wpos, ty, tx);
6396 everyone_lite_spot(wpos, ty, tx);
6397
6398 /* Redraw new grid */
6399 everyone_lite_spot(wpos, lty, ltx);
6400
6401 if (Ind2) verify_panel(Ind2);
6402 if (q_ptr) {
6403 /* Update stuff */
6404 q_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_DISTANCE);
6405
6406 /* Update Window */
6407 q_ptr->window |= (PW_OVERHEAD);
6408
6409 /* Handle stuff */
6410 if (!q_ptr->death) handle_stuff(Ind);
6411 }
6412 }
6413
6414 /* Check for new panel (redraw map) */
6415 #ifdef ENABLE_SELF_FLASHING
6416 panel = !local_panel(Ind);
6417 #endif
6418 verify_panel(Ind);
6419
6420 /* Update stuff */
6421 p_ptr->update |= (PU_VIEW | PU_LITE | PU_FLOW | PU_DISTANCE);
6422
6423 /* Update Window */
6424 p_ptr->window |= (PW_OVERHEAD);
6425
6426 /* Handle stuff */
6427 if (!p_ptr->death) handle_stuff(Ind);
6428
6429 return panel;
6430 }
6431
6432
6433 /*
6434 * Hack -- apply a "projection()" in a direction (or at the target)
6435 */
project_hook(int Ind,int typ,int dir,int dam,int flg,char * attacker)6436 bool project_hook(int Ind, int typ, int dir, int dam, int flg, char *attacker)
6437 {
6438 player_type *p_ptr = Players[Ind];
6439 int tx, ty;
6440
6441 /* WRAITHFORM reduces damage/effect! */
6442 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6443
6444 /* Pass through the target if needed */
6445 flg |= (PROJECT_THRU);
6446
6447 /* Use the given direction */
6448 tx = p_ptr->px + ddx[dir];
6449 ty = p_ptr->py + ddy[dir];
6450
6451 /* Hack -- Use an actual "target" */
6452 if ((dir == 5) && target_okay(Ind)) {
6453 // cave_type **zcave = getcave(&p_ptr->wpos);
6454
6455 tx = p_ptr->target_col;
6456 ty = p_ptr->target_row;
6457
6458 #if 0 /* oops, nonsense >_< this only concerns PROJECT_GRID/PROJECT_ITEM flags of course.. */
6459 /* Allow targetting the item/floor of a specific grid with a bolt spell
6460 ..if no monster on it! Assume that the floor won't get hit if the monster
6461 instead gets hit, basically. Makes sense for bolt spells and prevents
6462 too much loot destruction. */
6463 if (!(flg & PROJECT_BEAM) &&
6464 zcave && /* paranoia */
6465 zcave[ty][tx].m_idx == 0)
6466 flg &= ~PROJECT_THRU;
6467 #else
6468 if (!(flg & PROJECT_BEAM)) flg &= ~PROJECT_THRU;
6469 #endif
6470 }
6471
6472 /* Analyze the "dir" and the "target", do NOT explode */
6473 return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6474 }
6475
6476
6477 /*
6478 * Cast a bolt spell
6479 * Stop if we hit a monster, as a "bolt"
6480 * Affect monsters (not grids or objects)
6481 */
fire_bolt(int Ind,int typ,int dir,int dam,char * attacker)6482 bool fire_bolt(int Ind, int typ, int dir, int dam, char *attacker)
6483 {
6484 char pattacker[80];
6485 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID | PROJECT_EVSG;
6486 snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
6487
6488 #ifdef USE_SOUND_2010
6489 if (Players[Ind]->sfx_magicattack) sound(Ind, "cast_bolt", NULL, SFX_TYPE_COMMAND, FALSE);
6490 #endif
6491
6492 return (project_hook(Ind, typ, dir, dam, flg, pattacker));
6493 }
6494
6495 /*
6496 * Cast a beam spell
6497 * Pass through monsters, as a "beam"
6498 * Affect monsters (not grids or objects)
6499 */
fire_beam(int Ind,int typ,int dir,int dam,char * attacker)6500 bool fire_beam(int Ind, int typ, int dir, int dam, char *attacker)
6501 {
6502 char pattacker[80];
6503 //int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID;
6504 //Actually, since beams affect the whole tile, don't deflect or reflect them (we don't have proper code for changing beam path anyway) - Kurzel
6505 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6506 snprintf(pattacker, 80, "%s%s", Players[Ind]->name, attacker);
6507
6508 #ifdef USE_SOUND_2010
6509 if (Players[Ind]->sfx_magicattack) sound(Ind, "cast_beam", NULL, SFX_TYPE_COMMAND, FALSE);
6510 #endif
6511
6512 return (project_hook(Ind, typ, dir, dam, flg, pattacker));
6513 }
6514
6515 /*
6516 * Cast a cloud spell
6517 * Stop if we hit a monster, act as a "ball"
6518 * Allow "target" mode to pass over monsters
6519 * Affect grids, objects, and monsters
6520 */
fire_wall(int Ind,int typ,int dir,int dam,int time,int interval,char * attacker)6521 bool fire_wall(int Ind, int typ, int dir, int dam, int time, int interval, char *attacker)
6522 {
6523 player_type *p_ptr = Players[Ind];
6524 int tx, ty;
6525
6526 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_STAY | PROJECT_THRU | PROJECT_NODF | PROJECT_NODO;
6527
6528 /* WRAITHFORM reduces damage/effect! */
6529 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6530
6531 /* Use the given direction */
6532 tx = p_ptr->px + ddx[dir];
6533 ty = p_ptr->py + ddy[dir];
6534
6535 /* Hack -- Use an actual "target" */
6536 if ((dir == 5) && target_okay(Ind)) {
6537 tx = p_ptr->target_col;
6538 ty = p_ptr->target_row;
6539 }
6540 project_time_effect = EFF_WALL;
6541 project_interval = interval;
6542 project_time = time;
6543
6544 #ifdef USE_SOUND_2010
6545 sound(Ind, "cast_wall", NULL, SFX_TYPE_COMMAND, FALSE);
6546 #endif
6547
6548 /* Analyze the "dir" and the "target", do NOT explode */
6549 return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6550 }
6551
6552 /*
6553 * Cast a bolt spell, or rarely, a beam spell
6554 */
fire_bolt_or_beam(int Ind,int prob,int typ,int dir,int dam,char * attacker)6555 bool fire_bolt_or_beam(int Ind, int prob, int typ, int dir, int dam, char *attacker)
6556 {
6557 if (rand_int(100) < prob)
6558 return (fire_beam(Ind, typ, dir, dam, attacker));
6559 else
6560 return (fire_bolt(Ind, typ, dir, dam, attacker));
6561 }
6562
6563 /* Target bolt-like, but able to pass 'over' untargetted enemies to hit target grid,
6564 ie it manifests directly at the target location (like a ball of radius 0).
6565 Added for new mindcrafter spells; sort of a fake PROJECT_JUMP. - C. Blue */
fire_grid_bolt(int Ind,int typ,int dir,int dam,char * attacker)6566 bool fire_grid_bolt(int Ind, int typ, int dir, int dam, char *attacker) {
6567 player_type *p_ptr = Players[Ind];
6568 char pattacker[80];
6569 int tx, ty;
6570
6571 int flg = PROJECT_NORF | PROJECT_HIDE | PROJECT_STOP | PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID | PROJECT_EVSG | PROJECT_NODF | PROJECT_NODO;
6572
6573 /* WRAITHFORM reduces damage/effect! */
6574 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6575
6576 /* Use the given direction */
6577 tx = p_ptr->px + 99 * ddx[dir];
6578 ty = p_ptr->py + 99 * ddy[dir];
6579
6580 /* Hack -- Use an actual "target" */
6581 if ((dir == 5) && target_okay(Ind)) {
6582 flg &= ~PROJECT_STOP;
6583 tx = p_ptr->target_col;
6584 ty = p_ptr->target_row;
6585 }
6586
6587 #ifdef USE_SOUND_2010
6588 if (p_ptr->sfx_magicattack) sound(Ind, "cast_bolt", NULL, SFX_TYPE_COMMAND, FALSE);
6589 #endif
6590
6591 /* Analyze the "dir" and the "target". Hurt items on floor. */
6592 snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6593
6594 if (typ == GF_HEAL_PLAYER) flg |= PROJECT_PLAY; //mod_ball_spell_flags(typ, flg);
6595 return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6596 }
6597
6598 /* Added for new mindcrafter spells.
6599 The '_grid_' part here means that the beam also hits the floor grids,
6600 ie feat/terrain/item! Added for mindcrafter disarming. - C. Blue */
fire_grid_beam(int Ind,int typ,int dir,int dam,char * attacker)6601 bool fire_grid_beam(int Ind, int typ, int dir, int dam, char *attacker) {
6602 player_type *p_ptr = Players[Ind];
6603 char pattacker[80];
6604
6605 // (project_grid is required for disarm beam! same for project_item, for chests!)
6606 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6607 // flg |= PROJECT_STOP | PROJECT_HIDE;
6608
6609 /* Analyze the "dir" and the "target". Hurt items on floor. */
6610 snprintf(pattacker, 80, "%s%s", p_ptr->name, attacker);
6611
6612 #ifdef USE_SOUND_2010
6613 if (p_ptr->sfx_magicattack) sound(Ind, "cast_beam", NULL, SFX_TYPE_COMMAND, FALSE);
6614 #endif
6615
6616 #if 0 /* why needed for beam? */
6617 /* Use the given direction */
6618 int tx = p_ptr->px + 99 * ddx[dir], ty = p_ptr->py + 99 * ddy[dir];
6619
6620 /* WRAITHFORM reduces damage/effect! */
6621 if (p_ptr->tim_wraith) proj_dam_wraith(typ, &dam);
6622
6623 /* Hack -- Use an actual "target" */
6624 if ((dir == 5) && target_okay(Ind)) {
6625 flg &= ~PROJECT_STOP;
6626 tx = p_ptr->target_col;
6627 ty = p_ptr->target_row;
6628 }
6629
6630 return (project(0 - Ind, 0, &p_ptr->wpos, ty, tx, dam, typ, flg, attacker));
6631 #else
6632 return (project_hook(Ind, typ, dir, dam, flg, pattacker));
6633 #endif
6634
6635 }
6636
6637
6638 /*
6639 * Some of the old functions
6640 */
6641 /* TODO: the result should be affected by skills (and not plev) */
6642
lite_line(int Ind,int dir,int dam)6643 bool lite_line(int Ind, int dir, int dam)
6644 {
6645 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_KILL | PROJECT_NODF | PROJECT_NODO;
6646 return (project_hook(Ind, GF_LITE_WEAK, dir, dam, flg, ""));
6647 }
6648
drain_life(int Ind,int dir,int dam)6649 bool drain_life(int Ind, int dir, int dam)
6650 {
6651 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6652 return(project_hook(Ind, GF_OLD_DRAIN, dir, dam, flg, ""));
6653 }
6654
annihilate(int Ind,int dir,int dam)6655 bool annihilate(int Ind, int dir, int dam)
6656 {
6657 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6658 return(project_hook(Ind, GF_ANNIHILATION, dir, dam, flg, ""));
6659 }
6660
wall_to_mud(int Ind,int dir)6661 bool wall_to_mud(int Ind, int dir)
6662 {
6663 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_NODF | PROJECT_NODO;
6664 return (project_hook(Ind, GF_KILL_WALL, dir, 20 + randint(30), flg, ""));
6665 }
6666
destroy_door(int Ind,int dir)6667 bool destroy_door(int Ind, int dir)
6668 {
6669 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6670 return (project_hook(Ind, GF_KILL_DOOR, dir, 0, flg, ""));
6671 }
6672
disarm_trap(int Ind,int dir)6673 bool disarm_trap(int Ind, int dir)
6674 {
6675 int flg = PROJECT_NORF | PROJECT_BEAM | PROJECT_GRID | PROJECT_ITEM | PROJECT_NODF | PROJECT_NODO;
6676 return (project_hook(Ind, GF_KILL_TRAP, dir, 0, flg, ""));
6677 }
6678
heal_monster(int Ind,int dir)6679 bool heal_monster(int Ind, int dir)
6680 {
6681 int flg = PROJECT_STOP | PROJECT_KILL;
6682 snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker), "%s heals you for", Players[Ind]->name);
6683 return (project_hook(Ind, GF_OLD_HEAL, dir, damroll(4, 6), flg, Players[Ind]->attacker));
6684 }
6685
speed_monster(int Ind,int dir)6686 bool speed_monster(int Ind, int dir)
6687 {
6688 player_type *p_ptr = Players[Ind];
6689
6690 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6691 return (project_hook(Ind, GF_OLD_SPEED, dir, p_ptr->lev, flg, ""));
6692 }
6693
slow_monster(int Ind,int dir,int pow)6694 bool slow_monster(int Ind, int dir, int pow)
6695 {
6696 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6697 return (project_hook(Ind, GF_OLD_SLOW, dir, pow, flg, ""));
6698 }
6699
sleep_monster(int Ind,int dir,int pow)6700 bool sleep_monster(int Ind, int dir, int pow)
6701 {
6702 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6703 return (project_hook(Ind, GF_OLD_SLEEP, dir, pow, flg, ""));
6704 }
6705
confuse_monster(int Ind,int dir,int pow)6706 bool confuse_monster(int Ind, int dir, int pow)
6707 {
6708 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6709 return (project_hook(Ind, GF_OLD_CONF, dir, pow, flg, ""));
6710 }
6711
poly_monster(int Ind,int dir)6712 bool poly_monster(int Ind, int dir)
6713 {
6714 player_type *p_ptr = Players[Ind];
6715
6716 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_SELF | PROJECT_PLAY | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6717 return (project_hook(Ind, GF_OLD_POLY, dir, p_ptr->lev, flg, ""));
6718 }
6719
clone_monster(int Ind,int dir)6720 bool clone_monster(int Ind, int dir)
6721 {
6722 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6723 return (project_hook(Ind, GF_OLD_CLONE, dir, 0, flg, ""));
6724 }
6725
fear_monster(int Ind,int dir,int pow)6726 bool fear_monster(int Ind, int dir, int pow)
6727 {
6728 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6729 return (project_hook(Ind, GF_TURN_ALL, dir, pow, flg, ""));
6730 }
6731
teleport_monster(int Ind,int dir)6732 bool teleport_monster(int Ind, int dir)
6733 {
6734 int flg = PROJECT_BEAM | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6735 return (project_hook(Ind, GF_AWAY_ALL, dir, MAX_SIGHT * 5, flg, ""));
6736 }
6737
cure_light_wounds_proj(int Ind,int dir)6738 bool cure_light_wounds_proj(int Ind, int dir)
6739 {
6740 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6741 snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker), "%s heals you for", Players[Ind]->name);
6742 return (project_hook(Ind, GF_HEAL_PLAYER, dir, damroll(2, 10), flg, Players[Ind]->attacker));
6743 }
6744
cure_serious_wounds_proj(int Ind,int dir)6745 bool cure_serious_wounds_proj(int Ind, int dir)
6746 {
6747 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6748 snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker),"%s heals you for", Players[Ind]->name);
6749 return (project_hook(Ind, GF_HEAL_PLAYER, dir, damroll(4, 10), flg, Players[Ind]->attacker));
6750 }
6751
cure_critical_wounds_proj(int Ind,int dir)6752 bool cure_critical_wounds_proj(int Ind, int dir)
6753 {
6754 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6755 snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker),"%s heals you for", Players[Ind]->name);
6756 return (project_hook(Ind, GF_HEAL_PLAYER, dir, damroll(6, 10), flg, Players[Ind]->attacker));
6757 }
6758
heal_other_proj(int Ind,int dir)6759 bool heal_other_proj(int Ind, int dir)
6760 {
6761 int flg = PROJECT_STOP | PROJECT_KILL | PROJECT_NORF | PROJECT_NODF | PROJECT_NODO;
6762 snprintf(Players[Ind]->attacker, sizeof(Players[Ind]->attacker),"%s heals you for", Players[Ind]->name);
6763 return (project_hook(Ind, GF_HEAL_PLAYER, dir, 100, flg, Players[Ind]->attacker));
6764 }
6765
6766
6767
6768 /*
6769 * Hooks -- affect adjacent grids (radius 1 ball attack)
6770 */
6771
door_creation(int Ind)6772 bool door_creation(int Ind)
6773 {
6774 player_type *p_ptr = Players[Ind];
6775
6776 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6777 return (project(0 - Ind, 1, &p_ptr->wpos, p_ptr->py, p_ptr->px, 0, GF_MAKE_DOOR, flg, ""));
6778 }
6779
trap_creation(int Ind,int mod,int rad)6780 bool trap_creation(int Ind, int mod, int rad)
6781 {
6782 player_type *p_ptr = Players[Ind];
6783
6784 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6785 return (project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, mod, GF_MAKE_TRAP, flg, ""));
6786 }
6787
destroy_doors_touch(int Ind,int rad)6788 bool destroy_doors_touch(int Ind, int rad)
6789 {
6790 player_type *p_ptr = Players[Ind];
6791
6792 int flg = PROJECT_NORF | PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6793 return (project(0 - Ind, rad, &p_ptr->wpos, p_ptr->py, p_ptr->px, 0, GF_KILL_DOOR, flg, ""));
6794 }
6795
sleep_monsters_touch(int Ind)6796 bool sleep_monsters_touch(int Ind)
6797 {
6798 player_type *p_ptr = Players[Ind];
6799
6800 int flg = PROJECT_NORF | PROJECT_KILL | PROJECT_HIDE | PROJECT_NODF | PROJECT_NODO;
6801 return (project(0 - Ind, 1, &p_ptr->wpos, p_ptr->py, p_ptr->px, p_ptr->lev, GF_OLD_SLEEP, flg, ""));
6802 }
6803
6804 /* Scan magical powers for the golem */
scan_golem_flags(object_type * o_ptr,monster_race * r_ptr)6805 static void scan_golem_flags(object_type *o_ptr, monster_race *r_ptr)
6806 {
6807 u32b f1, f2, f3, f4, f5, f6, esp;
6808
6809 /* Extract the flags */
6810 object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &f6, &esp);
6811
6812 if (f1 & TR1_LIFE) r_ptr->hdice += o_ptr->pval;
6813 if (f1 & TR1_SPEED) r_ptr->speed += o_ptr->pval * 2 / 3;
6814 if (f1 & TR1_TUNNEL) r_ptr->flags2 |= RF2_KILL_WALL;
6815 if (f2 & TR2_RES_FIRE) r_ptr->flags3 |= RF3_IM_FIRE;
6816 if (f2 & TR2_RES_ACID) r_ptr->flags3 |= RF3_IM_ACID;
6817 if (f2 & TR2_RES_NETHER) r_ptr->flags3 |= RF3_RES_NETH;
6818 if (f2 & TR2_RES_NEXUS) r_ptr->flags3 |= RF3_RES_NEXU;
6819 if (f2 & TR2_RES_DISEN) r_ptr->flags3 |= RF3_RES_DISE;
6820
6821 /* Allow use of runes - some are redundant (for completeness) */
6822 if (o_ptr->tval == TV_RUNE) switch(o_ptr->sval) {
6823 case SV_R_LITE: r_ptr->flags9 |= RF9_RES_LITE; break;
6824 case SV_R_DARK: r_ptr->flags9 |= RF9_RES_DARK; break;
6825 case SV_R_NEXU: r_ptr->flags3 |= RF3_RES_NEXU; break;
6826 case SV_R_NETH: r_ptr->flags3 |= RF3_RES_NETH; break;
6827 case SV_R_CHAO: r_ptr->flags9 |= RF9_RES_CHAOS; break;
6828 case SV_R_MANA: r_ptr->flags9 |= RF9_RES_MANA; break;
6829
6830 case SV_R_CONF: r_ptr->flags3 |= RF3_NO_CONF; break;
6831 // case SV_R_INER: r_ptr->flags4 |= RF4_BR_INER; break; //Inertia has no resist; alt: RF3_NO_TELE!
6832 case SV_R_ELEC: r_ptr->flags3 |= RF3_IM_ELEC; break;
6833 case SV_R_FIRE: r_ptr->flags3 |= RF3_IM_FIRE; break;
6834 case SV_R_WATE: r_ptr->flags3 |= RF3_RES_WATE; break;
6835 // case SV_R_GRAV: r_ptr->flags4 |= RF4_BR_GRAV; break; //Gravity has no resist (for mobs)!
6836 case SV_R_COLD: r_ptr->flags3 |= RF3_IM_COLD; break;
6837 case SV_R_ACID: r_ptr->flags3 |= RF3_IM_ACID; break;
6838 case SV_R_POIS: r_ptr->flags3 |= RF3_IM_POIS; break;
6839 case SV_R_TIME: r_ptr->flags9 |= RF9_RES_TIME; break;
6840 case SV_R_SOUN: r_ptr->flags9 |= RF9_RES_SOUND; break;
6841 case SV_R_SHAR: r_ptr->flags9 |= RF9_RES_SHARDS; break;
6842 case SV_R_DISE: r_ptr->flags3 |= RF3_RES_DISE; break;
6843 // case SV_R_FORC: r_ptr->flags4 |= RF4_BR_WALL; break; //Force has no resist (for mobs); alt: RF3_NO_SLEEP!
6844 case SV_R_PLAS: r_ptr->flags3 |= RF3_RES_PLAS; break;
6845
6846 default: break;
6847 }
6848 }
6849
6850 /* multi builder stuff - move when complete */
6851 struct builder {
6852 int player;
6853 int lx, ly, dx, dy, minx, miny, maxx, maxy;
6854 int sx, sy;
6855 int odir;
6856 int moves;
6857 int cvert;
6858 struct worldpos wpos;
6859 bool nofloor;
6860 bool jail;
6861 struct dna_type *dna;
6862 char *vert;
6863 struct c_special *cs;
6864 struct builder *next;
6865 };
6866
6867 #define MAX_BUILDERS 4 /* Just so the builders can go on strike */
6868 /* end of move stuff */
6869
poly_build(int Ind,char * args)6870 static bool poly_build(int Ind, char *args) {
6871 static struct builder *builders = NULL;
6872 static int num_build = 0;
6873
6874 player_type *p_ptr = Players[Ind];
6875 struct builder *curr = builders;
6876 int x, y;
6877 int dir = 0;
6878 cave_type **zcave;
6879 if (!(zcave = getcave(&p_ptr->wpos))) return(FALSE);
6880 while (curr) {
6881 struct builder *prev = NULL;
6882 bool kill = FALSE;
6883 if (curr->player == p_ptr->id) break;
6884 if (!lookup_player_name(curr->player)) { /* disconnect or free builders */
6885 if (prev)
6886 prev->next = curr->next;
6887 else
6888 builders = curr->next;
6889 kill = TRUE;
6890 }
6891 prev = curr;
6892 curr = curr->next;
6893 if (kill) {
6894 KILL(prev, struct builder);
6895 }
6896 }
6897
6898 if (!curr) { /* new builder */
6899 #ifdef MAX_BUILDERS
6900 if (num_build == MAX_BUILDERS){
6901 msg_print(Ind,"The builders are on strike!");
6902 return FALSE;
6903 }
6904 #endif
6905 MAKE(curr, struct builder);
6906 curr->next = builders; /* insert is fastest */
6907 curr->player = p_ptr->id; /* set him up */
6908 C_MAKE(curr->vert, MAXCOORD, char);
6909 MAKE(curr->dna, struct dna_type);
6910 curr->dna->creator = p_ptr->dna;
6911 curr->dna->owner = p_ptr->id;
6912 curr->dna->owner_type = OT_PLAYER;
6913 curr->dna->a_flags = ACF_NONE;
6914 curr->dna->min_level = ACF_NONE;
6915 curr->dna->price = 5; /* so work out */
6916 curr->odir = 0;
6917 curr->cvert = 0;
6918 curr->nofloor = (args[0] == 'N');
6919 curr->jail = (args[1] == 'Y');
6920 curr->sx = p_ptr->px;
6921 curr->sy = p_ptr->py;
6922 curr->minx = curr->maxx = curr->sx;
6923 curr->miny = curr->maxy = curr->sy;
6924 curr->dx = curr->lx = curr->sx;
6925 curr->dy = curr->ly = curr->sy;
6926 curr->moves = 25; /* always new */
6927 wpcopy(&curr->wpos, &p_ptr->wpos);
6928 // if (zcave[curr->sy][curr->sx].feat == FEAT_PERM_EXTRA){
6929 if (zcave[curr->sy][curr->sx].feat == FEAT_WALL_HOUSE){
6930 #if 0 /* not necessary? - evileye */
6931 zcave[curr->sy][curr->sx].special.sc.ptr = NULL;
6932 #endif
6933 msg_print(Ind, "Your foundations were laid insecurely");
6934 KILL(curr->dna, struct dna_type);
6935 C_KILL(curr->vert, MAXCOORD, char);
6936 p_ptr->master_move_hook = NULL;
6937 KILL(curr, struct builder); /* Sack the builders! */
6938 return FALSE;
6939 }
6940 zcave[curr->sy][curr->sx].feat = FEAT_HOME_OPEN;
6941 /* CS_DNADOOR seems to be added twice (wild_add_uhouse)..
6942 * please correct it, Evileye? - Jir -
6943 */
6944 #if 0
6945 if ((curr->cs = AddCS(&zcave[curr->sy][curr->sx], CS_DNADOOR))) {
6946 curr->cs->sc.ptr = curr->dna;
6947 }
6948 #endif
6949 builders = curr;
6950 return TRUE;
6951 }
6952
6953 if (args) {
6954 curr->moves += 25;
6955 return TRUE;
6956 }
6957 x = p_ptr->px;
6958 y = p_ptr->py;
6959 curr->minx = MIN(x, curr->minx);
6960 curr->maxx = MAX(x, curr->maxx);
6961 curr->miny = MIN(y, curr->miny);
6962 curr->maxy = MAX(y, curr->maxy);
6963 if (x != curr->dx) {
6964 if (x > curr->dx) dir = 1;
6965 else dir = 2;
6966 }
6967 if (y != curr->dy) {
6968 if (dir) {
6969 curr->moves = 0;
6970 /* diagonal! house building failed */
6971 }
6972 if(y > curr->dy) dir |= 4;
6973 else dir |= 8;
6974 }
6975 if (curr->odir != dir) {
6976 if (curr->odir) { /* first move not new vertex */
6977 curr->vert[curr->cvert++] = curr->dx-curr->lx;
6978 curr->vert[curr->cvert++] = curr->dy-curr->ly;
6979 }
6980 curr->lx = curr->dx;
6981 curr->ly = curr->dy;
6982 curr->odir = dir; /* change direction, add vertex */
6983 }
6984 curr->dx = x;
6985 curr->dy = y;
6986
6987 if (p_ptr->px == curr->sx && p_ptr->py == curr->sy && curr->moves) { /* check for close */
6988 curr->vert[curr->cvert++] = curr->dx-curr->lx; /* last vertex */
6989 curr->vert[curr->cvert++] = curr->dy-curr->ly;
6990 if (curr->cvert == 10 || curr->cvert == 8) {
6991 /* rectangle! */
6992 houses[num_houses].flags = HF_RECT;
6993 houses[num_houses].x = curr->minx;
6994 houses[num_houses].y = curr->miny;
6995 houses[num_houses].coords.rect.width = curr->maxx + 1 - curr->minx;
6996 houses[num_houses].coords.rect.height = curr->maxy + 1 - curr->miny;
6997 #if 0 /* hm, isn't this buggy? should just be same as for HF_NONE? */
6998 houses[num_houses].dx = curr->sx-curr->minx;
6999 houses[num_houses].dy = curr->sy-curr->miny;
7000 #else
7001 houses[num_houses].dx = curr->sx;
7002 houses[num_houses].dy = curr->sy;
7003 #endif
7004 C_KILL(curr->vert, MAXCOORD, char);
7005 } else {
7006 houses[num_houses].flags = HF_NONE; /* polygonal */
7007 houses[num_houses].x = curr->sx;
7008 houses[num_houses].y = curr->sy;
7009 houses[num_houses].coords.poly = curr->vert;
7010 /* was missing: actually remember the door position! (for pick_house() to work) */
7011 houses[num_houses].dx = curr->sx;
7012 houses[num_houses].dy = curr->sy;
7013 }
7014 if (curr->nofloor) houses[num_houses].flags |= HF_NOFLOOR;
7015 if (curr->jail) houses[num_houses].flags |= HF_JAIL;
7016 /* Moat testing */
7017 #if 0
7018 houses[num_houses].flags |= HF_MOAT;
7019 #endif
7020 /* Do not commit! */
7021 wpcopy(&houses[num_houses].wpos, &p_ptr->wpos);
7022 houses[num_houses].dna = curr->dna;
7023 if (curr->cvert >= 8 && fill_house(&houses[num_houses], FILL_MAKEHOUSE, NULL)){
7024 int area = (curr->maxx-curr->minx) * (curr->maxy-curr->miny);
7025 houses[num_houses].flags |= HF_SELFBUILT;
7026 curr->dna->price = area * area * 400; //initial_house_price(&houses[num_houses])
7027 wild_add_uhouse(&houses[num_houses]);
7028 msg_print(Ind,"You have completed your house");
7029 num_houses++;
7030 } else {
7031 msg_print(Ind,"Your house was built unsoundly");
7032 if(curr->vert) C_KILL(curr->vert, MAXCOORD, char);
7033 KILL(curr->dna, struct dna_type);
7034 }
7035 curr->player = 0; /* send the builders home */
7036 p_ptr->master_move_hook = NULL;
7037 p_ptr->update |= PU_VIEW;
7038 return TRUE;
7039 }
7040 /* no going off depth, and no spoiling moats */
7041 if (inarea(&curr->wpos, &p_ptr->wpos) && !(zcave[curr->dy][curr->dx].info&CAVE_ICKY && zcave[curr->dy][curr->dx].feat == FEAT_DEEP_WATER)) {
7042 zcave[curr->dy][curr->dx].feat = FEAT_WALL_EXTRA;
7043 // zcave[curr->dy][curr->dx].feat = FEAT_WALL_HOUSE;
7044 if (curr->cvert < MAXCOORD && (--curr->moves) > 0) return TRUE;
7045 p_ptr->update |= PU_VIEW;
7046 }
7047 msg_print(Ind,"Your house building attempt has failed");
7048 cs_erase(&zcave[curr->sy][curr->sx], curr->cs);
7049 KILL(curr->dna, struct dna_type);
7050 C_KILL(curr->vert, MAXCOORD, char);
7051 curr->player = 0; /* send the builders home */
7052 p_ptr->master_move_hook = NULL;
7053 return FALSE;
7054 }
7055
house_creation(int Ind,bool floor,bool jail)7056 void house_creation(int Ind, bool floor, bool jail)
7057 {
7058 player_type *p_ptr = Players[Ind];
7059 struct worldpos *wpos = &p_ptr->wpos;
7060 char buildargs[3];
7061
7062 /* set master_move_hook : a bit like a setuid really ;) */
7063 printf("floor: %d jail: %d\n",floor,jail);
7064
7065 /* No building in town */
7066 if (wpos->wz) {
7067 msg_print(Ind, "\376\377yYou must build on the world surface.");
7068 return;
7069 }
7070 if (istownarea(wpos, MAX_TOWNAREA)) {
7071 msg_print(Ind, "\376\377yYou cannot build within a town area.");
7072 if (!is_admin(p_ptr)) return;
7073 }
7074 if (house_alloc - num_houses < 32) {
7075 GROW(houses, house_alloc, house_alloc + 512, house_type);
7076 house_alloc += 512;
7077 }
7078 p_ptr->master_move_hook = poly_build;
7079
7080 buildargs[0] = (floor ? 'Y' : 'N');
7081 buildargs[1] = (jail ? 'Y' : 'N');
7082 buildargs[2] = '\0';
7083
7084 poly_build(Ind, (char*)&buildargs); /* Its a (char*) ;( */
7085 }
7086
7087 /* (Note: Apparently currently only used by Moltor's second_handler().) */
place_foe(int owner_id,struct worldpos * wpos,int y,int x,int r_idx)7088 extern bool place_foe(int owner_id, struct worldpos *wpos, int y, int x, int r_idx) {
7089 int i, Ind, j;
7090 cave_type *c_ptr;
7091
7092 monster_type *m_ptr;
7093 monster_race *r_ptr = &r_info[r_idx];
7094
7095 char buf[80];
7096
7097 cave_type **zcave;
7098 if (!(zcave = getcave(wpos))) return (0);
7099 /* Verify location */
7100 if (!in_bounds(y, x)) return (0);
7101 /* Require empty space */
7102 if (!cave_empty_bold(zcave, y, x)) return (0);
7103
7104 /* Paranoia */
7105 if (!r_idx) return (0);
7106
7107 /* Paranoia */
7108 if (!r_ptr->name) return (0);
7109
7110 /* Update r_ptr due to possible r_idx changes */
7111 r_ptr = &r_info[r_idx];
7112
7113 if ((r_ptr->flags1 & RF1_UNIQUE)) return (0);
7114
7115 c_ptr = &zcave[y][x];
7116
7117 /* Make a new monster */
7118 c_ptr->m_idx = m_pop();
7119
7120 /* Mega-Hack -- catch "failure" */
7121 if (!c_ptr->m_idx) return (0);
7122
7123 /* Get a new monster record */
7124 m_ptr = &m_list[c_ptr->m_idx];
7125
7126 /* Save the race */
7127 m_ptr->r_idx = r_idx;
7128
7129 /* Place the monster at the location */
7130 m_ptr->fy = y;
7131 m_ptr->fx = x;
7132 wpcopy(&m_ptr->wpos, wpos);
7133
7134 m_ptr->special = m_ptr->questor = 0;
7135
7136 /* Hack -- Count the monsters on the level */
7137 r_ptr->cur_num++;
7138
7139
7140 /* Hack -- count the number of "reproducers" */
7141 if (r_ptr->flags7 & RF7_MULTIPLY) num_repro++;
7142
7143
7144 /* Assign maximal hitpoints */
7145 if (r_ptr->flags1 & RF1_FORCE_MAXHP)
7146 m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
7147 else
7148 m_ptr->maxhp = damroll(r_ptr->hdice, r_ptr->hside);
7149
7150 /* And start out fully healthy */
7151 m_ptr->hp = m_ptr->maxhp;
7152
7153 /* Extract the monster base speed */
7154 m_ptr->speed = r_ptr->speed;
7155 /* set cur speed to base speed */
7156 m_ptr->mspeed = m_ptr->speed;
7157
7158 /* Extract base ac and other things */
7159 m_ptr->ac = r_ptr->ac;
7160
7161 for (j = 0; j < 4; j++) {
7162 m_ptr->blow[j].effect = r_ptr->blow[j].effect;
7163 m_ptr->blow[j].method = r_ptr->blow[j].method;
7164 m_ptr->blow[j].d_dice = r_ptr->blow[j].d_dice;
7165 m_ptr->blow[j].d_side = r_ptr->blow[j].d_side;
7166 }
7167 m_ptr->level = r_ptr->level;
7168 m_ptr->exp = MONSTER_EXP(m_ptr->level);
7169 m_ptr->owner = 0;
7170
7171 /* Hack -- small racial variety */
7172 if (!(r_ptr->flags1 & RF1_UNIQUE)) {
7173 /* Allow some small variation per monster */
7174 i = extract_energy[m_ptr->speed] / 100;
7175 if (i) {
7176 j = rand_spread(0, i);
7177 m_ptr->mspeed += j;
7178
7179 if (m_ptr->mspeed < j) m_ptr->mspeed = 255;
7180 }
7181 }
7182
7183
7184 /* Give a random starting energy */
7185 m_ptr->energy = rand_int(1000);
7186
7187 /* Hack -- Reduce risk of "instant death by breath weapons" */
7188 if (r_ptr->flags1 & RF1_FORCE_SLEEP) {
7189 /* Start out with minimal energy */
7190 m_ptr->energy = rand_int(100);
7191 }
7192
7193 /* Starts 'flickered out'? */
7194 if ((r_ptr->flags2 & RF2_WEIRD_MIND) && rand_int(10)) m_ptr->no_esp_phase = TRUE;
7195
7196 /* No "damage" yet */
7197 m_ptr->stunned = 0;
7198 m_ptr->confused = 0;
7199 m_ptr->monfear = 0;
7200
7201 /* No knowledge */
7202 m_ptr->cdis = 0;
7203
7204 /* clone value */
7205
7206 m_ptr->owner = 0;
7207 m_ptr->pet = 0;
7208
7209 for (Ind = 1; Ind < NumPlayers + 1; Ind++) {
7210 if (Players[Ind]->conn == NOT_CONNECTED)
7211 continue;
7212
7213 Players[Ind]->mon_los[c_ptr->m_idx] = 0;
7214 Players[Ind]->mon_vis[c_ptr->m_idx] = 0;
7215 }
7216
7217 if (getlevel(wpos) > (m_ptr->level + 7)) {
7218 m_ptr->exp = MONSTER_EXP(m_ptr->level + ((getlevel(wpos) - (m_ptr->level + 7)) / 3));
7219 monster_check_experience(c_ptr->m_idx, TRUE);
7220 }
7221
7222 strcpy(buf, (r_name + r_ptr->name));
7223
7224 /* Update the monster */
7225 update_mon(c_ptr->m_idx, TRUE);
7226
7227
7228 /* Assume no sleeping */
7229 m_ptr->csleep = 0;
7230
7231 /* STR */
7232 for (j = 0; j < 4; j++) {
7233 m_ptr->blow[j].org_d_dice = r_ptr->blow[j].d_dice;
7234 m_ptr->blow[j].org_d_side = r_ptr->blow[j].d_side;
7235 }
7236 /* DEX */
7237 m_ptr->org_ac = m_ptr->ac;
7238 /* CON */
7239 m_ptr->org_maxhp = m_ptr->maxhp;
7240
7241 #ifdef MONSTER_ASTAR
7242 if (r_ptr->flags0 & RF0_ASTAR) {
7243 /* search for an available A* table to use */
7244 for (j = 0; j < ASTAR_MAX_INSTANCES; j++) {
7245 /* found an available instance? */
7246 if (astar_info_open[j].m_idx == -1) {
7247 astar_info_open[j].m_idx = c_ptr->m_idx;
7248 astar_info_open[j].nodes = 0; /* init: start with empty set of nodes */
7249 astar_info_closed[j].nodes = 0; /* init: start with empty set of nodes */
7250 m_ptr->astar_idx = j;
7251 break;
7252 }
7253 }
7254 /* no instance available? Mark us (-1) to use normal movement instead */
7255 if (j == ASTAR_MAX_INSTANCES) m_ptr->astar_idx = -1;
7256 }
7257 #endif
7258
7259 return (TRUE);
7260 }
7261 #ifdef RPG_SERVER
place_pet(int owner_id,struct worldpos * wpos,int y,int x,int r_idx)7262 bool place_pet(int owner_id, struct worldpos *wpos, int y, int x, int r_idx) {
7263 int Ind, j;
7264 cave_type *c_ptr;
7265
7266 monster_type *m_ptr;
7267 monster_race *r_ptr = &r_info[r_idx];
7268
7269 char buf[80];
7270
7271 cave_type **zcave;
7272 if (!(zcave = getcave(wpos))) return (0);
7273
7274
7275 /* Verify location */
7276 if (!in_bounds(y, x)) return (0);
7277 /* Require empty space */
7278 if (!cave_empty_bold(zcave, y, x)) return (0);
7279 /* Hack -- no creation on glyph of warding */
7280 if (zcave[y][x].feat == FEAT_GLYPH) return (0);
7281 if (zcave[y][x].feat == FEAT_RUNE) return (0);
7282
7283 /* Paranoia */
7284 if (!r_idx) return (0);
7285
7286 /* Paranoia */
7287 if (!r_ptr->name) return (0);
7288
7289 /* Update r_ptr due to possible r_idx changes */
7290 r_ptr = &r_info[r_idx];
7291
7292 /* No uniques, obviously */
7293 if (r_ptr->flags1 & RF1_UNIQUE) return (0);
7294
7295 /* No breeders */
7296 if (r_ptr->flags7 & RF7_MULTIPLY) return (0);
7297
7298 c_ptr = &zcave[y][x];
7299
7300 /* Make a new monster */
7301 c_ptr->m_idx = m_pop();
7302
7303 /* Mega-Hack -- catch "failure" */
7304 if (!c_ptr->m_idx) return (0);
7305
7306 /* Get a new monster record */
7307 m_ptr = &m_list[c_ptr->m_idx];
7308
7309 /* Save the race */
7310 m_ptr->r_idx = r_idx;
7311
7312 /* Place the monster at the location */
7313 m_ptr->fy = y;
7314 m_ptr->fx = x;
7315 wpcopy(&m_ptr->wpos, wpos);
7316
7317 m_ptr->special = m_ptr->questor = 0;
7318
7319 /* Hack -- Count the monsters on the level */
7320 r_ptr->cur_num++;
7321
7322 /* Assign maximal hitpoints */
7323 if (r_ptr->flags1 & RF1_FORCE_MAXHP)
7324 m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
7325 else
7326 m_ptr->maxhp = damroll(r_ptr->hdice, r_ptr->hside);
7327
7328 /* And start out fully healthy */
7329 m_ptr->hp = m_ptr->maxhp;
7330
7331 /* Extract the monster base speed */
7332 m_ptr->speed = r_ptr->speed;
7333 /* set cur speed to base speed */
7334 m_ptr->mspeed = m_ptr->speed;
7335
7336 /* Extract base ac and other things */
7337 m_ptr->ac = r_ptr->ac;
7338
7339 for (j = 0; j < 4; j++) {
7340 m_ptr->blow[j].effect = r_ptr->blow[j].effect;
7341 m_ptr->blow[j].method = r_ptr->blow[j].method;
7342 m_ptr->blow[j].d_dice = r_ptr->blow[j].d_dice;
7343 m_ptr->blow[j].d_side = r_ptr->blow[j].d_side;
7344 }
7345 m_ptr->level = r_ptr->level;
7346 m_ptr->exp = MONSTER_EXP(m_ptr->level);
7347 m_ptr->owner = 0;
7348
7349 /* Give a random starting energy */
7350 m_ptr->energy = rand_int(100);
7351
7352 /* No "damage" yet */
7353 m_ptr->stunned = 0;
7354 m_ptr->confused = 0;
7355 m_ptr->monfear = 0;
7356
7357 /* No knowledge */
7358 m_ptr->cdis = 0;
7359
7360 /* special pet value */
7361 m_ptr->owner = Players[owner_id]->id;
7362 m_ptr->pet = 1;
7363
7364 for (Ind = 1; Ind < NumPlayers + 1; Ind++) {
7365 if (Players[Ind]->conn == NOT_CONNECTED)
7366 continue;
7367
7368 Players[Ind]->mon_los[c_ptr->m_idx] = 0;
7369 Players[Ind]->mon_vis[c_ptr->m_idx] = 0;
7370 }
7371
7372 if (getlevel(wpos) >= (m_ptr->level + 8)) {
7373 m_ptr->exp = MONSTER_EXP(m_ptr->level + ((getlevel(wpos) - m_ptr->level - 5) / 3));
7374 monster_check_experience(c_ptr->m_idx, TRUE);
7375 }
7376
7377 strcpy(buf, (r_name + r_ptr->name));
7378
7379 /* Update the monster */
7380 update_mon(c_ptr->m_idx, TRUE);
7381
7382 /* Assume no sleeping */
7383 m_ptr->csleep = 0;
7384
7385 /* STR */
7386 for (j = 0; j < 4; j++) {
7387 m_ptr->blow[j].org_d_dice = r_ptr->blow[j].d_dice;
7388 m_ptr->blow[j].org_d_side = r_ptr->blow[j].d_side;
7389 }
7390 /* DEX */
7391 m_ptr->org_ac = m_ptr->ac;
7392 /* CON */
7393 m_ptr->org_maxhp = m_ptr->maxhp;
7394
7395 return (TRUE);
7396 }
7397
7398 /* Create a servant ! */
pet_creation(int Ind)7399 char pet_creation(int Ind)
7400 { //put the sanity tests here and call place_pet
7401 int id = 955; //green dr for now
7402 /* bleh, green dr is too powerful, lets do spiders. i'm fond of spiders. */
7403 int lev = Players[Ind]->lev;
7404 if (lev < 5) id = (randint(2)>1 ? 60 /*cave S*/ : 62 /*wild cat*/);
7405 else if (lev < 10) id = 127; //wood S
7406 else if (lev < 15) id = 277; //mirkwood S
7407 else if (lev < 20) id = 963; //aranea
7408 else id = 964; //elder aranea
7409
7410 if (!Players[Ind]->has_pet) {
7411 place_pet(Ind,
7412 &(Players[Ind]->wpos), Players[Ind]->py, Players[Ind]->px+1, /* E of player */
7413 id);
7414 Players[Ind]->has_pet = 1;
7415 return 1;
7416 }
7417 return 0;
7418 }
7419 #endif
7420
7421 /* Create a mindless servant ! */
golem_creation(int Ind,int max)7422 void golem_creation(int Ind, int max) {
7423 player_type *p_ptr = Players[Ind];
7424 monster_race *r_ptr;
7425 monster_type *m_ptr;
7426 int i;
7427 int golem_type = -1;
7428 int golem_arms[4], golem_m_arms = 0;
7429 int golem_legs[30], golem_m_legs = 0;
7430 s16b golem_flags = 0;
7431 cave_type *c_ptr;
7432 int x, y, k, g_cnt = 0;
7433 bool okay = FALSE;
7434 cave_type **zcave;
7435 if (!(zcave = getcave(&p_ptr->wpos))) return;
7436
7437 /* Process the monsters */
7438 for (k = m_top - 1; k >= 0; k--) {
7439 /* Access the index */
7440 i = m_fast[k];
7441
7442 /* Access the monster */
7443 m_ptr = &m_list[i];
7444
7445 /* Excise "dead" monsters */
7446 if (!m_ptr->r_idx) continue;
7447
7448 if (m_ptr->owner != p_ptr->id) continue;
7449
7450 if (!i) continue;
7451
7452 g_cnt++;
7453 }
7454
7455 if (g_cnt >= max) {
7456 msg_print(Ind, "You cannot create more golems.");
7457 return;
7458 }
7459
7460 for (x = p_ptr->px - 1; x <= p_ptr->px; x++)
7461 for (y = p_ptr->py - 1; y <= p_ptr->py; y++) {
7462 /* Verify location */
7463 if (!in_bounds(y, x)) continue;
7464 /* Require empty space */
7465 if (!cave_empty_bold(zcave, y, x)) continue;
7466
7467 /* Hack -- no creation on glyph of warding */
7468 if (zcave[y][x].feat == FEAT_GLYPH) continue;
7469 if (zcave[y][x].feat == FEAT_RUNE) continue;
7470
7471 if ((p_ptr->px == x) && (p_ptr->py == y)) continue;
7472
7473 okay = TRUE;
7474 break;
7475 }
7476
7477 if (!okay) {
7478 msg_print(Ind, "You don't have sufficient space to create a golem.");
7479 return;
7480 }
7481
7482
7483 /* Access the location */
7484 c_ptr = &zcave[y][x];
7485
7486 /* Make a new monster */
7487 c_ptr->m_idx = m_pop();
7488
7489 /* Mega-Hack -- catch "failure" */
7490 if (!c_ptr->m_idx) return;
7491
7492 /* Grab and allocate */
7493 m_ptr = &m_list[c_ptr->m_idx];
7494 MAKE(m_ptr->r_ptr, monster_race);
7495 m_ptr->special = TRUE;
7496 m_ptr->questor = FALSE;
7497 m_ptr->fx = x;
7498 m_ptr->fy = y;
7499
7500 r_ptr = m_ptr->r_ptr;
7501
7502 r_ptr->flags1 = 0;
7503 r_ptr->flags2 = 0;
7504 r_ptr->flags3 = 0;
7505 r_ptr->flags4 = 0;
7506 r_ptr->flags5 = 0;
7507 r_ptr->flags6 = 0;
7508 r_ptr->flags7 = 0;
7509 r_ptr->flags8 = 0;
7510 r_ptr->flags9 = 0;
7511 r_ptr->flags0 = 0;
7512
7513 msg_print(Ind, "Some of your items begins to consume in roaring flames.");
7514
7515 /* Find items used for "golemification" */
7516 for (i = 0; i < INVEN_WIELD; i++) {
7517 object_type *o_ptr = &p_ptr->inventory[i];
7518
7519 if (o_ptr->tval == TV_GOLEM) {
7520 if (o_ptr->sval <= SV_GOLEM_ADAM) {
7521 golem_type = o_ptr->sval;
7522 inven_item_increase(Ind, i, -1);
7523 inven_item_optimize(Ind, i);
7524 i--;
7525 continue;
7526 }
7527 if (o_ptr->sval == SV_GOLEM_ARM) {
7528 while (o_ptr->number) {
7529 if (golem_m_arms == 4) break;
7530 golem_arms[golem_m_arms++] = o_ptr->pval;
7531 inven_item_increase(Ind, i, -1);
7532 }
7533 inven_item_optimize(Ind, i);
7534 i--;
7535 continue;
7536 }
7537 if (o_ptr->sval == SV_GOLEM_LEG) {
7538 while (o_ptr->number) {
7539 if (golem_m_legs == 30) break;
7540 golem_legs[golem_m_legs++] = o_ptr->pval;
7541 inven_item_increase(Ind, i, -1);
7542 }
7543 inven_item_optimize(Ind, i);
7544 i--;
7545 continue;
7546 }
7547 else golem_flags |= 1 << (o_ptr->sval - 200);
7548 }
7549 /* Combine / Reorder the pack (later) */
7550 p_ptr->notice |= (PN_COMBINE | PN_REORDER);
7551
7552 /* Window stuff */
7553 p_ptr->window |= (PW_INVEN | PW_EQUIP);
7554 }
7555
7556 /* Ahah FAIL !!! */
7557 if ((golem_type == -1) || (golem_m_legs < 2)) {
7558 msg_print(Ind, "The spell fails! You lose all your material.");
7559 delete_monster_idx(c_ptr->m_idx, TRUE);
7560 return;
7561 }
7562
7563 r_ptr->text = 0;
7564 r_ptr->name = 0;
7565 r_ptr->sleep = 0;
7566 r_ptr->aaf = 20;
7567 r_ptr->speed = 110;
7568 for (i = 0; i < golem_m_legs; i++)
7569 r_ptr->speed += golem_legs[i];
7570 r_ptr->mexp = 1;
7571
7572 r_ptr->d_attr = TERM_YELLOW;
7573 r_ptr->d_char = 'g';
7574 r_ptr->x_attr = TERM_YELLOW;
7575 r_ptr->x_char = 'g';
7576
7577 r_ptr->freq_innate = 0;
7578 r_ptr->freq_spell = 0;
7579 r_ptr->flags1 |= RF1_FORCE_MAXHP;
7580 r_ptr->flags2 |= RF2_STUPID | RF2_EMPTY_MIND | RF2_REGENERATE | RF2_POWERFUL | RF2_BASH_DOOR | RF2_MOVE_BODY;
7581 r_ptr->flags3 |= RF3_HURT_ROCK | RF3_IM_COLD | RF3_IM_ELEC | RF3_IM_POIS | RF3_NO_FEAR | RF3_NO_CONF | RF3_NO_SLEEP;
7582 r_ptr->flags9 |= RF9_IM_TELE;
7583
7584 switch (golem_type) {
7585 case SV_GOLEM_WOOD:
7586 r_ptr->hdice = 10;
7587 r_ptr->hside = 10;
7588 r_ptr->ac = 20;
7589 break;
7590 case SV_GOLEM_COPPER:
7591 r_ptr->hdice = 10;
7592 r_ptr->hside = 20;
7593 r_ptr->ac = 40;
7594 break;
7595 case SV_GOLEM_IRON:
7596 r_ptr->hdice = 10;
7597 r_ptr->hside = 40;
7598 r_ptr->ac = 70;
7599 break;
7600 case SV_GOLEM_ALUM:
7601 r_ptr->hdice = 10;
7602 r_ptr->hside = 60;
7603 r_ptr->ac = 90;
7604 break;
7605 case SV_GOLEM_SILVER:
7606 r_ptr->hdice = 10;
7607 r_ptr->hside = 70;
7608 r_ptr->ac = 100;
7609 break;
7610 case SV_GOLEM_GOLD:
7611 r_ptr->hdice = 10;
7612 r_ptr->hside = 80;
7613 r_ptr->ac = 130;
7614 break;
7615 case SV_GOLEM_MITHRIL:
7616 r_ptr->hdice = 10;
7617 r_ptr->hside = 100;
7618 r_ptr->ac = 160;
7619 break;
7620 case SV_GOLEM_ADAM:
7621 r_ptr->hdice = 10;
7622 r_ptr->hside = 150;
7623 r_ptr->ac = 210;
7624 break;
7625 // default:
7626 }
7627 r_ptr->extra = golem_flags;
7628 //#if 0
7629 /* Find items used for "golemification" */
7630 for (i = 0; i < INVEN_WIELD; i++) {
7631 object_type *o_ptr = &p_ptr->inventory[i];
7632 unsigned char *inscription = (unsigned char *) quark_str(o_ptr->note);
7633
7634 /* Additionnal items ? */
7635 if (inscription != NULL) {
7636 /* scan the inscription for @G */
7637 while ((*inscription != '\0')) {
7638 if (*inscription == '@') {
7639 inscription++;
7640
7641 /* a valid @G has been located */
7642 if (*inscription == 'G') {
7643 inscription++;
7644
7645 scan_golem_flags(o_ptr, r_ptr);
7646 /* scan_golem_flags uses only one item */
7647 inven_item_increase(Ind,i,-1);
7648 inven_item_optimize(Ind,i);
7649 i--;
7650 continue;
7651 }
7652 }
7653 inscription++;
7654 }
7655 }
7656 }
7657 //#endif
7658 /* extract base speed */
7659 m_ptr->speed = r_ptr->speed;
7660 /* set cur speed to base speed */
7661 m_ptr->mspeed = m_ptr->speed;
7662 m_ptr->ac = r_ptr->ac;
7663 m_ptr->maxhp = maxroll(r_ptr->hdice, r_ptr->hside);
7664 m_ptr->hp = maxroll(r_ptr->hdice, r_ptr->hside);
7665 m_ptr->clone = 100;
7666
7667 for (i = 0; i < golem_m_arms; i++) {
7668 m_ptr->blow[i].method = r_ptr->blow[i].method = RBM_HIT;
7669 m_ptr->blow[i].effect = r_ptr->blow[i].effect = RBE_HURT;
7670 m_ptr->blow[i].d_dice = r_ptr->blow[i].d_dice = (golem_type + 1) * 3;
7671 m_ptr->blow[i].d_side = r_ptr->blow[i].d_side = 3 + golem_arms[i];
7672 }
7673
7674 m_ptr->owner = p_ptr->id;
7675 m_ptr->r_idx = 1 + golem_type;
7676
7677 m_ptr->level = p_ptr->lev;
7678 m_ptr->exp = MONSTER_EXP(m_ptr->level);
7679
7680 /* Assume no sleeping */
7681 m_ptr->csleep = 0;
7682 wpcopy(&m_ptr->wpos, &p_ptr->wpos);
7683
7684 /* No "damage" yet */
7685 m_ptr->stunned = 0;
7686 m_ptr->confused = 0;
7687 m_ptr->monfear = 0;
7688
7689 /* No knowledge */
7690 m_ptr->cdis = 0;
7691 m_ptr->mind = GOLEM_NONE;
7692
7693 /* prevent other players from killing it on accident */
7694 r_ptr->flags8 |= RF8_NO_AUTORET | RF8_GENO_PERSIST | RF8_GENO_NO_THIN;
7695 r_ptr->flags7 |= RF7_NO_TARGET;
7696
7697 /* Update the monster */
7698 update_mon(c_ptr->m_idx, TRUE);
7699 }
7700
7701 /* pernAngband Additions - Jir - */
call_chaos(int Ind,int dir,int extra_damage)7702 void call_chaos(int Ind, int dir, int extra_damage) {
7703 player_type *p_ptr = Players[Ind];
7704 int Chaos_type, dummy;
7705 int plev = p_ptr->lev;
7706 bool line_chaos = FALSE;
7707
7708 /* determine damage type */
7709 #if 0 /* traditional */
7710 int hurt_types[29] = { // 30
7711 GF_ELEC, GF_POIS, GF_ACID, GF_COLD,
7712 GF_FIRE, GF_MISSILE, GF_ARROW, GF_PLASMA,
7713 // GF_HOLY_FIRE,
7714 GF_WATER, GF_LITE, GF_DARK,
7715 GF_FORCE, GF_INERTIA, GF_MANA, GF_METEOR,
7716 GF_ICE, GF_CHAOS, GF_NETHER, GF_DISENCHANT,
7717 GF_SHARDS, GF_SOUND, GF_NEXUS, GF_CONFUSION,
7718 GF_TIME, GF_GRAVITY, GF_ROCKET, GF_NUKE,
7719 GF_DISINTEGRATE,
7720 GF_HELL_FIRE,
7721 };
7722 Chaos_type = hurt_types[rand_int(29)];
7723 #endif
7724 #if 0 /* redux (blend out 'weaker' types that monsters may be immune to etc) */
7725 int hurt_types[17] = {
7726 /* not that much of chaos */
7727 GF_MISSILE, GF_SHARDS, GF_INERTIA, GF_SOUND, GF_GRAVITY,
7728 /* pretty chaossy */
7729 GF_NEXUS, GF_TIME, GF_FORCE, GF_MANA,
7730 /* truly chaos */
7731 GF_CHAOS, GF_NUKE, GF_METEOR, GF_ROCKET,
7732 GF_INFERNO, GF_PLASMA, GF_HELL_FIRE, GF_DISINTEGRATE,
7733 };
7734 Chaos_type = hurt_types[rand_int(17)];
7735 #endif
7736 #if 1 /* redux^2 (only use damage types that deserve to be called chaos (hah)) */
7737 int hurt_types[12] = {
7738 /* pretty chaossy */
7739 GF_NEXUS, GF_TIME, GF_FORCE, GF_MANA,
7740 /* truly chaos */
7741 GF_CHAOS, GF_NUKE, GF_METEOR, GF_ROCKET,
7742 GF_INFERNO, GF_PLASMA, GF_HELL_FIRE, GF_DISINTEGRATE,
7743 };
7744 Chaos_type = hurt_types[rand_int(12)];
7745 #endif
7746
7747 /* determine shape */
7748 if (randint(4) == 1) line_chaos = TRUE;
7749
7750 #if 0
7751 /* Probably a meaningless line, a remnant from earlier code */
7752 while (Chaos_type > GF_GRAVITY && Chaos_type < GF_ROCKET);
7753 #endif
7754
7755 if (randint(6) == 1) {
7756 for (dummy = 1; dummy < 10; dummy++) {
7757 if (dummy - 5) {
7758 if (line_chaos) {
7759 // fire_beam(Ind, Chaos_type, dummy, 1500 + extra_damage, p_ptr->attacker);
7760 fire_beam(Ind, Chaos_type, dummy, 675 + extra_damage, p_ptr->attacker);
7761 } else {
7762 // fire_ball(Ind, Chaos_type, dummy, 1500 + extra_damage, 2, p_ptr->attacker);
7763 fire_ball(Ind, Chaos_type, dummy, 675 + extra_damage, 2, p_ptr->attacker);
7764 }
7765 }
7766 }
7767 }
7768 else if (randint(3) == 1) {
7769 // fire_ball(Ind, Chaos_type, 0, 1500 + extra_damage, 8, p_ptr->attacker);
7770 fire_ball(Ind, Chaos_type, 0, 675 + extra_damage, 8, p_ptr->attacker);
7771 } else {
7772 // if (!get_aim_dir(Ind) return;
7773 if (line_chaos) {
7774 // fire_beam(Ind, Chaos_type, dir, 1500 + extra_damage, p_ptr->attacker);
7775 fire_beam(Ind, Chaos_type, dir, 675 + extra_damage, p_ptr->attacker);
7776 } else {
7777 // fire_ball(Ind, Chaos_type, dir, 1500 + extra_damage, 3 + (plev/35), p_ptr->attacker);
7778 fire_ball(Ind, Chaos_type, dir, 675 + extra_damage, 3 + (plev/35), p_ptr->attacker);
7779 }
7780 }
7781 }
7782
summon_cyber(int Ind,int s_clone,int clone_summoning)7783 bool summon_cyber(int Ind, int s_clone, int clone_summoning) {
7784 player_type *p_ptr = Players[Ind];
7785 int i;
7786 int max_cyber = (getlevel(&p_ptr->wpos)/ 50) + randint(6);
7787 bool ok = FALSE;
7788
7789 for (i = 0; i < max_cyber; i++)
7790 ok = ok || summon_specific(&p_ptr->wpos, p_ptr->py, p_ptr->px, 100, s_clone, SUMMON_HI_DEMON, 1, clone_summoning);
7791 return ok;
7792 }
7793
7794 /* Heal insanity. */
heal_insanity(int Ind,int val)7795 bool heal_insanity(int Ind, int val)
7796 {
7797 player_type *p_ptr = Players[Ind];
7798
7799 if (p_ptr->csane < p_ptr->msane) {
7800 p_ptr->csane += val;
7801
7802 if (p_ptr->csane >= p_ptr->msane) {
7803 p_ptr->csane = p_ptr->msane;
7804 p_ptr->csane_frac = 0;
7805 }
7806
7807 p_ptr->update |= PU_SANITY;
7808 p_ptr->redraw |= PR_SANITY;
7809 p_ptr->window |= (PW_PLAYER);
7810
7811 if (val < (p_ptr->msane/8)) {
7812 msg_print(Ind, "You feel a little saner.");
7813 } else if (val < (p_ptr->msane/4)) {
7814 msg_print(Ind, "You feel saner.");
7815 } else if (val < (p_ptr->msane/2)) {
7816 msg_print(Ind, "You feel much saner.");
7817 } else {
7818 msg_print(Ind, "You feel very sane.");
7819 }
7820
7821 return TRUE;
7822 }
7823
7824 return FALSE;
7825 }
7826
do_vermin_control(int Ind)7827 bool do_vermin_control(int Ind) {
7828 dun_level *l_ptr = getfloor(&Players[Ind]->wpos);
7829 if (l_ptr && !(l_ptr->flags1 & LF1_NO_MULTIPLY)) {
7830 l_ptr->flags1 |= LF1_NO_MULTIPLY;
7831 msg_print(Ind, "You feel less itchy.");
7832 return TRUE;
7833 }
7834 return FALSE;
7835 }
7836
rune_combine(int Ind)7837 void rune_combine(int Ind) {
7838 player_type *p_ptr = Players[Ind];
7839
7840 clear_current(Ind);
7841
7842 p_ptr->current_rune = TRUE;
7843 get_item(Ind, ITH_RUNE);
7844
7845 return;
7846 }
7847
rune_combine_aux(int Ind,int item)7848 void rune_combine_aux(int Ind, int item) {
7849 player_type *p_ptr = Players[Ind];
7850
7851 if (item == p_ptr->current_activation) return; //don't combine the same rune
7852
7853 /* Recall the first rune */
7854 object_type *o_ptr = &p_ptr->inventory[p_ptr->current_activation];
7855
7856 /* Store the combining flag */
7857 s16b e_flags = r_elements[o_ptr->sval].flag;
7858
7859 /* Remember the original info */
7860 byte sval = o_ptr->sval;
7861 s32b owner = o_ptr->owner;
7862 byte mode = o_ptr->mode;
7863 s16b level = o_ptr->level;
7864 byte discount = o_ptr->discount;
7865 byte number = o_ptr->number;
7866 s16b note = o_ptr->note; //keep the incription of the initial rune
7867
7868 /* Recall the second rune */
7869 o_ptr = &p_ptr->inventory[item];
7870
7871 /* Sanity */
7872 if ((o_ptr->sval == sval) //same rune type
7873 || (o_ptr->tval != TV_RUNE) //not a rune (obselete)
7874 || (o_ptr->sval >= RCRAFT_MAX_ELEMENTS) //not a basic rune (obselete)
7875 || (!(o_ptr->level) && !(o_ptr->owner == p_ptr->id))) { //not owned
7876 msg_format(Ind, "You cannot combine these runes!");
7877 return;
7878 }
7879
7880 /* Store the combining flag */
7881 e_flags |= r_elements[o_ptr->sval].flag;
7882
7883 /* Lookup resulting rune -- (flags_to_projection) */
7884 byte i;
7885 for (i = 0; i < RCRAFT_MAX_PROJECTIONS; i++) {
7886 if (e_flags == r_projections[i].flags)
7887 break;
7888 }
7889
7890 /* Store combined item values -- use worst case! */
7891 level = (o_ptr->level > level) ? o_ptr->level : level;
7892 discount = (o_ptr->discount > discount) ? o_ptr->discount : discount;
7893 number = (o_ptr->number < number) ? o_ptr->number : number;
7894
7895 /* Destroy the rune stacks in the pack */
7896 msg_format(Ind, "There is a coupling of magic.");
7897 inven_item_increase(Ind, p_ptr->current_activation, -number);
7898 inven_item_increase(Ind, item, -number);
7899 if (p_ptr->current_activation > item) { //higher value (lower in inventory) first; to preserve indexes
7900 inven_item_optimize(Ind, p_ptr->current_activation);
7901 inven_item_optimize(Ind, item);
7902 } else {
7903 inven_item_optimize(Ind, item);
7904 inven_item_optimize(Ind, p_ptr->current_activation);
7905 }
7906
7907 /* Make new stack */
7908 object_type *q_ptr, forge;
7909
7910 /* Default rune template */
7911 q_ptr = &forge;
7912 object_wipe(q_ptr);
7913 invcopy(q_ptr, lookup_kind(TV_RUNE, i));
7914
7915 /* Recall original parameters */
7916 q_ptr->owner = owner;
7917 q_ptr->mode = mode;
7918 q_ptr->level = level;
7919 q_ptr->discount = discount;
7920 q_ptr->number = number;
7921 q_ptr->note = note;
7922
7923 /* Create the rune stack */
7924 inven_carry(Ind, q_ptr);
7925
7926 }
7927
7928 /* see create_custom_tome_aux() below */
tome_creation(int Ind)7929 void tome_creation(int Ind) {
7930 player_type *p_ptr = Players[Ind];
7931
7932 clear_current(Ind);
7933
7934 p_ptr->current_tome_creation = TRUE;
7935 get_item(Ind, ITH_CUSTOM_TOME);
7936
7937 return;
7938 }
7939
7940 /* add a spell scroll to the player's custom-made tome - C. Blue
7941 Note: pval must be incremented by 1, because first spell
7942 (MANATHRUST) starts at 0, but we use 0 for <not used>
7943 because xtra1..9 are of type 'byte' so we can't use -1. */
tome_creation_aux(int Ind,int item)7944 void tome_creation_aux(int Ind, int item) {
7945 player_type *p_ptr = Players[Ind];
7946 bool okay = TRUE;
7947 object_type *o_ptr, *o2_ptr;
7948 char o_name[ONAME_LEN];
7949 byte *xtra;
7950
7951 /* Get the item (in the pack) */
7952 if (item >= 0) o_ptr = &p_ptr->inventory[item];
7953 /* Get the item (on the floor) */
7954 else o_ptr = &o_list[0 - item];
7955 /* Get the item (in the pack) */
7956 if (p_ptr->using_up_item >= 0) o2_ptr = &p_ptr->inventory[p_ptr->using_up_item];
7957 /* Get the item (on the floor) */
7958 else o2_ptr = &o_list[0 - p_ptr->using_up_item];
7959
7960 /* severe error: custom book no longer there */
7961 if (o_ptr->tval != TV_BOOK || !is_custom_tome(o_ptr->sval)) {
7962 /* completely start from scratch (have to re-'activate') */
7963 msg_print(Ind, "A book's inventory location was changed, please retry!");
7964 clear_current(Ind); /* <- not required actually */
7965 return;
7966 }
7967
7968 #if 1 /* done in do_cmd_activate already. double-check */
7969 /* free space left? */
7970 /* k_info-pval dependant */
7971 switch (o_ptr->bpval) {
7972 case 0: okay = FALSE; break;
7973 case 1: if (o_ptr->xtra1) okay = FALSE; break;
7974 case 2: if (o_ptr->xtra2) okay = FALSE; break;
7975 case 3: if (o_ptr->xtra3) okay = FALSE; break;
7976 case 4: if (o_ptr->xtra4) okay = FALSE; break;
7977 case 5: if (o_ptr->xtra5) okay = FALSE; break;
7978 case 6: if (o_ptr->xtra6) okay = FALSE; break;
7979 case 7: if (o_ptr->xtra7) okay = FALSE; break;
7980 case 8: if (o_ptr->xtra8) okay = FALSE; break;
7981 default: if (o_ptr->xtra9) okay = FALSE; break;
7982 }
7983 if (!okay) {
7984 /* completely start from scratch (have to re-'activate') */
7985 msg_print(Ind, "That book has no blank pages left!");
7986 clear_current(Ind); /* <- not required actually */
7987 return;
7988 }
7989 #endif
7990
7991 if (o2_ptr->tval != TV_BOOK || o2_ptr->sval != SV_SPELLBOOK)
7992 {
7993 msg_print(Ind, "You can only transcribe a spell scroll!");
7994 /* restore silyl hack.. */
7995 p_ptr->using_up_item = item;
7996 /* try again */
7997 get_item(Ind, ITH_CUSTOM_TOME);
7998 return;
7999 }
8000
8001 /* for DISCRETE_SPELL_SYSTEM: DSS_EXPANDED_SCROLLS */
8002 //TODO: call Send_spell_request(Ind, item); here if client is not outdated (DSS_EXPANDED_SCROLLS)
8003
8004 /* need to actually be able to cast the spell in order to transcribe it! */
8005 if (exec_lua(Ind, format("return get_level(%d, %d, 50, -50)", Ind, o2_ptr->pval)) < 1) {
8006 msg_print(Ind, "Your knowledge of that spell is insufficient!");
8007 /* restore silyl hack.. */
8008 p_ptr->using_up_item = item;
8009 /* try again */
8010 get_item(Ind, ITH_CUSTOM_TOME);
8011 return;
8012 }
8013
8014 /* check for duplicate entry -> prevent it */
8015 if (o_ptr->xtra1 == o2_ptr->pval + 1 ||
8016 o_ptr->xtra2 == o2_ptr->pval + 1 ||
8017 o_ptr->xtra3 == o2_ptr->pval + 1 ||
8018 o_ptr->xtra4 == o2_ptr->pval + 1 ||
8019 o_ptr->xtra5 == o2_ptr->pval + 1 ||
8020 o_ptr->xtra6 == o2_ptr->pval + 1 ||
8021 o_ptr->xtra7 == o2_ptr->pval + 1 ||
8022 o_ptr->xtra8 == o2_ptr->pval + 1 ||
8023 o_ptr->xtra9 == o2_ptr->pval + 1) {
8024 msg_print(Ind, "The book already contains that spell!");
8025 /* restore silyl hack.. */
8026 p_ptr->using_up_item = item;
8027 /* try again */
8028 get_item(Ind, ITH_CUSTOM_TOME);
8029 return;
8030 }
8031
8032 /* - Success finally - */
8033
8034 /* Find the next free slot */
8035 if (!o_ptr->xtra1) xtra = &o_ptr->xtra1;
8036 else if (!o_ptr->xtra2) xtra = &o_ptr->xtra2;
8037 else if (!o_ptr->xtra3) xtra = &o_ptr->xtra3;
8038 else if (!o_ptr->xtra4) xtra = &o_ptr->xtra4;
8039 else if (!o_ptr->xtra5) xtra = &o_ptr->xtra5;
8040 else if (!o_ptr->xtra6) xtra = &o_ptr->xtra6;
8041 else if (!o_ptr->xtra7) xtra = &o_ptr->xtra7;
8042 else if (!o_ptr->xtra8) xtra = &o_ptr->xtra8;
8043 else xtra = &o_ptr->xtra9;
8044
8045 /* transcribe (add it)! */
8046 *xtra = o2_ptr->pval + 1;
8047
8048 /* Description */
8049 object_desc(Ind, o_name, o_ptr, FALSE, 0);
8050 /* Describe */
8051 msg_format(Ind, "%s %s glow%s brightly!",
8052 ((item >= 0) ? "Your" : "The"), o_name,
8053 ((o_ptr->number > 1) ? "" : "s"));
8054
8055 /* Did we use up an item? */
8056 if (p_ptr->using_up_item >= 0)
8057 {
8058 inven_item_increase(Ind, p_ptr->using_up_item, -1);
8059 inven_item_describe(Ind, p_ptr->using_up_item);
8060 inven_item_optimize(Ind, p_ptr->using_up_item);
8061 p_ptr->using_up_item = -1;
8062 }
8063
8064 /* unstack if our custom book was originally in a pile */
8065 if ((item >= 0) && (o_ptr->number > 1))
8066 {
8067 /* Make a fake item */
8068 object_type tmp_obj;
8069 tmp_obj = *o_ptr;
8070 tmp_obj.number = 1;
8071
8072 /* Restore remaining 'untouched' stack of books */
8073 *xtra = 0;
8074
8075 /* Message */
8076 msg_print(Ind, "You unstack your book.");
8077
8078 /* Unstack the used item */
8079 o_ptr->number--;
8080 p_ptr->total_weight -= tmp_obj.weight;
8081 item = inven_carry(Ind, &tmp_obj);
8082 }
8083
8084 /* Window stuff */
8085 p_ptr->window |= (PW_INVEN);
8086 p_ptr->notice |= (PN_REORDER);
8087
8088 /* Something happened */
8089 return;
8090 }
8091
do_mstopcharm(int Ind)8092 void do_mstopcharm(int Ind) {
8093 player_type *p_ptr = Players[Ind];
8094 monster_type *m_ptr;
8095 int m;
8096
8097 if (p_ptr->mcharming == 0) return; /* optimization */
8098
8099 p_ptr->mcharming = 0;
8100
8101 for (m = m_top - 1; m >= 0; m--) {
8102 m_ptr = &m_list[m_fast[m]];
8103 // r_ptr = race_inf(m_ptr);
8104 if (m_ptr->charmedignore && m_ptr->charmedignore == Ind)
8105 m_ptr->charmedignore = 0;
8106 }
8107 }
8108
test_charmedignore(int Ind,int Ind_charmer,monster_race * r_ptr)8109 bool test_charmedignore(int Ind, int Ind_charmer, monster_race *r_ptr) {
8110 player_type *q_ptr = Players[Ind_charmer];
8111 int chance = 1, cost = 1;
8112
8113 /* non team-mates are not affected (and would cost extra mana) */
8114 if (Ind != Ind_charmer &&
8115 (!player_in_party(q_ptr->party, Ind)))
8116 return FALSE;
8117
8118 /* some monsters show resistance spikes */
8119 if ((r_ptr->flags2 & RF2_SMART) ||
8120 (r_ptr->flags3 & RF3_NO_CONF) ||
8121 (r_ptr->flags1 & RF1_UNIQUE) ||
8122 (r_ptr->flags2 & RF2_POWERFUL)) {
8123 chance++;
8124 cost++;
8125 }
8126
8127 /* especially costly? */
8128 if (r_ptr->level > (q_ptr->lev * 7) / 5)
8129 cost++;
8130
8131 /* spell continuously burns mana! */
8132 if (turn % (cfg.fps / 10) == 0) {
8133 if (q_ptr->csp < 1) {
8134 do_mstopcharm(Ind_charmer);
8135 return FALSE;
8136 }
8137 q_ptr->csp -= 1;
8138 q_ptr->redraw |= PR_MANA;
8139 }
8140
8141 /* the charm-caster himself is pretty safe */
8142 if (Ind == Ind_charmer && magik(100 - chance))
8143 return TRUE;
8144 /* in same party?= slightly reduced effect >:) */
8145 if (magik(99 - 2 * chance))
8146 return TRUE;
8147
8148 return FALSE;
8149 }
8150
8151 /* Add certain flags to a ball/breath/cloud projection depending on the damage type. */
mod_ball_spell_flags(int typ,u32b flags)8152 u32b mod_ball_spell_flags(int typ, u32b flags) {
8153 switch (typ) {
8154 /* stuff that also acts on the casting player himself */
8155 case GF_HEAL_PLAYER:
8156 case GF_HEALINGCLOUD:
8157 return (flags | PROJECT_PLAY);
8158 /* 'environmentally instant' stuff */
8159 case GF_SOUND:
8160 case GF_CONFUSION:
8161 case GF_INERTIA:
8162 case GF_TIME:
8163 case GF_GRAVITY:
8164 case GF_STUN:
8165 case GF_PSI:
8166 case GF_UNBREATH:
8167 case GF_THUNDER:
8168 case GF_ANNIHILATION:
8169 return (flags | PROJECT_LODF);
8170 /* very powerful 'force' stuff */
8171 case GF_FORCE:
8172 case GF_METEOR:
8173 case GF_INFERNO:
8174 case GF_DETONATION:
8175 case GF_ROCKET:
8176 case GF_WAVE:
8177 return (flags | PROJECT_LODF);
8178 }
8179 return flags;
8180 }
8181